Security Posture and Threat Model
RiffDB’s alpha target is a controlled Linux deployment. Application gRPC can use verified direct TLS or a protected Unix socket; hosted MCP supports literal-loopback cleartext or verified direct TLS. The system is not hardened for an untrusted internet-facing or shared multi-tenant service.
The source-build TLS dependency baseline is pinned to rustls 0.23.46 and rustls-webpki 0.103.14 with the existing ring provider. This addresses RUSTSEC-2026-0285, which concerns handshake messages crossing encryption-key boundaries. Peer verification, transport limits and capability authentication remain required; there is no insecure fallback or application-selectable provider.
The 0.23.46 patch also addresses RUSTSEC-2026-0346 through RUSTSEC-2026-0349, with no TLS provider or feature-set change. See the upstream release.
Trust Boundaries
riffdbdowns authoritative storage, key providers, authentication, authorization, command execution, sequencing, and atomic persistence.riffdb, the Rust SDK, hosted MCP, andriffdb-mcpare public clients. None may open redb or construct a privileged service.- MCP tool discovery and invocation are policy filtered. Maintenance is not an MCP operation.
- Administrative V3 replication requires the explicit
ReplicateChangelogpermission, global tenant scope and all partitions. Application-role grants and bootstrap convenience capabilities cannot carry it. Each release uses current policy, and the RPC requires direct TLS or a protected local socket. The outbound replication peer requires an explicit protected CA file and exact server-name TLS verification before any credential is sent. It exposes no arbitrary-channel or cleartext constructor. Receiver connections verify the configured source lineage and complete durable transfer before allowing offline materialization; receiving bytes alone never grants readiness. See follower administration. - Projection and outbox workers consume committed authoritative state. Their failure may degrade service but cannot roll back a commit.
- The deterministic runtime receives checked inputs and reserved logical time; it has no ambient I/O, clock, or randomness.
- Row-policy source, principal-fact schemas, and role selection are compiler inputs. Application requests cannot submit a predicate, fact, evaluator, or bypass. The row-policy reference records the current compiler/runtime boundary.
- Symbolic application export has distinct Capability V5 authority. Entity, event, provenance, public-audit, capability-administration, and backup rights do not imply export. Principal-filtered scope requires the exact current V4 role/policy extension; whole-application scope requires an explicit named lineage under global tenant and all-partition scope.
- Compiler-owned application reimport has distinct Capability V7 authority. It binds one exact destination installation campaign, contract lineage, portability-manifest hash, and principal-filtered or whole-application scope. Every reimport grant also carries an exact compiled application-role identity and row-policy grant; whole-application scope does not disable that policy.
Primary Threats
| Threat | POC control | Residual limit |
|---|---|---|
| Unauthorized mutation | Opaque capabilities, current-state policy, shared service path | No production identity provider |
| MCP tool overexposure | Authorization-filtered catalogs and stale-name denial | Hosted transport requires loopback or verified direct TLS |
| Credential disclosure | Exact protected-file rules, zeroizing custody, redacted errors | Local root can read process/state |
| Retry duplication | Canonical input hash and principal/command/key identity | Restore can erase the suffix containing an idempotency record |
| Torn authoritative state | One commit coordinator and atomic storage transaction | Process/storage defects remain possible |
| Malformed input exhaustion | Bounded parsing, scans, waits, schemas, and diagnostics | POC limits are not production SLOs |
| Logging leakage | Closed telemetry vocabularies before subscriber layers | Operator-added subscribers require review |
| Corrupt storage | Complete startup structural/catalog validation, fail closed | No privileged repair tool |
| Backup path traversal | Checked name joined only beneath server-owned root | Backups are not encrypted |
| Destructive restore abuse | Exact confirmation plus current and staged authorization | History-incarnation fence; residual risk is non-participating clients |
Deployment Rules
- Keep cleartext application gRPC and hosted MCP on literal loopback. Remote
application gRPC and hosted MCP must use the
direct_tlsprofile; same-host/sidecar clients may use a protectedlocal_socketprofile for application gRPC. - A TCP or HTTP/2 proxy may forward verified TLS, but forwarded identity, tenant, database, principal, and authorization assertions are ignored. The normal RiffDB bearer credential and database selector remain mandatory.
- Keep the database file, backup root, capability digest-key file, and idempotency digest-key file lexically disjoint. The packaged layout does so.
- Make the
riffdbservice account the only writer to the database directory. Never run tworiffdbdprocesses against one database, and never grant the CLI, MCP bridge, backup utilities, or another service direct write access. - Own secret files by the exact service effective user at mode
0600. - Protect TLS private keys with no group or other permission bits. Replace the certificate and key atomically; an invalid replacement retains the last valid identity for new handshakes.
- Give the optional MCP bridge a narrowly scoped normal capability. Never use the bootstrap document as its long-lived credential.
- Treat membership in the
riffdb-mcpsocket group as access to the bridge capability. - Protect backup artifacts and receipts even though they contain no digest-key documents.
- Inspect only structured, redaction-safe output. Do not add raw business values, tokens, filesystem paths, or arbitrary error strings to telemetry.
The systemd units remove ambient capabilities, deny privilege escalation, restrict writable paths, devices, namespaces, kernel interfaces, address families, and non-loopback IP traffic. The bridge units have no access to the RiffDB state directory. Hardening is defense in depth; application-enforced loopback and authorization rules remain authoritative.
Incident Handling
For suspected bearer compromise, revoke the capability through the public
service and replace the credential file. Replacing a file alone does not revoke
the durable capability. Operators can list and inspect issued or revoked
capabilities without exposing bearer tokens or secret verifiers using
riffdb capability list and riffdb capability show, either against a closed
database file (--database-path <PATH>) or against the local non-secret
operator inventory ledger (--inventory-file <PATH>).
For digest-key compromise, stop admission and obtain architecture review before rotation. Capability and idempotency keys are distinct typed namespaces and must not reuse material. Preserve required readable keys during rotation.
For storage or receipt corruption, stop. RiffDB intentionally fails readiness closed and has no online repair path. Restore only from a fully validated offline backup and account for the destructive rewind limitations.
Capability-create JSON may include a bounded grant.export.applications
array. Each entry names one contract lineage, selects principal_filtered or
whole_application, and explicitly selects entities, events, provenance, and
public audit. At least one of entities or events is required. This authority
surface is separate from ordinary read or administrator credentials.
An operator capability for reimport adds grant.reimport alongside its
compiler-derived grant.row_policy and matching
application_role_identity permission. The reimport object accepts only:
{
"contract_lineage": "TicketDesk",
"campaign_id": "01900000-0000-7000-8000-000000000043",
"portability_manifest_hash": "4343434343434343434343434343434343434343434343434343434343434343",
"scope": "whole_application"
}
The campaign ID must be the exact destination installation UUIDv7 and the hash must identify the canonical adapter-owned portability manifest. Changing either identity, using the capability against another database, dropping the row-policy grant, or widening a principal-filtered grant fails closed. This authority is not advertised through application command discovery or MCP.
Follower read audit boundary
The accepted follower service audit boundary keeps the follower applier as the sole writer. The follower service component retains current authorization and redaction for reads. Authorized Health/Statistics and authenticated read denials produce bounded redacted operational telemetry, with no durable local service audit guarantee. Denials release no protected data. Telemetry cannot satisfy a policy-required durable audit obligation; standard reads with that obligation return the typed follower-mode refusal before releasing data. Applications requiring durable audit of reads or denials must use the primary. Primary audit behavior and replicated audit records are unchanged.
The daemon and process crash tests exercise this boundary across restarts. See follower administration before planning deployment.