Skip to content

dev → main: v0.2.0 release promotion - #17

Open
gnanirahulnutakki wants to merge 767 commits into
mainfrom
dev
Open

dev → main: v0.2.0 release promotion#17
gnanirahulnutakki wants to merge 767 commits into
mainfrom
dev

Conversation

@gnanirahulnutakki

@gnanirahulnutakki gnanirahulnutakki commented May 26, 2026

Copy link
Copy Markdown
Member

Summary

Promotes the current dev branch to main as the human-gated v0.2.0 release candidate. At the current head, dev is 524 commits ahead of main; main is an ancestor of dev, with zero reverse-only commits, so this remains a forward-only promotion.

The existing immutable v0.1.0 tag remains at 00c8d7eb88b0cc98cc8f65f8bfcca94491db5b9a. It will not be moved or rewritten. PR #245 prepared package, runtime, proxy, lock, and OCI documentation metadata at 0.2.0. A fresh v0.2.0 tag and GitHub Release remain deferred to #147 after this promotion.

Current release scope

  • Tool-call-boundary governance with fail-closed policy evaluation and signed, hash-chained evidence.
  • Mission Passport JWT identity and delegation controls.
  • Python governance proxy and CLI, including health, JWKS, rate limiting, kill switch, metrics, TLS, and SPIFFE X.509-SVID mTLS telemetry ingestion.
  • Go daemon, launch-wrapper session linkage, eBPF lifecycle capture, cgroup-scoped BPF policy, seccomp/container controls, and measured Linux/KVM paths.
  • Claude Code and Gemini integration surfaces.
  • Prepared Python package and immutable OCI proxy release pipelines.
  • Public protocol/profile documentation and offline verification artifacts.

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

  • Current dev / PR head: eb63d22361c45621df7c04884ee978b9bf0195c3.
  • origin/main at ce7ac316320b7b37ad03bf21a045c95126e45bec is an ancestor of origin/dev; 524 forward commits and zero reverse-only commits.
  • Current PR dev → main: v0.2.0 release promotion #17 rollup: 72 successful checks, 12 intentional skips, zero failures, zero pending.
  • Latest reviewed local Python suite: 1,811 passed, 33 skipped.
  • Exact merged-dev SHA 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 strict ardur run --enforce seccomp E2E.
  • Kernel attempt 1 encountered an upstream proxy.golang.org HTTP/2 reset during module download; failed-job attempt 2 passed on the unchanged SHA.
  • Package build/distribution validation, Python 3.9 rejection guard, fresh-user RWT, and authenticated proxy lifecycle smoke passed.
  • Historical v0.1.0 tag is unchanged; no v0.2.0 tag or GitHub Release exists.

Promotion gates

Approval boundary

Branch protection requires one human approving review. Automated work must not supply or bypass that approval. Stale reviews are dismissed when dev advances, so approval must apply to the final head after #272 is stamped on the real release date. Current head eb63d22361c45621df7c04884ee978b9bf0195c3 has zero approvals.

Related: #140, #147, #189, #191, #272, #79.

Comment thread python/tests/test_e2e_showcase.py Fixed
Comment thread python/tests/test_e2e_showcase.py Fixed
Comment thread python/tests/test_e2e_showcase.py Fixed
Comment thread python/tests/test_e2e_showcase.py Fixed
Comment thread python/tests/test_e2e_showcase.py Fixed
Comment thread python/tests/test_e2e_showcase.py Fixed
Comment thread python/tests/test_e2e_showcase.py Fixed
Comment thread python/tests/test_e2e_showcase.py Fixed
Comment thread python/tests/test_e2e_showcase.py Fixed
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
@gnanirahulnutakki gnanirahulnutakki changed the title dev → main: e2e showcase, dependabot bumps, controller-runtime update dev → main: v0.1.0 governance hardening, Phase 2 daemon, e2e showcase, dependabot bumps May 26, 2026
Comment thread python/vibap/gemini_cli_hook.py Fixed
Comment thread python/vibap/codex_app_server_fixture.py Fixed
Comment thread python/vibap/proxy.py Fixed
Comment thread python/vibap/gemini_cli_hook.py Fixed
Comment thread python/vibap/codex_app_server_fixture.py Fixed
Comment thread python/tests/test_gemini_cli_hook.py Fixed
Comment thread python/tests/test_examples_governance_integration.py Fixed
Comment thread python/tests/test_examples_governance_integration.py Fixed
Comment thread python/tests/test_examples_governance_integration.py Fixed
Comment thread python/tests/test_examples_governance_integration.py Fixed
Comment thread python/vibap/proxy.py Fixed
Comment thread python/vibap/mcp_gateway.py Fixed
Comment thread python/vibap/mcp_gateway.py Fixed
Comment thread python/vibap/proxy.py Fixed
Comment thread python/vibap/claude_code_hook.py Fixed
Comment thread python/tests/test_mcp_gateway.py Fixed
Comment thread python/tests/test_mcp_gateway.py Fixed
Comment thread python/tests/test_mcp_gateway.py Fixed
Comment thread python/tests/test_content_safety.py Fixed
Comment thread python/tests/test_content_safety.py Fixed
Comment thread scripts/generate_adversarial_scoreboard.py Fixed
Comment thread python/vibap/gemini_cli_hook.py Fixed
Comment thread python/vibap/passport.py Fixed
Comment thread python/vibap/proxy.py Fixed
Comment thread python/vibap/proxy.py Fixed
Comment thread go/pkg/kernelcapture/daemon_session_status_evidence_log_entry.go Fixed
Comment thread python/tests/test_ardur_personal_hub.py Fixed
Comment thread python/tests/test_claude_code_hook.py Fixed
Comment thread python/vibap/claude_code_daemon.py Fixed
Comment thread python/vibap/cli.py Fixed
Comment thread python/vibap/cli.py Fixed
Comment thread python/vibap/cli.py Fixed
Comment thread python/vibap/cli.py Fixed
Comment thread python/vibap/cli.py Fixed
Comment thread python/vibap/personal_hub.py Fixed
Comment thread python/vibap/run_bridge.py Fixed
Comment thread python/vibap/kernel_correlation.py Fixed
Comment thread python/vibap/run_bridge.py Fixed
Comment thread python/vibap/run_bridge.py Fixed
Comment thread go/cmd/ardur-kernelcaptured/main.go Fixed
Comment thread python/tests/test_bpf_lower.py Fixed
Comment thread python/tests/test_bpf_lower.py Fixed
Comment thread python/tests/test_bpf_lower.py Fixed
Comment thread python/vibap/bpf_lower.py Fixed
Comment thread python/vibap/bpf_lower.py Fixed
Comment thread go/cmd/ardur-kernelcaptured/daemon_enforce.go Fixed
Comment thread python/vibap/run_bridge.py Fixed
Comment thread docs/demo/enforce-e2e/agent.py Fixed
Comment thread python/tests/test_default_home_lazy_import.py Fixed
Comment thread python/tests/test_verify_output_flag.py Fixed
…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
Comment thread python/tests/test_unknown_verdict.py Fixed
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
CodeQL py/unused-import alerts #364, #365, #366 flagged three test
files importing pytest without using it. Remove the unused imports;
no behavioral change.
…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
Comment thread python/tests/test_process_lifecycle_evidence.py Fixed
Comment thread python/tests/test_process_lifecycle_evidence.py Fixed
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)
CodeQL alerts #367 and #368 flagged unused imports of 'sys' and 'pytest'
in test_process_lifecycle_evidence.py. Neither symbol is referenced anywhere
in the file. Removed both imports; all 46 tests pass.
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.
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.

3 participants