3.8 KiB
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
Recommended Additions
Social sign-in
- Add
golang.org/x/oauth2for 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
usersrow, then create a localsessionsrow 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:
- Google OIDC docs: https://developers.google.com/identity/openid-connect/openid-connect
- Google OAuth web-server docs: https://developers.google.com/identity/protocols/oauth2/web-server
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_secretas 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:
- Apple token validation: https://developer.apple.com/documentation/SigninwithAppleRESTAPI/Generate-and-validate-tokens
- Apple authorization request: https://developer.apple.com/documentation/signinwithapplerestapi/request-an-authorization-to-the-sign-in-with-apple-server.
- Apple client secret creation: https://developer.apple.com/documentation/accountorganizationaldatasharing/creating-a-client-secret
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:
- MDN SSE guide: https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events
- MDN WebSocket API: https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API
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.