Skip to content

Refactor: Auth Architecture Overhaul — CookieJar + State Machine + Threading (A+B+C+E) #20

Description

@diegohb

Problem Statement

The auth path has accumulated 5 uncoordinated cookie-jar writers, 10+ implicit state machine transitions, and scattered conversation-threading logic across 4 files. Every fix in the phantom-auth saga (v2.6.0–v2.7.0) added a new branch to the implicit state machine, and 4 of 10 fixes touched jar-writer logic — each with a different merge strategy.

The RotateCookies 401 session-kill fix is the first fix that UNDOES a previous fix — confirming the rotation apparatus was over-engineered. Comparison with v2.4.0 (which still works in production with 12-day-old sessions) shows that the RotateCookies + phantom detection + targeted L2 layers were built on the false premise that the jar was complete.

An alternate plan to remove these layers entirely is documented at docs/alternate-plan-simplify.md. This issue covers the active plan: keep the layers but make the architecture explicit.

See architecture review v5 at Temp folder.

Solution

  1. Candidate A — CookieJar unification: Replace 5 uncoordinated jar writers with one CookieJar module (replace/upsert policies).
  2. Candidate C — Explicit state machine: Split ensureAuthenticated into classifySession (5 states) and recover.
  3. Candidate B — Conversation threading: Deep module for cid/rid/rcid indexing.
  4. Candidate E — Post-call seam: Consolidate persistRefreshedCookies 8 call sites to one hook.

Commits

Phase 1: Merge prerequisite

  1. Merge fix/rotate-cookies-401-session-kill → main (4 commits, 954/1/0)

Phase 2: Candidate A — CookieJar (8 commits)

  1. Create cookie-jar.ts — replace/upsert, keyed by (name, domain, path)
  2. Wire CookieMonitor capture → CookieJar.replace()
  3. Wire persistRefreshedCookies → CookieJar.upsert()
  4. Wire L1 rotateCookies → CookieJar.upsert()
  5. Wire targeted silentRefresh → CookieJar.upsert()
  6. Wire full silentRefresh → CookieJar.upsert()
  7. Remove mergeCookies standalone function
  8. Integration tests for CookieJar pipeline

Phase 3: Candidate C — State machine (4 commits)

  1. Extract classifySession() with 5 states (Fresh/Phantom/Dead/Stale/Declined)
  2. Extract getRecoveryAction() policy function
  3. Wire into ensureAuthenticated
  4. Integration tests for state machine wiring

Phase 4: Candidate B — Conversation threading (4 commits)

  1. Create ConversationThreading module (threadOnto + captureFrom)
  2. Wire threadOnto into sendMessage
  3. Wire captureFrom into fetchChat/seedMetadataFromChat
  4. Remove raw metadata extraction from seedMetadataFromChat

Phase 5: Candidate E — Post-call seam (1-2 commits)

  1. Consolidate persistRefreshedCookies to one post-call hook
  2. Final verification (954+/1/0, typecheck, openspec validate)

Decision Document

  • CookieJar has two policies (replace/upsert), not five. Callers filter.
  • State machine is two pure functions (classification + recovery), independently testable.
  • ConversationThreading is pure transformations. Magic indices in one file.
  • CookieJar delegates to CookieStorageService (doesn't bypass to CookieStorage directly).
  • RotateCookies 401 → Declined state, not Dead state.
  • upsert key is (name, domain, path).

Testing Decisions

  • Test external behavior, not implementation
  • New unit tests for CookieJar, classifySession, getRecoveryAction, ConversationThreading
  • Integration tests using gimme helper pattern from phantom-auth.test.ts
  • Existing 954 tests must stay GREEN on every commit
  • Phase 0 v2 regression net (10 tests) is the safety net

Out of Scope

  • Candidate D (probe consolidation) — deferred
  • Removing RotateCookies/phantom detection — alternate plan in docs/alternate-plan-simplify.md
  • Background daemon / gemiterm watch
  • Profile-aware factory wiring full refactor
  • CI gating
  • Live verification (user-driven)

Further Notes

  • Baseline: 954/1/0 (2031 expects). Must not regress.
  • Branch: overhaul/auth-architecture off main after merging 401 fix.
  • Fallback: docs/alternate-plan-simplify.md if state machine proves too complex.
  • Related: docs/phantom-bug-synthesis.md, docs/phase-0/phase-0-v2-design.md

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions