Docs
Open in panel → /app · domains
Domains
The panel Domains section lets a workspace declare a sender domain and
publish TXT records. DKIM private material stays on the appliance
(service_role only) and is never sent to the browser.
Endpoint contract
| Path | Auth | Purpose |
|---|---|---|
GET /v1/panel/domains |
viewer+ | List domains + DNS records |
POST /v1/panel/domains |
operator+ | Create domain (auto-generates records via generateDomainDnsRecords) |
POST /v1/panel/domains/:id/verify |
operator+ | SPF/DKIM/DMARC verify; on success → policyRender.renderWorkspacePolicy → applyPolicyToKumo (epoch bump) |
Verify modes
- Lab:
MIB_DNS_VERIFY_STUB=1orPOSTMTA_HOSTED_DNS_VERIFY_STUB=1short-circuits and marks the domain verified without live lookup. - Production:
assertProductionProfile()in apps/api/src/app.ts throws if either stub env is set. The verify route then runs the live probe in apps/api/src/dnsVerify.ts:dns.resolveTxtfor SPF (@), DKIM ({selector}._domainkey), DMARC (_dmarc); matches against the domain checklist records plus the DKIM selector fromdomain_dkim_secrets. - Failure: 422 + per-record pass/fail, structured
{ ok, checks: { spf, dkim, dmarc }, missing[] }.
DKIM private key
domain_dkim_secrets is RLS-locked: service_role only, granted to the API
admin client; revoked from anon and authenticated (PMH-SEC-023). The
panel never renders the private PEM. apps/web/src/lib/dkim-pub.ts (when
extended) will surface the public key only.
Operational facts
- Selector defaults to
mib(legacy);dkim_signconfig in managed Lua wiresdomain → selector. - After verify success the route enqueues a
policy_jobs.kind='apply_policy'job and bumps the Kumo config epoch. apply-policyfailures are returned with HTTP 200 + awarningfield, not 5xx, so the operator sees the verify succeeded but the publish needs attention.
Related
- docs/build/credits.md — send gate uses domain
verified status when
REQUIRE_VERIFIED_DOMAIN=1. - docs/operate/policy.md — what
applyPolicyToKumoactually publishes. - docs/qa/MATRIX.md — M52 live DNS prove path.
Last verified: Sat Jul 11 2026 17:00:00 GMT-0700 (Pacific Daylight Time). Cross-link maintained byscripts/check-docs-drift.sh (M54).