Step 25 (S2): audit log view and export #38
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
PLAN step 25: authorized users can search and page through audit events and export them from the web, API, CLI and MCP, including rejected attempts. This is a security surface, so it runs on Sol. The owner approved starting S2 before step 16's perf numbers exist (2026-09-25).
Starting step 25 on branch
audit-logfrom basedbd66850f8a5d6190e65b4bd364e075950033425. Scope: audit query, API/export, CLI, MCP, and audit-log web page. I will commit the contract before code and report gate output here.Starting step 25 on branch
audit-logfrom basedbd66850f8a5d6190e65b4bd364e075950033425. Scope: audit query, API/export, CLI, MCP, and audit-log web page. I will commit the contract before code and report gate output here.Contract committed on
audit-log:docs/contracts.md§4.1 specifiesaudit:read, administrator/all vs human/own-user vs AI agent/own-token visibility, exact filters, stable keyset cursor, bounded streamed exports, export audit events, and read-time detail sanitization. ExistingScope::AuditReadis already in the scope registry. Base:dbd6685.Findings from the base head:
Scope::AuditReadalready exists incrates/proto/src/permissions.rs;audit_recordshas an integer primary key anddetails_jsonfrom migration 0014, but no read API or paging indexes. Stream OPEN details are stored throughaudit_stream_open; the new read path discards unknown detail keys. Migration 0015 adds principal, time, action, outcome, and request-id indexes. Query and schema code are committed asaec9f40; endpoint and client wiring is in progress.Implementation heads:
aec9f40(schema, query, migration 0015, benchmark),bea4973(authorized API/export and generated OpenAPI/client),7f1f176(CLI/MCP),3acb53d(web page). Focusedcargo test -p infraternal-server --test audit_http -- --nocapturepassed twice, including scope matrix, redaction, export audit and stable pagination while new rows are inserted.bun run --cwd packages/web checkreports zero errors and warnings. Full gates are next; current load5 exceeds the requested integration/browser start threshold.The first full
fastgate reached workspace tests and exposed three migration fixture assertions fixed at versions 1–14. Diagnosticcargo test --workspaceshowed each fixture upgraded correctly through new migration 0015 and failed only because the expected version vector stopped at 14 (crates/server/tests/migrations.rs:161,197,246). I updated those expectations to 15 and am rerunning the migration test and full gate. This was a deterministic test update, not a load-sensitive flake.df502fepassesscripts/verify fast(verbatim output):Integration and browser remain; waiting for load5 below 8 per the job rule.
First
scripts/verify integrationpassed release build, HTTP, Docker/Podman sockets, engine adapters, bounded log snapshots, TypeScript stream, stream authorization/CLOSE regressions, persistent PTY termination, and resource HTTP. It stopped at the compiled CLI/MCP test's fixed tool-name set: actual set includedsearch_audit, expected set did not (crates/infraternal/tests/cli_mcp.rs:827). This is deterministic. Commitca7f217updates that fixture and adds a real compiled CLI CSV export plus an MCP audit-search request withaudit:read; targeted and full integration reruns are pending the load threshold.The updated real compiled CLI/MCP test passes on
ca7f217:cargo test -p infraternal --test cli_mcp -- --ignored --nocapture --test-threads=1→test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 137.38s. It now checksinfraternal audit --csvagainst the real server andsearch_auditthrough MCP using anai_agenttoken withaudit:read, with empty results for a human-only event. Full integration rerun remains queued behind another job's browser/release run and the load5 threshold.Final-head
scripts/verify fastonca7f217passed all steps (verbatim output):Performance evidence gap for step 25: the 1M-record page benchmark is committed at
crates/server/benches/audit.rsand compiled by fast/Clippy. The repo contract requires reportable numbers from the perf-test VM through theperf-test-vmskill, but that skill and VM connection are absent in this job environment (searched available skill roots and.claude/skills). Also,docs/PLAN.mdhas no audit-page latency row to compare p50/p99 against; its 20 ms API p99 budget is explicitly for listing 500 containers. I have requested the perf VM/skill location and will not present dev-VM timing as reportable evidence.Integration gate on ca7f217 failed after passing release build, real HTTP, Docker/Podman, bounded logs, TS streaming, stream authorization, persistent PTY termination, and resource HTTP. Its existing CLI/MCP test stopped at crates/infraternal/tests/cli_mcp.rs:2366, before the new MCP audit assertions:
FAIL integration: compiled CLI and MCP against real server and engines
remote stty size should receive the SIGWINCH resize: [... "24 80\r\n24 80\r\n"]
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 99.55s
As requested for timing failures, I reran that single test once directly on the same head:
cargo test -p infraternal --test cli_mcp -- --ignored --nocapture --test-threads=1
remote stty size should receive the SIGWINCH resize: [... "24 80\r\n24 80\r\n"]
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 102.50s
An earlier direct run of this test on ca7f217 passed (1 passed; 0 failed; finished in 137.38s). The audit change does not edit the SSH resize assertion or its helper. Full logs: /mnt/hdd/infraternal/artifacts/s2-audit/verify-integration-final.log and /mnt/hdd/infraternal/artifacts/s2-audit/cli-mcp-flake-rerun.log. Integration remains red; I will not call it green.
Step 25 implementation is committed on audit-log at ca7f21753ddce298c7e8b060f68513f7da7e24c3 (base
dbd6685). No push. Contract, query/index/keyset cursor, redaction, authorization, streamed exports, API, CLI, MCP, web page, tests, and 1M-row benchmark harness are in the branch.Final-head fast gate output (verbatim):
PASS fast: migrations are append-only
PASS fast: workspace package dependencies
PASS fast: JavaScript dependencies
PASS fast: build web app
PASS fast: cargo fmt --check
PASS fast: cargo clippy
PASS fast: cargo test
PASS fast: svelte-check
PASS fast: UI package svelte-check
PASS fast: stream package typecheck
PASS fast: Vitest
PASS fast: UI package Vitest
PASS fast: stream package Vitest
PASS fast: OpenAPI and TypeScript client drift
PASS fast: terminal TypeScript
PASS fast: terminal Vitest
Integration gate output at the failing step (verbatim):
FAIL integration: compiled CLI and MCP against real server and engines
remote stty size should receive the SIGWINCH resize: [87, 97, 114, 110, 105, 110, 103, 58, 32, 116, 104, 101, 32, 79, 83, 32, 107, 101, 121, 99, 104, 97, 105, 110, 32, 105, 115, 32, 117, 110, 97, 118, 97, 105, 108, 97, 98, 108, 101, 59, 32, 117, 115, 105, 110, 103, 32, 97, 32, 112, 101, 114, 109, 105, 115, 115, 105, 111, 110, 45, 114, 101, 115, 116, 114, 105, 99, 116, 101, 100, 32, 99, 114, 101, 100, 101, 110, 116, 105, 97, 108, 32, 102, 105, 108, 101, 46, 13, 10, 50, 52, 32, 56, 48, 13, 10, 50, 52, 32, 56, 48, 13, 10]
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 99.55s
The direct single-test retry failed at the same assertion (102.50s). Both outputs and the earlier passing targeted run are in the preceding issue comment. Full log: /mnt/hdd/infraternal/artifacts/s2-audit/verify-integration-final.log.
Browser gate output at the failing step (verbatim):
PASS browser: JavaScript dependencies
PASS browser: install Chromium and system dependencies
PASS browser: terminal fixture Playwright
PASS browser: build web app
PASS browser: build release binary
FAIL browser: Playwright against release server
error: expect(locator).toBeHidden() failed
Locator: getByRole('button', { name: 'Jump to latest' })
Expected: hidden
Received: visible
Timeout: 5000ms
This is scripts/browser-check.mjs:1391 in the existing log-view check, before the audit route screenshots. Full log: /mnt/hdd/infraternal/artifacts/s2-audit/verify-browser.log.
Focused Playwright check against the production binary passed:
PASS audit route 1440x900: loaded, controls visible, no overflow
PASS audit route 390x844: loaded, controls visible, no overflow
PASS audit search empty state
Screenshots: /mnt/hdd/infraternal/artifacts/s2-audit/audit-1440x900.png and /mnt/hdd/infraternal/artifacts/s2-audit/audit-390x844.png. I inspected both; no clipping or overlap in the visible area.
Still required before merge: resolve or accept the unrelated SSH resize and log-view gate failures, then rerun the gates; run the 1M-event page-query benchmark on the perf-test VM and report p50/p99. The perf-test-vm skill/host details are unavailable in this job environment, and PLAN.md does not give an audit-query-specific latency target. I have not substituted dev-VM numbers.
UI rules applied from emil-design-eng and the better-interface / better-ui / better-layout / better-typography / better-colors / better-accessibility / better-writing skills: reused shared shadcn-svelte buttons, inputs, select, card, empty state, sheet, and VirtualTable; used existing color/type/spacing tokens; kept the filter grid responsive to its container; provided accessible names for controls, keyboard-openable rows, visible focus via primitives, and live status/error text; used short, factual loading/empty/error/export copy. The page adds no animation. Focused real-browser screenshots at 1440x900 and 390x844 were visually inspected with no visible clipping or overlap.
Independent review-25 started on audit-log ca7f217, base dev
dbd6685. Read-only review; evidence and verdict will be posted here.Review findings with evidence so far:
crates/infraternal/src/mcp.rsexposessearch_audit(lines 473-503) but no export tool or call toaudit_export; step 25's MCP export goal is unmet.crates/server/src/lib.rsconstructs rejected-request audit actions from the raw URL path (lines 523-526). A caller can place token or setup material in a rejected path and persist it in the unredactedactionfield returned by audit search/export.crates/server/src/audit.rsuses SHA-256 of public filter and visibility inputs as its cursor fingerprint (lines 107-122), then accepts decoded JSON bounds (lines 167-189). It is reproducible, so callers can forge cursor filter/principal bindings and bounds, though SQL visibility still limits returned rows.audit_httpfail at line 164 (own_unattributed.records.is_empty()); changing keyset< beforeto<= beforemade it fail at line 295 (10 seen versus 18 baseline). Both required tests detect their corresponding regression.Further query-plan, UI, benchmark, and dev-only log-view checks are in progress.
The
Jump to latestdiagnosis ondevdbd6685is complete. I built its production web assets and release binary in the throwaway worktree, served the real binary with a fresh database, and ran a focused Playwright check with a unique Docker log fixture. The exact Jump assertion passed, and the original fullcheckLogControlsfunction also passed. No audit diff touches the log-view component or browser assertion. The prior failure is not a deterministic dev regression; load/timing flake is the likely classification, though one successful run cannot rule out an intermittent dev race.Additional UI evidence: the supplied 1440×900 audit screenshot clips the time value (
9/25/2026, 9:16:23 ...) on every row.Card.Rootadds vertical padding and its own frame aroundVirtualTable, which already provides a framed surface, leaving blank space above the header. The repo has no shadcn date/time picker; native date-time inputs are acceptable. A production asset static-import graph measured with NodegzipSyncis 116,842 bytes for the dashboard path and 149,047 bytes for a cold audit route, so the latter exceeds the 120 KiB first-load budget pending browser transfer confirmation. The benchmark started when load5 was 7.59.Independent review-25 finished at head ca7f21753ddce298c7e8b060f68513f7da7e24c3 (base
dbd66850f8). Verdict: REQUEST CHANGES. Full findings: /mnt/hdd/infraternal/jobs/review-25/findings.md.Blocking findings:
search_auditbut no audit export tool (crates/infraternal/src/mcp.rs:473-503), so step 25's MCP export goal is unmet.action(crates/server/src/lib.rs:520-527); a credential-like value in a rejected path is returned unchanged by page/export despite the details allowlist.crates/server/src/audit.rs:114-128,172-190). SQL still enforces visibility.json_eachscan without a target index.EXPLAIN QUERY PLANshows rowid scan plusSCAN json_each EXISTS VIRTUAL TABLE INDEX 1:(crates/server/src/storage/audit.rs:69-75, migration 0015).Confirmed: effective
audit:readand principal visibility are enforced in SQL for page/export, with CLI/MCP using the same API; no-scope AI agent tokens are forbidden; accepted and rejected exports are audited; details are allowlisted on reads; CSV quoting/formula prefixes and bound SQL inputs are in place. The throwaway mutation tests failed without own-user authorization and strict< beforekeyset bounds, at audit_http.rs:164 and :295 respectively. The throwaway worktree was removed. A focusedJump to latestassertion and the original full log-controls function passed against productiondevdbd6685; the prior failure is not a deterministic dev regression and is likely timing/load-related.scripts/verify fastoutput:Audit benchmark started at load5=7.59. Harness output (dev VM, not the perf-test VM):
PLAN has no audit-page budget. Its 20 ms p99 container-list budget is a different workload, so the 4.003 ms audit p99 cannot be used as an audit acceptance gate. These are not perf-test VM A/B numbers.
fix-25 started on branch audit-log at base head ca7f21753ddce298c7e8b060f68513f7da7e24c3. Review findings: /mnt/hdd/infraternal/jobs/review-25/findings.md. Merging current dev before fixes.
fix-25 findings and decisions: rejected requests now store a fixed action; the audit read boundary redacts legacy unknown actions before page/export serialization. The existing owner-only stream signing key derives a separate HMAC key for cursor authentication. Migration 0015 backfills an indexed audit_targets relation and uses an insert trigger so every writer populates it. Targeted audit HTTP tests passed 6/6, including cursor tampering, a rejected-path sentinel, index use, migration backfill, and invalid input; the final registered-action assertion is being rerun. MCP export uses a bounded server export page (50 rows, 256 KiB) with an authenticated continuation cursor. The first fast run passed through web build and formatting, then Clippy reported an export-handler length lint; the ordering is now documented and the gate will be rerun.
Regression proof on fix-25: with only legacy-action redaction temporarily disabled,
rejected_paths_and_legacy_actions_never_leave_the_read_boundaryfailed because the page contained the sentinel. With only cursor MAC verification disabled,cursor_mac_rejects_rebound_filters_principals_and_high_waterfailed because a forged cursor returned a page instead ofinvalid_request. With onlyaudit_targets_target_pageremoved from migration 0015,exact_target_query_uses_index_and_trigger_populates_itfailed itsEXPLAIN QUERY PLANindex assertion. All mutations were restored. The clean targeted suite then passed: 6 passed, 0 failed.fix-25 implementation checkpoint: 8fa0f46 committed on audit-log. Targeted audit HTTP suite: 6 passed, 0 failed. Mutation proof for legacy-action redaction, cursor MAC and target index is recorded above. The first complete fast run passed Clippy, then the unrelated engine global-allocation test failed under parallel crate tests; the exact test passed on a direct rerun. A serialized fast gate is running. UI/browser measurement edits are in progress.
Fast-gate finding:
server_startupfailed because the first gzip implementation compressed all JavaScript synchronously inServer::open, delaying the protected setup banner beyond that test's 500 ms window. The failure reproduced directly. I removed startup compression and madescripts/build-webembed precompressed.js.gzassets, so static responses can send actual gzip bytes without request or startup compression. This is being retested. The earlier engine allocation failure passed its direct rerun.fix-25 fast gate at e5b4ccc (run with RUST_TEST_THREADS=1 because the engine global allocator test failed under parallel crate tests and passed directly):
PASS fast: migrations are append-only
PASS fast: workspace package dependencies
PASS fast: JavaScript dependencies
PASS fast: build web app
PASS fast: cargo fmt --check
PASS fast: cargo clippy
PASS fast: cargo test
PASS fast: svelte-check
PASS fast: UI package svelte-check
PASS fast: stream package typecheck
PASS fast: Vitest
PASS fast: UI package Vitest
PASS fast: stream package Vitest
PASS fast: OpenAPI and TypeScript client drift
PASS fast: terminal TypeScript
PASS fast: terminal Vitest
Additional security review and regression proof at 4cada62: a cursor for one
users:manageadministrator was previously reusable by another because both hadAllvisibility. The cursor fingerprint now includes the exact token id. The new same-visibility administrator test passes; removing only the principal binding made it fail because a page was returned whereinvalid_requestwas required. A direct storage assertion now checks that rejected URI segments never reachaudit_records.action; temporarily restoring a raw rejected path made that assertion fail (stored count 1 versus 0). Both mutations were restored, and the complete audit HTTP suite passed 6/6.fix-25 gate scheduling: the branch is committed and clean at b468879. The last green
scripts/verify fastpreceded the exact-token cursor andVaryfollow-ups; focused audit HTTP tests passed afterward. Final fast, integration, browser and 1M benchmark are queued because other jobs' concurrent Rust builds and Podman tests have kept load5 above the required <8 threshold (currently 13.73). No other jobs' processes or files have been touched.Latest fast gate at abfd520 (RUST_TEST_THREADS=1 to avoid the engine global allocator test's parallel interference):
WARN load5=11.52 exceeds online CPU count=8; timing-sensitive checks may be delayed
PASS fast: migrations are append-only
PASS fast: workspace package dependencies
PASS fast: JavaScript dependencies
PASS fast: build web app
PASS fast: cargo fmt --check
PASS fast: cargo clippy
PASS fast: cargo test
PASS fast: svelte-check
PASS fast: UI package svelte-check
PASS fast: stream package typecheck
PASS fast: Vitest
PASS fast: UI package Vitest
PASS fast: stream package Vitest
PASS fast: OpenAPI and TypeScript client drift
PASS fast: terminal TypeScript
PASS fast: terminal Vitest
fix-25 one-million-row audit benchmark on the dev VM, not the perf-test VM (no A/B claim). Command:
cargo bench -p infraternal-server --bench audit -- --quick --noplot. Verbatim measured output:METRIC audit target-only 1M dev VM, not the perf-test VM p50=463us p99=2838us
METRIC audit sparse scope/action 1M dev VM, not the perf-test VM p50=760us p99=3669us
METRIC audit page 1M dev VM, not the perf-test VM p50=524us p99=3982us
First
scripts/verify integrationat abfd520 stopped in release compilation. Verbatim gate output:PASS integration: JavaScript dependencies
PASS integration: build web app
FAIL integration: build release binary
Compiling infraternal-server v0.0.1 (/home/kayg/wt/audit-log/crates/server)
error[E0432]: unresolved imports
infraternal_proto::AuditFilters,infraternal_proto::AuditPage,infraternal_proto::AuditRecord--> crates/server/src/audit.rs:18:5
|
18 | AuditFilters, AuditPage, AuditRecord, ErrorCode, RequestId, Scope, TokenKind,
| ^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^ no
AuditRecordin the root| | |
| | no
AuditPagein the root| no
AuditFiltersin the rooterror[E0432]: unresolved imports
infraternal_proto::AuditFilters,infraternal_proto::AuditRecord--> crates/server/src/storage/audit.rs:4:25
|
4 | use infraternal_proto::{AuditFilters, AuditRecord};
| ^^^^^^^^^^^^ ^^^^^^^^^^^ no
AuditRecordin the root| |
| no
AuditFiltersin the rooterror[E0432]: unresolved imports
infraternal_proto::AuditFilters,infraternal_proto::AuditPage,infraternal_proto::AuditRecord--> crates/server/src/lib.rs:38:22
|
38 | ApiErrorDetails, AuditFilters, AuditPage, AuditRecord, CloseSessionResponse,
| ^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^ no
AuditRecordin the root| | |
| | no
AuditPagein the root| no
AuditFiltersin the rootFor more information about this error, try
rustc --explain E0432.error: could not compile
infraternal-server(lib) due to 3 previous errorsDiagnosis:
crates/proto/src/lib.rsexportsAuditFilters,AuditPage, andAuditRecord, and the debug fast gate compiled the same source. Release cache artifacts in this worktree predated this branch's proto surface. I removed only this worktree's releaseinfraternal-protoartifacts withcargo clean -p infraternal-proto --release(14 files, 28.0 MiB), then will rerun the gate when load5 < 8.Second
scripts/verify integrationat abfd520 stopped in a Podman stream regression after release build, real HTTP, Docker/rootless Podman pings, engine adapters, bounded log snapshots, and TypeScript stream client passed. Verbatim gate output:PASS integration: JavaScript dependencies
PASS integration: build web app
PASS integration: build release binary
PASS integration: real HTTP behavior
PASS integration: Docker socket _ping
PASS integration: rootless Podman socket _ping
PASS integration: engine adapters against Docker and Podman
PASS integration: bounded follow:false log snapshots against Docker and rootless Podman
PASS integration: TypeScript stream client against Docker and Podman
FAIL integration: stream authorization and CLOSE regressions against Docker
Compiling infraternal-server v0.0.1 (/home/kayg/wt/audit-log/crates/server)
Finished
testprofile [unoptimized] target(s) in 3.09sRunning tests/stream_regressions.rs (target/debug/deps/stream_regressions-53fd2437b4851c58)
running 12 tests
test authorization_loss_terminates_detached_persistent_exec_process ... ok
test authorization_loss_terminates_persistent_exec_process ... ok
test authorization_loss_terminates_stalled_stdin_on_both_engines ... docker stalled stdin CLOSE forbidden in 25.745854ms
podman stalled stdin CLOSE forbidden in 59.356762ms
ok
test client_data_written_after_grant_commit_never_reaches_exec ...
thread 'client_data_written_after_grant_commit_never_reaches_exec' (572162) panicked at crates/server/tests/stream_regressions.rs:1555:13:
podman exec did not consume pre-commit input
note: run with
RUST_BACKTRACE=1environment variable to display a backtraceFAILED
test events_channel_replies_to_client_close ... ok
test every_grant_shrink_closes_logs_and_persistent_exec_on_both_engines ... docker role_change both CLOSE forbidden in 72.180696ms
docker role_change owner process reaped in 541.229774ms
docker role_grant_removed both CLOSE forbidden in 44.338391ms
docker role_grant_removed owner process reaped in 105.585764ms
docker role_grant_removed_then_restored both CLOSE forbidden in 71.12536ms
docker transient shrink had an active log stream before mutation and delivered 3 DATA frames after commit before CLOSE
docker role_grant_removed_then_restored owner process reaped in 431.718142ms
docker token_grant_removed both CLOSE forbidden in 50.58611ms
docker token_grant_removed owner process reaped in 402.812724ms
docker tag_change both CLOSE forbidden in 3.630128ms
docker tag_change owner process reaped in 558.434827ms
docker user_disabled both CLOSE forbidden in 5.196778ms
docker user_disabled owner process reaped in 74.697406ms
docker token_revoked both CLOSE forbidden in 39.100439ms
docker token_revoked owner process reaped in 466.973651ms
docker token_expired both CLOSE forbidden in 3.267638ms
docker token_expired owner process reaped in 518.254405ms
podman role_change both CLOSE forbidden in 53.203891ms
podman role_change owner process reaped in 325.150625ms
podman role_grant_removed both CLOSE forbidden in 32.836478ms
podman role_grant_removed owner process reaped in 1.163885718s
podman role_grant_removed_then_restored both CLOSE forbidden in 145.836668ms
podman transient shrink had an active log stream before mutation and delivered 3 DATA frames after commit before CLOSE
podman role_grant_removed_then_restored owner process reaped in 1.319294635s
podman token_grant_removed both CLOSE forbidden in 4.862526ms
podman token_grant_removed owner process reaped in 752.908317ms
podman tag_change both CLOSE forbidden in 44.127497ms
podman tag_change owner process reaped in 1.436600596s
podman user_disabled both CLOSE forbidden in 66.862005ms
podman user_disabled owner process reaped in 1.005274213s
podman token_revoked both CLOSE forbidden in 79.112462ms
podman token_revoked owner process reaped in 840.62986ms
podman token_expired both CLOSE forbidden in 24.731309ms
podman token_expired owner process reaped in 1.089205854s
ok
test failed_dispatch_commit_never_leaves_a_persistent_exec ... ok
test failed_final_open_audit_terminates_new_persistent_exec ... ok
test logs_channel_replies_to_client_close ... ok
test logs_channel_replies_to_close_while_waiting_for_credit ... ok
test removing_a_host_tag_closes_an_existing_channel_with_forbidden ... ok
test session_http_lists_only_the_owner_and_closes_real_docker_and_podman_ptys ... ok
failures:
failures:
client_data_written_after_grant_commit_never_reaches_exec
test result: FAILED. 11 passed; 1 failed; 0 ignored; 0 measured; 7 filtered out; finished in 123.20s
error: test failed, to rerun pass
-p infraternal-server --test stream_regressionsDirect rerun of the single failing Podman stream test, after the integration gate failure above, passed without source changes. Command:
cargo test -p infraternal-server --test stream_regressions client_data_written_after_grant_commit_never_reaches_exec -- --ignored --nocapture --test-threads=1. Verbatim output:Finished
testprofile [unoptimized] target(s) in 1.05sRunning tests/stream_regressions.rs (target/debug/deps/stream_regressions-53fd2437b4851c58)
running 1 test
test client_data_written_after_grant_commit_never_reaches_exec ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 18 filtered out; finished in 15.25s
Third
scripts/verify integrationat abfd520 stopped on the known Podman exec cleanup flake (#42) after release build, real HTTP, Docker/rootless Podman pings, and ten other engine adapter tests passed. Verbatim gate output:PASS integration: JavaScript dependencies
PASS integration: build web app
PASS integration: build release binary
PASS integration: real HTTP behavior
PASS integration: Docker socket _ping
PASS integration: rootless Podman socket _ping
FAIL integration: engine adapters against Docker and Podman
Finished
testprofile [unoptimized] target(s) in 0.20sRunning tests/integration.rs (target/debug/deps/integration-f92617287b4ea6a8)
running 11 tests
test docker_and_podman_share_the_real_engine_contract ... infraternal-engine-foreign-docker-713882-1790331418852-0
infraternal-engine-foreign-docker-713882-1790331418852-1
infraternal-engine-foreign-docker-713882-1790331418852-2
time="2026-09-25T12:17:44+02:00" level=warning msg="StopSignal SIGTERM failed to stop container infraternal-engine-foreign-podman-713882-1790331418852-0 in 10 seconds, resorting to SIGKILL"
infraternal-engine-foreign-podman-713882-1790331418852-0
time="2026-09-25T12:17:54+02:00" level=warning msg="StopSignal SIGTERM failed to stop container infraternal-engine-foreign-podman-713882-1790331418852-1 in 10 seconds, resorting to SIGKILL"
infraternal-engine-foreign-podman-713882-1790331418852-1
time="2026-09-25T12:18:05+02:00" level=warning msg="StopSignal SIGTERM failed to stop container infraternal-engine-foreign-podman-713882-1790331418852-2 in 10 seconds, resorting to SIGKILL"
infraternal-engine-foreign-podman-713882-1790331418852-2
ok
test list_preserves_health_and_pod_identity_on_all_real_engines ... ok
test missing_container_scan_tools_report_unconfirmed_when_host_proc_is_restricted ... ok
test podman_completed_containers_are_safe_for_inventory_and_mutations ... ok
test podman_model_preserves_health_and_pod_identity ... ok
test podman_mutation_response_loss_is_unknown_outcome ... ok
test pty_close_reaps_setsid_and_double_fork_descendants ... ok
test pty_close_reaps_term_ignoring_group_child_after_leader_exits ... docker same-group child reaped in 537.156193ms
podman same-group child reaped in 1.338211464s
ok
test pty_session_drop_and_close_terminate_exec_processes_on_all_real_engines ...
thread 'pty_session_drop_and_close_terminate_exec_processes_on_all_real_engines' (726024) panicked at crates/engine/tests/integration.rs:875:5:
container shell after drop pid 17 remained in process table: PID PPID COMMAND
1 0 sh -c printf 'stdout-line\n'; printf 'stderr-line\n' >&2; i=0; while [ $i -lt 65600 ]; do printf x; i=$((i+1)); done; printf '\n'; i=0; while [ $i -lt 65600 ]; do printf y >&2; i=$((i+1)); done; printf '\n' >&2; while :; do sleep 1; done
17 0 /bin/sh -c (while :; do sleep 1; done) & helper=$!; echo pty-marker=infraternal_pty_cleanup_713882-1790331591062_podman shell=
helper=$helper; wait23 17 /bin/sh -c (while :; do sleep 1; done) & helper=$!; echo pty-marker=infraternal_pty_cleanup_713882-1790331591062_podman shell=
helper=$helper; wait446 0 ps -o pid,ppid,args
note: run with
RUST_BACKTRACE=1environment variable to display a backtraceFAILED
test rootful_podman_covers_inventory_and_mutations ... ok
test stalled_pty_stdin_cannot_hold_exec_termination ... docker stalled stdin + ignored SIGTERM reaped in 547.226546ms
podman stalled stdin + ignored SIGTERM reaped in 1.125295841s
ok
failures:
failures:
pty_session_drop_and_close_terminate_exec_processes_on_all_real_engines
test result: FAILED. 10 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 243.84s
error: test failed, to rerun pass
-p infraternal-engine --test integrationDirect rerun of known Podman cleanup flake also failed (same lingering shell):
Finished
testprofile [unoptimized] target(s) in 0.25sRunning tests/integration.rs (target/debug/deps/integration-f92617287b4ea6a8)
running 1 test
test pty_session_drop_and_close_terminate_exec_processes_on_all_real_engines ...
thread 'pty_session_drop_and_close_terminate_exec_processes_on_all_real_engines' (734980) panicked at crates/engine/tests/integration.rs:875:5:
container shell after drop pid 18 remained in process table: PID PPID COMMAND
1 0 sh -c printf 'stdout-line\n'; printf 'stderr-line\n' >&2; i=0; while [ $i -lt 65600 ]; do printf x; i=$((i+1)); done; printf '\n'; i=0; while [ $i -lt 65600 ]; do printf y >&2; i=$((i+1)); done; printf '\n' >&2; while :; do sleep 1; done
18 0 /bin/sh -c (while :; do sleep 1; done) & helper=$!; echo pty-marker=infraternal_pty_cleanup_734978-1790331679881_podman shell=
helper=$helper; wait24 18 /bin/sh -c (while :; do sleep 1; done) & helper=$!; echo pty-marker=infraternal_pty_cleanup_734978-1790331679881_podman shell=
helper=$helper; wait497 0 ps -o pid,ppid,args
note: run with
RUST_BACKTRACE=1environment variable to display a backtraceFAILED
failures:
failures:
pty_session_drop_and_close_terminate_exec_processes_on_all_real_engines
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 10 filtered out; finished in 56.51s
error: test failed, to rerun pass
-p infraternal-engine --test integrationStandalone CLI/MCP integration attempt reached the known PTY exit flake (#37):
Compiling infraternal-server v0.0.1 (/home/kayg/wt/audit-log/crates/server)
Compiling infraternal v0.0.1 (/home/kayg/wt/audit-log/crates/infraternal)
Finished
testprofile [unoptimized] target(s) in 20.14sRunning tests/cli_mcp.rs (target/debug/deps/cli_mcp-94557349a527577f)
running 1 test
test cli_and_mcp_use_the_public_http_contract ...
thread 'cli_and_mcp_use_the_public_http_contract' (745378) panicked at crates/infraternal/tests/cli_mcp.rs:3090:5:
PTY harness failed: Traceback (most recent call last):
File "", line 106, in
raise RuntimeError('compiled CLI did not exit: ' + output)
RuntimeError: compiled CLI did not exit: Warning: the OS keychain is unavailable; using a permission-restricted credential file.
Session s_01M3C1EDHCRVY0JRSNJRYT7NZM
[?2004hbash-5.2$
[K
bash-5.2$ stty size; printf 'CLI_SSH_COMMAND_OK\n'
[?2004l
41 111
CLI_SSH_COMMAND_OK
[?2004hbash-5.2$ exit 37
[?2004l
exit
note: run with
RUST_BACKTRACE=1environment variable to display a backtraceFAILED
failures:
failures:
cli_and_mcp_use_the_public_http_contract
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 29.98s
error: test failed, to rerun pass
-p infraternal --test cli_mcpDirect rerun of CLI/MCP integration also failed at the known PTY exit flake (#37), after audit export assertions passed:
Finished
testprofile [unoptimized] target(s) in 0.32sRunning tests/cli_mcp.rs (target/debug/deps/cli_mcp-94557349a527577f)
running 1 test
test cli_and_mcp_use_the_public_http_contract ...
thread 'cli_and_mcp_use_the_public_http_contract' (747062) panicked at crates/infraternal/tests/cli_mcp.rs:3090:5:
PTY harness failed: Traceback (most recent call last):
File "", line 106, in
raise RuntimeError('compiled CLI did not exit: ' + output)
RuntimeError: compiled CLI did not exit: Warning: the OS keychain is unavailable; using a permission-restricted credential file.
Session s_01M3C1FKWRRB9BMBQSMNAVPAYV
[?2004hbash-5.2$ printf 'CLI_SSH_REPLAY_BEFORE\n'; sleep 5; printf 'CLI_SSH_REPLAY
Y_AFTER\n'; exit 17
[?2004l
CLI_SSH_REPLAY_BEFORE
CLI_SSH_REPLAY_AFTER
exit
note: run with
RUST_BACKTRACE=1environment variable to display a backtraceFAILED
failures:
failures:
cli_and_mcp_use_the_public_http_contract
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 31.73s
error: test failed, to rerun pass
-p infraternal --test cli_mcpFirst production browser gate failed its dashboard transferred-byte assertion; gzip body remained below the existing 120 KiB limit. Optimizing audit cold route and preserving the dashboard gzip threshold while reporting actual transfer bytes:
PASS browser: JavaScript dependencies
PASS browser: install Chromium and system dependencies
PASS browser: terminal fixture Playwright
PASS browser: build web app
PASS browser: build release binary
FAIL browser: Playwright against release server
curl: (7) Failed to connect to 127.0.0.1 port 32209 after 0 ms: Could not connect to server
METRIC container-detail JS gzip before terminal: 221268 bytes
METRIC container action focus: {"focused":true,"activeElement":"<button data-slot="button" class="focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 border bor","disabled":false,"connected":true,"tabIndex":0,"display":"flex","visibility":"visible","rowKey":"h_01M3C21BD5RNJMKGGVETB9H1EV/docker/4978fe70bf1b44e2ca2a4369d20e0fd55b591f9bd6dfc3cf73adea0c71f4970a","visibilityState":"visible"}
METRIC terminal DATA/CREDIT accounting: {"storedOffset":18,"replayStart":0,"outputOffset":18,"dataBytes":18,"creditBytes":18,"expectedOffset":18}
METRIC Ghostty light terminal colors: {"tokenBackground":"#f5f7fa","expectedBackground":[245,247,250,255],"backgroundPixel":[245,247,250,255],"hostBackground":"rgb(245, 247, 250)","hostBackgroundPixel":[245,247,250,255],"tokenForeground":"#17212b","expectedForeground":[23,33,43],"glyphForeground":[24,34,44],"foregroundDistance":1.7320508075688772}
METRIC Ghostty light terminal colors: {"tokenBackground":"#f5f7fa","expectedBackground":[245,247,250,255],"backgroundPixel":[245,247,250,255],"hostBackground":"rgb(245, 247, 250)","hostBackgroundPixel":[245,247,250,255],"tokenForeground":"#17212b","expectedForeground":[23,33,43],"glyphForeground":[24,34,44],"foregroundDistance":1.7320508075688772}
METRIC Ghostty dark terminal colors: {"tokenBackground":"#11161c","expectedBackground":[17,22,28,255],"backgroundPixel":[17,22,28,255],"hostBackground":"rgb(17, 22, 28)","hostBackgroundPixel":[17,22,28,255],"tokenForeground":"#e9eef4","expectedForeground":[233,238,244],"glyphForeground":[232,237,243],"foregroundDistance":1.7320508075688772}
METRIC Ghostty dark terminal colors: {"tokenBackground":"#11161c","expectedBackground":[17,22,28,255],"backgroundPixel":[17,22,28,255],"hostBackground":"rgb(17, 22, 28)","hostBackgroundPixel":[17,22,28,255],"tokenForeground":"#e9eef4","expectedForeground":[233,238,244],"glyphForeground":[232,237,243],"foregroundDistance":1.7320508075688772}
METRIC terminal reattach DATA/CREDIT accounting: {"storedOffset":242,"replayStart":211,"dataBytes":31,"creditBytes":31,"expectedOffset":242}
METRIC lazy terminal JS gzip: 192469 bytes
METRIC route JS gzip after terminal: 413737 bytes
METRIC initial route JS gzip: 117953 bytes
METRIC dashboard first-load JS transferred: 125527 bytes
2054 | if (scriptSizes.size === 0) throw new Error("initial route JavaScript responses were not captured on the cold dashboard load");
2055 | initialRouteJsGzip = [...scriptSizes.values()].reduce((sum, size) => sum + size, 0);
2056 | console.log(
METRIC initial route JS gzip: ${initialRouteJsGzip} bytes);2057 | const dashboardTransferred = await actualJavaScriptBytes(browserPage);
2058 | console.log(
METRIC dashboard first-load JS transferred: ${dashboardTransferred} bytes);2059 | if (dashboardTransferred === 0 || dashboardTransferred > 120 * 1024) throw new Error(
dashboard first-load transferred JS exceeds 120 KiB or was not captured: ${dashboardTransferred});^
error: dashboard first-load transferred JS exceeds 120 KiB or was not captured: 125527
at /home/kayg/wt/audit-log/scripts/browser-check.mjs:2059:88
Bun v1.4.2 (Linux x64)
Fast gate after the audit cold-route trim at 562baec:
PASS fast: migrations are append-only
PASS fast: workspace package dependencies
PASS fast: JavaScript dependencies
PASS fast: build web app
PASS fast: cargo fmt --check
PASS fast: cargo clippy
PASS fast: cargo test
PASS fast: svelte-check
PASS fast: UI package svelte-check
PASS fast: stream package typecheck
PASS fast: Vitest
PASS fast: UI package Vitest
PASS fast: stream package Vitest
PASS fast: OpenAPI and TypeScript client drift
PASS fast: terminal TypeScript
PASS fast: terminal Vitest
Second production browser gate reached the known Jump to latest flake; direct Playwright rerun follows:
PASS browser: JavaScript dependencies
PASS browser: install Chromium and system dependencies
PASS browser: terminal fixture Playwright
PASS browser: build web app
PASS browser: build release binary
FAIL browser: Playwright against release server
curl: (7) Failed to connect to 127.0.0.1 port 22725 after 0 ms: Could not connect to server
METRIC container-detail JS gzip before terminal: 221580 bytes
METRIC container action focus: {"focused":true,"activeElement":"<button data-slot="button" class="focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 border bor","disabled":false,"connected":true,"tabIndex":0,"display":"flex","visibility":"visible","rowKey":"h_01M3C2VFF5CH9NP6N900Q1FQYX/docker/9175f0355adb46d0bf981df9dd6314c6929d9a4110f8b335a0f7449ab0d5b49b","visibilityState":"visible"}
8583 |
8584 | // packages/utils/stackTrace.ts
8585 | function captureRawStack() {
8586 | const stackTraceLimit = Error.stackTraceLimit;
8587 | Error.stackTraceLimit = 50;
8588 | const error = new Error();
^
error: expect(locator).toBeHidden() failed
Locator: getByRole('button', { name: 'Jump to latest' })
Expected: hidden
Received: visible
Timeout: 5000ms
Call log:
14 × locator resolved to <button type="button" data-slot="button" class="focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-3 aria-invalid:ring-3 [&_svg:not([class*='size-'])]:size-4 group/button inline-flex shrink-0 items-center justify-center whitespace-nowrap outline-none select-none disabled:pointer-…>…
matcherResult: {
message: "expect(locator).toBeHidden() failed\n\nLocator: getByRole('button', { name: 'Jump to latest' })\nExpected: hidden\nReceived: visible\nTimeout: 5000ms\n\nCall log:\n - Expect "toBeHidden" getByRole('button', { name: 'Jump to latest' }) with timeout 5000ms\n - waiting for getByRole('button', { name: 'Jump to latest' })\n 14 × locator resolved to <button type="button" data-slot="button" class="focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-3 aria-invalid:ring-3 [&_svg:not([class*='size-'])]:size-4 group/button inline-flex shrink-0 items-center justify-center whitespace-nowrap outline-none select-none disabled:pointer-…>…\n - unexpected value "visible"\n",
pass: false,
actual: "visible",
name: "toBeHidden",
expected: "hidden",
log: [ " - Expect "toBeHidden" getByRole('button', { name: 'Jump to latest' }) with timeout 5000ms",
" - waiting for getByRole('button', { name: 'Jump to latest' })", " 14 × locator resolved to <button type="button" data-slot="button" class="focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-3 aria-invalid:ring-3 [&_svg:not([class*='size-'])]:size-4 group/button inline-flex shrink-0 items-center justify-center whitespace-nowrap outline-none select-none disabled:pointer-…>…",
" - unexpected value "visible""
],
timeout: 5000,
ariaSnapshot: "- button "Jump to latest"",
},
Bun v1.4.2 (Linux x64)
Direct Playwright rerun cleared Jump to latest but revealed audit cold route over 120 KiB transfer budget:
METRIC container-detail JS gzip before terminal: 221580 bytes
METRIC container action focus: {"focused":true,"activeElement":"<button data-slot="button" class="focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 border bor","disabled":false,"connected":true,"tabIndex":0,"display":"flex","visibility":"visible","rowKey":"h_01M3C2YDQVP06DQEAFKX5XQGQ6/docker/fb9934d6aea98b343ee46d21dc651949a929fc580bce6fca03d81ce43e9ee791","visibilityState":"visible"}
METRIC terminal DATA/CREDIT accounting: {"storedOffset":18,"replayStart":0,"outputOffset":18,"dataBytes":18,"creditBytes":18,"expectedOffset":18}
METRIC Ghostty light terminal colors: {"tokenBackground":"#f5f7fa","expectedBackground":[245,247,250,255],"backgroundPixel":[245,247,250,255],"hostBackground":"rgb(245, 247, 250)","hostBackgroundPixel":[245,247,250,255],"tokenForeground":"#17212b","expectedForeground":[23,33,43],"glyphForeground":[24,34,44],"foregroundDistance":1.7320508075688772}
METRIC Ghostty light terminal colors: {"tokenBackground":"#f5f7fa","expectedBackground":[245,247,250,255],"backgroundPixel":[245,247,250,255],"hostBackground":"rgb(245, 247, 250)","hostBackgroundPixel":[245,247,250,255],"tokenForeground":"#17212b","expectedForeground":[23,33,43],"glyphForeground":[24,34,44],"foregroundDistance":1.7320508075688772}
METRIC Ghostty dark terminal colors: {"tokenBackground":"#11161c","expectedBackground":[17,22,28,255],"backgroundPixel":[17,22,28,255],"hostBackground":"rgb(17, 22, 28)","hostBackgroundPixel":[17,22,28,255],"tokenForeground":"#e9eef4","expectedForeground":[233,238,244],"glyphForeground":[232,237,243],"foregroundDistance":1.7320508075688772}
METRIC Ghostty dark terminal colors: {"tokenBackground":"#11161c","expectedBackground":[17,22,28,255],"backgroundPixel":[17,22,28,255],"hostBackground":"rgb(17, 22, 28)","hostBackgroundPixel":[17,22,28,255],"tokenForeground":"#e9eef4","expectedForeground":[233,238,244],"glyphForeground":[232,237,243],"foregroundDistance":1.7320508075688772}
METRIC terminal reattach DATA/CREDIT accounting: {"storedOffset":242,"replayStart":211,"dataBytes":31,"creditBytes":31,"expectedOffset":242}
METRIC lazy terminal JS gzip: 192474 bytes
METRIC route JS gzip after terminal: 414054 bytes
METRIC initial route JS gzip: 118551 bytes
METRIC dashboard first-load JS transferred: 126698 bytes
METRIC audit first-load JS transferred: 199717 bytes
2067 | await auditPage.goto(
${baseUrl}/audit-log, { waitUntil: "networkidle" });2068 | await auditPage.getByRole("heading", { name: "Audit log", level: 1 }).waitFor({ state: "visible" });
2069 | await auditPage.getByRole("status").filter({ hasText: /event.*on this page/ }).waitFor({ state: "visible" });
2070 | const auditTransferred = await actualJavaScriptBytes(auditPage);
2071 | console.log(
METRIC audit first-load JS transferred: ${auditTransferred} bytes);2072 | if (auditTransferred === 0 || auditTransferred > 120 * 1024) throw new Error(
audit first-load transferred JS exceeds 120 KiB or was not captured: ${auditTransferred});^
error: audit first-load transferred JS exceeds 120 KiB or was not captured: 199717
at /home/kayg/wt/audit-log/scripts/browser-check.mjs:2072:80
Bun v1.4.2 (Linux x64)
Fast gate at 5bba6b0 after lean audit shell:
PASS fast: migrations are append-only
PASS fast: workspace package dependencies
PASS fast: JavaScript dependencies
PASS fast: build web app
PASS fast: cargo fmt --check
PASS fast: cargo clippy
PASS fast: cargo test
PASS fast: svelte-check
PASS fast: UI package svelte-check
PASS fast: stream package typecheck
PASS fast: Vitest
PASS fast: UI package Vitest
PASS fast: stream package Vitest
PASS fast: OpenAPI and TypeScript client drift
PASS fast: terminal TypeScript
PASS fast: terminal Vitest
Browser gate at 5bba6b0 reached known Jump to latest flake; direct Playwright rerun follows:
PASS browser: JavaScript dependencies
PASS browser: install Chromium and system dependencies
PASS browser: terminal fixture Playwright
PASS browser: build web app
PASS browser: build release binary
FAIL browser: Playwright against release server
curl: (7) Failed to connect to 127.0.0.1 port 7065 after 0 ms: Could not connect to server
METRIC container-detail JS gzip before terminal: 221843 bytes
METRIC container action focus: {"focused":true,"activeElement":"<button data-slot="button" class="focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 border bor","disabled":false,"connected":true,"tabIndex":0,"display":"flex","visibility":"visible","rowKey":"h_01M3C438RY7GNT4NZHPCCW1FJ5/docker/c41ff16ae1417819b5e0ca519890a6280afb9d0e6aace6f40469d572dcd4956d","visibilityState":"visible"}
8583 |
8584 | // packages/utils/stackTrace.ts
8585 | function captureRawStack() {
8586 | const stackTraceLimit = Error.stackTraceLimit;
8587 | Error.stackTraceLimit = 50;
8588 | const error = new Error();
^
error: expect(locator).toBeHidden() failed
Locator: getByRole('button', { name: 'Jump to latest' })
Expected: hidden
Received: visible
Timeout: 5000ms
Call log:
14 × locator resolved to <button type="button" data-slot="button" class="focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-3 aria-invalid:ring-3 [&_svg:not([class*='size-'])]:size-4 group/button inline-flex shrink-0 items-center justify-center whitespace-nowrap outline-none select-none disabled:pointer-…>…
matcherResult: {
message: "expect(locator).toBeHidden() failed\n\nLocator: getByRole('button', { name: 'Jump to latest' })\nExpected: hidden\nReceived: visible\nTimeout: 5000ms\n\nCall log:\n - Expect "toBeHidden" getByRole('button', { name: 'Jump to latest' }) with timeout 5000ms\n - waiting for getByRole('button', { name: 'Jump to latest' })\n 14 × locator resolved to <button type="button" data-slot="button" class="focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-3 aria-invalid:ring-3 [&_svg:not([class*='size-'])]:size-4 group/button inline-flex shrink-0 items-center justify-center whitespace-nowrap outline-none select-none disabled:pointer-…>…\n - unexpected value "visible"\n",
pass: false,
actual: "visible",
name: "toBeHidden",
expected: "hidden",
log: [ " - Expect "toBeHidden" getByRole('button', { name: 'Jump to latest' }) with timeout 5000ms",
" - waiting for getByRole('button', { name: 'Jump to latest' })", " 14 × locator resolved to <button type="button" data-slot="button" class="focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-3 aria-invalid:ring-3 [&_svg:not([class*='size-'])]:size-4 group/button inline-flex shrink-0 items-center justify-center whitespace-nowrap outline-none select-none disabled:pointer-…>…",
" - unexpected value "visible""
],
timeout: 5000,
ariaSnapshot: "- button "Jump to latest"",
},
Bun v1.4.2 (Linux x64)
Direct Playwright rerun at 5bba6b0 measured audit 91,678 transferred JS bytes and passed the 1440px time fit, then found audit heading weight mismatch:
METRIC container-detail JS gzip before terminal: 221843 bytes
METRIC container action focus: {"focused":true,"activeElement":"<button data-slot="button" class="focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 border bor","disabled":false,"connected":true,"tabIndex":0,"display":"flex","visibility":"visible","rowKey":"h_01M3C458NCRSJKB87T6FXJ766H/docker/847fab319738a270b230232b58738f0463c4db167b8cc34a10abea6f9843a433","visibilityState":"visible"}
METRIC terminal DATA/CREDIT accounting: {"storedOffset":18,"replayStart":0,"outputOffset":18,"dataBytes":18,"creditBytes":18,"expectedOffset":18}
METRIC Ghostty light terminal colors: {"tokenBackground":"#f5f7fa","expectedBackground":[245,247,250,255],"backgroundPixel":[245,247,250,255],"hostBackground":"rgb(245, 247, 250)","hostBackgroundPixel":[245,247,250,255],"tokenForeground":"#17212b","expectedForeground":[23,33,43],"glyphForeground":[24,34,44],"foregroundDistance":1.7320508075688772}
METRIC Ghostty light terminal colors: {"tokenBackground":"#f5f7fa","expectedBackground":[245,247,250,255],"backgroundPixel":[245,247,250,255],"hostBackground":"rgb(245, 247, 250)","hostBackgroundPixel":[245,247,250,255],"tokenForeground":"#17212b","expectedForeground":[23,33,43],"glyphForeground":[24,34,44],"foregroundDistance":1.7320508075688772}
METRIC Ghostty dark terminal colors: {"tokenBackground":"#11161c","expectedBackground":[17,22,28,255],"backgroundPixel":[17,22,28,255],"hostBackground":"rgb(17, 22, 28)","hostBackgroundPixel":[17,22,28,255],"tokenForeground":"#e9eef4","expectedForeground":[233,238,244],"glyphForeground":[232,237,243],"foregroundDistance":1.7320508075688772}
METRIC Ghostty dark terminal colors: {"tokenBackground":"#11161c","expectedBackground":[17,22,28,255],"backgroundPixel":[17,22,28,255],"hostBackground":"rgb(17, 22, 28)","hostBackgroundPixel":[17,22,28,255],"tokenForeground":"#e9eef4","expectedForeground":[233,238,244],"glyphForeground":[232,237,243],"foregroundDistance":1.7320508075688772}
METRIC terminal reattach DATA/CREDIT accounting: {"storedOffset":242,"replayStart":211,"dataBytes":31,"creditBytes":31,"expectedOffset":242}
METRIC lazy terminal JS gzip: 192474 bytes
METRIC route JS gzip after terminal: 414317 bytes
METRIC initial route JS gzip: 118795 bytes
METRIC dashboard first-load JS transferred: 127290 bytes
METRIC audit first-load JS transferred: 91678 bytes
265 | };
266 | });
267 | if (!result.inter || !result.mono) throw new Error(
${label}: embedded UI fonts are not ready: ${JSON.stringify(result)});268 | if (!result.body?.family.includes("Inter Variable")) throw new Error(
${label}: body is not using Inter Variable: ${JSON.stringify(result)});269 | if (result.body.weight !== "400") throw new Error(
${label}: body is not using the regular variable weight: ${JSON.stringify(result.body)});270 | if (result.heading && result.heading.weight !== "600") throw new Error(
${label}: page heading weight is wrong: ${JSON.stringify(result.heading)});^
error: audit desktop: page heading weight is wrong: {"selector":"#main-content h1","family":""Inter Variable", ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif","size":"24px","weight":"400","lineHeight":"31.9992px","letterSpacing":"normal","numeric":"normal"}
at waitForFonts (/home/kayg/wt/audit-log/scripts/browser-check.mjs:270:68)
at async screenshotWithFonts (/home/kayg/wt/audit-log/scripts/browser-check.mjs:284:24)
Bun v1.4.2 (Linux x64)
Fast gate at c13b831 after audit heading fix:
WARN load5=9.72 exceeds online CPU count=8; timing-sensitive checks may be delayed
PASS fast: migrations are append-only
PASS fast: workspace package dependencies
PASS fast: JavaScript dependencies
PASS fast: build web app
PASS fast: cargo fmt --check
PASS fast: cargo clippy
PASS fast: cargo test
PASS fast: svelte-check
PASS fast: UI package svelte-check
PASS fast: stream package typecheck
PASS fast: Vitest
PASS fast: UI package Vitest
PASS fast: stream package Vitest
PASS fast: OpenAPI and TypeScript client drift
PASS fast: terminal TypeScript
PASS fast: terminal Vitest
Browser gate at c13b831 failed before the audit checks because the terminal fixture Playwright port 4175 was used by another process; next run will use the supported INFRATERMINAL_TERMINAL_TEST_PORT override:
PASS browser: JavaScript dependencies
PASS browser: install Chromium and system dependencies
FAIL browser: terminal fixture Playwright
$ playwright test tests/browser tests/screenshot.spec.ts --reporter=line
Error: http://127.0.0.1:4175 is already used, make sure that nothing is running on the port/url or set reuseExistingServer:true in config.webServer.
error: script "test:browser" exited with code 1
Browser gate at c13b831 measured audit 91678 transferred JS bytes and captured desktop/mobile screenshots. It later failed an unrelated dashboard refresh announcement under load. Visual inspection showed mobile sidebar mid-resize transition; fixed and added viewport assertion:
PASS browser: JavaScript dependencies
PASS browser: install Chromium and system dependencies
PASS browser: terminal fixture Playwright
PASS browser: build web app
PASS browser: build release binary
FAIL browser: Playwright against release server
curl: (7) Failed to connect to 127.0.0.1 port 22323 after 0 ms: Could not connect to server
METRIC container-detail JS gzip before terminal: 221843 bytes
METRIC container action focus: {"focused":true,"activeElement":"<button data-slot="button" class="focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 border bor","disabled":false,"connected":true,"tabIndex":0,"display":"flex","visibility":"visible","rowKey":"h_01M3C6K22TWXQQPEQESJ4YVRB3/docker/e498158c5b847585f8e1216b853c1aaf799a4992a8dd523383a944f777435868","visibilityState":"visible"}
METRIC terminal DATA/CREDIT accounting: {"storedOffset":18,"replayStart":0,"outputOffset":18,"dataBytes":18,"creditBytes":18,"expectedOffset":18}
METRIC Ghostty light terminal colors: {"tokenBackground":"#f5f7fa","expectedBackground":[245,247,250,255],"backgroundPixel":[245,247,250,255],"hostBackground":"rgb(245, 247, 250)","hostBackgroundPixel":[245,247,250,255],"tokenForeground":"#17212b","expectedForeground":[23,33,43],"glyphForeground":[24,34,44],"foregroundDistance":1.7320508075688772}
METRIC Ghostty light terminal colors: {"tokenBackground":"#f5f7fa","expectedBackground":[245,247,250,255],"backgroundPixel":[245,247,250,255],"hostBackground":"rgb(245, 247, 250)","hostBackgroundPixel":[245,247,250,255],"tokenForeground":"#17212b","expectedForeground":[23,33,43],"glyphForeground":[24,34,44],"foregroundDistance":1.7320508075688772}
METRIC Ghostty dark terminal colors: {"tokenBackground":"#11161c","expectedBackground":[17,22,28,255],"backgroundPixel":[17,22,28,255],"hostBackground":"rgb(17, 22, 28)","hostBackgroundPixel":[17,22,28,255],"tokenForeground":"#e9eef4","expectedForeground":[233,238,244],"glyphForeground":[232,237,243],"foregroundDistance":1.7320508075688772}
METRIC Ghostty dark terminal colors: {"tokenBackground":"#11161c","expectedBackground":[17,22,28,255],"backgroundPixel":[17,22,28,255],"hostBackground":"rgb(17, 22, 28)","hostBackgroundPixel":[17,22,28,255],"tokenForeground":"#e9eef4","expectedForeground":[233,238,244],"glyphForeground":[232,237,243],"foregroundDistance":1.7320508075688772}
METRIC terminal reattach DATA/CREDIT accounting: {"storedOffset":242,"replayStart":211,"dataBytes":31,"creditBytes":31,"expectedOffset":242}
METRIC lazy terminal JS gzip: 192474 bytes
METRIC route JS gzip after terminal: 414317 bytes
METRIC initial route JS gzip: 118795 bytes
METRIC dashboard first-load JS transferred: 127290 bytes
METRIC audit first-load JS transferred: 91678 bytes
8583 |
8584 | // packages/utils/stackTrace.ts
8585 | function captureRawStack() {
8586 | const stackTraceLimit = Error.stackTraceLimit;
8587 | Error.stackTraceLimit = 50;
8588 | const error = new Error();
^
error: expect(locator).toHaveText(expected) failed
Locator: locator('[data-dashboard-status-announcement]')
Expected: "Live inventory"
Received: "Refresh delayed"
Timeout: 5000ms
Call log:
14 × locator resolved to Refresh delayed
matcherResult: {
name: "toHaveText",
expected: "Live inventory",
message: "expect(locator).toHaveText(expected) failed\n\nLocator: locator('[data-dashboard-status-announcement]')\nExpected: "Live inventory"\nReceived: "Refresh delayed"\nTimeout: 5000ms\n\nCall log:\n - Expect "toHaveText" locator('[data-dashboard-status-announcement]') with timeout 5000ms\n - waiting for locator('[data-dashboard-status-announcement]')\n 14 × locator resolved to <span role="status" class="sr-only" aria-live="polite" aria-atomic="true" data-dashboard-status-announcement="">Refresh delayed\n - unexpected value "Refresh delayed"\n",
pass: false,
actual: "Refresh delayed",
log: [ " - Expect "toHaveText" locator('[data-dashboard-status-announcement]') with timeout 5000ms",
" - waiting for locator('[data-dashboard-status-announcement]')", " 14 × locator resolved to <span role="status" class="sr-only" aria-live="polite" aria-atomic="true" data-dashboard-status-announcement="">Refresh delayed",
" - unexpected value "Refresh delayed""
],
timeout: 5000,
ariaSnapshot: "- status: Refresh delayed",
},
Bun v1.4.2 (Linux x64)
Fast gate at 6f9e91d after mobile viewport fix:
WARN load5=8.67 exceeds online CPU count=8; timing-sensitive checks may be delayed
PASS fast: migrations are append-only
PASS fast: workspace package dependencies
PASS fast: JavaScript dependencies
PASS fast: build web app
PASS fast: cargo fmt --check
PASS fast: cargo clippy
PASS fast: cargo test
PASS fast: svelte-check
PASS fast: UI package svelte-check
PASS fast: stream package typecheck
PASS fast: Vitest
PASS fast: UI package Vitest
PASS fast: stream package Vitest
PASS fast: OpenAPI and TypeScript client drift
PASS fast: terminal TypeScript
PASS fast: terminal Vitest
Browser gate at 6f9e91d passed audit transferred-byte, time-fit and viewport-fit checks at 1440px/390px; screenshots: /mnt/hdd/infraternal/artifacts/s2-audit/audit-1440x900.png and audit-390x844.png. It later failed dashboard refresh announcement:
PASS browser: JavaScript dependencies
PASS browser: install Chromium and system dependencies
PASS browser: terminal fixture Playwright
PASS browser: build web app
PASS browser: build release binary
FAIL browser: Playwright against release server
curl: (7) Failed to connect to 127.0.0.1 port 27995 after 0 ms: Could not connect to server
METRIC container-detail JS gzip before terminal: 221845 bytes
METRIC container action focus: {"focused":true,"activeElement":"<button data-slot="button" class="focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 border bor","disabled":false,"connected":true,"tabIndex":0,"display":"flex","visibility":"visible","rowKey":"h_01M3C7VZ6N59D8HV6S3HX0ZEDG/docker/b159c147f395157e60846e6fcd88b7db06a919f7c8b5a271f2415eaf83b986a8","visibilityState":"visible"}
METRIC terminal DATA/CREDIT accounting: {"storedOffset":18,"replayStart":0,"outputOffset":18,"dataBytes":18,"creditBytes":18,"expectedOffset":18}
METRIC Ghostty light terminal colors: {"tokenBackground":"#f5f7fa","expectedBackground":[245,247,250,255],"backgroundPixel":[245,247,250,255],"hostBackground":"rgb(245, 247, 250)","hostBackgroundPixel":[245,247,250,255],"tokenForeground":"#17212b","expectedForeground":[23,33,43],"glyphForeground":[24,34,44],"foregroundDistance":1.7320508075688772}
METRIC Ghostty light terminal colors: {"tokenBackground":"#f5f7fa","expectedBackground":[245,247,250,255],"backgroundPixel":[245,247,250,255],"hostBackground":"rgb(245, 247, 250)","hostBackgroundPixel":[245,247,250,255],"tokenForeground":"#17212b","expectedForeground":[23,33,43],"glyphForeground":[24,34,44],"foregroundDistance":1.7320508075688772}
METRIC Ghostty dark terminal colors: {"tokenBackground":"#11161c","expectedBackground":[17,22,28,255],"backgroundPixel":[17,22,28,255],"hostBackground":"rgb(17, 22, 28)","hostBackgroundPixel":[17,22,28,255],"tokenForeground":"#e9eef4","expectedForeground":[233,238,244],"glyphForeground":[232,237,243],"foregroundDistance":1.7320508075688772}
METRIC Ghostty dark terminal colors: {"tokenBackground":"#11161c","expectedBackground":[17,22,28,255],"backgroundPixel":[17,22,28,255],"hostBackground":"rgb(17, 22, 28)","hostBackgroundPixel":[17,22,28,255],"tokenForeground":"#e9eef4","expectedForeground":[233,238,244],"glyphForeground":[232,237,243],"foregroundDistance":1.7320508075688772}
METRIC terminal reattach DATA/CREDIT accounting: {"storedOffset":242,"replayStart":211,"dataBytes":31,"creditBytes":31,"expectedOffset":242}
METRIC lazy terminal JS gzip: 192474 bytes
METRIC route JS gzip after terminal: 414319 bytes
METRIC initial route JS gzip: 118797 bytes
METRIC dashboard first-load JS transferred: 127290 bytes
METRIC audit first-load JS transferred: 91678 bytes
8583 |
8584 | // packages/utils/stackTrace.ts
8585 | function captureRawStack() {
8586 | const stackTraceLimit = Error.stackTraceLimit;
8587 | Error.stackTraceLimit = 50;
8588 | const error = new Error();
^
error: expect(locator).toHaveText(expected) failed
Locator: locator('[data-dashboard-status-announcement]')
Expected: "Live inventory"
Received: "Refresh delayed"
Timeout: 5000ms
Call log:
14 × locator resolved to Refresh delayed
matcherResult: {
name: "toHaveText",
expected: "Live inventory",
message: "expect(locator).toHaveText(expected) failed\n\nLocator: locator('[data-dashboard-status-announcement]')\nExpected: "Live inventory"\nReceived: "Refresh delayed"\nTimeout: 5000ms\n\nCall log:\n - Expect "toHaveText" locator('[data-dashboard-status-announcement]') with timeout 5000ms\n - waiting for locator('[data-dashboard-status-announcement]')\n 14 × locator resolved to <span role="status" class="sr-only" aria-live="polite" aria-atomic="true" data-dashboard-status-announcement="">Refresh delayed\n - unexpected value "Refresh delayed"\n",
pass: false,
actual: "Refresh delayed",
log: [ " - Expect "toHaveText" locator('[data-dashboard-status-announcement]') with timeout 5000ms",
" - waiting for locator('[data-dashboard-status-announcement]')", " 14 × locator resolved to <span role="status" class="sr-only" aria-live="polite" aria-atomic="true" data-dashboard-status-announcement="">Refresh delayed",
" - unexpected value "Refresh delayed""
],
timeout: 5000,
ariaSnapshot: "- status: Refresh delayed",
},
Bun v1.4.2 (Linux x64)
Direct Playwright rerun at 6f9e91d repeated the dashboard refresh recovery assertion after the audit size/layout checks passed:
METRIC container-detail JS gzip before terminal: 221845 bytes
METRIC container action focus: {"focused":true,"activeElement":"<button data-slot="button" class="focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 border bor","disabled":false,"connected":true,"tabIndex":0,"display":"flex","visibility":"visible","rowKey":"h_01M3C81NJ9V1JWNKRF3F1PFQEQ/docker/b2c31c48636c4b33d875346d3c3953bc95378dc66259148bffe4fc28eb1c158b","visibilityState":"visible"}
METRIC terminal DATA/CREDIT accounting: {"storedOffset":18,"replayStart":0,"outputOffset":18,"dataBytes":18,"creditBytes":18,"expectedOffset":18}
METRIC Ghostty light terminal colors: {"tokenBackground":"#f5f7fa","expectedBackground":[245,247,250,255],"backgroundPixel":[245,247,250,255],"hostBackground":"rgb(245, 247, 250)","hostBackgroundPixel":[245,247,250,255],"tokenForeground":"#17212b","expectedForeground":[23,33,43],"glyphForeground":[24,34,44],"foregroundDistance":1.7320508075688772}
METRIC Ghostty light terminal colors: {"tokenBackground":"#f5f7fa","expectedBackground":[245,247,250,255],"backgroundPixel":[245,247,250,255],"hostBackground":"rgb(245, 247, 250)","hostBackgroundPixel":[245,247,250,255],"tokenForeground":"#17212b","expectedForeground":[23,33,43],"glyphForeground":[24,34,44],"foregroundDistance":1.7320508075688772}
METRIC Ghostty dark terminal colors: {"tokenBackground":"#11161c","expectedBackground":[17,22,28,255],"backgroundPixel":[17,22,28,255],"hostBackground":"rgb(17, 22, 28)","hostBackgroundPixel":[17,22,28,255],"tokenForeground":"#e9eef4","expectedForeground":[233,238,244],"glyphForeground":[232,237,243],"foregroundDistance":1.7320508075688772}
METRIC Ghostty dark terminal colors: {"tokenBackground":"#11161c","expectedBackground":[17,22,28,255],"backgroundPixel":[17,22,28,255],"hostBackground":"rgb(17, 22, 28)","hostBackgroundPixel":[17,22,28,255],"tokenForeground":"#e9eef4","expectedForeground":[233,238,244],"glyphForeground":[232,237,243],"foregroundDistance":1.7320508075688772}
METRIC terminal reattach DATA/CREDIT accounting: {"storedOffset":242,"replayStart":211,"dataBytes":31,"creditBytes":31,"expectedOffset":242}
METRIC lazy terminal JS gzip: 192474 bytes
METRIC route JS gzip after terminal: 414319 bytes
METRIC initial route JS gzip: 118797 bytes
METRIC dashboard first-load JS transferred: 127290 bytes
METRIC audit first-load JS transferred: 91678 bytes
8583 |
8584 | // packages/utils/stackTrace.ts
8585 | function captureRawStack() {
8586 | const stackTraceLimit = Error.stackTraceLimit;
8587 | Error.stackTraceLimit = 50;
8588 | const error = new Error();
^
error: expect(locator).toHaveText(expected) failed
Locator: locator('[data-dashboard-status-announcement]')
Expected: "Live inventory"
Received: "Refresh delayed"
Timeout: 5000ms
Call log:
14 × locator resolved to Refresh delayed
matcherResult: {
name: "toHaveText",
expected: "Live inventory",
message: "expect(locator).toHaveText(expected) failed\n\nLocator: locator('[data-dashboard-status-announcement]')\nExpected: "Live inventory"\nReceived: "Refresh delayed"\nTimeout: 5000ms\n\nCall log:\n - Expect "toHaveText" locator('[data-dashboard-status-announcement]') with timeout 5000ms\n - waiting for locator('[data-dashboard-status-announcement]')\n 14 × locator resolved to <span role="status" class="sr-only" aria-live="polite" aria-atomic="true" data-dashboard-status-announcement="">Refresh delayed\n - unexpected value "Refresh delayed"\n",
pass: false,
actual: "Refresh delayed",
log: [ " - Expect "toHaveText" locator('[data-dashboard-status-announcement]') with timeout 5000ms",
" - waiting for locator('[data-dashboard-status-announcement]')", " 14 × locator resolved to <span role="status" class="sr-only" aria-live="polite" aria-atomic="true" data-dashboard-status-announcement="">Refresh delayed",
" - unexpected value "Refresh delayed""
],
timeout: 5000,
ariaSnapshot: "- status: Refresh delayed",
},
Bun v1.4.2 (Linux x64)
fix-25 finish report
Branch: audit-log
Head: 6f9e91dabce85c0c87fc11cb2ded3306b1f53439
Worktree: clean; committed locally; not pushed.
Audit cold-route JS transferred: 91678 bytes (120 KiB cap 122880). Dashboard first-load JS transferred: 127290 bytes; dashboard gzip body: 118797 bytes.
Screenshots inspected: /mnt/hdd/infraternal/artifacts/s2-audit/audit-1440x900.png and /mnt/hdd/infraternal/artifacts/s2-audit/audit-390x844.png. Audit timestamp and viewport-fit assertions passed at both widths.
Benchmark on dev VM, not the perf-test VM: target-only p50/p99 463/2838 us; sparse scope/action p50/p99 760/3669 us (1M rows).
Latest fast gate verbatim:
WARN load5=8.67 exceeds online CPU count=8; timing-sensitive checks may be delayed
PASS fast: migrations are append-only
PASS fast: workspace package dependencies
PASS fast: JavaScript dependencies
PASS fast: build web app
PASS fast: cargo fmt --check
PASS fast: cargo clippy
PASS fast: cargo test
PASS fast: svelte-check
PASS fast: UI package svelte-check
PASS fast: stream package typecheck
PASS fast: Vitest
PASS fast: UI package Vitest
PASS fast: stream package Vitest
PASS fast: OpenAPI and TypeScript client drift
PASS fast: terminal TypeScript
PASS fast: terminal Vitest
Latest integration gate verbatim (stopped at known Podman cleanup flake; direct rerun output is in prior comment):
PASS integration: JavaScript dependencies
PASS integration: build web app
PASS integration: build release binary
PASS integration: real HTTP behavior
PASS integration: Docker socket _ping
PASS integration: rootless Podman socket _ping
FAIL integration: engine adapters against Docker and Podman
Finished
testprofile [unoptimized] target(s) in 0.20sRunning tests/integration.rs (target/debug/deps/integration-f92617287b4ea6a8)
running 11 tests
test docker_and_podman_share_the_real_engine_contract ... infraternal-engine-foreign-docker-713882-1790331418852-0
infraternal-engine-foreign-docker-713882-1790331418852-1
infraternal-engine-foreign-docker-713882-1790331418852-2
time="2026-09-25T12:17:44+02:00" level=warning msg="StopSignal SIGTERM failed to stop container infraternal-engine-foreign-podman-713882-1790331418852-0 in 10 seconds, resorting to SIGKILL"
infraternal-engine-foreign-podman-713882-1790331418852-0
time="2026-09-25T12:17:54+02:00" level=warning msg="StopSignal SIGTERM failed to stop container infraternal-engine-foreign-podman-713882-1790331418852-1 in 10 seconds, resorting to SIGKILL"
infraternal-engine-foreign-podman-713882-1790331418852-1
time="2026-09-25T12:18:05+02:00" level=warning msg="StopSignal SIGTERM failed to stop container infraternal-engine-foreign-podman-713882-1790331418852-2 in 10 seconds, resorting to SIGKILL"
infraternal-engine-foreign-podman-713882-1790331418852-2
ok
test list_preserves_health_and_pod_identity_on_all_real_engines ... ok
test missing_container_scan_tools_report_unconfirmed_when_host_proc_is_restricted ... ok
test podman_completed_containers_are_safe_for_inventory_and_mutations ... ok
test podman_model_preserves_health_and_pod_identity ... ok
test podman_mutation_response_loss_is_unknown_outcome ... ok
test pty_close_reaps_setsid_and_double_fork_descendants ... ok
test pty_close_reaps_term_ignoring_group_child_after_leader_exits ... docker same-group child reaped in 537.156193ms
podman same-group child reaped in 1.338211464s
ok
test pty_session_drop_and_close_terminate_exec_processes_on_all_real_engines ...
thread 'pty_session_drop_and_close_terminate_exec_processes_on_all_real_engines' (726024) panicked at crates/engine/tests/integration.rs:875:5:
container shell after drop pid 17 remained in process table: PID PPID COMMAND
1 0 sh -c printf 'stdout-line\n'; printf 'stderr-line\n' >&2; i=0; while [ $i -lt 65600 ]; do printf x; i=$((i+1)); done; printf '\n'; i=0; while [ $i -lt 65600 ]; do printf y >&2; i=$((i+1)); done; printf '\n' >&2; while :; do sleep 1; done
17 0 /bin/sh -c (while :; do sleep 1; done) & helper=$!; echo pty-marker=infraternal_pty_cleanup_713882-1790331591062_podman shell=
helper=$helper; wait23 17 /bin/sh -c (while :; do sleep 1; done) & helper=$!; echo pty-marker=infraternal_pty_cleanup_713882-1790331591062_podman shell=
helper=$helper; wait446 0 ps -o pid,ppid,args
note: run with
RUST_BACKTRACE=1environment variable to display a backtraceFAILED
test rootful_podman_covers_inventory_and_mutations ... ok
test stalled_pty_stdin_cannot_hold_exec_termination ... docker stalled stdin + ignored SIGTERM reaped in 547.226546ms
podman stalled stdin + ignored SIGTERM reaped in 1.125295841s
ok
failures:
failures:
pty_session_drop_and_close_terminate_exec_processes_on_all_real_engines
test result: FAILED. 10 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 243.84s
error: test failed, to rerun pass
-p infraternal-engine --test integrationLatest browser gate verbatim (audit checks passed; stopped at dashboard refresh recovery; direct rerun output is in prior comment):
PASS browser: JavaScript dependencies
PASS browser: install Chromium and system dependencies
PASS browser: terminal fixture Playwright
PASS browser: build web app
PASS browser: build release binary
FAIL browser: Playwright against release server
curl: (7) Failed to connect to 127.0.0.1 port 27995 after 0 ms: Could not connect to server
METRIC container-detail JS gzip before terminal: 221845 bytes
METRIC container action focus: {"focused":true,"activeElement":"<button data-slot="button" class="focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 border bor","disabled":false,"connected":true,"tabIndex":0,"display":"flex","visibility":"visible","rowKey":"h_01M3C7VZ6N59D8HV6S3HX0ZEDG/docker/b159c147f395157e60846e6fcd88b7db06a919f7c8b5a271f2415eaf83b986a8","visibilityState":"visible"}
METRIC terminal DATA/CREDIT accounting: {"storedOffset":18,"replayStart":0,"outputOffset":18,"dataBytes":18,"creditBytes":18,"expectedOffset":18}
METRIC Ghostty light terminal colors: {"tokenBackground":"#f5f7fa","expectedBackground":[245,247,250,255],"backgroundPixel":[245,247,250,255],"hostBackground":"rgb(245, 247, 250)","hostBackgroundPixel":[245,247,250,255],"tokenForeground":"#17212b","expectedForeground":[23,33,43],"glyphForeground":[24,34,44],"foregroundDistance":1.7320508075688772}
METRIC Ghostty light terminal colors: {"tokenBackground":"#f5f7fa","expectedBackground":[245,247,250,255],"backgroundPixel":[245,247,250,255],"hostBackground":"rgb(245, 247, 250)","hostBackgroundPixel":[245,247,250,255],"tokenForeground":"#17212b","expectedForeground":[23,33,43],"glyphForeground":[24,34,44],"foregroundDistance":1.7320508075688772}
METRIC Ghostty dark terminal colors: {"tokenBackground":"#11161c","expectedBackground":[17,22,28,255],"backgroundPixel":[17,22,28,255],"hostBackground":"rgb(17, 22, 28)","hostBackgroundPixel":[17,22,28,255],"tokenForeground":"#e9eef4","expectedForeground":[233,238,244],"glyphForeground":[232,237,243],"foregroundDistance":1.7320508075688772}
METRIC Ghostty dark terminal colors: {"tokenBackground":"#11161c","expectedBackground":[17,22,28,255],"backgroundPixel":[17,22,28,255],"hostBackground":"rgb(17, 22, 28)","hostBackgroundPixel":[17,22,28,255],"tokenForeground":"#e9eef4","expectedForeground":[233,238,244],"glyphForeground":[232,237,243],"foregroundDistance":1.7320508075688772}
METRIC terminal reattach DATA/CREDIT accounting: {"storedOffset":242,"replayStart":211,"dataBytes":31,"creditBytes":31,"expectedOffset":242}
METRIC lazy terminal JS gzip: 192474 bytes
METRIC route JS gzip after terminal: 414319 bytes
METRIC initial route JS gzip: 118797 bytes
METRIC dashboard first-load JS transferred: 127290 bytes
METRIC audit first-load JS transferred: 91678 bytes
8583 |
8584 | // packages/utils/stackTrace.ts
8585 | function captureRawStack() {
8586 | const stackTraceLimit = Error.stackTraceLimit;
8587 | Error.stackTraceLimit = 50;
8588 | const error = new Error();
^
error: expect(locator).toHaveText(expected) failed
Locator: locator('[data-dashboard-status-announcement]')
Expected: "Live inventory"
Received: "Refresh delayed"
Timeout: 5000ms
Call log:
14 × locator resolved to Refresh delayed
matcherResult: {
name: "toHaveText",
expected: "Live inventory",
message: "expect(locator).toHaveText(expected) failed\n\nLocator: locator('[data-dashboard-status-announcement]')\nExpected: "Live inventory"\nReceived: "Refresh delayed"\nTimeout: 5000ms\n\nCall log:\n - Expect "toHaveText" locator('[data-dashboard-status-announcement]') with timeout 5000ms\n - waiting for locator('[data-dashboard-status-announcement]')\n 14 × locator resolved to <span role="status" class="sr-only" aria-live="polite" aria-atomic="true" data-dashboard-status-announcement="">Refresh delayed\n - unexpected value "Refresh delayed"\n",
pass: false,
actual: "Refresh delayed",
log: [ " - Expect "toHaveText" locator('[data-dashboard-status-announcement]') with timeout 5000ms",
" - waiting for locator('[data-dashboard-status-announcement]')", " 14 × locator resolved to <span role="status" class="sr-only" aria-live="polite" aria-atomic="true" data-dashboard-status-announcement="">Refresh delayed",
" - unexpected value "Refresh delayed""
],
timeout: 5000,
ariaSnapshot: "- status: Refresh delayed",
},
Bun v1.4.2 (Linux x64)
Starting verify-25 on branch
audit-logat base head6f9e91dabce85c0c87fc11cb2ded3306b1f53439.I’m checking all eight fix-round findings, reproducing the raw-path, cursor-MAC and target-index regressions without their fixes, then comparing the dashboard refresh recovery check on
devand this branch before integratingdevand running the requested gates.Regression proof for the three data/security fixes: from
/home/kayg/wt/verify-25-tmpat6f9e91d,CARGO_TARGET_DIR=/home/kayg/wt/audit-log/target cargo test -p infraternal-server --test audit_httppassed 6/6 with the fixes restored.In a separate run from that throwaway checkout, I removed only raw-path action redaction, list cursor MAC validation, and
audit_targets_target_page. The same three tests failed as intended:rejected_paths_and_legacy_actions_never_leave_the_read_boundary: stored-path count was 1 instead of 0.cursor_mac_rejects_rebound_filters_principals_and_high_water: the forged cursor returned an audit page (HTTP 200), so the test's expectedinvalid_requestbody could not deserialize as an API error.exact_target_query_uses_index_and_trigger_populates_it: the query plan no longer namedaudit_targets_target_page.The worktree started at the requested
6f9e91d; these mutations and generated web assets are confined to it.Integration decision and fast gate: the merge keeps both step 19 remote-agent and step 25 audit APIs. The audit migration is now
0017_audit_query.sql; its SHA-256 matches the pre-rename file byte for byte.docs/openapi.jsonand the API client schema were regenerated with both/api/v1/agents/*and/api/v1/audit*routes.The first fast attempt stopped on rustfmt ordering; the next stopped because the merged
Server::openexceeded clippy's line limit. I extracted the existing cursor-key derivation intoderive_audit_cursor_key(same key bytes), then reran the gate successfully. Finalscripts/verify fastoutput:Verify-25 result: not verified
Branch:
audit-logHead:
24586f960525d3b4f4a17188d42e3705cf39c9feThe merge and migration renumbering are committed.
0017_audit_query.sqlhas SHA-2563712f26022875cbe89598955e23f55ee8ba5a1dd4d081209b3cda8a8de966207, unchanged from the old0015_audit_query.sql. OpenAPI and the TypeScript client were regenerated. Merge commit:a4ec559; test-fixture correction:24586f9. Nothing was pushed.Findings
McpService::export_auditincrates/infraternal/src/mcp.rscalls the paged HTTP client, which caps each response at 256 KiB incrates/infraternal/src/http.rs. The integration assertion incrates/infraternal/tests/cli_mcp.rsfirst failed because the rejection was created by a different AI token; AI audit visibility is token-scoped. Commit24586f9corrects the fixture to seed the redacted rejection under the MCP token. The post-fix integration runs stopped earlier at Podman/PTY checks, before reaching the MCP assertion, so this finding is not runtime-verified.record_request_outcomerecords the fixedrequest.rejectedaction incrates/server/src/lib.rs;rejected_paths_and_legacy_actions_never_leave_the_read_boundarypasses. Removing the fix made that test find one stored sentinel path (expected zero).crates/server/src/audit.rscomputes and constant-time checks the HMAC.cursor_mac_rejects_rebound_filters_principals_and_high_waterpasses. Removing the check allowed the rebound cursor to return a page instead ofinvalid_request.crates/server/migrations/sqlite/0017_audit_query.sqlcreatesaudit_targets_target_page;exact_target_query_uses_index_and_trigger_populates_itpasses. Removing the index made its query-plan assertion fail.AppShell.sveltelazy-loadsAuditShell.sveltefor/audit-log. Browser output measured initial dashboard route JS gzip at 118,797 bytes and audit first-load JS transferred at 91,678 bytes. The route budget and audit 120 KiB limit passed.assertAuditTimesFitran at desktop and 390×844 and passed before the later dashboard assertion failed.filter_timescaps timestamp length and validates outcomes;invalid_time_lengths_and_outcomes_return_invalid_requestpassed.packages/web/src/routes/audit-log/+page.sveltewraps only the filter form inCard.Root;VirtualTablesupplies the table frame. Browser viewport assertions passed. Screenshots:target/verify-25-browser-rerun/audit-1440x900.pngandtarget/verify-25-browser-rerun/audit-390x844.png.The three regression proofs ran in the throwaway worktree and the fixed suite passed 6/6. That worktree was removed.
Gates
scripts/verify fastpassed on the committed fixture correction. Exact final output:The integration wait reached its 60-minute timeout with load5 above 8; runs proceeded as instructed:
podman token_grant_removed exec process did not start.PASS integration: stream authorization and CLOSE regressions against Docker, then the persistent PTY termination check timed out (Elapsed(())). Its one targeted retry passed:test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 13 filtered out.podman role_grant_removed_then_restored exec process did not start.--tailoutput, then on the SSH PTY resize/exit checks. The corrected MCP export runtime assertion therefore remains unverified.The first browser run failed the named
Jump to latestassertion (Expected: hidden; Received: visible). Its one retry passed that assertion and recorded dashboard transferred JS at 127,290 bytes and audit transferred JS at 91,678 bytes, but later failed dashboard recovery: expectedLive inventory, receivedRefresh delayed. The isolated production-browser dashboard recovery check passed on bothdev(b63a853) andaudit-log(e89d937), and passed again ondev; the full-suite failure was not branch-specific. Initial route JS gzip was 118,797 bytes.The integration and browser gates did not exit successfully, and the post-fix MCP export assertion could not be reached. No product fix was indicated for the dashboard behavior.
Starting final-25 on branch
audit-log, at head24586f960525d3b4f4a17188d42e3705cf39c9fe. I am fetching and merging the requestedorigin/devbase (expected9d4876a), then will regenerate API artifacts, check stream-session audit rendering/redaction, and run fast, integration, and browser verification.Finding on
b93595d: the first integration run passed through real HTTP, Docker/Podman engine tests, log snapshots, stream client, stream authorization/CLOSE, PTY termination, and resource HTTP; it stopped in the compiled CLI/MCP integration test before the audit export assertion. Step 21 addsssh:connectto the default MCP grants (9 total), while this fixture still expected 8. I updated the fixture to expect 9 and assertScope::SshConnect.Verbatim gate output:
A direct rerun of
cargo test -p infraternal --test cli_mcp -- --ignored --nocapture --test-threads=1hit the CLI SSH PTY harness timeout inexercise_cli_ssh(before the MCP audit assertions). The first full integration run passed this helper and stopped later at the stale grant count. I am treating the PTY result as intermittent and rerunning the requested gates; this path is outside the merge-only fix scope.Observed output:
The second
scripts/verify integrationrun passed release build, real HTTP, Docker/Podman pings, engine adapters, bounded log snapshots, TypeScript stream, stream authorization/CLOSE, persistent PTY termination, and resource HTTP. It then failed in the same CLI SSH PTY helper before reaching the MCP audit assertions. This helper also failed in pre-merge final-25 runs, so it is not caused by the merge-only grant-count fix.Verbatim end of gate output:
Startup:
WARN load5=8.32 exceeds online CPU count=8; timing-sensitive checks may be delayed.A further direct
cli_mcpattempt progressed past container/CLI work but failed insideexercise_cli_sshbefore the MCP audit calls. The failure was the remote terminal resize assertion (remote stty size should receive the SIGWINCH resize); earlier pre-merge runs also reported CLI/SSH PTY failures. No change was made because this is outside the merge-only fix scope.Observed output:
Orchestrator: final-25 was cut off by a transient Codex API failure. Its integration runs also kept stopping at the CLI SSH PTY resize assertion (SIGWINCH), and the unmerged #37 branch fixes that exec/PTY path. The order is now: #37 merges first (job final-cli-eof), then this branch reruns its final gates on top of it. The merge commit
b93595dand the grant-count fix7e3011aare already on the branch.Starting final-25 on branch
audit-log, base head7e3011a98288ca7b862b8f02c81462754993b049. I will mergeorigin/devand run the requested fast, integration, and browser gates after checking the audit read path and waiting for the required load/concurrency conditions.Merged
origin/devatc99e40335232bd611dd26abac5cced750703c706(merge commitac1c0c0). Migration history is intact in order:0015_remote_agents.sql,0016_session_attachment_audit.sql,0017_audit_query.sql. The audit storage read mapper allowlists bothstream.session.attachandstream.session.detach, and appliessanitized_detailsto each record. The audit table renders the stored safe action as plain text;audit_http::rejected_paths_and_legacy_actions_never_leave_the_read_boundarycovers legacy-path redaction and attach action retention.The first
scripts/verify fastpassed the append-only migration gate, web build, formatting, and Clippy, then stopped ininfraternal-engineatsteady_state_framing_does_not_allocate_per_chunk(measured 139 allocations; it expected fewer than 100). The same test passed alone withcargo test -p infraternal-engine --lib logs::tests::steady_state_framing_does_not_allocate_per_chunk -- --exact --test-threads=1. Its source comments say the test harness runs other unit tests in parallel and allows for allocator noise. The failure is unrelated to the merged files; I am leaving engine code unchanged and will rerun the standard gate.Resuming final-25 after VM reboot.
Branch: audit-log at ac1c0c0; refreshed origin/dev is
c99e403and its merge is already present.Initial checks: worktree clean, progress.md is excluded, docker ps and podman ps both respond, load5 is below 8, and no other scripts/verify integration or browser process is active.
Integration finding: the real engine step failed before the CLI/MCP audit assertion ran.
The two failing tests were docker_and_podman_share_the_real_engine_contract and podman_completed_containers_are_safe_for_inventory_and_mutations; both returned during compose grouping.
The engine source/tests have no diff against refreshed origin/dev, so this is not yet attributable to the merge. Full output: /tmp/audit-log-final25-integration.log.
Integration evidence: engine integration exited nonzero before the CLI/MCP test step. Both compose-grouping failures reported: getting graph driver info for the test container: readlink /home/kayg/.local/share/containers/storage/overlay: invalid argument.
The failing tests were docker_and_podman_share_the_real_engine_contract and podman_completed_containers_are_safe_for_inventory_and_mutations. Engine source and test files have no diff against origin/dev, so the failure is not attributable to this merge. Full gate log: /tmp/audit-log-final25-integration.log.
Follow-up diagnosis: Podman is version 5.4.2 and its rootless graph root is /home/kayg/.local/share/containers/storage on ext4. The failing container is an exited test fixture named infraternal-engine-foreign-podman-742248-1790425491847-2. A direct podman inspect --format GraphDriver.Name reproduces the same readlink .../storage/overlay: invalid argument error.
There are no crates/engine changes between this branch and origin/dev. The VM reboot makes stale overlay state a plausible cause; a Podman project discussion reports similar readlink storage errors after a hard reboot: https://github.com/podman-container-tools/podman/discussions/17362#discussioncomment-12941895. I did not remove the old fixture because its run ID cannot be attributed safely to this attempt.
The integration gate stopped before cli_and_mcp_use_the_public_http_contract, so the required MCP export assertion has not yet been reached. I will run the targeted real CLI/MCP test once competing integration work clears.
Targeted real CLI/MCP test attempt: cargo test -p infraternal --test cli_mcp cli_and_mcp_use_the_public_http_contract -- --ignored --exact --nocapture --test-threads=1 exited 101 before the MCP audit export assertion. The test calls exercise_cli_ssh near line 184, before the MCP export assertion near line 1010. It failed in the killed-client replay reattach path: the remote input echoed finish and exit, but the compiled CLI did not exit before the PTY harness deadline. Full output: /tmp/audit-log-final25-mcp-targeted.log. No source changes made.
Continuation finding for the MCP gate: the focused cli_mcp test reaches the persistent SSH kill and reattach scenario, but the reattached CLI times out after the remote shell echoes its exit. The failing helper and scenario are in cli_mcp.rs lines 2969-3003, introduced by
fed23a48(2026-09-25); the MCP audit export assertion follows exercise_cli_ssh and is therefore not reached. The merged31ee7f9changes move SIGWINCH registration before stream setup and extend resize coverage; the hang is in the pre-existing killed-client replay path, with no evidence tying it to that merge. No source changes made.Browser rerun finding: the second scripts/verify browser run passed JavaScript dependencies, Chromium install, terminal fixture Playwright, web build, and release binary build, then failed in Playwright against the release server. The expected rootless Podman log fixture did not appear in the container inventory; the embedded server logs the same overlay readlink EINVAL seen in the integration gate. The first browser attempt failed earlier because port 4175 was occupied; when checked afterward it was free. The protected infraternal-preview unit was left untouched. Full output is in /tmp/audit-log-final25-browser-rerun.log; no source changes made.
Final verification for
audit-log, headac1c0c06b74fa6b3fda59730e691e77a8c52a978. Refreshedorigin/devisc99e403;git merge origin/devreturnedAlready up to date.Migrations 0015–0017 pass the append-only check. The audit read path recognizesstream.session.attachandstream.session.detachas generic action text and runs row details through redaction.scripts/verify fastpassed. Verbatim output:scripts/verify integrationpassed dependency/build/HTTP/socket checks and stopped at engine adapters. Verbatim gate and failure excerpt:The error reproduces on
podman inspectfor an exited fixture from an earlier unique run.crates/enginehas no diff against refreshedorigin/dev; I left the fixture untouched because its ownership is unclear. A similar post-reboot overlay readlink report exists in the Podman project discussion; the reboot connection remains an inference, not a confirmed root cause.scripts/verify browserfirst failed because port 4175 was occupied:The rerun passed fixture Playwright, web build and release build, then failed because rootless Podman inventory did not show the test fixture:
Neither
Jump to latestnorRefresh delayedwas reached. The real-browser route capture against the release binary produced:Desktop and 390×844 audit screenshots are in
/tmp/audit-log-final25-browser-artifacts-d9hzAj.The unmodified focused CLI/MCP test first timed out in the existing killed-client SSH replay case, before export. A temporary skip diagnostic then stopped earlier at
real engine targets did not enter the server inventory. I restored the test source. To verify the required export path despite those preconditions, an isolated temporary branch in the same test function started the real server, logged in, generated a real token-scoped 404 audit event, and called MCPexport_audit. It passed:All temporary source edits were restored.
git status --short --branchis## audit-log; no source changes or commit were made, and nothing was pushed. Full gate logs are under/tmp/audit-log-final25-*.log.Continuation rerun started on branch
audit-logatac1c0c06b74fa6b3fda59730e691e77a8c52a978, based onorigin/devc99e40335232bd611dd26abac5cced750703c706. The previous rootless Podman fixture with the invalid overlay link was removed by the orchestrator after reboot; I will rerun the final gates after confirming no competing integration/browser gate is active. I will also measure cold first-load dashboard JavaScript onorigin/devalone and this branch using the same browser capture to determine whether 192,879 bytes is the same metric as the 120 KB gzip budget or a branch regression.Fast rerun evidence: the first
scripts/verify fastrun passed fmt, Clippy, and web build but the parallel workspace unit-test run reportedenrollment_ca::tests::ca_persists_and_enrollment_certificate_ignores_requested_ca_extensionsfailed. The exact test passes alone (cargo test -p infraternal-server --lib enrollment_ca::tests::ca_persists_and_enrollment_certificate_ignores_requested_ca_extensions -- --exact --nocapture:1 passed, 46 filtered out), and the full gate rerun passed every step. No source changes were made.Verbatim gate output:
Readiness check: rootless Podman reports
true; Docker reports server version29.8.1.I began
scripts/verify integrationat load5 2.74 with no competing integration/browser gate. A separate browser gate started while the release build was compiling, so I interrupted only my own verify process before the integration tests began. No fixture containers were created by this run. I will rerun after the shared browser/release build clears.Audit read-path check:
safe_actionpreserves bothstream.session.attachandstream.session.detach;audit_pageruns each row throughsafe_actionandsanitized_details, and the audit table rendersitem.actionas generic text. The existingaudit_http::rejected_paths_and_legacy_actions_never_leave_the_read_boundarytest verifies attach action retention and a secret-like sentinel is absent from both list and export.One contract gap is visible: storage writes attachment details
{session_id, attachment_id, reason}, and docs/contracts.md §4.1 lists those keys, butsanitized_detailscurrently drops all three. They remain available as targets only for the session id and target. This is in the step-25 implementation, not caused by the dev merge; I left it unchanged under the merge-only fix scope.Integration gate reached
compiled CLI and MCP against real server and enginesand stopped there. Exact gate line:FAIL integration: compiled CLI and MCP against real server and engines. The testcli_and_mcp_use_the_public_http_contractfailed inexercise_cli_killed_client_replay: after the remote shell printed__CLI_SSH_REPLAY_AFTER__and echoedfinish/exit, the PTY harness reportedRuntimeError: compiled CLI did not exit. The test stopped before the MCPexport_auditassertion, so that assertion is not yet verified in this rerun. Earlier integration steps passed through resource HTTP. I will run the real export assertion with only the independent killed-client replay scenario bypassed diagnostically; no production source fix is indicated by this failure.The required MCP audit export assertion was exercised against the real compiled server and MCP client with
INFRATER_CLI_MCP_SKIP_KILLED_CLIENT_REPLAY=1, bypassing only the independent SSH replay scenario that aborts the full test before MCP export. The actual export produced the token-visiblerequest.rejectedrow and omitted the sentinel. Verbatim assertion marker:The diagnostic test result was
test result: ok. 1 passed; 0 failed; 0 ignored. Temporary test-only edits (skip switch and marker) were restored and byte-compared to the backup. The full integration gate remains failed at the SSH replay case; this diagnostic does not replace that gate.Final rerun status for
audit-logat headac1c0c06b74fa6b3fda59730e691e77a8c52a978. Fetchedorigin/devisc99e40335232bd611dd26abac5cced750703c706; merge was already up to date. No source changes were committed or pushed.Verbatim
scripts/verify fastoutput:Verbatim integration step output:
The CLI/MCP test stopped before its audit export assertion in the SSH killed-client replay harness (
RuntimeError: compiled CLI did not exitafter the remote output marker andfinish/exit). The full integration gate therefore remains failed.The required audit export assertion was then run against the real compiled server and MCP client, bypassing only that separate replay subscenario for diagnosis. Exact assertion output:
The diagnostic test result was
test result: ok. 1 passed; 0 failed; 0 ignored. Temporary test-only edits were restored byte-for-byte; they are not in the worktree.The branch browser gate and requested same-method
origin/devversus branch dashboard measurement were not completed. I polled the shared gate queue for over 60 minutes; unrelated integration/browser gates repeatedly started during the available windows. At this finish check, another integration gate was active, so I did not overlap it. The code confirms the 120 KiB budget uses gzip-compressed response bodies while the browser transfer metric sums Resource TimingtransferSize(including headers); the prior192879capture cannot be classified against118797gzip /127290transferred without the requested A/B capture. No dashboard regression conclusion is claimed.Audit read-path check:
safe_actionpreservesstream.session.attachandstream.session.detach;audit_pageapplies action allowlisting and details sanitization to every row; the UI renders the action generically. The HTTP test verifies attach retention and sentinel redaction. A contract gap remains recorded above: the details sanitizer dropssession_id,attachment_id, andreasonalthough §4.1 lists them. It was not changed because it is in the step-25 implementation, not caused by this dev merge.