Repository navigation
feat(client,runtime): auth.mePermissions() reads GET /auth/me/permissions as MePermissionsResponse - #28766
Conversation
…ions as MePermissionsResponse, on its own route-ledger row Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
📓 Docs Drift Check3 anchor(s) derived from 2 changed package(s); no hand-written page names any of them, so this run has nothing to list — not a clean bill of health. This check sees only pages that NAME a derived anchor: one that documents this change in prose, or enumerates it in an authoring dialect, names none and stays invisible to it on every run. What this run could not see
Coarse fallback — 39 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 7ad3251320b60c9a9120ccfaa09c9da8688bad2b && git checkout 7ad3251320b60c9a9120ccfaa09c9da8688bad2b
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 706ac52d570096a47b64283e970bc1a8e569bc91 7ecb00173b85c50366402b29fe9ac10d78561bc8 && git checkout -B drift-repro 706ac52d570096a47b64283e970bc1a8e569bc91 && git merge --no-ff 7ecb00173b85c50366402b29fe9ac10d78561bc8
node scripts/docs-audit/affected-docs.mjs --json 706ac52d570096a47b64283e970bc1a8e569bc91 |
|
domain:server#3 · os-project-manager · session_01FEkQ5kE5BrPUPNMMyv6oCH Contract reviewServed-tier: Inputs read: card #28709 (body, triage, unblock note, claim, the dev's os-dev-report), PR #28766 (body, 5-file list), the net diff against merge-base ① Derived judgments
② Semver level
③ Boundary flags
Blocking: none. Should-fix (non-blocking):
Implemented-by: VERDICT: PASS |
|
domain:server#3 · os-project-manager · session_01FEkQ5kE5BrPUPNMMyv6oCH 席位核对 · ACCEPT · PR #28766 · 2026-11-01T18:36ZHead-sha: 维护者速读(席位终稿)
核对六项
|
Requested by Leehom · project thread
Fixes #28709
Clause-②: yes (widening) — one new SDK method,
client.auth.mePermissions(), over the existingGET /auth/me/permissions. No wire change, no new route, and nopackages/spec/**file is touched.Metadata-protocol: none — nothing a metadata author writes is read differently; the method reads a response body already declared in
@objectstack/spec/apiby PR #28704.维护者速读
@objectstack/client多了一个方法client.auth.mePermissions(),读当前用户的有效权限(GET /api/v1/auth/me/permissions),返回类型就是 spec 里已声明的MePermissionsResponse;未登录时返回{ authenticated: false },不抛错。路由台账给这条路由补了一行。* /auth/**通配行)。packages/runtime/src/route-ledger.ts新行(说明它由 plugin-hono-server 的 raw app 提供,不经dispatch());packages/qa/dogfood/test/route-ledger-live-mount-parity.dogfood.test.ts的新豁免条目;packages/client/src/index.ts的mePermissions。pnpm --filter @objectstack/client exec vitest run src/auth-me-permissions.test.ts src/client-url-conformance.test.ts,预期Tests 6 passed (6)。What changes
packages/client/src/index.ts:auth.mePermissions()resolvesMePermissionsResponse; it GETs${baseUrl}${getRoute('auth')}/me/permissionsthrough the shared fetch wrapper. The type is imported from@objectstack/spec/api, not restated. Its JSDoc says how it differs fromauth.me(): a signed-out caller resolves{ authenticated: false }(the route answers that at 200) rather than rejecting.packages/runtime/src/route-ledger.ts: aGET /auth/me/permissionsrow (domain: '/auth',disposition: 'sdk',client: 'auth.mePermissions',responseSchema: 'MePermissionsResponseSchema'). Exact rows sort ahead of the* /auth/**family inclient-url-conformance, so the method is credited to this row and not to the wildcard. The note states what serves it: plugin-hono-server'sregisterCurrentUserEndpointswithrawApp.get(), ahead of plugin-auth's catch-all, notdispatch()(the/authdomain only relays to the auth service, which does not serve this path). It names the suite that gives theresponseSchemaits conformance coverage:current-user-endpoints-has-any-queue.test.tsdrives this handler and parses every body it provokes through the strict schema. The census sentence was regenerated (check-route-ledger-census.mjs --fix: 115 → 116).packages/qa/dogfood/test/route-ledger-live-mount-parity.dogfood.test.ts:GET /api/v1/auth/me/permissionsjoinsUNEXERCISED_BY_THIS_BOOT, with its reason. A raw-app mount never passes through theIHttpServerport, so without the pin direction 1 ("every ledgered route is reachably mounted") would red on this row. Dogfood does not run in PR CI, so a missing pin would only show up onmain..changeset/28709-client-auth-me-permissions.md:@objectstack/clientpatch with both declaration lines.Metadata-protocol: nonegrades every entrypatch(check-changeset-no-major).route-ledger.tsships in no package:ROUTE_LEDGER/LEGACY_CHAIN_PREFIXESget 0 hits inpackages/runtime/dist(controlcreateDispatcherPluginhitsdist/index.js), and dogfood is private.Tests
packages/client/src/auth-me-permissions.test.ts(3 cases) runs over the real handler. plugin-hono-server'sregisterCurrentUserEndpointsis mounted onnew HonoHttpServer(0).getRawApp(), the appHonoServerPluginmounts it on, and the client'sfetchhands each request to that app.GET http://localhost:3000/api/v1/auth/me/permissions. The resolved value parses throughMePermissionsResponseSchemawith no issues, and narrows onauthenticatedto the caller's ownuserId,tenantId,hasAnyQueueandpermissionSets.{ authenticated: false }and does not throw.auth.mePermissionsand the schema these cases parse with.scripts/ablation-replace.mjs, anchor hit once, blob3dc5d07f→9b262a18): the row's route is renamed toGET /auth/me/permissions-ablated, andclient-url-conformance.test.tsreds with 1 failed / 2 passed:auth.mePermissions → GET /api/v1/auth/me/permissions (via * /auth/**): expected 1 to be +0. That is the failure this card was filed for, and the row is what closes it. Restore: blob equals HEAD's (3dc5d07f) andgit diff HEADis empty. The ledger is imported as relative source, so no build sits on the path.Acceptance notes
auth-plugin.ts's own mounts. A new plugin-hono-server ledger would be a sixth member of the client union with its own conformance gate. It would also have to give dispositions to/auth/me/localizationand/me/apps, which no ledger carries today and this card does not ask about. So the row went into the runtime ledger, and its note says plainly that the door is a raw-app mount./auth/me/localizationand/me/apps(same registrar) stay in no ledger and have no client method. Not filed: no consumer asks for an SDK method for them.ff0d7c02(written and then reverted on Session payload: the console learns once per session whether the caller's organization has at least one ownership queue (declared orsys_queue), with no widening of member read onsys_queue#28508's branch) was reused for the method and its JSDoc. Its test used a mocked fetch; this one runs over the real handler instead.Verification
All at head
7ecb0017(base7a48bf73,origin/mainwhen the branch was cut).Package suites and typecheck (under the verify lock)
pnpm --filter @objectstack/client test: Test Files 54 passed (54), Tests 693 passed (693).pnpm --filter @objectstack/client typecheck(tsc --noEmitpluscheck:test-typecheckovertsconfig.test.json, which covers the new test): exit 0.pnpm --filter @objectstack/runtime exec vitest run src/route-ledger.conformance.test.ts: 8 passed (8).pnpm --filter @objectstack/runtime typecheck: exit 0.auth-me-permissions,client-url-conformance,route-ledger-coverage,route-ledger-response-schema,auth-route-ledger-coverage: 5 files, 16 passed (16).pnpm --workspace-concurrency=2 --filter '@objectstack/dogfood^...' build):route-ledger-live-mount-parity.dogfood.test.ts8 passed (8). With the new pin's key changed (ablation, blob43b809da→d1fbf06f): 2 failed / 6 passed. Direction 1 saysruntime/route-ledger.ts: GET /auth/me/permissions — LEDGERED BUT NOT MOUNTEDand the stale-pin check names the changed key. Restore: blob equals HEAD's,git diff HEADempty.pnpm exec eslint --no-inline-configover the four touched source files: exit 0.Derived gates (dispatch-gates --commands, 66 families)
dispatch-gates.mjs --ran: "66 derived famil(ies) accounted for — 65 run, 1 NOT-MEASURED".pnpm check:dual-build-cjs-loads, exit 3 (PREREQUISITE NOT MET: packages outside this closure have nodist). CI runs it.check-plugin-teardown-shape.mjs --self-testfirst exited 3 on the shallow clone; aftergit fetch --depth=1 origin 621a4876it exited 0 (48 cases).spec check:skill-examplesfirst exited 3 until@objectstack/client-reactwas built, then 0 (279 prose examples, 23 client SDK blocks).check:dts-closurefirst exited 1 because it ran while a closure build was still writing, then 0 (241/241 declaration files across 77 packages).check:route-ledger-census: exit 0 after--fix(115 → 116).CI check-runs: read by the seat on this head.
🤖 Generated with Claude Code
https://claude.ai/code/session_01FEkQ5mKQh9Ew1XG2GQk2UN
Generated by Claude Code