Data handling
Data inventory
Section titled “Data inventory”| Data | Where | Leaves the bank? |
|---|---|---|
| Closing documents (PDFs) and rendered pages | documents volume, content-addressed by SHA-256 |
never |
| Extracted terms, findings, approvals, boarding records, wire requests | database | only to the bank’s own core (jXchange) or export folder, when a person commits a boarding or exports a wire |
| Evidence chain | database (append-only) | only when the bank exports a packet |
| Settings, including SMTP, core and OIDC credentials and the signing key | database; secrets AES-256-GCM encrypted with the master key | never |
| Users, roles, TOTP secrets (encrypted), API-key hashes, sign-in events | database | never |
| Template-studio samples | documents volume, by hash |
only the sample’s page text, and only if an administrator uses Suggest with ai.endpoint set; see below |
| Heartbeat | posted to metering.endpoint |
install id, version, period, closed-loan count, document page count, coarse health and the license key; see Metering. Off in air-gapped mode. |
| Diagnostics | GET /v1/diagnostics |
only if an operator sends it to support; it contains no loan data |
There are no subprocessors for loan data.
Optional outbound connections
Section titled “Optional outbound connections”Each is configured by the bank and can be left unset:
- Core boarding (
core.jxchange.*) or the export folder (core.file_export_path): the mapped boarding record, after checker approval. - SMTP (
smtp.*): sign-in links, invitations and assignment notices. Emails carry links and loan references, not documents. - OpenID Connect (
auth.oidc_*): the standard authorization-code exchange with the bank’s identity provider. - Metering (
metering.*): the daily heartbeat above. - Template suggestions (
ai.endpoint,ai.model,ai.api_key): when an administrator asks the template studio to Suggest a template, Bookend sends the text of the uploaded sample document, plus the field catalog and document taxonomy, to that OpenAI-compatible endpoint. It is blank by default, which disables Suggest. Point it at a model inside the bank’s network (Ollama, llama.cpp server and similar work), or use a hosted model only with a sample that contains no customer data. The model never sees production loans; pipeline extraction does not use it.
Protection in transit and at rest
Section titled “Protection in transit and at rest”- TLS at the bank’s terminator; inside the compose network, plain HTTP on one isolated bridge.
- Secrets encrypted at rest with
BOOKEND_MASTER_KEY(32 random bytes the bank holds). Losing the key means re-entering every secret. - Passwords hashed with Argon2id; sign-in link, refresh-token and API-key material stored as SHA-256 hashes.
- Documents are immutable once stored; the chain hashes reference them.
Retention
Section titled “Retention”documents.retention_days (default 2,555 days, about seven years) is enforced by a nightly sweep at 04:00 UTC. It deletes the stored PDF bytes and page renders of loans sealed longer ago than the policy. Database rows (metadata, SHA-256 hashes, extracted values, findings and the evidence chain) are kept, so a sealed packet still verifies and still names every document by hash. A file shared with a loan that is still inside the policy is kept. The last sweep’s result is shown in Diagnostics. Template-studio samples are not purged by the sweep. Backups and restores are documented in Backup and restore.
Logging
Section titled “Logging”Structured logs go to stdout for the bank’s collector; loan references appear, document contents and extracted values do not. The data audit (GET /v1/audit?source=data) records row-level changes on business tables with the actor; secrets are excluded from before and after values.
Support access
Section titled “Support access”Support has no access path into a deployment. Diagnostics and logs are shared by the bank; loan documents never need to leave the institution for a support case.