Skip to content

auth-mount coverage — follow-ups 1/2/4 LANDED; remaining scope is follow-up 3 (sdk bridge) + the #10975 ledger row (body below is the original census, now historical) #10534

Description

@os-zhuang

#10050 asked whether POST /organization/add-member being mounted-but-undocumented was a one-off. It was not. Census below, measured on origin/main at 4544be260, with positive controls on both legs.

Population

auth-plugin.ts mounts routes directly on the raw Hono app, ahead of the better-auth catch-all. Those mounts are the ObjectStack-owned auth surface — the catch-all never sees them, so the vendor's own route table cannot account for them.

Enumerated by matching rawApp.<verb>(\${basePath}/…`)inpackages/plugins/plugin-auth/src/auth-plugin.ts(excluding therawApp.allcatch-all and the.well-known/*mounts, which are not underbasePath`): 17 routes.

Leg 1 — documented?

Test: does the literal wire path /api/v1/auth<path> appear anywhere in the hand-written docs corpus (392 .md/.mdx files under content/docs, content/docs/releases/** excluded as release-owned)?

6 of 17 undocumented, before this card's PR:

Route In a ledger?
POST /api/v1/auth/admin/sso/request-domain-verification no
POST /api/v1/auth/admin/sso/verify-domain no
POST /api/v1/auth/admin/unban-user vendor inventory only
GET /api/v1/auth/bootstrap-status yes — objectstack / sdk
POST /api/v1/auth/organization/add-member yes — objectstack / server-only
POST /api/v1/auth/set-initial-password no

#10050's PR documents the last-but-one, leaving 5 of 17.

⚠️ Two refinements the raw number hides. set-initial-password is named once in prose (authentication.mdx, "offers set-initial-password") without its URL — named, not documented. And add-member was named three times in tenancy-modes.mdx with no URL anywhere, which is how it stayed invisible while looking discussed.

Positive control (leg 1): the same expression, run before the docs were written, returned organization/add-member — the known-present member of the set. So a zero would have been a real zero. Control output: POSITIVE CONTROL organization/add-member present in undocumented set: true.

Leg 2 — ledgered?

auth-route-ledger.ts has two halves: the reviewed AUTH_ROUTE_LEDGER rows and the machine-maintained BETTER_AUTH_MOUNTED_SURFACE inventory. A route in neither is unaccounted for.

9 of 17 appear in neither half:

/admin/import-users · /admin/oauth2/toggle-disabled · /admin/sso/register · /admin/sso/register-saml · /admin/sso/request-domain-verification · /admin/sso/verify-domain · /admin/unlock-user · /set-initial-password · /sys-oauth-application/register

Only 3 of the 17 carry a reviewed source: 'objectstack' row: /config, /bootstrap-status, /organization/add-member. The rest are either attributed to the vendor (correct where the vendor also declares the path — the ObjectStack mount shadows it) or absent entirely.

Verified two ways that agree: a regex parse of the ledger source, and a direct grep "auth<path>'" per route. Positive control (leg 2): the same grep returns 1 for /organization/add-member and 1 for /config, so an absence is an absence and not a broken pattern.

Leg 3 — why nothing caught it

Both of #10050's asks land on the same hole, and it is upstream of either ledger row.

scripts/docs-audit/affected-docs.mjs --bridge-coverage on this tree:

  client-bound ledger rows ... 221
    reachable ................ 45
    UNREACHABLE .............. 176
        55 of 55   unreachable  packages/plugins/plugin-auth/src/auth-route-ledger.ts

Every client-bound row in the auth ledger is unreachable by the sdk doc-nomination bridge. The bridge finds route registrars by filename convention — REGISTRAR_FILE_RE = /(?:^|\/)(?:[\w.-]*route[\w.-]*|[\w.-]*-server)\.ts$/ — and the file that actually registers this surface is auth-plugin.ts, which matches neither alternative. No registrar tail is produced for the auth surface, so no auth ledger row can be selected, so the sdk anchor never nominates a doc for an auth route.

add-member is then invisible a second time on top of that: its row is disposition: 'server-only' with no client, so it is not even among the 55 client-bound rows the bridge fails to reach.

The 221→45 shape is already recorded in #9572 (closed). What is new here is the auth slice being 55 of 55 and the concrete cause being one filename convention — plus the demonstration that this is what let a route mount and its documentation gap ship separately with nothing objecting.

⛔ Deliberately not acted on: scripts/docs-audit/affected-docs.mjs is being edited by open PR #10501, which is fixing a different silent-parse defect in the same file. Any remedy here belongs after that lands.

Suggested follow-ups

  1. Document the 5 remaining undocumented mounts (or record a deliberate "server-only, not user-facing" verdict for each — bootstrap-status may well be one).
  2. Ledger the 9 unledgered mounts as source: 'objectstack' rows, which is what the ledger's own header says objectstack mounts are for.
  3. Decide whether the sdk bridge should reach the auth surface at all — either by teaching REGISTRAR_FILE_RE about auth-plugin.ts, or by declaring registrars explicitly rather than by filename convention. After fix(docs-audit): a PARTIAL ledger read is a verdict, not a smaller number #10501.
  4. Consider a gate: a rawApp mount under basePath with no ledger row is exactly the state that produced [finding] sys_member "Add Member" action targets POST /organization/add-member, which better-auth 1.7.0-rc.2 never mounts (server-only) — on multi-org there is NO remaining UI path to attach an existing user to an org #9941 and docs: the newly mounted POST /organization/add-member is undocumented — and it is the ONLY multi-org path to attach an existing user #10050, and it is mechanically detectable.

Refs

#10050 (the card this sweep came from) · #9941 / PR #10049 (the mount) · #9572 (the 221→45 bridge measurement, closed) · #10501 (open, owns affected-docs.mjs) · #9969 / #9652 (adjacent: vendor /admin/ routes and their admit sets)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions