# ISO/IEC 27001:2022 Annex A — engineering evidence

EdgeCMS maps a focused Annex A subset to **code, tests, CI and host hooks** so a host can collect security evidence. This document is **not** a Statement of Applicability, **not** an ISMS, and **not** an ISO 27001 certification claim (see `SAAS-PRD.md` SP-07 / D7). For SOC 2 Common Criteria pairing and a draft SoA applicability matrix, see the [SOC 2 ↔ ISO SoA crosswalk](soc2-iso-soa.md) (`CMP-02` stub).

Status vocabulary used here and in `apps/api/src/compliance/iso27001/`:

| Status | Meaning |
| --- | --- |
| `engineered` | Repeatable product evidence exists (code + tests and/or operator docs). |
| `partial` | Some evidence exists; gaps are listed. |
| `planned` | Not implemented in this repo yet. |
| `out_of_scope` | Host / ISMS owns it. |

Never treat `engineered` as “certified” or “compliant”.

## How to export evidence

```bash
bun scripts/iso27001-evidence.ts           # verify cited paths exist
bun scripts/iso27001-evidence.ts --json    # print the evidence bundle
```

Programmatic export from a host Worker:

```ts
import {
  buildIso27001EvidenceBundle,
  buildAssetInventoryStub,
  buildSupplierDependencyNote,
  type ChangeControlSink,
} from 'edgecms-api/app'

const evidence = buildIso27001EvidenceBundle({
  configuredEnvKeys: Object.keys(env), // names only; values never inventoried
})

const changeControlSink: ChangeControlSink = {
  record: (event) => evidenceQueue.send({ body: event }),
}

export const app = createApp({ host: { changeControlSink } })
```

`claim` in the JSON bundle is always `engineering_evidence_only`.

## Themes

### Access control (A.5.15–A.5.18, A.8.2, A.8.3, A.8.5)

RBAC, default-deny ABAC, tenant isolation, signup policy, and MFA gates. Operator guide: [Authentication And Access](auth-and-access.md). Related PRD / SaaS ids: `HS-01`, `HS-11`, `PL-03`, `CMP-03`, `CMP-04`.

### Logging and monitoring (A.8.15, A.8.16)

Hash-chained `audit_events` ledger, export/verify routes, optional `host.auditSink` / SIEM webhook. Operator guide: [Operations and security](operations-security.md). Related: `HS-12`, `CMP-05`.

### Change and configuration management (A.8.9, A.8.32)

- Infra/config as code: `apps/api/wrangler.toml`, composition-time `createApp({ host })` (never request-mutable).
- Code change evidence: PR + CI (`.github/workflows/ci.yml`) and deploy workflows.
- Optional `host.changeControlSink` records structured change events (including a boot `host_policies_applied` event when the sink is set). Related: `CMP-06`.

### Asset inventory stub (A.5.9)

`buildAssetInventoryStub()` lists known Worker asset classes (D1, KV, R2, queues, secrets by **name**, lockfile, source repo). `completeness` is always `stub`. Hosts must keep the authoritative CMDB.

### Supplier and dependencies note (A.5.19, A.5.21, A.5.23)

`buildSupplierDependencyNote()` names Cloudflare, optional IdPs/AI/payments, host email, and the open-source lockfile (`bun.lock`). It is **not** a completed vendor review or subprocessor DPA pack. Related: `CMP-12`, `CMP-14`. SBOM/SLSA gates are a separate track.

## Control table (engineering map)

| Control | Title | Status | Primary evidence |
| --- | --- | --- | --- |
| A.5.15 | Access control | engineered | `auth/rbac.service.ts`, `auth/abac.ts`, `auth-and-access.md` |
| A.5.16 | Identity management | partial | `auth/auth.ts`, invites |
| A.5.17 | Authentication information | partial | `auth/mfa.ts`, auth policies |
| A.5.18 | Access rights | engineered | RBAC + authorization/ABAC tests |
| A.8.2 | Privileged access rights | engineered | Super-admin MFA + tests |
| A.8.3 | Information access restriction | engineered | Tenant middleware, ABAC, isolation tests |
| A.8.5 | Secure authentication | partial | Sessions/JWT; social IdP MFA not counted |
| A.8.15 | Logging | engineered | Audit ledger + operations-security.md |
| A.8.16 | Monitoring activities | partial | `auditSink` / SIEM helpers, metrics |
| A.8.9 | Configuration management | partial | wrangler.toml, host policies, changeControlSink |
| A.8.32 | Change management | partial | CI/deploy workflows, changeControlSink |
| A.5.9 | Inventory of assets | partial | Asset inventory stub |
| A.5.19 | Supplier relationships | partial | Supplier/deps note |
| A.5.21 | ICT supply chain | partial | Lockfile pointer + this doc |
| A.5.23 | Cloud services | partial | Cloudflare bindings + hosting seams |

Full pointer list and gaps: `apps/api/src/compliance/iso27001/controls.ts`.

## Explicit non-claims

- No ISO 27001 certificate, surveillance audit, or accredited certification body engagement is asserted here.
- No completed Statement of Applicability (SoA) or risk register is shipped; only a [SOC 2 ↔ ISO crosswalk stub](soc2-iso-soa.md). Living SoA + risk register remain host ISMS documents (`CMP-01`, `CMP-02`).
- No production backup, penetration-test, or remote performance proof is claimed by this map.
- Staff security training, background checks, and physical controls are out of product scope (`CMP-17`).

## Related guides

- [Auth and access](auth-and-access.md)
- [Operations and security](operations-security.md)
- [Hosting seams](hosting-seams.md)
- SaaS compliance track: `SAAS-PRD.md` §4.8
