Repository navigation
docs(releases): write the curated 17.7.0 release page — 17.7.0 is published (2026-10-06) and content/docs/releases/v17/17-7.mdx does not exist #21989
Description
Activity
- addeddocumentationImprovements or additions to documentationImprovements or additions to documentationpriority:p1High: required for production / M2High: required for production / M2
on Oct 6, 2026 objectstack-fleet commented
on Oct 6, 2026 ContributorAuthorMore actionsClaim: director round 1 (the maintainer's direct order: write the 17.7.0 notes now, and land them)
Session:session_016tKoy8NJa35Yih1FdzrVmn
Account:hotlong(the session's linked user asGET /useranswers it; the card's assignee)
Branch:claude/issue-21989-release-notes-17-7, cut frommain
Worktree:objectstack-issue-21989
Domain:domain:devx
Seat: the director seat, summon #32. The maintainer's order, verbatim: 「版本说明你抓紧时间写,并且提交合并」.
File surface:content/docs/releases/v17/17-7.mdx(new);content/docs/releases/v17/meta.json;content/docs/releases/v17/index.mdx;scripts/docs-audit/handwritten-docs.json;- at most one dated correction on
17-6.mdx, if the compile finds one owed.
Docs only,
skip-changeset. The page is the final one, because 17.7.0 has already published.
Container & model:M,mode:subagent,model: opus
Clause-②: no
Why no: release-owned prose; no package publishes from this PR.
Thread-read: none
Serial constraints cleared: read 2026-10-06T12:35Z. No open PR editscontent/docs/releases/.objectstack-fleet commented
on Oct 6, 2026 ContributorAuthorMore actionsos-dev-report
{
"issue": 21989,
"status": "done",
"branch": "claude/issue-21989-release-notes-17-7",
"pr": "#21994",
"session": "session_016tKoy8NJa35Yih1FdzrVmn",
"premise_still_valid": true,
"summary": "Wrote the curated 17.7.0 release page content/docs/releases/v17/17-7.mdx (1,402 lines, on the 17.6 page's structure). It covers highlights; silent changes; triaged breaking changes with a migration line and a coverage table for all 8 ADR-0087 conversions and 41 D3 entries added since 17.6.0; new capabilities; notable fixes, with security as classes; and Console, answering each objectui declared-breaking change. It also lists the two shipped-but-unlisted changesets and the one listed again, and ends with an upgrade checklist whose every line is Not exercised. The page is wired into v17/meta.json, v17/index.mdx and scripts/docs-audit/handwritten-docs.json, and 17-6.mdx gets one dated correction (#21158 was closed as not planned). The binding fact-check pass corrected 31 claims (e4a6280). After it, main gained 1abfc58 (#21985, the read half of #21922), which is not in the version commit; 8347e0d therefore records that 17.7.0's metadata-door reads still serve a stored row under a code-defined datasource name, and every gate and the docs build were rerun on that head. Premise correction: the dispatch named two objectui pin moves ending at 9dfaca654311, but the tree has five, ending at 0abd4f9f8769 (8832655, #21827), and the page covers all five. pr_create takes no labels, so skip-changeset and PR assignee hotlong were added afterwards through label-write (the read-back matches). The PR stays draft, with no ready and no auto-merge. The worktree is removed after this comment is posted.",
"tests": "Head 8347e0d (git rev-parse --short HEAD). Derived gates: node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands gives 57 commands, the same 57 as on e4a6280. Each ran on its own, output redirected before the exit was captured: 57 x EXIT=0, in batches of 30 (242 s) and 27 (146 s). --ran: '57 derived famil(ies) accounted for, 57 run, 0 NOT-MEASURED (a DERIVED zero, all 57 recorded an exit code and none of them is 3)'. Verdict lines: check-doc-anchors '457 internal #fragment link(s) across 416 source file(s) all resolve to a real heading'; check-issue-citations '303 resolves-as-pull-request, 15 cross-repo-unjudged, 8 resolves; every citation this change adds resolves'; check:role-word 'OK, no new occurrences of the reserved word'; check-release-notes OK; check-release-page-status OK (v16, v17); check-release-section-coverage OK, plain and --strict (10 published minors); the docs-accuracy-audit scope is in sync (199 hand-written docs); check-nul-bytes OK (10022 files, no raw control bytes). Two families once refused with PREREQUISITE NOT MET (exit 3): docs-transcript-drift and skill-examples. They passed after pnpm --filter '@objectstack/lint...' build and '@objectstack/client-react...' build were run under os-verify-lock. Docs production build under os-verify-lock: TURBO_FORCE=true pnpm turbo run build --filter=@objectstack/docs --concurrency=2 gave 'Tasks: 2 successful, 2 total', 'Cached: 0 cached, 2 total' and VERDICT command-exit 0 (held 151 s, shared box). BUILD_ID is NyE37SoduS08cU-KmnoFv, and .next/server/app/en/docs/releases/v17/17-7.html carries the final text. The earlier heads also built, and their 57-gate unions were green: bf08109 (BUILD_ID XY0WXS1yzK8pMoVeHaW7S) and e4a6280 (cq-KE8HxJJmCGI_pNUywe). Fact-check: the second pass corrected 31 claims (C1-C31, e4a6280), and 2 more were corrected while drafting (#21361 closed, not tracking; seventeen ui-object-* members, not eighteen). Mechanical checks on the final page: 276 cited SHAs resolve (objectstack, or an objectui blobless clone); 216 distinct sha-PR pairs match their commit subjects (0 mismatches); all 40 printable new D3 ids and all 8 conversions are present; MDX compiles with @mdx-js/mdx 3.1.1 and remark-gfm 4.0.1; 0 reserved-word hits; 0 control bytes. Ancestry on a shallow checkout: 1abfc58 against version commit 4e4e881 exits 1, and the control 753e7a1 (older) exits 0; 8a399b2 and 04e776b against 4e4e881 each exit 0. No ablation or reverse check: this is a docs-only change and neither applies. NOT MEASURED locally: the repo-wide lint and the CI-only families, which CI owns. CI on 8347e0d at report time: 12 success, 10 skipped, 13 in_progress, 0 failure.",
"mcp_calls": "0 (no MCP GitHub tool called)",
"api_writes": "3 REST writes, each through a scripts/pm tool on the fleet relay (transport auto, so dispatch). (1) fleet-write/dispatch.mjs: POST /repos/objectstack-ai/objectstack/dispatches, request fw-20261006T135248Z-685148, run 37474320519. pr_create sent POST /repos/objectstack-ai/objectstack/pulls (draft forced) and opened #21994; the read-back found 5408 bytes sent and stored, identical. (2) label-write.mjs: POST /repos/objectstack-ai/objectstack/dispatches, request fw-20261006T135348Z-cb45b0, run 37474455313. labels_add sent POST /repos//issues/21994/labels [skip-changeset], and assign sent POST /repos//issues/21994/assignees [hotlong]. The read-back shows documentation, size/xl and skip-changeset, with assignee hotlong. (3) post-stamped.mjs: this os-dev-report comment, POST /repos//issues/21989/comments. git push (not REST) went 4 times to claude/issue-21989-release-notes-17-7: the empty branch at 1c563af, then bf08109, e4a6280 and 8347e0d. There was no write to the card's assignee or labels, and no PATCH to the PR body.",
"open_questions": [],
"out_of_scope_findings": [
"carrier: the author of the 17.8.0 release page, noted, not filed. 8a399b2 (#21977) and 04e776b (#21976) shipped in 17.7.0, but their changesets are still in .changeset/, so 17.8.0's CHANGELOG will list them again. That page owes a section saying they shipped in 17.7.0 and are listed again, the shape this page uses for 748b240 (#21270).",
"carrier: the author of the 17.8.0 release page, noted, not filed. 1abfc58 (#21985) fixes the 17.7.0 metadata-door datasource read that this page now names, so the 17.8.0 page should list it as a fix to 17.7.0 behaviour."
]
}
Generated by Claude Code
objectstack-fleet commented
on Oct 6, 2026 ContributorAuthorMore actionsIndependent fact-check record — PR #21994, head
8347e0d172(read-only checker, not the page's author). Verdict FAIL → fix round dispatched to the same branch; ACCEPT, ready and auto-merge wait for the re-check. 2026-10-06T14:24ZFull record (13 findings: 2 wrong-fact, 1 security-recipe, 3 missing, 1 link, 4 overstated, 2 minor)
Verdict: FAIL
Fact-check record: PR #21994,
content/docs/releases/v17/17-7.mdx(head 8347e0d)Checked against: the version commit
4e4e881427(#21352), the 17.6.0 version commit617f25f8a4(tag@objectstack/spec@17.6.0), the 69## 17.7.0CHANGELOG sections at4e4e881427, commit and changeset bodies, code at4e4e881427, the objectui clone (deepened to0abd4f9f8769), GitHub (read-only: #21158, #21361, PR #21352 commits, Release run 37458970237 and its integrity-job log), and npm (npm view @objectstack/spec). No repo file was edited.Coverage
Release arithmetic (all recounted, all match the page).
- 323 changeset files deleted by
4e4e881427. - 69 CHANGELOG files carry
## 17.7.0. 48 of them carry 444 entries: 194 minor, 250 patch, 0 major. De-duplicated, that is 323 entries. - 8 ADR-0087 conversions added to
packages/spec/src/conversions/registry.ts. Their ids match the page. - 41 D3 semantic files added under
migrations/entries/semantic/, 18.*. The page's table rows sum to 4+3+1+2+3+1+1+2+5+19 = 41, and the "seventeenui-object-*and twoui-action-group-menu-*" claim is exact. - The 4 retired keys and 6 retired defs match the page.
PROTOCOL_VERSION = '17.0.0'at4e4e881427.- npm:
latest= 17.7.0, published 2026-10-06T12:22Z; 17.6.0 published 2026-10-02T03:03Z. So "4 days after 17.6.0" holds.
sha ↔ PR ↔ subject.
- Mechanically checked every distinct backticked
sha+#PRpair on the page: 227 pairs against the subjects in617f25f8..4e4e881427. There are 0 mismatches. - Three pairs are out of range on purpose (
1abfc58×1,748b240×2), and each was verified separately.
Breaking changes & migration. Breaking-marked entries are those with a
(narrowing)arm or!: 95 entries.- 94 are cited inside the Breaking section or the console pins. One is missing:
0fc8087(F4). - I read the full changeset bodies of about 113 entries cited in this section and compared each against the page text. That covers every bullet of every
####subsection, the page-block table (12 rows; commit subjects confirm the 9 stages of spec(ui): theComponentPropsMaprows still type renderer-read members asz.unknown()—navigationon object-map / object-gantt / object-tree andconditionalFormattingon object-kanban accept42— the family close-out after #21445 #21464 plus feat(spec)!: an object-grid block's exportOptions is the list view's export options object, and a bare format array is refused (#21229) #21287 / feat(spec)!: an object-grid page block types the seven members the grid reads, and resizableColumns retires for resizable (#21445) #21463 / feat(spec)!: an action:group / action:menu member refuses a non-array params unless its type is api, with the action:button prescription (#21855) #21869), and the ADR-0087 table.
What's new / silent runtime list.
- All 10 Highlights bullets and all 19 "running deployment" bullets were checked against their changesets.
- I read the 70 uncited changelog entries by title, and in full where a runtime effect was possible. Most are docs or provenance changes. One security-relevant fix is unlisted (F11).
Upgrade checklist.
- All 40 lines carry Not exercised. (parsed mechanically).
- Each line was traced to a migration note or a changeset. One step lacks a rollback caveat (F9).
Security fixes. All 6 Security bullets plus the credential and stored-metadata write-ups were checked for recipe content (F8, F10).
Shipped-but-unlisted / listed again.
8a399b2b15(fix(service-datasource): the admin door reads a datasource's origin from provenance, and a metadata-door write reaches it in the same boot #21977, for finding(service-datasource): a datasource created through the metadata door is missing from the admin door until restart, then reads as code-defined because the admin read defaults a missing origin to code #21923) and04e776b39a(docs(spec, docs): App.defaultAgent and actions-as-tools name the agent route as the one chat door #21976, for docs(spec, docs): App.defaultAgent's docblock and actions-as-tools.mdx name POST /api/v1/ai/assistant/chat, a route cloud retired (cloud#2621) #21968) are ancestors of4e4e881427and not of617f25f8. Their changesets.changeset/21923-…and.changeset/21968-…are still in the4e4e881427tree.- Commit times are 10:34:43Z and 10:41:08Z. The version PR's last refresh was 10:29:32Z (
d9af53a), and the merge was 11:12:52Z. - The integrity-job log of run 37458970237 contains a
##[warning]naming both changesets, and the job concluded success. 748b240(feat(types,automation): a host's per-kernel scheduled-work OFF reports its own reason #21270) is an ancestor of617f25f8. Its changeset (21110-scheduled-work-host-reason.md) was present at617f25f8and deleted by4e4e881427. The 17.6.0 page lists it under "Also shipped". All three are confirmed.
1abfc58is NOT an ancestor of4e4e881427. It was committed 12:26:10Z, after npm publish at 12:22:14Z.- At
4e4e881427,getMetaItemadopts the stored row (protocol.ts:10047 if (record && !shippedFlowActiveRead)), anddeclinesStoredRow/storedRowDeclineddo not exist. packages/metadata-protocol/srcis unchanged betweenf76c6221ac(where fix(metadata-protocol): the metadata door serves a code-defined datasource's code definition while a stored row exists #21985 measured H1/H2) and4e4e881427.753e7a1's own changeset says "While a stored row exists under a code-defined name,GET /api/v1/meta/datasource/:namestill serves that row".- The page's description of 17.7.0 behaviour (by-name, list,
effectivelayer) is accurate.
New capabilities / Notable fixes / Console.
- Content-checked 28 New-capabilities shas (title level, and the body where a specific claim was made) and 34 Notable-fixes shas, including bodies for
c9761cd,31e3e00,1968d5e,1c3a4d9,ff16740,7ebb543,607463d,4c8363f,aead296and025008a. That is well over 40 spot checks in total. - Pin moves: exactly 5
.objectui-shachanges in range,31971ff1e28f → … → 0abd4f9f8769, carried by8963dbf/1cbe165/100f68b/1354e7b/8832655. The final pin is0abd4f9f8769. - objectui recount over
31971ff1e28f..0abd4f9f8769: 173 commits; 254 changesets added; 229 releasing (74/111/17/24/3); 25 release-nothing; 13 commits with no changeset; 65 declared breaking (16/43/2/4/0, from each pin entry's tally). All match. - All 44 objectui hashes in the console text and table are inside the range. Thirteen bullet subjects were matched to their objectui commits, for example
c096f0327→ objectui#11383,d93e53f5d→ driver-sql (PG): sum/avg/min/max over a boolean column throw the raw PostgreSQL 42883 with no ADR-0112 envelope (status undefined) #11455 andf624f278d→ fix(runtime): the dispatcher /metadata transport folds the URL segment before the org-scope decision #11553. - No retired objectui node key is a
PageComponentTypemember or aComponentPropsMaprow (both enumerated at4e4e881427).
Edits to index.mdx and 17-6.mdx.
- Release dates are correct.
- security(core, plugin-security): an unauthenticated principal never resolves the permission sets bound to the
guestanchor; ADR-0090 D9 is declared and seeded but not enforced #21158:state_reason: not_planned, closed 2026-10-04T13:40Z. The closing comment quotes the maintainer's ruling (no demand). Confirmed. - Every clause of the index summary was checked (F1 is the exception).
meta.jsonandhandwritten-docs.jsonare trivial and correct.
Names. About 75 config keys, env vars, routes, exports and error codes named on the page were grepped at
4e4e881427. None is invented.OS_LOCALIZATION_*_FORMATandOS_LOCALIZATION_FIRST_DAY_OF_WEEKare absent by design: the page says they are no longer read, and0d8ea5econfirms it. Every in-page anchor resolves to a heading (slugged), as do the cross-page anchors17-6#known-issues-found-after-publish,17-6#also-shipped-in-1760--not-in-its-changelog,upgrading#moving-the-dependency-pinsandv17#upgrade-checklists.Findings
F1 — wrong-fact.
content/docs/releases/v17/index.mdxlines 86–87.- Claim: "App-authored bodies and flows reach
sys_metadataandsys_metadata_historyonly through the metadata API". - Evidence: a flow still reads both tables through its
get_recordnode, outside the metadata API.a4f0cb0(fix(service-automation): a flow's get_record node serves the stored-metadata family the way the data door does (#21519) #21621) changeset: "a flow'sget_recordnode that reads the stored-metadata tables is served what the generic data door serves".f40bb32(fix(service-automation): flow write nodes refuse a stored-metadata family target (#21624) #21649): "get_recordkeeps serving these tables projected and keyed".a2aadab(feat(spec)!: FlowSchema refuses a create_record, update_record or delete_record node whose static objectName is a stored-metadata table, with the runtime's prescription (#21654) #21687), under "What stays accepted, byte for byte": "Aget_recordnode on those tables (a read is not a write…)".- The 17.7 page itself says so at lines 225–227.
- Corrected wording: "App-authored hook, action and job bodies reach
sys_metadataandsys_metadata_historyonly through the metadata API, and a flow can no longer write them (itsget_recordnode is served the projected body and a keyed hash);"
F2 — wrong-fact.
17-7.mdxlines 205–206.- Claim: "For app-authored work, the metadata protocol is now their only writer and their only reader."
- Evidence: same as F1. A flow is app-authored work:
a2aadabsays "a flow is app-authored automation". The page contradicts itself at lines 225–227 ("Aget_recordnode on either table is served the projected body and the keyed hash"). - Corrected wording: "For app-authored work, the metadata protocol is now their only writer; for a sandboxed hook, action or job body it is also their only reader, and a flow's
get_recordnode reads them only in the projected, keyed form the data door serves."
F3 — security-recipe (borderline).
17-7.mdxlines 241–243, read with line 204.- Claim: "On the data door, so does a filter that reaches the body or a hash column through a
{ $field }comparand, or more than 32 combinators deep (5d0e4e2, fix(metadata-protocol)!: one stored-metadata filter collector and search narrowing, owned by the door and called by the reader seam; cross-field and deep family reads refused #21619)." - Evidence:
- Line 204 says the body holds "credential material included".
- This sentence names both shapes that evaded the 17.6.0 body/hash filter refusal: the cross-field comparand and nesting past the collector's depth. It also gives the exact threshold.
5d0e4e2's changeset explains that each shape let row presence disclose the column ("A body$containsof a stored credential answered the row and a wrong guess answered none").- For a reader on 17.7.0 the threshold carries no migration value, because every filter on those columns is refused at any depth. Its only use is against an unpatched 17.6.0 deployment.
- There is no payload or step list, hence "borderline". The same detail is in the shipped CHANGELOG, so fixing the page is cheap but does not undo that disclosure.
- Corrected wording: "On the data door, so does any filter that reaches the body or a hash column indirectly (
5d0e4e2, fix(metadata-protocol)!: one stored-metadata filter collector and search narrowing, owned by the door and called by the reader seam; cross-field and deep family reads refused #21619)."
F4 — missing (breaking). Breaking changes & migration (lines 177–918). The change appears only in checklist line 1330.
- Claim: none.
0fc8087(fix(lint)!: action-name-undefined resolves record:related_list action ids against the child object #21626, changeset title "fix(lint)!:action-name-undefinedresolvesrecord:related_listaction ids against the related object, and refuses an id the list cannot draw (lint:validate-action-name-refsdoes not walkrecord:related_list.actions, which the objectui renderer now resolves as action ids (objectui#11163), so a misspelled id is refused only at runtime #20936)", Clause-②no (narrowing)) is the only breaking-marked 17.7.0 changeset not written up in the section. - Evidence: its changeset says "A stack whose related list names an id the list cannot draw built clean before and now fails
os validate/os lint/os buildwithaction-name-undefined(severityerror)." That is reachable from app metadata, so it is inside the section's own triage rule. - Corrected wording (add under "Smaller breaking changes"): "-
action-name-undefinednow readsrecord:related_listproperties.actions: each id must name an action of the related object that declares alist_toolbar,list_itemorrecord_relatedlocation, so a stack that built clean can failos validate,os buildandos lint(0fc8087, fix(lint)!: action-name-undefined resolves record:related_list action ids against the child object #21626). Such an id never drew a button; define the action on the related object, or remove the id."
F5 — link.
content/docs/releases/v17/17-6.mdxlines 1515–1517 (the added correction).- Claim: "See 17.6.0's known issues on the 17.7.0 page."
- Evidence: the anchor lands on the
### Notable fixes in 17.7.0heading (17-7.mdx line 989), whose first block is the Security list. "17.6.0's known issues" is a bold lead-in 40 lines further down (17-7.mdx line 1029), with no anchor of its own. The label and the target do not match. - Corrected wording: either promote 17-7.mdx line 1029 to a heading
#### 17.6.0's known issuesand link/docs/releases/v17/17-7#1760s-known-issues, or relabel the link: "See Notable fixes in 17.7.0 (its "17.6.0's known issues" list) on the 17.7.0 page."
F6 — overstated.
17-7.mdxlines 158–159, and lines 432–434.- Claims: "
PUT/DELETE /api/v1/meta/datasource/defaultanswer403" (line 158), and "PUTandDELETEon/api/v1/meta/datasource/defaultanswer403too" (lines 432–434). - Evidence:
753e7a1(fix(service-datasource,runtime,metadata-protocol)!: a stored datasource row no longer displaces a code-defined datasource at boot, and the metadata door refuses edits to the host default #21965): "DELETE /api/v1/meta/datasource/defaultwith no stored row answered 200 and now answers the same403", and "A row the boot warning names is removable …DELETE /api/v1/meta/datasource/:nameanswers 200 and deletes it." A DELETE of a storeddefaultrow still answers 200. The page's own repair step at line 1315 depends on that. - Corrected wording:
- Line 158: "
PUT /api/v1/meta/datasource/default, and aDELETEof it with no stored row, answer403;" - Lines 432–434: "
PUTon/api/v1/meta/datasource/default, and aDELETEthere with no stored row, answer403too".
- Line 158: "
F7 — overstated.
17-7.mdxlines 74–75 and 743–746.- Claims: "a withdrawal at any metadata layer holds (
3c7785d, fix(rest,metadata-protocol): a public form's intake withdrawal at any metadata layer holds; layering can only narrow intake #21864)", and "An explicitenabled: falseorallowAnonymous: falseat any layer closes the form". - Evidence: the changeset of
3c7785dcarries two "Known limit" paragraphs that the page drops:- "An organization overlay that was stored before the env-wide withdrawal, or that a rollback or commit-revert restores, can still be served if it keeps the form open under a different key or place than the env-wide definition. … Rollback and commit-revert restores are not gated by the save check."
- "A withdrawal of a view name closes that name in every package … it may over-close, never under-close. Per-package precision is tracked in security(metadata): tighten the draft publish gate and package identity for org view overlays (follow-up to #21864) #21934."
- Corrected wording (append after line 749): "Two limits remain: an organization overlay stored before the withdrawal, or restored by a rollback or commit revert, can still serve the form under a different key or place, so withdraw it in that overlay too; and a withdrawal closes the view's name in every package that ships one (security(metadata): tighten the draft publish gate and package identity for org view overlays (follow-up to #21864) #21934)."
F8 — overstated.
17-7.mdxlines 1001–1008 (Security).- Claim: "Field-level reads are narrowed on more surfaces: … and judges an
objectOverrideparam against the object it names (e6dc7a2, fix(metadata-core,rest,runtime): judge an objectOverride action param against the object it names #21904); … global search skips the objects and fields the caller cannot read instead of answering403(87712ab, fix(metadata-protocol): global search skips objects and fields the caller cannot read #21879)". - Evidence:
e6dc7a2isClause-②: yes (widening). Its measured effect: "the only served action that moved issys_user.invite_user, which is now served to thedelegated_adminand themember". The mask had been over-withholding.87712abturns a blanket403into an answer. Before, nothing leaked, because the engine refused the search.- Neither narrows a read.
- Corrected wording: "Field-level reads are narrowed on more surfaces: the object-schema mask removes a denied field's references from the whole served document (
a6a7547, fix(metadata-core): the object-schema field mask also removes a denied field's references from the served document (ADR-0106 D1) #21743); an activity row whose every changed field the reader is withheld is no longer served (3bddd4a, fix(plugin-audit): an update activity row whose every recorded change is withheld from the reader is withheld as a row, on every listing face (#21388) #21427); and a field-narrowed search no longer matches through the pinyin companion of a field outside the set (0728cbf, fix(objectql): a field-narrowed search no longer matches through the companion of a field outside the search-field set #21930). The mask also judges anobjectOverrideparam against the object it names, so a delegated admin is served the invite action again (e6dc7a2, fix(metadata-core,rest,runtime): judge an objectOverride action param against the object it names #21904), and global search skips the objects and fields the caller cannot read instead of answering403(87712ab, fix(metadata-protocol): global search skips objects and fields the caller cannot read #21879)."
F9 — missing (checklist caveat).
17-7.mdxlines 1309–1310, read with lines 1273–1275.- Claim: "Run
os secret rewrap, thenos secret rewrap --apply, to re-seal oldersys_secretciphertext." - Evidence:
- The rewrap goes through
rotateKey, andlocal-crypto-provider.ts:107at4e4e881427says "(rotateKeyopens with the recorded derivation and seals with version 2)". 57cc695says "a secret set or rotated by this release carries thev2:marker, and an earlier release cannot open it".- So
--applymakes every re-sealed row unreadable to 17.6.0. The step is presented as unconditional, while0557c2fsays "nothing on any boot or upgrade path invokes it", which makes it optional. - The rollback line at 1273 covers secrets "you set or rotate", not a bulk rewrap. As written, the step silently removes the rollback path the checklist warns about.
- The rewrap goes through
- Corrected wording: "Once you will not roll back past 17.7.0, run
os secret rewrap, thenos secret rewrap --apply, to re-seal oldersys_secretciphertext. Every row it re-seals carriesv2:, which an earlier release cannot open. Not exercised."
F10 — overstated.
17-7.mdxlines 351–352.- Claim: "Set
account.accountLinking.requireLocalEmailVerified: falseto restore the old linking, after reading the library's account-takeover warning." - Evidence:
41a1135: "falseturns off only the local-verification check and keeps the unlink rule." The old behaviour is not fully restored, because a provider the user unlinked still does not re-link implicitly. The key itself is real:auth-manager.ts:4609at4e4e881427. - Corrected wording: "Set
account.accountLinking.requireLocalEmailVerified: falseto turn the local-verification check off again (an unlinked provider still does not re-link implicitly), after reading the library's account-takeover warning."
F11 — missing (security fix). Notable fixes → Security, lines 994–1027.
- Claim: none.
49524f6(fix(rest): withdrawing a public form takes effect on every anonymous intake door #21420,@objectstack/rest) is not on the page: "When an administrator withdraws a public form, both anonymous form routes (GET /forms/:slugandPOST /forms/:slug/submit) now answer404 FORM_NOT_FOUNDand no record is created … If a service the routes need to resolve the form is registered but cannot be reached, both routes refuse the request instead of serving the form." - Evidence: this is a fail-closed anonymous-intake fix, separate from
6dd99b8and3c7785d. - Corrected wording (add a Security bullet): "- A withdrawn public form is refused on both anonymous form routes and creates no record, and both routes refuse instead of serving when they cannot resolve the form (
49524f6, fix(rest): withdrawing a public form takes effect on every anonymous intake door #21420)."
F12 — minor.
17-7.mdxlines 671–676.- Claim: "an undeclared key, a refused value … and a missing
approversare refused atos validate,os compile,defineStack, the metadata save door andregisterFlow, where they used to register and fail every run that reached the node." - Evidence:
866683f: "Registration already refused an undeclared key, but a refused value such asescalation.timeoutHours: 0.5registered and then failed every run". SoregisterFlowis new only for the refused-value case. - Corrected wording: "…are refused at
os validate,os compile,defineStackand the metadata save door, and a refused value atregisterFlowtoo, where it used to register and fail every run that reached the node (registerFlowalready refused an undeclared key)."
F13 — minor.
17-7.mdxlines 1120–1121.- Claim: "The per-commit lists are in
packages/console/CHANGELOG.mdunder## 17.7.0." - Evidence: the
1cbe165entry says "…and 11 more releasing changesets in this range (list capped at 100; see the objectui range below)". That list is not complete. - Corrected wording: "The per-commit lists (the second pin's capped at 100 of its 111 entries) are in
packages/console/CHANGELOG.mdunder## 17.7.0."
Not checked
- Docs build and link checker. I did not run the docs site build,
check-doc-anchorsor any other repo script; the repo is read-only for this task. Anchors were checked with a GitHub-style slug approximation. scripts/collect-release-notes.sh. Not run. I extracted the## 17.7.0sections directly fromgit show 4e4e881427:<CHANGELOG>, which is the same source.- objectui changesets. Only the 13 cited subjects and the per-pin tallies were verified. The prose of the 65 upstream breaking changesets, and the "How ObjectStack answers" column beyond the
PageComponentType/ComponentPropsMapmembership check and the dashboarddataset/componentrefusal, were not re-derived. - Measured-behaviour claims quoted from changesets. Statements such as "on PostgreSQL several of these answered 500", "No renderer for it ever shipped" and the census counts were taken from the changesets and not reproduced. No runtime was booted, and no upgrade was exercised; the page correctly says so.
- The cloud repository's commits in the window. The page makes no cloud claims.
- Access to
sys_metadatathrough the generic data door on 17.6.0. I did not check which principal classes can read it there. That would refine F3's real-world exposure, not whether the text names the bypass.
- 323 changeset files deleted by
objectstack-fleet commented
on Oct 6, 2026 ContributorAuthorMore actionsos-dev-report
{
"issue": 21989,
"status": "done",
"branch": "claude/issue-21989-release-notes-17-7",
"pr": "#21994",
"session": "session_016tKoy8NJa35Yih1FdzrVmn",
"premise_still_valid": true,
"summary": "Fix round on PR #21994: one commit, a53c972, pushed fast-forward on top of 8347e0d. No rebase, amend or force-push. The PR stays draft, with no ready and no auto-merge. I re-verified each of F1-F13 against its cited source before applying it, and all 13 are confirmed. F1/F2: the a4f0cb0 (#21621), f40bb32 (#21649) and a2aadab (#21687) changesets say what the record quotes. The job-body half of the new index wording rests on code at 4e4e881: packages/runtime/src/sandbox/body-runner.ts:1024-1035 applies both the read refusal and the write refusal in buildSandboxApi, which the job face uses at :1245. F3: 5d0e4e2's changeset names both evading shapes and the 32-combinator backstop. F4: the 0fc8087 changeset carries Clause-2 no (narrowing). F6: 753e7a1 and 9cc2c79 say DELETE of a stored row still answers 200. F7: 3c7785d has two Known limit paragraphs. F8: e6dc7a2 is Clause-2 yes (widening), and 87712ab replaces a 403 with an answer. F9: rotateKey seals v2 (local-crypto-provider.ts:107), and 0557c2f says nothing on any boot or upgrade path invokes it. F10: 41a1135 says false keeps the unlink rule. F11: 49524f6 is an ancestor of 4e4e881 (exit 0) and not of 617f25f (exit 1; the control leg 16c5a33, older, exits 0). Its entry is in packages/rest/CHANGELOG.md under 17.7.0, and the page did not cite it. F12: 866683f says registration already refused an undeclared key. F13: the 1cbe165 entry reads 'and 11 more releasing changesets in this range (list capped at 100'. Per-finding table (all in commit a53c972; none refuted): F1: applied (record wording), at index.mdx 86-89 | F2: applied, tightened wording, at 17-7.mdx 206-209 | F3: applied (seat ruling wording, verbatim), at 17-7.mdx 244-245 | F4: applied, tightened wording (adds the changeset's stack.actions-by-objectName arm); checklist line reworded to match, at 17-7.mdx 873-879; checklist 1359-1360 | F5: applied (seat ruling relabel, no new heading), at 17-6.mdx 1515-1517 | F6: applied (record wording), at 17-7.mdx 159-160 and 437-440 | F7: applied, tightened wording (limit stated without the key/place shape, as 'may still serve'); Highlights now says 'within two known limits' and links #public-forms, at 17-7.mdx 756-762; Highlights 74-76 | F8: applied, tightened wording ('now served the invite action', since 'again' is not in e6dc7a2's changeset; pinyin clause reduced to class, see F3 scan), at 17-7.mdx 1020-1028 | F9: applied, tightened wording (optional; nothing on the upgrade path runs it; v2 re-seal removes the rollback path; Not exercised kept); same caveat added at the write-up and the rollback line, at 17-7.mdx 1334-1339; also 316-319 and 1298-1300 | F10: applied (record wording), at 17-7.mdx 354-357 | F11: applied, tightened wording (the unreachable-service clause follows 49524f6's changeset), at 17-7.mdx 1032-1035 | F12: applied, tightened wording: all three are refused at registerFlow now ('That covers ... registerFlow'), 'used to register' is limited to the refused value, and a missing approvers' prior state is not claimed, at 17-7.mdx 680-683 | F13: applied, tightened wording, at 17-7.mdx 1144-1146. F3 scan: I re-read Notable fixes, Security, the credentials write-up and the stored-metadata write-up, and changed two more lines, each reduced to its class. (1) 17-7.mdx 1022-1023 (was 1007-1008): 'no longer matches through the pinyin companion of a field outside the set' became 'no longer matches through a field outside the set'. The companion column was the channel that evaded the field narrowing (0728cbf). (2) 17-7.mdx 1043-1045 (was 1020-1021): 'resolves a driver by every spelling the write door accepts' became 'identifies a driver the way the write door does'. Alternate driver spellings were the shape that evaded the redaction (fb69825). I read the following and kept them, because each is class-level or carries migration value: Highlights 14-16; the door list at 238-243 (integrations that filter those columns now get 400); the credential-column list at 272-284 (rotation rationale and the integration move, no evasion shape); the fail-closed guards at 162-163 and 339-342; the linking condition at 343-352 (the behaviour change itself); Ed25519 at 831-834 and 1048-1049 (re-sign migration); the attachment and comment refusal at 1029-1031 (a surface, not an evasion shape); the having {$field} rule at 655-658 (correctness, not security); and the RLS examples at 1386 (the author's own policies). Kept on purpose: the section heading and Highlights title 'App-authored code reaches stored metadata ... through the metadata API'. A flow is not code, and renaming the heading would break the anchors at 910 and 1015. PR body follow-up for the seat (I do not PATCH it): the body's test evidence names head 8347e0d. It should name a53c972 and this round's results from tests below, and add the line: 'Fix round: the 13 findings of the independent fact-check record (#21989 comment 6018402030) applied in a53c972.' The worktree is removed after this comment is posted.",
"tests": "Head a53c972 (git rev-parse --short HEAD, tree clean). Derived gates: node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands gives 57 commands, the same 57 as last round. Each ran on its own; output went to a file and the exit was captured before any pipe. First pass: 54 x exit 0, and 3 x exit 3 PREREQUISITE NOT MET (lint check:doc-formula-expressions and check:doc-security-posture: no lint/formula build; spec check:skill-examples: no client-react d.ts). Those 3 are NOT MEASURED, not failures. I then ran pnpm exec turbo run build --filter=@objectstack/formula --filter=@objectstack/lint --filter=@objectstack/client --filter=@objectstack/client-react --concurrency=2 under os-verify-lock (VERDICT command-exit 0, 34/34 tasks, held 174 s, shared box). All 3 re-ran at exit 0. The spec build ran first under the lock (VERDICT command-exit 0, held 73 s). --ran reconciliation with exit codes: '57 derived famil(ies) accounted for - 57 run, 0 NOT-MEASURED (a DERIVED zero - all 57 recorded an exit code and none of them is 3)'. Verdict lines: check-doc-anchors '458 internal #fragment link(s) across 416 source file(s) all resolve to a real heading'; check-issue-citations (node scripts/check-issue-citations.mjs) '305 resolves-as-pull-request, 15 cross-repo-unjudged, 9 resolves; every citation this change adds resolves'; check:role-word 'OK, no new occurrences of the reserved word'; check-release-notes 'OK - every released major has a curated, navigable release page'; check-release-page-status OK, 2 GA majors (v16, v17); check-release-section-coverage OK, plain and --strict (10 published minors); check:docs-audit-scope 'docs-accuracy-audit scope is in sync with content/docs/: 199 hand-written doc(s)'; check-nul-bytes 'OK (scanned 10022 text file(s) ... no raw ASCII control bytes)'. Docs production build under os-verify-lock: TURBO_FORCE=true pnpm turbo run build --filter=@objectstack/docs --concurrency=2. It gave 'Tasks: 2 successful, 2 total' and 'Cached: 0 cached, 2 total', with VERDICT command-exit 0 (held 205 s). The built page .next/server/app/en/docs/releases/v17/17-7.html and its llms body carry the corrected text, and the removed text is absent. Present, html/llms counts: 'reaches the body or a hash column indirectly' 2/1, 'A sandboxed hook, action or job' 2/1, 'within two' 2/1, 'record_related' 2/1, '49524f6' 2/1, 'already refused an' 2/1, '100 of its 111' 2/1, 'removes the rollback path' 2/1, 'delegated admin is now served' 2/1, 'identifies a driver the way the write door does' 2/1. Absent (0/0): 'their only reader', 'more than 32 combinators', 'pinyin companion', 'every spelling the write door accepts'. The built 17-6 page carries the relabelled link, and the built v17 index carries the new summary. Mechanical checks on the final page: 231 distinct sha-PR pairs (302 occurrences), 0 unresolved, 0 subject mismatches. 279 distinct backticked hex tokens: 232 resolve in objectstack and 46 in the objectui clone; the remaining one is the word ed25519, not a sha. MDX compile of 17-7.mdx, index.mdx and 17-6.mdx with @mdx-js/mdx 3.1.1 and remark-gfm 4.0.1: exit 0, 3 OK. 0 reserved-word hits (role-word gate). 0 control bytes (grep -P scan of the 3 files, plus check-nul-bytes). No ablation or reverse check: this is a docs-only change and neither applies. NOT MEASURED locally: the repo-wide lint and the CI-only families, which CI owns. CI on a53c972 at report time: 25 success, 7 skipped, 1 in_progress, 0 failure.",
"mcp_calls": "0 (no MCP GitHub tool called)",
"api_writes": "1 REST write: post-stamped.mjs posts this os-dev-report comment through the fleet-write relay (transport auto resolves to dispatch). That is POST /repos/objectstack-ai/objectstack/dispatches, which the relay run turns into POST /repos//issues/21989/comments. git push (not REST) went once to claude/issue-21989-release-notes-17-7, fast-forward 8347e0d..a53c972. There was no label write, no assignee write, no PR body PATCH and no draft flip. Reads only: GET of the #21989 comments, GET of the PR, and GET of the check-runs for a53c972.",
"open_questions": [],
"out_of_scope_findings": []
}objectstack-fleet commented
on Oct 6, 2026 ContributorAuthorMore actionsACCEPT — PR #21994 at
a53c972fa7(Fixes #21989: the curated 17.7.0 release page)Director seat, summon #32 · session
session_016tKoy8NJa35Yih1FdzrVmn· holder of claim6016390252· 2026-10-06T14:58Z · the review of record for the reports6017859876and6018968013. The independent fact-check6018402030returned FAIL on8347e0d172, and the fix rounda53c972fa7addresses it. No contract review is owed:Clause-②: no, and nothing underpackages/spec/src/**is touched. Release-notes prose is not a contract surface, so the seat re-read the fixes sentence by sentence against their sources.Checklist (read on GitHub, not from the report):
- Form: draft, base
main, first lineFixes #21989,Clause-②: no, labelsdocumentationandskip-changeset. - Scope: 5 files, all on the claimed surface:
content/docs/releases/v17/17-7.mdx(new);v17/index.mdx,v17/meta.jsonandscripts/docs-audit/handwritten-docs.json;- one dated correction in
17-6.mdx. check-governed-merges.mjs --pr 21994: NOT governed, 1,449 changed lines, which is under the human-merge threshold. ⛔ No version, CHANGELOG, changeset or release-workflow file.
- Mergeability: the head merges cleanly onto
main, and the fix round is a fast-forward of8347e0d172.
The fact-check and its fixes (the seat read diff
8347e0d172..a53c972fa7, one item at a time):- F1 and F2, wrong facts: fixed consistently in
index.mdxand17-7.mdx.- Hook, action and job bodies reach the stored-metadata tables only through the metadata API.
- A flow can no longer write them. Its
get_recordnode reads them only in the projected, keyed form. - The page no longer contradicts itself at the
get_recordparagraph.
- F3, security: the seat ruled for the safer fix. The cross-field comparand and the depth threshold that evaded 17.6.0's refusal are no longer named; only the class remains. The author's scan of the Security and credential write-ups reduced two more lines to their class (
0728cbf,fb69825). - F4, breaking:
0fc8087(fix(lint)!: action-name-undefined resolves record:related_list action ids against the child object #21626) now sits under "Smaller breaking changes".- The seat checked the
stack.actions-by-objectNamearm against.changeset/20936-action-name-refs-related-list.md:15. - The checklist line was reworded to match.
- The seat checked the
- F5, link: the link is relabelled "Notable fixes in 17.7.0 (its 17.6.0's known issues list)". No new heading was added.
- F6: the
403is now scoped toPUT, and to aDELETEwith no stored row. This matches753e7a1, and the repair step's200still holds. - F7: the two known limits of
3c7785dare stated: the pre-withdrawal or restored overlay, and the cross-package name (security(metadata): tighten the draft publish gate and package identity for org view overlays (follow-up to #21864) #21934). Highlights now says "within two known limits".- The page's "may still serve" leaves out the changeset's different-key-or-place condition. It over-warns, never under-warns, so the seat accepts it.
- F8:
e6dc7a2and87712abare no longer filed as read narrowings. - F9:
os secret rewrap --applyis marked optional. The page says nothing on the upgrade path runs it, and that it removes the rollback path because the re-sealed rows carryv2:. The rollback line now covers re-wrapped secrets. Not exercised is kept. - F10:
requireLocalEmailVerified: falseis described as turning only the local check off; the unlink rule stays. - F11:
49524f6(fix(rest): withdrawing a public form takes effect on every anonymous intake door #21420) is added to Security. The seat checked the unreachable-service clause against.changeset/21331-public-form-withdrawal.md:9. - F12: the
registerFlowwording is checked against866683f's changeset:20 ("…registerFlowand the metadata save door"). It says an undeclared key was already refused there. - F13: the capped console list is now disclosed: "100 of its 111".
Confirmed unchanged by the fact-check:
- the 227 sha–PR pairs (231 after the fix round, with 0 mismatches);
- the 323 / 444 / 8 / 41 counts;
- the five pin moves ending
0abd4f9f8769, and the 229 / 65 tallies; - the ancestry of the shipped-but-unlisted
8a399b2b15and04e776b39a; - that
1abfc58(fix(metadata-protocol): the metadata door serves a code-defined datasource's code definition while a stored row exists #21985) is not in 17.7.0; - all 40 checklist lines marked Not exercised;
- the security(core, plugin-security): an unauthenticated principal never resolves the permission sets bound to the
guestanchor; ADR-0090 D9 is declared and seeded but not enforced #21158not_plannedclose.
Gates on
a53c972fa7(the dev's measurement):- All 57 derived families exited 0, with 0 not measured.
- The anchor gate (458 links), the citation gate, the role-word gate, release-notes, release-page-status, and section coverage both plain and
--strictall pass. - The docs production build is uncached, and the built page carries the corrected text and none of the removed text.
Carried to the 17.8.0 page (noted, not filed):
- Changesets
21923-…and21968-…are still in.changeset/, so 17.8.0's CHANGELOG will list them again. That page owes a "shipped in 17.7.0, listed again" section. 1abfc58(fix(metadata-protocol): the metadata door serves a code-defined datasource's code definition while a stored row exists #21985) belongs there as a fix to 17.7.0's metadata-door datasource read.
Landing: the PR body is updated to name
a53c972fa7and the fix round. At this reading CI ona53c972fa7hadLint & Repo Gatesstill running, and none was red. The seat flips the PR ready and arms auto-merge, so the PR enters the queue only once every check is green.
Generated by Claude Code
- Form: draft, base
- added a commit that references this issue
on Oct 7, 2026
Filing gate: ③ a task the maintainer assigned directly. In the live director chat, after 17.7.0 published, the maintainer said, verbatim: 「版本说明你抓紧时间写,并且提交合并」. Filed by the director seat, summon #32 (
session_016tKoy8NJa35Yih1FdzrVmn), which claims and drives it. Reader who acts: the director seat's dispatched dev, then the seat's ACCEPT and landing.What
latest, 2026-10-06T12:22Z), through version PR chore: version packages #21352 (merge4e4e881427) and the Release run.content/docs/releases/v17/17-7.mdxdoes not exist, and no pre-cut draft was made.Scope (
content/docs/releases/is release-owned; one docs-only PR,skip-changeset,Clause-②: no)content/docs/releases/v17/17-7.mdxin the 17.6 page's structure:content/docs/releases/v17/meta.json, updatecontent/docs/releases/v17/index.mdxas docs(releases): finalize the 17.6.0 notes after publish #21362 did, and add it toscripts/docs-audit/handwritten-docs.json.scripts/collect-release-notes.sh "@objectstack/spec@17.6.0" "@objectstack/spec@17.7.0";scripts/objectui-range.mjsover the.objectui-shamoves in the range, for the Console section, with objectui's declared-breaking changes named.Generated by Claude Code