Repository navigation
Git history proof: reject raw commits missing or duplicating the author header #86
Description
Verified implementation finding (2026-10-23)
PR #81 head: a4761daa9fa87026ea106a3d722e7299b3de3b8b (target release/0.6.0).
Source: src/devostasis/codeanalysis/history_proof.py::commit_headers, blob f5f0445cba726571b88ac77fec6f440e58e22c78.
The parser checks exactly one tree and one committer header, but it does not check author header count. The same structural parser is used for independently checking raw historical commit objects. A Git-object digest proves byte integrity, not that the bytes form a well-shaped Git commit.
Reproduction and evidence
In a disposable Git repository, create a raw commit with a valid tree and committer, but without any author line. Repeat with two author lines. Write each raw commit with git hash-object --literally -t commit -w --stdin, and inspect with git fsck --strict.
On Git 2.47.3, independently repeated with both SHA-1 and SHA-256:
- valid single-author commit:
fsckexit 0, isolated exact-sourcecommit_headers()accepts it; - missing author:
fsckexit 1 (missingAuthor), isolated exact-source parser accepts it; - duplicate author:
fsckexit 1 (multipleAuthors), isolated exact-source parser accepts it.
This is a confirmed parser-level inconsistency in the exact code at PR #81 head. End-to-end code verify/historical bundle acceptance is not yet tested and must not be assumed. This is distinct from #82 (Git tree ordering/duplicates) and #83 (persisted Integrity carrier arrays). Searching open and closed repository issues for missingAuthor, multipleAuthors, and commit-author header shape found no dedicated duplicate.
Proposed bounded implementation
In the commit header admission path, require exactly one syntactically valid author header while retaining existing tree/parent/committer checks. This is format validation only: it does not authenticate the person's identity, and it must not alter Git hashes, report semantics, history windows or model-free runtime.
Acceptance criteria
- Add regression cases for missing, duplicated, and malformed author headers for SHA-1 and SHA-256, validating the real raw-object admission/verification path rather than only a copied function.
- Positive controls must preserve ordinary root commits, merge commits and multiline
gpgsigheaders. Avoid rejecting supported legitimate Git formats. - Confirm full offline pytest, v1/v2 historical verification, sample bundles and exact-head CI before any qualifying merge. Unknown/not-run checks are not PASS.
- Record any new structured admission behavior in the existing Code Analysis specification/conformance map, without reassigning permanent case identifiers.
Related PR: #81; related structural hardening: #82. Issue #83 remains independent.
Evidence limits: native Git and isolated parser reproduction passed; full Devostasis pytest/replay was NOT_RUN.
Activity
andy-zen-dev commentedon Oct 23, 2026
Implementation handoff for #86, scoped to PR #81 exact head
a4761daa9fa87026ea106a3d722e7299b3de3b8b(src/devostasis/codeanalysis/history_proof.pyblobf5f0445cba726571b88ac77fec6f440e58e22c78).The existing
commit_headers()validates one tree and one committer but does not count or validateauthor. A minimal candidate fix:Preserve the existing committer, tree, parent and timestamp rules. This is raw format admission, not identity authentication. Do not change historical bundles or semantic policies.
Independent bounded checks run today: original extracted exact-source parser 6/24 expected outcomes (18 invalid author variants falsely accepted); patched parser 24/24; native Git 2.47.3
git fsck --strictin disposable SHA-1/SHA-256 repos 22/22 across root, multiline gpgsig, missing/duplicate author, malformed name, date and timezone. The parser-only merge control is not a native fsck claim. A prospective parametrized 20-case pytest addition exercises actualhistory_proof.graph()with raw commit bytes and exact framed hashes; it has been syntax-checked, NOT_RUN in Devostasis. The patch was syntactically validated and applied only to an isolated exact-context stub, not to the complete repo.Acceptance still requires applying it to the release-branch head, running the real
tests/test_code_history_proof.py, complete pytest, v1/v2 and sample historical verification, docs/spec alignment, exact-head CI, then an independent later-wake review. No code has been committed; connected identityandy-zen-devhaspull=true,push=false. This comment does not claim full Git fsck equivalence or release readiness.2026-10-23 correction to the proposed patch (same PR #81 exact HEAD)
The preceding candidate code snippet is not yet safe to adopt unchanged. A fresh bounded native Git 2.47.3
git fsck --strictoracle, with one disposable repository per case and both SHA-1/SHA-256 formats, found discrepancies that were absent from the original 22-case set. The first candidate accepts hash-valid but invalid author identities containing embedded NUL, extra</>characters in the name/email, and out-of-range positive author epochs. It also rejects a whitespace-only but nonempty author name which native Git accepts; Git also accepts a nonempty author name with empty email (Name <>).40/40 native-oracle cases matched by the refined standalone parser; original exact-head extracted function matched 10/40; earlier candidate matched 24/40. These numbers are for isolated parser checks against real Git objects, not full Devostasis tests or proof of complete Git-format parity.
Refine the candidate after
author_name, delimiter, author_email = author_identity.rpartition(b" <"):Keep
len(authors) == 1in the original shape check. Positive controls: regular and Unicode names, empty email, whitespace-only-but-nonempty name, maximal signed-64-bit epoch, multilinegpgsig. Negatives: missing/duplicate author, stray angle brackets, NUL, overflow, negative/zero-padded epoch and malformed timezone. A 32-variant prospectivegraph()pytest snippet is syntax-checked but NOT_RUN on an actual checkout.Full pytest, historical v1/v2 bundle replay, exact-head CI, real-code integration and later independent approval all remain NOT_RUN / NOT_PASS. No commit/branch/PR created:
andy-zen-devstill haspull=true,push=false. The #81/#75 release gates are unchanged.andy-zen-dev commentedon Oct 23, 2026
2026-10-23 follow-up: Git commit header ordering and non-semantic trailing
parentExact reviewed source: PR #81 head
a4761daa9fa87026ea106a3d722e7299b3de3b8b,src/devostasis/codeanalysis/history_proof.py::commit_headers(), blobf5f0445cba726571b88ac77fec6f440e58e22c78. I am correcting the earlier author-only patch proposal in this same Issue; there is no new PR/commit.Confirmed new correctness gap: the current source and the previously proposed author-refinement candidate scan all
parentlines anywhere in a hash-valid raw commit. Git only treats the contiguousparentprefix aftertreeand beforeauthoras ancestry. With a syntactically validparent <real-oid>aftercommitter, Git 2.47.3git fsck --strictaccepts the commit, butgit rev-list --parentsreports zero parents. The earlier candidate incorrectly derives one parent. This can poison claimed historical roots/ancestry even when object hashes are correct; it is not merely cosmetic ordering. Separately, the earlier candidate accepts invalid interleavedauthor/committerheaders and a NUL in an unrelated header.Fresh isolated verification: 38 header-format variants × SHA-1/SHA-256 = 76/76 Git-admission verdicts matched by the combined candidate (prior refined candidate 50/76, 26 mismatches). An independent 8-placement × two-format 16/16 test also compared Git
rev-list --parentsparent counts with the candidate for all admitted commits. Proposedgraph()regression cases: 22/22 PASS only in an extracted-function harness with local dependency stubs, NOT a real Devostasis checkout. Combined patch applies to the exact isolated originalcommit_headers()text and compiles. Native rejection viagit update-refis distinguished fromfsckin the evidence.Bounded combined patch candidate (extends the earlier author fix, without new contract semantics):
Required acceptance: add real SHA-1/SHA-256
graph()regressions for reordered/interleaved headers, header NUL, normal root/parent/merge, and multilinegpgsig; specifically assert post-committerparentis an extension, not ancestry, while prefix parent remains an ancestry edge. Full pytest, conformance and historical v1/v2 replay, exact-head CI and fresh independent review remain NOT_RUN / NOT_PASS. No approval or merge is warranted yet.andy-zen-devstill haspull=true,push=falseon upstream.andy-zen-dev commentedon Oct 23, 2026
2026-10-23 additional exact-head QA: the proposed #86 fix still needs symmetric committer admission
Source: PR #81
a4761daa9fa87026ea106a3d722e7299b3de3b8b,src/devostasis/codeanalysis/history_proof.py::commit_headers(blobf5f0445cba726571b88ac77fec6f440e58e22c78). This refines—not supersedes the ancestry-order finding in—the preceding comment.The combined candidate hardens
authorbut still parsescommitterusing onlyidentity.endswith(b">")andepoch.lstrip(b"-").isdigit(). A hash-valid commit withcommitter Name> <a@b> 1700000000 +0000,committer Name <a@b> 01 +0000, or a negative committer epoch is accepted by that candidate, while Git 2.47.3fsck --strictrejects it (verified on both SHA-1 and SHA-256). Conversely, Git accepts two spaces between the closing email bracket and epoch (Name <a@b> 1700000000 +0000), but the candidate rejects this valid form for author and committer.New independently executed oracle: 100 targeted variations × two object formats, each in a fresh repo using
hash-object --literally,update-ref, andfsck --strict: prior candidate 160/200 matches; refined symmetric parser 192/200. The earlier 38-variation × two-format matrix still matches 76/76 after refinement. The remaining eight mismatches (across both formats) are intentional conservative rejections, not false acceptance: the signed-64-bit maximum committer timestamp cannot be represented by Pythondatetime, and Git accepts trailingauthor,committer, ortreeextension headers that this strict proof parser rejects as duplicates. Do not claim complete equivalence with Git.Implementation refinement: use one helper for both identities and dates. Split on the final two ASCII spaces, then strip only extra ASCII spaces from the identity's right edge before checking
name <email>; reject extra angle brackets; require unsigned, non-zero-padded decimal epoch bounded to signed 64-bit and a signed four-digit zone. Feed the validated committer epoch into the existing UTC timestamp conversion. Keep the previously verifiedtree, parent*, author, committerprefix and derive ancestry only from its contiguous parent prefix. This is structural admission only, not identity authentication or a Vital semantic-policy change.Required integration regression: include malformed committer name/email, negative/zero-padded committer epoch, valid double-space identity/date in both roles, normal roots/merges, trailing non-ancestry
parent, and multilinegpgsig, for SHA-1 and SHA-256; run through real history-proof admission rather than only extracted functions.Verification boundary: candidate code compiles; the generated unified diff dry-runs against the isolated exact function text. Full Devostasis pytest, historical replay, real-module integration, upstream CI, and later independent acceptance remain NOT_RUN / NOT_PASS. This is a ready implementation handoff, not a commit or merged fix. Authenticated
andy-zen-devremainspull=true,push=false.2026-10-24 consolidated executable candidate / Git-oracle qualification
At PR #81 exact HEAD
a4761daa9fa87026ea106a3d722e7299b3de3b8b, I consolidated the earlier #86 author, committer, header-order and ancestry corrections into one proposedcommit_headers()patch plus one shared_checked_commit_person()validator. Source target:src/devostasis/codeanalysis/history_proof.py, original blobf5f0445cba726571b88ac77fec6f440e58e22c78.Concrete behavior: require
tree, parent*, author, committeras the commit prefix; count one author/committer; derive ancestry only from the contiguous prefix parents; reject NUL in the header; format-check both identities and their unsigned canonical epochs/timezones; preserve legitimately empty email/whitespace-only name/double spaces before epoch and multilinegpgsig. Hash integrity alone is insufficient. The candidate deliberately rejects ambiguous trailing duplicate author/committer extension fields, although Git fsck accepts them; this is a stricter, explicitly scoped offline-proof admission policy, not full Git fsck equivalence.New independent executable QA: Python 3.13.5, Git 2.47.3, 22 cases × SHA-1/SHA-256 in fresh disposable Git repositories. Native Git and the candidate agree on 40/44 admission verdicts; the remaining 4 are the stated conservative rejects. Therefore 44/44 cases meet the explicitly qualified candidate policy, including Git
rev-list --parentschecks for ordinary prefix ancestry versus a trailing extensionparent. The original extractedcommit_headersparser disagreed with native Git on 24/44 cases. A unified one-function patch passedgit apply --check, application, and Python compilation only in a synthetic exact-function context. The source is still unchanged in GitHub.Prepared handoff checksums: unified patch SHA-256
d2e25d4579f3e5989512664decaa30d0e75d2be5f19a44fbdb9a4ff66591c669; runnable native-Git oracle SHA-256f737b44f1a984419b413042eac8f1a06ed5b32c1cedbfa4fe5fcbb6ef256302f. Files are available as an attachment in this run's delivery, not as GitHub source files.Required before closure: apply to a real feature checkout targeting
release/0.6.0after confirming head/blob, add actualgraph()andcode verifyregressions on both hash formats, run complete pytest plus historical/sample replay and installed-package gates, obtain exact-head CI and later independent review. Those repository-level checks are NOT_RUN, upstream workflows areaction_required(NOT_PASS). GitHub identityandy-zen-devispull=true,push=false; 0 commits/PRs/merges from this handoff.