Repository navigation
fix(cloud-connection)!: install-local judges a ledger entry in the CLI's lifted shape through the install door's flatten, at boot and on the sample-data doors - #28683
Conversation
…ugh the install door's flatten at boot and on purge/reseed Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FEkQ5piHvtwq5wxJ2RJYfj
📓 Docs Drift CheckThis PR changes 1 package(s): 1 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
What this run could not see
Coarse fallback — 5 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 3fe06cd3f7f2a5bb8e4234ecc9843559eef3d2fd && git checkout 3fe06cd3f7f2a5bb8e4234ecc9843559eef3d2fd
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin da46b2afe3e6829dcf70051f10578c61d611ec72 365d3ac3cab55c47125879dc62e258396d9216d2 && git checkout -B drift-repro da46b2afe3e6829dcf70051f10578c61d611ec72 && git merge --no-ff 365d3ac3cab55c47125879dc62e258396d9216d2
node scripts/docs-audit/affected-docs.mjs --json da46b2afe3e6829dcf70051f10578c61d611ec72
|
|
domain:server#2 · os-project-manager · session_0186vfjHHMsRXC9EUT9hTFMo Contract reviewServed-tier: Face: narrowing ( ① Derived judgments
② Semver level
③ Boundary flags
④ Design judgmentOn the narrowing face, against the published contract on Implemented-by: VERDICT: PASS Must-fixes: none. Generated by Claude Code |
|
domain:server#2 · os-project-manager · session_0186vfjHHMsRXC9EUT9hTFMo 席位核对ACCEPT · The maintainer's standing authorisation for landing reviewed PRs, verbatim: 「按照 pm-dispatch 规则复核过的都授权」.
Generated by Claude Code |
Requested by Leehom · project thread
Fixes #28604
Clause-②: no (narrowing) — at
kernel:readythe install-local rehydrate no longer loads, andPOST /api/v1/marketplace/install-local/:manifestId/reseed-sample-dataand/purge-sample-dataanswer 422OS_PROTOCOL_INCOMPATIBLEfor, a ledger entry an install wrote before #28535 in the bodyos package install FILEsends (idandversionlifted beside a nestedmanifest) whose nestedengines.protocolexcludes this runtime. That entry loaded, and those doors acted on it, before. A flat entry with the same range was already refused the same way. Nothing is widened.Metadata-protocol: none
Skills-docs: none — the pages already state the behaviour this restores:
skills/objectstack-platform/SKILL.md("The runtime checks it before it loads anything and refuses an out-of-range app at the boundary"). No page described a ledgered CLI install as an exception.BREAKING boot-load and accept-set narrowing for already-ledgered install-local entries (
@objectstack/cloud-connection): thekernel:readyrehydrate and the two sample-data doors, reached by a deployment whereos package install ./dist/objectstack.jsonran before PR #28603.维护者速读
kernel:readyrehydrate)、以及「重置/清除示例数据」两个接口,读台账条目时先经安装接口已有的同一个展平函数(flattenPackageBody)再做协议握手;rehydrate 的依赖排序也读展平后的条目。os package install发来的产物(id/version提到顶层、engines嵌在manifest下)原样写进台账。启动时只看顶层engines,读不到嵌套的范围,于是不兼容协议的包每次启动都照常加载,没有任何报错。notLoaded、两个示例数据接口答 422,DELETE 与兼容版本重装照常)。兼容的条目照旧加载,注册的内容与台账一字不差。回滚即 revert。packages/cloud-connection/src/marketplace-install-local-plugin.ts(rehydrate 握手 ≈:1109、inDependencyOrder、refuseProtocolIncompatibleEntry、flattenPackageBody的空值守卫);marketplace-install-local-protocol-handshake.test.ts新[#28604]用例组;.changeset/28604-install-local-rehydrate-lifted-entry.md。pnpm --filter @objectstack/cloud-connection exec vitest run src/marketplace-install-local-protocol-handshake.test.ts src/marketplace-install-local-sample-data-not-loaded.test.ts src/marketplace-install-local-rehydrate-order.test.ts→ 37/37 通过。What changes
The one flatten, read at three more places (
packages/cloud-connection/src/marketplace-install-local-plugin.ts). An install before PR #28603 ledgered the CLI's body as it arrived:{ id, version, manifest: { …, engines, dependencies }, objects, data, … }. Every reader that decides by a manifest key read it at the top, so the nested keys were invisible. Each now reads the entry throughflattenPackageBody, the function the install door already uses (no second flatten, no second handshake):kernel:readyrehydrate'scheckProtocolCompat(flattenPackageBody(entry.manifest)), so an excluded nested range is not loaded, is recorded inrefusedAtRehydrate(the listing'snotLoadedmarker) and gets the one error line, exactly as a flat entry;refuseProtocolIncompatibleEntry, the reseed/purge doors' handshake, so both answer the install route's 422 for it before any side effect;inDependencyOrder, so a lifted entry is ordered by thedependenciesits nested manifest declares (ADR-0141 D5). At boot, a flat entry's dependencies are used for this ordering only (the rehydrate runs no dependency check:checkDeclaredDependenciesis called only at the install door), so ordering is the parity a lifted entry is owed.flattenPackageBodygains a!isPlainObject(body)guard so it is total over a ledger value, whichLocalManifestSourcedoes not shape-check. Measured: anull, a string and a numbermanifestproduce byte-identical rehydrate logs, registrations and door answers on base and head (probe in the evidence folder below).What stays as today. A compatible lifted entry registers, converts, binds and seeds the body exactly as ledgered: only the judging and the ordering read the flattened view. The install door and its #28603 flatten are untouched.
Why
ADR-0087 D1 puts the handshake "before loading a package's metadata", and a rehydrate is a load (#21762). The triage (
6557784727) graded the reach p3: one closed population, the entries a CLI install wrote before PR #28603 (7449e479), since new installs are refused at the door.Tests
marketplace-install-local-protocol-handshake.test.ts, new group[#28604] kernel:ready rehydrate of an entry ledgered in the CLI's lifted shape: the lifted^17entry is not registered, nothing is synced, and its error lines equal a flat^17entry's on a fresh ledger, byte for byte; the GET listing marks itnotLoaded { code: OS_PROTOCOL_INCOMPATIBLE, requiredRange: ^17 }; lit control: a lifted^18entry rehydrates with no error and registers the body deep-equal to the ledgered one.marketplace-install-local-sample-data-not-loaded.test.ts, new group: precondition (lifted refused not loaded, lifted loadable loaded); reseed and purge on the lifted refused entry answer 422, leave i18n, seed-datasets, the engine and the ledger unchanged, and their payloads equal the flat entry's byte for byte; lit control: both doors answer 200 on the lifted loadable entry.marketplace-install-local-rehydrate-order.test.ts: a lifted module entry listed ahead of its parent registers after it.Red on base (plugin source swapped to
origin/main0b6a52e8; on disk: flatten-at-judge count 0, base judge count 2; restored withgit checkout HEAD --,git diff HEADempty, blob hash equal to HEAD): 5 failed / 32 passed of 37, exactly the five lifted-shape cases above that judge or order; both lit controls pass on both trees. Green on head: 37/37.Ablation, one leg per site, through
scripts/ablation-replace.mjs(anchor 1 → 0 on disk, restored to the HEAD blob,git diff HEADempty after each). The tests import the plugin by relative path (source), so there is no dist leg.entry.manifestentry.manifestentry.manifestAcceptance notes
manifestisnullthrowsCannot read properties of null (reading 'engines')fromcheckProtocolCompat, at the rehydrate (logged as "rehydrate failed") and out of the reseed/purge handlers. Identical on base and head. No door or producer writes such an entry, so it is noted here and not filed.pr_create; none touches the plugin file or the three test files.Verification
All on head
365d3ac3(the only commit; the base isorigin/main0b6a52e8).pnpm --filter @objectstack/cloud-connection test: 65 files / 796 tests passed.pnpm --filter @objectstack/cloud-connection typecheck: exit 0 (under the verify lock,VERDICT command-exit 0).(narrowing)arm), closure built thenpnpm --filter @objectstack/dogfood testunder the lock:VERDICT command-exit 0(held 2009s) · Test Files 369 passed, 3 skipped (372) · Tests 2981 passed, 28 skipped (3009) · no failures.dispatch-gates --commands --repo objectstack-ai/objectstackderived 60 families; all 60 exit 0, exit codes captured before any pipe.--ran: "60 derived famil(ies) accounted for — 60 run, 0 NOT-MEASURED (a DERIVED zero — all 60 recorded an exit code and none of them is 3)". Two first runs were not measurements and were re-run to exit 0:check-plugin-teardown-shape --self-testexited 3 on the shallow clone until its pinned fixture commit was fetched, andcheck:dual-build-cjs-loadsexited 3 until a fullpackages/**build. Record: project filepm-orders/server/evidence/28604/gates-ran-365d3ac3.txt.pm-orders/server/evidence/28604/non-object-ledger-probe.txt.Human Minimum
packages/specholds no runtime logic. (not touched)pnpm lintpasses (CI).main, one pull request.packages/spectouched: n/a.content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.🤖 Generated with Claude Code
https://claude.ai/code/session_01FEkQ5piHvtwq5wxJ2RJYfj
Generated by Claude Code