Security
How Propus decides who sees what, and how it protects data at rest and in transit.
Identity
Every engine checks the caller itself; none trusts another engine to have done it.
| Credential | Stored as | Notes |
|---|---|---|
| Server admin key | SHA-256 hash | Printed once by init; root-only file when installed |
Database key (pk_…) | SHA-256 hash | The secret in the database's URL; admin for that database; resettable |
Role key (pk_…) | SHA-256 hash | Carries a role, tenant and user |
Token (pt_…) | signed, not stored | 30 s to 1 h, bound to its key's role and tenant; revoking the key kills its tokens |
| Console session | HTTP-only cookie | Password hashed with Argon2id; one account per server |
Row-level security
On for every new table. Roles other than admin see nothing until a policy allows it:
CREATE POLICY own_tenant ON invoices USING (tenant_id = current_setting('propus.tenant'))
WITH CHECK (tenant_id = current_setting('propus.tenant'));
GRANT SELECT, INSERT, UPDATE ON invoices TO app;
The same tenant boundary holds in FlashCache (a keyspace per database), PulseStream, ObjectCore and TrackSense (tenantColumn). The console's Tables › Access check runs a query as any role and tenant.
Data at rest
propus init --encryptencrypts row values and audit entries with AES-256-GCM (the installer does this by default). The key file is kept apart from the data and its backups;propus rotate-keyre-wraps the data key.- Secondary-index keys are stored as they sort, so an indexed column's values are readable in the file; index only what may be.
- Pages are checksummed; damaged data is reported, never served.
- Backups are integrity-checked before they count and carry a SHA-256 manifest that
restorechecks.
In transit
--tls-cert/--tls-keyfor HTTPS;--protocol-tls-cert/--protocol-tls-keyfor the Postgres, Redis and Kafka protocols. Certificates reload when their files change.- Kafka clients authenticate with SASL PLAIN; S3 with SigV4 using secrets derived per database.
Replicas
- A replica authenticates to its primary with the replication secret (kept as a hash on the primary); use HTTPS between them (
--primary-cafor a private CA). - Replicas receive the data as stored, still encrypted, so a replica needs the primary's key file to read it; its database keys and the console account are the primary's.
- A replica refuses every write, over every protocol.
The installed server
- Runs as the unprivileged
propususer in a sandboxed systemd service. - Keys and settings:
admin-key600 root,master.key,propus.envand the TLS key 640 root:propus. - Releases are signed (Ed25519); the installer checks the signature and the checksum before running anything, and rolls back an upgrade that fails its health check.
Not yet
Request rate limits beyond console sign-in, and two-step sign-in for the console.
Reporting a vulnerability
Please report privately to the maintainers rather than in a public issue.