Security

Where credentials live, and what the proxy can actually see

AccessFlow is a full proxy, not a gateway. It terminates the user's session, holds the database and API credentials itself, and is the only thing that ever opens the real connection — under whatever policy you configure, from a multi-stage approval chain down to an audited break-glass path. That decision settles the three things a security reviewer asks about first: where the secrets are stored, what the proxy is able to read while a query runs, and what evidence survives afterwards. This page answers all three, and links to the operator chapters that configure them.

Database proxy security architecture — one component holds the credentials

Nobody gets the database password or the API credentials — not even your own team. AccessFlow sits in the middle and is the only thing that ever connects to the real database or upstream API, and only after a request is approved. Users sign in to AccessFlow, never to the target; behind the scenes the proxy holds the real database connection pools and the connectors' encrypted credentials, and reaches out on their behalf.

That single choke point is what makes everything below it possible: the component that decides whether a query may run is also the one that parses it, checks the schema allow-list against the parsed statement rather than against a string, applies masking and row-level security at execution time, and writes the audit record.

CLIENT React SPA · /ws · REST
API GATEWAY REST + WebSocket gateway · JWT · modular service
SERVICE Query & API Proxy
SERVICE Review Workflow
SERVICE AI Analyzer
SERVICE Admin & Audit
INTERNAL STATE PostgreSQL · Redis
CUSTOMER DATABASES & APIS (PROXIED) PostgreSQL · MySQL · MariaDB · Oracle · MSSQL · ClickHouse · custom drivers · MongoDB · Couchbase · Redis · Cassandra · ScyllaDB · Elasticsearch · OpenSearch · DynamoDB · Neo4j · Snowflake · BigQuery · Databricks · REST · SOAP · GraphQL · gRPC APIs
Encryption AES-256-GCM for datasource credentials at rest — or resolve them from HashiCorp Vault, AWS Secrets Manager, or Azure Key Vault via secret references at connection time. RSA-2048 JWT signing. SAML 2.0 keystore.
Runtime Concurrent request-per-task runtime — horizontally scalable behind any L7 load balancer.
Observability HTTP health and readiness probes. OpenTelemetry OTLP trace export of the full proxy pipeline (Tempo / Jaeger / Honeycomb), Prometheus metrics, and pre-built Grafana dashboards (query volume, approval SLAs, AI usage, rejection rates, pool stats). HMAC-SHA256 chained, append-only metadata audit log of every action. Optional one-line-JSON console logs (logstash / ECS / GELF) for ELK / OpenSearch.

Where the credentials actually live

A datasource password is encrypted with AES-256-GCM before it is stored, under a key that lives only in the deployment's environment — never in the database beside the ciphertext it protects. The encrypted column is excluded from serialization on the entity itself rather than filtered per endpoint, so a future API route cannot leak it by accident — there is no response shape in which it appears.

If you would rather AccessFlow never store the secret, a datasource can hold a secret reference instead of a value and resolve it on demand from HashiCorp Vault, AWS Secrets Manager, or Azure Key Vault. Rotating the secret upstream rotates it here, with no redeploy and no copy left behind.

Either way the plaintext has a deliberately short life. It is decrypted once, handed to the connection pool at initialisation, and not retained in application memory beyond that point; the query path works against a warm pool, never against a password.

Three other keys matter operationally, and they are deliberately not all sourced the same way. The RSA-2048 JWT signing key comes from the environment. The audit HMAC key can too, but it is optional — left unset it is derived from the encryption key via HKDF-SHA256, and startup fails if neither is available. The SAML SP signing keypair is hybrid: supply the key and certificate as environment values and AccessFlow uses them verbatim and never persists them; leave them unset and it generates a self-signed RSA-2048 pair on first use, encrypts the private key with the same AES-256-GCM service, and stores it on the saml_config row so it survives restarts. If your policy is that no signing key may rest in the application database, supply that pair explicitly.

None of these is logged or returned by an endpoint. One exception is worth knowing before you grep and find it: the zero-config docker compose up demo stack ships throwaway keys inline so a fresh clone runs with no setup. They are committed on purpose, and every production install path generates or demands its own. Datasource docs →

Who can sign in, and who takes them out

Because nobody holds a production credential, the identity check moves entirely to AccessFlow's front door. So it has to be the front door your company already runs — and offboarding has to reach it without anyone remembering to click anything.

Workforce-ready auth

Sign in with the accounts your company already uses — SAML 2.0 SSO and OAuth 2.0 / OIDC, with built-in templates for Google, GitHub, Microsoft, GitLab, and a generic provider for any other IdP (Keycloak, Auth0, Okta, …). Roles and group memberships sync automatically from your identity provider on every login, with optional TOTP two-factor. With SCIM 2.0 provisioning, the IdP drives the whole user lifecycle: joiners are created, movers re-grouped, and leavers deactivated automatically — sessions and standing access grants revoked the moment someone is offboarded in Okta or Entra ID. One deployment hosts multiple fully-isolated organizations, and a super-admin manages tenants across the cluster — with per-org quotas and a kill-switch that disables an org instantly. Auth & SSO docs → Users & roles docs →

JWT · SAML · OAuth · SCIM provisioning · IdP group sync · TOTP · Multi-tenant orgs · Per-org quotas

What the audit log proves

The proxy is the only thing that talks to the database, so its log is the complete record — and a complete record is only worth something if it can be shown to be complete. A separate, dedicated writer role owns the table and appends the rows, while UPDATE, DELETE and TRUNCATE are revoked from the general application role, which keeps SELECT for the admin read endpoint. That privilege split raises the bar; the hash chain is what makes the log tamper-evident rather than merely tamper-resistant, so an edit made around the split still surfaces as a broken chain.

The AccessFlow audit log: a filterable table of append-only events, each row naming when it happened, which actor triggered it, the action, the resource and its id, and the originating IP address, with export-CSV and verify-chain actions in the header.
/admin/audit-log — every action, its actor and its resource, with a chain-verification pass and a CSV export.

Tamper-evident audit & compliance reports

Every decision is recorded in a log that can't be quietly edited after the fact — append-only, cryptographically chained, and searchable, with CSV export and no row data ever stored. Pre-built compliance reports — classified-data access (PII/PCI/PHI/GDPR) and a DDL/DELETE trail with approver names — export as digitally signed PDF/CSV that verify offline, surfaced to a dedicated read-only Auditor role. And once a permitted query returns, result-export governance decides what may leave: per-datasource policies allow, watermark, row-cap, or deny downloads of classified results — the watermark (who, when, which query) is baked into the signed bytes, every export is audited, and "who downloaded this data" always has an answer. Need it in your SIEM? External audit sinks stream every audit event to Splunk HEC, syslog/CEF (TCP/TLS), or an HMAC-signed HTTPS endpoint, and archive digitally-signed segments to S3 Object Lock for WORM retention — at-least-once off a durable per-sink cursor, a dead sink never blocks the log, and every exported event carries its chain links so the external copy verifies on its own. Audit log docs →

HMAC-SHA256 chain · signed exports · SIEM streaming · WORM archival

What AccessFlow keeps, and what it never touches

The last question is the simplest: sitting in the middle of every query, how much of the data does the proxy keep? None of it. Results stream through; what is written down is the request and the decision.

Does AccessFlow store or copy my data?

No. AccessFlow proxies queries and streams results back without persisting them. Its own database stores the query text, the approval decisions, and audit metadata — row counts and timings, not rows. Datasource credentials are AES-256-GCM encrypted, or held in Vault, AWS Secrets Manager, or Azure Key Vault.

Agents are held to the same line: a query arriving over the built-in MCP server takes the same parse, risk analysis, approval and audit path as one a person submitted, and masking and row-level security apply to the samples it reads. Governed access for AI agents → Install AccessFlow →