feat: add canonical typed review identity model - #83
Conversation
Co-Authored-By: Codex <noreply@openai.com>
Co-Authored-By: Codex <noreply@openai.com>
🤖 Codex PR Review🚫 Merge blocked: 2 serious issue(s) found in high-risk files ⚖️ Codex Review Arbitration🚫 block: Both current blocking findings remain valid on the cumulative PR diff. First, the secret-leak finding is proven by the implementation: 🚫 Blocking IssuesThese issues must be fixed before this PR can be merged: 1. 🟠 [HIGH] Security in
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0270b353c9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Co-Authored-By: Codex <noreply@openai.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9520846df3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if anchors: | ||
| expected_kind = "identifier" if index % 2 == 0 else "operator" | ||
| if token["kind"] != expected_kind or (expected_kind == "operator" and token["value"] != "::"): | ||
| raise IdentityError("anchors must alternate identifier and ::") |
There was a problem hiding this comment.
Reject anchors that end with namespace separators
When anchors has an even number of tokens, e.g. [identifier("Namespace"), operator("::")], this positional check accepts it even though the normalized anchor represents an incomplete qualified symbol ending in ::. That lets malformed contract identities be hashed and verified as canonical records; require anchor lists to end on an identifier after enforcing the alternation.
Useful? React with 👍 / 👎.
| if any(not isinstance(record[key], str) or not _DIGEST.fullmatch(record[key]) for key in expected): | ||
| raise IdentityError("record contains invalid digest") | ||
| payload = {key: value for key, value in record.items() if key not in expected} | ||
| identity = validate_identity(payload) |
There was a problem hiding this comment.
Reject records that are not already canonical
When verify_identity_record() is given a record whose payload is merely normalizable, such as scope.repo set to AcMe/Audit-Bridge with digests computed for the lowercase canonical payload, this call re-canonicalizes the payload and accepts the record instead of rejecting the non-canonical JSON it actually received. That undermines verification for stored or signed records because altered-but-equivalent text can pass digest checks; compare the supplied payload to identity.payload before returning.
Useful? React with 👍 / 👎.
| _CATEGORIES = frozenset({"bug", "contract", "logic", "performance", "reliability", "security"}) | ||
| _SEVERITIES = frozenset({"critical", "high", "medium", "low"}) | ||
| _OWNER = re.compile(r"^[A-Za-z0-9](?:[A-Za-z0-9-]{0,37}[A-Za-z0-9])?$") | ||
| _REPO = re.compile(r"^[A-Za-z0-9._-]{1,100}$") |
There was a problem hiding this comment.
Reject dangling identifier punctuation
The identifier pattern accepts malformed symbols such as Class., module..name, or validate-() because dots and hyphens are allowed anywhere before the optional call suffix. In those cases the strict typed identity layer will hash and verify incomplete or ambiguous symbol tokens as canonical contract identities; require non-empty identifier segments and a real identifier before ().
Useful? React with 👍 / 👎.
|
Superseded by bounded fresh-main replacement #84. This PR remains frozen and will not be merged. |
Summary
Scope
This is R1 of the replacement chain for superseded PR #82. It introduces only the secret-free typed identity model and focused tests. It does not add reviewer adaptation, evidence binding, persistence/history, workflow changes, or runtime adoption.
Validation
python3 -m unittest tests.test_canonical_typed_identity(6 passed)python3 -m unittest tests.test_run_codex_pr_review(54 passed)python3 -m unittest discover tests(626 passed, 1 skipped)python3 -m ruff check .python3 -m compileall -q service scripts testsactionlint .github/workflows/*.ymlgit diff --check origin/main...HEAD