feat(auth): #28 OAuth messaging password β modal setup mode + unlock polish#84
Merged
TortoiseWolfe merged 4 commits intomainfrom May 7, 2026
Merged
Conversation
β¦tions Phase A β wireframe gate: - validate.py v5.4 returns 0 errors on both 01-oauth-password-setup.svg and 02-oauth-password-unlock.svg (annotation text now uses #1f2937 / #374151 instead of #6b7280 the 2026-01-16 review flagged). - Refreshed both .issues.md files to "Status: PASSED" with history table showing the v5.0 fail β v5.4 pass transition. - Added ## UI Mockup section to spec.md per Constitution v1.0.2 Principle III, linking both wireframes with sign-off date. Phase B β clarifications encoded: - Updated the stale Implementation Status block (was "Not Started, no OAuth modal found"; now reflects the partial-ship reality: isOAuthUser/getOAuthProvider already shipped, /messages/setup already shows password+confirm, ReAuthModal already OAuth-aware on unlock). - Added ## Clarifications / ### Session 2026-05-06 with 5 QβA bullets per /speckit.clarify convention: setup-mode trigger, no persistence of messaging password, no recovery flow, provider badge UX, and modal-vs-page primary path. - Added FR-018 through FR-022 encoding the clarification answers. Unblocks /speckit.plan via the harness shipped in PR #83. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Continues the v1.0.2 cascade for OAuth Messaging Password (issue #28). - checklists/implementation-readiness.md: "unit-tests-for-English" validation that plan.md and spec.md together carry enough info to drive /speckit.tasks and /speckit.implement without re-asking decisions. All 7 sections PASS. - tasks.md: 19 tasks ordered T001..T019 across 6 phases. US-1 (T002-T008) ships modal setup mode + EncryptionKeyGate redirect-flip. US-2 (T009-T012) layers in unlock-mode polish + provider badge. US-3 (T013-T015) is regression-only. T016-T019 polish (Storybook stories, AAA re-verify, manual smoke + screenshots, wireframe re-validate). RED tests authored before GREEN per Constitution II. - analysis.md: cross-artifact consistency check. FR-to-task traceability matrix shows every one of FR-001..022 has a task or already-shipped marker. User stories independently testable per their checkpoints. Plan-vs-tasks file paths align. Constitution v1.0.2 compliance verified across all 6 principles. Flags scripts/constitution-check.py layout bug as a separate one-liner. Recommendation in analysis: proceed to /speckit.implement. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
β¦olish
Closes the gap where OAuth users (Google/GitHub) had no in-modal way to
create the messaging password used to derive ECDH keys for E2E messaging.
Today they were redirected to /messages/setup; per FR-021 they now see
the modal in setup mode inline. The setup page is preserved as a deep-
link fallback per FR-022.
Implementation per features/auth-oauth/013-oauth-messaging-password/plan.md:
- New helper: src/lib/messaging/welcome/send-welcome-message.ts.
Extracted from app/messages/setup/page.tsx so both modal-setup and
page-setup share one welcome-message dispatch (cleaner long-term per
memory rule). setup/page.tsx now imports and calls the helper.
- ReAuthModal grows a 'mode' state ('unlock' | 'setup') decided at open
time by inspecting hasKeys() when an OAuth user opens the modal:
setup mode β password + confirm fields, "Create a Messaging
Password" title, "Create Messaging Password" submit
button, lossless-recovery warning copy, calls
initializeKeys + dispatches welcome message
unlock mode β existing single-password flow, calls deriveKeys
(unchanged behavior)
Provider badge ("Signed in via Google" / "Signed in via GitHub")
renders in both modes when isOAuthUser(user) is true (FR-020).
Unlock-mode description for OAuth users now explicitly says "This is
separate from your <Provider> login" per US-2 wireframe 02.
- EncryptionKeyGate.tsx flips the no-keys redirect: OAuth users get
setNeedsReAuth(true) (modal opens in setup mode); email users still
get the full-page redirect to /messages/setup so the browser's
password manager can offer auto-fill on a real <form>.
- ReAuthModal stories updated with documentation describing both modes.
Storybook stories rely on real AuthProvider; the per-mode behavioral
differentiation is covered by the unit tests rather than per-story
mocks.
7 new RED tests authored before implementation per Constitution II:
- setup-mode title renders for OAuth user without keys
- confirm-password field renders in setup mode
- submit calls initializeKeys (not deriveKeys) in setup mode
- mismatched passwords block submit + show alert
- provider badge renders with provider name in setup mode
- provider badge does NOT render for email users (FR-014)
- existing OAuth-with-keys regex updated for new copy
Full unit suite: 3261/3261 passing. type-check + lint clean.
Manual browser smoke + Playwright E2E spec + post-implement screenshots
follow in a subsequent commit (T013/T015/T018/T019 in tasks.md).
Refs: #28
Spec: features/auth-oauth/013-oauth-messaging-password/spec.md
Plan: features/auth-oauth/013-oauth-messaging-password/plan.md
Tasks: features/auth-oauth/013-oauth-messaging-password/tasks.md
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three test slots in tests/e2e/messaging/oauth-setup-modal.spec.ts: US-3 (runs in CI across chromium-msg, firefox-msg, webkit-msg, plus mobile profiles) β email user lands on /messages with cleared IndexedDB, ReAuthModal opens in unlock mode, asserts byte-identical pre-feature copy: "Enter Your Messaging Password" title, "Password" label (NOT "Messaging Password"), "Unlock Messages" submit button, no provider badge. Pins FR-013/FR-014/FR-020 invariants for the email flow. US-1 + US-2 (.skip()'d) β OAuth user setup mode and unlock-with-badge flows. Skipped because the repo does not yet have an OAuth test fixture (no Google/GitHub test app credentials in CI). The unit tests in src/components/auth/ReAuthModal/ReAuthModal.test.tsx carry the behavioral coverage; manual smoke at T018 in tasks.md exercises the real OAuth flow end-to-end. Spec body documents the future implementation path (Supabase admin API to flip app_metadata.provider + teardown). Refs: #28 Tasks: T003, T009, T013 (US-3 portion only β OAuth portions deferred) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #28.
Summary
OAuth users (Google/GitHub) now see ReAuthModal in setup mode when they first land on
/messageswithout encryption keys, instead of being redirected to the full-page form. The page at/messages/setupis preserved as a deep-link fallback. US-2 polish + provider badge + clearer "separate from your $provider login" subtext per wireframe 02.First feature to walk the v1.0.2 cascade as a hard gate end-to-end.
What changed
New helper β
src/lib/messaging/welcome/send-welcome-message.tsextracts the welcome-message dispatch fromapp/messages/setup/page.tsx:133-149so both modal-setup and page-setup share one implementation.ReAuthModal extension β
src/components/auth/ReAuthModal/ReAuthModal.tsxgrows amode: 'unlock' | 'setup'state. Mode is decided at open time bykeyManagementService.hasKeys()for OAuth users:initializeKeys, dispatches welcome messagederiveKeys(unchanged behavior)Provider badge ("Signed in via Google" / "Signed in via GitHub") renders in both modes when
isOAuthUser(user). Unlock copy for OAuth users now explicitly differentiates the messaging password from the OAuth login.EncryptionKeyGate β flips the no-keys redirect: OAuth users get
setNeedsReAuth(true)(modal opens in setup mode); email users still redirect to/messages/setupso the browser's password manager benefits from a real<form>context.Tests β 7 new unit tests (RED β GREEN per Constitution II), full unit suite stays at 3261/3261 green. New Playwright spec at
tests/e2e/messaging/oauth-setup-modal.spec.tsruns the US-3 email-user regression in CI; US-1/US-2 OAuth scenarios are.skip()'d pending an OAuth test fixture (documented inline).Cascade artifacts (constitution v1.0.2)
features/auth-oauth/013-oauth-messaging-password/spec.mdβ Clarifications session 2026-05-06 (5 QβA bullets), FR-018..022 addedfeatures/auth-oauth/013-oauth-messaging-password/plan.mdβ Constitution Check pass on all 6 principlesfeatures/auth-oauth/013-oauth-messaging-password/tasks.mdβ 19 tasks across 6 phasesfeatures/auth-oauth/013-oauth-messaging-password/analysis.mdβ FR-to-task traceability matrix, file-path alignment, all 6 categories PASSfeatures/auth-oauth/013-oauth-messaging-password/checklists/implementation-readiness.mdβ plan-readiness validationTest plan
Refs
/speckit.*cascade ran againstπ€ Generated with Claude Code