xtablo-source/.planning/research/STACK.md

3.8 KiB

v2.0 Research: Stack Additions

Date: 2026-05-15 Scope: Native per-tablo chat, etapes, Google/Apple sign-in, individual planning, tablo events.

Existing Stack

  • Go 1.26 module in backend/
  • chi router, gorilla/csrf, server-managed sessions
  • templ + HTMX + Tailwind
  • Postgres via pgx + sqlc + goose migrations
  • River worker already installed for background jobs
  • Single container / VPS-oriented deploy

Social sign-in

  • Add golang.org/x/oauth2 for OAuth2 authorization-code exchange and state handling helpers.
  • Add a small internal OIDC/JWT verifier package rather than a managed auth platform.
  • Store external identities in Postgres with provider, provider subject, verified email, and linked user ID.
  • Keep existing session issuance path: after provider verification, create or find a local users row, then create a local sessions row and cookie.

Google sign-in

  • Use Google's OpenID Connect server flow.
  • Required provider setup: Google Cloud OAuth client ID/secret and registered redirect URI.
  • Required runtime config: GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, GOOGLE_REDIRECT_URL.
  • Verify ID token claims before linking:
    • issuer is Google
    • audience equals configured client ID
    • subject is stable provider identity
    • email is present and verified

Sources:

Apple sign-in

  • Use Apple's web OAuth/REST flow.
  • Required provider setup: Apple Services ID, Team ID, Key ID, private key, redirect URI.
  • Required runtime config: APPLE_CLIENT_ID, APPLE_TEAM_ID, APPLE_KEY_ID, APPLE_PRIVATE_KEY, APPLE_REDIRECT_URL.
  • Generate Apple's client_secret as an ES256 JWT server-side; cache it until near expiration.
  • Exchange authorization code at POST https://appleid.apple.com/auth/token.
  • Verify Apple's ID token with Apple's public keys and persist provider subject. Treat Apple email/name as first-login-only data.

Sources:

Real-time chat

Two viable options:

  • SSE receive + normal POST send:

    • Best fit for HTMX/server-rendered UI.
    • Browser opens a per-tablo event stream; messages are posted with normal forms/HTMX.
    • Easier auth/CSRF story because writes remain HTTP POSTs.
    • One-way stream is enough for "new messages appear in real time".
  • WebSocket:

    • Best if the same connection must both send and receive messages.
    • Requires explicit message protocol, origin checks, backpressure decisions, and CSRF-equivalent protection on upgrade.

Recommendation for v2: implement SSE for receive and HTMX POST for send. It satisfies "real time" without bringing in a managed chat vendor or forcing a larger client-side app model. Revisit WebSockets only if typing indicators, presence, or very high-frequency bidirectional events become requirements.

Sources:

Avoid

  • No Stream Chat, Ably, Pusher, Firebase, Supabase Realtime, or managed chat/realtime services.
  • No Clerk/Auth0/Lucia. Google and Apple should only verify identity; Xtablo still owns account rows and sessions.
  • No recursive task hierarchy. Etapes are a one-level grouping table, not nested tasks.