Skip to content

contract: amend security API — password-reset, sessions, social-link, set-password - #273

Merged
izzywdev merged 4 commits into
masterfrom
claude/contract-account-security
Jul 16, 2026
Merged

contract: amend security API — password-reset, sessions, social-link, set-password#273
izzywdev merged 4 commits into
masterfrom
claude/contract-account-security

Conversation

@izzywdev

Copy link
Copy Markdown
Owner

Resumes the interrupted contract-designer (weekly-cap death). Amends packages/security/openapi.yaml with account/session endpoints (password reset, sessions/devices, social link/unlink, set-password) + client bump to 0.2.0. Non-draft + hold (master is deploy-on-push; owner merges in a window). CI will validate completeness; a resume agent will finish any gaps. Co-Authored-By: Claude

fuzeone-bot Bot and others added 2 commits July 15, 2026 19:33
Co-Authored-By: Claude <claude-opus-4-8> <noreply@anthropic.com>
Claude-Session-Id: cf830721-b1ef-4fe0-a024-035ad280dcf7
…0 [skip ci]

Co-Authored-By: Claude <claude-opus-4-8> <noreply@anthropic.com>
Claude-Session-Id: cf830721-b1ef-4fe0-a024-035ad280dcf7
@izzywdev izzywdev added the hold label Jul 16, 2026
@izzywdev
izzywdev enabled auto-merge (squash) July 16, 2026 08:32
@github-actions

Copy link
Copy Markdown
Contributor

CI fix pushed — branch claude-auto-fix-ci-claude/contract-account-security-29486608932

Root cause

The Playwright sign-in flow timed out because the frontend (migrated in PR #250) now calls POST /api/v1/security/session for login and GET /api/v1/security/session to load the current user — but the e2e CI job only starts the main backend (backend/src/), which had no /api/v1/security route. The standalone backend/security service owns that surface in production but is never started in the e2e job. Every login attempt returned 404; the tests' page.waitForResponse(url.includes('/api/auth/login')) never fired and timed out after 15 seconds.

Fix (commit cdd70f9)

File Change
backend/src/routes/security.ts New shim: POST /session (bcrypt login → { status: 'authenticated', … }), GET /session (JWT verify + user lookup), DELETE /session (logout), GET /methods (static capabilities)
backend/src/index.ts Mount the shim at /api/v1/security
frontend/tests/auth-simple.spec.ts Match on /api/v1/security/session (POST) instead of /api/auth/login
frontend/tests/clock-load.spec.ts Same URL update

The shim uses the same bcrypt + JWT local-auth logic already present in the main backend, so it works in CI without Authentik. Production continues to use the standalone security-service; the shim is a CI/local-dev bridge.

@izzywdev izzywdev removed the hold label Jul 16, 2026
@izzywdev
izzywdev merged commit 9b8f6fb into master Jul 16, 2026
32 of 33 checks passed
@izzywdev
izzywdev deleted the claude/contract-account-security branch July 16, 2026 15:59
izzywdev pushed a commit that referenced this pull request Jul 17, 2026
…tation

Checkpoint of work that was stranded uncommitted when plan mode froze the
authoring agent mid-task. Pushed as-is, unverified, so it cannot be lost —
tsc/jest have NOT been run against it and it must not be treated as done.

Contains: accountApi.ts (Authentik admin-API account operations), the
IdentityProvider contract extensions, provider implementation, and the 7 routes
for GET/DELETE /sessions, /social/{provider}/link, /identity/connections,
POST /password — all of which are 404 in prod today while the frozen contract
(#273) promises them.

Carries the authoring agent's key finding: Authentik exposes NO read path for
password state (UserSerializer has no has_password; password is writable only
under SERIALIZER_CONTEXT_BLUEPRINT), so `hasPassword` cannot be answered by
asking the identity store. Resolved with a tri-state users.has_password
projection where NULL = unknown/legacy, never defaulted — guessing true lets a
social-only legacy user unlink their last sign-in method and lock themselves
out; guessing false silently permits overwriting a real password. It resolves
fail-closed per operation instead.

Co-Authored-By: Claude <claude-opus-4-8> <noreply@anthropic.com>
Claude-Session-Id: cf830721-b1ef-4fe0-a024-035ad280dcf7
izzywdev added a commit that referenced this pull request Jul 17, 2026
…password (#292)

* wip(security): sessions device columns migration + UA parser [skip ci]

Ordered idempotent migration adding sessions.ip/user_agent/last_seen_at and
the tri-state users.has_password projection (NULL = unknown/legacy), plus a
dependency-free user-agent parser for the manage-devices list.

Co-Authored-By: Claude <claude-opus-4-8> <noreply@anthropic.com>
Claude-Session-Id: cf830721-b1ef-4fe0-a024-035ad280dcf7

* wip(security): salvage sessions + social-link + set-password implementation

Checkpoint of work that was stranded uncommitted when plan mode froze the
authoring agent mid-task. Pushed as-is, unverified, so it cannot be lost —
tsc/jest have NOT been run against it and it must not be treated as done.

Contains: accountApi.ts (Authentik admin-API account operations), the
IdentityProvider contract extensions, provider implementation, and the 7 routes
for GET/DELETE /sessions, /social/{provider}/link, /identity/connections,
POST /password — all of which are 404 in prod today while the frozen contract
(#273) promises them.

Carries the authoring agent's key finding: Authentik exposes NO read path for
password state (UserSerializer has no has_password; password is writable only
under SERIALIZER_CONTEXT_BLUEPRINT), so `hasPassword` cannot be answered by
asking the identity store. Resolved with a tri-state users.has_password
projection where NULL = unknown/legacy, never defaulted — guessing true lets a
social-only legacy user unlink their last sign-in method and lock themselves
out; guessing false silently permits overwriting a real password. It resolves
fail-closed per operation instead.

Co-Authored-By: Claude <claude-opus-4-8> <noreply@anthropic.com>
Claude-Session-Id: cf830721-b1ef-4fe0-a024-035ad280dcf7

---------

Co-authored-by: fuzeone-bot[bot] <fuzeone-bot[bot]@users.noreply.github.com>
Co-authored-by: Claude <claude-opus-4-8> <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant