Compliance answers in minutes
Encryption, capability catalog, SSO, hash chain, redaction — every claim maps to a subsystem. We can produce a one-pager from the platform itself.
AES-256-GCM master-key encryption with online rotation. Append-only audit log with SHA-256 hash chain and actingAsOrgId for delegation. Published capability catalog (12 operational + 7 provider) at /v1/capabilities. Email/password plus Google, Microsoft, and Apple Sign-In. PII redaction on every log path.
Overview
Persisted secrets — IMAP credentials, webhook signing secrets, app-level configuration — are encrypted with AES-256-GCM under a master key supplied via env. Rotation is online with both old + new keys present during migration. Identity is via email/password (bcrypt with reuse-window) plus Google, Microsoft, and Apple Sign-In. Sessions are opaque, server-side, with idle and absolute TTLs. Access control runs against a published capability catalog of 12 operational + 7 provider capabilities, exposed at /v1/capabilities; the JWT carries an org_roles claim and audit rows carry actingAsOrgId so cross-tenant delegation is unambiguous in evidence packets.
AES-256-GCM via SecretEncryptor. Master key supplied via env; rotation supported online with the previous key still readable during migration.
12 operational capabilities (loan.read, loan.write, loan.share, loan.price, ratesheet.activate, lock.commit, etc.) + 7 provider capabilities. Published at /v1/capabilities for client integrations.
Every cross-tenant action writes actingAsOrgId into common_audit_log. Wholesale lenders can prove which originator instigated each request.
Google, Microsoft, and Apple Sign-In. Apple's client_secret JWT is signed at runtime from an operator-supplied P-256 key, never persisted.
New sign-ups land in PENDING. An admin approves or rejects; both paths trigger branded transactional emails. No automatic admin escalation.
Repeated failed logins lock the account on a sliding window. The lockout decision is rate-limited via bucket4j on Redis to prevent enumeration.
PiiRedactor scrubs emails, phones, SSN-shaped numbers, and PANs from every outbound log and audit payload before persistence — including OTLP spans.
SafeUrlValidator blocks loopback, private, link-local, and cloud-metadata IPs. Per-service host allowlists for outbound integrations (scrape, webhook target, IMAP).
common_audit_log linked by SHA-256(prevHash || canonical(row)). Mutating a row is detectable on the verify endpoint.
Postfix/Dovecot/Rspamd mail stack with DKIM/SPF/DMARC, TLS, and SAFE-DEFAULT relay. Certs migrated to Let's Encrypt HTTP-01 in 2026-05.
How it works
Numbered steps from input to output. Each step maps to a specific subsystem you can inspect via OpenTelemetry.
Anything sensitive (IMAP password, webhook secret, app setting) goes through SecretEncryptor before insert. The DB only sees AES-256-GCM ciphertext + a per-row IV.
Email/password (bcrypt with reuse-window check), Google OIDC, Microsoft OIDC, Apple Sign-In. All four converge on the same opaque session ID.
The browser holds an HttpOnly cookie containing an opaque session ID; the server-side store maps it to user identity, capabilities, and the upstream auth token. Never a JWT.
Capability checks run at the api-service layer before the call hits the rule engine or persistence. Denials return RFC 7807 with a stable correlationId.
Set PRICING_MASTER_KEY_PREVIOUS to the old key and PRICING_MASTER_KEY to the new one; SecretEncryptor decrypts with previous, encrypts with current. Re-encrypt rows via the rekey endpoint, then drop the previous.
GET /v1/admin/audit/verify recomputes the hash chain (including actingAsOrgId) and reports the first break, if any. Run it on a schedule from your monitoring stack.
Hands on
Live cURL sample — copy, paste, ship.
# Read the published capability catalog
curl https://api.ratestack.com/v1/capabilities \
-H "X-API-Key: $RATESTACK_KEY"
# {
# "operational": [
# { "key":"loan.read", "description":"Read loans within scope" },
# { "key":"loan.write", "description":"Create or update loans" },
# { "key":"loan.share", "description":"Grant TTL visibility to another org" },
# { "key":"loan.price", "description":"Run pricing on a loan" },
# ...
# ],
# "provider": [
# { "key":"provider.ratesheet.publish", ... },
# { "key":"provider.lock.commit", ... },
# ...
# ]
# }Why this matters
Encryption, capability catalog, SSO, hash chain, redaction — every claim maps to a subsystem. We can produce a one-pager from the platform itself.
actingAsOrgId makes wholesale and TPO audits trivial. Every cross-tenant action carries the grantor org id in its audit row.
Online rotation means no maintenance window. Roll services with both keys, re-encrypt, drop the old. Done.
Frequently asked
Today we ship Google, Microsoft, and Apple. SAML and arbitrary OIDC are available on Enterprise; talk to sales for activation.
12-character minimum, no common-password matches, no repeats from the last N passwords (configurable, default 5), bcrypt at cost 12. Account lockout after sustained failures.
Sessions are server-side — revocation is a row delete; effective on the next request. We revoke on password change, role change, and explicit admin action.
On Business and Enterprise tiers, yes. The setting is per-organization and gates the UI in addition to the API.
It is supplied via env (PRICING_MASTER_KEY). We do not persist it. Rotation requires both keys present during the overlap window. KMS integrations are available on Enterprise.
When org A holds a delegation grant from org B and uses it to operate on a loan, the audit row records actingAsOrgId=B and actor.orgId=A. Wholesale and TPO audits get unambiguous evidence of who initiated each action under whose delegation.
How we compare
Specific angles, not generic feature checklists. Each row links to a longer side-by-side; we're transparent about where competitors are the better choice.
Append-only audit log with SHA-256 hash chain and actingAsOrgId — wholesale delegation is unambiguous, not inferred.
See the side-by-sideOnline master-key rotation, per-tenant encryption, and a published capability catalog endpoint.
See the side-by-sidePII redaction is on by default in every outbound log — not an Enterprise-tier checkbox.
See the side-by-sideComparisons reflect each vendor's public positioning. Where a fact is unverifiable, we mark it "Depends" or "Unknown" instead of guessing.
Related capabilities
Ready to see it on your data?
We'll spin you a sandbox, load your actual ratesheets, and walk you through this capability against your top scenarios.