Commit Graph
10 Commits
Author SHA1 Message Date
Matthew Meszaros 1018068942 feat: stop recipient suppression and the entitlement gate being skipped when a campaign has no organization: the send path now fails closed (an orgless campaign is paused with the reason in its activity feed instead of mailing an unsubscribed, bounced or complained address, since routing's own suppression filter joins on the campaign's organization_id and matches nothing when it is NULL), the same tenancy gate covers warmup and unibox sends and an orgless mailbox resolves to the free pool rather than defaulting into the paid one, the state is no longer creatable (sequenceRepository.Create inherits organization_id from its campaign instead of inserting NULL, campaign creation and mailbox onboarding refuse without a workspace via errx.ErrNoOrganization, guardInboxLimit / guardMailboxThrottle / the campaign creation throttle no longer treat a missing org as exempt, and a new session resolves the user's default workspace so the orgless session that produced these rows cannot exist), and migration 000092 backfills then sets organization_id NOT NULL on campaigns, contacts, email_accounts and sequences plus sessions.current_organization_id, provisioning a recovery workspace for any user with none so no row is deleted to satisfy the constraint (live-tested in TestLiveOrglessCampaignDoesNotSendToSuppressedRecipient, TestLiveSuppressedRecipientIsSkipped, TestLiveCampaignRequiresAnOrganization and TestLiveHealthyCampaignStillSends) 2026-08-24 08:47:08 -07:00
Matthew Meszaros 5bcc2baaa8 feat: implement the coming-soon security features — logged-in change-password (verify current, policy-checked, POST /me/password) with a real dialog, and new-device sign-in alerts (security notification category fired from the token service on an unrecognized OS+browser, delivered in-app and by email), removing the comingSoon stub helper and updating docs 2026-06-11 12:30:44 +02:00
Matthew Meszaros 218af13dd9 feat: add session management
Add authenticated session listing and revocation APIs, track the auth provider on sessions, and expose active session controls in account security settings.
2026-06-01 05:53:49 +02:00
Matthew Meszaros 87f9bf58b0 feat: add Safari-ready passkey login
Add passkey enrollment and login wiring, including a Safari-safe explicit login path that prefetches the WebAuthn challenge before the click and calls the credential ceremony immediately from the user gesture.
2026-06-01 03:09:17 +02:00
Matthew Meszaros 17ce31a942 feat: extend dashboard session lifetime 2026-05-30 14:06:27 +00:00
Matthew Meszaros 8267458f4e fix(auth): invalidate cached session after refresh — was logging users out at 10 min
After /auth/refresh, Postgres got the new access + refresh nonces but
the Redis cached session still held the OLD ones. The next request:

  1. Frontend uses the new access token (new access_nonce in JWT)
  2. Backend ValidateAccessToken → GetSession → hits Redis cache
  3. Cached session has the OLD access_nonce
  4. session.AccessNonce != t.Nonce  → ErrToken (401)
  5. Frontend tries to refresh with the new refresh token
  6. RefreshToken → GetSession → again hits stale Redis
  7. sess.RefreshNonce (old) != t.Nonce (new)  → ErrToken
  8. Frontend clears tokens and bounces to /auth/login

The access token's 10-minute TTL was the trigger window because that's
when the first refresh fires. After the first refresh, the stale cache
poisoned every subsequent request.

Fix: delete the cached session after a successful repository update,
mirroring what SwitchOrganization already does for the same reason
(it updates current_organization_id in Postgres and then drops the
Redis copy). Next GetSession misses, re-reads from Postgres, caches
the fresh nonces.

The deleteSession failure path is intentionally swallowed — the
refresh already succeeded and we returned the new tokens, so worst
case is the next request triggers another refresh, not a logout.
2026-05-22 15:37:00 +00:00
Matthew Meszaros d8d88c7f69 feat: add warmup health tracking, migrate repos to postgres, and overhaul web UI 2026-04-03 06:08:52 +00:00
Matthew MeszarosandClaude Opus 4.6 fbb55379c5 fix: propagate captcha errors and fix JWT signing
- Return actual captcha verification errors instead of generic
  internal errors in login, registration, and reset password flows
- Fix Sentry capturing wrong variable (err -> xerr) in
  RegistrationConfirm
- Pass AuthSecret as []byte to JWT SignedString/keyfunc
- Send form data in request body instead of PostForm for Turnstile
- Improve Turnstile non-200 error handling with response body logging

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 06:30:50 +01:00
Máté Mészáros (Laptop) 6adb4cdd5a Organization, Subscription, Inqueries, limits. 2026-01-27 05:55:48 +01:00
Matthew Meszaros 772c19820d New Repository: Add Backend Code 2026-01-17 14:11:14 +00:00