Skip to content

feat(d3): evaluator core — per-type handlers + advisory-lock eval-tx (component 2 step 3)#119

Merged
MoltyCel merged 4 commits into
mainfrom
feat/d3-c2-evaluator
Jun 1, 2026
Merged

feat(d3): evaluator core — per-type handlers + advisory-lock eval-tx (component 2 step 3)#119
MoltyCel merged 4 commits into
mainfrom
feat/d3-c2-evaluator

Conversation

@MoltyCel

@MoltyCel MoltyCel commented Jun 1, 2026

Copy link
Copy Markdown
Owner

Evaluator (Komponente 2) Code-Schritt 3 — der ALLOW/DENY-Kern. Verweist Evaluator-Brief v4 (#115).

app/enforcement/evaluator.py

  • Per-Type-Handler (async, mirror anomaly.py; Verdict-Form type/threshold/current_value/delta/verdict/reason):
    • max_transaction_value: numeric-hardening (integer-minor-units, >=0, finite, upper-bound, float/str/bool→reject) + currency-match + value_source-Gating (self_asserted + required → Default-DENY)
    • allowed_domains: exakter Match (kein substring-bypass)
    • rate_limit: COUNT über aae_evaluations (NICHT IPR) im ISO-8601-Fenster via created_at
    • not_before/not_after: server-timestamp vs window + D1-clock-skew
    • single_use: aae_ref schon in einem ALLOW-eval? (gleiche Lock-tx)
    • revocation_check: DEFERRED-Stub → bei Präsenz fail-closed DENY (SSRF-proxy-Subkomponente)
  • Kritische Regel: unknown/unevaluable required:true → Default-DENY; required:false unknown → ignore
  • Orchestrator evaluate_envelope: single-bigint pg_advisory_xact_lock(('x'||substr(sha256_hex,1,16))::bit(64)::bigint) + load + alle Constraints + VALIDITY + aggregate (ein DENY → DENY) + signiertes eval-row (verdict_sign feat(d3): verdict signing — component 2 step 2 (Ed25519 over full record) #118, created_at = signierter timestamp) — alles in EINER Transaktion (TOCTOU-frei).

Tests (server-venv, 14 grün)

pro Typ ALLOW+DENY; numeric-bypass (neg/str/over-bound/float/bool→reject); self_asserted-Betrag→DENY; currency-mismatch; rate_limit-window-count; single_use-collision; parallel-TOCTOU (2 Verbindungen, advisory-lock serialisiert → genau 1 ALLOW + 1 DENY); unknown required→DENY / not-required→ignore; aggregierter DENY; revocation-deferred-DENY; signiertes eval-row in-memory + aus-DB-rekonstruiert verifizierbar.

Hinweise

§3.1 + §3.2 ✅. NICHT auf Live. Der Parallel-TOCTOU-Test hinterlässt test-markierte append-only Rows (immutable Tabelle, kein DELETE — Konvention wie IPR/credit_transactions).

Nächste Schritte

  1. POST /vc/aae/evaluate-Endpoint + vc_id-Binding · 5. violation_records-Write. Davor: Security-Code-Review (ai_review security auf evaluator.py).

🤖 Generated with Claude Code

Lars Kroehl added 3 commits June 1, 2026 13:14
…(component 2 step 3)

app/enforcement/evaluator.py: async _eval_<type> handlers (max_transaction_value w/ numeric-hardening + value_source gating, allowed_domains exact-match, rate_limit COUNT over aae_evaluations, not_before/not_after w/ clock-skew, single_use, revocation_check deferred-DENY stub); Default-DENY on unknown/unevaluable required:true; evaluate_envelope orchestrator: single-bigint pg_advisory_xact_lock + load + aggregate (one DENY -> DENY) + signed eval-row insert (created_at = signed timestamp) all in one tx. 14 server-venv tests green incl. parallel-TOCTOU (advisory-lock serializes) + stored-row re-verify.

Per evaluator brief v4 (#115). Code+tests only — NOT live. NB: parallel-toctou test leaves test-marked append-only rows (immutable table, per convention).
1) advisory-lock key: null-byte separator (DIDs+sha256-refs contain ':' -> colon-concat collision); 2) constraint-handler exception -> always DENY (fail-closed, was ALLOW on required=False); 3) server-timestamp written into action_context (verbatim jsonb store + signed -> robust re-verify, enforces server time over client); 4) rate_limit per-(agent_did, aae_ref) not agent-global; 5) domain case-insensitive + string-type check, constraints-is-list guard. 18 server-venv tests green (4 new: no-colon-collision, fail-closed-on-exception, per-envelope rate-limit isolation, server-overrides-timestamp).
1) nonce REQUIRED — no uuid fallback (server never mints the client replay-token); missing/empty -> fail-closed DENY (closes replay-bypass). 2) never-crash-without-audit: evaluate_envelope fully wrapped, any error -> signed DENY audit row; nonce-replay (unique_violation) -> controlled DENY. 3) empty/missing agent_did -> DENY (no shared advisory-lock). 4) ISO-8601 duration upper-bound cap (>366d -> reject, DoS). 23 server-venv tests green (5 new).

STEP-4 QUEUE (endpoint /vc/aae/evaluate, defense-in-depth): nonce-missing->422 (user-facing, before core); action_context schema+size validation; format checks; size-cap. Endpoint 422 AND core-DENY both.

Per evaluator brief v4 (#115).
@MoltyCel

MoltyCel commented Jun 1, 2026

Copy link
Copy Markdown
Owner Author

Step-4-Queue (endpoint-boundary, explizit dokumentiert — nicht verlieren): Am POST /vc/aae/evaluate-Endpoint (Schritt 4) gehören die untrusted-input-Härtungen aus Code-Review-v2 #3/#4: nonce-missing → 422 (user-facing, VOR Core), action_context Schema- + Size-Validierung, Format-Checks, Size-Cap. Defense-in-Depth: Endpoint-422 UND Core-DENY beide (Core-DENY ist bereits in diesem PR). Kein dritter Core-Review für Endpoint-Items.

…nt single_use TOCTOU

Lock key = sha256(aae_ref) only (not agent_did:aae_ref): serializes ALL evals of an envelope incl. cross-agent, closing the single_use bypass where two agent_dids present the same envelope concurrently. rate_limit stays per-agent (count query still filters agent_did). 25 server-venv tests green (2 new: cross-agent-single_use-serialized, rate_limit-per-agent-isolated-under-envelope-lock).
@MoltyCel
MoltyCel merged commit ae0ba1b into main Jun 1, 2026
12 checks passed
MoltyCel added a commit that referenced this pull request Jun 2, 2026
Boundary validation (defense-in-depth to fail-closed core): aae_ref format, action_context schema+8KB size-cap, nonce-missing->422, numeric value finite-check, agent_did==auth-principal (403 else), vc_id<->envelope direct binding (substitution-safe; delegation-chain = follow-up). Calls evaluate_envelope; returns signed verdict. verdict_signature added to _KNOWN_PUBLIC_CREDENTIAL_FIELDS (scrub-allowlist, lesson #101).

Per evaluator brief v4 (#115) + core #119.

Co-authored-by: Lars Kroehl <kersten.kroehl@cryptokri.ch>
MoltyCel added a commit that referenced this pull request Jul 11, 2026
…moltrust-web (#238)

Load the positive English voice profile (my-voice-en.md) into the drafter
system prompt next to anti-KI-Sprech.md, register-matched via its sarcasm scale.
Repoint DOC_ANTI_KI at the moltrust-web shallow clone so the worker reads the
canonical anti-KI-Sprech.md (with the new 2026-07-11 §3 tells) instead of the
stale ~/moltstack/docs copy. Retire that copy to a pointer stub — one canonical
source (moltrust-web) so the two cannot diverge again.

Depends on moltrust-web PR #119 (adds anti-KI-Sprech.md + my-voice-en.md at repo
root on main); merge #119 BEFORE deploying this branch, else the .webdocs main
clone lacks the files and the drafter loads the [missing] marker.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant