Zilla CRM

Security & controls

Plain-language summary of controls documented in the zilla-crm codebase. This page does not describe marketing-site hosting, only CRM agent and delivery mechanics.

Early access status: delivery is test_only during early access (see crm_0002_policy.sql). Email delivery is test-only, not production bulk sending.

  1. 01 / Per-tenant runtime tokens

    Tokens are random; only the SHA-256 hash is stored, tenant-bound in SQL, revocable, and issuable only by service_role.

    packages/db/migrations/crm_0011_agents.sql

  2. 02 / No provider keys in agents

    The agent holds one runtime token. Every read and write goes through the host tool API POST /crm/agent. The gateway strips client auth headers and holds the model key.

    runtime/README.md · runtime/gateway.py · runtime/tenant.sh

  3. 03 / Network lockdown

    Internal-only Docker network. The gateway allows exactly two endpoints (the model API /v1/messages and POST /crm/agent), checked by a network probe. Containers are read-only, non-root, drop all capabilities, no-new-privileges, base image pinned by digest, packages hash-locked.

    runtime/tenant.sh · runtime/gateway.py · runtime/netprobe.py · runtime/Dockerfile

  4. 04 / Locked-down agent

    All built-in tools, memory and plugins are off; the agent can reach only the CRM's own tool server, one tool per run. Each run uses a fresh scratch home and fails closed on tool mismatch. The DB enforces tools per agent: Insights can only write recommendations and notes; email agents can only write or revise email.

    runtime agent config · runtime/crm_runtime/policy.py · runtime/crm_runtime/launcher.py · packages/db/migrations/crm_0011_agents.sql

  5. 05 / Content checks

    Every email version is checked for price, link, offer, stock, superlative, spam, shouting, number, and restricted content. Agents are denied; people are flagged. Human approval never overrides a deny.

    packages/core/src/content-check.ts · packages/db/migrations/crm_0004_messages.sql

  6. 06 / Approval bound to content hash

    Each approval is bound to an exact message version via SHA-256 over content, audience, sender, schedule, products, and policy. Any edit requires a new approval.

    packages/db/migrations/crm_0004_messages.sql

  7. 07 / Agent modes and ceilings

    Modes order: off < draft < approve < auto. Each agent has a hard maximum (Insights draft-only; Prospect maxes at Approve and starts Off). Effective mode is the lowest of client setting, policy ceiling, and hard max.

    packages/db/migrations/crm_0002_policy.sql

  8. 08 / Kill switches and delivery brakes

    Pause everything, all campaigns, or one agent. Automatic brakes pause the tenant at 0.08% complaints or 4% hard bounces over 30 days (minimum 50 sends). The console can only tighten those limits.

    packages/db/migrations/crm_0002_policy.sql · packages/db/migrations/crm_0008_delivery.sql

  9. 09 / Append-only audit log

    A trigger refuses UPDATE and DELETE; each row records actor type and actor.

    packages/db/migrations/crm_0002_policy.sql

  10. 10 / Consent ledger

    Consent per tenant, address, dealer, channel, and category, with evidence. Never inferred (no row means no). Ledger is append-only; opt-out lifts only via the recipient’s new opt-in.

    packages/db/migrations/crm_0003_consent.sql

  11. 11 / RFC 8058 unsubscribe

    One-click unsubscribe. GET shows a confirm page so link scanners cannot unsubscribe anyone. Tokens carry 244 random bits.

    packages/host-next/src/unsubscribe.ts

  12. 12 / Bounces and complaints

    Hard bounces and provider suppressions are never deleted. A complaint counts as a global withdrawal.

    packages/db/migrations/crm_0008_delivery.sql

  13. 13 / Weekly send cap

    Per-recipient weekly cap reserved atomically under row locks.

    packages/db/migrations/crm_0005_sends.sql

  14. 14 / Signed delivery webhooks

    URL and secret per tenant. Signature verified over raw bytes; DB checks tenant; processing is idempotent.

    packages/host-next/src/webhook.ts

  15. 15 / Database lockdown

    No grants to anon or authenticated. RLS on every table. Functions granted explicitly.

    packages/db/migrations/crm_0001_foundation.sql

Questions about your deployment? Early access form or al@zilla.wtf.