feat/sec-base
blocked2ad7120 · incrementalPR #267reviewed 2026-07-08 17:33 UTC7H · 14M · 11L · 1I- Purpose
- Land the ISO 27001 + SOC 2 compliance baseline: CI dependency/code scanning, CDK CloudTrail/GuardDuty stacks reconciled to live reality, GitHub org security settings enabled, and a comprehensive compliance knowledge base (SSOT rule, 18+ policy skeletons, auditor documents, evidence machinery).
- Goal
- Pass ISO 27001 Stage 1 (target M7) + SOC 2 Type I (target M6) with a 'pass-with-findings' trajectory; complete the observation window for Type II (~M11) and ISO Stage 2 (~M9).
- Sub-goals
- SG-1: Dependency & code scanning — dependabot.yml + codeql.yml + advisory audit job (done)
- SG-2: CDK security baseline reconcile — AuditTrailStack + GuardDutyBaseline match live reality (done)
- SG-3: GitHub org security settings enabled (done)
- SG-4: Compliance knowledge base — 48 docs/policies under docs/compliance/ (done)
- SG-mock-audit: Independent mock Stage 1 audit run (48/100 initial), full remediation pass (72/100 re-grade), residuals RG-1/RG-2 closed
- What
- Mock Stage 1 audit remediation: 4 new ISMS documents (audit-remediation-tracker, competence-and-communication, context-and-interested-parties, document-control-procedure), 10 updated policies/SoA/objectives/system-description to remove false-present-tense claims, add 5.2c/5.2d commitments, [operating]/[designed] tags on SOC 2 controls, CSOCs/CUECs/incident-disclosure sections, and SoA tally/exclusion corrections (7.13 reclassified, 5.15/5.23/8.25 downgraded to ◐). Score improved 48→72/100.
- Why
- The initial mock audit returned NOT READY (48/100) with 7 majors and 8 minors. All doc-fixable findings were closed in one pass; remaining 4 open items are founder actions (risk workshop, sign-off session, management review, vendor attestation collection) and one code fix (BAT-256).
- Areas
- docs/compliance/ (root docs)+1298−0docs/compliance/policies/+357−0.claude/rules/+70−0.github/+122−0infra/cdk/src/stacks/+41−6.branch/+61−164
- Blast
- 48 files changed, +1909/−170. Pure documentation + CI config — no runtime code, no database migrations, no API surface changes. CDK stacks authored but not deployed. Risk is compliance program correctness, not operational stability.
Findings · 35
correctness6
SOC 2 description implies subprocessor list is already published
docs/compliance/soc2-system-description.md:27
Confidentiality commitment at line 27 states 'subprocessor list published' in present tense. vendor-register.md action ③ marks publication as outstanding. Same false-present-tense class as MAJ-7/RG-2 — not caught in the remediation pass. Change to 'subprocessor list (to be published — vendor register action ③)'.
SoA physical-exclusion justification still says provider reports 'on file'
docs/compliance/statement-of-applicability.md:73
7.1 justification and its 'Same' siblings for all 9 N-A controls read 'reports on file'. Provider attestations are not yet collected (MIN-8 open, vendor register action ① outstanding). RG-2 was fixed in scope-statement.md but this SoA instance was missed.
Certification timeline in O-9 contradicts compliance.md SSOT
docs/compliance/security-objectives.md:23
O-9 says 'SOC 2 Type II ~M12 · ISO 27001 certificate ~M10'. compliance.md says 'Type II ~M11; ISO Stage 2 M9'. Both dates differ; auditors will flag the inconsistency. Align security-objectives.md to compliance.md.
Policies lack version/date required by the newly-adopted document-control procedure
docs/compliance/policies/information-security-policy.md:6
document-control-procedure.md defines 'v0.x = draft' with version date = commit date. All 18 policy skeletons use bare 'DRAFT — not approved' with no version number or date, immediately contradicting the procedure they are governed by. The new context-and-interested-parties.md and competence-and-communication.md were correctly versioned — the convention should be back-applied to policies.
MAJ-1 tracker note oversimplifies the two-tier approval model
docs/compliance/audit-remediation-tracker.md:13
Tracker says 'owner merge to main = approval' without noting the exception: the master Information Security Policy and risk acceptances require explicit Alvaro sign-off (per document-control-procedure.md, 'A merge SHA is insufficient'). A founder reading only the tracker may incorrectly believe their merge suffices for the master policy.
Tracker '5/7 majors closed' count is inconsistent with MAJ-7 being 'doc-closed' not 'closed'
docs/compliance/audit-remediation-tracker.md:42
Counting Closed rows: MAJ-2/3/4/5 = 4 fully closed; MAJ-7 = doc-closed; MAJ-1/6 = open. Summary should read '4/7 fully closed + 1 doc-closed (MAJ-7, code residual BAT-256), 2 founder-action open' rather than '5/7 fully closed, MAJ-7 doc-closed' which conflates the two categories.
security8
AUP FDE/MFA self-attestation has no defined artifact — will fail Type II sampling
docs/compliance/policies/acceptable-use-policy.md:15
The transition language converts hard controls to honor-system attestations. No artifact is defined: no form, no checklist row, no re-attestation trigger on device change, no retention location. A Type II sampler will ask for evidence the self-attestation happened per person; without an artifact, 'self-attestation' is indistinguishable from 'no control'. Specify: what the artifact is, who holds it, where retained.
CFE credential manual-deletion interim has no defined SLA or exercise record (RG-3 unexercised)
docs/compliance/policies/data-retention-disposal-policy.md:19
Manual deletion of CFE Secrets Manager secrets on offboarding: (1) not in the HR policy offboarding checklist (hr-security-policy.md lists Google/GitHub/AWS/Vercel/Supabase/Tinybird/Stripe/Notion/Linear — CFE secrets absent); (2) no interim deletion SLA defined (the 'days' SLA only applies post-BAT-256); (3) never been exercised (RG-3 open). Crown-jewel data class + LFPDPPP personal-data obligations make this a live privacy liability, not just a compliance gap.
Document-control allows policy self-approval without second reviewer
docs/compliance/document-control-procedure.md:33
Operational policies can be approved by 'merge to main by the approving owner'. If Alex is sole tech-lead in CODEOWNERS, he can author + merge his own access-control, IR, and data-retention policies. ISO 7.5 expects the producer not to be the sole approver. Recommend: require a named second reviewer (Diego or Alvaro) when author and approving owner are the same person.
IR plan SEV1 24h notification window may breach LFPDPPP 'without delay' obligation
docs/compliance/policies/incident-response-plan.md:13
SEV1 says 'customer/regulator notification decision ≤ 24h'. LFPDPPP Article 36 requires notification 'without delay' once a breach is confirmed — it does not offer a 24h safe harbor for the decision itself. CFE credentials may qualify as personal data under LFPDPPP. The ir-tabletop scenario confirms this gap is known. Add a specific LFPDPPP timing commitment alongside the 24h target.
SOC 2 system description embeds all four AWS account IDs in a customer-distributable document
docs/compliance/soc2-system-description.md:33
Prod (353625676934), staging (966363209222), dev (706877673155), management (397762539248) are in plain text. This file is designed for external distribution to customers and prospects. Account IDs enable targeted reconnaissance (confused-deputy attacks, S3 resource enumeration). Replace with environment labels and move the account→environment mapping to an internal-only doc not included in the customer PDF extract.
Access [operating] overstates OIDC posture: OIDC roles hold AdministratorAccess (BAT-259 open)
docs/compliance/soc2-system-description.md:85
The [operating] bucket claims 'OIDC (no static AWS keys)' as an operating control. compliance.md SSOT confirms GitHub OIDC deployer roles attach AdministratorAccess (open finding, BAT-259). An AdministratorAccess OIDC role is an operating security gap, not an operating control. Either note the residual inline or move OIDC least-privilege claim to [designed, implementing] until BAT-259 is closed.
CUECs missing customer obligation to report external CFE account compromise
docs/compliance/soc2-system-description.md:110
CUECs cover Batu API key rotation but not the customer's duty to notify Batu if their CFE portal account is externally compromised or if CFE credentials change outside of Batu. The F-4 auth-cache issue (25-min stale session) makes this a real attack vector. Add: 'Notifying Batu promptly if their CFE Mi Espacio account is compromised externally or if CFE portal credentials are changed outside of Batu, so cached sessions can be invalidated.'
Notion token incident disclosure lacks scope-analysis before claiming no customer-data impact
docs/compliance/soc2-system-description.md:119
Assessment rationale ('not affecting customer data') is not documented. Evidence needed: what databases/pages the token accessed, whether customer PII was in those pages, basis for 'no external access' claim (Notion audit log check). CA-001 records only revocation. If the token had access to customer-related Notion pages, the assessment may be incorrect. The SOC 2 description should cite the scope analysis, not just the remediation action.
conventions7
Version format inconsistency: 'DRAFT 0.1' vs canonical 'DRAFT v0.1' in SoA
docs/compliance/statement-of-applicability.md:6
document-control-procedure.md defines 'v0.x = draft'. The SoA uses 'DRAFT 0.1' (no 'v' prefix). soc2-system-description.md has the same deviation. context-and-interested-parties.md and competence-and-communication.md correctly use 'DRAFT v0.1'. The procedure controls itself — deviations in documents introduced this branch are immediate self-contradictions.
soc2-system-description.md uses 'DRAFT 0.1' and is missing Owner field
docs/compliance/soc2-system-description.md:7
Uses 'DRAFT 0.1' not 'DRAFT v0.1', and has no Owner header row. Every other ISMS document (audit-rfq.md, cfe-credential-data-flow.md, context-and-interested-parties.md, etc.) includes an Owner row. The SOC 2 system description is a managed document requiring an accountable owner.
scope-statement.md Status field missing the date component
docs/compliance/scope-statement.md:6
document-control-procedure.md requires 'version date = commit date'. scope-statement.md Status reads 'DRAFT v0.1 — for founder review' with no date, while all other new documents in this branch include the date (e.g. 'DRAFT v0.1 · 2026-07-08').
security-objectives.md uses separate Version row instead of inline Status pattern
docs/compliance/security-objectives.md:8
Uses a split '| Version | 0.1 · date |' row while canonical pattern (and document-control-procedure.md) puts version inline in Status: 'DRAFT v0.1 · 2026-07-08'. Also the version token is '0.1' not 'v0.1'.
SoA physical-exclusion justification retains 'reports on file' (same false-claim class as RG-2)
docs/compliance/statement-of-applicability.md:73
RG-2 was closed by rewording scope-statement.md. The SoA's N-A justification for 7.1 (and 'Same' siblings) still says 'inherited from cloud providers (reports on file)'. Provider reports are not yet collected (MIN-8 open). Parenthetical should read 'reports to be collected into the vendor register'.
audit-remediation-tracker.md missing Owner field
docs/compliance/audit-remediation-tracker.md
Every ISMS document includes an Owner row. The remediation tracker has Source/Purpose/Status but no Owner. Alex (ISMS owner) is the logical choice.
All 18 policy skeletons use bare 'DRAFT — not approved' without version/date
docs/compliance/policies/information-security-policy.md:6
Systemic across all policies (consistent pattern). The document-control-procedure.md now in place requires version+date stamps. No fix needed before merge; the next editorial pass on policies should add 'DRAFT v0.1 · <commit-date>' to each Status field for consistency.
tests7
SEV1 ≤1h acknowledge commitment is unverifiable — no on-call mechanism defined
docs/compliance/policies/incident-response-plan.md:13
No alerting channel is named, no PagerDuty/SNS/phone escalation path exists in any doc, no IC rotation or backup defined for when Alex is unreachable. logging-monitoring-policy.md only says GuardDuty findings route to 'an alerting channel' without specifying it. Auditors will ask 'how do you know within 60 minutes at 2am?' — current docs cannot answer.
O-2 interim measurement 'Vercel deployment/health metrics' has no operational definition
docs/compliance/security-objectives.md:16
No dashboard URL, no query, no sampling cadence. An auditor cannot reproduce the 99.5% availability figure from this description. Define concretely: which Vercel page, which date range, which export method, whose responsibility, what cadence.
SOC 2 system description says observation-window prerequisites are 'scheduled' but no concrete dates exist
docs/compliance/soc2-system-description.md:90
control-calendar.md lists the IR tabletop as 'Before the Type II window opens' with no actual meeting date. backup-policy.md specifies quarterly restore tests but records no first scheduled instance. 'Scheduled' implies a date exists; if it doesn't, this is a false-precision claim of the MAJ-7/RG-2 class.
Corrective-action register has 4 open CAs with 'TBD' due dates — Clause 10.1 nonconformity
docs/compliance/corrective-action-register.md
CA-002 (CFE deletion, High), CA-003 (auth-cache, Medium), CA-004 (AdministratorAccess, High), CA-005 (mgmt account workloads, Medium) all show 'Due: TBD'. ISO 10.1 requires specific target completion dates. Stage 1 auditors routinely flag TBD due dates on open CAs as evidence the corrective-action process is not operating. CA-002 and CA-004 (both High) need concrete dates.
Document-drift detection relies on undocumented recurring standup with no calendar evidence
docs/compliance/control-calendar.md:45
control-calendar.md says 'calendar reminders + the fortnightly compliance standup are the mechanism' for document freshness until BAT-232 ships. No evidence the standup exists as a recurring calendar event; no defined owner for reminder creation; no pointer in document-control-procedure.md. 'We had reminders' is not a verifiable control.
O-8 restore-test cadence conflicts: quarterly (O-8 + backup-policy) vs annual (BC/DR policy)
docs/compliance/policies/business-continuity-dr-policy.md:13
Security objective O-8 and backup-policy.md both specify quarterly restore tests. business-continuity-dr-policy.md line 13 says 'Annual DR exercise'. control-calendar.md correctly lists quarterly. BC/DR policy is the outlier; an auditor sampling at the lower-frequency anchor will observe fewer tests than expected.
CFE credential manual interim deletion never exercised — no test record exists
docs/compliance/policies/data-retention-disposal-policy.md:21
The policy describes the obligation but there is no runbook for the interim manual deletion path and no evidence of a test run. RG-3 explicitly notes 'designed but never exercised'. Type I auditor would expect either an exercise record or a step-by-step runbook for the interim procedure.
improvement7
Open CAs CA-002..CA-005 have no due dates — fix before Stage 1
docs/compliance/corrective-action-register.md
All four open corrective actions carry 'Due: TBD'. Each needs a concrete date: CA-002 tied to BAT-256 milestone, CA-004 tied to BAT-259, CA-005 to BAT-260. Cheap fix; an auditor sampling Clause 10 compliance at Stage 1 will cite TBD dates as the corrective-action process not operating.
RG-3 (CFE offboarding dry-run) has no owner, date, or artifact spec
docs/compliance/audit-remediation-tracker.md
RG-3 is the only residual that produces an auditor-inspectable artifact (dated offboarding checklist). Currently: no owner, no date, no artifact definition. HR policy promises the dry-run before the observation window. Name Diego as owner, set target date (before M6 window open), specify artifact: 'completed offboarding checklist with Secrets Manager deletion confirmation, logged in CA-002'.
No legal register exists; 5.31 is ▢ 'with counsel' — Stage 1 auditors probe this
docs/compliance/statement-of-applicability.md
Context-and-interested-parties.md lists INAI/LFPDPPP as a primary interested-party whose requirements the ISMS must address. 5.31 is ▢ with 'Register: LFPDPPP, fiscal retention, customer contracts — with counsel'. No legal register exists in docs/compliance/. A one-page legal register listing LFPDPPP, Código Fiscal, and applicable NOM obligations + status closes this gap before Stage 1. Much of the content is already known without external counsel.
Controls 5.5/5.6 reference IR plan contacts that don't exist in the IR plan
docs/compliance/statement-of-applicability.md
SoA 5.5 says 'Name contacts (LFPDPPP authority INAI, CERT-MX) in the IR plan' and 5.6 says 'List AWS/GitHub security bulletins in IR plan'. Neither section exists in incident-response-plan.md. Both are cheap to add (a list of 5 contacts + a list of 5 advisory subscriptions) and close two ▢ controls without founder action.
Competence evidence for ISMS owner is aspirational — 'CTO experience' is not an auditable record
docs/compliance/competence-and-communication.md
ISO 7.2 requires documented evidence of competence. 'CTO experience; leads the program; (optional) ISO Lead Implementer course' is not a document. Name the fallback evidence: 'documented engagement in ISMS design decisions evidenced by commit history and management-review minutes'. IR tabletop participation record should be listed as 'pending — scheduled for [date]' rather than implicitly current.
document-control-procedure does not specify external-document expiry tracking — attestations will silently age out
docs/compliance/document-control-procedure.md
vendor-register.md lacks obtained-date and expiry columns. SOC 2 reports expire after 12 months; during the Type II observation window, an attestation collected in M3 expires in M15 — but without expiry tracking it will appear current. Add an 'obtained / expires' column to the vendor register and an explicit attestation-expiry spot-check to the control calendar.
Break-glass procedure for key-person concentration (R-9) referenced but not written
docs/compliance/risk-register.md
R-9 mitigation cites 'documented deputies, break-glass procedure, password-manager shared vaults'. access-control-policy.md mentions 'break-glass path' but no runbook exists. A one-page doc (which vault, who has deputy credentials, post-use review) provides evidence for R-9, A.5.2, A.5.3, and BC/DR simultaneously — and is the answer to 'what if Alex is unavailable during a SEV1?'
History · 6 commits
- 2ad7120blockedincremental7H · 14M · 11L2026-07-08 17:33current
- 26393f2needs attentionincremental5H · 19M · 11L2026-07-08 04:57
- 9b22f9fneeds attentionincremental6H · 12M · 9L2026-07-08 03:15
- 697438cneeds attentionfull3H · 7M · 6L2026-07-07 20:12
- aaec085needs attentionincremental7H · 11M · 9L2026-07-07 17:59
- 6a3693cneeds attentionfull11H · 13M · 6L2026-07-07 17:41