Skip to content

Tracer A: user_activity_day capture — live unflagged write in Pasaport.validateSession #7029

Description

@usirin

Stories: 3
TDD: yes
Containment: exempt (founder ruling R1.2 on #7028, 2026-08-23: capture ships live on deploy, no flag — activity days are forward-only and cannot be backfilled)

What to build

The visit-return data seam of epic #6767: one append-only D1 table user_activity_day (user_id, day, PRIMARY KEY (user_id, day)) and one memoized upsert wired at the end of Pasaport.validateSession (apps/web/worker/features/pasaport/Pasaport.ts, the success path where session?.user resolves).

  • Schema export in apps/web/worker/db/drizzle/schema.ts plus migration numbered off the existing sequence in apps/web/worker/db/drizzle/migrations/.
  • On each validated session: compute today's UTC day bucket, check an isolate-local memo (user_id → day), skip when already touched today, else upsert ON CONFLICT DO NOTHING and record the memo. The memo is load-bearing — this sits on the hottest path in the worker and must cost ~one D1 write per active user per day, never per request.
  • Any failure of the capture is caught, logged through the existing worker error pipeline (Effect.logError, surfaced to Sentry), and swallowed: the capture never fails a login.
  • No flag, no config surface — live on deploy per founder ruling R1.2 (Week-1 survival cohort funnel on /funnel #7028).

Acceptance criteria

  • a validated session for user X on day N produces exactly one user_activity_day (X, N) row, and repeated same-isolate validations that day produce no further writes
  • the upsert builder is .toSQL()-asserted with no engine, carrying ON CONFLICT DO NOTHING
  • an injected capture failure leaves validateSession returning the session unchanged, with the error visible on the worker error pipeline
  • no feature flag or gate stands between a deployed worker and the capture write

Metadata

Metadata

Assignees

No one assigned

    Labels

    p0Highest priorityready-for:agentAn execution engine may pick this up.status:awaiting-releasePost-merge release-queue marker: deployed dark, awaiting a human flag flip (ADR 0083).status:plannedplan-epic child: planned, not yet verified by review-plan, not pickabletype:featureNew capability, directly implementable

    Type

    No type

    Projects

    Status
    Done

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions