Repository navigation
Commit 446c8b2
docs(sso): both domain-verification steps answer 400 DOMAIN_VERIFICATION_DISABLED with the switch unset, and an unknown provider 404 RESOURCE_NOT_FOUND with it on (#22504)
Fixes #22493
Clause-②: no
## What changed
`content/docs/permissions/sso.mdx`, the callout under **Domain
verification (opt-in)**. Only the middle sentence changed. The callout's
headline, its first clause and the identity-before-capability sentence
are byte-identical. Docs only: no code, no test, no changeset.
**Before** (`origin/main` `e148ca98`, `:281`–`:284`):
> Both routes exist whether or not `OS_SSO_DOMAIN_VERIFICATION` is set —
and with it unset the two halves report that differently, so match on
the code rather than the status: step 1 answers **400
`DOMAIN_VERIFICATION_DISABLED`**, step 2 passes the inner **404**
through with an explanatory message.
**After:**
> Both routes exist whether or not `OS_SSO_DOMAIN_VERIFICATION` is set —
and with it unset there is no endpoint behind them, so both steps answer
**400 `DOMAIN_VERIFICATION_DISABLED`**. With it on, either step answers
an unknown `providerId` with **404 `RESOURCE_NOT_FOUND`**; step 2's
`NO_PENDING_VERIFICATION` is a 404 too, so match on the code rather than
the status.
The page still tells readers to match on the code, but the reason is now
true. With the switch on, step 2 answers both an unknown provider and a
provider with no pending verification with a 404. Only the code tells
them apart.
## The code these answers were read from
All paths are under `packages/plugins/plugin-auth/src`, read at
`e148ca98`:
- `auth-plugin.ts:3084`–`:3089` and `:3102`–`:3107`: each mount runs
`gateAdmin(c)` first. It then calls its bridge with `{
domainVerificationEnabled:
this.authManager!.isSsoDomainVerificationEnabled() }`.
- `register-sso-provider.ts:455` and `:511`: `if
(options.domainVerificationEnabled === false) return
domainVerificationDisabled();`. This line comes before the inner request
is built, so the vendor is never asked.
- `register-sso-provider.ts:370`–`:372`: `domainVerificationDisabled()`
returns `{ status: 400, … code: 'DOMAIN_VERIFICATION_DISABLED' … }`.
Both doors share this one helper.
- `register-sso-provider.ts:464` and `:530`: `if (resp.status === 404 &&
!parsed?.code) return codelessVendorNotFound(providerId, options);`
- `register-sso-provider.ts:380`–`:381`: when `domainVerificationEnabled
=== true`, that 404 becomes `{ status: 404, … code: 'RESOURCE_NOT_FOUND'
… }`.
- `register-sso-provider.ts:541`: a vendor error that carries a code
passes through with the vendor's own status and code. This is how step
2's `NO_PENDING_VERIFICATION` keeps its 404.
- `auth-manager.ts:7036`–`:7040`: `isSsoDomainVerificationEnabled()` is
false unless SSO is wired. Otherwise it reads
`config.plugins.ssoDomainVerification`, then
`OS_SSO_DOMAIN_VERIFICATION`, and defaults to `false`.
The not-found answer is the bridge's own code, `RESOURCE_NOT_FOUND`. The
page quotes no vendor wording.
## Pins that hold these answers
- `sso-domain-verification-unknown-provider.pin.test.ts` runs a real
`AuthManager` behind the plugin's real route registration. Its blocks
pin these answers:
- `:196`: switch on, unknown provider: 404 `RESOURCE_NOT_FOUND` on both
doors.
- `:210`: switch off: 400 `DOMAIN_VERIFICATION_DISABLED` on both doors,
and the vendor is never asked.
- `:232`: switch on, existing provider, no pending verification: 404
`NO_PENDING_VERIFICATION` on verify-domain.
- `:244`: anonymous: 401 `UNAUTHENTICATED` on both doors, with the
switch on or off.
-
`packages/qa/dogfood/test/admin-route-nonadmin-refusal.dogfood.test.ts`:
- It asserts the 401 `UNAUTHENTICATED` and 403 `PERMISSION_DENIED`
sentence (`:614`–`:619`), and that the platform admin is not refused
(`:627`–`:632`).
- The `400 DOMAIN_VERIFICATION_DISABLED` at `:307` and `:312` is in a
`note:` string. It is not asserted. The plugin-auth file above is what
pins the off answer.
- I did not run either test locally. This card is docs-only, so no test
is owed. The `Test Core` check concluded `success` on `e148ca98`.
- No docs gate checks this page's claims. The nearest one,
`check:error-status-conformance`, reconciles statuses on
`api/error-catalog.mdx` and `protocol/kernel/error-handling.mdx` only.
No gate is added.
## Sweep for other stale copies
`git grep` before the edit, at `e148ca98`:
- `inner \*\*404\*\*\|passes the inner` over `content/docs/**`: 1 hit,
`sso.mdx:284`.
- `report that differently` over `content/docs/**`: 1 hit,
`sso.mdx:282`.
- Both patterns over the whole tree: only those two lines.
- `DOMAIN_VERIFICATION_DISABLED` over `content/**`, `skills/**`,
`docs/**`, `apps/docs/**` and `*.md`/`*.mdx`: `sso.mdx:283`, plus the
two generated code lists (`references/api/contract.mdx:143` and
`references/api/error-code-ledger.mdx:310`, code names only). The rest
were the pending `.changeset` for the code change and the released
`plugin-auth/CHANGELOG.md`, which this PR does not touch.
The callout was the only stale copy.
## Local gates, at `620e67e2`
- `node scripts/pm/dispatch-gates.mjs --commands` derived 43 commands
from merge base `e148ca984`, with 1 path changed (+4/−3).
- All 43 ran, and every one ended with exit 0.
- Four first exited 3 with `PREREQUISITE NOT MET` because
`@objectstack/lint`, `@objectstack/formula` and
`@objectstack/client-react` were not built. Those runs measured nothing.
After those packages were built, all four ran again and exited 0. The
four were `check:doc-formula-expressions`, `check:doc-security-posture`,
`check:skill-examples` and `check:docs-transcript-drift`.
- `--ran` reconciliation: `43 derived famil(ies) accounted for — 43 run,
0 NOT-MEASURED (a DERIVED zero — all 43 recorded an exit code and none
of them is 3)`.
The four the dispatch named:
| command | exit | verdict line |
|---|---|---|
| `pnpm check:doc-authoring` | 0 | `doc authoring guard: 418 files clean
— no bare metadata literals.` |
| `pnpm check:doc-anchors` | 0 | `472 internal #fragment link(s) across
417 source file(s)` all land on a real heading |
| `pnpm --filter @objectstack/lint run check:doc-security-posture` | 0 |
`28 ObjectSchema.create example(s) in 230 marked block(s) across 254
prose file(s) in 2 root(s) carry an os validate-clean security posture`
|
| `pnpm --filter @objectstack/spec run check:docs` | 0 | `225 generated
files in sync with packages/spec` |
NOT MEASURED here because these are CI's own shell: `ci.yml · Build
Docs` (the docs app build), the `Test Core` shards and the type-check
lanes.
## Acceptance notes
- On this page, "the switch" means `OS_SSO_DOMAIN_VERIFICATION`.
`isSsoDomainVerificationEnabled()` also reads the config key
`plugins.ssoDomainVerification`, which wins over the env var, and it is
false whenever SSO itself is not wired. The callout keeps the page's
existing env-var framing. Nothing changed here.
- The step text at `:274`–`:277` names `NO_PENDING_VERIFICATION` without
a status. The callout now gives its status. That paragraph is otherwise
untouched.
- No changeset is needed: `content/docs/**` ships in no public package's
`files[]`. I checked every tracked public `package.json` and found zero
`files[]` entries naming content or docs. As a control, 69 public
packages do list `dist`.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01LYXc6ckoWuZyVZpWYizdMh)_
Co-authored-by: Claude <noreply@anthropic.com>1 parent f8566a0 commit 446c8b2
1 file changed
Lines changed: 4 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
279 | 279 | | |
280 | 280 | | |
281 | 281 | | |
282 | | - | |
283 | | - | |
284 | | - | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
285 | 286 | | |
286 | 287 | | |
287 | 288 | | |
| |||
0 commit comments