# SOC 2 Trust Services Criteria — EdgeCMS control checklist

**Status: control mapping and evidence stubs — not an attestation.**

This document maps the SOC 2 **Common Criteria (CC1–CC9)** series to EdgeCMS product features and operator procedures. It exists so design partners and internal operators can collect evidence toward a future Type I/II examination.

It does **not** claim that EdgeCMS, EdgeCMS Cloud, or any deployment is SOC 2 certified, SOC 2 compliant, or has completed a SOC 2 audit. Until an independent report exists with a date, the website and sales materials must keep the standard tagged **Planned** or **In progress** (SAAS-PRD `SP-07`).

Related product requirements: `CMP-01`–`CMP-18`, `HS-11`, `HS-12`, `OPS-02`.  
For Annex A pairing and draft SoA applicability, see the [SOC 2 ↔ ISO SoA crosswalk](soc2-iso-soa.md) (`CMP-02` stub — not a completed SoA).

## How to read this table

| Column | Meaning |
| --- | --- |
| **CC** | AICPA Trust Services Criteria Common Criteria series |
| **EdgeCMS features** | Runtime or repo capabilities that produce or support evidence |
| **Evidence today** | What you can already export or point an auditor at |
| **Gap** | What still needs process, policy, or product work before examination |

Evidence endpoints below require tenant **owner/admin** (tenant routes) or **super-admin** (global audit routes). Responses are `Cache-Control: no-store`.

## CC series map

| CC | Theme | EdgeCMS features | Evidence today | Gap |
| --- | --- | --- | --- | --- |
| **CC1** | Control environment | Named operator accounts (`SUPER_ADMIN_EMAILS`), signup policy, DPA / acceptable-use legal drafts | Legal stubs under `apps/website/legal/`; auth policy env | Formal board/management oversight, yearly policy set (`CMP-01`), staff agreements (`CMP-17`) |
| **CC2** | Communication & information | Public docs, trust-oriented website ledger (standards listed as Planned), audit export for security events | `docs/public/*`, website standards ledger | Customer-facing trust page with dated status (`CMP-18`); internal comms of control changes |
| **CC3** | Risk assessment | Product risk notes in PRD / handoff; ABAC attribute denials logged | PRD §4.8; `abac.denied` audit events | Living risk register + SoA reviewed quarterly (`CMP-02`) |
| **CC4** | Monitoring | Hash-chained audit ledger, optional SIEM webhook/batch sink, health routes | `GET .../audit/export`, `.../verify`, `.../completeness`; `AUDIT_SIEM_*` | Continuous monitoring runbooks, alerting SLAs, management review of findings |
| **CC5** | Control activities | RBAC + ABAC, MFA flags, CSRF, rate limits, security headers | Auth/access guide; MFA env (`HS-11`) | Documented control matrix owned by ops; exception handling |
| **CC6** | Logical access | Tenant membership roles, RBAC permissions, MFA, invites, session model | **Access-review stub:** `GET /api/tenants/:slug/api/admin/compliance/access-review` (membership snapshot + role summary; records `compliance.access_review_exported`) | Quarterly acknowledgement workflow, joiner/mover/leaver tickets, 1-day offboarding SLA proof (`CMP-04`) |
| **CC7** | System operations | Health endpoints, retention pruning with in-chain record, backups via Cloudflare Time Travel (ops docs) | Audit retention ≥ 365 days; ops/security guide | Stated RPO/RTO, quarterly restore drills, incident runbook with 72h breach path (`CMP-09`, `CMP-10`) |
| **CC8** | Change management | Reviewed PRs, CI, tagged production deploys (`OPS-02`), Keep a Changelog | **Product changelog:** root `CHANGELOG.md`. **Content change evidence:** `GET .../compliance/change-log` (redacted `change_log` pages; records `compliance.change_log_exported`) | Emergency-change log + after-action review; link deploy tags to tickets consistently (`CMP-06`) |
| **CC9** | Risk mitigation | Vendor list drafts, Cloudflare-only year-one posture, Stripe SAQ A intent | Subprocessor / DPA drafts; no card data in app | Yearly vendor security reviews on file (`CMP-14`); pen-test cadence (`CMP-08`) |

## Evidence endpoints (shipped this slice)

### Audit export completeness (CC4 / CC7 / CMP-05)

```text
GET /api/tenants/:slug/api/admin/audit/export
GET /api/tenants/:slug/api/admin/audit/completeness
GET /api/admin/audit/export
GET /api/admin/audit/completeness
```

- JSON export pages include `completeness`: `pageEventCount`, `firstSeq`, `lastSeq`, `contiguous`, `reachesHead`.
- NDJSON export mirrors page flags in `x-edgecms-audit-page-count`, `x-edgecms-audit-contiguous`, `x-edgecms-audit-reaches-head` (plus existing cursor/head headers).
- `/completeness` returns `eventCount`, `head`, chain `verification`, and `exportComplete` when the stored chain verifies and matches the exportable head/count.

Typical collector loop: page `/export` until `nextCursor` is null and `completeness.reachesHead` is true, then call `/completeness` and archive `head.hash` outside D1.

### Access review stub (CC6 / CMP-04)

```text
GET /api/tenants/:slug/api/admin/compliance/access-review
```

Returns `{ status: "stub", note, members[], roleSummary, generatedAt, ... }`. Explicitly a **snapshot for human quarterly review**, not an attestation UI. Acknowledgement / ticketing is not shipped.

### Change log evidence (CC8 / CMP-06)

```text
GET /api/tenants/:slug/api/admin/compliance/change-log?after=<seq>&limit=<n>&since=<iso>
GET /api/admin/compliance/change-log   # global (unscoped) stream; super-admin
```

Pages redacted content `change_log` rows for runtime change evidence. Application change management still relies on PRs, CI, tagged deploys, and `CHANGELOG.md` — this endpoint does not replace them.

## What not to say

- Do not write “SOC 2 certified”, “SOC 2 compliant”, “we passed SOC 2”, or equivalent on the website, in pilots kits, or questionnaires.
- Prefer: “We maintain a SOC 2 CC control checklist and produce exportable evidence; examination is planned.”
- Website build tests already fail on certification language (`SP-07`).

## Maintenance

- Re-check this map on each major release alongside ASVS / ISO evidence work.
- When an independent SOC 2 report exists, update the website standards ledger with the report date — never before.
