""" Evidence pack: one printable page an auditor can read, built from the gateway's own records. squidbrake evidence --days 90 --out evidence.html (or the dashboard's Reports tab) It says what controls were in place (rules, who may approve, second-person approval, emergency stop), what happened (actions checked, blocked, held, approved and by whom), whether the audit trail is intact, and which common audit requirements each of those speaks to. The mapping is a starting point for the conversation with an auditor, not a certification: the auditor decides what satisfies a control. server.py gathers the numbers (build_evidence); this file only turns them into the page. """ from __future__ import annotations from html import escape def _n(count: int, word: str) -> str: return f"{count} {word}{'' if count == 1 else 's'}" def _pct(part: int, whole: int) -> str: return f"{round(100 * part / whole)}%" if whole else "n/a" def mapping(ev: dict) -> list[dict]: """Which requirement each recorded control speaks to, with this period's numbers filled in.""" a, sp, p, t = ev["approvals"], ev["second_person"], ev["policy"], ev["team"] stops = ev["changes"]["stops"] chain = "intact" if ev["audit"]["ok"] else "BROKEN" keys = (f"{_n(t['people'], 'person') if t['people'] == 1 else str(t['people']) + ' people'} ({t['approvers']} can approve, " f"{_n(t['admins'], 'admin')}) and {_n(t['agents'], 'agent key')}, " f"{t['agents_with_owner']} of them tied to the person they work for") oversight = (f"{a['held']} actions held for a person; {a['approved']} approved, {a['rejected']} rejected, " f"{a['timed_out']} timed out. {_pct(sp['by_someone_else'], sp['by_someone_else'] + sp['by_owner'])} of decisions on agents " f"with a known owner were made by someone other than that owner (second-person approval is {'on' if sp['enforced'] else 'off'}).") logging = (f"{ev['total']} agent actions recorded in a hash-chained trail ({ev['audit']['entries']} entries, " f"chain {chain}); each decision carries the fingerprint of the rules that made it.") rules = (f"{p['rules']} rules ({p['by_action'].get('deny', 0)} block, {p['by_action'].get('review', 0)} hold for a person, " f"{p['by_action'].get('allow', 0)} allow), {p['sequences']} sequence rules, default '{p['default']}', " f"mode '{p['mode']}'. {p['versions_in_period']} rules versions were in force during the period.") stop = f"Emergency stop available for all agents, one agent or one conversation; used {stops} times in the period." retention = (f"Records kept {'forever' if not ev['retention_days'] else str(ev['retention_days']) + ' days'}.") k = ev.get("controls") or {} signed = (f" {k.get('checkpoints', 0)} signed checkpoints (Ed25519, one per 50 entries) let anyone verify an export " f"against the published ledger key." if k else "") devices = (f" {k.get('device_signed', 0)} decisions were signed by a registered device (passkey: Face ID or " f"fingerprint){'; device signatures are required for approvals' if k.get('device_required') else ''}." if k else "") undo = (f" Before held or irreversible actions run, a copy of what they change is kept ({k.get('snapshots_kept', 0)} " f"kept, {k.get('snapshots_skipped', 0)} could not be made" f"{', and those actions were blocked' if k.get('snapshots') == 'required' else ''})." if k else "") proof = (f" Completed actions were checked in the real system: {k['proofs']['confirmed']} confirmed, " f"{k['proofs']['mismatch']} not actually done." if k.get("proof_checks") else "") rows = [ {"framework": "SOC 2 (2017 TSC)", "ref": "CC6.1, CC6.3", "requirement": "Logical access; access granted by role", "evidence": keys + ". Rules can name who may approve (a person or a role)."}, {"framework": "SOC 2 (2017 TSC)", "ref": "CC7.2", "requirement": "Monitor system components for anomalies", "evidence": logging + f" {ev['by_status'].get('denied', 0)} actions were blocked."}, {"framework": "SOC 2 (2017 TSC)", "ref": "CC8.1", "requirement": "Changes are authorized before they are made", "evidence": oversight}, {"framework": "ISO/IEC 42001", "ref": "Annex A, AI system operation and monitoring; event logs", "requirement": "Monitor AI system operation and keep event logs", "evidence": logging + " " + retention}, {"framework": "EU AI Act", "ref": "Art. 12", "requirement": "Automatic recording of events (logs)", "evidence": logging + " " + retention}, {"framework": "EU AI Act", "ref": "Art. 14", "requirement": "Human oversight, including the ability to intervene and stop", "evidence": oversight + " " + stop}, {"framework": "EU AI Act", "ref": "Art. 26(6)", "requirement": "Deployers keep logs for at least six months", "evidence": retention}, {"framework": "CERT-In AI security blueprint (2026)", "ref": "Agentic AI controls", "requirement": "Operational boundaries, continuous monitoring, audit logging, emergency shutdown", "evidence": rules + " " + logging + " " + stop}, {"framework": "RBI FREE-AI (2025, guidance)", "ref": "Audit and oversight recommendations", "requirement": "Audit trails and human oversight of AI decisions", "evidence": logging + " " + oversight}, ] if k: rows += [ {"framework": "SOC 2 (2017 TSC)", "ref": "CC7.4, CC7.5", "requirement": "Respond to and recover from incidents", "evidence": (stop + undo + proof).strip()}, {"framework": "SOC 2 (2017 TSC)", "ref": "CC6.7, C1.1", "requirement": "Protect confidential information", "evidence": f"Stored action details: {k.get('redaction')}; long values are cut to a preview where shown."}, {"framework": "ISO/IEC 42001", "ref": "Annex A, AI system records and responsible use", "requirement": "Records are protected from tampering and decisions are attributable", "evidence": (logging + signed + devices).strip()}, {"framework": "EU AI Act", "ref": "Art. 14(4)", "requirement": "Overseers can decide not to use, override or " "reverse the output, and interrupt the system", "evidence": (oversight + " " + stop + undo).strip()}, {"framework": "EU AI Act", "ref": "Art. 15", "requirement": "Accuracy, robustness, resilience to faults", "evidence": f"When Squidbrake is unreachable, actions are {'blocked' if k.get('when_unreachable') == 'block' else 'allowed'} " f"by default; {k.get('allow_while_unreachable', 0)} rule(s) explicitly allow their actions while it's " f"down.{proof}"}, ] return rows def _table(head: list[str], rows: list[list], empty: str = "None in this period.") -> str: if not rows: return f"
{escape(empty)}
" th = "".join(f"The audit trail is {'intact' if ok else 'BROKEN'}:
{ev['audit']['entries']} entries, each hash covering the one before, so an edited or deleted entry breaks every hash after it.
Head hash {escape(str(ev['audit']['head_hash']))}.
To check independently: download the full evidence file (dashboard → Reports → Evidence, or
GET /v1/audit/export.json) and run python verify.py FILE from the open-source Squidbrake repository.
It needs no access to this system.
{a['held']} actions were held for a person. {a['approved']} approved, {a['rejected']} rejected, {a['timed_out']} timed out (timeouts follow each rule's setting). Of {sp['decided']} decisions by a person, {sp['by_someone_else']} were made by someone other than the agent's owner, {sp['by_owner']} by the owner, and {sp['owner_unknown']} for agents with no owner set.
{_table(["Approver", "Approved", "Rejected"], [[x["approver"], x["approved"], x["rejected"]] for x in a["by_approver"]])}A starting point for your auditor, not a certification. Control references are given as commonly cited; your auditor decides what satisfies each one.
{_table(["Framework", "Reference", "Requirement", "Evidence from this period"], [[r["framework"], r["ref"], r["requirement"], r["evidence"]] for r in m])} """