aeat.application.operator_surface._risk_table module¶
Declared per-command risk classification, keyed by full command key.
The MCP console’s tool annotations and its human-in-the-loop confirmation tier need each command’s risk posture: is it destructive, a filing handoff, or a (never-exposed) AEAT live-write? The accepted mcp-protocol-hardening H3 ruled this “becomes declared data keyed by command key … with a parity gate asserting every mutating verb carries an explicit classification”. The first implementation shipped hand-listed leaf-NAME frozensets instead, matching on the command key’s trailing word - so a new mutating verb named purge/wipe/finalize fell through every set, classified non-destructive, and auto-approved (the safety finding of the 2026-07-08 MCP console review).
This module is that declared table. Every command in a LOCAL_STATE_MUTATING family carries EXACTLY ONE row; a row with no flags is the explicit declaration “this command mutates local state but is not destructive, not a handoff, and not a live-write” - not a silent default. The no-silent-default parity gate (test_risk_table_parity.py) fails the build when a mutating-family command has no row, so a new verb cannot slip through unclassified. Read-only families derive their classification from the manifest mutability and need no rows here; idempotent is derived (read-only) and open_world is derived from the app.live./pull facts - only the three genuinely-judgment axes are declared.
The two rows the frozensets got wrong, corrected in the human-review pass: quickfile runs the readiness->calculate->verify->file chain and so produces a filing-grade artefact (handoff), and config.profile.sandbox.prune irreversibly removes sandboxes (destructive).
- class CommandRiskDeclaration(**data)[source]¶
Bases:
BaseModelThe declared risk flags for one mutating command.
All three default False: a bare declaration states “mutating but safe”. The axes are the genuinely-judgment ones - destructive (irreversibly destroys or overwrites local state), handoff (produces a filing-grade artefact a human files outside the app), live_write (would write to AEAT; never exposed, but declared so the permanent block is data, not a leaf-string heuristic).
- destructive: bool¶
- handoff: bool¶
- live_write: bool¶
- COMMAND_RISK: dict[str, CommandRiskDeclaration]¶
The declared risk table. One row per LOCAL_STATE_MUTATING-family command, keyed by full command key. Read-only families are absent (derived).
- declared_risk(command_key)[source]¶
Return the declared risk row for command_key, or None when absent.
Absent means the command’s family is read-only (classification is derived) OR - the case the parity gate exists to catch - a mutating command was added without a declaration. classify_command treats an absent row for a mutating command as all-false at runtime; the gate makes that state a build failure.
- Return type:
- Parameters:
command_key (str)