Skip to content

@objectstack/core's operation-private-keys pin SCANS .tsx but its declared radius covers only .ts — the #7802 blind spot, one extension wide #15090

Description

@baozhoutao

Found while implementing a tree-scoped absence pin (#14878, PR #15085) and reading the two in-tree precedents for that shape. Recording only — no severity asserted, unassigned.

The mismatch, at origin/main 89eb997d8

packages/core/src/security/operation-private-keys.pin.test.ts walks the repo with git ls-files and filters the candidate set with:

const isScannedSource = (path: string) => /\.tsx?$/.test(path) && !path.endsWith('.d.ts');

/\.tsx?$/ matches .ts and .tsx. Its declared radius in scripts/cross-package-test-inputs.mjs is:

'@objectstack/core': {
  globs: ['packages/**/*.ts'],
},

packages/**/*.ts does not cover .tsx. So the pin judges a population strictly wider than the population turbo re-runs it for.

Why that is the exact defect the declaration table exists to prevent

Both scoping layers check-cross-package-test-inputs drives are keyed on the declared globs: Layer A unions the package into the shard when the diff touches them, Layer B puts them in @objectstack/core#test's turbo inputs so the cache hash moves. A .tsx file under packages/ that declares its own OPERATION_PRIVATE_KEY_PREFIX or withoutOperationPrivateKeys would therefore be scanned by the pin and invisible to both layers — a fourth hand-copy landing on main with every PR reporting green, which is the #7802 shape the table was written to close.

⚠️ The gate cannot see this itself, and that is not a gate bug: the pin's paths come out of git ls-files/git grep, which the roster's literal collector deliberately cannot name (its header states that trade). The correspondence between scanner and glob is therefore prose-held here, and prose held a radius exactly once before, in #9763.

The sibling that got it right, and why it is the model

packages/types/src/driver-error-classification.callers.test.ts has the identical shape and the identical glob, and it narrows its scanner to .ts rather than widening the glob — with the reason written out:

⚠️ The EXTENSION boundary is .ts alone, and unlike the tree above that one is not free — it is a deliberate trade with a second gate. […] this package's declared radius is INHERITED as watch hints by check:cross-package-test-inputs, and the dispatch-gates self-test pins that no hint of that family reaches the realtime-hooks.test.tsx file in packages/client-react […] A glob here that covers .tsx makes that case fail.

Widening @objectstack/core's glob to .tsx is probably the wrong repair — it is the one the types header says breaks a scripts/pm/ self-test specimen owned by another lane. Narrowing isScannedSource to .ts is the cheap half; whoever takes it should measure the .tsx population under packages/ first (the types header measured 8 tracked .tsx files there, all with zero mentions of its own subject) and record what is lost, rather than assuming.

Measurement a fixer should redo rather than trust

git ls-files 'packages/**/*.tsx' | wc -l
git grep --files-with-matches --fixed-strings -e OPERATION_PRIVATE_KEY_PREFIX -e withoutOperationPrivateKeys -- packages | grep '\.tsx$'

Negative claims here should be paired with a positive control on the same command shape, the way that pin's own anti-vacuity tests are.

Dedup

One targeted search_issues pass. It was live rather than silently zero — the query returned the ancestor card #7284 (withoutOperationPrivateKeys is now hand-copied into three packages) as a hit. Nearest neighbour by shape is #8113 (a detector seeing only one idiom of the thing it pins); neither is this subject.

Refs: #7284 (the convergence the pin guards), #7802 and #9763 (the declaration table and the day prose held a radius), #14878 / PR #15085 (where this was noticed).

Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions