You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
attach-requires-parent-edit c3: #4757 multi-delete pin can't execute against the prebuilt @objectstack/core (stale-dist / CI) #7668
All 17 cases in packages/services/service-storage/src/attachment-access-hooks.test.ts error with:
TypeError: withoutOperationPrivateKeys is not a function
The predicate-less unscoped-multi-delete refusal (#4757) cannot be expressed over REST (deleteMany with no ids/where → 400 before the hook is reached), so it rests on this unit pin — which cannot run in the checkout, leaving #4757unguarded by an executable test here.
Root cause
Located — a build-ordering / CI test-infra gap, not a runtime defect. withoutOperationPrivateKeysis exported on origin/main at packages/core/src/security/operation-private-keys.ts:115 (and re-exported from packages/core/src/security/index.ts:145). The test resolves a stale built@objectstack/core that predates that export; the source is correct and the live server enforced every other gate in this item. The fix is a CI/build-ordering one: rebuild @objectstack/core before running the service-storage suite (or give the pin a live oracle).
Reproduction
Against the prebuilt tree, run attachment-access-hooks.test.ts → 17/17 error TypeError: withoutOperationPrivateKeys is not a function. Confirm git grep withoutOperationPrivateKeys origin/main -- packages/core/src/security/operation-private-keys.ts shows the export exists → the source is not missing the function; the built dist is stale.
Source
Extracted from the QA run #7635 (framework 92f26f7, console 6314e87f).
Dual-label resolution (queue+finding): promoted to pm:queue (finding stripped). Concrete, scoped CI/build-ordering fix with a named landing site — the #4757 pin's missing symbol is a stale prebuilt @objectstack/core, and withoutOperationPrivateKeys is verified exported at packages/core/src/security/operation-private-keys.ts:115 on origin/main @ 6a9dec6. domain:devx stands (test-infra/build ordering, not runtime code). No open duplicate found; #7671 cross-references this card as the owner.
Claim: PM loop round 4 (devx seat, 2026-08-11 term) — wave 4 unit B
Session: session_01GZKbx4xyF7U5WXj6ch49BM
Branch: claude/issue-7668-storage-test-build-order
Worktree: cloud session, own clone
Domain: domain:devx
File surface: the build-ordering fix face — expected turbo.json (test task deps) or the service-storage package's test config; the dev derives the true landing site and declares it in the PR (⛔ no product code, no checklist area files). If the right fix is instead a live oracle for the #4757 pin, that changes the surface into packages/services/service-storage test code — report the fork before implementing it.
Container & model: M, mode:cloud, model: opus
Serial constraints cleared: no other claim or open PR touches turbo.json or the service-storage test infra (checked at claim time). ⚠️ turbo.json is a shared hot file — merge origin/main before opening the PR.
premise_still_valid: true — reproduced from a clean checkout at origin/main @ 7a8476f before touching anything.
Root cause (my derivation, not the LEAD's guess)
Neither candidate in the brief is the defect.turbo.json already declares "test": { "dependsOn": ["^build"] }, and pnpm turbo run test --filter=@objectstack/service-storage builds core first and passes 352/352 on unmodified main. turbo.json is untouched by this PR.
The real cause is one directory down:
packages/services/service-storage ships no vitest.config.ts, so @objectstack/core resolves through the workspace link to packages/core/dist/index.js — a build artifact. The verdict of every unit pin in the package is a function of build state, not of the source in the checkout.
attachment-access-hooks.test.ts is the only executable guard on the #4757 predicate-less unscoped-multi-delete refusal (unexpressible over REST — deleteMany with no ids/where is rejected 400 before the hook). Against a prebuilt tree whose core dist predated the export it errored TypeError: withoutOperationPrivateKeys is not a function, while packages/core/src/security/operation-private-keys.ts:117 was correct throughout — matching the issue's diagnosis of stale dist, but locating the fixable seam in the package's test resolution rather than in task ordering.
The loud error is the mild half. A core dist merely behind rather than missing the symbol lets a pin run green against core's old behaviour — a passing test not testing the checkout, with nothing in the output saying so.
Why ordering can't fix it: turbo already orders correctly, so turbo run test was never the failing path. What broke are the paths turbo does not mediate — pnpm test in the package, vitest run <file>, an editor runner, a QA tree built at an older commit (how #7635 hit it). Those are exactly where a pin is re-run while someone is changing core. No dependsOn edit reaches them.
PR
#7778 (draft, base main, Fixes #7668) — branch claude/issue-7668-storage-test-build-order.
Landing site
2 new files, no product code and no test assertions changed:
packages/services/service-storage/vitest.config.ts — aliases @objectstack/core → packages/core/src/index.ts (anchored regex, array form, per the service-knowledge precedent; 10 packages already do this). Graph-wide aliasing keeps a single core instance for the deps still on dist; tsup externalizes workspace deps so none inline one.
turbo.jsonnot modified → the hot-file conflict risk in the claim does not apply. git merge origin/main was already up to date at push.
Reproduction / verification (commands + results)
Repro, clean tree, no dists — cd packages/services/service-storage && npx vitest run src/attachment-access-hooks.test.ts → Error: Failed to resolve entry for package "@objectstack/core" at attachment-access-hooks.ts:3.
turbo exonerated — pnpm turbo run test --filter=@objectstack/service-storage → 24 files / 352 passed, before any change.
Regression sweep (dist restored): bare npx vitest run in the package (the previously-broken path) → 352 passed; turbo run test → 352 passed; eslint on the new file → clean; pnpm check:published-files → ✓; pnpm check:empty-changeset → ✓.
Out-of-bounds findings — reported only, not fixed
The same hazard shape exists wherever a package with unit tests imports @objectstack/core and ships no vitest config. Fixed only the package this issue names; a repo-wide sweep — or a lint gate asserting the invariant — deserves its own issue.
service-storage's other runtime imports (@objectstack/spec/*, observability, platform-objects/*, objectql, types) still resolve to dist, so the suite still needs a build for those. Correct today (turbo orders it); no observed defect justifies widening the alias set now.
Not touched: no merge, no auto-merge, no merge queue, no content/docs/releases/**, no git stash. CI convergence and the ready flip are PM's. The known base red check:platform-checklist → coverage.json · qa: UNCLASSIFIED (#7347) is unrelated and was not pursued.
Activity
claude commentedon Aug 11, 2026
Dual-label resolution (queue+finding): promoted to
pm:queue(finding stripped). Concrete, scoped CI/build-ordering fix with a named landing site — the #4757 pin's missing symbol is a stale prebuilt@objectstack/core, andwithoutOperationPrivateKeysis verified exported atpackages/core/src/security/operation-private-keys.ts:115onorigin/main@6a9dec6.domain:devxstands (test-infra/build ordering, not runtime code). No open duplicate found; #7671 cross-references this card as the owner.本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
huangyiirene commentedon Aug 11, 2026
Claim: PM loop round 4 (devx seat, 2026-08-11 term) — wave 4 unit B⚠️ turbo.json is a shared hot file — merge origin/main before opening the PR.
Session:
session_01GZKbx4xyF7U5WXj6ch49BMBranch:
claude/issue-7668-storage-test-build-orderWorktree: cloud session, own clone
Domain:
domain:devxFile surface: the build-ordering fix face — expected
turbo.json(test task deps) or the service-storage package's test config; the dev derives the true landing site and declares it in the PR (⛔ no product code, no checklist area files). If the right fix is instead a live oracle for the #4757 pin, that changes the surface intopackages/services/service-storagetest code — report the fork before implementing it.Container & model: M,
mode:cloud,model: opusSerial constraints cleared: no other claim or open PR touches turbo.json or the service-storage test infra (checked at claim time).
Generated by Claude Code
huangyiirene commentedon Aug 11, 2026
premise_still_valid: true — reproduced from a clean checkout at
origin/main@7a8476fbefore touching anything.Root cause (my derivation, not the LEAD's guess)
Neither candidate in the brief is the defect.
turbo.jsonalready declares"test": { "dependsOn": ["^build"] }, andpnpm turbo run test --filter=@objectstack/service-storagebuilds core first and passes 352/352 on unmodifiedmain.turbo.jsonis untouched by this PR.The real cause is one directory down:
attachment-access-hooks.test.tsis the only executable guard on the #4757 predicate-less unscoped-multi-delete refusal (unexpressible over REST —deleteManywith noids/whereis rejected 400 before the hook). Against a prebuilt tree whose core dist predated the export it erroredTypeError: withoutOperationPrivateKeys is not a function, whilepackages/core/src/security/operation-private-keys.ts:117was correct throughout — matching the issue's diagnosis of stale dist, but locating the fixable seam in the package's test resolution rather than in task ordering.The loud error is the mild half. A core dist merely behind rather than missing the symbol lets a pin run green against core's old behaviour — a passing test not testing the checkout, with nothing in the output saying so.
Why ordering can't fix it: turbo already orders correctly, so
turbo run testwas never the failing path. What broke are the paths turbo does not mediate —pnpm testin the package,vitest run <file>, an editor runner, a QA tree built at an older commit (how #7635 hit it). Those are exactly where a pin is re-run while someone is changing core. NodependsOnedit reaches them.PR
#7778 (draft, base
main,Fixes #7668) — branchclaude/issue-7668-storage-test-build-order.Landing site
2 new files, no product code and no test assertions changed:
packages/services/service-storage/vitest.config.ts— aliases@objectstack/core→packages/core/src/index.ts(anchored regex, array form, per theservice-knowledgeprecedent; 10 packages already do this). Graph-wide aliasing keeps a single core instance for the deps still on dist; tsup externalizes workspace deps so none inline one..changeset/service-storage-tests-pin-core-to-source.md—patch.turbo.jsonnot modified → the hot-file conflict risk in the claim does not apply.git merge origin/mainwas already up to date at push.Reproduction / verification (commands + results)
Repro, clean tree, no dists —
cd packages/services/service-storage && npx vitest run src/attachment-access-hooks.test.ts→Error: Failed to resolve entry for package "@objectstack/core"atattachment-access-hooks.ts:3.turbo exonerated —
pnpm turbo run test --filter=@objectstack/service-storage→ 24 files / 352 passed, before any change.Decisive A/B — stripped the export from the built
packages/core/dist/index.js(source untouched) to recreate the exactattach-requires-parent-editc3: #4757 multi-delete pin can't execute against the prebuilt@objectstack/core(stale-dist / CI) #7668 condition:vitest.config.tsThe 17 reproduce the issue's count exactly, with its verbatim
TypeError: withoutOperationPrivateKeys is not a function. So the config is demonstrably what closes the hole —installAttachmentAccessHooksdoes not authorize an UNSCOPED multi-delete: no id + nowherereads as "nothing to authorize" anddeleteManyruns over the whole table #4757 now has a pin a build artifact cannot silence.Regression sweep (dist restored): bare
npx vitest runin the package (the previously-broken path) → 352 passed;turbo run test→ 352 passed;eslinton the new file → clean;pnpm check:published-files→ ✓;pnpm check:empty-changeset→ ✓.Out-of-bounds findings — reported only, not fixed
@objectstack/coreand ships no vitest config. Fixed only the package this issue names; a repo-wide sweep — or a lint gate asserting the invariant — deserves its own issue.service-storage's other runtime imports (@objectstack/spec/*,observability,platform-objects/*,objectql,types) still resolve to dist, so the suite still needs a build for those. Correct today (turbo orders it); no observed defect justifies widening the alias set now.Not touched: no merge, no auto-merge, no merge queue, no
content/docs/releases/**, nogit stash. CI convergence and the ready flip are PM's. The known base redcheck:platform-checklist→coverage.json · qa: UNCLASSIFIED(#7347) is unrelated and was not pursued.Generated by Claude Code
test(runtime): resolve @objectstack/platform-objects to source in vitest
test(service-storage): resolve `@objectstack/core` from source so a s…
ci(test-alias): gate that a unit test judges source, not a sibling's …
fix(runtime): actionLooksDestructive classifies on declared semantics…
docs(cloud-connection): re-anchor the dead tracker citations in packa…