feat(spec): retire ApiKeySchema — sys_api_key has one declaration, the platform object (#8715, ADR-0049) - #8932
Conversation
…e platform object (#8715, ADR-0049) Maintainer ruling 2026-08-15 (disposition B: delete). ApiKeySchema documented better-auth's apiKey plugin schema — a plugin this platform does not load — so one table had two declarations and the published one was fiction (PD #10). Zero consumers outside its own unit test, re-measured at base 7901b2d. Route 3 retirement kit (#8586 / PR #8702, #8075 precedents): retired-def entry identity/ApiKey + D3 semantic entry identity-api-key-schema-retired under protocol 18; manifest and authorable-surface/authorable-defaults lines removed via the sanctioned deliberate-deletion path the #2978/#4725 gates prescribe; pin tests on both sides of the package boundary; developer-portal prose corrected (the marketplace-key plan is ruled NOT live). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fgvh1iEJfxetei7aNVdtJt
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
📓 Docs Drift CheckThis PR changes 1 package(s): 106 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
⛔ 7 release-owned page(s) also reference the affected code. These are read-only:
|
…o the changeset (#8715) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fgvh1iEJfxetei7aNVdtJt
…ption (#8715) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fgvh1iEJfxetei7aNVdtJt
…key-schema-retirement
…try sibling (#8793) os-regen relay for #8932's retired-def:18 landing: merge committed first, then gen:migration-registry / api-surface / export-origins / spec-changes / upgrade-guide / openapi re-run on the merged tree. Both sides asserted surviving: this branch's filter-preset-ordering-comparand-refused entry AND #8932's identity-api-key-schema-retired entry + its identity.zod.ts deletion. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fgvh1iEJfxetei7aNVdtJt
…relay) gen:migration-registry (96 semantic — both semantic:18 entries stack: engine-dotted-filter-refused + filter-preset-ordering-comparand-refused), spec build, gen:export-origins, gen:api-surface, gen:spec-changes, gen:upgrade-guide, gen:openapi restore. check:generated: all 13 artifacts up to date. Survival asserted on the merged tree: #8935's entry and its implementation body (isDateRangePresetName), #8932's ApiKeySchema still absent, this branch's entry and classifyDottedFilterHead at all three consuming files. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fgvh1iEJfxetei7aNVdtJt
…8939 relay) gen:migration-registry, spec build, gen:export-origins, gen:api-surface, gen:spec-changes, gen:upgrade-guide, gen:openapi restore. check:generated: all 13 artifacts up to date. Survival asserted on the merged tree, one hit each in the regenerated registry: engine-dotted-filter-refused (this branch), driver-sql-unresolvable-where-column-refused (#8927), filter-preset-ordering-comparand-refused (#8935), identity-api-key-schema-retired (#8932) - plus implementation bodies: sql-driver.ts INVALID_FIELD refusal + envelope test (#8927), isDateRangePresetName (#8935), ApiKeySchema still absent (#8932), classifyDottedFilterHead at both doors (this branch). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fgvh1iEJfxetei7aNVdtJt
…filter comparand at publish time (objectstack-ai#8793) (objectstack-ai#8935) * feat(spec,lint): refuse bare date-range preset names in ordering filter comparands (objectstack-ai#8793) The C half of objectstack-ai#8690 (maintainer ruling 5299879288): the declared dashboard date-range preset vocabulary (last_7_days / last_30_days / last_90_days and their ten calendar siblings) is refused at publish time when authored as a bare ordering comparand, where no layer of the platform can interpret it. - data/date-range-presets.ts: vocabulary re-homed from ui/dashboard.zod.ts (single source objectstack-ai#4614 kept; ui re-exports) + macro-window prescriptions - data/filter.zod.ts: FilterConditionSchema refuses presets under $gt/$gte/$lt/$lte and $between endpoints, ordering positions only - lint: new filter-preset-comparand rule, all three authored filter shapes, CLI + runtime-publish surfaces Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fgvh1iEJfxetei7aNVdtJt * feat(spec): ADR-0087 entry, changeset, runtime-gate pin updates (objectstack-ai#8793) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fgvh1iEJfxetei7aNVdtJt * fix(lint): give the new rule test its .js import extension — clears the +2 TEST_DEBT drift (objectstack-ai#8793) Same class as objectstack-ai#8808's TS2550: invisible to 'pnpm --filter @objectstack/lint typecheck' because tsconfig excludes **/*.test.ts; only the TEST_DEBT re-measure compiles the file. The two TS7006s were downstream of the one unresolved import (TS2835). Ledger not raised; re-measured 19 vs recorded 20 on the fully built workspace closure. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fgvh1iEJfxetei7aNVdtJt * chore(spec): regenerate os-regen artifacts after merging main's registry sibling (objectstack-ai#8793) os-regen relay for objectstack-ai#8932's retired-def:18 landing: merge committed first, then gen:migration-registry / api-surface / export-origins / spec-changes / upgrade-guide / openapi re-run on the merged tree. Both sides asserted surviving: this branch's filter-preset-ordering-comparand-refused entry AND objectstack-ai#8932's identity-api-key-schema-retired entry + its identity.zod.ts deletion. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fgvh1iEJfxetei7aNVdtJt --------- Co-authored-by: Claude <noreply@anthropic.com>
…ad is a relation, a formula, or a plain scalar — at both doors (objectstack-ai#8371) (objectstack-ai#8936) * feat(objectql,metadata-protocol): refuse a dotted filter key whose head is a relation, a formula, or a plain scalar (objectstack-ai#8371) Implements the objectstack-ai#8371 maintainer ruling (Option 2, delegated adjudication): a dotted filter key whose head segment is a relation, a virtual formula, or a plain scalar is refused at BOTH doors — the REST ingress (assertFilterFieldsExist) and the engine's filter seam (assertFilterIsMaterializable) — with the existing INVALID_FIELD/400 identity and the SORT objectstack-ai#4256 denormalise remedy sentence. The structured/JSON head (address.city) stays deliberately unjudged, per the ruling's carve-out: it is live on two of three backends. Both doors judge the head by one shared classification (classifyDottedFilterHead, new @objectstack/spec/data export), the same one-source move objectstack-ai#8296 made with isVirtualSearchField. Precedence mirrors the sort axis: unknown > dotted > unmaterializable. ADR-0087: semantic entry engine-dotted-filter-refused (protocol major 18). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fgvh1iEJfxetei7aNVdtJt * test(objectql): re-judge the objectstack-ai#7534 dotted pass-through GUARD under the objectstack-ai#8371 verdict The GUARD pinned exactly the limb the ruling deletes ('a dotted path on a REAL head passes through — nothing may refuse it after'). owner_id is a registry-injected lookup, so 'owner_id.name' is now refused with the whole key named; the surviving guarded properties (nested-relation OBJECT form not descended into, unknown-head precedence) stay pinned by their own tests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fgvh1iEJfxetei7aNVdtJt * chore(spec): record the four objectstack-ai#8371 exports in the api-surface snapshot check:api-surface red at fd8f1eb: DottedFilterHeadClass, DottedFilterHeadMeta, SCALAR_FILTER_HEAD_TYPES and classifyDottedFilterHead are intentional additions (the shared dotted-head classification both filter doors read); gen:api-surface run on a freshly built spec. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fgvh1iEJfxetei7aNVdtJt * chore(spec): regenerate the os-regen chain on the merged tree (objectstack-ai#8935 relay) gen:migration-registry (96 semantic — both semantic:18 entries stack: engine-dotted-filter-refused + filter-preset-ordering-comparand-refused), spec build, gen:export-origins, gen:api-surface, gen:spec-changes, gen:upgrade-guide, gen:openapi restore. check:generated: all 13 artifacts up to date. Survival asserted on the merged tree: objectstack-ai#8935's entry and its implementation body (isDateRangePresetName), objectstack-ai#8932's ApiKeySchema still absent, this branch's entry and classifyDottedFilterHead at all three consuming files. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fgvh1iEJfxetei7aNVdtJt * merge origin/main (os-regen artifacts taken from main; regeneration follows) * chore(spec): regenerate the os-regen chain on the merged tree (objectstack-ai#8927/objectstack-ai#8939 relay) gen:migration-registry, spec build, gen:export-origins, gen:api-surface, gen:spec-changes, gen:upgrade-guide, gen:openapi restore. check:generated: all 13 artifacts up to date. Survival asserted on the merged tree, one hit each in the regenerated registry: engine-dotted-filter-refused (this branch), driver-sql-unresolvable-where-column-refused (objectstack-ai#8927), filter-preset-ordering-comparand-refused (objectstack-ai#8935), identity-api-key-schema-retired (objectstack-ai#8932) - plus implementation bodies: sql-driver.ts INVALID_FIELD refusal + envelope test (objectstack-ai#8927), isDateRangePresetName (objectstack-ai#8935), ApiKeySchema still absent (objectstack-ai#8932), classifyDottedFilterHead at both doors (this branch). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fgvh1iEJfxetei7aNVdtJt --------- Co-authored-by: Claude <noreply@anthropic.com>
Fixes #8715
§1 only, per the maintainer ruling of 2026-08-15 (「接受全部建议。」 item 1, comment 5299771349): disposition B — delete. §2 (the
sk_live_prefix) merged separately via PR #8733 and is untouched here.What this does
ApiKeySchema/ApiKey/ApiKeyParsedleave@objectstack/spec/identityentirely. The schema documented better-auth'sapiKeyplugin shape — a plugin this platform does not load:start/lastRefetchAt(no such columns),enabled(the real column isrevoked, opposite polarity), four per-key rate-limit keys (no such surface exists anywhere),permissions/metadata(no columns), camelCaseorganizationIdnext to the real snake_caseactive_organization_id. One table had two declarations and the published one was fiction (AGENTS.md PD #10).packages/platform-objects/src/identity/sys-api-key.object.tsis now the single declaration; the generated reference page'sApiKeysection disappears with the schema.Zero-consumer premise re-measured at base 7901b2d (three spec PRs merged since the 08-14 measurement): grep hits are only the schema's own file, its unit test, the export/api-surface snapshots, the generated docs pages, and the
developer-portal.zod.tsprose mention. Premise holds.The retirement kit (route 3 — no carrier key, no authored document, so no tombstone and no D2 conversion)
identity.zod.ts, the spec 双源清账 C4:Session / SessionSchema(./api ≠ ./identity)—— 2 条 #4641 Session-block pattern).identity/ApiKey(entries/retired-defs/18.identity__ApiKey.ts) + D3 semantic entryidentity-api-key-schema-retired(entries/semantic/18.identity-api-key-schema-retired.ts), concatenated bygen:migration-registry. The registry entries ARE the declaration (the ADR-0049:plugin-runtime.zod.ts剩余家族(DynamicLoadRequest / DynamicUnloadRequest / DynamicPluginResult / PluginSource / DynamicPluginOperation)四仓零 runtime consumer —— enforce-or-remove 悬置待裁 #4834 / ui/ 五个交互配置文件(22 个 z.object 站点)没有任何承载键:实测「无授权门」,按 ADR-0049 定去留 #4988 / ADR-0049 enforce-or-remove: ui/widget.zod.ts 全文件 + ui/i18n.zod.ts 五个形状实测无门(#4001 批 16 改判) #5055 / [sweep] ADR-0049 retire 5 declared-but-inert spec surfaces (#5295 #5703 #6239 #6247 #6414) #6486 / [security] Two more spec schemas permit inline credentials:ExternalDataSourceSchema.authentication(clientSecret/apiKey) andMessageQueueConfigSchema.sasl.password— census toward #7990's parked boundary-guard reopen trigger #8075 shape; post-cut major-18 placement per theadditionalTypesonMetadataPluginConfigis authorable, documented as THE way a plugin declares a metadata type, and has no reader — a plugin cannot declare a kind at all #8586 / PR feat(spec): retire the inert additionalTypes key from MetadataPluginConfig (#8586, ADR-0049) #8702 precedent).json-schema.manifest/identity.json−1 def andauthorable-surface/identity.json−19 keys, both via the sanctioned deliberate-deletion path — the gen:schema silently drops PageTabsProps since #2967 — references regen would delete real docs #2978 ratchet fired first and demanded theRETIRED_DEFS_BY_MAJORdeclaration, then per-key gate (a)'s case-3 waiver (whole def no longer emitted, adjudicated by the manifest gate) makes the shard-line deletion the documented procedure (build-schemas.tscomment at the check).authorable-defaults/identity.json−1 line regenerated bygen:schema.authorable-surface.base.jsondeliberately lags percheck:authorable-surface在--check模式下也会重写authorable-surface.base.json—— 一次纯核验会改工作区,且任何无关 PR 都能因此静默推进删除门的锚点 #5358 (re-anchoring is its own reviewed act; past retirements' keys are still in it).spec-changes.jsonanddocs/protocol-upgrade-guide.mdproject majors 10→17 only — a protocol-18 registration appears when 18 is cut, byte-identical to theadditionalTypesonMetadataPluginConfigis authorable, documented as THE way a plugin declares a metadata type, and has no reader — a plugin cannot declare a kind at all #8586 precedent's behavior. No liveness ledger change:packages/spec/liveness/covers metadata types only and has no identity ledger (the dispatch prompt'scheck:livenesshard-fail assumption did not reproduce; the gate passes untouched).packages/spec/src/identity/api-key-retirement.test.ts(zero holders for all three names on every public entry via export-origins; survivorsUser/Account/VerificationToken/Organization/Memberstand — the ruling accepts the sibling asymmetry; the fictional keys cannot quietly reappear in the module) andpackages/platform-objects/src/identity/sys-api-key-single-declaration.test.ts(the exact real column set includingrevoked-not-enabled; spec's runtime namespace lost the name — value export only, deliberately, since the two type names have no runtime footprint and are covered by the export-origins pin).cloud/developer-portal.zod.tsno longer points marketplace API keys atIdentity.ApiKeySchema(the marketplace-key plan is ruled NOT live); it now names thesys_api_keyobject andPOST /api/v1/keys. Bounded in-place fix in the same comment block, named here per contract: the adjacentIdentity.SessionSchemamention named a schema the identity module deliberately does not declare (spec 双源清账 C4:Session / SessionSchema(./api ≠ ./identity)—— 2 条 #4641) — same defect class, mechanical fix pinned by the spec 双源清账 C4:Session / SessionSchema(./api ≠ ./identity)—— 2 条 #4641 block, same file and gates; corrected to point atSessionfrom@objectstack/spec/api.@objectstack/specminorwith BREAKING framing and FROM → TO — the post-cut lockstep launch-window class, measured from the feat(spec): retire the inert additionalTypes key from MetadataPluginConfig (#8586, ADR-0049) #8702 precedent changeset.packages/spec/src/migrations/registry.tsis touched (HOT) — viagen:migration-registryfrom two new entry files; the marked regions are generated, never hand-edited. One hand edit outside the markers: the18: [ … ]region scaffolding forretired-def:18, which did not exist yet — this PR is the first retired-def entry of major 18, which is one of the two merge-queue conflict shapes the entries README documents (first-entry-of-a-new-major). If a sibling lands a retired-def:18 entry first, I am the second lander and the os-regen relay applies at landing.content/docs/references/identity/identity.mdx,cloud/developer-portal.mdx,index.mdx) andapi-surface//export-origins/identity shards regenerated, not hand-edited.data/filter.zod.ts+ contracts + lint) is disjoint at source level.Out of scope, recorded
docs/adr/0056-permission-model-landing-verification.mdnamesApiKey(scopes/permissions)in a historical verification table — ADRs are decision records, left untouched (theadditionalTypesonMetadataPluginConfigis authorable, documented as THE way a plugin declares a metadata type, and has no reader — a plugin cannot declare a kind at all #8586 precedent corrected live source comments, not ADRs).runtime/src/domains/keys.ts) and verify (core/src/security/api-key.ts) work byte-identically.Verification
Gate readings and the union run at the final head are posted in the report comment on #8715 (report lands at draft-PR time; CI convergence is the PM's read per the 2026-08-10 ruling).
Generated by Claude Code