Chapter 08

Security

Three optional knobs. Off for dev. On for production. No identity platform reinventing.

Philosophy

DocumentForge is a database, not an identity platform. We provide three simple knobs that cover the common cases — bearer-token auth on the REST API, a shared secret for replication handshakes, and TLS for encrypted transport. Everything else (user accounts, RBAC, OAuth, OIDC) is better handled by an API gateway in front of DocumentForge.

By default everything is off. This keeps the dev loop friction-free. Turn knobs on individually as you go to production.

Threat model

SurfaceDefaultWith all knobs on
REST APIOpen (localhost only by default)Bearer-token auth, TLS
Replication protocolNo handshake secretShared secret required
Cluster inter-shard (HTTP)Plain HTTPTLS + bearer token
Data file on diskOS file permissionsOS file permissions + disk encryption (your job)

Knob 1 — API key (bearer token)

If set, every HTTP request must include:

Authorization: Bearer <your-api-key>

Configure a node

{
  "nodeName": "shard-a",
  "port": 5001,
  "dataDir": "./data/shard-a",
  "security": {
    "apiKey": "sk_prod_abc123xyz"
  }
}

Or via CLI / env:

dfdb serve --node-name shard-a --port 5001 --api-key sk_prod_abc123xyz

# or
DFDB_API_KEY=sk_prod_abc123xyz dfdb serve

From the admin UI

Go to Settings, paste the key. It's stored in localStorage and attached to every fetch. Works offline across page loads.

From your application

using var cluster = DocumentForgeCluster.FromConfig(config,
    desc => new HttpShardTransport(desc.Name, desc.LeaderEndpoint,
                                   apiKey: "sk_prod_abc123xyz"));

The constant-time compare ensures timing attacks don't leak partial-match information.

Knob 2 — Replication secret

Before a follower starts receiving streamed operations from a leader, it presents a shared secret. Mismatch = connection dropped. Prevents attackers on your network from pretending to be followers (siphoning every write) or leaders (injecting fake writes).

{
  "security": {
    "replicationSecret": "rp_xyz789abc"
  }
}

The leader and every follower must agree on the same secret. In C# code:

leader.StartLogicalReplicationServer(port: 5500,
    sharedSecret: "rp_xyz789abc");

follower.StartLogicalReplicationFollower("leader-host", 5500,
    sharedSecret: "rp_xyz789abc");

Knob 3 — TLS

ASP.NET Kestrel handles this; point at a PFX cert file.

{
  "security": {
    "tls": {
      "certPath": "./certs/node.pfx",
      "certPassword": "env:TLS_PASSWORD"
    }
  }
}

When certPassword starts with env:, the value is read from that environment variable at startup — keeps secrets out of config files.

The URL scheme flips to https://. Point clients (including the admin UI) at the HTTPS URL.

Network hygiene

Data at rest

DocumentForge does not encrypt data files. This is intentional — OS-level disk encryption is available, well-audited, and better than anything we'd ship.

Production checklist

What we don't build (and where to go)

NeedWhere to get it
User accounts / RBACAuth0, Keycloak, AWS Cognito in front of the API
OAuth / OIDC / SAMLSame — an API gateway terminates and forwards
Field-level encryptionApplication layer (encrypt before insert)
Key rotation automationHashiCorp Vault, AWS Secrets Manager, Azure Key Vault
Data-at-rest encryptionOS disk encryption (above)
Audit logging to SIEMTap the REST API proxy / gateway you deploy in front
Rate limiting / quotasAPI gateway (Kong, Tyk, Envoy)
Tested: the test suite includes Replication_SharedSecretEnforced — a follower with the right secret connects successfully and receives ops; a follower with the wrong secret is rejected and sees zero ops. Invariant: an attacker can't siphon writes or inject fake ones without the secret.