Repository navigation
Commit 1ca7a80
Fixes #23121
Clause-②: no
The browser pass of #23104 scored six acceptance clauses in the platform
test checklist as `fail`. In each case the product is right and the
clause is out of date: it pins a shape the product has since ruled away.
This PR revises the five items that carry those clauses. Each item gets
`revision` +1 and one appended `history` entry. No product code, test or
fixture changes.
Before each edit, I checked the row's "what the product does now"
against code and tests. I did not use a browser or boot the app. I read
objectui source at this repo's `.objectui-sha`, `1fb1ced36243`. Every
objectui file cited below is byte-identical at `7578323a544e`, the pin
the dispatch named (`git diff --quiet` exit 0).
## Rows: item, clause, old to new, and what it was checked against
Clause indices are zero-based, like a run record's `clause`. `#23104 X`
is the QA run's own label.
| item · clause | old | new | checked against |
|---|---|---|---|
| `platform-core.home-admin-cluster-links` · acceptance[2] (#23104 A2) ·
rev 2 → 3 | roles, positions and permissions redirect to the
`sys_position` / `sys_permission_set` object routes | roles and
positions go to `/apps/setup/metadata/position?scope=environment` and
permissions to `/apps/setup/metadata/permission?scope=environment`: the
Setup metadata catalog, via `SystemCatalogRedirect` (objectui#7611).
`users` and `organizations` are unchanged | objectui
`apps/console/src/AppContent.tsx:167-171,289-293` ·
`apps/console/src/__tests__/AppContent.systemHubRoutes.test.tsx:344-382`
· `packages/app-shell/src/views/metadata-admin/catalog-scope.ts:55` @
`1fb1ced36243` |
| `identity-auth.auth-method-matrix` · acceptance[9] (#23104 A9) · rev 6
→ 7 | delete-user answers 404 "to every caller, authed or not" |
delete-user is never 2xx: a signed-in caller gets 404 (the capability
switch) and an anonymous one gets 401 `UNAUTHORIZED` (session guard).
The existing wiring test is the oracle |
`packages/plugins/plugin-auth/src/change-email-delete-user-wiring.test.ts:320-375`
(anonymous 401 at :349, authed 404 at :352, callback 404 at :372) ·
`auth-route-ledger.ts:157` @ `f931e765b` |
| `identity-auth.self-signup-gate` · negative[4] (#23104 N5) · rev 2 → 3
| under stock `invite_only` the login page offers the register link and
`/register` renders the form | no generic sign-up link, and `/register`
shows the by-invitation notice with no form. The form is offered only
for an `/accept-invitation/ID` redirect or on a deployment with no
owner. The negative now fails the old offer-then-refuse shape, and still
fails an invitee left without a form | objectui
`packages/app-shell/src/console/auth/signUpOffer.ts:144-157` ·
`apps/console/src/pages/auth/RegisterPage.tsx:125-143,229-257` ·
`LoginPage.tsx:146-153,361-362` ·
`__tests__/signUpFollowsPosture-11691.test.tsx:156-260` @
`1fb1ced36243`; server unchanged:
`packages/plugins/plugin-auth/src/auth-manager.ts:6809-6816` @
`f931e765b` |
| `access-security.owd-save-gate` · acceptance[3] (#23104 A3) · rev 3 →
4 | widening a packaged object's OWD answers 403 `PERMISSION_DENIED`
with `declaredCode: owd_widening_forbidden` (R1) | 403 `NOT_OVERRIDABLE`
from the managed-content seal, or `ITEM_LOCKED` with `?package=`. The
seal is saveMetaItem's package door. It is asked ahead of every check
that judges the body (#22338), and the hatch does not open it (ADR-0131
D6, #22401). R1 cannot be reached here on stock, so its oracle is its
unit pins, named in the item. No fixture package was built for it |
`packages/metadata-protocol/src/protocol.ts:20652` (the door, in
`saveMetaItem`, ahead of `runAuthoringGate` at :21233) · `:17465-17537`
(`refusePackagedBaseOverride`) · `:16669-16672` (`isSealedManagedItem`)
· `packages/spec/src/kernel/metadata-plugin.zod.ts:786` (`object`:
`allowEnvironmentOverlay: false`) ·
`packages/rest/src/meta-object-owd-gate.test.ts:346-430` ·
`packages/plugins/plugin-security/src/object-posture-gate.test.ts:61-131`
@ `f931e765b`; commits `35afb1587`, `e02833c24` |
| `api-backend.formula-stdlib-matrix` · acceptance[0] (#23104 C1) · rev
1 → 2 | 27 registered stdlib functions; the joinNonEmpty row is the
literal `joinNonEmpty(['a', null, ' ', 'b'], '-')` | 29 functions: the
27 plus `isoDate` and `isoDatetime` (`345d3f3d8`, #22347), with their
known answers. The joinNonEmpty row now feeds the same values through
record fields and expects `'a-b'`. The receiver method `can` is named as
outside the count | `packages/formula/src/stdlib.ts:261-423` (29 chained
`registerFunction` calls, counted from source; `can` registered at :267
→ :196) · `packages/formula/src/validate.ts:1240-1280` (the 29 tally) ·
`content/docs/data-modeling/formulas.mdx:178-198` (29 names, 19 rows) @
`f931e765b`; probe against the built `packages/formula/dist/index.mjs`
(below) |
| `api-backend.formula-stdlib-matrix` · acceptance[5] (#23104 C6) · rev
1 → 2 | EXPECTED-FAIL: an unregistered function is a silent null at head
| positive: an active object save whose formula calls `sqrt(...)`
answers 422 `INVALID_METADATA` (rule `expression-invalid`, a NAME
fault), and nothing is stored. A draft promotion is refused the same
way. The read-path residual is named |
`packages/metadata-protocol/src/protocol.runtime-authoring-gate.test.ts:1630-1700`
· `packages/lint/src/runtime-gate.object-formula-writes.test.ts:66-107`
· `packages/formula/src/validate.ts:548` ·
`packages/objectql/src/engine-formula-fault-log.test.ts` @ `f931e765b`;
commit `f85a83b83` (#22031; card #22019) |
The C6 pin search found a test that pins this refusal: the `'runtime
authoring gate on OBJECT writes — the formula field verdict (#22019)'`
block. The item names it, so the clause does not rest on a browser
reading alone.
**Probe against the built formula package** (`pnpm --filter
'@objectstack/formula...' build` under the shared lock, then `celEngine`
imported from `packages/formula/dist/index.mjs` at `f931e765b`):
```text
joinNonEmpty(['a', null, ' ', 'b'], '-') -> ok:false "List elements must have the same type, expected type 'string' but found 'null'"
joinNonEmpty([record.a, record.b, record.c, record.d], '-')
with record a='a' b=null c=' ' d='b' -> ok:true 'a-b'
isoDate(date('2026-02-28T13:45:00Z')) -> '2026-02-28'
isoDatetime(date('2026-02-28T13:45:00Z')) -> '2026-02-28T13:45:00.000Z'
isoDate(today()), now 2026-08-30T22:00Z, Asia/Shanghai -> '2026-08-31'
isoDate('2026-01-01') -> ok:false found no matching overload for 'isoDate(string)'
sqrt(4) -> ok:false found no matching overload for 'sqrt(int)'
```
**Coupled fields.** Each row also revises the fields of the same item
that restate the same stale fact, so that no item contradicts itself
after the edit:
- **A2:** the title, step 4, and the AppContent source note.
- **A9:** step 9.
- **N5:** the title and step 1. Step 2 drops its "submit the register
form" half and keeps the direct POST, because the stock `/register` has
no form for an uninvited visitor. Also one new objectui source note.
- **A3:** the title, step 5, the R1 knownGap, the first knownGap's
"packaged tighten-only" parenthetical, and the R1 variant. Also two new
source notes, including the anchor
`protocol.ts#refusePackagedBaseOverride`.
- **C1:** the title, step 1, step 3, the 27-function knownGap, the
clause's evidence, and the `registerStdLib` source note.
- **C6:** the title, step 7, and negative[2]. Also two new source notes,
including the anchor
`packages/lint/src/authoring-rules.ts#EXPRESSION_INVALID`.
Each `history` entry lists the fields it touched.
## Gates
All gates ran at `c84cc2314` (`git rev-parse --short HEAD` after the
last commit). Each ran in its own foreground process with its own log,
and the exit code was read before any pipe.
| command | exit | verdict line |
|---|---|---|
| `node scripts/check-ci-filter-parity.mjs` | 0 | `OK: all 197 declared
cross-package glob(s) (144 unique) are covered …` |
| `node scripts/check-closing-keyword-parity.mjs` | 0 |
`check-closing-keyword-parity: OK (3 parsers agree on all 9 keywords …)`
|
| `node scripts/check-closing-keyword-parity.mjs --self-test` | 0 | `✓ …
40 assertions, 5 mutations of the shipped parsers each driven to red.` |
| `node scripts/check-comment-mask-corpus.mjs` | 0 | `✓ comment-mask
corpus sweep …: 8933 files, 0 disagree, 0 unparseable` |
| `pnpm --filter @objectstack/lint run check:doc-formula-expressions` |
0 | `✓ check:doc-formula-expressions: 22 record-scoped formula
example(s) across 474 files …` (first run exited 3, PREREQUISITE NOT
MET: lint was unbuilt; re-run after `pnpm --filter
'@objectstack/lint...' build`) |
| `pnpm check:cross-package-test-inputs` | 0 | `OK: 30 package(s) read
outside themselves, all declared …` |
| `pnpm check:doc-authoring` | 0 | `✓ doc authoring guard: 421 files
clean …` |
| `pnpm check:driver-memory-census` | 0 | `check-driver-memory-census:
OK …` |
| `pnpm check:gitlink-declared` | 0 | `check-gitlink-declared: OK (11177
index entries …)` |
| `pnpm check:nul-bytes` | 0 | `check-nul-bytes: OK (scanned 11168 text
file(s) … no raw ASCII control bytes).` |
| `pnpm check:platform-checklist` | 1 | `check-platform-checklist: 8
problem(s)`, the same 8 lines at the base `f931e765b` (sorted problem
lines diff empty). None is in the five items, so this PR adds no problem
(see Acceptance notes) |
| `pnpm check:refd-timer-probe` | 0 | `OK check-refd-timer-probe: 8927
source file(s) swept …` |
| `pnpm check:watch-hint-literal` | 0 | `✓ check-watch-hint-literal: 73
declaration(s) across 4 rostered name(s) …` |
`node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack
--ran FILE`, run after the edits with no paths so the script derives the
change set (4 paths vs merge base `f931e765b`), printed `✓
dispatch-gates --ran: 13 derived famil(ies) accounted for — 13 run, 0
NOT-MEASURED (a DERIVED zero …)`. This is the same 13 the dispatch
named. Symbol anchors per file rose and never fell (`--anchor-census`:
access-security 64, api-backend 66, identity-auth 90, platform-core 67,
all above their floors). `skip-changeset`: `docs/qa/**` ships in no
package.
## Acceptance notes
- **The `check:platform-checklist` red predates this PR.** At
`f931e765b` it reports 8 problems:
- 5 ABSENT SYMBOL in `access-security.public-form-withdrawal-layers`
(`protocol.ts#anonymousFormIntakeOrgScopeRefusal`,
`#anonymousFormIntakeReopenRefusal` and `#envWideRawViewRows`, the last
two each cited twice);
- 1 ABSENT SYMBOL in `attachments-storage.attach-requires-parent-edit`
(`attachment-access-hooks.ts#canEdit`), plus that file's SYMBOL ANCHORS
LOST (27 resolve, floor 28);
- 1 ABSENT SYMBOL in `search.rls-both-personas`
(`protocol.ts#countable`).
All 8 are outside this card's file surface and untouched here. Carrier:
the daily `platform-checklist-watchdog` workflow, which files or
refreshes one issue while `main` is red. Not filed.
- **`identity-auth.self-signup-gate`, other text.** acceptance[2] ends
"which is exactly why the register form stays rendered under the closed
posture". After objectui#11691 that is true for an invitee only. That
clause is outside this row and is left as written. Its two older
objectui source notes also cite line ranges (`RegisterPage.tsx,69-88`,
`LoginPage.tsx,136,298`) that no longer match the pin.
- **`access-security.owd-save-gate`, other text.** fixtures.requires[1]
still says to author the R2 probe with `?mode=draft`, while step 3 says
to drive it at the active door. That predates this PR and sits outside
the row.
- **R1 now has no live path.** No write reaches R1's packaged-baseline
comparison through `PUT /api/v1/meta/object/NAME` on any kernel
topology: the seal answers first, as the REST pin's own comment records.
R1 keeps only its in-process unit pins. This is an observation, not a
defect, so it is not filed.
- **`can` is undocumented.** `current_user.can(object, verb)` is
registered inside `registerStdLib` (as a receiver method) but appears in
no doc outside release notes; the formulas.mdx stdlib table and its
variable-scope table omit it. This is a doc observation, not filed.
- **Pin discrepancy.** The dispatch named `.objectui-sha`
`7578323a544e`. `origin/main` moved it to `1fb1ced36243` (#23110) after
the PM's read at `e9e10fdab`. I read at the current pin. Every cited
file is byte-identical across the two.
## 维护者速读(草稿)
**改了什么**:平台测试清单里五个测试项的六条验收子句改了指向:Setup
旧链接的落点、删除账号接口的应答、注册页在「仅限邀请」下的表现、受管对象 OWD 的拒绝码、公式函数数量与未注册函数的拒绝。只改了
`docs/qa/platform-checklist/areas/` 下四个 JSON 文件,产品代码一行未动。
**为什么改**:#23104 浏览器测试把这六条判成 fail,但产品行为是对的,是清单写的时候早于后来的裁决或实现。不改的话,每次发版 QA
都会重复报出这六个假失败,把真问题淹没。
**风险与代价(含回滚)**:不发布任何包(`skip-changeset`),不影响运行时。风险只在于清单措辞:若某条改写不准,下次 QA
会把它判成 fail,而不是漏报。回滚就是 revert 本 PR,清单回到旧措辞。
**席位意见**:
**你要做的**:无需操作。合并由席位按常规非受管路径完成。
---
_Generated by [Claude
Code](https://claude.ai/code/session_012dGTuJen61ECNHXYXKChoC)_
---------
Co-authored-by: Claude <noreply@anthropic.com>
1 parent 287fd6e commit 1ca7a80
4 files changed
Lines changed: 63 additions & 43 deletions
File tree
- docs/qa/platform-checklist/areas
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1318 | 1318 | | |
1319 | 1319 | | |
1320 | 1320 | | |
1321 | | - | |
| 1321 | + | |
1322 | 1322 | | |
1323 | 1323 | | |
1324 | | - | |
| 1324 | + | |
1325 | 1325 | | |
1326 | 1326 | | |
1327 | 1327 | | |
| |||
1335 | 1335 | | |
1336 | 1336 | | |
1337 | 1337 | | |
1338 | | - | |
1339 | | - | |
| 1338 | + | |
| 1339 | + | |
1340 | 1340 | | |
1341 | 1341 | | |
1342 | 1342 | | |
1343 | 1343 | | |
1344 | 1344 | | |
1345 | 1345 | | |
1346 | 1346 | | |
1347 | | - | |
| 1347 | + | |
1348 | 1348 | | |
1349 | 1349 | | |
1350 | 1350 | | |
| |||
1368 | 1368 | | |
1369 | 1369 | | |
1370 | 1370 | | |
1371 | | - | |
| 1371 | + | |
1372 | 1372 | | |
1373 | | - | |
1374 | | - | |
| 1373 | + | |
| 1374 | + | |
1375 | 1375 | | |
1376 | 1376 | | |
1377 | 1377 | | |
| |||
1393 | 1393 | | |
1394 | 1394 | | |
1395 | 1395 | | |
1396 | | - | |
| 1396 | + | |
1397 | 1397 | | |
1398 | 1398 | | |
1399 | 1399 | | |
| |||
1404 | 1404 | | |
1405 | 1405 | | |
1406 | 1406 | | |
1407 | | - | |
| 1407 | + | |
| 1408 | + | |
| 1409 | + | |
1408 | 1410 | | |
1409 | 1411 | | |
1410 | 1412 | | |
| |||
1414 | 1416 | | |
1415 | 1417 | | |
1416 | 1418 | | |
1417 | | - | |
| 1419 | + | |
| 1420 | + | |
1418 | 1421 | | |
1419 | 1422 | | |
1420 | 1423 | | |
| |||
0 commit comments