Prepared: 12 August 2026 · Standard: AICPA TSP Section 100, 2017 Trust Services Criteria with revised 2022 points of focus · Aligned to directive v36
Working copy and full detail: D:\gh\compliance\soc2\ (27 files, including per-project remediation plans, a 14-policy pack, and an 81-control register mapped to all 61 criteria with zero coverage gaps).
JBNX is a one-human company whose engineering labour is performed by AI agents under a versioned written directive. That is unusual for SOC 2 and it cuts both ways.
In your favour. The directive, the claim → boot → work → verify → status → release loop, agent_ops.escalations, portal handover history, and the billable work-session ledger already constitute a documented, enforced, evidence-producing operating procedure. Change management and monitoring are the two hardest criteria for a company this size, and the design here is further along than a ten-person team typically manages.
Against you. Two things. First, segregation of duties: one human authors requirements, approves changes, holds every credential, and is the only party who could detect his own error. Second — and this emerged during the engagement — no change gate is actually enforced anywhere in the estate today. See the security review published alongside this document.
JBNX is a one-human company whose engineering labour is performed by AI agents under a versioned written directive. That is unusual for SOC 2, and it cuts both ways:
hi.jbnx.io directive, the claim→boot→work→verify→status→release loop, agent_ops.escalations, the portal handover history, and the billable work-session ledger already constitute a documented, enforced, evidence-producing operating procedure. Most companies your size have nothing like it. Change management (CC8) and monitoring (CC4) are the two hardest criteria for a startup, and you are further along on both than a ten-person team typically is.
approves PRs, holds every credential, administers every vendor console, and is the only person who could detect his own error. There is no "second pair of eyes" available. This must be solved with documented compensating controls, not hand-waved. Section 4 of the control framework does that explicitly.
The single biggest risk to this program is not a missing control. It is scope. Five TSC across 18 repositories, from a standing start, with one human, is a two-year program if attempted literally. Read 02-plan-of-attack.md §1 before you commit budget — it contains a scope pressure-test and a recommended de-scope that gets you a sellable report in ~7 months instead of ~20, with a documented path to the full five later.
The system description is the part of a SOC 2 report the auditor does not write. You write it; they opine on whether it is fairly presented. A vague boundary here produces an unlimited audit, because anything you failed to exclude is assumed included.
Version: 0.1 (draft) · Date: 11 August 2026 · Owner: Joey Nguyen
| Field | Value |
|---|---|
| Legal entity | JBNX LLC |
| DBA / trading name | CipherDeck |
| Personnel | 1 human (Joey Nguyen, CEO). All engineering, operations, and support labour performed by AI agents under the JBNX work directive (https://hi.jbnx.io, currently v35). |
| Governing operating procedure | The JBNX work directive, versioned, re-fetched at the start of every work session. Supplemented by the jbnx-ops runbook. |
| Decision authority model | agent_ops.policy on the jbnx Supabase project. CEO escalation thresholds: legally binding, irreversible, or ≥ $500/mo recurring / ≥ $2,000 one-off — and all three critical_test conditions. Everything else decided by agent 02 (Delivery Lead) with a mandatory recorded rationale. |
| Escalation SLA | decide_by capped at 12 hours; take_default_actions() runs every 10 minutes under pg_cron. Silence resolves to the recorded default. |
Why this matters to the audit. An auditor's first instinct on a one-person company is that the control environment (CC1) is unauditable — there is no board, no HR function, no segregation. JBNX has an unusual answer: the control environment is codified in a database with an immutable decision log, not held in one person's head. Lead with that. It is stronger than the org chart most seed-stage companies present.
Eighteen repositories were surveyed at D:\gh on 11 August 2026. Classification below.
| System | Public surface | Data | Infrastructure | Why Tier 1 |
|---|---|---|---|---|
FedM8 (fedm8-scan) | ai.fedm8.com, scan.fedm8.com | Veteran PII, CAGE/UEI, federal contracting profiles, Stripe customer + subscription data | Supabase oeohvlajtexuxjfrtcdb, Cloudflare Workers, GitHub Pages | Highest-sensitivity personal data in the estate. Paid SaaS. Prior audit (AUDIT.md, 28 Jul 2026) recorded P0 findings including a security model not held in version control. |
JBNX Bill (jbnx-bill) | bill.jbnx.io | Customer identities, credentials, work-session records, credit purchases, billing amounts | Railway, Postgres (billing.* schema) | This is the customer's financial record of what they were charged. Integrity failures here are directly monetary and directly customer-visible. |
Projects Portal + Directive (jbnx.io → projects-portal/) | projects.jbnx.io, hi.jbnx.io | Agent claims, handovers, usage/token records, portfolio. and agent_ops. schemas | Railway project ai.jbnx.io service projects, Supabase ngjmqdzpnhwpybtssykz | Not customer-facing, but maximum blast radius: one service serves both the portal and the directive every agent depends on. Also holds SUPABASE_SERVICE_KEY and ANTHROPIC_API_KEY at the jbnx.io service. A compromise here compromises everything. |
| System | Public surface | Data | Infrastructure |
|---|---|---|---|
CipherDeck Apps (cipherdeck-apps) | app.cipherdeck.com | User accounts, Stripe billing, marketplace/collection data, TCG + PSA ingest | Railway project-cipherdeck, Supabase xrlpdsovirwluwhemuwf |
NodeDough / Know Dough (nodedough) | nodedough.com | Personal financial data — accounts, balances, debt payoff plans, recurring items, household membership | Railway nodedough, Supabase hykjfezeywjvzslowjyf |
ai.jbnx.io (ai-portal) | ai.jbnx.io | LLM gateway usage, prompts/completions routed via LiteLLM, model spend | Railway ai.jbnx.io service web, Supabase ngjmqdzpnhwpybtssykz |
nguy.in (nguy.in) | nguy.in | Calendar/personal data, Supabase edge functions, email routing | Cloudflare, Supabase, Next.js |
| System | Role | Note |
|---|---|---|
mkt.jbnx.io | Internal marketing service | Holds SQL + skills; Railway-deployed Flask app |
mockups | Internal hosting service | Has an authed deploy API and Supabase Storage backing — this is an application, not a static site. Treat accordingly. |
claude-ops | Agent command/result store | Contains agent instructions and outputs; review for data leakage into results/ |
deploy-all.ps1 / .cmd | Deployment tooling at estate root | Any credential handling here is in scope |
cipherdeck (webhook-dispatcher) | Outbound webhook engine | Static storefront plus a webhook dispatch engine — the dispatcher is in scope even though the page is not |
fedm8 (marketing), demo, scytherdeck, tensuite, cipherdeck-shopify (Shopify-hosted theme).
Caveat that must be written into the description: these are excluded on the basis that they store no customer data and perform no processing. Each has a GitHub Pages deploy workflow, so they remain in scope for change management and repository access control (CC6.1, CC8.1) even while excluded from the data-processing boundary. Do not exclude the repositories; exclude the systems.
JBNX will use the carve-out method for all subservice organisations. This is the correct choice for a company this size: the inclusive method would require you to describe and be opined on for controls you neither operate nor can evidence.
| Subservice org | Function | Report you must collect annually | Complementary Subservice Organisation Controls (CSOCs) you rely on |
|---|---|---|---|
| Railway | Application hosting, container runtime, deploy pipeline | SOC 2 Type II (confirm availability; if none, this is a finding requiring a documented compensating assessment) | Physical/environmental security, hypervisor isolation, network security |
| Supabase | Managed Postgres, auth, storage, edge functions | SOC 2 Type II | Database host security, backup execution, encryption at rest, physical security |
| Cloudflare | DNS, CDN, WAF, Workers, Pages | SOC 2 Type II | Edge network security, DDoS mitigation, TLS termination |
| GitHub | Source control, CI/CD (Actions), secrets store | SOC 2 Type II | Repository access enforcement, Actions runner isolation, secret encryption |
| Stripe | Payment processing (FedM8, CipherDeck Apps) | SOC 1 + SOC 2, PCI DSS AoC | Cardholder data handling — JBNX must never store PAN; confirm this is true in every integration |
| Anthropic | Model inference (via LiteLLM gateway) | SOC 2 Type II | Model API security, data handling / no-training commitments — verify contractual terms |
| Shopify | CipherDeck storefront commerce | SOC 2, PCI DSS | Payment and order data handling |
| Email provider (Resend/SES — confirm) | Transactional email, auth email | SOC 2 | Message delivery, content handling |
Action (Phase 0): build vendor-register in the control matrix. For each: report obtained, report date, period covered, CSOCs mapped, exceptions noted, next collection date. A vendor whose SOC 2 you have not read is a vendor you have not assessed.
These are controls your customers must operate for your controls to be effective. Every SOC 2 report has them; omitting them transfers your customers' failures onto you.
Candidate CUECs for JBNX (to be finalised in Phase 1):
enabling MFA where offered.
access revocation.
(particularly relevant to FedM8 — veteran PII is uploaded by the customer).
bill.jbnx.io andreporting discrepancies within a defined window.
(CipherDeck webhook dispatcher).
| Class | Definition | Where it lives | Handling |
|---|---|---|---|
| Restricted | Veteran PII, personal financial account data, authentication secrets, payment tokens | FedM8 Supabase, NodeDough Supabase, credential stores | Encryption in transit + at rest; RLS enforced and tested; access logged; never in a repository, never in a chat transcript, never in an LLM prompt without a documented decision |
| Confidential | Customer identity, billing records, work sessions, contract/opportunity data, agent handovers | billing., portfolio., agent_ops.*, CipherDeck Apps | RLS enforced; least privilege; retention defined |
| Internal | Directive, runbooks, ops docs, non-secret configuration | Repos, portal /framework/* | Version controlled; no external publication of infrastructure specifics |
| Public | Marketing content, published frameworks, security.txt | Static sites, portal | No restriction |
Standing rule (already in the runbook, elevate to policy): credentials live only in Railway service variables, GitHub Actions secrets, Supabase Edge Function secrets, or Supabase Vault. Reference by name only. Anything read into a chat enters the transcript and is thereafter compromised.
Required for the description. Must show, at minimum:
of error in this estate — the runbook warns explicitly not to guess**)
projects.jbnx.io API, agent_ops, billing.work_sessionspoint for most of this estate — say so explicitly)
Recorded now so they are not discovered during fieldwork.
from the repository's migration series. An auditor testing CC8.1 (change management) will ask you to demonstrate that production schema matches an approved, version-controlled change. Today you cannot for this system. This is a material change-management finding and it is on the critical path.
AUDIT.md P0-5, the paywall,entitlement logic, free tier, and PII visibility all live as RLS policies and functions that exist only in the hosted database. Same criterion, same problem, higher sensitivity.
www.jbnx.io serves a certificate that does not match the hostname (missing Railway TXTvalidation record). A browser TLS warning on a company domain during fieldwork is an avoidable embarrassment and arguably a CC6.7 finding.
jbnx/projects-portal repository is stale and does not deploy. If anauditor samples a change from it, the evidence trail will be wrong. Archive it or document it explicitly as non-authoritative.
gitleaks runs in jbnx.io quality-gates only.Seventeen other repositories have no secret scanning. CC6.1/CC7.1.
01-control-framework.md §4 — but it must be addressed, not omitted.
gated lane (nodedough, fedm8, cipherdeck) and an ungated PROD-IT lane (everything else, including jbnx-bill and projects-portal). The full-stack handover records that the gated lane is not actually enforced: production branches exist, but each Railway service still builds its production environment from main, and repointing is a 2FA-gated dashboard action no API can perform. CC8.1 fails estate-wide until this is corrected. See 01-control-framework.md CC8.1.
/ and /json serve v36; /md and /txt serve v35. Agents are directed to the Raw/Plain/JSON variants, so an agent can operate from a superseded procedure.
Standard: AICPA TSP Section 100, 2017 Trust Services Criteria with revised points of focus (2022) — the current version as of 2026. Roughly 61 criteria across five categories, plus several hundred points of focus. Points of focus are not requirements; they are illustrations of how a criterion might be met. Do not build a control for every point of focus. Build a control for every criterion, then use the points of focus to argue completeness.
Version: 0.1 · Owner: Joey Nguyen · Companion artifact: 02-control-matrix.xlsx
| Category | Criteria | Required? | JBNX decision |
|---|---|---|---|
| Security (Common Criteria, CC1–CC9) | 33 | Always | In scope |
| Availability (A1.1–A1.3) | 3 | Optional | In scope |
| Processing Integrity (PI1.1–PI1.5) | 5 | Optional | In scope — see scope pressure-test |
| Confidentiality (C1.1–C1.2) | 2 | Optional | In scope |
| Privacy (P1–P8) | 18 | Optional | In scope — see scope pressure-test |
Common Criteria breakdown: CC1 Control Environment (5) · CC2 Communication and Information (3) · CC3 Risk Assessment (4) · CC4 Monitoring Activities (2) · CC5 Control Activities (3) · CC6 Logical and Physical Access (8) · CC7 System Operations (5) · CC8 Change Management (1) · CC9 Risk Mitigation (2).
Note on effort distribution. CC6, CC7, and CC8 are ~14 of 33 Common Criteria but will consume ~60% of the work, because they are the ones that require operating evidence across the whole window rather than a document. CC1–CC5 are mostly documentation. Privacy (P1–P8) is 18 criteria and behaves like a second audit bolted onto the first — it requires notice, choice, consent, data subject access request handling, and disclosure tracking that JBNX does not currently have any of.
Four principles, derived from what already works here. Controls that violate these will not survive a Type II window.
P1 — If it isn't automated, it won't happen. One human, no ops team. A control that requires Joey to remember something monthly will fail in month three and the failure will appear in the report as an exception. Every recurring control must be a GitHub Action, a pg_cron job, a portal API side-effect, or a Claude scheduled task.
P2 — Evidence is a byproduct, not a task. The best controls in this estate already work this way: security-boundaries.yml re-proves closed holes nightly and leaves a dated run log. That is a perfect Type II artifact — automatic, timestamped, tamper-evident, and it fails loudly. Copy that pattern rather than inventing checklists.
P3 — The database is the control point. For most of this estate, authorisation is the RLS policy. That means control testing is SQL, not screenshots — and it means the runbook's hard-won Postgres traps (column REVOKE is a no-op against a table grant; default privileges grant EXECUTE to anon directly; TRUNCATE ignores RLS; views have no policies) are control design requirements, not trivia.
P4 — Test the positive case. A probe that only tests denials cannot distinguish a correct policy from one that denies everyone. Already learned the hard way here; make it a standard in the test procedure column of every access control.
Format: criterion → what it asks → the JBNX control → evidence artifact → current status. Status key: ✅ exists · 🟡 partial · 🔴 gap · ⬜ not assessed
| ID | Asks | JBNX control | Evidence | Status |
|---|---|---|---|---|
| CC1.1 | Commitment to integrity and ethical values | Code of Conduct policy; the directive's defect definitions (silent $0 usage, duplicate billables, falsified durations) are literally an ethics statement about not falsifying customer receipts | Signed policy; directive v35 §Billable time | 🟡 |
| CC1.2 | Board independence / oversight | No board. Compensating control: documented advisory arrangement (external CPA/counsel) + quarterly written program review by CEO, recorded and dated | Quarterly review memo | 🔴 |
| CC1.3 | Structures, reporting lines, authorities | agent_ops.policy — seat register, escalation thresholds, v_needs_ceo / v_needs_manager split, immutable manager_decide() audit trail | DB export of policy + decision rows | ✅ strong |
| CC1.4 | Commitment to competence | Agent seat definitions; the directive as the operating standard; the jbnx-ops runbook as institutional knowledge; method-analysis scoring gate (>90) | Seat register, analysis-run JSON history | 🟡 |
| CC1.5 | Accountability | One claim = one billable session = one handover = one release. Every unit of work is attributed, timed, and closed out | billing.work_sessions, pf_project_pages handovers | ✅ strong |
| ID | Asks | JBNX control | Evidence | Status |
|---|---|---|---|---|
| CC2.1 | Quality information for internal control | Portal handover BLUF (state_now/next/traps/done); token usage + health bands; RAD lifecycle readiness bars | Portal API exports | ✅ |
| CC2.2 | Internal communication of objectives/responsibilities | The directive itself, re-fetched every session and version-pinned; runbook; ceo_actions queue | Directive version history, /json endpoint | 🟡 — strong design, live defect: / and /json serve v36 while /md and /txt serve v35 (verified 12 Aug 2026). Agents are told to use Raw/Plain/JSON, so some read a superseded deploy model |
| CC2.3 | External communication | Published frameworks at /framework/<slug>; security.txt; Terms/Privacy pages; customer-readable --done text requirement | Live URLs | 🟡 — Terms/Privacy exist for FedM8, NodeDough, nguy.in only |
| ID | Asks | JBNX control | Evidence | Status |
|---|---|---|---|---|
| CC3.1 | Objectives specified with sufficient clarity | Written security objectives per system tier; service commitments per product | Risk assessment doc | 🔴 |
| CC3.2 | Identify and analyse risk | Annual formal risk assessment + quarterly refresh; risk register with likelihood/impact/treatment | Risk register | 🔴 |
| CC3.3 | Consider potential for fraud | Highest-value criterion for JBNX. Billing integrity is the fraud surface: duplicate billables, inflated durations, credits-unit errors (the v35 factor-of-100 defect class). Controls: one-claim-one-session invariant, >12h auto-close, read-time-only conversion | Reconciliation job output | 🟡 |
| CC3.4 | Identify and assess change | Change risk assessed at claim time; irreversible/legally-binding/spend thresholds route to CEO | Escalation records | ✅ |
| ID | Asks | JBNX control | Evidence | Status |
|---|---|---|---|---|
| CC4.1 | Ongoing and separate evaluations | Nightly security-boundaries.yml (NodeDough); schema-drift.yml; Supabase advisors; to add: monthly dead-grants sweep across all projects, weekly rotating deep review | Actions run history, advisor output | 🟡 — exists on one project only |
| CC4.2 | Evaluate and communicate deficiencies | Findings register with severity, owner, due date, acceptance test — the format AUDIT.md already uses | Findings register | 🟡 |
| ID | Asks | JBNX control | Evidence | Status |
|---|---|---|---|---|
| CC5.1 | Select and develop control activities | This framework + control matrix | Control matrix | 🟡 |
| CC5.2 | Technology general controls | CI quality gates, healthchecks, RLS, secret scanning, branch protection | Actions config, branch rules | 🟡 |
| CC5.3 | Deploy through policies and procedures | Policy pack (04-policies/) + directive + runbook | Signed policies | 🔴 |
| ID | Asks | JBNX control | Evidence | Status |
|---|---|---|---|---|
| CC6.1 | Restrict logical access | Supabase RLS on every table; explicit revoke execute … from anon on every function; no write grants on views; TRUNCATE revoked estate-wide; least-privilege GitHub/Railway/Cloudflare roles | Dead-grants query output, grant snapshots | 🟡 — proven applied on NodeDough, unverified elsewhere |
| CC6.2 | Register and authorise new users | Documented provisioning procedure incl. agent seats; approval recorded before access granted | Access request log | 🔴 |
| CC6.3 | Modify/remove access | Monthly access review across GitHub, Railway, Supabase, Cloudflare, Stripe, Anthropic, email. Removal within defined SLA | Monthly review record | 🔴 |
| CC6.4 | Restrict physical access | Carved out to Railway/Supabase/Cloudflare. JBNX-side: endpoint (CEO workstation) disk encryption, screen lock, device inventory | Device attestation | 🔴 |
| CC6.5 | Protect against unauthorised disposal | Data deletion procedure; Supabase project deletion procedure; retention purge (data-retention.yml pattern) | Purge job logs | 🟡 |
| CC6.6 | Protect against external threats | Cloudflare WAF/DDoS; TLS everywhere; fix the www.jbnx.io certificate mismatch; bill.jbnx.io must remain grey-cloud with a documented compensating rationale | TLS scan results | 🟡 |
| CC6.7 | Restrict transmission/movement of information | TLS enforced; secrets referenced by name only; no credentials in repos, files, or chat transcripts; migration to sb_publishable_/sb_secret_ keys before the end-2026 legacy deprecation | Gitleaks results across all repos | 🟡 |
| CC6.8 | Prevent/detect unauthorised software | Dependabot on all repos; pinned action SHAs (already done in quality-gates.yml — good practice, extend it); lockfile integrity | Dependabot alerts, CI config | 🟡 |
| ID | Asks | JBNX control | Evidence | Status |
|---|---|---|---|---|
| CC7.1 | Detect configuration changes / vulnerabilities | schema-drift.yml pattern extended estate-wide; Supabase advisors; Dependabot; secret scanning | Drift + advisor reports | 🟡 |
| CC7.2 | Monitor for anomalies | Weakest area. Railway healthchecks are deploy-time only and explicitly not uptime monitoring — the runbook says so. No alerting, no log aggregation, no uptime monitor today | Monitoring dashboards | 🔴 |
| CC7.3 | Evaluate security events | Incident classification + triage procedure; ceo_actions for anything actively costing money or exposing data | Incident register | 🔴 |
| CC7.4 | Respond to incidents | Incident Response Plan + at least one tabletop per year | IR plan, tabletop record | 🔴 |
| CC7.5 | Recover from incidents | Documented recovery: Supabase PITR/backups, Railway redeploy-from-source (note: deployments past retention cannot be rolled back, only redeployed), restore test performed and evidenced | Restore test record | 🔴 |
| ID | Asks | JBNX control | Evidence | Status |
|---|---|---|---|---|
| CC8.1 | Authorise, design, develop, configure, test, approve, implement changes | Directive v36 defines two lanes: gated (nodedough, fedm8, cipherdeck) — PR → test URL → chat approval → promote; ungated (PROD-IT — everything else, including jbnx-bill and projects-portal) — main IS production; a push deploys live with no gate | PR history, approval record, Actions runs | 🔴 Failing — see below |
### The CC8 problem, stated plainly — corrected against directive v36 and the livefull-stackhandover This is the most serious finding in the engagement, and it is worse than it looks on paper. 1. Two of your three Tier 1 systems have no change gate by design. Under v36's PROD-IT lane,jbnx-bill(the customer's financial record) andprojects-portal/jbnx.io(the control plane and the directive itself) deploy to production on a push tomain. No PR requirement, no approval, no test lane. The directive is explicit that this is intentional — "there is no test gate and none is wanted." That is a defensible engineering position and an indefensible CC8.1 position, because the criterion requires changes to be authorised and approved before implementation. 2. The gated lane is not actually enforced either. Thefull-stackhandover records the trap directly: "Branches alone do not create the gate — each Railway service production environment must be repointed frommaintoproductionin the dashboard, which no API can do. Until then the gate in directive v36 is still not enforced." Production branches now exist for NodeDough and both CipherDeck projects, but the Railway services still build frommain. So today, in practice, every repository in the estate is push-to-production. CC8.1 currently fails everywhere, not just on the ungated lane. 3. Approval, where it happens, is ephemeral. Chat approval is a sensible design choice, but a chat transcript is not durable, addressable audit evidence. An auditor sampling 25 changes will ask you to produce the approval for each. 4. Production schema that did not come from an approved change. NodeDough's divergent migration lineage and FedM8's unversioned security model are the same criterion failing from the data side. Remediation, in order: | # | Action | Note | |---|---|---| | 1 | Repoint the Railway production environments fornodedough,fedm8,cipherdeckfrommaintoproduction| Dashboard-only, 2FA-gated — a CEO action, not an agent action. Nothing else on this list matters until this is done, because the gate that exists on paper does not exist in the service | | 2 | Bringjbnx-billandprojects-portalonto the gated lane | This is a scope decision with a cost: PROD-IT exists because it is fast. The honest options are (a) gate them, (b) exclude them from the audit boundary, or (c) accept a CC8.1 exception with compensating detective controls. Option (b) is not available forjbnx-bill— it is the billing system | | 3 | Persist chat approvals to GitHub + achange_approvalsrow before merge | Converts approval from ephemeral to evidenced | | 4 | Branch protection on all in-scope repos, no admin bypass | Prevents silent gate bypass | | 5 | Reconcile NodeDough lineage; version FedM8's security model | The data-side half of the same criterion | Do not paper over this. A control that is documented but not enforced is worse in an audit than an acknowledged gap, because it calls the accuracy of the whole description into question.
| ID | Asks | JBNX control | Evidence | Status |
|---|---|---|---|---|
| CC9.1 | Business disruption risk mitigation | BCDR plan; single-service blast radius for portal+directive documented with a failover position; cyber insurance decision recorded | BCDR plan | 🔴 |
| CC9.2 | Vendor and business partner risk | Vendor register + annual SOC 2 collection + CSOC mapping (see 00-scope §3) | Vendor register | 🔴 |
| ID | Asks | JBNX control | Status |
|---|---|---|---|
| A1.1 | Capacity management | Railway metrics review; LLM spend/credit budget monitoring at #/credits; documented capacity thresholds | 🟡 |
| A1.2 | Environmental protections, backup, recovery infrastructure | Supabase automated backups + PITR level per project (verify per project — plan-dependent); Railway redeploy-from-source; documented RPO/RTO per system tier | 🔴 |
| A1.3 | Recovery testing | Annual restore test per Tier 1/2 system, evidenced | 🔴 |
Availability requires a published commitment. You cannot be audited against an SLA you never stated. Phase 0 must define uptime commitments per product (e.g. 99.5% for Tier 1, best-effort for Tier 3) and publish them. Then you need an uptime monitor to measure against them — this is the single most concrete missing tool in the estate.
| ID | Asks | JBNX control | Status |
|---|---|---|---|
| PI1.1 | Information about processing objectives is communicated | Product documentation stating what each system computes and its data sources | 🔴 |
| PI1.2 | Inputs are complete, accurate, authorised | FedM8 ingest validation; NodeDough transaction entry validation; billing input controls | 🔴 |
| PI1.3 | Processing is complete, accurate, timely, authorised | The credits calculation is the flagship PI control: seconds stored, converted once at read boundary, CREDITS_PER_HOUR = 6000 consistent across all four locations. Also reconcile-billing.yml | 🟡 |
| PI1.4 | Output is complete, accurate, timely | Customer-visible billing totals reconcile to session records; FedM8 result counts are measured not extrapolated | 🔴 — AUDIT.md P0-3 documents a headline figure overstated by 8.8% presented as live data |
| PI1.5 | Storage is complete, accurate, timely, authorised | Retention + purge jobs; checkpoint/balance-history integrity | 🟡 |
Processing Integrity is the criterion FedM8 currently fails hardest. AUDIT.md records hardcoded sample data presented to paying customers as retrieved data, a headline figure extrapolated under a "Live from USAspending.gov" indicator, and a 500-row cap silently truncating results while the counts conceal it. Those are textbook PI1.2/PI1.4 failures. They are also product-quality problems worth fixing regardless of SOC 2 — but including PI in scope makes them audit blockers, not backlog items.
| ID | Asks | JBNX control | Status |
|---|---|---|---|
| C1.1 | Identify and maintain confidential information | Data classification (see 00-scope §5) applied to every table/bucket; documented per system | 🔴 |
| C1.2 | Dispose of confidential information | Retention schedule + automated purge (the data-retention.yml pattern) + deletion-on-request procedure | 🟡 |
| ID | Asks | Status |
|---|---|---|
| P1.1 | Privacy notice communicated | 🟡 — exists for FedM8, NodeDough, nguy.in; missing elsewhere; none reviewed for accuracy against actual practice |
| P2.1 | Choice and consent obtained | 🔴 |
| P3.1–3.2 | Collection limited to stated purpose; explicit consent for sensitive data | 🔴 — veteran PII in FedM8 is the sensitive-data trigger |
| P4.1–4.3 | Use, retention, and disposal limited to stated purpose | 🟡 — 90-day analytics retention is stated and now enforced on NodeDough; nothing comparable elsewhere |
| P5.1–5.2 | Data subject access and correction | 🔴 — no DSAR process exists |
| P6.1–6.7 | Disclosure to third parties, tracking, breach notification | 🔴 — no disclosure log, no breach notification procedure |
| P7.1 | Data quality | 🔴 |
| P8.1 | Monitoring and enforcement of privacy commitments, complaint handling | 🔴 |
Privacy is 18 criteria and roughly zero of them are met today. It also drags in GDPR/CCPA adjacent obligations that a SOC 2 privacy opinion will effectively hold you to. Read the scope pressure-test in 02-plan-of-attack.md §1 before committing.
This section exists because it is the first thing a competent auditor will challenge, and because the honest answer is better than a fudged one.
The problem. Joey authors requirements, approves every PR, holds every credential, administers every vendor console, and is the only party who could detect his own error. Agents write the code and could, absent controls, approve and deploy it. Classic SoD is unavailable.
The wrong answers. Hiring a nominal second employee to sign things. Claiming agents provide independence (they don't — they operate under your instruction). Omitting the topic.
The defensible position — compensating controls. Argue that JBNX substitutes structural separation for personnel separation, and evidence each of these:
| # | Compensating control | Why it substitutes | Evidence |
|---|---|---|---|
| 1 | Automated gates the approver cannot silently bypass — quality-gates, gitleaks, security-boundaries, schema-drift must be green; branch protection enforced with no admin bypass | Removes "approver overrode the check" as an undetectable event | Branch protection config; Actions history showing no force-merges |
| 2 | Preventive/detective split across independent agents — the agent that writes a change is not the agent that verifies it. Distinct seats, distinct claims, recorded separately | Reintroduces two-party review, even though both parties are non-human | Claim records showing author seat ≠ verifier seat |
| 3 | Immutable decision log — agent_ops.manager_decide() requires a rationale, refuses CEO-class items, and produces immutable rows | You cannot retroactively rewrite why a decision was made | DB rows with insert triggers, routed_because |
| 4 | Independent external review — annual third-party penetration test and an external readiness/gap assessment by a party who is not you | Supplies the genuine independence the org chart cannot | Pen test report; readiness assessment |
| 5 | Tamper-evident, append-only evidence — Actions run logs, immutable billing sessions, append-only analysis runs, portal handover versioning | Detection substitutes for prevention where prevention is impossible | The artifacts themselves |
| 6 | Formal risk acceptance for residual SoD risk, signed and dated by the CEO, reviewed quarterly | Auditors accept documented, owned residual risk; they do not accept undisclosed risk | Signed acceptance in the risk register |
Write this into the system description. Do not wait to be asked. A well-argued compensating-control narrative disclosed up front reads as maturity; the same facts discovered during fieldwork read as a finding.
| Aspect | Control or risk | Treatment |
|---|---|---|
| Directive re-fetched, version-pinned, "don't trust a paste" | Control — a documented, enforced, versioned procedure with tamper detection | Cite in CC2.2. Retain version history as evidence |
| Claim → one billable session → release | Control — complete work attribution and time accounting | Cite in CC1.5, CC3.3 |
| Mandatory usage recording; "silent $0 is a defect" | Control — spend accountability | Cite in CC1.1, A1.1 |
| Agents hold write access to production repositories | Risk | Scoped tokens per seat, no shared credentials, revocation procedure, quarterly token rotation |
| Agents can read customer data during troubleshooting | Risk — sharpest one for Privacy | Documented data-access rules for agents; prohibition on restricted data entering prompts; logged and reviewed access |
| Prompts/completions traverse LiteLLM → Anthropic | Risk | Contractual no-training terms verified; data classification rules for prompt content; documented in the description as a data flow |
| "Never ask the CEO" / auto-default escalations | Risk if unbounded | Bounded already by critical_test + 12h decide_by + mandatory default_action; evidence the defaults were reviewed |
| Chat-based PR approval | Risk — ephemeral evidence | Persist approvals to GitHub + a change_approvals table (see CC8.1) |
PROD-IT ungated lane (main IS production) | Risk — no authorisation step at all | Gate, exclude from boundary, or accept with compensating detective controls. Applies to jbnx-bill and projects-portal, both Tier 1 |
| Directive served inconsistently across endpoints | Risk — agents operate from a stale procedure | / and /json serve v36 while /md and /txt serve v35. The page directs agents to Raw/Plain/JSON, so an agent can read a superseded deploy model. Add the daily directive-integrity check (COM-02) |
A control moves to Implemented only when all five are true. This is the definition of done for the entire program.
the implementer (a different agent seat qualifies), and passed.
Anything short of five is In Progress. There is no partial credit at fieldwork.
Program start: 11 August 2026 · Owner: Joey Nguyen · Cadence: phase gates, not sprints
You selected all five Trust Services Criteria across the full estate. Here is what that actually costs, so the decision is made with the number in front of you rather than after.
| Path | Criteria | Systems | Realistic readiness | Report issued | First-year cost |
|---|---|---|---|---|---|
| A. Security only, Tier 1+2 systems | 33 | 7 | ~4 months | ~Q2 2027 | ~$25–45k |
| B. Security + Availability + Confidentiality, Tier 1+2 | 38 | 7 | ~5–6 months | ~Q3 2027 | ~$35–55k |
| C. All five TSC, full estate (as selected) | 61 | 12+ | ~12–15 months | ~Q1 2028 | ~$70–120k+ |
Audit fees alone for a company this size run roughly $20–40k with a boutique or mid-tier CPA firm; some auditors price explicitly by TSC — around $20k for Security only vs $26k for Security + Availability + Confidentiality. The audit invoice is typically only ~40% of true first-year spend once readiness work, tooling, and internal labour are counted.
Adopt Path B as the audited scope, and keep Path C as the roadmap.
Reasoning:
Security, sometimes plus Availability. Privacy (P1–P8) is 18 criteria, requires notice, consent, DSAR handling, disclosure tracking, and breach notification — none of which exist today — and it effectively holds you to GDPR/CCPA-adjacent obligations under audit. It roughly doubles the program. Add it when a contract requires it, not before.
fabricated data shown to paying customers as retrieved, a headline figure overstated by 8.8% under a "live data" indicator, and silent 500-row truncation. Under PI in scope, those are audit blockers. Fix them because they are product-integrity problems worth fixing — then add PI at the next annual audit and it becomes a selling point instead of a gauntlet.
Include it.
this estate: actual uptime monitoring. Railway healthchecks are deploy-time only and, per your own runbook, will never notice a dependency dying later.
Decision required from you (Phase 0, gate G0): confirm Path B, or confirm Path C with eyes open. Everything below is written for Path B with Path C items marked [C]. If you choose C, the [C] items move from the roadmap into Phase 1 and every date slips roughly two quarters.
Dates assume Path B and start 11 Aug 2026. Each phase ends at a gate — a decision you make, not a date that passes.
Phase 0 Foundation 11 Aug – 07 Sep 2026 (4 wks) → G0: scope locked, auditor engaged
Phase 1 Gap closure 08 Sep – 09 Nov 2026 (9 wks) → G1: all Tier 1/2 controls implemented
Phase 2 Readiness + Type I 10 Nov – 21 Dec 2026 (6 wks) → G2: Type I report issued
Phase 3 Type II window 01 Jan – 30 Jun 2027 (6 mths) → G3: window closed, evidence complete
Phase 4 Fieldwork + report 01 Jul – 15 Aug 2027 (6 wks) → G4: Type II report issued
Phase 5 Steady state continuous → annual re-audit, scope expansion
Goal: know exactly what you are auditing, what the risks are, and who is auditing it. No remediation work happens in this phase — resist the urge.
| Wk | Work | Deliverable | Owner |
|---|---|---|---|
| 1 | Lock scope (Path B or C). Finalise system boundary from 00-scope. Produce the boundary diagram | Signed scope memo + diagram | CEO |
| 1 | Complete the asset inventory: every repo, Railway service, Supabase project, domain, third-party account, and credential location (never the credential) | asset-register sheet | Agent |
| 2 | Formal risk assessment. Threat scenarios per system tier, likelihood × impact, treatment decision. Must explicitly cover: single-human key-person risk, portal/directive blast radius, veteran PII exposure, billing integrity/fraud, agent credential compromise, LLM prompt data leakage | risk-register sheet + narrative | Agent → CEO approves |
| 2 | Vendor register: every subservice org, SOC 2 report obtained and read, CSOCs mapped, exceptions logged | vendor-register sheet | Agent |
| 3 | Adopt the policy pack (04-policies/). Draft → CEO review → sign → date → publish to /framework/ | 14 signed policies | Agent → CEO signs |
| 3 | Define service commitments: uptime targets per tier, support response times, data retention periods. These become what you are audited against — state them conservatively | Service commitments doc | CEO |
| 4 | Select and engage auditor. Get 3 quotes from boutique/mid-tier CPA firms with SaaS experience. Ask each: TSC-based pricing, readiness assessment included?, observation window minimum, one-person-company experience | Signed engagement letter | CEO |
| 4 | Build-vs-buy decision (see 05-build-vs-buy.md) | Decision recorded | CEO |
Gate G0: scope memo signed · risk register approved · policies signed · auditor engaged. Do not proceed without an engaged auditor — their readiness assessment shapes Phase 1 and starting remediation blind wastes weeks.
Goal: every control in the matrix reaches Implemented (all five conditions in 01-control-framework.md §6). This is the bulk of the work.
Sequenced by dependency, not by criterion number.
Weeks 1–2 — Access control foundation (CC6.1–6.3, C1.1)
oeohvlajtexuxjfrtcdb, xrlpdsovirwluwhemuwf, hykjfezeywjvzslowjyf, ngjmqdzpnhwpybtssykz). Check relrowsecurity before revoking anything — a table with RLS off means the grant is the access control.
anon/authenticated estate-wide.EXECUTE granted directly to anon. Remember: revoke … from publicis not enough, and you cannot revoke EXECUTE on a function used inside an RLS policy — constrain the function instead.
positive cases**, not the absence of an exception.
anon/service_role keys to sb_publishable_/sb_secret_ (deprecatedend of 2026 — this has a hard external deadline regardless of SOC 2).
Weeks 2–3 — Change management evidence (CC8.1) — highest audit value per hour spent
writes a change_approvals row (PR URL, approver, timestamp, verification evidence, decision).
admin bypass.
remediation date. Add the CI drift check already on record as the long-term fix.
AUDIT.md P0-5): RLS policies, my_plan(), top_opportunities(), the vet_directory view. Until these are in migrations they cannot be reviewed, diffed, tested, or rolled back — and cannot pass CC8.1.
jbnx/projects-portal repository as non-authoritative.Weeks 3–5 — Detection and monitoring (CC7.1, CC7.2, CC4.1) — largest genuine gap
actually read. Railway healthchecks do not count and your runbook says why.
gitleaks secret scanning from jbnx.io to all 18 repositories.jbnx.io to all repositories; add CodeQL where the language is supported.security-boundaries.yml pattern (nightly, transaction-rolled-back, productionRLS re-proof) to FedM8, CipherDeck Apps, and the portal. This is your best control — replicate it.
schema-drift.yml to all Supabase-backed projects.Weeks 5–7 — Operations and resilience (CC7.3–7.5, CC9.1, A1.1–A1.3)
and key-person risk.
www.jbnx.io certificate mismatch (TXT record from the Railway dashboard — the APIwill not give it to you).
Weeks 7–9 — Governance, remaining criteria, and dry run
data-retention.yml purge pattern beyond NodeDough (C1.1/C1.2).
[C] If Path C: add ~8 weeks here for Privacy (notice rewrite, consent capture, DSAR process, disclosure log, breach notification procedure) and ~4 weeks for Processing Integrity (FedM8 P0-1/P0-3/P0-4 remediation, billing reconciliation controls, output accuracy attestation).
Gate G1: every in-scope control Implemented or formally risk-accepted · pen test complete · readiness assessment clean.
| Work | Note |
|---|---|
| Auditor readiness assessment | Their findings, not yours. Fix before fieldwork. |
| Remediate readiness findings | Budget 2 weeks; there will be findings |
| Type I fieldwork | Point-in-time — design of controls as of a date (target: 1 Dec 2026) |
| Type I report issued | This is the artifact you can start selling with in ~4 months |
Gate G2: Type I report issued with no qualifications.
Type I is optional. Skip it if budget is tight and you can wait for Type II. Take it if you have a deal blocked on "do you have SOC 2?" — a Type I answers that question honestly today.
Goal: do nothing new. Operate the controls and let evidence accumulate.
This phase is where programs fail, and they fail quietly. The controls stop running in February, nobody notices until June, and the report comes back with exceptions.
The entire defence is 07-scheduled-tasks.md. During this phase:
evidence chain get investigated this week, not in June.
populations. Avoid unless remediating a real failure — and if you must, document the change and the date.
Gate G3: window closed with a complete, gap-free evidence set for every control.
| Work | Note |
|---|---|
| Evidence package assembly | Should be assembly, not creation. If you are creating, Phase 3 failed |
| Auditor sampling and testing | Typically 25 samples per population; they choose |
| Management responses to exceptions | Every exception gets a response; a well-written response materially changes how the report reads |
| System description finalised | You write it; they opine on fair presentation |
| Report issued |
Gate G4: Type II report issued.
cycle if a contract requires it. By then the machinery exists and marginal cost is far lower.
Six items block everything downstream. If a week is going badly, work on these.
nodedough, fedm8, and cipherdeck from main to production. Production branches exist; the services still build from main, so the change gate described in directive v36 is not enforced anywhere in the estate today. This is dashboard-only and 2FA-gated — a CEO action, not an agent action. It is item zero because CC8.1 fails estate-wide until it is done, and several other controls assume it.
jbnx-bill and projects-portal are Tier 1 systems on the ungated lane where a push to main is a production deploy. Gate them, exclude them from the boundary, or accept a documented CC8.1 exception. jbnx-bill cannot be excluded; it is the billing system.
Stated in advance so it is recognised rather than rationalised.
Mitigation: the scheduled tasks — the program continues without you.
Mitigation: scope changes require a written decision in the register.
check exists solely to catch this in week 1 rather than month 5.
department and a security committee. Mitigation: the policy pack is written for this company.
disabled. Mitigation: nightly security-boundaries re-proof and monthly dead-grants sweep.
Decision required: Phase 0, week 4 · Owner: Joey Nguyen
Compliance automation platforms (Vanta, Drata, Secureframe, Sprinto, Thoropass) do four things:
AWS/GCP, GitHub, Google Workspace, HR systems, and endpoints, and screenshot it on a schedule.
often reduces audit fees.
What they do not do: write your system description, run your risk assessment, fix your controls, reconcile your migration lineages, or make your product accurate.
| Option | Year 1 platform cost | Audit fee | Internal effort | Year 1 total |
|---|---|---|---|---|
| Self-managed (this framework + scheduled tasks) | $0–2k (uptime monitor, pen test tooling) | $20–30k | High in Phase 0–1, low thereafter | ~$25–40k |
| Vanta | ~$10k/yr at small-company scale, up to $25k+ | $20–30k (often reduced with platform) | Lower in Phase 1, moderate ongoing | ~$35–55k |
| Drata | ~$8–20k/yr by tier and size | $20–30k | Similar to Vanta; more evidence customisation | ~$35–55k |
| Secureframe | Starts ~$7.5k, ranges past $80k | $20–30k | More guided implementation | ~$35–60k |
Typical all-in market figures: $45–70k for a small company using a platform; smaller startups land nearer $45–55k. Pen test ($5–15k) is additional in every column and is not optional if you want buyers to take the report seriously.
Platform value is proportional to how much of your estate their integrations cover. Score:
| Your infrastructure | Platform coverage | Notes |
|---|---|---|
| Railway | ❌ Poor / none | Not a first-class integration for any major platform. Your entire compute tier would be manual evidence. |
| Supabase | ❌ Poor / none | Your entire data tier, and where most of your access controls actually live, would be manual. |
| Cloudflare | 🟡 Partial | Some coverage |
| GitHub | ✅ Strong | Good coverage — repos, branch protection, access |
| Google Workspace | ✅ Strong | If used for identity |
| Endpoint/device | ✅ Strong | Agent-based; covers one laptop |
| HR / onboarding | ✅ Strong | Irrelevant — one person, no HR system. A large fraction of platform value is personnel controls you do not have |
| AI agent operating model | ❌ None | No platform models this. Your most distinctive controls are entirely bespoke |
This is the crux. Platforms are priced for companies on AWS/GCP with 30 employees, an HRIS, and an IdP. Roughly half of what you pay for is personnel and cloud-provider automation that either does not apply to you or does not cover your stack. Your two most important control surfaces — Supabase RLS and Railway — are the two they cover worst.
Worth pricing honestly, because it is unusual:
| Platform feature | Your equivalent | Verdict |
|---|---|---|
| Continuous control monitoring | security-boundaries.yml — nightly, against production, transaction-rolled-back, fails loudly | Better than generic platform checks. Theirs check configuration; yours re-proves an exploit is closed |
| Evidence collection with timestamps | GitHub Actions run history | Equivalent, and tamper-evident |
| Policy templates | You need these — a platform provides them | Real gap, but 04-policies/ closes it |
| Auditor portal | A folder and a shared drive | Platform is genuinely better; worth something |
| Access review workflow | Manual today | Real gap — the scheduled task closes it |
| Vendor management | Manual today | Real gap — the control matrix closes it |
| Personnel/onboarding automation | N/A | Zero value at one employee |
| Drift detection | schema-drift.yml | Yours is more specific and more useful |
Self-manage for the first audit cycle. Revisit at the second.
Reasoning:
two least covered. You would pay ~$10k/yr and still collect most evidence manually.
headcount one.
matter here. Replicating security-boundaries.yml across four systems buys more assurance than a platform integration would.
07-scheduled-tasks.md cover the three genuine gaps — accessreview, evidence completeness, and vendor management — for the cost of already-owned tooling.
which buyers actually ask to see and which no platform provides.
paying for itself.
where platforms are genuinely strong, and FedM8's federal customer base makes this plausible.
three quotes explicitly: "what is your fee with and without a compliance platform?" If the delta approaches the platform cost, buy.
that self-management is failing, and it is better to buy in month 2 than to discover a gap in month 6.
| Item | Cost | Why |
|---|---|---|
| Uptime monitoring + alerting | ~$0–50/mo | The single largest capability gap; A1 depends on it |
| Third-party penetration test | $5–15k | CC4.1 independence; buyers ask for it; no platform substitutes |
| Password manager / secrets vault (if not already) | ~$0–60/yr | CC6.1 evidence and basic hygiene |
| External readiness assessment (from the auditor) | Often bundled | Their findings are the ones that count |
segregation of duties?
Question 3 is the filter. An auditor who has never seen a one-person company will spend your money learning on you.
A Type II opinion is about whether controls operated effectively throughout the period. The report stands or falls on evidence, and evidence is the thing that quietly stops being produced in month three.
Evidence is a byproduct of the control operating, never a separate task.
If producing the evidence requires someone to remember to do something, the control will fail in a 6-month window and the failure will appear in the report as an exception. Every control in the matrix must answer: what artifact does this produce automatically, and where does it land?
The estate already has the model right in one place. security-boundaries.yml runs nightly against production, proves specific closed holes are still closed, and leaves a dated, immutable GitHub Actions run record. Nobody has to do anything. That is the pattern.
| Tier | Description | Examples | Auditor confidence |
|---|---|---|---|
| A — System-generated, immutable | Produced by a system, timestamped, cannot be edited after the fact | Actions run logs, DB rows with insert triggers, billing.work_sessions, immutable decision rows, cloud audit logs | Highest. Prefer this always |
| B — System-generated, mutable | Produced by a system but editable | Exported CSVs, config snapshots, monitoring dashboards | Good, with a documented generation procedure |
| C — Human-attested | A person says a thing happened | Review sign-offs, tabletop records, risk acceptances | Acceptable for governance controls only. Never for technical controls |
| D — Reconstructed | Assembled after the fact | Backfilled screenshots, "we always did this" | Worthless, and actively harmful. Auditors are trained to spot it and it undermines everything else |
Target: ≥80% of controls evidenced at Tier A. Where a control can only produce Tier C, ask whether it can be redesigned.
D:\gh\compliance\soc2\
└── evidence\
├── ledger.csv # the index — every artifact, dated, hashed
├── 2027-01\ # one folder per month of the observation window
│ ├── access-review\
│ ├── dead-grants\
│ ├── control-health\
│ └── ...
├── annual\ # pen test, restore test, tabletop, risk assessment
└── vendor\ # subservice org SOC 2 reports, dated
Primary evidence stays in the system that generated it (GitHub Actions history, Supabase logs, the portal API). The folder holds references plus point-in-time exports, so that:
evidence/ledger.csv — one row per artifact:
| Column | Purpose |
|---|---|
date | When the evidence was produced (not when it was filed) |
control_id | Maps to the control matrix |
criteria | TSC criteria satisfied |
artifact | Path or URL |
tier | A / B / C |
source | System that generated it |
sha256 | Integrity hash for exported files |
result | pass / fail / exception |
The ledger is what makes completeness provable. An auditor's real question is not "show me an access review" but "show me every access review for the period." A gapped ledger answers that question badly; a complete one answers it in one file.
The weekly control-health check exists for one reason: to detect a missing artifact within 7 days rather than at fieldwork.
Its logic:
last run.
A gap found in week 1 is a footnote. The same gap found in month 6 is a qualified opinion.
| Evidence type | Retain | Why |
|---|---|---|
| Type II window evidence | 7 years | Report period + typical customer/contract lookback |
| Vendor SOC 2 reports | 7 years | Prove you assessed them at the time |
| Risk assessments, policies (all versions) | 7 years | Demonstrate the control environment evolved |
| Incident records | 7 years | Regulatory and contractual |
| Routine operational logs | 12–13 months minimum | Must exceed the observation window plus fieldwork |
Watch out: GitHub Actions log retention defaults to 90 days. Your observation window is 6 months. Export Actions run summaries monthly or you will lose the first half of your window's evidence before fieldwork begins. This is the single most common self-managed evidence failure and it is entirely avoidable.
Expect ~25 samples per population. Design controls so that any sample is easy to produce.
| Population | Likely sample | You must be able to produce |
|---|---|---|
| Changes deployed to production | 25 PRs across the window | For each: the PR, the approval record, the CI evidence, the deploy record |
| Access grants | All (small population) | Request, approval, date, current status |
| Access removals | All | Trigger, date actioned, elapsed time vs SLA |
| Incidents | All | Detection, classification, response, resolution, post-incident review |
| Backups/restores | The restore tests | Date, scope, result, RPO/RTO measured vs stated |
| Vendor reviews | All | Report obtained, date read, CSOCs mapped, exceptions |
| Nightly control runs | 25 dates | Run log for each date, plus proof of no gaps between |
The change-management sample is where self-managed programs most often fail, because the approval was in a chat. This is exactly why change_approvals persistence is on the critical path.
That last one is worth internalising. A test that cannot fail is not evidence — which is precisely why security-boundaries.yml's own comment ("a test that enforces a hole is worse than no test") is the right instinct, and why every acceptance test in 03-projects/ asks you to break the thing and confirm the check goes red.
This is the part of the program that decides whether you get a clean report. Everything else is a document; this is the machine that keeps the documents true.
Three layers, in order of reliability. Push work down this list wherever possible.
| Layer | Mechanism | Reliability | Use for |
|---|---|---|---|
| 1 | CI / cron in the estate (GitHub Actions, pg_cron) | Highest — runs without a human or an app open | Technical control re-proof, drift, purge, scans |
| 2 | Claude scheduled tasks | High — but only run while the desktop app is open | Judgement work: review, correlation, gap analysis, reporting, drafting |
| 3 | Calendar reminders for the CEO | Lowest | Decisions only. Never for evidence |
Design rule: anything that can be a GitHub Action should be a GitHub Action. Claude scheduled tasks are for the work that needs reading, correlating, and writing — the things CI cannot do.
These are not Claude tasks; they are the technical backbone. Listed here so the full cadence is visible in one place.
| Control | Schedule | Where | Status |
|---|---|---|---|
| Security boundaries re-proof (RLS/entitlement, transaction-rolled-back, against prod) | Nightly | NodeDough ✅ · FedM8 🔴 · CipherDeck Apps 🔴 · Portal 🔴 | Extend to all |
| Schema drift (repo migrations vs live) | Per push + nightly | NodeDough ✅ · all others 🔴 | Extend |
| Data retention purge | Nightly | NodeDough ✅ · all others 🔴 | Extend |
| Secret scanning (gitleaks, full history) | Per push | jbnx.io ✅ · 17 repos 🔴 | Extend to all |
| Dependency scanning (Dependabot / CodeQL) | Continuous | jbnx.io ✅ · all others 🔴 | Extend to all |
| Billing reconciliation (seconds → credits → charged) | Daily | 🔴 | Build (see jbnx-bill.md) |
| Change-approval completeness (merges without an approval row) | Nightly | 🔴 | Build (see projects-portal.md) |
Directive integrity (/json, /md, / agree with repo) | Daily | 🔴 | Build |
| Uptime + alerting on all Tier 1/2 surfaces | Continuous | 🔴 | Buy |
| Actions log export (before 90-day retention expiry) | Monthly | 🔴 | Build — critical, see 06-evidence-model.md §5 |
Six tasks. Deliberately six and not sixteen: a cadence you ignore is worse than no cadence, because it produces evidence gaps with your name on them.
Why: catches a broken control the morning after it breaks, not in month six.
Pulls yesterday's state across the estate: GitHub Actions runs for every in-scope repo (pass/fail/ skipped), Supabase advisor output, Railway deploy and service status, uptime incidents. Appends results to evidence/ledger.csv. Reports only what changed or failed — a green day is one line.
Covers: CC4.1, CC7.1, CC7.2, A1.1.
Why: this is the completeness control from 06-evidence-model.md §4. It is the most important task in the list.
For every control with a defined frequency, computes expected artifacts since the last run, diffs against the ledger, and reports gaps as exceptions with an investigation prompt. Produces a running scorecard: controls implemented / in progress / not started, and the trend.
Covers: CC4.1, CC4.2 — and it is the reason a gap becomes a footnote rather than a finding.
Why: the project files in 03-projects/ are a snapshot of 11 Aug 2026. Systems drift.
Rotates through the ten in-scope systems, roughly one full pass per quarter. Runs the dead-grants query for that project, reviews the week's merged changes for security impact, re-reads the project's plan of attack, and updates status. Raises findings in the AUDIT.md format the estate already uses — stable ID, evidence, impact, fix direction, acceptance test.
Covers: CC4.1, CC6.1, CC7.1, CC3.2.
Why: CC6.2/CC6.3 is a criterion you cannot pass retroactively, and it is pure Tier C evidence unless it is scheduled.
Enumerates every principal with access to GitHub org and repos, Railway projects, Supabase projects, Cloudflare, Stripe, Anthropic/LiteLLM, email, and the bill admin console — including agent seats and service tokens. Flags anything unrecognised, unused for 90 days, or over-privileged. Produces a dated review record requiring CEO confirmation.
Covers: CC6.1, CC6.2, CC6.3, CC1.3.
Why: CC9.2 and CC3.2 both require periodic, evidenced review, and CC1.2 needs a documented CEO oversight event in the absence of a board.
Checks each subservice org's SOC 2 report is current (report date, period covered, gap between periods, exceptions and their relevance to JBNX). Refreshes the risk register against what actually happened that quarter — incidents, near-misses, changes in the estate. Produces the quarterly CEO program review memo.
Covers: CC9.2, CC3.2, CC3.4, CC1.2.
Why: GitHub Actions logs expire at 90 days. Your window is 6 months. Without this, half your evidence is gone before fieldwork.
Exports Actions run summaries for every in-scope repo, portal API handovers and usage, billing reconciliation output, and monitoring history to evidence/YYYY-MM/. Hashes each artifact into the ledger. Verifies the previous month's exports still hash correctly.
Covers: the entire evidence model. Quiet, unglamorous, and the one whose absence is discovered too late.
| When | Decision |
|---|---|
| Phase 0, week 4 | Scope: Path B or Path C · auditor selection · build-vs-buy |
| Quarterly | Sign the program review memo; confirm the access review; re-sign residual SoD risk acceptance |
| Annually | Approve policies, risk assessment; commission pen test; approve the restore test result |
| Before the window opens | Confirm control design freeze |
Daily 07:00 (wkdy) Evidence sweep [Claude #1]
Nightly ~04:00–05:00 Boundaries · retention · drift [CI]
Weekly Mon 08:00 Control health + gap report [Claude #2]
Weekly Fri 15:00 Deep review, 1 project on rotation [Claude #3]
Monthly 1st 09:00 Access review [Claude #4]
Monthly last 18:00 Evidence export + integrity [Claude #6]
Quarterly 1st 09:00 Vendor + risk + CEO program review [Claude #5]
Annually Pen test · restore test · tabletop · policy review
runs at next launch. That is fine for weekly and monthly tasks; for the daily sweep it means an occasional late run, which the weekly health check will catch. Anything where a missed run is genuinely unacceptable belongs in Layer 1.
and health band recorded. Compliance work is billable work and there is no ops exemption.
acceptance test; code changes go through the normal claim → PR → chat-approve path.
and the ledger before the window opens — which is exactly when you want them already working.
One remediation plan per system, each with known findings, applicable criteria, sequenced steps, and an acceptance test per step. Held in D:\gh\compliance\soc2\03-projects\.
| Tier | System | Blocking findings |
|---|---|---|
| 1 | FedM8 | Security model not in version control; processing-integrity failures; veteran PII |
| 1 | JBNX Bill | On the ungated PROD-IT lane; credits unit defect class; no reconciliation control |
| 1 | Projects Portal + Directive | Ungated lane; ungated control-plane API; directive render inconsistency |
| 2 | NodeDough | Two divergent migration lineages; gate not enforced in the Railway service |
| 2 | CipherDeck Apps | RLS and grant posture unverified; gate not enforced |
| 2 | ai.jbnx.io | Prompt/completion data flow undocumented; provider terms unverified |
| 2 | nguy.in | Edge function authorisation; DNS automation uncontrolled; boundary decision open |
| 3 | Supporting services | mockups authed deploy API; cipherdeck webhook dispatcher |
Fourteen policies. Six drafted in full — Information Security, Access Control, Change Management, Data Classification and Handling, AI Agent Operating, and Incident Response. Eight scaffolded for Phase 0 week 3. The AI Agent Operating Policy has no industry template; it is the document an auditor will read most closely.
Prepared by an AI agent under the JBNX work directive. Findings are recorded for remediation; no product code was modified in producing this framework.