Skip to content

Port decoded legacy statement validation (3f-2a) - #122

Merged
schickling-assistant merged 3 commits into
mainfrom
port-legacy-statement-of
Nov 10, 2026
Merged

schickling-assistant merged 3 commits into
mainfrom
port-legacy-statement-of

Conversation

@schickling-assistant

@schickling-assistant schickling-assistant commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

Summary

3f-2a ports the decoded-statement structural guard from statement_of. The owned legacy Value API retains unknown fields, integer lexemes and empty string argv entries. It validates subject/digest shape, both predicate URIs, schema-version Python equality (including true and 1.0), change/tier/signer/observed/check/input fields, lowercase OIDs/digests, integer-only exit codes and timezone-aware ISO timestamps. Python whitespace includes U+001C..U+001F. Clock validation covers basic/extended calendar and ISO-week dates, arbitrary one-character date/time separators, partial times, comma/dot fractions and fractional-second offsets. Candidate validity grants no signer trust.

Python source lines ported

Pinned oracle cff667c (v0.6.0), scripts/evidence-verify 637-665, with the parse_time zoned-time condition at 655-657. The source file is unchanged. README and PROVENANCE record the boundary.

Split plan

The complete byte-oriented statement_of needs a further 3f-2b slice: Python-compatible JSON byte decoding at 635-636 and exception handling at 666-667. This includes UTF-16/32/BOM handling, NaN/Infinity, lone surrogates, recursion and integer conversion limits. The existing shared Rust JSON decoder deliberately has narrower limits; this change does NOT silently substitute that decoder for Python's loader. The public guard takes a decoded Value, not bytes. Tests use the existing parser only to construct ordinary-JSON fixture values.
The decoded guard plus its differential matrix uses almost the entire 280-line cap; adding a correct byte decoder and its distinct fixtures cannot fit here. After 3f-2b, 3f-3 ports read_statement/load and the owned cache; signature integration, 3g selection and 3h require_all follow. CLI/native behavior remains unchanged. The projection OID/end-of-options and input_git output-bound Janitor P3s do not touch this code and remain the next focused hardening slice before wiring.

Differential tests

legacy_statement_shapes_match_oracle compares the public structural guard with unchanged statement_of on ordinary JSON: valid/missing/wrong fields; schema boolean/float distinctions; both predicate URIs; subject/digest shape; whitespace; tier and signer types; runner/input/check/argv/hash types; empty checks/argv strings; integer/float/bool exits and 100/4300/4301-digit integers; calendar/week/basic dates, arbitrary Unicode separators, zones, comma and submicrosecond fractions, offset seconds/normalization, naive timestamps, bad dates/hours/year/offsets. It checks a retained change_id in returned data; empty argv strings remain exercised by the accepted baseline and matrix. Rust differential tests have not run locally; hosted failure corrections are recorded below.

Evidence

On dev3, pinned rustfmt 1.9.0 from /nix/store/jpcqlbhkwxwvq507mq0hkacpxbxcdwjj-rustfmt-1.98.1 (nixpkgs 4ba99f3209788ed04f01af38f77ddb803ad6ec63) formatted the changed Rust files with repo rustfmt.toml. A subsequent rustfmt --check --config-path rustfmt.toml on statement.rs, statement_tests.rs and legacy_verify.rs exited 0.
On dev5, prepared the pinned shell with:
gate-slot --class eval --max-wait 1800 --max-hold 600 -- nix develop --override-input fractal-fixture path:/var/tmp/mergemaster-port3f-fractal --no-write-lock-file --profile /var/tmp/mergemaster-statement-shell --command true
This admitted after 1618s and exited 0. The override source is the exact e2721e52 Git archive transferred in 3f-1; Python oracles retain their pinned store paths.
Attempted all requested checks through a Python runner importing the shell profile's exported environment, with CARGO_TARGET_DIR=/var/tmp/mergemaster-statement-target:
gate-slot --lane build --profile disk=cargo-cold --max-wait 1800 -- python3 /var/tmp/mergemaster-statement-verify.py
Build admission never occurred (38 initially ahead); gate-slot withdrew with max-wait exit 94 at 2026-11-10T18:37:50Z. No runner command or Cargo process executed. Stopped remote attempts at the required 30-minute build-admission ceiling. No Cargo targets were created under ~/.megarepo.

NOT RUN

  • cargo fmt --all --check (direct pinned rustfmt check passed locally instead)
  • cargo clippy --locked --offline -p mergemaster-evidence --all-targets -- -D warnings
  • cargo test --locked --offline -p mergemaster-evidence legacy_statement_shapes_match_oracle
  • cargo test --locked --offline -p mergemaster-evidence (full crate suite)
  • Local cargo check (optional fallback was not used), Nix checks, hosted CI, CLI cutover, push or PR publication.

CI review correction

Chrono validates calendar values only after an exact ASCII date-shape check:
YYYY-MM-DD, YYYYMMDD, YYYY-Www[-D] or YYYYWww[D]. This rejects Chrono's otherwise
permitted short/signed/space-prefixed numeric fields before parsing. The differential
matrix now includes all four reported failures (2026-1-1T12:00Z, 2026-W1T12Z,
26-01-01T12Z, 2026- 1-01T12Z), plus an explicit 2026-01-01T24:00Z case alongside
the existing T24Z case. No broadening of the accepted timestamp grammar is intended.

OID parity: evidence/mod.rs:213-221 requires byte length 40 or 64 and every byte
to be ASCII 0-9/a-f. This is exactly Python's full lowercase OID regex, including
its strict end anchor (LF/CR/trailing bytes fail). Existing gate integration tests
legacy_tree_record_indexes_match_real_oracle exercise SHA-1/SHA-256, uppercase
and newline refusals through this helper; legacy_input_indexes_and_note_presence_match_real_oracle
also covers uppercase and 39/64-character input keys. There is no claimed standalone oid unit test.

Pinned CI Python: flake.nix's evidence check uses pkgs.python3 from nixpkgs
4ba99f3209788ed04f01af38f77ddb803ad6ec63; the prepared shell uses that same
interpreter with packages. Its executable
/nix/store/6cg92xlgwwwl88fiwrid0l924fmy8slp-python3-3.14.7-env/bin/python3
reported Python 3.14.7 on dev5. Calendar/week and 24:00 expectations come from
the oracle under this pinned interpreter, not the host's ambient Python.
Pinned local rustfmt formatting and --check passed again after the correction.

Hosted fixture failure correction: the mutation matrix includes /predicate/observed/inputs,
so the baseline now explicitly declares inputs: {} before pointer_mut is used.
A separate case removes that key again to retain coverage of the optional-inputs default.
No dev3 Cargo tests were attempted; Fleet Load r179 permits only the optional small check there.

Repair verification attempt on dev5:
gate-slot --lane build --profile disk=cargo-cold --max-wait 1800 -- python3 /var/tmp/mergemaster-statement-verify-fix.py
The already prepared pinned shell environment and /var/tmp target were reused.
No admission: initially 34 ahead; withdrew at 2026-11-10T19:15:03Z after 1801s,
exit 94. No Cargo command ran. Clippy, focused oracle test and full suite remain
NOT RUN for the repair. Stopped at the 30-minute admission ceiling; no dev3 test fallback.

Fraction and midnight correction

The same clock guard now requires seconds before either a local-time fraction
or an offset fraction (basic length 6 / extended length 8). Whole-hour/minute
offsets remain allowed when they have no fraction. The expanded matrix covers
both refused partial fractions and accepted basic/extended offset-second fractions.

The requested local oracle pass also found that pinned Python 3.14.7 ACCEPTS
24Z and 24:00Z, rolling to the next date. The guard now accepts only zero-valued
24-hour times, using Python's first-six-fractional-digits truncation, and refuses
overflow beyond 9999-12-31. This closes a conservative mismatch already present
in the matrix, rather than waiting for another hosted failure.

Executed locally on dev3 with
/nix/store/6cg92xlgwwwl88fiwrid0l924fmy8slp-python3-3.14.7-env/bin/python3
and runpy.run_path('/nix/store/bbj5s0bmhsv4a9mjqb97x80r8dvkas45-source/scripts/evidence-verify')['parse_time'].
Every matrix timestamp was extracted directly from the Rust concat fixture.
An additional 108 local-time/offset combinations were probed, including partial
times, fractions before seconds, offset hours/minutes/seconds and normalization.
A Python transcription of the intended Rust clock/shape/rollover guards matched
all 145 oracle verdicts. This is NOT a Rust test/build claim; calendar validity
in the transcription used Python date.fromisoformat after the same exact shape guard.
Pinned rustfmt --check passed again. Cargo checks remain NOT RUN locally.

Python aware-time verdict table (intended Rust guard agrees on every row):
2026-01-01 false
2026-01-01T12:30:00 false
20260101T1230Z true
2026-W01-1T12Z true
2026W011T12Z true
2026-W01T12Z true
2026W01T12Z true
2026-01-01🐍12:30:00,123456789+013045.25 true
2026-01-01Z12Z false
2026-01-01T12.5-00 false
2026-01-01T24Z true
2026-01-01T24:00Z true
2026-1-1T12:00Z false
2026-W1T12Z false
26-01-01T12Z false
2026- 1-01T12Z false
2026-02-30T12Z false
0000-01-01T12Z false
2026-01-01T12+24:00 false
2026-01-01T12+00:99 true
2026-01-01T12+23:59:59.99 true
2026-01-01T12+ false
2026-01-01T1Z false
2026-01-01T1230.5Z false
2026-01-01T12:30.5Z false
2026-01-01T12+01.5 false
2026-01-01T12+0130.5 false
2026-01-01T12+01:30.5 false
2026-01-01T12+013045.5 true
2026-01-01T12+01:30:45.5 true
2026-01-01T12+00:00:99 true
2026-01-01T12+23:59:60 false
2026-01-01T24:00:00.0000001Z true
2026-01-01T24:00:00.1Z false
2026-01-01T24:00:01Z false
2026-01-01T24:01Z false
9999-12-31T24Z false

Posted on behalf of @schickling
field value
agent_identity agent/compoundingtech/mergemaster
session 01a19dbc
agent_persona generalist
agent_supervisor unavailable
agent_tool OMP
agent_tool_version 18.12.5
agent_runtime OMP 18.12.5
agent_model anthropic/claude-opus-5-5
worktree port-legacy-statement-of/port-legacy-statement-of

@schickling-assistant

Copy link
Copy Markdown
Contributor Author

U04 exposure audit: PASS at exact head 57ba5a336de55e948abefb4e79d1001bb8b0b3e2 (rust-port slice 3f-2a, decoded legacy statement validation).

  • CI 42885318002 succeeded (pull_request, PR list contains Port decoded legacy statement validation (3f-2a) #122). Release 42885317965 succeeded.
  • Hosted test evidence: both checks jobs (x86 and ARM) printed test evidence::legacy_verify::statement::tests::legacy_statement_shapes_match_oracle ... ok, the differential test against the pinned Python statement_of. This test failed at c89b7242 (fixture) and at 7d98ae47 (observed_at 2026-01-01T12.5-00 was accepted by Rust and refused by Python).
  • All 3 commits are verified. A merge-tree against main 852b6ff88dae7520df009587687a623ac3add3b8 is clean.
  • Review of legacy_verify/statement.rs:
    • statement_of is a structural guard on an already decoded value. It grants no signature or signer trust, and no caller uses it yet; record loading and signature checks follow in 3f-2b, 3f-3 and 3g.
    • Slicing uses get or indices from find, so no input can make it panic. Exit codes are integer lexemes up to 4300 digits; digests are 64 lowercase hex characters.
    • Timestamps: exact ASCII date shapes come before chrono. A fraction is accepted only after seconds. Hour 24 is accepted only as 24:00 with a zero fraction and without rollover past year 9999, as in Python 3.14.7.
    • No change to credentials, workflows, dependencies or network surface.
  • No findings.

Signed: Janitor (agent/dotfiles/janitor).

Posted on behalf of @schickling
field value
agent_identity agent/dotfiles/janitor
session 01a1a1ea
agent_persona generalist
agent_supervisor unavailable
agent_tool OMP
agent_tool_version 18.12.5
agent_runtime OMP 18.12.5
agent_model anthropic/claude-opus-5-5
worktree unknown

@schickling-assistant
schickling-assistant marked this pull request as ready for review November 10, 2026 20:04
@schickling-assistant
schickling-assistant merged commit 496506a into main Nov 10, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant