Repository navigation
Commit fdf844c
<!-- claude-projects-attribution: {"github_login":"os-elon-musk"} -->
_Requested by **Elon** · [project
thread](https://claude.ai/code/project/chan_01WedDzV26nniwxv7jC88B9D?thread=cmsg_01WedDzV26nniwxv7jC88B9DRif1zFPxSGzmPepjdDRQNb)_
Fixes #27728
Fixes #27729
domain:server#3 · os-elon-musk · session_016WV4cxENxbA8ZpRgwafjvs
Clause-②: no (narrowing)
Metadata-protocol: none
Skills-docs: none — no hand-written docs page or published skill states
what either import door answers for an unregistered object, a disabled
package's object, or a short name (`git grep` of `content/docs` outside
`references/`/`releases/` and of `skills/` for the import routes with
`OBJECT_NOT_FOUND`, `OBJECT_PACKAGE_DISABLED`, 404 or "not found": 0
hits; `wire-format.mdx` names the sync route only as the bulk door,
`import-mappings.mdx` documents per-row outcomes).
## 维护者速读
- 改了什么:同步导入 `POST /data/OBJ/import` 现在先问对象在不在:没注册的对象回 404
`OBJECT_NOT_FOUND`,停用包里的对象回 404 `OBJECT_PACKAGE_DISABLED`,和数据门 `POST
/data/OBJ` 一字不差(原来回 200,错误藏在每行结果里)。两个导入门与 API 暴露闸都改用同一种读法:旧式 `ns__short`
对象用短名访问时,认的就是数据门认的那个对象。
- 为什么改:按分诊 6509235875(#27728)与
6509225810(#27729):只看状态码的导入客户端,拼错对象名时会以为成功;作业门对短名比数据门更严;暴露闸对短名放行,`apiEnabled:
false` 的 `ns__short` 对象用短名能被读写(实测)。
- 风险与回滚:收窄,已写 BREAKING 说明;只影响拼错/未注册/停用包的对象名和带 `__` 的旧对象名,已发运的对象都不带
`__`。回滚即删 `data-action-routes.ts` 里同步门那一行调用,再把两处 `item.name === name`
比较加回去。
- 先看:`packages/rest/src/data-action-routes.ts`(同步门新增的
`assertImportObjectExists`
调用与函数里去掉的名字比较);`packages/rest/src/meta-item-read-gate.ts` 的
`loadObjectItem`;新测试
`packages/rest/src/import-door-object-existence.test.ts`。
- 两分钟验证:`pnpm --filter @objectstack/rest exec vitest run
src/import-door-object-existence.test.ts`,预期 11/11 通过。
- 需要你做的:无,席位落地(合同复审由席位安排)。
## What changes
- **#27728, the synchronous import door.** `POST /data/:object/import`
now calls `assertImportObjectExists` right after the API-exposure gate
and before the control opt-out gate and the body parse, the same place
the async job door asks it (#27711). An unregistered object answers the
data door's 404 `OBJECT_NOT_FOUND`, byte for byte; an object of a
disabled package answers its 404 `OBJECT_PACKAGE_DISABLED`. Nothing is
parsed or written, dry run included. Placed after the exposure gate, so
a hidden object keeps its 404 and the door is no existence oracle.
- **#27729 item 1, pinned.** The async job door's disabled-package
refusal (propagated since #27711, read from the code) is now measured:
status and body `toEqual` the data door's answer for the same name, zero
`sys_import_job` rows, zero object rows. It was already green on the
base, as #27711 said.
- **#27729 item 2, one read.** `assertImportObjectExists` and the
exposure gate's `loadObjectItem` (`meta-item-read-gate.ts`) both dropped
`item.name === name`: whatever item the by-name read serves counts. That
read (`getMetaItemForExecution`, else `getMetaItem`) resolves a legacy
`ns__short` object from its short name exactly as the data door's
`registry.getObject` does (measured: `widget` → `exl__widget` on both).
Results:
- the job door creates a job for a short name the data door serves,
where it answered `OBJECT_NOT_FOUND`;
- the exposure gate judges the resolved object's `enable`. Before, a
short name was "no object here" to the gate and passed through, so an
`ns__short` object with `enable.apiEnabled: false` was served under its
short name (measured on the base: `POST /data/vault` 201, sync import
200, while `POST /data/exl__vault` answered 404 `OBJECT_API_DISABLED`).
Now all three doors answer 404 `OBJECT_API_DISABLED` for the short name
too.
- The list fallback (a protocol with no by-name read) keeps its name
match; it has no resolution to follow, and the docblock says so.
- Changeset: `@objectstack/rest` patch, BREAKING note, ADR-0087
`not-required (no-migration-prescription)` marker.
## Tests
`packages/rest/src/import-door-object-existence.test.ts` (new), real
`RestServer` routes on a real `ObjectQL` engine +
`ObjectStackProtocolImplementation`, SQLite `:memory:`, real
`sys_import_job`, real `disablePackage`:
- #27728: unregistered object → sync door 404 equal to the data door's
body; dry run and an unparseable CSV body get the same answer; control:
a registered object still imports (200, 1 row).
- #27729 item 1: disabled package → data door 404
`OBJECT_PACKAGE_DISABLED`; sync and job doors equal it (status + body),
zero job rows, zero object rows.
- #27729 item 2: premise (`registry.getObject('widget')` →
`exl__widget`, data door 201); job door 201 + one job row for the short
name; sync door imports under it; an unregistered short name is still
`OBJECT_NOT_FOUND` at both import doors, zero job rows; `apiEnabled:
false` object hidden under its short name at the data, sync and job
doors, zero rows.
Ablation (both source files reverted to `main`, test kept): 6 of 11 red
(the two #27728 cases, the sync disabled-package case, and three
short-name cases); the 5 that stay green are the controls, the data-door
reference reading, and the job-door disabled-package pin (already true
on the base). Restored: 11/11.
## Acceptance notes
- Triage rulings followed as written; nothing re-ruled.
- Out of scope, read from the code and not measured: the cross-object
`POST /batch` per-op exposure gate (`batch-routes.ts`) keys the object
LIST by `name`, so it keeps the old short-name pass-through. This
harness's runtime answers 501 for a transactional batch, so it could not
be measured here. Noted for the seat; not filed.
## Verification
Head `c0b19922`, base `main` `30f8fdd3` (#27795 and #27711 already in
the base).
- `pnpm --filter @objectstack/rest exec vitest run` (whole package):
Test Files 353 passed (353), Tests 7031 passed, 350 skipped.
- `pnpm --filter @objectstack/rest run typecheck`: exit 0. `pnpm lint`:
exit 0.
- dispatch-gates: 60 derived families, 59 run with exit 0, 1 NOT
MEASURED: `pnpm check:dual-build-cjs-loads` exits 3 (needs every
package's dist; CI builds it). `check-plugin-teardown-shape --self-test`
first exited 3 in the shallow clone and passed (0) after fetching its
pinned commit. `--ran` reconciliation: "60 derived famil(ies) accounted
for — 59 run, 1 NOT-MEASURED".
<details><summary>Dogfood battery (narrowing arm), full, under the
verify lock, at c0b1992</summary>
`pnpm --filter @objectstack/dogfood test` after the
`@objectstack/dogfood^...` closure build. `os-verify-lock: VERDICT
command-exit 1`. Test Files 3 failed, 353 passed, 3 skipped (359); Tests
4 failed, 2867 passed, 20 skipped (2891). None is this diff's (none
reads an import door, the exposure gate or a `__` name):
- `error-sentences-live.dogfood.test.ts`, acceptance[1], both `POST
/data/OBJECT` and `/createMany`; and
`object-hook-lifecycle-scratch.dogfood.test.ts`, acceptance[6]
negative[0]: the `HOOK_ABORTED` main red tracked as #27806 (fix in PR
#27878).
- `platform-app-object-entry-views.test.ts`, "every object an entry
names is declared by the composition or by the identity barrel":
`expected [ 'sys_exchange_rate' ] to deeply equal []`. A main-side red
from `194e66c0` (`sys_exchange_rate` named by a Setup entry the dogfood
composition does not register), tracked as the second red of #27813.
Named, not fixed.
</details>
The dogfood shards do not run on the PR or in the merge queue for this
diff (their `if:` excludes both events), so the reading above is the
only one before the merge.
## Human Minimum
- [x] 1. Schemas start as Zod; `packages/spec` holds no runtime logic.
(Not touched.)
- [x] 2. Every name I added uses the casing for its kind.
- [x] 3. No formatter ran; `pnpm lint` passes.
- [x] 4. One issue, one branch off an up-to-date `main`, one pull
request. (Two cards carried together on the seat's order: one file, one
read.)
- [x] 5. A change that publishes carries a changeset, and both
declaration lines are filled in here and in the changeset.
- [x] 6. `packages/spec` touched: not touched.
- [x] 7. No hand edits to `content/docs/references/`,
`packages/*/CHANGELOG.md` or `content/docs/releases/`.
- [x] 8. Title, body and comments are in English.
- [x] The *Before Submitting* list in CONTRIBUTING.md is done.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_016WV4cxENxbA8ZpRgwafjvs
---------
Co-authored-by: Claude <noreply@anthropic.com>
1 parent e41642d commit fdf844c
4 files changed
Lines changed: 276 additions & 21 deletions
File tree
- .changeset
- packages/rest/src
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
319 | 319 | | |
320 | 320 | | |
321 | 321 | | |
322 | | - | |
323 | | - | |
324 | | - | |
325 | | - | |
326 | | - | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
327 | 330 | | |
328 | 331 | | |
329 | | - | |
330 | | - | |
331 | | - | |
332 | | - | |
333 | | - | |
334 | | - | |
335 | | - | |
336 | | - | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
337 | 342 | | |
338 | 343 | | |
339 | 344 | | |
| |||
345 | 350 | | |
346 | 351 | | |
347 | 352 | | |
348 | | - | |
| 353 | + | |
349 | 354 | | |
350 | 355 | | |
351 | 356 | | |
352 | 357 | | |
353 | | - | |
| 358 | + | |
354 | 359 | | |
355 | 360 | | |
356 | 361 | | |
| |||
517 | 522 | | |
518 | 523 | | |
519 | 524 | | |
| 525 | + | |
| 526 | + | |
| 527 | + | |
| 528 | + | |
| 529 | + | |
| 530 | + | |
| 531 | + | |
| 532 | + | |
520 | 533 | | |
521 | 534 | | |
522 | 535 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
0 commit comments