Source code for aeat.application.operator_surface._risk_table

"""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).
"""

from __future__ import annotations

from pydantic import BaseModel, ConfigDict

_STRICT_FROZEN = ConfigDict(frozen=True, strict=True, validate_assignment=True, extra="forbid")


[docs] class CommandRiskDeclaration(BaseModel): """The 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). """ model_config = _STRICT_FROZEN destructive: bool = False handoff: bool = False live_write: bool = False
#: The declared risk table. One row per LOCAL_STATE_MUTATING-family command, #: keyed by full command key. Read-only families are absent (derived). COMMAND_RISK: dict[str, CommandRiskDeclaration] = { "agent": CommandRiskDeclaration(), "app.live.borrador.100.latest": CommandRiskDeclaration(), "app.live.borrador.100.list": CommandRiskDeclaration(), "app.live.borrador.100.view": CommandRiskDeclaration(), "app.live.expedientes.latest": CommandRiskDeclaration(), "app.live.expedientes.list": CommandRiskDeclaration(), "app.live.expedientes.pull": CommandRiskDeclaration(), "app.live.expedientes.view": CommandRiskDeclaration(), "app.live.filed.list": CommandRiskDeclaration(), "app.live.filed.pull": CommandRiskDeclaration(), "app.live.filed.pull_sources": CommandRiskDeclaration(), "app.live.iva_wallet.history": CommandRiskDeclaration(), "app.live.iva_wallet.pull": CommandRiskDeclaration(), "app.live.iva_wallet.pull_evidence": CommandRiskDeclaration(), "app.live.iva_wallet.pull_history": CommandRiskDeclaration(), "app.live.justificante.list": CommandRiskDeclaration(), "app.live.justificante.pull": CommandRiskDeclaration(), "app.live.justificante.view": CommandRiskDeclaration(), "app.live.notifications.latest": CommandRiskDeclaration(), "app.live.notifications.list": CommandRiskDeclaration(), "app.live.notifications.pull": CommandRiskDeclaration(), "app.live.notifications.view": CommandRiskDeclaration(), "app.live.portals.list": CommandRiskDeclaration(), "app.live.portals.view": CommandRiskDeclaration(), "app.live.verify.latest": CommandRiskDeclaration(), "app.live.verify.list": CommandRiskDeclaration(), "app.live.verify.nif_iva": CommandRiskDeclaration(), "app.live.verify.tgvi": CommandRiskDeclaration(), "app.live.verify.view": CommandRiskDeclaration(), "config.auth.apoderado.check": CommandRiskDeclaration(), "config.auth.apoderado.clear": CommandRiskDeclaration(destructive=True), "config.auth.apoderado.configure": CommandRiskDeclaration(), "config.auth.apoderado.scopes.list": CommandRiskDeclaration(), "config.auth.apoderado.status": CommandRiskDeclaration(), "config.auth.certificate.check": CommandRiskDeclaration(), "config.auth.certificate.list": CommandRiskDeclaration(), "config.auth.certificate.register": CommandRiskDeclaration(), "config.auth.certificate.remove": CommandRiskDeclaration(destructive=True), "config.auth.certificate.secret.remove": CommandRiskDeclaration(destructive=True), "config.auth.certificate.secret.set": CommandRiskDeclaration(), "config.auth.certificate.select": CommandRiskDeclaration(), "config.auth.clear": CommandRiskDeclaration(destructive=True), "config.auth.configure": CommandRiskDeclaration(), "config.auth.diagnostics.list": CommandRiskDeclaration(), "config.auth.diagnostics.report": CommandRiskDeclaration(), "config.auth.diagnostics.show": CommandRiskDeclaration(), "config.auth.login": CommandRiskDeclaration(), "config.auth.providers": CommandRiskDeclaration(), "config.auth.status": CommandRiskDeclaration(), "config.auth.test": CommandRiskDeclaration(), "config.bucket.history": CommandRiskDeclaration(), "config.collab.recipient.add": CommandRiskDeclaration(), "config.collab.recipient.list": CommandRiskDeclaration(), "config.collab.recipient.remove": CommandRiskDeclaration(destructive=True), "config.google.credential_source.set": CommandRiskDeclaration(), "config.google.credential_source.show": CommandRiskDeclaration(), "config.google.folder.get": CommandRiskDeclaration(), "config.google.folder.set": CommandRiskDeclaration(), "config.google.login": CommandRiskDeclaration(), "config.google.logout": CommandRiskDeclaration(destructive=True), "config.google.register": CommandRiskDeclaration(), "config.google.status": CommandRiskDeclaration(), "config.google.sync.calc.compute": CommandRiskDeclaration(), "config.google.sync.calc.export": CommandRiskDeclaration(handoff=True), "config.google.sync.calc.pull": CommandRiskDeclaration(), "config.google.sync.calc.verify": CommandRiskDeclaration(), "config.google.sync.probe": CommandRiskDeclaration(), "config.google.sync.push": CommandRiskDeclaration(), "config.lock": CommandRiskDeclaration(), "config.profile.archive.export": CommandRiskDeclaration(handoff=True), "config.profile.archive.import": CommandRiskDeclaration(), "config.profile.archive.inspect": CommandRiskDeclaration(), "config.profile.capabilities.set": CommandRiskDeclaration(), "config.profile.capabilities.show": CommandRiskDeclaration(), "config.profile.censo.apply": CommandRiskDeclaration(), "config.profile.censo.compare": CommandRiskDeclaration(), "config.profile.censo.pull": CommandRiskDeclaration(), "config.profile.censo.show": CommandRiskDeclaration(), "config.profile.create": CommandRiskDeclaration(), "config.profile.delete": CommandRiskDeclaration(destructive=True), "config.profile.descendiente.add": CommandRiskDeclaration(), "config.profile.descendiente.list": CommandRiskDeclaration(), "config.profile.descendiente.remove": CommandRiskDeclaration(destructive=True), "config.profile.duplicate": CommandRiskDeclaration(), "config.profile.edit": CommandRiskDeclaration(), "config.profile.export": CommandRiskDeclaration(handoff=True), "config.profile.import": CommandRiskDeclaration(), "config.profile.list": CommandRiskDeclaration(), "config.profile.logout": CommandRiskDeclaration(destructive=True), "config.profile.preflight": CommandRiskDeclaration(), "config.profile.rename": CommandRiskDeclaration(), "config.profile.sandbox.archive": CommandRiskDeclaration(), "config.profile.sandbox.create": CommandRiskDeclaration(), "config.profile.sandbox.discard": CommandRiskDeclaration(destructive=True), "config.profile.sandbox.list": CommandRiskDeclaration(), "config.profile.sandbox.merge": CommandRiskDeclaration(destructive=True), "config.profile.sandbox.prune": CommandRiskDeclaration(destructive=True), "config.profile.sandbox.restore": CommandRiskDeclaration(), "config.profile.sandbox.usage": CommandRiskDeclaration(), "config.profile.sandbox.use": CommandRiskDeclaration(), "config.profile.show": CommandRiskDeclaration(), "config.profile.status": CommandRiskDeclaration(), "config.profile.subject_access_request": CommandRiskDeclaration(), "config.profile.validate": CommandRiskDeclaration(), "config.recover": CommandRiskDeclaration(destructive=True), "config.rekey": CommandRiskDeclaration(destructive=True), "config.repair.connectivity": CommandRiskDeclaration(), "config.repair.integrity.objects": CommandRiskDeclaration(), "config.repair.integrity.registry": CommandRiskDeclaration(), "config.repair.logs": CommandRiskDeclaration(), "config.repair.profile": CommandRiskDeclaration(), "config.repair.quarantine": CommandRiskDeclaration(), "config.repair.reset_progress": CommandRiskDeclaration(), "config.reset": CommandRiskDeclaration(destructive=True), "config.show_recovery": CommandRiskDeclaration(), "config.switch": CommandRiskDeclaration(), "config.verify_recovery": CommandRiskDeclaration(), "ledger.add": CommandRiskDeclaration(), "ledger.allocate": CommandRiskDeclaration(), "ledger.archive": CommandRiskDeclaration(), "ledger.attach": CommandRiskDeclaration(), "ledger.bienes_inversion.declare": CommandRiskDeclaration(), "ledger.bienes_inversion.list": CommandRiskDeclaration(), "ledger.categories": CommandRiskDeclaration(), "ledger.check": CommandRiskDeclaration(), "ledger.classify": CommandRiskDeclaration(), "ledger.doclink": CommandRiskDeclaration(), "ledger.evidence.add": CommandRiskDeclaration(), "ledger.evidence.confirm": CommandRiskDeclaration(), "ledger.evidence.extract": CommandRiskDeclaration(), "ledger.evidence.list": CommandRiskDeclaration(), "ledger.evidence.remove": CommandRiskDeclaration(destructive=True), "ledger.evidence.update": CommandRiskDeclaration(), "ledger.evidence.view": CommandRiskDeclaration(), "ledger.exclude": CommandRiskDeclaration(), "ledger.export": CommandRiskDeclaration(handoff=True), "ledger.history": CommandRiskDeclaration(), "ledger.import": CommandRiskDeclaration(), "ledger.inventory.create": CommandRiskDeclaration(), "ledger.inventory.list": CommandRiskDeclaration(), "ledger.inventory.movement.add": CommandRiskDeclaration(), "ledger.inventory.valuation.preview": CommandRiskDeclaration(), "ledger.invoice.add": CommandRiskDeclaration(), "ledger.invoice.catalogue.create": CommandRiskDeclaration(), "ledger.invoice.catalogue.import": CommandRiskDeclaration(), "ledger.invoice.catalogue.list": CommandRiskDeclaration(), "ledger.invoice.catalogue.remove": CommandRiskDeclaration(destructive=True), "ledger.invoice.catalogue.view": CommandRiskDeclaration(), "ledger.invoice.catalogue.wizard": CommandRiskDeclaration(), "ledger.invoice.list": CommandRiskDeclaration(), "ledger.invoice.remove": CommandRiskDeclaration(destructive=True), "ledger.invoice.update": CommandRiskDeclaration(), "ledger.invoice.view": CommandRiskDeclaration(), "ledger.link": CommandRiskDeclaration(), "ledger.list": CommandRiskDeclaration(), "ledger.llm_diagnostics": CommandRiskDeclaration(), "ledger.merge": CommandRiskDeclaration(destructive=True), "ledger.participation": CommandRiskDeclaration(), "ledger.participation.rebuild": CommandRiskDeclaration(), "ledger.preflight": CommandRiskDeclaration(), "ledger.prorrata.declare_sector": CommandRiskDeclaration(), "ledger.prorrata.elect_especial": CommandRiskDeclaration(), "ledger.prorrata.elect_general": CommandRiskDeclaration(), "ledger.prorrata.list": CommandRiskDeclaration(), "ledger.providers": CommandRiskDeclaration(), "ledger.pull_folder": CommandRiskDeclaration(), "ledger.ratios.eligible": CommandRiskDeclaration(), "ledger.ratios.list": CommandRiskDeclaration(), "ledger.ratios.set": CommandRiskDeclaration(), "ledger.ratios.unset": CommandRiskDeclaration(), "ledger.ratios.validate": CommandRiskDeclaration(), "ledger.remove": CommandRiskDeclaration(destructive=True), "ledger.reset": CommandRiskDeclaration(destructive=True), "ledger.restore": CommandRiskDeclaration(), "ledger.review": CommandRiskDeclaration(), "ledger.rule.add": CommandRiskDeclaration(), "ledger.rule.apply": CommandRiskDeclaration(), "ledger.rule.list": CommandRiskDeclaration(), "ledger.split": CommandRiskDeclaration(), "ledger.stash": CommandRiskDeclaration(destructive=True), "ledger.status": CommandRiskDeclaration(), "ledger.track": CommandRiskDeclaration(), "ledger.update": CommandRiskDeclaration(), "ledger.view": CommandRiskDeclaration(), "modelo.aggregate": CommandRiskDeclaration(), "modelo.audit.check": CommandRiskDeclaration(), "modelo.audit.export": CommandRiskDeclaration(handoff=True), "modelo.audit.replay": CommandRiskDeclaration(), "modelo.audit.show": CommandRiskDeclaration(), "modelo.bindings.list": CommandRiskDeclaration(), "modelo.bindings.resolve": CommandRiskDeclaration(), "modelo.casilla": CommandRiskDeclaration(), "modelo.casillas": CommandRiskDeclaration(), "modelo.compare": CommandRiskDeclaration(), "modelo.describe": CommandRiskDeclaration(), "modelo.export": CommandRiskDeclaration(handoff=True), "modelo.filing_record.import": CommandRiskDeclaration(), "modelo.filing_record.list": CommandRiskDeclaration(), "modelo.filing_record.observe_local": CommandRiskDeclaration(), "modelo.filing_record.view": CommandRiskDeclaration(), "modelo.formulas": CommandRiskDeclaration(), "modelo.history": CommandRiskDeclaration(), "modelo.iva_wallet.balance": CommandRiskDeclaration(), "modelo.iva_wallet.correct": CommandRiskDeclaration(), "modelo.iva_wallet.override": CommandRiskDeclaration(), "modelo.iva_wallet.seed": CommandRiskDeclaration(), "modelo.list": CommandRiskDeclaration(), "modelo.m036.alta": CommandRiskDeclaration(), "modelo.m036.baja": CommandRiskDeclaration(), "modelo.m036.list": CommandRiskDeclaration(), "modelo.m036.modificacion": CommandRiskDeclaration(), "modelo.m036.view": CommandRiskDeclaration(), "modelo.m145.create": CommandRiskDeclaration(), "modelo.m145.export": CommandRiskDeclaration(handoff=True), "modelo.m145.mark_delivered_to_payer": CommandRiskDeclaration(), "modelo.m145.mark_locally_completed": CommandRiskDeclaration(), "modelo.m145.validate": CommandRiskDeclaration(), "modelo.project": CommandRiskDeclaration(), "modelo.readiness": CommandRiskDeclaration(), "modelo.reconcile.file": CommandRiskDeclaration(handoff=True), "modelo.reconcile.history": CommandRiskDeclaration(), "modelo.reconcile.pull": CommandRiskDeclaration(), "modelo.requires": CommandRiskDeclaration(), "modelo.review_package.build": CommandRiskDeclaration(), "modelo.review_package.counter_sign": CommandRiskDeclaration(), "modelo.review_package.decrypt": CommandRiskDeclaration(), "modelo.review_package.encrypt_feedback": CommandRiskDeclaration(), "modelo.review_package.encrypt_for_recipient": CommandRiskDeclaration(), "modelo.review_package.import_feedback": CommandRiskDeclaration(), "modelo.review_package.sign": CommandRiskDeclaration(), "modelo.review_package.verify": CommandRiskDeclaration(), "modelo.review_package.verify_receipt": CommandRiskDeclaration(), "modelo.review_package.verify_signature": CommandRiskDeclaration(), "modelo.support_matrix": CommandRiskDeclaration(), "modelo.verification_report.list": CommandRiskDeclaration(), "modelo.verification_report.view": CommandRiskDeclaration(), "modelo.work.amend": CommandRiskDeclaration(), "modelo.work.amend_wizard": CommandRiskDeclaration(), "modelo.work.calculate": CommandRiskDeclaration(), "modelo.work.compare_taxation": CommandRiskDeclaration(), "modelo.work.create": CommandRiskDeclaration(), "modelo.work.dependencies": CommandRiskDeclaration(), "modelo.work.discard": CommandRiskDeclaration(destructive=True), "modelo.work.file": CommandRiskDeclaration(handoff=True), "modelo.work.history": CommandRiskDeclaration(), "modelo.work.list": CommandRiskDeclaration(), "modelo.work.observations": CommandRiskDeclaration(), "modelo.work.preview_maritime_exemption": CommandRiskDeclaration(), "modelo.work.rename": CommandRiskDeclaration(), "modelo.work.resume": CommandRiskDeclaration(), "modelo.work.revision": CommandRiskDeclaration(), "modelo.work.revisions": CommandRiskDeclaration(), "modelo.work.runs": CommandRiskDeclaration(), "modelo.work.status": CommandRiskDeclaration(), "modelo.work.verify": CommandRiskDeclaration(), "modelo.work.wizard": CommandRiskDeclaration(), "quickfile": CommandRiskDeclaration(handoff=True), }
[docs] def declared_risk(command_key: str) -> CommandRiskDeclaration | None: """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 COMMAND_RISK.get(command_key)