Skip to content
PostMTA Hosted
StatusSign inOpen panelRequest access
Open menu

Docs

Open in panel → /app · reputation

Reputation

On-box complaint / FBL / suppression pulse. No outbound calls. Honest SKIP: actual SNDS / Postmaster / Google Postmaster Tools API connectors require third-party sign-up that is out of scope for the appliance. Recorded in ECC_VERIFY Phase 3 and in the Honest SKIPs block of trust/security.

What ships (matrix M74)

Both routes require admin role. The Reputation panel section fetches the pulse on load and offers a simple add-suppression form.

On-box pulse loop

flowchart LR
  Kumo[Kumo delivery / FBL ingest] --> FBL[fbl_events]
  Webhook[Delivery webhooks] --> SUP[suppressions]
  FBL --> SUP
  FBL --> Pulse[GET /v1/panel/reputation/pulse]
  SUP --> Pulse
  Pulse --> Panel[/app Reputation section]
  Panel -->|POST suppression| SUP
  1. Kumo posts FBL ARF to POST /v1/fbl/ingestfbl_events.
  2. The FBL poller / webhook path may also write suppressions.
  3. The pulse endpoint aggregates the last 30 days locally.
  4. Operators react in-panel (manual suppression) or via policy / wallet controls.

FBL loop (operator)

CSV / Postmaster import (manual)

We do not ship SNDS or Google Postmaster API connectors. Operators can still import third-party exports into suppressions on the appliance host via the bundled CSV importer scripts/postmaster-csv-import.ts — pipe recipient,complaint_count rows on stdin and it upserts each address as reason='complaint', source='reputation' against the unique index (workspace_id, address, reason), so re-imports are idempotent and --workspace-id=<uuid> (default seed) lets you attribute rows per tenant without touching SQL.

Option A — psql one-liner (bounce CSV)

# columns: address (header row optional)
psql "$DATABASE_URL" -c "\copy tmp_bounces(address) FROM 'snds-bounces.csv' CSV HEADER"
psql "$DATABASE_URL" -c "
  INSERT INTO public.suppressions (workspace_id, address, reason, source, note)
  SELECT '<workspace-uuid>'::uuid, address, 'bounce', 'manual', 'snds import'
  FROM tmp_bounces
  ON CONFLICT (workspace_id, address, reason) DO NOTHING;
"

Option B — documented SQL (Postmaster-style complaint list)

-- Replace values per export row
INSERT INTO public.suppressions (workspace_id, address, reason, source, note)
VALUES
  ('<workspace-uuid>', 'user@example.com', 'complaint', 'manual', 'postmaster export 2026-07-13')
ON CONFLICT (workspace_id, address, reason) DO NOTHING;

For FBL-shaped rows, prefer fbl_events ingest via the HTTP contract rather than hand-inserting hashes unless you are replaying a backup.

What does NOT ship (honest SKIP)

Operators can attach outbound vendors via cron on the appliance host (write into suppressions or fbl_events directly).

Fixtures / smoke

# JSON fixtures only (no secrets)
MOCK_REPUTATION=1 pnpm exec tsx scripts/seed-reputation-fixtures.ts ws-demo

# Live lab seed (service role required; keys never logged)
SUPABASE_URL=http://127.0.0.1:54321 \
SUPABASE_SERVICE_ROLE_KEY=... \
  pnpm exec tsx scripts/seed-reputation-fixtures.ts <workspace-uuid>

Last verified: Sun Jul 12 2026 17:00:00 GMT-0700 (Pacific Daylight Time). Cross-link maintained byscripts/check-docs-drift.sh (M54).

← All docs