Commit Graph
613 Commits
Author SHA1 Message Date
Matthew Meszaros f93a01e966 Merge pull request #20 from warmbly/feature/remote-infra-dev-config
feat: support remote dev infra
2026-05-31 09:30:24 +02:00
Matthew Meszaros c1a744b656 feat: refresh repository banner assets
Update the repository banner artwork and stop tracking the stray root node_modules install by adding a root ignore rule.
2026-05-31 09:24:01 +02:00
Matthew Meszaros 1f4d06e881 feat: add repository banner
Replace the README mark heading with a branded banner asset and refresh the repository badges.
2026-05-31 09:11:20 +02:00
Matthew Meszaros 73d8ea3b5e feat: restore site header logo in repo docs
Use the same Warmbly paper-plane mark from the site header in the README and docs header.
2026-05-31 09:01:42 +02:00
Matthew Meszaros 3beb3bed0d feat: remove repository logo from docs
Remove the README logo block, delete the repository logo asset, and drop the docs header image reference so no broken logo path remains.
2026-05-31 08:59:54 +02:00
Matthew Meszaros fe6b2cca54 feat: update repository docs branding
Replace the repository logo with the site mark on a sky background and move contribution guidance into CONTRIBUTING.md.
2026-05-31 08:57:26 +02:00
Matthew Meszaros adedcc337e feat: support remote dev infra
Allow native dev services to target infrastructure running on another host by parameterizing local endpoints with INFRA_HOST and SELF_HOST.

Document the workflow and make Kafka advertise a configurable host for off-box clients.
2026-05-31 08:53:21 +02:00
Matthew Meszaros 88741ee960 Merge pull request #19 from warmbly/feature/dashboard-plans
feat: improve unibox scheduling and campaign wakeups
2026-05-31 07:26:51 +02:00
Matthew Meszaros 545dcea940 feat: show scheduled replies in threads
Add a thread_id filter for scheduled Unibox sends and expose a per-thread hook for the dashboard.

Render queued sends inline in ThreadView with cancellation, refreshing the thread, scheduled list, and overview caches after cancel.
2026-05-31 05:19:39 +00:00
Matthew Meszaros 2d11ed8166 feat: add mobile unibox scope picker
Expose the Unibox scope rail through a mobile sheet so smaller screens can switch between inbox scopes, mailboxes, tags, and scheduled views.

Simplify template rows in the reply composer to keep the picker compact.
2026-05-31 05:17:32 +00:00
Matthew Meszaros 6249d3e1a2 feat: refine unibox reply workflow
Open the reply composer only after the user chooses a message to reply to or forward, and wire per-message actions through the thread view.

Also clean up cancelled scheduled sends from Cloud Tasks on a best-effort basis while keeping the database status as the source of truth.
2026-05-31 05:14:22 +00:00
Matthew Meszaros 72073c669e feat: bootstrap campaign wakeups
Create the initial per-campaign Cloud Tasks wakeup when a campaign starts, using the same idempotent task chain as subsequent sends. Pause or complete campaigns instead of leaving active campaigns with no scheduler when no work can be queued.
2026-05-31 04:51:03 +00:00
Matthew Meszaros 946cd087e5 feat: cap active campaign schedulers
Limit organizations to 50 active campaigns before starting another campaign, make campaign wakeups idempotent per campaign, keep warmup wakeups idempotent per mailbox, and no-op stale non-pending campaign/warmup dispatches.
2026-05-31 04:48:39 +00:00
Matthew Meszaros 70bfa39163 feat: update unibox scheduled UI
Add scheduled-send scope, queued-send review and cancel flows, richer reply composer controls, snooze picker polish, and API client models for the new Unibox endpoints.
2026-05-31 04:26:46 +00:00
Matthew Meszaros 7b5a87d1d1 feat: add unibox scheduled send backend
Add Unibox overview, snooze, and scheduled-send endpoints with task repository support, queue caps, execution-time guards, and snooze persistence.
2026-05-31 04:26:26 +00:00
Matthew Meszaros bf40834557 feat: update unibox experience 2026-05-30 16:37:50 +00:00
Matthew Meszaros 4663333d2c feat: update billing and email settings 2026-05-30 15:45:10 +00:00
Matthew Meszaros 0740a8bbbe feat: fix local migrations and kafka topics 2026-05-30 14:11:47 +00:00
Matthew Meszaros a227938778 feat: seed unibox trial fixtures 2026-05-30 14:06:36 +00:00
Matthew Meszaros 17ce31a942 feat: extend dashboard session lifetime 2026-05-30 14:06:27 +00:00
Matthew Meszaros d08c984c42 feat: snapshot current dashboard changes 2026-05-30 13:56:27 +00:00
Matthew Meszaros 44c837d8ac Merge branch 'main' into feature/dashboard-plans
# Conflicts:
#	AGENTS.md
2026-05-30 09:49:12 +00:00
Matthew Meszaros 9027086d77 feat: remove worker installer api alias 2026-05-30 09:40:46 +00:00
Matthew Meszaros b168f4d466 feat: simplify worker installer route 2026-05-30 09:37:26 +00:00
Matthew Meszaros e35a91f6bc feat: make worker enrollment default 2026-05-30 05:13:18 +00:00
Matthew Meszaros d8a546eca5 feat: add worker enrollment install 2026-05-30 05:10:27 +00:00
Matthew Meszaros d28c607013 feat: document api release standards 2026-05-30 04:35:26 +00:00
Matthew Meszaros cb0c2b4fac feat: harden webhook endpoints 2026-05-30 04:33:43 +00:00
Matthew Meszaros 640da62b32 feat: add api idempotency keys 2026-05-30 04:31:43 +00:00
Matthew Meszaros 878e8d921e feat: enforce api key email scopes 2026-05-30 04:28:25 +00:00
Matthew Meszaros 3076cff5d6 feat: add api request ids 2026-05-30 04:26:12 +00:00
Matthew Meszaros 67bbd72777 feat: harden api permission gates 2026-05-30 04:24:41 +00:00
Matthew Meszaros 60773b3d8e feat: make dashboard realtime 2026-05-30 04:17:10 +00:00
Matthew Meszaros 7f830b976f feat: sync org session, harden campaign loading, add mailbox bulk-remove 2026-05-30 03:42:39 +00:00
Matthew Meszaros 090cc1c832 feat: rework dev workflow with native go services and dockerized infra 2026-05-30 02:57:27 +00:00
Matthew Meszaros 515ffcf099 feat: rework dev workflow with native go services and dockerized infra 2026-05-30 02:16:32 +00:00
Matthew Meszaros 49e21113dc feat: wire analytics and rate limit services into backend handler 2026-05-29 16:49:52 +00:00
Matthew Meszaros b146417b50 chore: dashboard and plans 2026-05-29 16:42:05 +00:00
Matthew Meszaros ff763c4483 feat: add role and team-size onboarding questions and rework site SEO me 2026-05-29 14:47:16 +00:00
Matthew Meszaros 1d132ccd56 feat: rework auth layout for mobile sky backdrop and email pill 2026-05-29 09:57:59 +00:00
Matthew Meszaros 483e27270b feat: telegraph next slide via progress bar fill and fix panel blur 2026-05-29 09:44:19 +00:00
Matthew Meszaros bb7008c50a feat: pin logo to showcase pane and restructure auth layout 2026-05-29 06:11:18 +00:00
Matthew Meszaros 68022ad813 feat: rework auth showcase carousel and layout framing 2026-05-29 06:05:35 +00:00
Matthew Meszaros 6766031cc5 feat: add discount code support for checkout and plan changes 2026-05-29 05:49:19 +00:00
Matthew Meszaros e7ef328b2d Merge pull request #18 from warmbly/feature/admin-management
feat: admin management surface with overrides, ban scope, and throttles
2026-05-29 05:01:00 +02:00
Matt e73ff0aa86 ci(go): gofmt fixes and AGENTS.md CI rules
Two files were unformatted, tripping the golangci-lint gate that runs
gofmt:

  - cmd/backend/main.go: dailythrottle import out of alphabetical order
  - internal/repository/pg_admin_outreach.go: numbered list comment used
    three-space indentation; gofmt wants two

Both fixed by running gofmt -w against the offending files.

Add a "Working In This Repo" section near the top of AGENTS.md (which
CLAUDE.md symlinks to) documenting the rules this PR violated:

  - go build is not the ship signal; CI runs gofmt via golangci-lint
  - always gofmt -w changed Go files before considering work done
  - run the right typecheck/lint step in each frontend tree before
    pushing
  - commit messages do not carry Co-Authored-By or other AI/agent
    attribution footers
2026-05-29 04:57:31 +02:00
Matt b633e326e5 feat(throttle): per-day creation throttles for campaigns/mailboxes/orgs
The HardCap* constants stop "you have 5000 campaigns on this org"; the
throttles in this commit stop "you created 1000 campaigns today on a
fresh unlimited account." Different shape, different abuse, different
mechanism — Redis-backed per-(scope, resource, UTC-day) counters that
reset by key design at midnight UTC, no scheduled job needed.

New service internal/app/dailythrottle:
  - CheckAndIncrement(scope, resource, ceiling) atomically bumps the
    counter and returns errx.TooManyRequests when the post-increment
    value exceeds the ceiling.
  - 25h TTL so the key always expires after the day rolls over even
    if the process restarts before midnight.
  - Fail-open when the cache is absent (jobs/tests) so creation paths
    that haven't been wired with a cache still work.

Caps (config.DailyThrottleNew*):
  - 20 new campaigns/org/day
  - 5  new mailboxes/org/day
  - 3  new workspaces/owner/day

Wired into three creation paths:
  - campaign.Create — scoped on the orgID when present
  - email.OAuthFinish + email.OnboardSMTPIMAP — scoped on the orgID;
    fires only at actual create, not OAuthStart, so retrying a failed
    OAuth flow doesn't burn the day's budget.
  - organization.Create — scoped on the owner uuid (the org doesn't
    exist yet)

Adds errx.TooManyRequests (HTTP 429) since no caller had one before.

emailService gains WireThrottle alongside the existing WireWebhooks
pattern so jobs / tests can build the service without a cache. Same
treatment in main.go.
2026-05-28 13:34:01 +02:00
Matt d80efc88b4 feat(ban): runtime enforcement for ban-scope bitmask
The bitmask landed in 000045 with schema + UI; this commit wires the
three gates the bits describe.

  - BanScopeLogin    → authService.LoginConfirm checks the scope after
                       password verification and refuses the session
                       with "this account has been suspended"
  - BanScopeOrgCreate → organizationService.Create checks the scope
                       before any other validation and refuses with
                       "this account cannot create new workspaces"
  - BanScopeSend     → emailSendService.SendEmail checks the scope
                       before validating the email account and refuses
                       with "this account cannot send email"

Adds UserRepository.GetBanState(ctx, userID) → uint32 — a single-column
read so the hot paths don't have to fetch the full user row just to
check a flag. Returns 0 when no ban (the column defaults to 0); the
caller treats 0 as "allow."

Threads userRepo into emailSendService — the only constructor change
in this commit. cmd/backend/main.go updated accordingly.
2026-05-28 12:43:50 +02:00
Matt 3ffa416e40 feat(admin): mailboxes admin (cross-org triage)
Adds GET /admin/mailboxes — paginated platform-wide mailbox list that
joins email_accounts → users → organizations so the table answers
"whose mailbox is this and where does it live" without N+1 fetches.

Search covers mailbox email / owner email / org name; status filter
defaults to active so the active surface shows first ("inactive" /
"all" both available). Provider filter speeds up "show me every Gmail
mailbox" investigations. Cursor pagination matches the rest of the
admin lists.

Frontend page surfaces warmup-on/off, send budget, and last-sync time
with red-when-never / amber-when-stale-over-24h tone so an
investigator can spot dead mailboxes fast. Mailbox email links into
the owning user's detail page; org name links into the workspace
admin so the pivot path stays one click in either direction.

Gated on AdminPermViewUsers since mailbox triage is tightly coupled to
user/org context today; a dedicated bit can be carved later if
mailbox-specific actions land.
2026-05-28 12:38:08 +02:00
Matt 705877f2ff feat(admin/ui): analytics page with daily/hourly/worker charts
Replace the AnalyticsPage stub with the full chart pack over the
existing /admin/analytics/* endpoints. Four-up trend cards on top
(users / emails / campaigns / revenue growth vs. previous period),
then a 30-day stacked bar chart for daily email volume (delivered /
replied / bounced), and a two-up row with hourly-by-today plus a
sorted worker-load list that links into each worker's detail page.

No chart library — bars are CSS divs so the admin bundle doesn't pay
for recharts/d3 for this one screen. Hover tooltips on the bars carry
the per-day breakdown.

User-growth strip lives below the email charts for symmetry with the
Overview's "platform pulse" framing.
2026-05-28 12:33:31 +02:00