QWED-Infra v0.3.0 ships Verification Context v1.0 across all four guards and the Attestation Trust Boundary — every ADMIT is now backed by an ES256-signed receipt bound to the exact claim and evidence.
✅ Added
Verification Context v1.0 (tracker #36)
to_verification_context()on all four guards — IamGuard (#45), NetworkGuard (#46), CostGuard (#48), ArtifactBoundaryGuard (#50) — producing schema-valid, tamper-evident VC documents (claim, verifier identity,sha256-boundproof_ref, ADMIT/DENY admission)- Shared
verification_context_bridgemodule (#37/#44): diagnostic → VC document conversion with fail-closed attestation policy and decision-status demotion - Conformance suite
tests/test_vc_conformance.py(#42/#52) — bridge + all guards + document validation + malformed-input fail-closed acceptance tests - README "Verification Context v1.0" section: why VC, usage examples, downstream integration guide
Attestation trust boundary (#47/#54)
- New
qwed_infra/attestation.py: ES256 (ECDSA P-256) JWT attestation service — signing, verification (signature/issuer/expiry/revocation), revocation registry, ephemeral key lifecycle auditing, never-None fail-closedAttestationResult enforce_trust_decision(): single consumption-side gate validating tokens plus full claim binding (status,query_hash == sha256(formal_statement),proof_hash == diagnostic proof_ref)mint_diagnostic_attestation(): issue a token bound to a diagnostic's own evidence commitment
⚠️ Changed
- BREAKING (pre-1.0 API): guard adapters no longer accept pre-computed result objects.
to_verification_context()takes raw verification inputs and runs the guard's deterministic solver internally — a result-accepting signature was forgeable (fabricated results could mint ADMIT), so it was removed before release. - ADMISSION SEMANTICS: VERIFIED results admit only with a cryptographically valid attestation bound to the exact claim and evidence. Arbitrary non-empty attestation strings no longer grant ADMIT (rejected as forged); a missing token demotes VERIFIED to UNVERIFIABLE/DENY. Callers using placeholder tokens must mint via
create_verification_attestation()/mint_diagnostic_attestation()instead. - New runtime dependencies:
pyjwt>=2.8.0,!=2.12.1,cryptography>=41.0.0
🔒 Fixed
- Fail-closed on malformed inputs at every VC boundary: undecimal budgets, extreme Decimal values, non-string build backends, malformed topology/policy/package inputs, symlink escapes/loops, wheel entries outside the scanned boundary — all map to BLOCKED/DENY documents instead of exceptions or guessed approval (#48, #49/#51, #50)
- ArtifactBoundaryGuard proof binding: per-file sha256 content manifests, package identity derived from the inspected directory, exact-match build-backend allowlist
- IAM verified-denial results demote to BLOCKED (never ADMIT), with the document-level proof_ref staying null for every DENY decision
📦 Upgrade notes
- If you passed placeholder strings as
attestation_token, either drop the argument (VERIFIED → UNVERIFIABLE/DENY) or mint real attestations bound to your claim+evidence - Guard adapter calls change shape: pass raw inputs directly, e.g.
NetworkGuard().to_verification_context(infra, source, dst, port, formal_statement=..., attestation_token=...) - Build reproducibility:
hatchling==1.27.0pinned (Metadata-Version 2.4)
Full changelog: see CHANGELOG.md