check_action
Kerne-gaten (to-lags evaluering): Lag A (deterministisk hard-rule/outward-match, ingen
LLM) + Lag B (Sonnet vurderer mod charterets NL-principper via LiteLLM :4000, citerer
principle_id + reasoning — INGEN egen alvorligheds-dom) → most-restrictive-wins aggregeret,
auditerbar receipt: {action, deterministic_flags[], values_assessment[],
values_assessment_unavailable, unrecognized_principle_citations, principles_evaluated,
recommendation, requires_human, charter_name, scope_note}.
`recommendation` ∈ {allow, flag, gate_to_human} — ALDRIG approved/denied/true/false.
ADVISORY: anbefaler, blokerer/eksekverer/autoriserer ALDRIG (never-decide-for-you).
FAIL-SAFE: Lag B utilgængelig -> Lag A kører stadig, values_assessment_unavailable=true,
recommendation løftet til MINDST 'flag' (aldrig stille 'allow'). Read-only — skriver
INTET, ingen side-effekter.
PUBLIC_DEMO-mode: vurderet mod det OFFENTLIGE Art-14-demo-charter (ikke din org — se
scope_note). Rate-limitet (default 5/min + 30/time, ÉN global demo-bucket). Over grænsen
returneres `{error:"rate_limited", retry_after_s, scope_note}` — ALDRIG et
recommendation-formet svar. Bogholderi-fejl i rate-limiteren -> deny (fail-safe).
RED-TEAM-FIX (minimal-indgreb): tomt/whitespace-only `action` valideres FØR rate-limiteren
forbruger en kvote-token — en ugyldig-input-loop kan ellers stille dræne demoens kvote uden
at nogensinde levere en receipt (rå ValueError fra firewall.check_action's fail-loud-guard
ville ellers både forbruge kvote OG propagere ubehandlet til transport-laget, hvilket
bryder "check_action leverer ALTID en receipt/struktureret fejl"-disciplinen). Uden for
PUBLIC_DEMO uændret: fw.check_action's egen ValueError-fail-loud gælder stadig (bindende,
testet i test_values_firewall.py).