feat(extension): batched data sync with retry (Week 2 AC 5)#10
Merged
Conversation
Verifies Bearer token via JWT_SECRET, checks session ownership on POST.
POST creates a session for the authenticated user. PATCH /:id sets endedAt, scoped to the user's own sessions.
…retry Adds dbSessionId to local Session, fire-and-forget POST /api/v1/sessions on start and PATCH on stop. Failures left for sync alarm to retry.
PageMetadata flattens to content via metaDescription + headings. Notes get worktrace://note/<uuid> URL so z.url() passes without schema changes.
Every 30s a chrome.alarms tick flushes up to 50 queued events. Final flush also fires on SESSION_STOP. 4xx drops poison events, 401 stops until re-login, network and 5xx keep the queue for the next tick.
Adds a SYNC_GET_STATUS message that returns lastSyncedAt, lastError and queueSize. Popup renders a second line under the queue count showing time since last sync or the error message.
Two lockfiles (root husky/lint-staged and dashboard) made Turbopack infer the repo root as workspace root, watching extension and unrelated paths and slowing dev. Setting turbopack.root scopes the watcher.
AUTH_GET_STATUS now returns the email decoded from the JWT payload. Popup renders it under the logo while authenticated, hides on logout.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
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.
What
Closes Week 2 AC 5: extension batches captured events and notes, POSTs them to
/api/v1/eventsevery 30s with retry on network/5xx, plus immediate flush on session stop. Also closes Gaps 2/3/4 from the AC 2+3 plan (DB-side sessions API, normalized payload shape, note URL).Changes
Code
dashboard/server/jwt.ts— newrequireUser(req)helper that verifies the Bearer token viaJWT_SECRETand throwsUnauthorizedErroron missing/invalid token.dashboard/app/api/v1/events/route.ts— now callsrequireUserandcreateEventForUser, which checksSession.userIdmatches the token's user.dashboard/app/api/v1/sessions/route.tsanddashboard/app/api/v1/sessions/[id]/route.ts— newPOST(creates a Session for the authenticated user) andPATCH /:id(setsendedAt, scoped to owner).dashboard/server/sessions.ts+dashboard/server/schemas/sessions.ts— DB layer + Zod for the session id path param.extension/src/types/session.ts,pending.ts,sync.ts— addsSession.dbSessionId, wire-shapePendingEvent, andSYNC_GET_STATUSmessage.extension/src/background/session.ts— addsattachDbSessionId(id)helper.extension/src/background/sync.ts— new module: alarm registration,flush()with per-event POST loop,getStatus().extension/src/background/index.ts—SESSION_STARTtriggers DB-session create;SESSION_STOPdoes a final flush before clearing;PAGE_METADATA/NOTE_ADDnow normalize payload at enqueue;AUTH_GET_STATUSreturns the email decoded from the JWT.extension/src/popup/— email line under the logo, second-row sync status ("synced Xs ago" or "error: …").Tooling / config
extension/src/manifest.ts— adds"alarms"permission (silent in Chrome's permission UI).dashboard/next.config.ts— pinsturbopack.rootto thedashboard/directory so the dev watcher does not crawl the whole monorepo (two lockfiles were forcing inference to the repo root).Docs / plan
plans/week2/AC5-data-sync.md— full design rationale, commit order, and verification checklist.Design decisions
/api/v1/sessionsand/api/v1/events— without it, sessions endpoints would allow creating sessions for arbitraryuserId, and the events route would accept anything from a Chrome-extension Origin. Formally bleeds into Week 3 AC 1, but the alternative is leaving a write-anything hole open for two weeks.worktrace://note/<uuid>— keepsCreateEventInput.url = z.url()strict (custom schemes are valid URLs) and avoids a Prisma migration to makeurlnullable.contentflattens at enqueue, not at flush —[metaDescription, ...headings].filter(Boolean).join(" | "). One canonical shape inpendingEvents; sync just attachessessionId.chrome.alarms+ final flush on stop, no in-batch retries — the next alarm IS the backoff. Simpler than per-event timers; the service worker can be killed between ticks without losing state because the queue lives inchrome.storage.local.See
plans/week2/AC5-data-sync.mdfor full reasoning.Verification
npx tsc --noEmit(dashboard) — cleannpm run lint(dashboard) — clean (via lint-staged on each commit)npm run build(extension) — cleanpendingEventswith the right shape, triggered flush, verified Events in DB with the correctsessionId. Added a note → arrived withurl: worktrace://note/<uuid>and tagnote. Email shown under the logo while authenticated, hides on logout.Out of scope (future PRs)
middleware.tsfor/dashboard/*— Week 3 AC 1.POST /api/v1/eventsaccepting an array) — current per-event POST in batches of 50 is enough for MVP.Trackendpoint — Week 2 bonus AC 6.plans/backlog/email-password-auth.md, explicitly post-Week 3.keyso Google OAuth redirect URI stays stable across machines.Closes
docs/Task.md(AC 5 section)plans/week2/AC2-AC3-content-sessions.md