{
  "standard": "Firm-Safe Standard",
  "version": "1.0",
  "published": "2026-10-26",
  "licence": "CC BY 4.0",
  "attribution": "Firm-Safe Standard v1.0, published 26 October 2026, firmsafe.io/standard, CC BY 4.0",
  "levels": {
    "blocking": 10,
    "scored": 20
  },
  "areas": [
    {
      "id": "A",
      "name": "Client separation",
      "guarantee": "One client's data never reaches another client"
    },
    {
      "id": "B",
      "name": "Ledger protection",
      "guarantee": "Nothing reaches the ledger without a person, once"
    },
    {
      "id": "C",
      "name": "Secrets and access",
      "guarantee": "Keys and access stay inside the firm"
    },
    {
      "id": "D",
      "name": "Audit trail",
      "guarantee": "Any figure can be traced to its source"
    },
    {
      "id": "E",
      "name": "Continuity",
      "guarantee": "A second person can run it, and it can be stopped"
    },
    {
      "id": "F",
      "name": "Handoffs",
      "guarantee": "Client data survives the move between two systems"
    }
  ],
  "checks": [
    {
      "id": "A1",
      "area": "A",
      "level": "blocking",
      "text": "Every request is tied to one client; nothing runs without a client ID",
      "evidence": "Code search, plus a test where a call without a client ID fails",
      "automatable": false
    },
    {
      "id": "A2",
      "area": "A",
      "level": "blocking",
      "text": "With two demo clients loaded, client 1's output contains no client 2 records",
      "evidence": "Manual run against the public two-client demo dataset, logged, with the output attached",
      "automatable": true
    },
    {
      "id": "A3",
      "area": "A",
      "level": "blocking",
      "text": "Stored files and caches are separated per client",
      "evidence": "A query of the storage layer showing a per-client prefix per client, plus the paths",
      "automatable": false
    },
    {
      "id": "A4",
      "area": "A",
      "level": "blocking",
      "text": "AI prompts contain only the current client's data",
      "evidence": "Sample of the prompt log",
      "automatable": false
    },
    {
      "id": "A5",
      "area": "A",
      "level": "blocking",
      "text": "Staff see only the clients assigned to them",
      "evidence": "Role settings, plus a test",
      "automatable": false
    },
    {
      "id": "B1",
      "area": "B",
      "level": "blocking",
      "text": "Nothing posts to the ledger until a named person approves it",
      "evidence": "The log line showing the approver identity and timestamp, plus the approval step's code path",
      "automatable": false
    },
    {
      "id": "B2",
      "area": "B",
      "level": "blocking",
      "text": "Writes land as drafts by default",
      "evidence": "One sample run showing the draft state, plus the code path that sets it",
      "automatable": false
    },
    {
      "id": "B3",
      "area": "B",
      "level": "scored",
      "text": "Running the tool twice does not post twice",
      "evidence": "Two consecutive manual runs on the demo client, both logged, the second showing no duplicate post",
      "automatable": true
    },
    {
      "id": "B4",
      "area": "B",
      "level": "scored",
      "text": "Every posted entry can be reversed and traced to the run that created it",
      "evidence": "Reversal demo, plus the log ID",
      "automatable": false
    },
    {
      "id": "B5",
      "area": "B",
      "level": "scored",
      "text": "Amounts and accounts are validated against the chart of accounts before posting",
      "evidence": "Test with a bad account code",
      "automatable": false
    },
    {
      "id": "C1",
      "area": "C",
      "level": "blocking",
      "text": "No passwords or API keys in prompts, code, or shared documents",
      "evidence": "Secret-scan output",
      "automatable": true
    },
    {
      "id": "C2",
      "area": "C",
      "level": "scored",
      "text": "Keys live in a secrets store and are rotated when staff leave",
      "evidence": "Settings, plus a rotation record",
      "automatable": false
    },
    {
      "id": "C3",
      "area": "C",
      "level": "scored",
      "text": "Each connection has the narrowest access it needs (read-only unless it must write)",
      "evidence": "The token's scopes as returned by the provider, plus the code path that requests them",
      "automatable": false
    },
    {
      "id": "C4",
      "area": "C",
      "level": "blocking",
      "text": "Sign-in required; no public link can reach client data",
      "evidence": "Access test from a logged-out browser",
      "automatable": false
    },
    {
      "id": "C5",
      "area": "C",
      "level": "scored",
      "text": "Client data goes only to AI providers whose terms exclude training on it",
      "evidence": "Provider terms on file, with a \"terms read on\" date and a review interval",
      "automatable": false
    },
    {
      "id": "D1",
      "area": "D",
      "level": "scored",
      "text": "Each run logs who, when, which client, the inputs and the outputs",
      "evidence": "Sample log entry",
      "automatable": true
    },
    {
      "id": "D2",
      "area": "D",
      "level": "scored",
      "text": "AI outputs are stored next to the source data they used",
      "evidence": "Sample record",
      "automatable": false
    },
    {
      "id": "D3",
      "area": "D",
      "level": "scored",
      "text": "Logs are kept for a set period and tool users cannot edit them",
      "evidence": "The retention configuration, plus a permission test showing the result of an editing attempt",
      "automatable": false
    },
    {
      "id": "D4",
      "area": "D",
      "level": "scored",
      "text": "Errors are logged and alert a named person",
      "evidence": "Forced-error test",
      "automatable": false
    },
    {
      "id": "D5",
      "area": "D",
      "level": "scored",
      "text": "Any figure can be traced to its source in under five minutes.",
      "evidence": "Timed walkthrough recording",
      "automatable": false
    },
    {
      "id": "E1",
      "area": "E",
      "level": "scored",
      "text": "A one-page handover: purpose, data used, owner, how to run it, how to stop it",
      "evidence": "The document",
      "automatable": false
    },
    {
      "id": "E2",
      "area": "E",
      "level": "scored",
      "text": "A second named person has run it end to end from the handover alone",
      "evidence": "Their run log",
      "automatable": false
    },
    {
      "id": "E3",
      "area": "E",
      "level": "scored",
      "text": "Code and settings are in version control with change history",
      "evidence": "Repository link",
      "automatable": false
    },
    {
      "id": "E4",
      "area": "E",
      "level": "scored",
      "text": "Automated tests on demo data pass before every change",
      "evidence": "Test-run history",
      "automatable": true
    },
    {
      "id": "E5",
      "area": "E",
      "level": "scored",
      "text": "One step turns the tool off, and the manual fallback is written down",
      "evidence": "Shutdown demo, plus the fallback page",
      "automatable": false
    },
    {
      "id": "F1",
      "area": "F",
      "level": "blocking",
      "text": "Every client has one canonical key, and every system in the path maps to it; the same client created in two systems resolves to one record",
      "evidence": "The mapping table, plus a test showing a client created in system A is matched, not duplicated, in system B",
      "automatable": false
    },
    {
      "id": "F2",
      "area": "F",
      "level": "scored",
      "text": "A write that lands in one system and fails in the other is visible and reversible",
      "evidence": "Forced-failure test, plus the log showing the partial state and the reversal",
      "automatable": false
    },
    {
      "id": "F3",
      "area": "F",
      "level": "scored",
      "text": "The two sides of the path reconcile for a period, with every exception named",
      "evidence": "A reconciliation query, plus the exception register it produces",
      "automatable": true
    },
    {
      "id": "F4",
      "area": "F",
      "level": "scored",
      "text": "Every synced figure carries the time it was pulled, and an out-of-date copy is visible to the person using it",
      "evidence": "The stored pull timestamp, plus the view that shows staleness",
      "automatable": true
    },
    {
      "id": "F5",
      "area": "F",
      "level": "scored",
      "text": "Where a person re-keys data between two systems, it is a logged approval point with a name, never an unlogged step",
      "evidence": "The log line with the person and timestamp, plus the code path that requires it",
      "automatable": false
    }
  ]
}
