Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
5404dd0
feat(realm): scoped Direct Access Grants exception for naruon-web only
seonghobae Sep 2, 2026
5661b3d
feat(registration): scoped password-credential issuance for naruon si…
seonghobae Sep 2, 2026
7c1939d
fix(registration): clear required actions on new password accounts
seonghobae Sep 3, 2026
c97f333
docs(adr): correct ADR-0014 with the RFC 9700/10017 ROPC prohibition …
seonghobae Sep 3, 2026
0ddcad6
docs(relying-party): expand validate_relying_party_registration's doc…
seonghobae Sep 3, 2026
79fe43d
fix(adr-0014): disable directAccessGrantsEnabled, fix stale index status
seonghobae Sep 3, 2026
44f0cb9
fix(adr-0015): fail closed password registration, guard realm regression
seonghobae Sep 3, 2026
86de970
docs(adr-0014/0015): OpenAPI accuracy, changelog, operability, doctor…
seonghobae Sep 3, 2026
31a21ca
test(auth): reject cleartext Keycloak admin URLs
seonghobae Sep 3, 2026
c2a5013
test(auth): use TLS origins in product transport fixtures
seonghobae Sep 3, 2026
7deedf0
test(auth): cover Keycloak origin validation edges
seonghobae Sep 3, 2026
cd0e435
fix(auth): enforce TLS on product Keycloak transport
seonghobae Sep 3, 2026
70c8004
test(auth): require seed-time password token revocation
seonghobae Sep 3, 2026
f6912b1
fix(auth): revoke omitted password registration token
seonghobae Sep 3, 2026
10f28e7
test(auth): require seed-time signup token revocation
seonghobae Sep 3, 2026
5f61cab
fix(auth): revoke omitted registration token
seonghobae Sep 3, 2026
6ffef10
docs(product-keycloak-client): flag reset_password as dormant capability
seonghobae Sep 3, 2026
ab8fedc
Merge remote-tracking branch 'origin/main' into codex/goal20-keyverse…
seonghobae Sep 4, 2026
bad8635
fix(auth): remove dormant password reset authority
seonghobae Sep 4, 2026
239e362
test(actions): remove retired steward contract
seonghobae Sep 4, 2026
737624f
Merge commit '239e362c95d48894a10841ec8a087f9107f3f90c' into codex/go…
seonghobae Sep 4, 2026
e1cf080
Merge remote-tracking branch 'origin/codex/keyverse-orchestrator-free…
seonghobae Sep 5, 2026
f893ec6
docs(auth): propose product-rendered passkey ceremonies
seonghobae Sep 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,14 @@ Product extensions are isolated behind `ProductAdminApi`; relying-party client
CRUD is further narrowed behind `RelyingPartyAdminApi`. Deterministic preflight
modules require neither protocol nor any network client.

### Proposed product-rendered ceremonies

Product-rendered login, signup, and recovery remain a proposed owner extension
in [ADR 0019](docs/adr/0019-product-owned-passkey-ceremonies.md), not a current
service capability. It keeps credential verification and token issuance in
Keyverse and requires a pinned-engine experiment and origin/RP-ID migration
before any product consumes the released ceremony contract.

### Deployment controller

- resolves every `{{placeholder}}` from KV or a secret manager;
Expand Down
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ Keep a Changelog, and releases use semantic versioning.

## [Unreleased]

- Documented the work required for products to present their own passkey
login, signup, and recovery forms. These forms remain proposed, and the
existing password-signup route remains unavailable.

### Added

- ADR-0008 and the non-fork RP authorization matrix, requiring explicit
Expand Down Expand Up @@ -111,6 +115,17 @@ Keep a Changelog, and releases use semantic versioning.

### Fixed

- Disabled `naruon-web`'s Direct Access Grants (ADR-0017) and the
`POST /registration/accounts/password` signup endpoint that depended on it
(ADR-0018): RFC 9700 §2.4 (BCP 240) and RFC 10017 §7.3 prohibit the OAuth
2.0 Resource Owner Password Credentials grant, and disabling it in isolation
had left password-only signups with no way to authenticate at all -- the
bound `browser-passwordless` flow accepts only passkeys. The endpoint now
fails closed (`503`) rather than create dead accounts, the shared runtime
adapter no longer carries dormant password-reset authority, and
`scripts/validate_realm.py` rejects a silent re-enable of the grant. See
`docs/doctoring/2026-09-03-naruon-password-ropc-standards-correction.md`
for the full evidence trail.
- Prevented relying-party inventory from silently accepting a KV key/body
identity mismatch, rejected unsafe live or `Location`-derived client UUIDs,
and aligned exact client discovery with Keycloak's documented
Expand Down
20 changes: 20 additions & 0 deletions deploy/keycloak/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,26 @@ and `role`/`org`/`workspace` claims required by the current Naruon session
contract. Its access tokens last 300 seconds; the longer SSO session is serviced
through normal token refresh/reissue rather than a twelve-hour bearer token.

`naruon-web`'s `directAccessGrantsEnabled` is currently `false`. It was
briefly `true` as a scoped, reviewed exception
([ADR-0017](../../docs/adr/0017-naruon-owned-password-form.md)) so naruon
could render its own login form with zero Keycloak-rendered HTML in the
loop, but that ADR's Correction (2026-09-03) found the grant type itself
(OAuth2 ROPC) violates RFC 9700 §2.4 / RFC 10017 §7.3, so the flag was set
back to `false` pending a standards-compliant replacement. No other RP ever
gets this exception; the account-unification dynamic-registration validator
still hard-rejects `directAccessGrantsEnabled: true` for everyone else.

A real password credential to authenticate with comes from
`POST /registration/accounts/password`
([ADR-0018](../../docs/adr/0018-naruon-password-credential-issuance.md)),
gated by its own `password_registration_api_token` — a third bearer
credential, distinct from `operator_api_token` and `registration_api_token`.
Without it configured, naruon's signup surface stays unavailable (503)
rather than open. The realm's `passwordPolicy`
(`"length(12) and notUsername and notEmail"`) enforces the same minimum a
second time, server-side, independent of the endpoint's own validation.

## Bootstrap

```bash
Expand Down
1 change: 1 addition & 0 deletions deploy/keycloak/realm-cwl.json
Comment thread
devin-ai-integration[bot] marked this conversation as resolved.
Comment thread
devin-ai-integration[bot] marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"displayName": "ContextualWisdom IdP",
"enabled": true,
"sslRequired": "external",
"passwordPolicy": "length(12) and notUsername and notEmail",
"registrationAllowed": false,
"registrationEmailAsUsername": true,
"resetPasswordAllowed": false,
Expand Down
21 changes: 21 additions & 0 deletions docs/OPERABILITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,27 @@ must test the **Naruon** product login/token/authorization journey using the
`naruon-web` RP client ID and verify the expected audience and bounded claims.
Mapper unit tests alone do not prove Naruon product authorization readiness.

## naruon password-signup 503 (expected, not an incident)

`POST /registration/accounts/password` (ADR-0018) currently returns `503` on
every call, unconditionally, before any Keycloak work happens. This is
deliberate, not a live-dependency failure: `naruon-web`'s Direct Access
Grants was disabled (ADR-0017's Correction, RFC 9700 §2.4 / RFC 10017 §7.3),
and a password-only account created without it has no way to authenticate --
the bound `browser-passwordless` flow accepts only passkeys. The endpoint is
gated behind `services/account_unification/app/password_registration.py`'s
module constant `PASSWORD_CREDENTIAL_LOGIN_AVAILABLE = False`.

On-call triage: if this 503 is the *only* symptom (health checks, other RP
clients, and the passwordless registration/login endpoints are otherwise
green), no incident response is needed -- confirm the constant is still
`False` in the deployed image and close as expected behavior. Re-enabling
requires a standards-compliant replacement login mechanism (Authorization
Code + PKCE or passkey/WebAuthn-capable headless contract), tracked against
ADR-0017; flipping the constant back to `True` without that replacement
reintroduces the original RFC violation. Full evidence trail:
`docs/doctoring/2026-09-03-naruon-password-ropc-standards-correction.md`.

## Account merge recovery

The active PR implementation makes merge, SCIM full replacement (`PUT`),
Expand Down
Loading