Skip to content

v0.1.0

Choose a tag to compare

@github-actions github-actions released this 10 Oct 21:54
04a0b28

0.1.0 (2026-10-10)

⚠ BREAKING CHANGES

  • segments: remove Segment type; a Segment is always a rule

Features

  • api: add-suppression and unsubscribe operations in /api and MCP (#55) (5bce053)
  • api: broadcast drafts, audience, test-send and report in /api and MCP (dfd78b2)
  • api: manage Integrations through the external API (402306f)
  • api: manage Sending domains through the external API (5d0e0b4)
  • api: rails-style resourceful URLs via TypeSpec CRUD templates (0628507)
  • api: read-only custom fields, sending domains and complaint/bounce rates (#54) (3ebda14)
  • api: segments CRUD and preview in the external API (be9cbda)
  • api: templates and webhooks in /api (a50b2a2)
  • apitokens: one module mints and revokes API tokens; a token cannot grant what it lacks (2cae730)
  • auth: a single login route; remove the library /auth/ and avatar routes (30feed3)
  • auth: add login link to register page (b3f70de)
  • auth: email Users when a Second factor is required and before their grace ends (6bd3a2a), closes #191
  • auth: enforce session expiry and carry user id and epoch in the session token (ceb8d75)
  • auth: enforced session expiry, session epoch, TOTP second factor and two-step login (ADR 0020) (a54fb7c)
  • auth: enforced session expiry, session epoch, TOTP second factor and two-step login (ADR 0020) (#195) (a54fb7c)
  • auth: enroll a TOTP Second factor with Recovery codes (ad0c3b8)
  • auth: let a withheld Owner or Admin lift the requirement from the SPA (cb88630)
  • auth: mark the JWT cookie Secure when served over HTTPS (5d7297d)
  • auth: password reset, email verification, and email change (b732f56)
  • auth: rate limit forgot-password without revealing accounts (9cbda8e)
  • auth: require a Second factor for a Workspace with a grace period (32d4e78), closes #190
  • auth: reset another User's Second factor (Owner/Admin and operator command) (7a71da0), closes #192
  • auth: revoke sessions on password change, reset, email change and sign-out-everywhere (7ebf7ad)
  • auth: self-service account pages + profile email management (4713e61)
  • auth: throttle login per account with exponential delay (6291441)
  • auth: two-step login with TOTP or Recovery code (49976b2)
  • automations: sync workflow builder theme with Mantine color scheme (1deee46)
  • config: fail fast on weak production JWT secrets and make examples safe (7fcf520)
  • contacts: emit PII-free contact.erased Event and webhook on Erasure (eb06f3f)
  • contacts: erase a Contact by id (delete is Erasure, ADR 0021) (8783bbb)
  • contacts: erase by email and by visitor_id (1d97f28)
  • contacts: stop in-flight work and clear internal queues on erasure (119f7a4)
  • contacts: subject-access export of one Contact (32c3d2f)
  • db: bound Postgres pools, export pool stats, explicit river retention (816d5c8)
  • deploy: add Helm chart with migrate hook and check:helm (2a3b753)
  • dev: one Postgres for all checkouts, started by an idempotent db:up (d2f295f)
  • dev: per-worktree dev stack ports and origin (2961828)
  • dev: shared Postgres profile and per-checkout scratch database names (6d55b8c)
  • dev: worktrees:gc sweeps databases and daemon state of deleted worktrees (7ee8a95)
  • edit Integration send limits and show effective limit and usage (dc079a3)
  • ee: advanced retention prunes the audit log (47fe2c0)
  • ee: align audit diff keys with the explicit entries (from/to, changed marker) (d6c351e)
  • ee: audit access and configuration entities (e0cb2d9)
  • ee: audit capture in the scoped client, Tag first (a3e448f)
  • ee: audit content, audience and Contact changes (47341f3)
  • ee: audit explicit actions (invitation, login, password change, suspension) (cc474c0)
  • ee: audit log (spec #110) (65b0ae7)
  • ee: audit log CSV export and /api read with audit:read scope (0f80ff6)
  • ee: audit log filters, diff view and change-history links (dacef11)
  • ee: audit log retention setting, /api filters, audited export, safer snapshots (926c63d)
  • ee: audit log skeleton, a role change is recorded and listed (23db54c)
  • ee: audit retention control and audit UI tests (ab582a1)
  • ee: forward audit entries to Webhook endpoints (76cef23)
  • events: delete analytical Events past EVENTS_RETENTION_DAYS (427de7c)
  • events: prune the domain-event outbox below the slowest consumer (68e4d50)
  • export: typed contact export document; river API for test queue access (66a8fec)
  • expose Integration effective send limit, source and 24h usage (8183b7e)
  • external: automations in /api with tag steps, activate behind a second lock (6e06db3)
  • external: batch upsert of contacts and batch record of events (bd717be)
  • frontend: migrate Templates to the resource form module (55906e1)
  • frontend: resource form lifecycle module, proven on Contacts (1335b6c)
  • i18n: instance-level ru/en/es localization (4ca2d88)
  • infra: SaaS infra in Terraform on DigitalOcean App Platform (#214) (27691b2)
  • mcp: add oauth 2.1 for claude.ai connectors (b9fe50a)
  • mcp: mark contact-supplied fields as untrusted in tool results (87bf6e1)
  • mcp: serve shipped playbooks as MCP prompts and grant authoring scopes to OAuth connectors (5c9f116)
  • mcp: serve the external API as MCP tools at /mcp (7b14dbb)
  • merge ticket-92 metrics listener into spec-91 integration (045c11f)
  • metrics: count provider deferrals apart from send errors (bc085f9)
  • metrics: export outbox lag, queue depth and send outcomes (b487d7e)
  • operations docs, retention, pools, metrics, Helm, security policy (a6474f0)
  • outbound: classify provider too-fast and quota replies as Deferral (57387c0)
  • outbound: count transactional sends against the send rate limit (6b3815a)
  • outbound: route every send surface through one Outbound send module (34e150b)
  • pace Broadcast recipients at the Send rate limit and expose progress and ETA (42f3eec), closes #123
  • rate limiting for public and authenticated endpoints (ADR 0018) (305836b)
  • ratelimit: rate limit /api and /mcp per Workspace (0ff76a1)
  • ratelimit: rate limit /collect and cap payload size (0379086)
  • ratelimit: rate limit public human endpoints per IP (049de64)
  • ratelimit: tracking never refuses a recipient (3bca8f7)
  • segments: migrate Segment create/edit to the resource form module (8cf434b)
  • segments: remove Segment type; a Segment is always a rule (9466fa7)
  • send lock with broadcasts:send, automations:activate and mcp:send scopes (2b0f37d)
  • send rate limit on Integration with Deferral outcome (6c9f75b)
  • sending: add sending domains with DKIM verification (ADR 0010 slice 1) (d39b84c)
  • sending: double opt-in confirmation, slice 1 (ADR 0013) (9ce2ded)
  • sending: gate sending on a verified domain + notify on loss (ADR 0010 slice 3) (b9f5c93)
  • sending: RFC 8058 one-click unsubscribe (ADR 0012) (0d10d33)
  • sending: sign outbound mail with native DKIM (ADR 0010 slice 2) (de4ff7b)
  • sending: trust seeded sending domains in dev so the send gate doesn't block local mail (35fad76)
  • sending: workspace CAN-SPAM postal address in email footer (4c575b0)
  • sendlimit: discover SES send quota on save and hourly (5a3c76a)
  • serve /metrics on an opt-in internal listener (868b807)
  • server: serve /metrics on an opt-in internal listener (214d391)
  • server: serve /metrics on an opt-in internal listener (e6ced4c)
  • site: explicit null clears optional fields on Contact and Broadcast update (a84ad67)
  • spa: confirm and unsubscribe pages call the generated client (d92e889)
  • spa: explain 403 on token and OAuth consent actions (2a746d3)
  • suspension: show the owner a banner when the workspace is suspended (7670331)
  • suspension: workspace suspend CLI, owner notice, hold UI; fence outbound claims (c9fb068)
  • tags: tags end to end with has-tag segment rule and MCP tools (9e1ca94)
  • telemetry: OpenTelemetry traces + metrics (78deb33)
  • ui: add erase and export actions to the contact view (94b2235)
  • ui: warn when an Integration's provider send quota cannot be read (71777a5)
  • workspace scoping through a generated scoped client (ADR 0017) (87e9012), closes #78
  • workspaces: members UI, invite accept flow, and hardening (86c0b1a)
  • workspaces: multi-user memberships and invitations (fb1439d)

Bug Fixes

  • api: do not expose which members have a Second factor (88d6ff9)
  • audit path list follows the suspension package (09001c8)
  • auth: atomic per-address reset budget and uniform forgot-password work (5b751b9)
  • auth: harden the Second factor flows after the #143 review (678d06c)
  • auth: satisfy errcheck on the authtoken HMAC write (b9d6330)
  • automations: deleting an automation deletes its enrollments (14e2766)
  • broadcasts: bind delayed send job to its schedule (#77) (840c8f4)
  • consent: a failed consent write is a 5xx, a deleted workspace is a no-op (87faaba)
  • consent: tell an expired confirmation link from an invalid one (7a0e748)
  • contacts: adapt in-flight erasure to the operator-aware API after merge (ace1f06)
  • contacts: dedicated erase role check, shared export lookup and server-named download (39f68ec)
  • contacts: erasure clears queued webhook deliveries and keeps recipients_total consistent (329ddb2)
  • count only awake recipients in a Deferral's backlog (4bebbb1)
  • deps: make realclientip-go a direct dependency (go mod tidy) (a0e3d5d)
  • dev: per-instance Caddy admin and HTTP ports, stricter worktrees:gc (aecad32)
  • dev: use the host's global pnpm store instead of one inside the repo (2c3f9c7)
  • docs: render the VitePress theme templates instead of raw placeholders (2852fbe)
  • docs: render the VitePress theme templates instead of raw placeholders (048e82a)
  • e2e: isolate metrics port, reuse app Accounts, share mail wait helper (0ab63f9)
  • e2e: keep a cut-short poll from masking the inbox listing (6bba9c2)
  • e2e: keep RequireNone's lookup error off t while Never's condition runs (4291e53)
  • ee: mask the Operator identity in forwarded audit entries (c7d16b7)
  • eventlog list tests follow the optional Event fields from main (8a9832d)
  • external: an explicit null on contact update clears the field (fca1b72)
  • external: complete the token scope enum and workspace-scope /api token management (a872bc5)
  • external: publish ContactCreated for contacts created through /api (9c24027)
  • fixtures: add missing invitations fixture (7f5c01f)
  • fixtures: drop the removed segments.type column from the Globex fixture (86129b2)
  • fixtures: register inviteHash template func for invitation fixtures (5cde016)
  • frontend: address review findings for resource form module (408be80)
  • harden the e2e Inbox and the app lifecycle after review (b6b2a97)
  • logs: drop email and phone from log statements (1bd72ec)
  • look through the metrics decorator for the quota reader; count both new tables (97ccf16)
  • oauth: consent and token management need owner or admin; validate RFC 8707 resource (2d87867)
  • ops: address review findings on metrics, retention and migrations (83b1bc4)
  • pace and estimate by the effective Send rate limit, provider quota included (5e80a4d)
  • ratelimit: cap collect events before decoding, wait-aware recovery 429 (f82bcca)
  • refuse to start when the job queue cannot start (4bcce5f)
  • scoped update Modify cannot assign workspace_id (8914dfb)
  • security: explicit SameSite=Lax and cross-origin protection on cookie APIs (4e960b0)
  • segments: make Segment definition non-nullable in the contract (88d0dc0)
  • server: cap request body size and add read timeouts (8ec54a9)
  • site: name and cover contact alias-key and custom-field clearing (51d06ef)
  • telemetry: address review findings on the metrics listener (9992f1b)
  • transactional sends never defer; rename throttle vocabulary to busy; honest quota discovery response (1e321c1)
  • ui: give each error toast a case-specific fallback message (cad7cdd)
  • ui: stop error toasts repeating the title as the message (76f9593)