dev → main: v0.2.0 release promotion - #17
Open
gnanirahulnutakki wants to merge 767 commits into
Open
Conversation
gnanirahulnutakki
added a commit
that referenced
this pull request
May 26, 2026
…o/sigs.k8s.io/controller-runtime-0.24.0 deps(go)(deps): bump sigs.k8s.io/controller-runtime from 0.23.3 to 0.24.0 in /go
This was referenced Jun 23, 2026
This was referenced Jun 29, 2026
…tion Add 'unknown' to the receipt verdict taxonomy alongside 'compliant', 'violation', and 'insufficient_evidence'. This is the honest-abstention outcome: the verifier observed a tool call but cannot determine compliance because evidence is structurally outside the capture boundary (observation gaps, unobserved side effects, bypassed adapter). Distinct from 'insufficient_evidence' (verifier tried to evaluate but couldn't due to operator unavailability, state corruption, or network errors — fail-closed DENY). 'unknown' means the system honestly says 'I observed this call but I don't know what really happened.' Changes: - receipt.py: _VERDICTS, _DENIAL_REASONS, _verdict_from_decision, _public_denial_reason now accept and map 'unknown' - execution_receipt_v02.schema.json: verdict enum includes 'unknown' - governance_telemetry_v01.schema.json: severity enum includes 'unknown' - test_unknown_verdict.py: 11 new tests covering all mapping paths - CHANGELOG + source mirrors synced
CVE-2026-69247: cryptography PKCS#7 EnvelopedData decryption exposes a Bleichenbacher oracle through distinguishable errors. Fixed in 50.0.0. The previous pin cryptography>=41.0,<50 capped Ardur at the vulnerable 49.0.0 release, which the Trivy scan in the Hardened proxy image smoke job correctly rejected as a fixable HIGH finding. Bumping the upper bound to <51 lets pip resolve 50.0.0. Full test suite (2762 passed, 35 skipped) is green on 50.0.0 across all cryptography-touching modules: receipts, passports, attestations, DRP, transparency, mission, memory, risk budget, Claude Code hook, offline verification, and receiver attestation fixtures.
Follow-up to e3879ef: the pyproject.toml constraint bump alone did not move the Docker image off 49.0.0 because packaging/oci/runtime-requirements.lock pins exact versions with hashes. The Hardened proxy Trivy scan kept failing on CVE-2026-69247 because the OCI image was still built from the locked 49.0.0. Regenerated both lock files: - packaging/oci/runtime-requirements.lock: cryptography 49.0.0 -> 50.0.0 (uv pip compile --generate-hashes) - python/uv.lock: cryptography 49.0.0 -> 50.0.0 (uv lock --upgrade-package) OCI release validator passes. 22/22 OCI + package release tests pass.
Add UNKNOWN as a first-class Decision enum value representing a genuine observation gap where the verifier observed the call but the evidence is structurally outside the capture boundary (e.g., visibility != 'full'). Unlike INSUFFICIENT_EVIDENCE (transient operational failure — approval operator unavailable, state file corrupted), UNKNOWN records the honest 'I cannot know what happened' — the information needed for a decision was never visible at all. Both UNKNOWN and INSUFFICIENT_EVIDENCE fail-closed as DENY. The distinction exists so audit trails can separate structural observation gaps from retryable operational failures. Changes: - proxy.py: Decision enum gains UNKNOWN; _legacy_denial_reason maps it to DenialReason.OBSERVATION_GAP; visibility-insufficient path (MIC-State/ MIC-Evidence Check 3) now returns UNKNOWN instead of INSUFFICIENT_EVIDENCE - denial.py: DenialReason gains OBSERVATION_GAP - receipt.py: _DENIAL_REASONS gains 'observation_gap' - codex_app_server_fixture.py, gemini_cli_hook.py, provider_adapter_fixture.py: _status_from_verdict now explicitly handles verdict='unknown' - execution-receipt-v0.2 schema description updated from 'Tri-state' to 'Four-state verifier result' - test_unknown_decision.py: 10 new tests covering enum, denial mapping, fixture handling - test_mic_conformance.py, test_http.py: visibility tests updated to expect UNKNOWN
…OWN vs INSUFFICIENT_EVIDENCE
…est observation-gap abstention The Python receipt schema and governance proxy already landed 'unknown' as a first-class verdict for structural observation gaps (genuine visibility boundary), distinct from 'insufficient_evidence' (transient operational failure). The Go SyntheticKernelReceipt correlator still mapped daemon-restart-gap and coverage-unknown events to 'insufficient_evidence', conflating the two. This commit: - Adds SyntheticKernelReceiptVerdictUnknown constant in types.go - Adds markUnknown() helper in correlator.go - Wires coverage_status='unknown' (restart gap, coverage unknown) to emit verdict='unknown' instead of 'insufficient_evidence' - Updates enforce_event_summary.go doc comment to include 'unknown' in the verdict list - Updates existing correlator tests to assert verdict='unknown' for restart-gap scenarios - Completes cross-language consistency of the five-state Decision taxonomy The semantic distinction mirrors the Python side exactly: unknown = the daemon observed the event but evidence is structurally unknowable; insufficient_evidence = the verifier tried but could not evaluate. Both fail-closed as DENY.
Post-landing docs drift: the honest-abstention wedge landed 'unknown' as a first-class receipt verdict (42cf640 + 3f452a0 + 56de799 + 22bc179) but docs/coverage-map.md still only listed 'insufficient_evidence' in its per-receipt evidence-level table. Added 'unknown' as a distinct row, corrected the provider-side gap row to reference 'unknown', and aligned the closing paragraph with the five-state Decision taxonomy in security-model.md. Also regenerated site/content/source/docs/coverage-map.md mirror.
The v0.1 protocol specs defined a tri-state verifier codomain
{compliant, violation, insufficient_evidence} while the runtime
schema (execution_receipt_v02) and governance proxy already include
'unknown' as a fourth verdict for structural observation gaps.
This commit brings the v0.1 specs into alignment:
- verifier-contract-v0.1.md §4: add 'unknown' to codomain with v0.2
extension note explaining the distinction (unknown = structural
observation gap, insufficient_evidence = transient operational failure)
- execution-receipt-v0.1.md: update verdict enum and remove 'tri-state'
- execution-receipt-v0.1.schema.json: add 'unknown' to verdict enum
- conformance-profiles-v0.1.md: update codomain reference
- execution-receipt-eat-profile-v0.1.md: update verdict list
- governance-telemetry-v0.1.md: expand verdict tuple
- idm-extension-v0.1.md: clarify both honesty outcomes
- offline-verification-bundle-v0.1.md: expand verdict projection
- auditbench-evaluation-protocol-v0.1.md: accept 4-state verdicts
- ardur-drp-mapping-v0.1.json: map unknown to DENY
- oauth-and-managed-agent-auth.md: update comparison tuple
Historical 'tri-state' references in research/comparison narrative
docs are preserved as design-history context. Two intentional
references remain in verifier-contract-v0.1.md (v0.2 extension note
and precursor citation).
Review t_869df4ed (BLOCKED on criterion 6) found the prose rationale correctly maps 'unknown to DENY', but the structured profile_shape.decision_projection table omitted the unknown key. Add it to both canonical and site mirror so DRP implementers get an explicit rule for the unknown verdict. Files changed: - docs/specs/ardur-drp-mapping-v0.1.json - site/static/repo/docs/specs/ardur-drp-mapping-v0.1.json
…ignment Add CHANGELOG entry for the v0.1 protocol specification updates that completed the honest-abstention product wedge end-to-end: receipt schema → governance enforcement → security model → Go correlator → coverage map → protocol specs. Documents the verifier-codomain alignment across all 8 v0.1 spec docs plus the DRP decision-projection mapping fix.
…n taxonomy The honest-abstention wedge (42cf640..232fe9f) landed 'unknown' as a first-class verdict across receipt schema, proxy, Go correlator, protocol specs, security-model, and coverage-map. Three top-level public-facing surfaces were stale: - STATUS.md had zero mention of the five-state Decision taxonomy; now documents PERMIT/DENY/VIOLATION/INSUFFICIENT_EVIDENCE/UNKNOWN with the distinction between structural observation gap (UNKNOWN) and transient operational failure (INSUFFICIENT_EVIDENCE). - README.md AuditBench scoring description said 'tri-state' after the protocol spec codomain was updated to four-state with 'unknown'. - CHANGELOG gains entries for both docs alignment items. Source mirrors regenerated via sync_source_docs.py.
When UNKNOWN was added to the five-state Decision taxonomy (3f452a0), _build_summary was not updated — its denials tuple only covered DENY, INSUFFICIENT_EVIDENCE, and VIOLATION. An UNKNOWN event would silently pass uncounted, understating the aggregate denial count and incorrectly reporting scope_compliance: 'full'. Fix: add Decision.UNKNOWN to the denials tuple and break out unknowns and insufficient_evidence as separate count fields for audit clarity. 6 new regression tests prove UNKNOWN is counted as a denial, that total_events == denials when all events are non-PERMIT, and that the new summary fields are present.
…on and telemetry export The 'unknown' verdict (added for honest observation-gap abstention) was missing from _verdict_label and the OTel severity map, causing KeyError crashes that broke offline verification and telemetry export for any receipt chain containing an UNKNOWN decision. This was a denial-of-audit: an attacker who could trigger UNKNOWN verdicts could crash post-hoc verification. - Map 'unknown' -> 'UNKNOWN' in _verdict_label (offline_verification.py) - Add 'UNKNOWN' severity mapping in receipt_telemetry.py OTel export - Add 'UNKNOWN' to governance_telemetry_v01 schema decision enum - Sync all three schema copies (python/_specs, docs/specs, site/static) - Add regression tests for both crash paths Adversarial review confirmed UNKNOWN is correctly fail-closed in all governance paths: counted as denial in _build_summary, not upgradeable to PERMIT, and _budget_decision treats it as not_applicable (not allowed).
Add CHANGELOG 'Fixed' entry for the KeyError crash in offline verification (_verdict_label) and telemetry export severity map when a receipt chain contains an 'unknown' verdict. The verdict was added as a first-class outcome for honest observation-gap abstention, but the label dict and OTel severity map were not updated alongside it. This was a denial-of-audit vector: an attacker who could trigger unknown verdicts could crash post-hoc verification paths.
Add zero-privilege process-lifecycle capture to 'ardur run -- <cli>': the launched root process's PID, command, started_at (wall-clock), wall_clock_s, exit_code, and exit_signal are recorded in GovernanceRunResult.process_lifecycle and surfaced in --json output and the human-readable summary. capture_tier='host-observer' honestly marks this as root-process lifecycle only — consumers never mistake it for full process-tree capture (which requires eBPF daemon correlation). Works with any CLI on macOS/Linux without any host plugin API dependency. Review remediation (t_697da6a7): - C1 (critical): started_at was derived from time.monotonic() (boot-relative), producing 1970 dates. Fixed: capture time.time() separately at launch for the wall-clock timestamp; monotonic clock retained for elapsed-duration. Added year-bound regression tests (unit + integration). - W1 (warning): process_lifecycle.command bypassed redact_paths in to_result_dict. Fixed: redact each command element via _redact_local_path_embedded when redact_paths=True. Added regression tests. - W2 (warning): commit message overclaimed '655 regression tests'. Dropped the unreliable count; actual full suite is 2808 passed / 35 skipped. Verification (this worktree, post-remediation): - 24 focused lifecycle tests + 14 json-output tests = 38 PASS - Full regression: 2808 passed, 35 skipped - check-local --quick GREEN - sync_source_docs --check: 125 pages / 133 artifacts - gen-agent-docs-check up to date
When an adapter transforms argv before launch (Claude Code --plugin-dir injection, seccomp shim, launch-gate wrapping), the actual argv is now captured in the lifecycle evidence's run_command field alongside the original command field. This lets consumers distinguish 'what was asked to run' from 'what the OS was told to execute.' run_command is omitted when identical to command (the common via=env case). Both fields are redacted under --redact-paths. 6 new focused tests: unit (absent when omitted, absent when identical, present when differs, redacted, preserved), integration (env adapter omits run_command). 2814 passed, 35 skipped.
Add Layer 1.5 host-observer lifecycle to coverage-map boundary diagram and capture table. Document process_lifecycle evidence fields (pid, command, run_command, started_at, wall_clock_s, exit_code, exit_signal, capture_tier=host-observer) for ardur run -- <cli>. STATUS.md Capture Boundary section updated with the same tier description. Claim boundary preserved: host-observer is root-process lifecycle only, not subprocess-tree interior, syscalls, or provider-side actions.
The host-observer process-lifecycle evidence now records the absolute working directory the launched process was started in. This closes the gap where consumers could see root_pid, command, started_at, wall_clock, exit code/signal, and adapter-wrapped run_command, but not the filesystem context of the run. When --redact-paths is set, the cwd is redacted via _redact_local_path (full path replacement) rather than _redact_local_path_embedded (argv element path replacement), since cwd is a single absolute path string. Added 11 focused tests: 4 unit (builder), 3 redaction (result dict), 4 integration (run_governed end-to-end including explicit cwd and redact_paths).
…idence Post-landing scan after d985f14 found cwd was missing from the host-observer tier description in coverage-map.md and STATUS.md. Added cwd (absolute working directory) to: - coverage-map.md: header summary, capture table row, boundary diagram, and Layer 1.5 prose - STATUS.md: capture boundary paragraph - Hugo source mirrors regenerated
The host-observer process-lifecycle evidence now records the time budget (max_duration_s) the caller set for the process, if any. This lets consumers compare the budget against wall_clock_s to detect budget-exhaustion or near-exhaustion. - _build_process_lifecycle_evidence: +duration_budget_s param (int|None, omitted when None for backward compat) - run_governed: wires max_duration_s to the builder - 6 new tests: absent-when-omitted, present-when-provided, int-type, zero-is-included, result-dict round-trip, not-redacted (plain integer)
…r lifecycle evidence
The host-observer process-lifecycle evidence (root_pid, command, run_command, cwd, duration_budget_s, started_at, wall_clock_s, exit_code, exit_signal, capture_tier) is now included in the session attestation JWT as a 'process_lifecycle' claim, making it cryptographically verifiable alongside the receipt chain. - proxy.py: add process_lifecycle param to issue_attestation_for_session, include in extra_claims when provided - run_bridge.py: build lifecycle evidence before attestation call, pass to issue_attestation_for_session; initialize exit_code before Popen to avoid UnboundLocalError on preexec failures - test_proxy.py: 3 new tests (includes, omits, with kernel_enforcement) - 2833/2833 regression PASS, 0 failures
…ation token CHANGELOG: add entry for process_lifecycle claim injection into the session-final attestation JWT, making lifecycle evidence cryptographically verifiable in the attestation chain. coverage-map: note that lifecycle evidence is now signed into the attestation token as a process_lifecycle claim, not just present in the governance result object. Source mirrors regenerated via sync_source_docs.py.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Promotes the current
devbranch tomainas the human-gatedv0.2.0release candidate. At the current head,devis 524 commits ahead ofmain;mainis an ancestor ofdev, with zero reverse-only commits, so this remains a forward-only promotion.The existing immutable
v0.1.0tag remains at00c8d7eb88b0cc98cc8f65f8bfcca94491db5b9a. It will not be moved or rewritten. PR #245 prepared package, runtime, proxy, lock, and OCI documentation metadata at0.2.0. A freshv0.2.0tag and GitHub Release remain deferred to #147 after this promotion.Current release scope
This release does not claim universal kernel enforcement for unknown or uncooperative agents. Remaining unknown-agent attach and independent-corpus work stay explicitly tracked.
Current evidence — 2026-07-12
dev/ PR head:eb63d22361c45621df7c04884ee978b9bf0195c3.origin/mainatce7ac316320b7b37ad03bf21a045c95126e45becis an ancestor oforigin/dev; 524 forward commits and zero reverse-only commits.devSHA verification: all 17 workflows successful, including Python 3.10/3.13, Go, CodeQL, package/wheel smoke, OCI, docs/links/formats/secrets, Linux governance benchmark, BPF generation, KVM kernel smoke, seccomp smoke, and strictardur run --enforceseccomp E2E.proxy.golang.orgHTTP/2 reset during module download; failed-job attempt 2 passed on the unchanged SHA.v0.1.0tag is unchanged; nov0.2.0tag or GitHub Release exists.Promotion gates
devcontains prepared0.2.0release metadata.mainancestry is clean and forward-only.CHANGELOG.md[0.2.0]section on the actual release date and adds the matching-version validation before final approval.devupdate.mainchecks are green.v0.2.0tag and GitHub Release at the promotedmainSHA.Approval boundary
Branch protection requires one human approving review. Automated work must not supply or bypass that approval. Stale reviews are dismissed when
devadvances, so approval must apply to the final head after #272 is stamped on the real release date. Current headeb63d22361c45621df7c04884ee978b9bf0195c3has zero approvals.Related: #140, #147, #189, #191, #272, #79.