Repository navigation
[Decision] May an app owner put their own title, description, version, contact and license on the API document ObjectStack serves (/openapi.json)? #20359
Description
Activity
- addedarea:apiThe API a customer can call, and integrations — REST, connectors, webhooks, jobsThe API a customer can call, and integrations — REST, connectors, webhooks, jobs
on Sep 28, 2026 objectstack-fleet commented
on Sep 28, 2026 ContributorAuthorMore actionsRuling: batch #231 item 1 · letter B · maintainer 「同意 B」 2026-09-28T02:58Z
Director seat (objectstack#12708, summon #30 续 2,
session_01AsCNgFBs8HCjwhyHQsFbx3). Provenance: maintainer, live PM chat with the director seat, 2026-09-28, replying to batch #231 (this card, item 1, recommendation B, presented with the full four-axis body); verbatim 「同意 B」.Ruled: B. The eight identity members of
api.documentation—title,description,termsOfService,contact.name/contact.url/contact.email,license.name/license.url— are ENFORCED: an authored value overlays the servedinfoon both doors (/api/v1/openapi.jsonand the environment-scoped door); nothing authored ⇒ the servedinfois byte-identical to the artifact.documentation.versionis RETIRED: the servedinfo.versionstaysSPEC_VERSION, exactly as #11646 (5405070350) ruled, and an authoredversionis refused at publish time by aretiredKey()tombstone whose message names the protocol version as the one source and points an app's own release number todescription. A (all nine overlay, version included) and C (retire all nine) are not taken.Readings that decided it:
- Long-term: the cover's version is a fact of the protocol, owned by
packages/spec; the cover's name, contact, terms and licence are the publisher's identity. One truth per field. [finding] the served openapi.json overrides theinfo.versionthatpackages/specowns, so the published artifact says17.2.0and the served document saysv1#11646's motive stands — an integrator must be able to read which protocol version they are talking to — and [Decision] Route declared≠enforced work by the SEAM, not the layer — aSeam:line on filing, vertical dispatch by default in the spec lane, automatic parent + sub-issues for spec↔objectui seams, Journey as a filter, bulk retirement per spec family, Console Pin Gate back to required (the maintainer's 「同意」 on the five-line batch, 2026-09-18) #18900's criterion (5727134555) is applied to the identity keys, where the API-management mainstream lets the owner sign the cover. A would makeinfo.versiona contested field again, in a third meaning; C would tell an app owner the document they publish is always signed ObjectStack. - Mainstream (from memory, not re-read): Azure API Management, Apigee, ServiceNow Scripted REST and Power Platform custom connectors let the API owner set the whole cover; the metadata-generated peers (PostgREST under Supabase, Directus) keep the cover engine-owned, engine-versioned. The split supports neither wholesale rule; B follows the field's owner.
- Real use: zero authors of
api.documentationin the three repos; the change is small in every direction, so cost did not decide. - AI-safety: the current state (nine keys parsed, none honoured) is the worst one. B leaves no silent key: eight are honoured, one refuses loudly. The same block already carries a
retiredKey()tombstone (enabled, spec(api): retireapi.responseFormatandapi.documentation.enabled(4 keys); the envelope is fixed andenableOpenApialready decides the document #20295), so a mixed block is the repo's existing pattern, not a new one.
Execution parameters (ruled in the same stroke; no further decision card):
- rest: the served OpenAPI document's
infoblock comes fromapi.documentation(9 keys) #20294 is re-dispatched on the dev's kept worktree and resume plan as the seat's own B: eight keys ENFORCE +documentation.versionRETIRE. Lanedomain:spec,priority:p3unchanged; apackages/restsub-issue only if triage's anchoring rule requires one. Clause-② yes (behaviour change on a public document;titlebecomes.optional(),versiontombstoned) ⇒@objectstack/specminor,@objectstack/restper its bump policy;CONTRACT_REVIEW_TIER. - Semantics:
titlebecomes.optional()(the materialized default'ObjectStack API'was never served; the artifact's'ObjectStack REST API'is the default).contactandlicensereplace the bundled block whole, never member by member (an MIT name at the Apache URL would be a false statement in a machine-read contract). The overlay lives inregisterOpenApiEndpointsand applies on both doors. The API route version (api.version) and the runtime version never enterinfo.version. - ADR-0087 D3 entry for
api.documentation.version(familyrest-api-documentation); the liveness-ledger rows of the eight keys flip to enforced with the pin as evidence, theversionrow retires with the key. - Pins: (1) all eight keys authored ⇒ the served
infoon both doors carries them andinfo.versionis stillSPEC_VERSION; (2) nothing authored,documentation: {}, and one key alone ⇒infoequals the artifact except the authored member — the [finding] the served openapi.json overrides theinfo.versionthatpackages/specowns, so the published artifact says17.2.0and the served document saysv1#11646 pin (rest-openapi-route.test.ts) stays as the control; (3) an authoreddocumentation.versionis refused at parse with the tombstone message; (4) an authoredlicensewithouturlserves nourl. - Step one of [finding] the served openapi.json overrides the
info.versionthatpackages/specowns, so the published artifact says17.2.0and the served document saysv1#11646 (zero readers of the servedinfo.versionby value) was measured then and is not reopened.
State:
needs-user-decisionremoved here; nopm:*state on this card — it is the ruling carrier, not the work card. #20294:pm:blocked→pm:queue, itsBlocked-by: #20359resolved by this comment (note there in the same stroke). The PR that lands #20294 closes this card too.- Long-term: the cover's version is a fact of the protocol, owned by
objectstack-fleet commented
on Sep 28, 2026 ContributorAuthorMore actionsClaim: PM loop round 3 (closure claim: this card is closed by #20294's landing PR, as its ruling orders)
Session:session_01ARcDurZ5j34RdqsGgc4jgH
Account:os-warren(the seat's linked user asGET /useranswers it; the card's assignee)
Branch:claude/issue-20294-openapi-info-overlay
Worktree:objectstack-issue-20294
Domain:domain:spec
Seat:domain:spec#4(seat post #18917)
File surface: none of its own. This card is the ruling carrier, not a work card. The diff that executes its ruling B is #20294's, under claim5876330236on that card, as PR #20512. The ruling says: 「The PR that lands #20294 closes this card too.」 So PR #20512 carriesFixes #20359, and this claim records that the closer owns the card, which is what the closing-target claim guard reads.
Container & model: as #20294's claim5876330236. An at-tier contract review of PR #20512 is owed before enqueue.
Clause-②: yes
Thread-read: 5862477514
Serial constraints cleared: as #20294's claim5876330236.Ruling carried:
5862477514· batch #231 item 1 · letter B · maintainer 「同意 B」.domain:specseat 4 · #18917 ·session_01ARcDurZ5j34RdqsGgc4jgH- added a commit that references this issue
on Sep 29, 2026
Ruled: 5862477514 · letter B · 2026-09-28T02:59Z
Decision card for #20294, which is blocked on it. It was opened at the maintainer's request in chat (「看不懂,开决裁卡」, 2026-09-28) because the analysis on #20294 was hard to read. Filed by the
domain:specexecution seat 1 (session_01Rjy9MeetSfq34PKn81CRiN, seat post #6017). ⛔ Not a claim.维护者速读
这是什么。 ObjectStack 的 REST 服务会发布一份「API 说明书」
/openapi.json,给开发者和工具看这个系统有哪些接口。说明书最上面有一个「封面」info,写着:现在的情况。 配置里其实有 9 个设置项可以写这个封面(
api.documentation.title、description、version、contact、license等),但写了也没用。封面永远是 ObjectStack 自己的:ObjectStack REST API17.x实测:9 个设置全写上,0 个生效。三个仓里目前没有任何人写这些设置。
为什么要你拍板。 你之前的两次裁决在这里撞上了:
info.versionthatpackages/specowns, so the published artifact says17.2.0and the served document saysv1#11646(你「全部同意」):封面整块归平台 spec 所有,版本号固定显示平台 spec 版本;「为没人要的需求加配置键」那个选项被否掉了。Seam:line on filing, vertical dispatch by default in the spec lane, automatic parent + sub-issues for spec↔objectui seams, Journey as a filter, bulk retirement per spec family, Console Pin Gate back to required (the maintainer's 「同意」 on the five-line batch, 2026-09-18) #18900(你的判据):每个功能看主流平台有没有这个能力,有就把它做实。分诊按这条判了「做实」(ENFORCE)。Azure API Management、Apigee、ServiceNow 都让 API 所有者给自己的 API 设封面。两条放在一起,就是:要不要让在 ObjectStack 上做应用的客户,给自己发布的 API 说明书写上自己的标题、简介、联系人、许可证和版本?
三个选项
席位意见:A。 客户给自己的 API 起名字、留联系人是主流平台都有的基本能力,而且不写就完全不变,零风险。8 月那次否掉的是「给路由版本号占用封面」,A 不碰那个。如果你认为封面上的版本必须永远等于平台版本,就选 B。如果你觉得这个能力现在不需要,就选 C,也最省事。
你要做的(一个动作): 回一个字母,A / B / C。
Governing text (verbatim, retrieved by the seat)
info.versionthatpackages/specowns, so the published artifact says17.2.0and the served document saysv1#11646, maintainer ruling5405070350: 「theinfoblock returns to being whollypackages/spec-owned」 … 「A (keep the two-meanings split) and C (a config key for a demand nobody expressed) are dead.」Seam:line on filing, vertical dispatch by default in the spec lane, automatic parent + sub-issues for spec↔objectui seams, Journey as a filter, bulk retirement per spec family, Console Pin Gate back to required (the maintainer's 「同意」 on the five-line batch, 2026-09-18) #18900, maintainer criterion5727134555: 「每族该问的是:主流平台有没有这个能力 —— 有 ⇒ 补消费端(一次做对)」.infoblock comes fromapi.documentation(9 keys) #20294, triage grade5859594397: 「Verdict: ENFORCE, by the maintainer's criterion」.Evidence
infoblock comes fromapi.documentation(9 keys) #20294 (theos-dev-reportcomment): both serving doors ignore all nine authored keys, and the unset cases equal the artifact.contact/license), are on rest: the served OpenAPI document'sinfoblock comes fromapi.documentation(9 keys) #20294, on theRelease:comment of 2026-09-28.Execution after the answer
infoblock comes fromapi.documentation(9 keys) #20294 on the dev's ready resume plan. Its worktree is kept.infoblock comes fromapi.documentation(9 keys) #20294 as eight keys ENFORCE plusdocumentation.versionRETIRE.infoblock comes fromapi.documentation(9 keys) #20294 is re-graded RETIRE for all nine keys.