Commit Graph

152 Commits

Author SHA1 Message Date
Matthew Meszaros 9d7e3aa61f feat: make scheduled sending self-healing - dispatch Cloud Tasks callbacks by the task row type (all enqueues share one webhook URL, so campaign callbacks were run through the warmup handler), cancel pending tasks stranded past their slot so the reconcilers re-seed chains after a lost callback or emulator restart, and cast the status enum in the two UPDATE ... CASE queries that failed parameter type deduction on every callback 2026-07-11 17:31:23 +02:00
Matthew Meszaros 167cc370b3 feat: re-key dedicated_worker_assignments to organizations (migration 000055) - the assignment service has always keyed by org id but the column carried a users FK, so every runtime bind failed with an FK violation and dedicated-plan orgs could never get a worker; renames the column, remaps seed rows, and updates the repository, admin filter, and convert-to-dedicated endpoint to org semantics 2026-07-11 17:31:23 +02:00
Matthew Meszaros 07a6777536 feat: email OAuth callback page gains a native-app fallback - when there is no web opener to postMessage (an ASWebAuthenticationSession has no popup parent) it redirects to warmbly://email-oauth with provider/code/state/error so the iOS app can finish the connect; web popup behavior is unchanged and the docs describe both delivery paths 2026-07-11 10:13:10 +02:00
Matthew Meszaros cc0871d1b8 feat: contacts search gains an additive lead_status filter plus per-status lead_counts on the first page when exactly one campaign_id is set - the SQL predicates reproduce the read-time status derivation exactly (unsubscribed > bounced > replied > active > pending via LATERAL bool_or rollups), invalid lead_status or multi-campaign combinations return 400, and the web types/table pick up the new lead_counts shape 2026-07-11 10:11:36 +02:00
Matthew Meszaros 3acb51df6c feat: add server-side status-bucket filtering to GET /campaigns (draft/active/paused/completed, paused matches every paused_* variant, invalid values 400) and a new GET /campaigns-overview endpoint returning status and per-folder counts, with the campaigns API reference and endpoint scope map updated 2026-07-07 09:40:27 +02:00
Matthew Meszaros 13f193d91e feat: unibox list filters - from now matches sender addresses by case-insensitive substring as documented, and a new uncategorized=true param returns only threads with no labels, documented in the unibox API reference 2026-07-07 05:56:47 +02:00
Matthew Meszaros a20ba926cb feat: add native Apple/Google sign-in to the backend - POST /auth/apple and /auth/google exchange provider-signed ID tokens for sessions, GET /auth/providers exposes configured providers for app discovery, with a JWKS-verifying idtoken package, auth config, stable error codes, and API/security docs 2026-07-07 05:56:35 +02:00
Matthew Meszaros d4ead05456 feat: persist campaign sequence canvas coordinates with x/y columns (migration 000053) plus a bulk sequence-layout service/repo path that scopes by campaign owner and never bumps updated_at 2026-06-30 10:06:20 +02:00
Matthew Meszaros 73838cecf5 feat: add an unaudited automation node-layout endpoint handler/service/repo backed by an atomic jsonb x/y merge that leaves edges, config, and updated_at untouched 2026-06-30 10:06:19 +02:00
Matthew Meszaros 5e94b945ff feat: add GetIdentity handler returning user, org, auth type, and granted scopes for GET /v1/me 2026-06-28 19:09:37 +02:00
Matthew Meszaros 9dd37b0d62 Merge pull request #52 from warmbly/referral-credits
feat: implement referral program with credit-based rewards
2026-06-28 09:12:57 +02:00
Matthew Meszaros 7e75394ab8 feat: decode the admin discount list and redemption cursors as opaque offset tokens, returning 400 on a malformed cursor instead of silently resetting to the first page 2026-06-28 05:58:25 +00:00
Matthew Meszaros 789da671d6 feat: send organization member invitations through GenerateInvitationHTML so they match the rest of the transactional mail 2026-06-28 05:27:18 +00:00
Matthew Meszaros 8bd3a1137e feat: expose the JWT referral and applied-discounts endpoints with handlers and manage_billing-gated routes 2026-06-28 05:09:50 +00:00
Matthew Meszaros 03acdb87e3 fix: thread organization_id through contact, CRM, and unibox reads and writes so non-owner org members see and edit their workspace data, and backfill contacts.organization_id for single-membership users (migration 000049) 2026-06-15 08:11:53 +02:00
Matthew Meszaros 9d0c432be7 feat: let OAuth apps subscribe to webhooks by declaring a url/events/secret and materializing per-org endpoints gated by each grant's scopes, with secret rotation and delivery observability (migration 000050) 2026-06-15 08:11:20 +02:00
Matthew Meszaros 173736a004 feat: add a Stripe-grade webhook platform with a typed event catalog, HMAC-signed delivery, retries with backoff, endpoint ownership verification, per-endpoint throttling, an audit-spine event bridge, and firehose emit sites (migration 000048) 2026-06-15 08:11:20 +02:00
Matthew Meszaros fcdb31cda7 feat: OAuth apps always issue a client secret (drop the public/PKCE-only client type, secret required for the token exchange), add an app-logo upload endpoint, and align the docs to OAuth2 with optional PKCE 2026-06-14 09:52:49 +02:00
Matthew Meszaros 8c175d4221 feat: add an OAuth 2.1 authorization server (migration 000047 apps/codes/grants, app registration CRUD, authorization-code-with-PKCE authorize+token+refresh-rotation+revoke endpoints, RFC 8414 discovery, bearer-token validation wired into the auth middleware reusing the API-permission gates, scopes mapped to API permission bits) 2026-06-13 13:56:39 +02:00
Matthew Meszaros 331745ecc5 feat: add a generic per-automation inbound webhook trigger (inbound.webhook event, token-gated POST /api/v1/integrations/inbound/automation/:token, migration 000046 inbound_token, background graph run with the JSON body as event payload) 2026-06-13 13:04:10 +02:00
Matthew Meszaros aed4a06190 feat: unify pagination by making the offset-based CRM deals/tasks search and meetings endpoints expose the same opaque next_cursor and {total, next_cursor, has_more} envelope as every keyset list (offset hidden inside the token), updating web clients, the OpenAPI spec, and the reference docs 2026-06-13 10:47:17 +02:00
Matthew Meszaros 57e8705a82 feat: make public API list cursors opaque base64 tokens (internal/utils/paging) instead of raw record UUIDs, decoding on input with a 400 on a bad cursor; admin endpoints keep transparent UUID cursors 2026-06-13 07:18:23 +02:00
Matthew Meszaros a7a43e0c4c feat: rename the campaign sequences resource to steps across the API and URL (/campaigns/:id/steps), the JSON fields (target_step_id, step_id/step_name/step_index, analytics steps[], create body steps), the web client/models/route segment/labels, the audit step entity type, and the wire-contract docs; internal Go type names and the Kafka avro schema stay 2026-06-12 09:38:11 +02:00
Matthew Meszaros 0fd3d03f55 feat: add org-wide team presence privacy columns (presence_show_online, presence_show_activity) with update plumbing and a PRESENCE_POLICY_UPDATED realtime event so a settings change re-gates connected sockets live 2026-06-12 05:59:01 +02:00
Matthew Meszaros 8547fe97eb feat: scope unibox MarkSeenBulk by organization so a non-owner member opening a thread clears the shared org-wide unread state instead of updating zero rows 2026-06-12 05:14:50 +02:00
Matthew Meszaros 4db027a342 feat: scope unibox GetByThread by organization instead of user_id so non-owner members see the full conversation they already see in the org-scoped inbox list, not an empty thread 2026-06-12 05:10:00 +02:00
Matthew Meszaros 6a3b8ac0eb fix: scope the unibox unread-count endpoint by organization_id so the sidebar Inbox badge counts the workspace's unread mail instead of always showing 0 for non-owner members 2026-06-11 18:05:18 +02:00
Matthew Meszaros 594c696bf6 fix: scope the unibox inbox list and overview by organization_id (via the workspace's email accounts) instead of the logged-in user_id, so every member sees the org's incoming mail; per-user thread labels and snoozes stay personal 2026-06-11 17:57:52 +02:00
Matthew Meszaros 21032a8fce fix: scope the contacts list by organization_id instead of user_id so all members see the workspace's contacts (and per-contact campaign badges); categories badge still user-scoped pending an organization_id column on categories 2026-06-11 17:52:36 +02:00
Matthew Meszaros 88e241d536 fix: scope the analytics dashboard (overall stats, recent activity, top campaigns, daily trend, account health) by organization_id instead of user_id, so every workspace member sees the org's analytics rather than an empty dashboard 2026-06-11 17:49:39 +02:00
Matthew Meszaros a21dc57e07 fix: scope campaign list/detail/count queries by organization_id instead of user_id, so all workspace members see the org's campaigns rather than only the creator 2026-06-11 17:47:04 +02:00
Matthew Meszaros 6ae5e52c4e fix: scope email-account list/detail queries by organization_id instead of the logged-in user_id, so every member of a workspace sees the org's mailboxes (not just the owner who connected them) 2026-06-11 17:43:56 +02:00
Matthew Meszaros 3c040649c0 fix: changing your password now revokes every other session (keeping the current device), matching the security promise in the sign-in alert and docs 2026-06-11 12:39:24 +02: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 39a9752d63 feat: real tokenized invite-accept link — public /invite landing page with safe preview (org, inviter, roles), accept-by-token plus the previously-broken accept-by-invitation-id, public preview + admin copy-link endpoints, login next-param redirect, and a Copy button that yields a working /invite?token link 2026-06-11 11:57:45 +02:00
Matthew Meszaros 19f66507b4 feat: fix multi-role review findings — atomic member+roles insert on invite accept (no partial-failure stranding), gate role deletion on the actor holding the role's permissions (blocks team-managers de-privileging admins), and hydrate+chip pending-invitation role sets 2026-06-11 11:32:57 +02:00
Matthew Meszaros 3473d09bcc feat: fix review findings in the roles redesign — GetMembers role_id column (members endpoint 500), TransferOwnership role_id hygiene, accept-time role re-resolution, race-free in-use delete guard covering invitations, assignment anti-escalation with self-role-change block, canManage-gated members UI, colored RolePills, fresh currentOrganization on refetch, dev JWT_SECRET wiring for make realtime, docs corrections 2026-06-11 10:45:21 +02:00
Matthew Meszaros edd4524007 feat: custom organization roles backend (organization_roles table with write-through member propagation, CRUD endpoints with anti-escalation and in-use guards, custom-role invites and assignment via role_id, audited as role entity) 2026-06-11 09:39:52 +02:00
Matthew Meszaros 8732805934 feat: replace signed click redirects with server-side link tickets (tracked_links store, internal resolver API, opaque /c/<id> URLs, layered anti-probe caches with miss budget and circuit breaker) removing TRACKING_LINK_SECRET entirely 2026-06-11 09:30:21 +02:00
Matthew Meszaros fe96eff7b4 feat: audit-log coverage for teams, automations (typed entity), lead-sync sources, and manual meetings so the org activity trail and its realtime spine see every mutation 2026-06-11 07:47:29 +02:00
Matthew Meszaros a6acb97dea feat: key the worker-facing internal DEK endpoint by organization
The /api/v1/internal/dek route parameter is now :orgID to match the
org-scoped encryptedkeys store. Workers fetch the organization DEK for
the account they are operating on instead of a user DEK.
2026-06-10 17:16:07 +02:00
Matthew Meszaros 5954ac53c2 feat: add automation execution safeguards
Support chained automation execution from native actions, guard automation recursion depth, carry idempotency context through campaign-launched automations, allow team task assignment in backend action execution, and reject deletes while campaign steps still reference an automation.
2026-06-09 10:56:56 +02:00
Matthew Meszaros b2c5117eca feat: preview campaign templates
Adds the shared template helper function map, send-path spintax expansion, server-side template preview validation, and the campaign template preview endpoint.
2026-06-08 15:04:53 +02:00
Matthew Meszaros 4013b33008 feat: expose security notification APIs
Wires notification and two-factor services into the backend and consumer, adds the authenticated notification feed/preferences endpoints, and exposes the public 2FA login verification endpoint.
2026-06-08 15:04:47 +02:00
Matthew Meszaros 5f7ac801ba feat: execute automation graphs 2026-06-08 12:03:11 +02:00
Matthew Meszaros b28fc9e957 feat: expose automation APIs 2026-06-08 06:55:11 +02:00
Matthew Meszaros e6b2f233a1 feat: expand integration and meeting APIs 2026-06-08 06:25:40 +02:00
Matthew Meszaros 8773b7f7f3 feat: push contacts to integrations 2026-06-07 20:30:52 +02:00
Matthew Meszaros 051ae73fd2 feat: resolve named sender contacts 2026-06-07 07:54:02 +02:00
Matthew Meszaros 5f3940602f feat: add CRM task search summaries 2026-06-07 07:04:16 +02:00