Wrap discovery + token-exchange fetch in try/catch so a DNS/network
failure returns BadRequest/Unauthorized instead of a bare 500.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- OidcConfig entity (single row) + DB registration.
- OidcService: discovery, Authorization Code + PKCE, state/ticket as
short-lived signed JWTs (no server session), userinfo/id_token claim
resolution. Auto-provisions a passwordless user by email.
- Public endpoints /auth/oidc/{status,start,callback,exchange}; callback
bounces a one-time ticket to the SPA in the URL fragment.
- AuthService.provisionOidcUser + issueSessionForUserId (login shape).
- CLI: 'config oidc' upserts issuer/clientId/secret/callback/redirect/
scopes/enabled (secret masked on print).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
C1: replace fragile path.endsWith() guard whitelist with a metadata
@Public() decorator + Reflector (no more path-shape bypass surface).
C2: CenterApiKeyGuard attaches the authenticated GuildNode; introspect
& resolve-names now reject when body.guildNodeId != that node
(stops one node probing/enumerating another guild's identities).
C3: heartbeat/status are self-only (a node can't revoke/hijack another);
GET /nodes no longer returns apiKeyHash (credential-hash leak).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
package.json type=module, tsconfig module/moduleResolution=NodeNext,
target es2022, explicit .js on all relative imports. Center: jsonwebtoken
& bcryptjs switched to default imports (ESM/CJS interop). Verified:
builds, boots, full auth + plugin round-trip work under ESM.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
UserApiKey (apiKeyHash->userId); CLI 'user apikey --email'; POST
/auth/agent/login {apiKey} -> normal user session (api-key-guard exempt).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Resolve display names/emails to userIds within a guild node's active
members (api-key auth). Used by guild for <@user.name:NAME> translation.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- User.name column, defaults to email on register
- GET /auth/me, PATCH /auth/me to view/change own name (api-key exempt)
- login + guild members responses now include name
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>