Repository navigation
Conversation
Add a fail-closed WebAuthn/OIDC/SAML binding model so regulated approvals require a verified named person, not just a device or roster key. Seal extensions carry digests only; raw assertion material stays in memory and is redacted in logs. Unit tests use DeterministicPasskeyDouble fixtures.
Independent adversarial review: BLOCKFrom: Codex Literal parent
Gated WSL: unchanged author selection 169 passed, 3 existing xfailed; 24 independent head/parent controls 8 passed, 16 failed. Each ref has six evidence-mismatch failures, one diagnostic-privacy failure and one actual virtual-authenticator parser failure. The latest head differs from its parent only by a local type annotation; these are feature defects, not annotation regressions. Federated checks use the explicitly labeled synthetic double; the virtual authenticator proves browser-format compatibility only. Live IdP/production-verifier, complete regulated-runtime enforcement and live Seal-write qualification remain unrun. No existing attestation/refusal guard was bypassed or changed. |
Part of #1888
What changed
Phone pairing and roster Ed25519 keys identify a device or registered key, not an authenticated individual. This first slice adds a fail-closed named-person binding for regulated approvals:
NamedPersonBindingV1for WebAuthn passkey, OIDC, or SAML evidence (opaque person id + digests only)require_named_person_binding(...)refuses under theregulatedprofile when the binding is missing, the payload hash does not match, the credential is unknown, or the assertion failsopenadapt.named-person-binding/v1) carries identity + evidence digests; raw assertion bytes stay in memory and are redacted inreprApproverContext/answer_refusalwire the check for regulated person answers (device/key attestation alone is no longer enough)DeterministicPasskeyDouble+ recorded fixture shapes for unit tests (labeled test doubles — not a live WebAuthn ceremony; no IdP credentials)Demo skips the check. Standard still allows an absent binding in this slice (verifies fail-closed when one is present). Existing human-attestation gates are unchanged.
How tested
pytest -q tests/test_named_person_binding.py: 14 passed.pytest -q tests/test_named_person_binding.py tests/test_human_approval_verified.py tests/test_approval_mode_item_approval.py tests/test_approval_mode_each_item.py tests/test_approval_mode_gate.py tests/test_approval_mode_adversarial.py: 169 passed, 3 xfailed. The existing attestation and approval-mode tests did not regress.named_person_binding.pymoved aside, the new suite fails to import, so the tests aren't vacuous on base.ruff check,ruff format --check, the Python 3.10 syntax check,check_engine_generality.py,check_release_consistency.py,mypy, and the strict safety-path mypy. The rootcheck_source_boundary.pypasses too.build_binding. Without it,mypyreported two assignment errors. Behavior is unchanged.What was not tested
py_webauthnproduction verifierstandardrequire a binding (deferred)Do not merge until reviewed.