Repository navigation
feat(spec)!: retire the view-level api data source — a view binds its object or static rows; an API call is the page element's binding (#23082) - #23160
Conversation
Claude-Session: https://claude.ai/code/session_01BRQ9Mp1yH7R1az6MaUM18H Co-authored-by: Claude <noreply@anthropic.com>
… pins Regenerated: content/docs/references/** (gen:docs), the strictness counts shard (gen:strictness-ledger). The retirement pin joins the spec repo project (it walks five repo roots) and is the second witness on the absence-walk radius rows. Claude-Session: https://claude.ai/code/session_01BRQ9Mp1yH7R1az6MaUM18H Co-authored-by: Claude <noreply@anthropic.com>
…tire-view-api-source
…rom the merged tree origin/main (287fd6e) brought PR #23101's component rows; the branch's retirement removes the view-level api arm from the same page. Regenerated with gen:docs on the merged tree per scripts/pm/os-regen-merge.sh step 4. Claude-Session: https://claude.ai/code/session_01BRQ9Mp1yH7R1az6MaUM18H Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 1 package(s): 3 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 3 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 141 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 c9876c263d6f588d9f934bfcc6a7dd3f08e56430 && git checkout c9876c263d6f588d9f934bfcc6a7dd3f08e56430
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin dc93781c1947b53cff50a550ad551e462a464594 12f86031637d7aaffe0ce28819166fb55bad8931 && git checkout -B drift-repro dc93781c1947b53cff50a550ad551e462a464594 && git merge --no-ff 12f86031637d7aaffe0ce28819166fb55bad8931
node scripts/docs-audit/affected-docs.mjs --json dc93781c1947b53cff50a550ad551e462a464594
|
Contract reviewServed-tier: Inputs read: card #23082 (body and all 4 comments, ruling Check-runs on the head as read for this record: 27 completed ① Derived judgmentsAccept set and public surface, each judged:
② Semver level
③ Boundary flagsDev report
Escalations raised by this review:
Required before a PASS on the next head: ① items 4, 5 and 7 (three string edits plus Implemented-by: VERDICT: FAIL |
…omponent describes, pin wording Review 6138665801 ① items 4, 5, 7: the prescription, its pin regex and the changeset quotation stamp the bare major (the house form of every prescription added since the v18 line opened; 18.0.0-next.N is the first release carrying this); ObjectGrid/ObjectMap/ObjectTree/ObjectGantt `data` describes no longer list the `api` discriminator; the ledger note and the changeset say 'measured at 7578323a544e' instead of 'the pin'. Claude-Session: https://claude.ai/code/session_01BRQ9Mp1yH7R1az6MaUM18H Co-authored-by: Claude <noreply@anthropic.com>
…tire-view-api-source
… the four data describes drop the api discriminator gen:docs on the merged tree; check:generated reads all 14 artifacts up to date. Claude-Session: https://claude.ai/code/session_01BRQ9Mp1yH7R1az6MaUM18H Co-authored-by: Claude <noreply@anthropic.com>
Contract reviewServed-tier: Inputs read: card #23082 (body and all 5 comments: triage Check-runs on the head as read for this record: 48 runs, every one ① Derived judgmentsThe three items
The whole net diff on this head, accept set and public surface:
Landing, stated so the record is not misread: the diff touches ② Semver level
③ Boundary flagsDev report
Escalations standing after this record: E and F (kit owner, What landing still needs beyond this record: the maintainer's authorized APPROVED review on Implemented-by: VERDICT: PASS |
维护者速读(终稿)
改了什么: 视图(列表、表单)的 为什么改: 您在 #23082 批了 C。旧的视图级 API 源能把密钥写进 风险与代价(含回滚): 风险在没测到的存量元数据。如果 cloud 或客户项目有视图写了 席位意见: 建议批准。第一轮契约复核判 FAIL:提示语里的版本号、四处组件描述仍在教已退役写法、液性账本里的 pin 引用过期。补丁轮已全部修正。第二轮复核 PASS,48 个 CI 检查全部完成,没有失败。技能文本只删不增,没有教任何已被拒绝的写法。还有一个不阻塞的缺口留作后续:技能包里还没有任何一处教页面元素 你要做的: 在本 PR 上点 Approve(请审已发给 Generated by Claude Code |
Fixes #23082
Clause-②: no (narrowing)
Ruling
6134088274(batch #331 item 5, letter C): the view-levelapidata source retires under ADR-0049 enforce-or-remove. A view binds its object or static rows; a metadata-declared API call is the page element'sdataSourcebinding (the #23016 rule, PR #23079), same-origin and credential-free. Executed per thespec-property-retirementplaybook as a VALUE retirement (the retired bare-stringsortclause's route):datasurvives one arm lighter, so there is noretiredKey()tombstone and noRETIRED_KEYS_BY_MAJORrow — the prescription ridesViewDataSchema's own discriminated-unionerrormap, keyed on the input'sprovider === 'api', so every other unknown provider keeps zod's default report (which lists the three live arms).What changed
packages/spec/src/ui/view.zod.ts— theprovider: 'api'arm ofViewDataSchema(itsread/writeHttpRequestSchemablocks and the arm's own near-miss guidance) is removed; the union carriesVIEW_DATA_API_PROVIDER_RETIREDas itserrormap. Two stale prose sites in the same file no longer teach the arm (the ganttobjectFielddescribe, the formdatadocblock).HttpRequestSchema/HttpMethodSubsetSchemaand theiruire-exports are untouched; the page-elementapibinding (ElementApiDataSourceSchema,ui/page.zod.ts) is untouched.view-data-api-provider-retired(migrations/entries/semantic/18.view-data-api-provider-retired.ts) and itsSTEP18_RATIONALEfragment (order 95). No D2 conversion, deliberately: the replacement lives on a different metadata type (a page element), and the only mechanical edit a conversion could make — deleting the view'sdataso the view falls back to querying its bound object — would silently change what the view shows. An authored source or a stored row still carrying the arm is refused at parse with the prescription (therest-api-endpoint-handler-status-retired/kernel/Manifest:loadingno-D2 precedents).packages/spec/liveness/view.json:list.dataandform.datastaylive(their surviving arms are read) and carry the arm's retirement record;list.datagainsverifiedAt/evidenceScope: cross-repowith objectui read points cited at7578323a544e. A renderer reader existed in objectui, measured at7578323a544e(.objectui-shaonmainis1fb1ced36243; the next cross-repo re-measure re-readsListView.tsx/ObjectGantt.tsxthere;ListView.tsxrouted anapiblock toApiDataSource,ObjectGantt.tsxbuilt one from the block'sread/write) and is now unreachable from authored metadata. The ledger has no per-arm row (the walk never descends a union arm), so the record sits on the key's row; the README's per-type counts do not move.packages/spec/variant-docs.json: the union key is nowprovider:object|schema|value.src/ui/view-data-api-provider-retirement.test.ts— the refusal atprovider/data.provider/list.data.providerwith its prescription, the three surviving arms value-for-value and still closed, zod's default report for any other unknown provider, the D3 registration and the absence of any key row, and a tree-scoped absence scan over the authored spelling (TS / JSON / YAML dialects; the page element'sdataSource: { provider: 'api' … }deliberately does not match). It joins the specrepovitest project and is the second witness on the spec: the rest of the incident-response, training and change-management families — every remaining key and all fifteen defs — has zero readers; whole-def enforce-or-remove is the open question left after #14477 #15513 absence-walk rows inscripts/cross-package-test-inputs.mjs. The four fixtures that pinned the arm were re-judged: two accept pins replaced by one refusal control (view.test.ts), the kanban fixture moved to thevaluearm (its point is a non-object source), the batch-18 strictness row for the arm removed, thecomponent-props-unknown-membersledger loses itsHTTP_REQUESTlines (nodatamember reaches a request block any more) and now refuses their return, and the two@objectstack/lintfixtures that used the arm to mean "a non-objectprovider" use thevaluearm.content/docs/ui/views.mdxloses the view-level example and points at Element data sources;skills/objectstack-ui/rules/list-views.mdthe same (readings below); the generated reference pages regenerate (gen:docs), the strictness counts shard regenerates (ui/view.zod.tsstrict sites 60 → 59)..changeset/23082-view-data-api-provider-retired.md:@objectstack/specminor, BREAKING, FROM → TO, one-line fix, the prescription verbatim,adr-0087: registered view-data-api-provider-retired.Measurements the ruling asked for
provider: 'api', outside documentation — each repo with a lit control in the same run:bcebd8409(this branch's base): 0 outsidepackages/spec/src/**(its own tests),CHANGELOG.md, generated reference pages, the two hand-written docs pages and the skill rule file; controlprovider: 'object'150 files. The onlycase 'api':reader in a runtime package (service-automationengine.ts) switches on a flow trigger kind, not onViewData.0f84c9c: 0; controlprovider: 'object'in 5 view files (src/*/views/*.view.ts).origin/mainf228d710: 0 authored producers.apps/console/src/services/approvalRequestsDataSource.tsconstructsnew ApiDataSource({ read: { url, method, params? }, fetch })in code — anApiDataSourceConfig, never aViewData; the phraseprovider: 'api'there is its docblock. Not a fork. Note for the objectui follow-up: its "deleteApiDataSourceand itsrelated-count-storeuse" step must keep or re-home the approvals route (three construction sites in that file). The 29 non-testprovider: 'api'/=== 'api'sites are readers (ListView, ObjectGantt,resolveDataSource,ViewDataProvider,useViewData,createAuthenticatedFetch), the objectui follow-up's population.packages/typesre-exportstype ViewData/type HttpRequestfrom the spec and declares noprovider: 'api'view type of its own;ViewDataProvider.tscarries an in-codeViewDataConfigunion with anapimember that does not derive from the spec. Control:provider: 'object'169 files.writeleg: no producer anywhere above (the fork clause's second trigger).HttpRequestSchemareaders (packages/**, excluding dist):ui/view.zod.ts(the removed arm, and theuire-export at line 108 — kept),shared/http.test.ts,ui/view.test.ts(single-source and backward-compat pins — kept),scripts/schema-index.test.ts(a fixture),scripts/build-docs.ts(a comment),ui/component-props-unknown-members.pin.test.ts(theHTTP_REQUESTlines — removed here), plus the generated shards (api-surface,authorable-surface,export-origins,declaration-map,json-schema.manifestforshared/HttpRequestandui/HttpRequest;contracts.jsonnames the unrelatedIHttpRequest). After this change no schema in the package composesHttpRequestSchema: its remaining readers are the two public re-exports and tests. Left in place per the ruling ("touches only theViewDataSchemabranch"); the orphan — and the now-stale describes onHttpMethod/HttpMethodSubsetSchemathat still say "what view data sources may request" — is recorded in the acceptance notes for a follow-up, not acted on here.scripts/build-console.shinjects this tree's spec only through the console SPA's Vite hook (OBJECTSTACK_SPEC_DIST,apps/console/vite.config.ts); objectui'stsc-building packages (types,core,react,app-shell) type-check against the published spec in objectui's own lockfile (^17.x), so the arm's removal cannot red that gate on a type, and no objectui file at the pin parses authoredprovider: 'api'metadata at build time.api-surface/,authorable-surface/(+.base.json),export-origins/,declaration-map/,json-schema.manifest/all green and unchanged (check:generatedon the built tree). What did move:content/docs/references/**(thedatatype column; the gantt's nesteddata[provider='api']section), the strictness counts shard, and (prose only)references/system/migration.mdx.skills/**readings (Tier H; net budget ≤ 0)ceil(bytes/4)) before → afterskills/objectstack-ui/rules/list-views.mdskills/*/SKILL.md(sum)skills/**/*.md(sum)The replacement pointer ("A view never calls an API: an API read is a page element's
dataSourcebinding") costs less than the example it replaces.check:skills-token-ratchetgreen.Verification
Head
be64fe664(=41045ab6f+ a merge oforigin/main287fd6e5dthroughscripts/pm/os-regen-merge.sh+ the hand-off commit regeneratingcomponent.mdx). Every exit code below was captured before any pipe; builds and tests ran throughscripts/pm/os-verify-lock.shand are quoted from itsVERDICT command-exitlines.pnpm --filter '@objectstack/lint^...' build— the diff touchespackages/spec(built,command-exit 0, three times on this head's tree) andpackages/lint(tests only; its closure spec + formula + sdui-parser built, thenturbo run build --filter=@objectstack/lint --filter=@objectstack/objectql,command-exit 0).pnpm --filter @objectstack/spec typecheck(gen:migration-registry,tsc --noEmit,check:scripts-typecheck,check:test-typecheck: OK, 52 files / 246 errors / 135 pinned signatures held — the retirement pin compiles clean) ·pnpm --filter @objectstack/spec test(thelocalproject): 660 test files passed ·pnpm --filter @objectstack/spec test:repo: 58 files / 1007 tests passed (the retirement pin's refusal, controls, D3 registration and the tree-scoped absence walk are in this project) ·pnpm --filter @objectstack/lint typecheck: OK ·pnpm --filter @objectstack/lint test: 138 files / 6649 passed, 5 skipped. Downstream importers ofViewData/ViewDataSchemaoutside spec: none in anysrc/(git grep; the two hits are release-owned CHANGELOGs), so no consumer package owes a typecheck for the narrowed type; the full closure is CI'sTypeScript Type Check.node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack→ 135 commands (the PM's lead list of 100 plus 35 the tree adds; none dropped), every one run onbe64fe664with its exit recorded, then--ranreconciled with every exit code recorded (COMMAND :: exit Nper line):Run reconciliation — 135 derived, 132 run, 3 NOT-MEASURED, 0 UNRUN(the 3 derived from recorded exit 3s), reconcile exit 0. 131 exit 0. The rest, each read at its own log, none a finding against this diff:pnpm check:platform-checklist— exit 1, inherited: 8 ABSENT SYMBOL / anchor-floor problems indocs/qa/platform-checklist/areas/{access-security,attachments-storage,search}.jsoncitingpackages/metadata-protocol/src/protocol.ts#anonymousFormIntakeOrgScopeRefusal,#anonymousFormIntakeReopenRefusal,#envWideRawViewRows,#countableandservice-storage/.../attachment-access-hooks.ts#canEdit. All four protocol symbols are absent onorigin/main(287fd6e5d) and on this branch's base (bcebd8409) alike; this diff touches none of those files. A main-red for its lane (e5f9f0160/c8a9783ecare the main commits that movedprotocol.tssince the base); reported, not repaired here.pnpm --filter @objectstack/spec run check:skill-examples— exit 3, PREREQUISITE NOT MET: its client-SDK surface reads@objectstack/client-react's built output, which needs thecoreclosure built; the shared verify lock was held by other seats' builds for two full queue budgets (holders named in the logs), so it is NOT MEASURED here. Narrowing stated, not assumed: the gate type-checks onlyos:check-marked blocks, and neither edited block is marked (skills/objectstack-ui/rules/list-views.mdmarkers at 17/166/221, the Data Source block at 38–50 is unmarked;content/docs/ui/views.mdxmarkers at 13/168/426/472, the block at 295 is unmarked;view.zod.tscarries no marker), so its verdict is invariant under this diff; CI runs it.pnpm check:type-check-debt— exit 3, NOT MEASURED: it builds twelve packages itself and@objectstack/core#buildcollided with a concurrent build of mine under the lock (the batch's own log says so); spec's and lint'stsc --noEmitran green directly (②), so their rows cannot have moved; CI re-measures.pnpm check:dual-build-cjs-loads— exit 3, NOT MEASURED: it loads every package's built output and 53 of 68 workspace packages (adapters, apps) are unbuilt in this worktree; a whole-workspace build is CI's run.@objectstack/lint/@objectstack/objectqlwere not yet built, and were re-run green (exit 0) on this head once they were:check:doc-formula-expressions,check:doc-security-posture,check:docs-transcript-drift,check:lean-entry-closure.pnpm --filter @objectstack/spec check:generatedon this head: all 14 up to date (check:docs,check:strictness-ledger,check:liveness,check:test-typecheck,check:authorable-surface,check:api-surface,check:export-origins,check:declaration-map… all ✓). The 14 pure source audits it does not run were run as one group on the built tree: all ✓ exceptcheck:skill-examples(above).pnpm lintand the farm) are CI's; this PR adds no lint-relevant surface.Acceptance notes
HttpRequestSchema/HttpMethodSubsetSchemaorphaned (class b candidate,carrier:the spec seat's follow-up or the objectui follow-up card): zero schema readers in@objectstack/specafter this PR; both still exported from./sharedand./ui, and their describes still speak of "view data sources". objectui'spackages/typesimportsHttpRequestSchemafrom the spec in a test and re-exportstype HttpRequest, so a def retirement is cross-repo and belongs with the objectui follow-up (the cross-repo unlock rule). Not touched here per the ruling.ApiDataSource,resolveDataSource's'api'arm,ViewDataProvider.resolveApi,useViewData'sprovider === 'api'branches,createAuthenticatedFetch'sprovider: 'api'lane, the gantt's adapter arm,content/docs/plugins/plugin-gantt.mdx(teaches a ganttdata: { provider: 'api' }),plugin-calendar.mdx/plugin-map.mdx(mention it as not honoured), andpackages/core/src/adapters/README.md. The approvals route constructsApiDataSourcedirectly and must be kept or re-homed.sdui.manifest.json(repo root; generated from objectui's built tree at the pin bygen-sdui-manifest-node.mjs) still describes the gantt'sdataas accepting{ provider: 'api', read }; it regenerates on the next pin bump, not here.sys_metadataview rows carrying the arm (none measured; cloud unmeasured) are refused at rehydration with the prescription — loud by design, the D3 entry says what to do.维护者速读(草稿)
改了什么: 视图(列表/表单)的
data数据源不再接受provider: 'api'(自带read/write请求块、任意url与headers的那一种)。视图只绑定对象(object)或静态行(value);元数据里声明的 API 调用只剩一条路:页面元素的dataSource绑定(同源、不带凭据、用控制台登录态请求)。写了旧写法的视图在校验、发布、保存时被拒绝,错误信息里直接写明改法。对外技能文本与文档同步改成指向页面元素绑定;spec 发一个 minor 版本并带 BREAKING 说明与迁移对照表。为什么改: 您在 #23082 批了 C。旧的视图级 API 源可以把密钥写进
headers、把请求指向任意域名,这些会随视图一起存储、下发给每个读取该视图的客户端、并由控制台照原样发出;而页面元素那条路已经按 #23016 的规则锁死。同一件事两套规则,按裁决保留受治理的那一套、撤掉另一套。实测三个仓(objectstack、objectui、hotcrm)都没有视图在用它;cloud 未测,您的「同意」已覆盖。风险与代价(含回滚): 风险在未测的存量元数据:若 cloud 或某个客户项目有视图写了
provider: 'api',升级后该视图加载时会被拒绝并给出改法(不会悄悄换成别的数据),需要作者把 API 读取改到页面元素上。没有自动迁移(D2),因为机械删掉data会让视图静默改读对象。回滚:撤销本 PR 即恢复旧分支,无数据迁移需要回退。objectui 侧的删除(ApiDataSource等)是另一张卡,等 spec 发版后再做,本 PR 不动 objectui。席位意见:
你要做的: 本 PR 动了
skills/**(受治理,Tier H),需要您的批准才能合入:请审阅上面的中文说明与skills/objectstack-ui/rules/list-views.md的改动(净减 2 行),同意则在 PR 上点 Approve,由席位排队合入。Generated by Claude Code