Matthew Meszaros
|
bb4156cc6a
|
feat: add resource-scoped member access that restricts a member to selected campaign folders, campaigns and mailboxes read-only, enforced in the API route gate, SQL filters, permission trigger, realtime channels and dashboard
|
2026-10-09 13:34:05 +02:00 |
|
 Matthew MeszarosandDevin AI
|
b4ef37fe82
|
feat: restore existing self-host realtime connections through normalized legacy gateway URLs and an authenticated API-origin WebSocket proxy, preserve ticket-bound client IP limits and direct retry fallback, and remember workspace mailbox tag filters across navigation with deterministic default account grouping
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
2026-10-08 06:57:48 +00:00 |
|
Matthew Meszaros
|
8cb5893e37
|
feat: keep accepting API keys and OAuth tokens in the realtime socket URL as a deprecated fallback for existing clients, preferring the x-warmbly-token header and keeping the value out of logs
|
2026-10-04 05:20:20 -07:00 |
|
Matthew Meszaros
|
3a2d80b8bf
|
feat: accept realtime API keys and OAuth tokens only in the x-warmbly-token handshake header with the ws ticket alone in the query string, filter token and key params from Phoenix connect logs, refuse realtime keys, OAuth tokens and pool link tokens held by a login-banned user or a suspended app with an uncached key check, and send the key as a header from warmbly events tail
|
2026-10-04 02:56:18 -07:00 |
|
Matthew Meszaros
|
1b45c630bb
|
feat: end a removed member's sessions and OAuth app grants through a removal hook detached from the request, refuse OAuth tokens whose holder is no longer a member, clear and detach a session selection that outlived its membership, gate subscription checkout, portal and cancel on manage_billing in the API and the dashboard, re-read org channel permissions live on member, role and ownership changes and withhold gated events while they cannot be read, drop the unrouted GitHub releases webhook handler, and correct v1 and release trigger paths in the docs
|
2026-09-26 22:07:54 -07:00 |
|
Matthew Meszaros
|
7f324a38ac
|
feat: open inbox placement tests to workspaces with probes rendered like the campaign send and paced as placement tasks, Message-ID matching instead of a subject token and warmup header, instance, workspace and Warmbly Cloud seed panels, a tracking comparison, scheduled campaign monitors with alerts and optional auto-pause, monthly allowances, realtime updates and org transfer registration
|
2026-09-25 20:48:15 -07:00 |
|
Matthew Meszaros
|
e58921484d
|
feat: rebuild mailbox import around column mapping and automatic host and sign-in detection (CSV, XLSX, pasted lists, saved mappings, retryable rows with fixes, migrations 000205-000206), connect whole Google Workspace domains and Microsoft 365 organizations through a proved administrator grant, import from inbox vendors (InboxKit, Zapmail, Mailforge, Infraforge, Maildoso, Cheap Inboxes, ScaledMail) with vendor-managed forwarding and DNS, add a sending domains page with per-domain tracking and verified root redirects, unify Add account into one Google and one Microsoft entry with per-method choices, mark per-mailbox Google sign-in as retiring with in-place moves to the admin grant or an app password, allow the loopback security mode in the credential columns (migration 000207), read semicolon-separated CSVs, and add a mock vendor API to the sandbox
|
2026-09-23 08:41:01 -07:00 |
|
Matthew Meszaros
|
e668a2a36b
|
feat: complete the ADA CASA v2.1.1 AL1 control set across authentication, sessions, access control, cryptography, input validation and configuration, adding a breached-password denylist and per-account login throttling, enforced multi-factor authentication on the admin panel, step-up confirmation before an action that mints a lasting credential, purpose-scoped session tokens, single-use TOTP steps, tenant verification on every cross-referenced identifier, security headers on every surface, encrypted webhook signing secrets, per-organization idempotency, PKCE and a minimal two-scope Gmail consent on the mailbox OAuth flow, bounded spreadsheet and archive decoding, a patched Go toolchain with govulncheck in CI, and the evidence pack under compliance/casa
|
2026-09-19 08:18:35 +02:00 |
|
Matthew Meszaros
|
8745dd988d
|
feat: correct direct-mail analytics attribution and publish live engagement updates
|
2026-09-17 04:27:00 -07:00 |
|
Matthew Meszaros
|
60c9e316d9
|
feat: hosted lead-capture forms end to end: drag-and-drop builder with field settings, design panel, embed/share and submissions tabs in the dashboard, a public TanStack form app (forms/) served by the new standalone forms service (cmd/forms + internal/formserver) on FORMS_DOMAIN with per-form frame-ancestors CSP, honeypot/fill-time/Turnstile/per-IP submit protection and a same-origin JSON API proxying the backend internal API, form submissions creating contacts with categories and campaign enrollment plus realtime, audit, webhook and org-transfer coverage, migration 000114, seed forms, CI jobs, Dockerfile, systemd/nginx/compose manifests and docs
|
2026-09-01 01:17:51 -07:00 |
|
Matthew Meszaros
|
27630eec0a
|
feat: add website visitor tracking for issue #255 with migration 000106 (website_tracking_settings, website_visitors, website_page_hits, all registered in the orgtransfer spec), a consent-gated dependency-free tracking.js served by the Rust tracking service with a rate-limited, size-capped, prefetch-filtered POST /p ingest that forwards to a new backend internal page-hits endpoint for server-side user-agent and GeoIP enrichment, contact identification only through the click ticket the redirect appends to registered hosts, a per-workspace retention job, page_hit events with an expandable detail view in the contact Activity timeline, a Settings > Website tracking page for the snippet and consent, location and retention configuration, realtime PAGE_HIT fanout, and a website tracking guide plus endpoint, export and configuration docs
|
2026-08-29 03:25:50 -07:00 |
|
Matthew Meszaros
|
42ddb78e60
|
feat: make the realtime service survive a client that spams channel joins, and stop both clients from being that client: ws_join is now spent per phx_join in a shared RealtimeWeb.ChannelGuard that every channel runs BEFORE its Auth lookup (it was only ever spent on the socket handshake, so an established socket could issue unlimited joins and each one cost a Postgres query), handshakes move to their own ws_connect bucket so a reconnect storm cannot eat the budget a client needs to rejoin with, the retry_after_ms hint now points at the next window instead of shrinking as overage grew, every channel's join rejection carries the numeric code the API reference already promised (plus 4005 for a malformed topic), BulkChannel only pushes an event to the user who owns the operation instead of to anyone who guesses the id, and the web and admin clients treat a rate_limited join as transient (wait out the hint, keep the socket) while backing off per-channel rejoins on a decaying schedule rather than reconnecting on the 120ms floor forever; adds an ExUnit suite for realtime and a vitest suite for admin, both wired into CI
|
2026-08-26 21:14:34 -07:00 |
|
Matthew Meszaros
|
8bd2c2b57a
|
feat: make self-hosting work end to end and rewrite the guide around what was tested (#97)
|
2026-08-13 09:47:46 +02:00 |
|
Matthew Meszaros
|
4962765a79
|
fix: format the org_channel AI_DRAFT access_unibox clause to satisfy mix format --check-formatted (Elixir CI)
|
2026-07-15 06:47:07 +02:00 |
|
Matthew Meszaros
|
56de65380b
|
feat: inbox agent that drafts a suggested unibox reply on inbound human replies for human approve/edit/discard - paid + per-org opt-in (organizations.inbox_agent_enabled) feature where the consumer's reply hook, on a non-automated reply, detaches a goroutine (panic-contained, never blocks ingest) that checks entitlement, dedupes via ai_thread_drafts partial unique indexes (one pending per thread, unique source_message_id), pre-checks balance, grounds a reply in the thread history + org voice + skills via generation.Provider.Complete, reserves a draft row then charges 5 credits (idempotency inbox_agent:<draft.ID>, row unwound on a fresh context if the charge fails so no unpaid draft lingers), and emits an org-scoped AI_DRAFT_READY event gated on access_unibox; the agent never sends - only a human POST to /unibox/agent-drafts/:id/approve sends through the normal reply path, claiming pending->approved before send with an approved->pending revert on send failure, alongside list + discard endpoints; plus the unibox awaiting_agent_draft badge + agent_drafts search scope, an AgentDraftCard in the thread view with inline-editable approve-and-send/discard, the workspace settings opt-in toggle, CanUseInboxAgent paid gate, migration 000065, and docs (inbox-agent guide, endpoints, realtime)
|
2026-07-14 06:13:27 +02:00 |
|
Matthew Meszaros
|
f48d51bf16
|
feat: AI contact research agent that gathers cited web findings per contact with sync and background-batch runs - contact_research_runs table plus a strict save_research schema (every signal and public_artifact must carry a url, confidence high/medium/low, signals<=5 hooks<=3, reject-and-reprompt once then fail), a text/template runtime prompt injecting org voice, contact record, objective, and 5-search/6-fetch budgets, a research service that drives search_web/fetch_url through the provider loop and charges 2 credits on save (billable even for nothing_found, refund-free since charged only on save, balance and abuse-cap pre-checked so a capped org never does free work), POST/GET /contacts/:id/research plus a 500-cap /contacts/research/batch draining through a bounded pool of 4 workers over FOR-UPDATE-SKIP-LOCKED claims (no new Kafka), an org-scoped AI_RESEARCH_PROGRESS realtime event gated to view_contacts, APIPermAIResearch bit 23, a ContactEdit Research tab and a ContactsTable bulk Research action, and docs; also org-scopes every credit and research idempotency key so a client-supplied Idempotency-Key can never replay across tenants
|
2026-07-13 19:34:11 +02:00 |
|
Matthew Meszaros
|
262d25779c
|
feat: realtime admin dashboard + diagnosability - new Elixir admin:platform channel (JWT-only, gated on users.admin_permissions) mirrors every platform event, the admin app connects through a /getaway-tokenized Phoenix socket client with a throttled react-query invalidation spine, a Live Events firehose page streams the platform with filters/pause/JSON expand, a System Status page runs parallel infra probes (postgres/redis/kafka/schema-registry/realtime/tracking via /admin/system/status), and the worker logs viewer gains follow mode, line-count selection, and copy
|
2026-07-12 09:00:10 +02:00 |
|
Matthew Meszaros
|
e190571696
|
feat: harden the live channel with an is_map payload guard, byte-bounded chat/id/resource strings, a per-surface permission gate that strips cursor-chat text, and a websocket max_frame_size cap
|
2026-07-02 20:33:44 +02:00 |
|
Matthew Meszaros
|
88cabf5cac
|
feat: cap the live:select ids payload before traversal so an oversized selection list is never fully walked by the realtime channel
|
2026-07-02 14:31:36 +02:00 |
|
Matthew Meszaros
|
02b25724f4
|
feat: extend the ephemeral live channel with a sanitized chat field on live:cursor frames and a new live:select kind that broadcasts a capped node-id list for canvas selections
|
2026-07-02 07:40:06 +02:00 |
|
Matthew Meszaros
|
3ffd4416a2
|
feat: add a generic live:patch channel kind that fans out a small sanitized scalar map for ephemeral collaborative-state hints
|
2026-06-30 10:34:14 +02:00 |
|
Matthew Meszaros
|
248c886290
|
feat: add an ephemeral live:cursor/live:node channel path to the realtime org channel that bypasses the Redis ws limiters and the sequenced resume buffer via an in-process token bucket and broadcast_from fan-out
|
2026-06-30 10:06:19 +02:00 |
|
Matthew Meszaros
|
b83aa51921
|
feat: make CUSTOM_EVENT fire-event signals an explicit allow on the org channel and return structured {code, reason} errors on a failed channel join
|
2026-06-14 11:02:12 +02:00 |
|
Matthew Meszaros
|
799e5f10ef
|
feat: surface WebSocket connection-rejection reasons to the client as a structured {code, reason, retry_after_ms} payload (Discord-style 4003/4004/4007/4009/4010) instead of a bare 403, and fix the rate-limit 3-tuple match
|
2026-06-14 11:02:12 +02:00 |
|
Matthew Meszaros
|
4552ab4e31
|
feat: make the org realtime channel a resumable gateway — assign a monotonic per-org sequence + buffer each event in a capped Redis stream (Realtime.EventLog) before broadcast, advertise the current seq in the HELLO and stamp it on every event, and replay the missed gap (re-filtered) on reconnect via resume.last_seq or signal a full resync when the buffer no longer covers the client
|
2026-06-13 11:23:07 +02:00 |
|
Matthew Meszaros
|
c5ced50868
|
fix: apply mix format to the realtime service (supervisor child-list indentation in application.ex + org_channel.ex) so the Elixir CI format check passes
|
2026-06-12 17:45:32 +02:00 |
|
Matthew Meszaros
|
3cbfc06bc4
|
feat: add WebSocket intents (selective event-family subscription) and a HELLO-style org join reply advertising heartbeat cadence, and correct realtime docs on connection rejections and at-most-once delivery
|
2026-06-12 07:17:09 +02:00 |
|
Matthew Meszaros
|
4f1ac8c273
|
feat: enforce org team-presence privacy in the realtime OrgChannel — gate Presence.track on show_online, strip viewing/editing detail when show_activity is off, and re-track/untrack live on PRESENCE_POLICY_UPDATED
|
2026-06-12 05:59:01 +02:00 |
|
Matthew Meszaros
|
70064e9e1d
|
fix: define OrgChannel.handle_out/3 so presence_diff broadcasts are pushed to clients instead of crashing the channel — the missing callback was terminating the org channel and dropping every websocket connection in a reconnect loop
|
2026-06-11 13:47:11 +02:00 |
|
Matthew Meszaros
|
371fe0c0a3
|
feat: add Phoenix.Presence org collaboration layer (online members, viewing/editing/replying activity) with permission-gated org event fanout in the realtime service
|
2026-06-11 07:51:34 +02:00 |
|
Matthew Meszaros
|
ce870a15b3
|
ci: fix Elixir formatting / Elixir version / missing pnpm lockfile
- realtime/: `mix format` applied; long Logger calls reformatted across
config/runtime/application/connections/user_channel/user_socket/
endpoint. CI's "Check formatting" step now passes.
- CI Elixir bumped from 1.16 → 1.18 (with OTP 27) to match mix.exs's
`~> 1.18` requirement. Phoenix 1.8.7 + plug 1.19 also expect this.
- web/: generate + commit pnpm-lock.yaml so actions/setup-node@v4's
pnpm cache step + `pnpm install --frozen-lockfile` can resolve.
|
2026-05-23 16:17:27 +00:00 |
|
Matthew Meszaros
|
141bc54974
|
Add sample auth UI theme
|
2026-02-10 19:30:47 +01:00 |
|
Máté Mészáros (Laptop)
|
ed35ab2dbc
|
Realtime Updates
|
2026-01-30 15:32:58 +01:00 |
|
Máté Mészáros (Laptop)
|
6adb4cdd5a
|
Organization, Subscription, Inqueries, limits.
|
2026-01-27 05:55:48 +01:00 |
|
Máté Mészáros (Laptop)
|
5ac159d2f8
|
Realtime, api keys & more
|
2026-01-26 16:04:42 +01:00 |
|