INTB-279: identify Tabellio v0.6.0 runners - #44
Conversation
Entire-Checkpoint: 29c1c7c761ec
|
Linked to Plane Work Item(s) References This comment was auto-generated by Plane |
Entire-Checkpoint: 29c1c7c761ec
Entire-Checkpoint: 1a7858ccb0d6 Entire-Checkpoint: 29c1c7c761ec
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 27e8475655
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| } | ||
|
|
||
| async function readGitSourceIdentity(root, packageVersion) { | ||
| const revision = await runGit({ args: ["rev-parse", "HEAD"], cwd: root }); |
There was a problem hiding this comment.
Stop binding packaged installs to the consumer repo
When Tabellio is installed under another Git checkout, such as a consumer project's node_modules, this git rev-parse HEAD walks up to the consuming repository because the package directory has no .git. tabellio-version and v0.4 validation results then record the consumer commit/status/tag as the runner source instead of reporting unavailable source identity, so provenance can falsely validate an unrelated project commit. Please fence Git discovery to the package checkout or return null unless the package root is itself a Git worktree.
Useful? React with 👍 / 👎.
| requiredString(value.packageName, "validation result.runner.packageName"); | ||
| requiredString(value.packageVersion, "validation result.runner.packageVersion"); |
There was a problem hiding this comment.
Enforce package identity in the runtime reader
For v0.4 results validated through the repository's runtime path (check-tabellio-validation --result or latestValidationResult), any non-empty runner.packageName and arbitrary package version currently pass even though the v0.4 schema pins packageName to @intelip/tabellio and the release contract is about Tabellio's package identity. This lets mispackaged or forged runner evidence satisfy the new identity checks whenever consumers use the built-in validator instead of an external JSON Schema validator.
Useful? React with 👍 / 👎.
| } | ||
| }, | ||
| "revision": { | ||
| "$ref": "validation-result.v0.3.schema.json#/$defs/revision" |
There was a problem hiding this comment.
Use resolvable refs in the v0.4 schema
Because this schema declares an absolute URN $id, this relative $ref is resolved under that URN rather than to the packaged validation-result.v0.3.schema.json file. External JSON Schema validators that load v0.4 by id or from the file can therefore fail to resolve the shared definitions for every v0.4 result; use internal definitions or refs keyed to the v0.3 schema id.
Useful? React with 👍 / 👎.
| assert.equal(result.result.runner.packageVersion, "0.6.0"); | ||
| assert.match(result.result.runner.sourceCommit, /^(?:[0-9a-f]{40}|[0-9a-f]{64})$/); | ||
| assert.equal(typeof result.result.runner.sourceDirty, "boolean"); | ||
| assert.equal(result.result.runner.releaseTag, null); |
There was a problem hiding this comment.
Allow release tags in the runner identity test
Once the approved v0.6.0 tag exists on the release commit, tabellioRunnerIdentity() returns that tag for this checkout, so this assertion makes npm test fail on the released source even though that is the desired post-release identity. Avoid pinning null here, or use a no-tag fixture, so checks keep passing after the release tag is created.
Useful? React with 👍 / 👎.
Entire-Checkpoint: d123a88b9899 Entire-Checkpoint: 29c1c7c761ec
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c20ba5467f
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| const expectedCommit = options.expectRef | ||
| ? verifiedCommit((await runGit({ | ||
| args: ["rev-parse", "--verify", "--end-of-options", `${options.expectRef}^{commit}`], | ||
| cwd: process.cwd(), |
There was a problem hiding this comment.
Resolve expected refs in the runner checkout
Although the identity lookup is now fenced to the package root, this expectation check still resolves --expect-ref in the caller's current directory. When tabellio-version is invoked via an installed bin or absolute script path from outside the Tabellio checkout, HEAD is looked up in the caller repo (or fails outside any repo) while identity.sourceCommit comes from the runner package, producing a false source_commit_mismatch/blocked result for the same runner; resolve the expected ref against the runner checkout or compare full OIDs without using the caller cwd.
Useful? React with 👍 / 👎.
| "releaseTag": { | ||
| "oneOf": [ | ||
| { | ||
| "type": "string", | ||
| "pattern": "^v(?:0|[1-9][0-9]*)\\.(?:0|[1-9][0-9]*)\\.(?:0|[1-9][0-9]*)(?:-[0-9A-Za-z.-]+)?$" |
There was a problem hiding this comment.
Tie releaseTag to packageVersion in the schema
Because the v0.4 schema only checks that releaseTag looks like some version tag, an external JSON Schema validator will accept a runner such as packageVersion: "0.6.0" with releaseTag: "v9.9.9"; the runtime reader rejects that mismatch, but consumers relying on the published schema can still treat forged or stale release identity as structurally valid. Pin the tag to the package version for this schema version, or otherwise make mismatches invalid in the schema contract.
Useful? React with 👍 / 👎.
| } | ||
|
|
||
| async function readGitSourceIdentity(root, packageVersion) { | ||
| const worktree = await runGit({ args: ["rev-parse", "--show-toplevel"], cwd: root }); |
There was a problem hiding this comment.
Sanitize ambient Git environment before reading identity
This call still inherits GIT_DIR/GIT_WORK_TREE through runGit, so an environment that sets GIT_WORK_TREE to the package directory and GIT_DIR to some other repository makes the realpath fence pass while rev-parse HEAD, status, and tag --points-at report the unrelated Git dir as a clean released Tabellio source. Fresh evidence is that this bypass works even for a non-Git package directory, so clear ambient Git repository variables or otherwise bind the .git directory to the package checkout before recording runner provenance.
Useful? React with 👍 / 👎.
Entire-Checkpoint: 80c483965edd Entire-Checkpoint: 29c1c7c761ec
Entire-Checkpoint: 8648bed8c3f0 Entire-Checkpoint: 29c1c7c761ec
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ff12eca263
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| dirty: status.stdout.length > 0, | ||
| releaseTag: matchingReleaseTag(tags.stdout), | ||
| fingerprint: await worktreeFingerprint(root, commit, status.stdout), |
There was a problem hiding this comment.
Check index bits before declaring clean source
This clean check can be bypassed in checkouts where a tracked runner file has Git's assume-unchanged or skip-worktree bit set: git status and the later git diff HEAD used for the fingerprint both ignore the modified contents. I reproduced this by marking scripts/lib/runner-identity.mjs with each bit, editing it, and tabellioRunnerIdentity() still returned sourceDirty: false, so release/validation provenance can claim a clean tagged commit while executing different local code; clear or detect these index bits, or hash tracked worktree contents, before marking the runner clean.
Useful? React with 👍 / 👎.
| "requiredValidatorTypes": ["static", "schema", "semantic", "workflow", "operational", "security"] | ||
| }, | ||
| "validators": [ | ||
| {"id": "v060-identity-static", "type": "static", "argv": ["node", "scripts/tabellio-validator.mjs", "--profile", "v060-identity-static", "--validator-id", "v060-identity-static", "--out", ".artifacts/tabellio/v060-identity-static.json"], "cwd": ".", "timeoutMs": 300000, "required": true, "evidence": {"path": ".artifacts/tabellio/v060-identity-static.json"}, "policy": {"metricThresholds": [{"metric": "runner_identity_static_pass", "operator": "eq", "value": 1}], "maxCostUsd": 0, "requireCostTelemetry": true}}, |
There was a problem hiding this comment.
Ship the validator registry with the focused manifest
When this new packaged manifest is run from an npm install, these validators invoke scripts/tabellio-validator.mjs without --config, so the CLI looks for the default .tabellio/validators.json; I checked npm pack --dry-run --json, and that file is absent from the published file list because the package allow-list only includes the validation JSONs and scripts. The shipped tabellio.v060-identity.validation.json therefore blocks immediately with a missing registry instead of producing the promised v0.6.0 identity evidence, so either include .tabellio/validators.json in the package or make the manifest reference a packaged config.
Useful? React with 👍 / 👎.
| } | ||
|
|
||
| async function worktreeFingerprint(root, commit, status) { | ||
| const diff = await runGit({ args: ["diff", "--no-ext-diff", "--binary", "HEAD", "--"], cwd: root }); |
There was a problem hiding this comment.
Avoid buffering dirty source diffs for identity
For dirty runner checkouts with a large tracked text change, this full git diff --binary is captured through runGit's fixed output buffer before identity can be returned. I reproduced a checkout with a ~12 MB text diff where tabellioRunnerIdentity() failed with a git diff max-buffer error instead of emitting sourceDirty: true, so version checks and validation runs can block exactly when the contract says dirty source should remain visible; stream/hash the diff or fall back to a dirty fingerprint without requiring the entire patch in memory.
Useful? React with 👍 / 👎.
33ff5f7 to
642c078
Compare
Entire-Checkpoint: 5f2b26ae1e15
642c078 to
620e49f
Compare
Entire-Checkpoint: 79aed0fa931c
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8f57e196f4
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| }); | ||
| const refs = new Map(result.stdout.trim().split(/\r?\n/) | ||
| .filter(Boolean) | ||
| .map((row) => row.split(/\s+/))); |
There was a problem hiding this comment.
Fix remote tag parsing for release verification
When --require-release-tag reaches a real annotated origin tag, this parse stores the git ls-remote rows as [oid, ref] entries. I checked a local annotated-tag remote and git ls-remote --tags printed the object ID first and refs/tags/v0.6.0 second, so the later refs.get(directRef)/refs.get(peeledRef) lookups are keyed by ref and always miss. That makes verifyPublishedRunnerRelease return false before querying GitHub, so the documented release gate can never pass even after the annotated tag and release exist; swap the tuple to [ref, oid] before constructing the Map.
Useful? React with 👍 / 👎.
Entire-Checkpoint: a91d97f163c9
Entire-Checkpoint: 4370fb5a4f45
Entire-Checkpoint: d43fbf86bed8
Entire-Checkpoint: 7044872f4085
Entire-Checkpoint: 0c3674f381c8
Entire-Checkpoint: 00cd873c5d9a
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4b87fe5642
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| "summary": "Packaged artifact completeness and private-evidence boundaries" | ||
| }, | ||
| "v060-identity-static": { | ||
| "commands": [["node", "--test", "tests/runner-identity.test.mjs", "tests/validation-runner.test.mjs"]], |
There was a problem hiding this comment.
Ship tests used by identity validators
Fresh evidence after the registry was added: npm pack --dry-run --json now includes .tabellio/validators.json, but it still includes no tests/** files, while this packaged profile invokes tests/runner-identity.test.mjs and tests/validation-runner.test.mjs. Extracting the package and running this profile produces failed evidence (Could not find 'tests/runner-identity.test.mjs, tests/validation-runner.test.mjs'), so the focused v0.6 identity validation shipped in the npm package cannot pass from a packaged install unless the tests are shipped or these profiles are changed to use packaged checks.
Useful? React with 👍 / 👎.
|
|
||
| ## Unreleased | ||
|
|
||
| ## 0.6.0 - release candidate |
There was a problem hiding this comment.
Date the v0.6.0 changelog heading
When tabellio-release plan is used for this 0.6.0 candidate, the existing release planner rejects the current changelog because it specifically requires a heading matching ## 0.6.0 - YYYY-MM-DD before creating the release intent. Leaving this as release candidate means the documented release gates cannot pass for the version introduced here until this heading is converted to the dated release format.
Useful? React with 👍 / 👎.
|
Buildkite gate update for exact candidate
No subscription change or merge performed. Next gate: increase Buildkite quota or activate Pro, rerun required exact-head Buildkite CI, then request separate merge approval. |
Entire-Checkpoint: 0bdb97273214
ci: run Tabellio gates on macOS M4
Summary
releasedAcceptance
Plane: INTB-279
Contract: docs/intb-279-v060-execution-contract.md
Candidate: 4b87fe5
Entire checkpoint: 00cd873c5d9a
Evidence
validation-67f80c48-36b4-4303-8b33-d9f813f9b088, six required validator types, zero costvalidation-50f19084-f35e-4e2e-9cb6-bb30b950852d, ten validators, zero costBoundaries
No merge, tag, GitHub Release, deployment, billing, DNS, infrastructure, production-data, or consumer-repository mutation is authorized by this PR.