Commit Graph
166 Commits
Author SHA1 Message Date
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 ab3c925eca feat: detect permanent NDRs worker-side from the synced bounce body across gmail/graph/imap and emit an INBOUND_BOUNCE event, giving api-sent mail its only bounce signal without adding SQL or S3 to the worker 2026-07-04 11:36:47 +02:00
Matthew Meszaros 3738f17643 feat: make warmup read engagement heavy-tailed up to an hour instead of uniform within four minutes and defer read/star/important actions into the recipient's waking hours so no pool mailbox reads mail at 3am 2026-07-04 11:27:36 +02:00
Matthew Meszaros 4c0da59763 feat: categorize Graph warmup mail by surfacing the verify token into flags and filing it into the Warmbly folder, re-resolving the live message id from the immutable RFC Message-ID so post-move engagement actions never act on a stale id 2026-07-04 08:07:50 +02:00
Matthew Meszaros 049d751a11 feat: route the outlook provider through Microsoft Graph in the wmail worker with nil-guarded send/sync/new-email dispatch and a delta-cursor event, request delegated Graph OAuth scopes instead of the legacy IMAP/SMTP scopes, and always sync Outlook mailboxes 2026-07-04 08:07:49 +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 5377374816 feat: add Identity model for the GET /v1/me caller-identity response shape 2026-06-28 19:09:37 +02:00
Matthew Meszaros 56fce77b0a feat: swap the admin discount search's query-bound UUID cursor for a handler-decoded Offset so the discount list's wire cursor stays opaque 2026-06-28 05:58:25 +00:00
Matthew Meszaros a21f4d0d0e feat: capture the signup referral code through the auth registration flow and the WireReferral attributor hook 2026-06-28 05:09:50 +00:00
Matthew Meszaros 6996588cb4 feat: add referral domain models, Plan month-equivalent and reward-cents helpers, and the referral and referral_credit audit entity types in internal/models 2026-06-28 05:09:50 +00:00
Matthew Meszaros c5dfa5e4e7 feat: remove the HTTP-request action from campaign steps and automations in favor of signed webhooks, keep fire_event for custom payloads, and drop the now-unused outbound quota plumbing 2026-06-15 08:11:35 +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 fcafac4195 refactor: remove the campaign 'notify (webhook)' step type now that the HTTP request step covers outbound calls and there is no webhook setup surface 2026-06-14 10:48:06 +02:00
Matthew Meszaros ab24d8bbc8 feat: add a 'Fire event' action and campaign step that publish custom events to the realtime gateway (no public URL), an HTTP-request campaign step, a configurable automation dry-run test with per-step toggles, and fix the false 'updated by a teammate' toast on your own save 2026-06-14 09:52:49 +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 534928cfdd feat: add a safe Set-variables (transform) automation node — computes named values from Go templates against the event + prior step output and writes them back for later steps to reuse, running the same sandboxed text/template engine as every other action value (no I/O, no arbitrary code execution) 2026-06-13 12:18:45 +02:00
Matthew Meszaros f4a2b87c50 feat: add a configurable warmbly.http_request automation action (the generic send-a-webhook/call-any-API node) — templated method/url/headers/query/body, SSRF-guarded + bounded retry, captures the response back into the event data under an output key so downstream nodes use {{.response.body...}} and conditions branch on {{.response.ok}} 2026-06-13 12:02:11 +02:00
Matthew Meszaros 3c7c0b6411 fix: finish the opaque-cursor doc sweep — change the offset query params to cursor on the CRM search operations in the OpenAPI spec, and drop the dead SearchContacts.Offset field and its docs (clamped but never used in SQL) 2026-06-13 11:00:59 +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 4762256c49 feat: add the warmbly.label_email native action type and the label_ids action config field across the campaign ActionConfig and the IntegrationAction enum + IsNativeAction 2026-06-12 16:44:07 +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 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 160dc0bc76 feat: implement the coming-soon notification delivery channels — Email (SES/SMTP to the account email) and Slack (posts to the org's connected workspace via a new integration NotifySlack), wired in both backend and consumer with per-channel gating, real toggles replacing the coming-soon labels, and updated docs 2026-06-11 12:21:48 +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 8540f7db15 feat: members can hold multiple roles — join tables for member/invitation role sets (migration 000044) with effective permissions as the bitwise OR recomputed on every assignment and role edit/delete, role_ids in invite/update APIs, multi-select checkbox role picker with colored chips in roster and invite flow, freely deletable roles 2026-06-11 11:24:19 +02:00
Matthew Meszaros 091b39f34e feat: roles become workspace data — seed editable Admin/Manager/Viewer rows per org (migration 000043 with member backfill), require role_id for invites and role changes, add role colors with a shared colored RoleSelect dropdown in the roster and invite flow, and rebuild Roles & access around real roles with an Owner reference column 2026-06-11 10:18:45 +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 014cbe79fa feat: label machine opens (Apple MPP prefetch, UA-less fetchers) with human-open upgrade semantics, exclude them from open-triggered automations, and surface the auto-open count in workspace and campaign analytics (migration 000040) 2026-06-11 08:33:09 +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 ae0c433084 feat: seal mailbox validation credentials with the organization DEK
SMTP/IMAP passwords on the validation round-trip are now encrypted and
decrypted under the organization DEK, carried as OrgID on
EventWorkerEmailValidation. Onboarding requires an organization before
a mailbox can be validated.

This fixes a latent key mismatch: the payload never set UserID, so the
worker decrypted with the zero-UUID platform key while the backend had
encrypted with the user key.
2026-06-10 17:16:56 +02:00
Matthew Meszaros ac3c11bf9a feat: seal outbound email content with the organization DEK
The send pipeline (publisher subject/body encryption, the S3 emsg blob,
and the worker-side decrypt) now keys off models.SendEmail.OrgID
instead of UserID. EmailMessage loses its UserID field entirely:
emailSender.Send derives the cipher identity from the email account's
OrganizationID and refuses to send for an account without one.

This also fixes two latent bugs. Emails sent through user_email_task
never set UserID, so they were silently encrypted under the zero-UUID
platform key. campaign_task's discarded Encrypt() pair is replaced with
an explicit DEK warm that fails fast when KMS is unavailable.
2026-06-10 17:16:42 +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 3eb96e33a1 feat: support automation expressions
Adds free-form expression conditions for automation graph branches and shares template helper functions with automation action rendering.
2026-06-08 15:04:59 +02:00
Matthew Meszaros c40a83c22d feat: add two factor auth core
Adds TOTP enrollment state, sealed secrets, recovery codes, pending login challenges, and the auth-service login gate for users with 2FA enabled.
2026-06-08 15:04:36 +02:00
Matthew Meszaros e67ee189a2 feat: add in-app notification core
Adds the persisted notification feed, user preferences, realtime notification events, and advanced-service notification hooks for replies and deliverability health events.
2026-06-08 15:04:29 +02:00
Matthew Meszaros ad7c87acca feat: expand deliverability metrics 2026-06-08 12:03:23 +02:00
Matthew Meszaros 5f7ac801ba feat: execute automation graphs 2026-06-08 12:03:11 +02:00
Matthew Meszaros 1199a17f7e feat: add automation persistence 2026-06-08 06:55:07 +02:00
Matthew Meszaros e6b2f233a1 feat: expand integration and meeting APIs 2026-06-08 06:25:40 +02:00
Matthew Meszaros c724ba59ec feat: expose integration action metadata 2026-06-07 20:30:41 +02:00
Matthew Meszaros fcef5008c4 feat: add CRM task team assignment 2026-06-07 19:32:37 +02:00