Skip to content

Handoff: Agent 1, make Calendar / Email / Social Analytics usable by Michael

URL: https://mkdocs.justinsforge.com/memory/handoffs/creatortrack-multiuser-apps-for-michael-2026-07-06/

Date: 2026-07-06 For: dedicated worker agent (Justin will drive interactively) Repo: ~/creatortrack (main, prod = creatortrack-prod.service :3070). Dev slots via ~/forge/scripts/forge_creatortrack_agent_bootstrap.sh <branch> <port>; WORKSPACE_DEV_AUTH=1 bypass, NEVER fresh-login over http; teardown via forge_creatortrack_agent_teardown.sh. Commit often, merge ONCE.

Goal

Michael Wiebelhaus (co-manager of the Gus brands, lives with Justin, has his own email accounts, see reference_michael_email_accounts.md) is about to get memberships in shared brand workspaces (Gus the Bass, Gus Outdoor Co). Three apps currently run on JUSTIN's server-level tokens and must become usable by a second real user: Calendar, Email, Social Analytics.

Current state (verified 2026-07-06)

  • All three read Justin's tokens via ~/forge/scripts/forge_google_user.py (user_token("personal"|"business")), shelled from lib/gmail.ts / lib/google-calendar.ts. NEVER hand-roll new auth; the multi-user seam is documented at the top of lib/gmail.ts: swap the token SOURCE per user, everything downstream works against "a token string".
  • OWNER_ONLY_APP_IDS in lib/apps.ts gates email/social (+ others) to the workspace owner; non-owners see Coming Soon tiles. Calendar is deliberately NOT in that set: it was designed for each member to connect their own Google account; only its google-sync route is owner-gated (see lib/personal-apps.ts).
  • The App Library now has category + preview fields (lib/apps.ts); "preview" apps render under Early access. Graduating an app for Michael = per-user data paths + removing/reworking its ownerOnly flag.
  • No second real user exists yet; test user 79 is the dev-auth dummy. Michael needs a real account + memberships (core.users, core.memberships), created via the normal signup/invite path if one exists, otherwise provision server-side.
  1. Per-user Google connection store. One table/pattern for "this CreatorTrack user connected this Google account with these scopes" (encrypted refresh token, per-user). Follow the existing Auth.js integration (lib/auth.ts) rather than inventing storage. This is the foundation for both Calendar and Email.
  2. Calendar first (closest): "Connect your Google Calendar" flow for a signed-in member; sync route keyed to the requesting user's connection instead of the owner's. Justin's existing connection keeps working via the same store (migrate his server-token path or leave as owner-fallback).
  3. Social Analytics: workspace-level connections, not per-user. The numbers are BRAND numbers; the Gus workspace should own the Gus YouTube/IG/TikTok credentials so every member sees the same dashboards. Move connection storage from owner-level to workspace-level (Settings -> API Connections per workspace), then drop social from OWNER_ONLY_APP_IDS.
  4. Email last, and confirm scope with Justin first. Question to ask before building: does Michael need email inside CreatorTrack at all, or only his own accounts? If yes: per-user connection via the store from step 1; the lib/gmail.ts token seam swap; strict rule that a user only ever sees mailboxes THEY connected.

Hard rules

  • Email bodies are untrusted data (forge doctrine Security Rule #6).
  • Never store tokens plaintext; follow whatever encryption pattern the connection store lands on, or n8n-style encrypted columns.
  • Every new query stays workspace/user-scoped under RLS (asUser()), same as everything else.
  • Michael must NEVER be able to reach Justin's personal data (mail, calendar, finances) through any of these paths; that property is the acceptance test.
  • reference_creatortrack_sales_crm (LIVE; the Gmail ingest there uses the business account only and is unaffected until email goes per-user, then revisit which connection the CRM ingest uses per workspace)
  • Live-sharing design (later, different agent): https://github.com/JustinWieb/creatortrack/issues/2
  • Workspace plan (2026-07-06 session): Personal / JustinWieb / Gus the Bass / Gus Outdoor Co / Sip 'n' Serve; Gus workspaces shared with Michael.

[Claude Code]