Repository navigation
Commit 1edceb1
docs(qa): wave-3 accuracy slice S7 — integration-system, attachments-storage, cli (#28373)
<!-- claude-projects-attribution: {"github_login":"os-zhuang"} -->
_Requested by **Sam** · [project
thread](https://claude.ai/code/project/chan_01LjZwNRFiG2fkp8SNf6rHNx?thread=cmsg_01LjZwNRFiG2fkp8SNf6rHNxPFBmNgjEvS25JDSkgtHHvX)_
Fixes #28341
Part of #27377 (wave-3 checklist accuracy, slice S7)
Clause-②: no
Metadata-protocol: none
## 维护者速读
- 改了什么:校准三份 QA 测试清单 JSON(cli、attachments-storage、integration-system)中 14
个条目的文字,覆盖切片 S7 的全部 28 行普查记录;每条 revision +1,main 的 history
原样保留为前缀,追加一行引用对应的 QA 运行记录与 #27377。另给 cli.json 的 `cli-18-prerelease-db`
配方加了第 3 步:恢复后把重置令牌的过期时间往后挪。
- 为什么改:wave-3
的运行记录(#27392、#27409、#27438、#27441、#27481)实测发现这些条目的步骤、夹具或校验说法与当前代码不符(例如
`os serve` 只打印拒绝消息、从不打印错误码;邮件发送接口 200 的响应体没有 `result` 包装;`?schema=` 在
SQLite 上现在答 400 而非整表)。
- 风险与回滚:只改 `docs/qa/` 下三份清单,不动产品代码、不发布;没有任何条款被放宽,有三处变得更严格。回滚即 revert 本
PR。
- 先看:`cli.json` 的 `cli.organization-ownership-ceremony`(7
行合并成一次修订,acceptance[1] 和 [3] 改动最大);`integration-system.json` 的
`external-schema-introspection` acceptance[1].verify(由“200 整表”收紧为“400
拒绝”);`attachments-storage.json` 的 `upload-limits-scope-and-ownership`
steps[4]。
- 两分钟验证:`pnpm check:platform-checklist`,预期 `OK — 16 areas, 352
items`,symbol anchors `1079/1089`(基线 1072/1082,新增 7 个锚点全部可解析)。
- 需要你做的:无,席位落地。
## What changes
Three files, 14 items, and one area recipe step. Each item's `revision`
is +1 from main. Main's `history` is kept as an exact prefix, and one
row is appended citing the run record the finding came from (`ref`) and
the wave anchor #27377 (in `change`). All 28 census rows were re-checked
against the source at base `22ce3d13fe` before editing. All 28 still
held; none had been fixed upstream. No commit touched the three files
between the census base `501c864dd5` and `22ce3d13fe` (`git log
501c864..origin/main` over the three paths is empty; `501c864dd5` is
an ancestor of `origin/main`, exit 0, and the range spans 20 commits).
No clause is weakened.
| item | census rows | change (brief) | record |
|---|---|---|---|
| cli.fresh-install-migrate-apply-first | 19 | requires[0]: `os migrate
plan` creates no file on an absent path (plan.ts `readOnlyProbe`), so
only `os dev` / `os serve` are named as table-creating; the `test ! -e`
check stays | #27392 |
| cli.hook-body-extraction-gates | 20 | steps[2], requires[0],
acceptance[3].verify: adds the data-body probe (the retired comment
inside `body.source`), which expects `body.capabilities` `[]`. The
TS-config probe passes trivially because esbuild strips the comment |
#27392 |
| cli.qa-suite-execution | 21 | acceptance[4]: the refused suite adds
one to the scenario tally (`FAILED: 3 scenarios failed.` for the
steps[5] trio, `summaryLine`) | #27392 |
| cli.organization-ownership-ceremony | 39, 62, 63, 64, 132, 143, 144 |
requires[1]: the v17 recipe (create-objectstack@17.7.0 blank scaffold,
`--legacy-peer-deps`, one own `os dev` boot). acceptance[1]: the oracle
is the primary file's checksum; under `--dev` the telemetry sibling gets
a row-level read. acceptance[3]: the code literal is deferred to the
pins (serve.ts prints the message only), as in
platform-core.v18-boot-refusals acceptance[1], and the named command
carries `--dev` on a dev serve. steps[5]: the reset token is re-dated
(new recipe step 3); under a production serve the delivery row lands in
the primary (`resolveTelemetryDbPath`) | #27409, #27481 |
| attachments-storage.download-authz-both-sides | 54 | steps[6]: the
panel's place depends on the width tier (`recordPageTierFor`). At 1600px
it is resident; at 1280px it sits behind the `Related` rail toggle.
There is no Attachments tab | #27409 |
| attachments-storage.orphan-tombstone-reap | 55 | steps[1]: the sweep
has no HTTP door. The trigger is a restart and the first sweep 60 s
later (`DEFAULT_LIFECYCLE_INITIAL_DELAY_MS`) | #27409 |
| attachments-storage.upload-session-abort | 56 | steps[0] to [2]:
`resumeToken` and the `x-resume-token` header (else 403
`INVALID_RESUME_TOKEN`); complete takes `parts: [{chunkIndex, eTag}]` |
#27409 |
| attachments-storage.upload-limits-scope-and-ownership | 57 | steps[4],
acceptance[5]: a data-API write is copy-on-claim (`copyOwnedFile`), so
the id is planted with a driver-level write and read back raw; the
reader is one refused `sys_file` read | #27409 |
| integration-system.job-scheduled-run | 118 | acceptance[5]: the
`job.id` prescription now ends with the aged-out `os migrate meta`
sentence, not `--from 16` | #27441 |
| integration-system.notify-inbox-delivery | 119 | steps[0]: `assignee`
is a text field holding the persona's email | #27441 |
| integration-system.external-schema-drift-gate | 151 (gap), 192 |
acceptance[0], steps[2]: the boot prints renderDiffMessage's text after
`Bootstrap failed after plugins started`, exits 1, and never prints the
class name. steps[7] (new, appended): the negative[5] federation-free
boot recipe (stock app-todo) | #27438 |
| integration-system.external-schema-introspection | 188 |
acceptance[1].verify, knownGaps[0]: on SQLite, `?schema=X` answers 400
`EXTERNAL_DATASOURCE_ERROR` (the #24664 refusal); empty or repeated
`?schema` still answer 200 with the full set | #27438 |
| integration-system.email-template-render | 189, 190, 191 |
acceptance[7]: the 200 body is a top-level `{id, status, messageId}`.
steps[5]: `fromOverride` is `{name?, address}`. acceptance[1] and [2]:
the evidence is the `sys_notification_delivery` row (`dead`,
`MISSING_VARIABLES: title` / `TEMPLATE_INACTIVE: NAME`), and the oracle
moves from log to api | #27438 |
| integration-system.notification-org-and-redeliver-eligibility | 193 |
requires[2]: the `sys_webhook` create needs `method: 'post'` (lower-case
select) and `definition_json` | #27438 |
**Area recipe.** `cli.json` fixtures `cli-18-prerelease-db` gains
`sequence[2]` (step 3). It is one `node:sqlite` UPDATE that moves the
dump's one `sys_verification` row a day ahead and prints `1`. The call
was replayed against the committed `database.sql` loaded into a scratch
file: it printed `1`, and `expires_at` read back moved forward.
**Where clauses got stronger.** external-schema-introspection
acceptance[1].verify now requires the 400 refusal, where 200 with the
full set used to pass. upload-limits acceptance[5] adds a raw column
read, so a minted copy cannot pass for the planted id. hook-body
acceptance[3] adds the data-body probe, which the old probe could not
fail.
## Tests
None. The diff is ledger text in `docs/qa/`, so no package test reads
it. The ledger's own gate is the evidence (Verification).
## Acceptance notes
- Census rows 62 and 144 (and the cli half of an anchor note about the
optional `--dev`) are one edit to acceptance[3]: the code is deferred to
the pins, and the named command matches the boot (`ceremonyCommand` in
organization-ownership-boot-guard.ts).
- Census rows 63 and 132 (the reset-token fixture) are fixed in the
recipe, not by scoring the leg differently. The ceremony's steps[5]
points at the new recipe step.
- The recipe's `requires[2]` still says a production `os serve` over the
restored pair is NOT MEASURED. QA run #27409 drove one, but that
requirement is not one of this slice's rows, so it is left as it was.
- upload-limits: a reader holding `sys_file` read sees a foreign file's
metadata in full. This is reported as STALE, not as a defect. The
hydration code mints the refused marker only on the refused-read arm,
and the download door judges bytes by the owning record on its own
(engine-file-reference-hydration.ts header).
- No product defect found. No out-of-scope file touched.
## Verification
<details><summary>Gates at head 2b4bc3b (local, derived by
dispatch-gates --commands)</summary>
Head `2b4bc3be`, base `22ce3d13fe`. `node scripts/pm/dispatch-gates.mjs
--commands --repo objectstack-ai/objectstack` derived 16 families from
the three changed paths (188 changed lines, under the 3000 threshold).
Every one exited 0:
```
node scripts/check-adr-links.mjs :: exit 0
node scripts/check-adr-links.mjs --self-test :: exit 0
node scripts/check-closing-keyword-parity.mjs :: exit 0
node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0
node scripts/check-comment-mask-corpus.mjs :: exit 0 (19451 files, 0 disagree)
node scripts/ci/plan-test-core-shards.mjs --self-test :: exit 0
pnpm --filter @objectstack/lint run check:doc-formula-expressions :: exit 0
pnpm check:ci-filter-parity :: exit 0
pnpm check:cross-package-test-inputs :: exit 0
pnpm check:doc-authoring :: exit 0
pnpm check:driver-memory-census :: exit 0
pnpm check:gitlink-declared :: exit 0
pnpm check:nul-bytes :: exit 0
pnpm check:platform-checklist :: exit 0
pnpm check:refd-timer-probe :: exit 0
pnpm check:watch-hint-literal :: exit 0
```
`pnpm check:platform-checklist`: `OK — 16 areas, 352 items (347 active,
1 planned)`, symbol anchors `1079/1089` resolved (base 1072/1082: the 7
new anchors all resolve; the 10 unresolved are the unchanged #16898
residual).
`--ran` reconciliation: `16 derived, 16 run, 0 NOT-MEASURED, 0 UNRUN` (a
derived zero: all 16 record an exit code).
On the first pass, five families exited 3 (PREREQUISITE NOT MET: a fresh
worktree with no `node_modules`, and `@objectstack/formula` /
`@objectstack/lint` unbuilt). They were re-run after `pnpm install
--frozen-lockfile` and `turbo run build --filter=@objectstack/formula
--filter=@objectstack/lint` (lock VERDICT command-exit 0), and the lines
above are those re-runs. CI's own families are on this PR's check-runs.
</details>
---
_Generated by [Claude
Code](https://claude.ai/code/session_01QUs3BwBJH8nkmvFpQugNUm)_
Co-authored-by: Claude <noreply@anthropic.com>1 parent edf9714 commit 1edceb1
3 files changed
Lines changed: 137 additions & 51 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
254 | 254 | | |
255 | 255 | | |
256 | 256 | | |
257 | | - | |
| 257 | + | |
258 | 258 | | |
259 | 259 | | |
260 | 260 | | |
| |||
281 | 281 | | |
282 | 282 | | |
283 | 283 | | |
284 | | - | |
| 284 | + | |
285 | 285 | | |
286 | 286 | | |
287 | 287 | | |
| |||
371 | 371 | | |
372 | 372 | | |
373 | 373 | | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
374 | 380 | | |
375 | 381 | | |
376 | 382 | | |
| |||
726 | 732 | | |
727 | 733 | | |
728 | 734 | | |
729 | | - | |
| 735 | + | |
730 | 736 | | |
731 | 737 | | |
732 | 738 | | |
| |||
738 | 744 | | |
739 | 745 | | |
740 | 746 | | |
741 | | - | |
| 747 | + | |
742 | 748 | | |
743 | 749 | | |
744 | 750 | | |
| |||
800 | 806 | | |
801 | 807 | | |
802 | 808 | | |
| 809 | + | |
| 810 | + | |
| 811 | + | |
| 812 | + | |
| 813 | + | |
| 814 | + | |
803 | 815 | | |
804 | 816 | | |
805 | 817 | | |
| |||
808 | 820 | | |
809 | 821 | | |
810 | 822 | | |
811 | | - | |
| 823 | + | |
812 | 824 | | |
813 | 825 | | |
814 | 826 | | |
| |||
823 | 835 | | |
824 | 836 | | |
825 | 837 | | |
826 | | - | |
827 | | - | |
828 | | - | |
| 838 | + | |
| 839 | + | |
| 840 | + | |
829 | 841 | | |
830 | 842 | | |
831 | 843 | | |
| |||
909 | 921 | | |
910 | 922 | | |
911 | 923 | | |
| 924 | + | |
| 925 | + | |
| 926 | + | |
| 927 | + | |
| 928 | + | |
| 929 | + | |
912 | 930 | | |
913 | 931 | | |
914 | 932 | | |
| |||
1125 | 1143 | | |
1126 | 1144 | | |
1127 | 1145 | | |
1128 | | - | |
| 1146 | + | |
1129 | 1147 | | |
1130 | 1148 | | |
1131 | 1149 | | |
| |||
1144 | 1162 | | |
1145 | 1163 | | |
1146 | 1164 | | |
1147 | | - | |
| 1165 | + | |
1148 | 1166 | | |
1149 | 1167 | | |
1150 | 1168 | | |
| |||
1178 | 1196 | | |
1179 | 1197 | | |
1180 | 1198 | | |
1181 | | - | |
| 1199 | + | |
1182 | 1200 | | |
1183 | | - | |
1184 | | - | |
| 1201 | + | |
| 1202 | + | |
1185 | 1203 | | |
1186 | 1204 | | |
1187 | 1205 | | |
| |||
1220 | 1238 | | |
1221 | 1239 | | |
1222 | 1240 | | |
| 1241 | + | |
| 1242 | + | |
| 1243 | + | |
| 1244 | + | |
| 1245 | + | |
| 1246 | + | |
1223 | 1247 | | |
1224 | 1248 | | |
1225 | 1249 | | |
| |||
0 commit comments