Security & compliance

Security isn't a feature we bolt on.
It's how every line is written.

Twelve disjoint encryption keys. Per-route RBAC against sixty-one permissions. A hash-chained audit log enforced by database triggers. Single-tenant infrastructure on dedicated hardware. The MoonFactory security posture is engineered — and documented.

Section A

Encryption Architecture

No master key. No shared secrets. Compromise one slice, not the platform.

  • Twelve AES-256-GCM keys with disjoint per-column scoping. Each key protects one specific data type — credentials, session tokens, lead-capture payloads, OAuth tokens, payout details — and one only.
  • Rotation CLI with a CI guardrail that fails the build if a column is encrypted with an undeclared key.
  • Keys live in a single registry (KEY_REGISTRY) that the application reads at boot. No keys hardcoded, no keys in source control.
  • The blast radius of any one key compromise is the column it protects — not the database.

Section B

Authentication & Access Control

Six roles, sixty-one permissions, zero global auth middleware.

  • Six-role RBAC: viewer → support → financial admin → admin → owner → engineer. Each role is a strict superset of the one below it, except engineer (which carries owner + technical permissions).
  • 61 named permissions enforced per-route. Every protected endpoint declares its required permission explicitly. There is no global middleware to bypass (ADR-002).
  • TOTP-based MFA on every staff and affiliate account.
  • Sensitive operations (payouts, tax data export, account deletion) re-challenge if your last MFA verification is older than 15 minutes.
  • Magic-link login for clients — no passwords to store, leak, rotate, or remember.
  • Admin and affiliate credentials hashed with bcrypt at cost 12.
  • Atlas embed API keys: prefix-indexed for fast lookup, bcrypt-hashed at rest, raw value shown exactly once.

Section C

Audit Integrity

Tamper-evident by construction, not by policy.

  • Append-only ledger enforced by database triggers. The audit_log table physically rejects UPDATE and DELETE — at the engine level, not the application.
  • Hash-chain linking: every row's entry_hash is SHA-256 of the previous row's hash plus the new row's payload. Insert a fake row in the middle, the chain breaks, the tampering is visible.
  • 180+ tracked action types across every surface — admin actions, system actions, webhook actions, cron actions.
  • A serial in-process tail guards concurrent writes against racing into the same previous-hash.
  • System-driven events use a sentinel SYSTEM_ACTOR_ID so cron, webhook, and worker events are first-class in the audit trail.

Section D

Data Privacy

GDPR-aligned by design. Not a banner. A lifecycle.

  • GDPR lifecycle: soft delete → 30-day cooldown → automatic anonymisation. Restorable until the cooldown elapses; cryptographically erased after.
  • Data export endpoint serves right-of-access requests in a machine-readable format.
  • Consent-gated analytics — no Umami tracking pixel until the visitor opts in.
  • Per-column encryption of all PII: names, emails, addresses, tax IDs, payout details, OAuth tokens.
  • 7-year invoice retention for tax/legal compliance; everything else erasable on request.
  • Self-hosted Umami means no third-party analytics processor — your visitor data does not leave our infrastructure.

Section E

Infrastructure

Single-tenant. SSH-key only. No public database port.

  • Single-tenant Hetzner dedicated server (CCX33). Not shared hosting. Not a VPS pool.
  • SSH key-only access — password authentication is disabled at the sshd level.
  • Postgres has no public port. The database is reachable only from inside the container network.
  • Cloudflare proxy fronts every public hostname with TLS termination and DDoS shielding.
  • Backups via pgBackRest: full, differential, and incremental schedules with point-in-time recovery to three destinations — local, Hetzner Storage Box, and Cloudflare R2.
  • EasyPanel-managed Docker Swarm for orchestration; rolling deploys with health-gated promotion.

Section F

Compliance Posture

Regulation is engineering work. We treat it as such.

  • GDPR — Articles 6, 7, 12–17, 20, 25, 30, 32, 33 mapped to code-level evidence in our compliance matrix.
  • FTC 16 CFR Part 255 — automated weekly disclosure audit for affiliate program. First flag is a notice; sustained non-compliance escalates to commission holds and program termination.
  • IRS 1099-NEC — automated annual generation pipeline via Track1099, threshold-driven.
  • CCPA — same controls as GDPR, with California-specific opt-out surfaces where required.
  • WCAG 2.2 AA — accessibility treated as security of access. Lighthouse 100% enforced in CI on every build.

Section G

Monitoring

Watch the watchers. Then watch them again.

  • GlitchTip self-hosted error tracking. No third-party error processor; no exception data leaves our infrastructure.
  • 25+ scheduled jobs each monitored by a Healthchecks.io dead-man switch. If a cron misses its window, on-call gets paged.
  • Uptime monitoring via Checkmate with a public status page.
  • Privacy-first analytics — self-hosted Umami, consent-gated, cookieless.
  • Per-cron success and failure pings via pingHealthcheck — the absence of success is a failure, by design.

Questions about our security posture?

We're happy to walk a CTO, compliance officer, or curious operator through the architecture. Send a message — we'll set up a call.

Let's talk