You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs(plugin-auth): ledger and document the unaccounted ObjectStack auth mounts (#10660)
auth-plugin.ts mounts 17 routes directly on the raw Hono app ahead of the
better-auth catch-all. Nine were in neither half of auth-route-ledger.ts and
six carried no literal wire path in the hand-written docs.
Ledger: eight gain reviewed `source: 'objectstack'` rows, all `server-only`,
each measured to have zero ObjectStackClient callers and exactly one real
caller (a declarative metadata action target or a Console wizard). The
conformance pin over the objectstack-sourced set grows 3 -> 11 in the same
edit, so the enlarged set stays reviewable.
set-initial-password is deliberately left unledgered: its peer group makes it
read as `gap`, not `server-only`, and `gap` is ratcheted to zero — so a
disposition there would be a false declaration written to dodge a ratchet.
Escalated on the issue instead.
Docs: bootstrap-status, set-initial-password, admin/unban-user,
admin/sso/register and the two admin/sso domain-verification routes now carry
their literal wire paths. admin/sso/register was NOT documented before — the
census's substring test had credited it to its longer sibling register-saml.
No route's mounting, behaviour or accept/reject set changes.
Claude-Session: https://claude.ai/code/session_01PnJHU45vPJj5UQrxe946Bx
Co-authored-by: Claude <noreply@anthropic.com>
Ledger and document the ObjectStack-owned auth mounts that were in neither the route ledger nor the docs (#10534).
6
+
7
+
`auth-plugin.ts` mounts 17 routes directly on the raw Hono app ahead of the better-auth catch-all. A census found **nine** of them in neither half of `auth-route-ledger.ts`, and **six** with no literal wire path anywhere in the hand-written docs — the state that let a mount and its documentation gap ship separately with nothing objecting.
8
+
9
+
**Ledger:** eight mounts gain reviewed `source: 'objectstack'` rows — `/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`, `/sys-oauth-application/register`. All are `disposition: 'server-only'`: each was measured to have zero `ObjectStackClient` callers and exactly one real caller that is a declarative metadata action target or a Console wizard. `POST /api/v1/auth/set-initial-password` is deliberately left unledgered and escalated rather than given a guessed disposition.
10
+
11
+
**Docs:**`GET /api/v1/auth/bootstrap-status`, `POST /api/v1/auth/set-initial-password`, `POST /api/v1/auth/admin/unban-user`, `POST /api/v1/auth/admin/sso/register`, `POST /api/v1/auth/admin/sso/request-domain-verification` and `POST /api/v1/auth/admin/sso/verify-domain` are now documented with their literal wire paths, including the opt-in `OS_SSO_DOMAIN_VERIFICATION` domain-verification flow and the asymmetric way its two halves report the switch being off.
12
+
13
+
No route's mounting, behaviour or accept/reject set changes.
-`mode: 'insert' | 'upsert'` with `matchBy: 'email' | 'phone'`. Upsert
904
961
updates only touch profile fields (`name`, `image`, `phone_number`, `role`)
905
962
— a re-imported file can never modify an existing user's email or reset
@@ -1002,11 +1059,13 @@ All endpoints are available under `/api/v1/auth/*`:
1002
1059
#### Session
1003
1060
1004
1061
-`GET /api/v1/auth/get-session` - Get current user session
1062
+
-`GET /api/v1/auth/bootstrap-status` - Public, unauthenticated first-run probe: `{ "hasOwner": boolean }`, telling a client whether this environment has any user yet ([details](#first-run-bootstrap-status))
-`POST /api/v1/auth/reset-password` - Reset password with token
1068
+
-`POST /api/v1/auth/set-initial-password` - Set a **first** local password for a signed-in user who has no credential yet (SSO-onboarded accounts). Session required; refuses when a password already exists ([details](#setting-a-first-local-password))
1010
1069
1011
1070
#### Email Verification
1012
1071
@@ -1042,6 +1101,8 @@ All endpoints are available under `/api/v1/auth/*`:
1042
1101
-`POST /api/v1/auth/admin/set-user-password` - Set/reset a user's password (also provisions a credential for SSO-onboarded users)
// 2, `get-session` → 6 in `packages/client/src`). Every route below came
199
+
// back with ZERO `ObjectStackClient` callers and exactly one real caller
200
+
// that is a DECLARATIVE metadata action target or a Console wizard — the
201
+
// `organization/add-member` precedent directly above. Their peer routes
202
+
// (`/admin/create-user`, `/admin/ban-user`, `/admin/set-user-password`) are
203
+
// uniformly SDK-absent too, so "the SDK deliberately does not cover
204
+
// platform-operator user administration" is the surface's actual shape, not
205
+
// an accommodation written to make a row fit.
206
+
//
207
+
// ⚠️ `POST /api/v1/auth/set-initial-password` is the ninth mount and is
208
+
// DELIBERATELY NOT LEDGERED HERE. It fails the test above in a way none of
209
+
// these do: its caller is `@object-ui/auth`'s `createAuthClient`, whose
210
+
// three other auth URLs (`/config`, `/get-session`, `/list-accounts`) are
211
+
// ALL expressed on `ObjectStackClient` — and its own sibling branch in the
212
+
// same Console password card, `changePassword`, is ledgered `sdk`. That
213
+
// shape reads as `gap` ("should be in the SDK and is not"), not as
214
+
// `server-only`, and `gap` is ratcheted to zero by this file's conformance
215
+
// suite. Writing `server-only` there would be a false declaration of intent
216
+
// to dodge a ratchet. It is escalated on #10534 instead.
217
+
//
218
+
// `requires` follows the add-member precedent: it names the better-auth
219
+
// plugin the route's WORK needs, not whether the mount is conditional —
220
+
// every one of these is mounted unconditionally on the raw app.
221
+
{route: 'POST /api/v1/auth/admin/import-users',family: 'objectstack-mount',source: 'objectstack',disposition: 'server-only',note: 'no SDK method builds this URL — objectui app-shell\'s identity-import wizard (views/identityImport.ts) posts it directly from the Users list; platform-admin gated (ADR-0068), #2766 V2'},
222
+
{route: 'POST /api/v1/auth/admin/oauth2/toggle-disabled',family: 'objectstack-mount',source: 'objectstack',disposition: 'server-only',note: 'no SDK method builds this URL — the sys_oauth_application disable/enable actions post it directly; ObjectStack mount closing a vendor gap (better-auth\'s /admin/oauth2/update-client strips `disabled` from its body schema), platform-admin gated (ADR-0068)'},
223
+
{route: 'POST /api/v1/auth/admin/sso/register',family: 'objectstack-mount',source: 'objectstack',disposition: 'server-only',requires: 'sso',note: 'no SDK method builds this URL — the sys_sso_provider register action posts flat form fields; ObjectStack bridge re-dispatching into @better-auth/sso /sso/register, platform-admin gated ahead of the delegation (ADR-0068 D4, #9653). Distinct path from the vendor\'s own /sso/register, which the catch-all serves'},
224
+
{route: 'POST /api/v1/auth/admin/sso/register-saml',family: 'objectstack-mount',source: 'objectstack',disposition: 'server-only',requires: 'sso',note: 'no SDK method builds this URL — the sys_sso_provider register_saml_provider action posts flat fields the bridge reshapes into better-auth\'s nested samlConfig; platform-admin gated (ADR-0068 D4, #9653), ADR-0069 P3'},
225
+
{route: 'POST /api/v1/auth/admin/sso/request-domain-verification',family: 'objectstack-mount',source: 'objectstack',disposition: 'server-only',requires: 'sso',note: 'no SDK method builds this URL — the sys_sso_provider action posts it and renders the returned DNS TXT record; ObjectStack bridge over @better-auth/sso, additionally gated on the opt-in ssoDomainVerification switch (OS_SSO_DOMAIN_VERIFICATION) — off means the inner endpoint 404s, the mount itself is unconditional; platform-admin gated (ADR-0068 D4), ADR-0024 ②'},
226
+
{route: 'POST /api/v1/auth/admin/sso/verify-domain',family: 'objectstack-mount',source: 'objectstack',disposition: 'server-only',requires: 'sso',note: 'no SDK method builds this URL — the sys_sso_provider action posts it after the DNS TXT record is published; same opt-in ssoDomainVerification switch and platform-admin gate as request-domain-verification (ADR-0068 D4), ADR-0024 ②'},
227
+
{route: 'POST /api/v1/auth/admin/unlock-user',family: 'objectstack-mount',source: 'objectstack',disposition: 'server-only',note: 'no SDK method builds this URL — the sys_user unlock_user action posts it directly; clears a brute-force lockout (sys_user.locked_until / failed_login_count), a custom per-identity mechanism with no better-auth endpoint; platform-admin gated (ADR-0068), ADR-0069 D2'},
228
+
{route: 'POST /api/v1/auth/sys-oauth-application/register',family: 'objectstack-mount',source: 'objectstack',disposition: 'server-only',note: 'no SDK method builds this URL — the sys_oauth_application create action posts it directly; session-required self-service wrapper over better-auth /oauth2/create-client that splits the Console\'s newline-separated redirect-URL textarea into the redirect_uris array the vendor schema requires'},
0 commit comments