How Coriqo protects the record, and what we don't have yet.
Your vendor-risk team answers for every system that holds your AI evidence. Everything on this page is in the product today. Architecture diagrams, sub-processors and the full questionnaire are in our security pack, available under NDA.
Last verified 15 September 2026
In short
- Each customer's data lives in its own database schema.
- The evidence record is append-only, enforced by the database itself.
- Checkpoints are signed with Ed25519 and verifiable offline against our public key.
- Single sign-on with Microsoft Entra ID, Google Workspace, or any OIDC issuer.
- Self-hostable, including with no outbound network access.
- AI providers can be set so your data stays inside your own cloud.
Identity and access
Your examiner will ask who could see or change the record. These are the controls that decide that.
Single sign-on
Users sign in with a password or through OIDC single sign-on with Microsoft Entra ID, Google Workspace or another standard identity provider. Single sign-on does not create accounts. An administrator creates each user first.
Role-based access
Access is granted through named scopes for reading, writing, review, approval, export and administration. Each scope is granted separately. Every request must be authenticated unless the route is on a short reviewed list, and a test fails the build if a new route is added without either.
Examiner access
An administrator issues an examiner a read-only token with an expiry date, so a regulator needs no account. Revoking a token takes effect on the next request, and every examiner read is logged.
Service accounts
Pipelines use scoped API keys. A key is shown once when it is created and then stored only as a one-way hash, so nobody can read it back from the database, including us.
Operator sign-in limits
Coriqo staff sign in to a separate operator console. In production three counters apply, each over 15 minutes: 5 attempts for one username from one IP address, 30 for one username across all addresses, and 30 from one address across all usernames. Usernames are counted the same however they are capitalised or padded. Customer sign-in allows 10 per IP. Past any limit, requests get HTTP 429 and the refusal is recorded. A successful sign-in does not count toward any limit, and someone who only knows an operator's username blocks their own address, not the operator's. The client IP is the entry our hosting provider's proxy adds to X-Forwarded-For, never the part of the header the client sends, and the web server does not apply proxy headers itself. The limits stay on if Redis, which holds the shared counters, is down: each API worker then counts on its own, so the real ceiling is the limit times the number of workers, and it resets when a worker restarts. Known gaps: 30 wrong passwords sent from 30 or more addresses still lock a username everywhere for 15 minutes; one address can try 30 usernames per window; and the IP logic assumes exactly one proxy in front of the app, which we have not yet checked against our production proxy. This control does not require a second factor.
Record of operator actions
Coriqo staff actions go to a separate hash-linked log: staff sign-ins, including failed and rate-limited attempts; creating or deactivating a staff account; resetting a staff password; draining a database; editing the feature catalog; quarantining or recycling a tenant schema; and deleting a tenant. Each entry carries the hash of the entry before it, so editing, deleting or reordering an entry breaks the chain, and the verification check reports where. Apart from sign-ins, an action and its log entry are saved together: if the entry cannot be written, the action does not happen. Deleting a tenant or recycling a schema cannot be undone, so a "started" entry is saved first, and if that fails nothing is deleted. The application's database account can only read and add entries, and database triggers reject updates and deletes. Once an hour, if there are new entries, a scheduled job signs the latest entry and the entry count with the deployment signing key, publishes that to the Sigstore Rekor public log, and adds the Rekor receipt to the log. Known gaps: sign-ins are recorded best-effort, so staff are not locked out when the log cannot be written, and a sign-in can be missing during that outage (the failure goes to our error monitoring). Nothing yet compares the log with Rekor automatically, so entries removed from the end of the log are only caught by a manual comparison. Someone with database owner access can remove the triggers. A deletion that fails partway can leave a "started" entry with no "finished" entry. The first staff account created at deployment is recorded best-effort. Staff actions from before this change stay in the ordinary audit log. The newest entries can go up to an hour without an outside copy, longer if Rekor is unreachable.
SCIM provisioning
SCIM 2.0 lets your identity provider create, update and deactivate users in Coriqo.
Data protection and tenancy
Your reviewers need to know how your data is kept apart from other customers' and how it is protected in transit and at rest.
Tenant isolation
Each organization's data lives in its own PostgreSQL schema. The application selects that schema on every request and again at the start of every transaction.
Encryption
Traffic is encrypted with TLS. Stored files are encrypted at rest, and the upload itself requests encryption rather than relying on a storage default. Hosted customers choose their data region in the contract. Self-hosted customers choose where everything runs.
Tamper evidence
A record only works as evidence if the people relying on it can check that nobody changed it afterwards, without taking our word for it.
Append-only record
Governance changes are hash-chained. Database triggers refuse edits and deletes on the governance and audit tables, so the application cannot change past entries.
Signed checkpoints
Chains are sealed into Merkle trees, and each tree head is signed with Ed25519. You can check any event offline against our public key with a verification tool we publish. The check does not contact Coriqo.
Public transparency anchoring
Each checkpoint is recorded in the Sigstore Rekor public transparency log when it is sealed. We send only a digest of the signed tree head and our public key, never governance content. Each checkpoint is also time-stamped by DigiCert's public RFC 3161 time authority, unless an operator turns that off (an air-gapped deployment does). A checkpoint can still be verified from our signature if the log is unreachable. If a submission fails, a scheduled job tries again, waiting 5 minutes after the first failure and up to 6 hours between later tries. It stops after 20 attempts, and an administrator can then retry by hand. No database transaction stays open during the call to Rekor, and a row lock stops the scheduled retry, the attempt made at sealing and a manual retry from working on the same checkpoint at once. An operator can turn anchoring off for a whole deployment; checkpoints still seal but stay pending, and the unanchored-checkpoint alert keeps running. A checkpoint signed with a revoked or unknown key, or an old V1 checkpoint, is never anchored, and deployments whose signing key is held in a cloud KMS cannot anchor yet. The retry path is tested against Postgres, our production database: a Rekor call slower than the database's idle-transaction timeout, two retries racing on one checkpoint, and a late result arriving after another retry succeeded. The scheduled job's loop over tenants is tested on SQLite only.
Countersigned by your own people
When someone at the bank signs in with a passkey, the sign-in challenge is a hash of the newest checkpoint's signed tree head plus a random value, so the passkey's answer is that person's signature over the checkpoint. The private key stays on their device or in their password manager; Coriqo stores only the public key. One countersignature covers every record sealed up to that checkpoint. It is on by default for every plan, a bank admin can turn it off, and anyone at the bank can also countersign on demand. Our verification tool checks each countersignature and counts it as the bank's only when the key is in a keyring file the bank keeps; each person also gets an email with their key's fingerprint when they add a passkey. Known limits: Coriqo serves the sign-in page, so it could ask someone to countersign a forged checkpoint, but it cannot change one already countersigned without breaking the chain's append-only check and the public log. Records sealed after the last countersignature rest on our signature and the public log until someone signs in again. Examiners, outside firms and people signing in with a password and code do not countersign.
Independent witness cosigning
A checkpoint can carry a second signature from an outside witness who holds their own key. Our verification tool checks those signatures. No outside witness has signed up yet.
AI usage
Your board and your examiner will want to know whether AI made any decision in the record, and where your documents go when AI reads them.
AI drafts, people decide
AI features such as examiner-reply drafts, minutes parsing and challenge narration produce drafts. A person approves each governance decision, and the record names that person. Two things are recorded without a person approving them: verdicts from an enrolled agent runtime, signed with that device's own identity, and AI answers, stored with their citations so they can be checked later. Neither is a governance decision.
Grounding
AI answers draw on your own stored records. Each citation is checked against a real record, and an answer that cites something missing is retried or not shown.
Providers, and where your data goes
You choose the language-model and embeddings providers for each tenant. Use our defaults, or point Coriqo at an OpenAI-compatible endpoint in your own network, Azure OpenAI in your Microsoft tenant, or AWS Bedrock in your AWS account, so document text stays inside your cloud. Administrators change this under Settings, AI & Billing. We recommend choosing a provider inside your cloud before uploading real documents.
Integrations
Each connection into your systems is another way in, so here is what each one can read, what it stores and what it never does.
Inbound email
Examination correspondence and committee minutes can arrive by email. Each inbound message is authenticated before Coriqo reads it, and a message that fails is rejected.
Microsoft Teams
Capture is off for every channel until an administrator turns it on for that channel. Financial identifiers and credentials are redacted before a message is stored. Stored text can be erased without breaking the evidence record.
Read-only connectors
Discovery connectors read your model registries and cloud accounts and never write to them. Your source systems stay the system of truth.
Alert delivery
Alerts go out by webhook, Slack, email, Teams, PagerDuty and Opsgenie. Webhook and Slack sends work like this:
- Signed webhooks. A webhook in Coriqo's own format gets a signing secret when you create it, shown to you once. Every request carries a
Coriqo-Signatureheader,t=<unix time>,v1=<hex>, where the hex is an HMAC-SHA256 of<timestamp>.<body>under that secret. Every request also carries aCoriqo-Deliveryid that stays the same when a delivery is retried, so your receiver can drop duplicates. Slack messages are not signed: the Slack webhook URL is the credential, and Coriqo accepts only URLs onhooks.slack.com. - HTTPS to public addresses only. A target must use https. Coriqo refuses any host that resolves to a private, loopback, link-local or other internal address, which includes cloud metadata endpoints such as 169.254.169.254. The check runs when you save a target and again every time an alert is sent. Coriqo then connects to the exact address it checked, so a DNS change between the check and the send cannot point the request somewhere else. Redirects are not followed.
- Retries, then dead. A failed send is tried again after 30 seconds, 2 minutes, 10 minutes and 30 minutes. If the fifth attempt fails, the delivery is marked dead. When the alert belongs to a model version, that outcome is also sealed on the version's governance chain. A 4xx response other than 408 or 429 is marked dead at once, because sending the same request again will not fix it.
- "Delivered" means your receiver returned 2xx. It never means a person saw the alert. Acknowledgement is recorded separately, with who acknowledged and when.
- Metadata and a link, nothing more. The payload carries the alert's category, severity, title, status, times and a link back to Coriqo. It never carries evidence text or people's names. Who acknowledged or resolved an alert is sent as a kind (a person or automation), and the name stays in Coriqo.
Evidence Connect: where credentials live
Jira, GitHub and SharePoint credentials are stored by a connector runtime we operate, scoped to your tenant, never in Coriqo's application database. The runtime is software we run on your behalf, not a third party we send your data to. Raw records it pulls live in a separate store under your tenant's namespace; a read-only role in our application reads only the fields your approved mapping names. Retention of raw records is a window you set per source; deleting them automatically once that window passes is not yet built. See "What we don't have yet" below.
Resilience
If something fails, the record has to come back intact. This is how we check that it does.
Backups and restore
Encrypted backups run nightly to separate storage. Once a month an automated drill restores the latest backup into a scratch database and checks that the governance chain still verifies.
Audit trail
Every state change and every examiner read is written to an append-only audit log that database triggers protect.
What we don't have yet
You should hear about gaps from us before you rely on the record. The known limitations page has the full dated list.
- A SOC 2 report or another third-party security certification. SOC 2 is in progress.
- An independent cryptographic review of the sealing core.
- An outside witness cosigning our checkpoints. The feature is built.
- Enforced evidence-file retention. You can record a retention period, but files are not yet deleted when it ends. The same is true of Evidence Connect's raw-record retention window.
- Kubernetes manifests or a Helm chart. The container runs under Kubernetes; we don't ship the chart.
- Continuous connectors for most systems. Evidence Connect runs daily or manual sync from Jira, GitHub and SharePoint today; every other system still comes in by file import, with a review step before anything is applied.
- A customer-hosted Evidence Connect data plane. Running the connector runtime inside your own environment is on the Enterprise roadmap, not available today.
- Built-in on-call routing such as SMS, on-call rotations, or a PagerDuty or Opsgenie app. Alerts reach PagerDuty and Opsgenie through their events APIs today (opened, acknowledged and closed from Coriqo), alongside webhook, Slack, email and Teams.
Evidence Connect: licensing position
The connector runtime behind Evidence Connect is software we operate ourselves, inside our own infrastructure, on your behalf. It never receives your data as an independent third party would. Our internal review of that software's license terms, and the specific self-hosting and hosted-service distinctions it draws, is available on request under NDA.
Report a vulnerability
Email security@coriqo.io, or see /.well-known/security.txt. We fix confirmed issues and credit reporters privately unless they ask otherwise.
Request the full security pack.
Under NDA we send the full questionnaire, architecture and data-flow diagrams and our sub-processor list. We can also complete your own questionnaire, such as SIG Lite.