Skip to content

docs(protocol): correct the X-API-Key example to the real osk_ prefix - #8733

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-8715-apikey-reference-truth
Aug 14, 2026
Merged

docs(protocol): correct the X-API-Key example to the real osk_ prefix#8733
os-zhuang merged 1 commit into
mainfrom
claude/issue-8715-apikey-reference-truth

Conversation

@os-zhuang

@os-zhuangos-zhuang commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Part of #8715

Carries only §2 of the card. §1 is escalated, not implemented — it is not the
docs correction the card assumed, and the reason is measured below. Deliberately Part of
rather than a closing keyword: this PR does not finish #8715, whose main half sits in the
decision box. (Wording note: an earlier draft of this line used a bare closing keyword in
a negated sentence — GitHub's parser ignores the negation, so Part-of PR must not also close its card correctly refused it. Reworded, not re-argued.)

What changed (§2 — the osk_ prefix)

content/docs/protocol/kernel/http-protocol.mdx showed a Stripe-shaped
sk_live_abc123... value in the X-API-Key example. Corrected to osk_abc123..., and
since the surrounding prose was silent on the prefix, added a short paragraph saying why
it is load-bearing.

Traceable to source: API_KEY_PREFIX = 'osk_' and extractApiKey in
packages/core/src/security/api-key.ts, whose own comment states the mechanism — Bearer
is accepted only for prefixed api-keys, never for session tokens, because a better-auth
session token never starts with osk_.

Swept content/docs/** for sk_live / sk_test / pk_live / os_pk_ as #8717 asks.
Two other hits are correct as written and were left alone: automation/connectors.mdx
(an OUTBOUND bearer token for a third-party API) and protocol/kernel/config-resolution.mdx
(OS_CRM_API_KEY, a third-party CRM credential). Neither is an ObjectStack inbound key.

#8717 is the split-out card for this same example and remains open — the PM decides
whether it is served by this PR or should carry its own.

Why §1 is not in this PR

The card asks for the ApiKey reference table to be rebuilt from the real sys_api_key
column set. Three findings say that cannot be a docs change:

  1. The page is generated.content/docs/references/identity/identity.mdx carries the
    AUTO-GENERATED — DO NOT EDIT banner and names its source,
    packages/spec/src/identity/identity.zod.ts. Hand-editing it is barred and would be
    undone by the next gen:docs. The table is a faithful rendering of ApiKeySchema,
    which really does declare start, lastRefetchAt, enabled, rateLimitEnabled,
    rateLimitTimeWindow, rateLimitMax, remaining, permissions, metadata,
    organizationId. The doc is not the defect; the schema is.

  2. Fixing the schema is an ADR-0049 retirement, not a JSDoc edit. All 19
    identity/ApiKey:* keys are in packages/spec/authorable-surface.base.json. Removing
    ten of them needs the ADR-0087 conversion plus the exact-key RETIRED_KEYS_BY_MAJOR
    entry, the liveness ledger, regenerated baselines, forms, i18n, pin tests and a
    major changeset for @objectstack/spec. That is the opposite of this card's stated
    skip-changeset, docs-only disposition.

  3. The card's prescribed replacement column set is ahead of main. It lists
    active_organization_id, which sys_api_key does not have on main
    packages/platform-objects/src/identity/sys-api-key.object.ts declares no such field,
    and resolveApiKeyPrincipal still reads row.organization_id ?? row.organizationId.
    The column arrives with PR fix(identity): API keys are minted against the minter's active organization (#8287) #8709, still an open draft. Documenting it today would
    re-commit the same PD chore: version packages #10 sin the card was filed about.

The real column set on main, each traceable to sys-api-key.object.ts:
name, prefix, user_id, scopes, expires_at, last_used_at, revoked, key, id, created_at, updated_at — eleven, not the card's twelve.

There is also a disposition question the dev seat should not settle alone: ApiKeySchema
has zero consumers anywhere in the monorepo (only its own test, the export-surface
snapshots and this generated page), so "delete it and let the platform object be the one
declaration" is a live alternative to rebuilding it. Full analysis in the report on #8715.

Verification

Gate union run after the final commit, at f82c72acd, all PASS:

check:nul-bytes · check:doc-authoring · check:doc-anchors · check:docs-audit-scope
· check:role-word · check:adr-links · check:empty-changeset ·
check:changeset-gate-self-tests

Re-derived against the actual changed path with scripts/pm/dispatch-gates.mjs, which
surfaced check:role-word — a family the dispatch prompt did not name. The prompt also
named check:doc-formula-expressions, which exists as no script in the root
package.json. check:generated is not implicated: no generated artifact moved, because
the generated page is untouched.

check:doc-anchors failed on the first pass purely for a missing github-slugger — the
worktree had no pnpm install yet. It passes after installing.

Docs-only prose, releases nothing, so no changeset and the skip-changeset label;
check:empty-changeset passes on this diff in that shape.


Generated by Claude Code

The HTTP protocol page showed a Stripe-shaped `sk_live_abc123...` placeholder.
ObjectStack keys are `osk_`-prefixed (API_KEY_PREFIX, core/src/security/api-key.ts)
and the prefix is load-bearing: extractApiKey accepts an Authorization: Bearer token
only when it starts with osk_, which is what stops a session Bearer being read as an
API key. Also states why the prefix matters, since the surrounding prose was silent.
Part of #8715
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E5tUwGM3LQoqErTfkvRW7W
@vercel

vercelBot commented Aug 14, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
ProjectDeploymentActionsUpdated (UTC)
objectstackIgnoredIgnoredAug 14, 2026 4:41pm

Request Review

@os-zhuangos-zhuang added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Aug 14, 2026 — with Claude
@github-actionsgithub-actionsBot added the documentation Improvements or additions to documentation label Aug 14, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review August 14, 2026 16:44
@os-zhuang
os-zhuang enabled auto-merge August 14, 2026 16:44
@os-zhuang
os-zhuang added this pull request to the merge queueAug 14, 2026
Merged via the queue into main with commit 38ba5b7Aug 14, 2026
28 of 29 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-8715-apikey-reference-truth branch August 14, 2026 17:03
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/sskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@os-zhuang@claude