Repository navigation
qa(authz-conformance), docs(api): record that POST /api/v1/keys mints only for a signed-in session - #27718
Conversation
… only for a signed-in session Adds the `keys-mint-session-required` row to the authz-conformance matrix beside `anonymous-deny-keys` (enforcement read from runtime/domains/keys.ts, note naming the 14-case pin), aligns `anonymous-deny-keys` to say a session-admitted caller reaches the mint, refreshes the docblock's covers census figures, and adds one sentence naming the rule to the API-key bullet in content/docs/api/index.mdx and under "Or mint one over REST" in content/docs/ai/connect-mcp.mdx. No runtime change. Claude-Session: https://claude.ai/code/session_01QSeKYmTYfaPbLQD4BJfomW Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckNothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs. What this run could not see
Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
|
domain:devx#2 · os-justin · session_01QSeKYmTYfaPbLQD4BJfomW 席位核对 — ACCEPT · domain:devx#2 · head
|
Fixes #27708
Clause-②: no
Metadata-protocol: none
维护者速读
keys-mint-session-required,记录「只有登录会话才能创建 API key」;两处文档各加一句说明这条规则。POST /api/v1/keys得到 403PERMISSION_DENIED),但矩阵和文档都没写,脚本作者只能从 403 才发现。packages/qa/dogfood/test/authz-conformance.matrix.ts新行的enforcement(对照runtime/domains/keys.ts第 146 行);content/docs/api/index.mdx的 API key 条目;content/docs/ai/connect-mcp.mdx的 "Or mint one over REST" 一句。pnpm --filter @objectstack/dogfood exec vitest run test/authz-conformance.test.ts test/authz-probe-blind-spot.test.ts,预期 2 个文件、70 个用例全绿。What changes
packages/qa/dogfood/test/authz-conformance.matrix.tskeys-mint-session-requiredbesideanonymous-deny-keys,state: 'enforced'. Itsenforcementis read frompackages/runtime/src/domains/keys.ts: the domain-wide positive checkcontext.admission?.credential === 'session'(L146), directly below the anonymous decision (L129) and ahead of the body read and the method check. Every other admission (an API key in any of its three header spellings, or no recorded admission) answers 403PERMISSION_DENIED. Thenotenames the pin fileruntime/domains/keys-mint-interactive-session.pin.test.ts(14 cases).coverskey. This is a predicate inside a domain thatanonymous-deny-keysalready classifies, so it adds no entry point fordiscover(). Acoverskey that no probe mints fails as STALE. This is the matrix's in-resolver convention, and the row'snotesays so.anonymous-deny-keys: "a signed-in caller reaches the mint exactly as before" now reads "a session-admitted caller ... (a caller admitted by an API key is refused by the next row,keys-mint-session-required)", so the two rows agree.enforcedrows" now reads "51 of 69 ... 45 of 62". See the Acceptance notes.content/docs/api/index.mdx(the API key bullet): one sentence saying that minting needs a signed-in session, a request authenticated with an API key is refused403 PERMISSION_DENIED, and so a key cannot mint another key. "Send it as" becomes "Send the key as" so the pronoun stays unambiguous.content/docs/ai/connect-mcp.mdx(under "Or mint one over REST"): the lead-in now names the signed-in session (the-b cookies.txtin the snippet) and the 403 for an API-key request. Open PR fix(runtime)!: a same-origintype: 'api'action is dispatched through the action doors, so its packaged-action switch holds (#27506) #27649 edits this file only at its L242 and L392 hunks, so the two do not overlap.No runtime change.
packages/qa/dogfoodisprivate: trueandcontent/docsdoes not publish, so no changeset is owed and the PR carriesskip-changeset.Tests
Every reader of the matrix that imports or reads its text was run.
authz-conformance.test.tsimportsAUTHZ_CONFORMANCE.authz-probe-blind-spot.test.tsreads the matrix text. The other files that grep the name only mention it in comments.Matrix readers: 2 files, 70 tests, pass (head 2ba6263)
The pin the new row cites: 14 tests, pass
Dogfood typecheck: exit 0, and the program does include the matrix file
pnpm --filter @objectstack/dogfood run typecheckexits 0. With--listFilesthe program holds 409 files underpackages/qa/dogfood/test/, one of themauthz-conformance.matrix.ts.Acceptance notes
2140821ea6. It said 67 rows and 60enforced, but a count at base read 68 rows, 50 with nocovers, 61enforcedand 44enforcedwith nocovers. The new row moves each figure by one more, so they were corrected to the measured values: 69, 51, 62 and 45. No test pins these figures. The [finding]authz-conformance.matrix.ts:27states the route ledger holds "94 rows / 19 families" in the present tense — measured 91 today, and the cause is #14503, not the gate move it sits next to #17111 pin reads only the two ledger group counts, which this PR does not move.Verification
Gate families come from
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackat head2ba6263244(3 paths). Each exit code was recorded before any pipe and reconciled with--ran.Local derived set: 71 derived, 70 run exit 0, 1 NOT MEASURED
--ranverdict:71 derived famil(ies) accounted for — 70 run, 1 NOT-MEASURED (1 DERIVED from a recorded exit 3).pnpm check:dual-build-cjs-loadsexits 3 with PREREQUISITE NOT MET, because six packages outside this diff's build closure have nodist/(studio, embedder-openai, knowledge-memory, knowledge-ragflow, service-cluster-redis, service-knowledge). CI'sLint & Repo Gatesruns it on a full build.pnpm --filter '@objectstack/dogfood^...' buildexits 0.@objectstack/client-react...was also built, becausecheck:skill-examplesreads itsdist. That gate exited 3 before the build and 0 after it.--ranflagged the tree as 11 commits behind origin/main. The one derivation input that changed in that range isscripts/pm/check-skill-line-ratchet.mjs, which none of the 71 derived families runs.Generated by Claude Code