v1 — 2026-06-10 · SOC 2: audit deliberately deferred until commercially gated; this page is the structural answer.
Audience: InfoSec reviewers, procurement teams, and vendors completing a security questionnaire. This page is honest about what is shipped, what is in progress, and what is explicitly deferred. Every claim cites the artifact or code path that backs it.
A fully-compromised coordinator — stolen disk, compromised process, subpoenaed operator — yields:
It does not yield: original documents (since v0.117 the platform has no document upload and stores no document bytes — only platform-authored sample PDFs exist server-side), decryption keys (the ceremony Content Key lives only in the URL fragment and in exported artifacts — it is never sent to the server), plaintext face images (E2E design; see §2), or the ability to forge a signer's consent (SHA-256 chain integrity; see INV-3 below).
Source: docs/ZERO_TRUST_INVARIANTS.md
| Invariant | Statement | Enforcement evidence |
|---|---|---|
| INV-1 Content integrity | Every document, face, and chain block returned by the server is addressed by its SHA-256; any mismatch is rejected client-side. | blobstore keys are content hashes; verify.verify_chain re-derives every block hash; signer re-hashes the PDF vs the QR code. Tests: test_invariants.test_inv1_*, test_seal_and_qr.test_blobstore_self_verifies, test_verify.test_pdf_hash_mismatch. |
| INV-2 Chain independence | Ceremony validity is decidable from the chain document alone — no server contact required. | verify.verify_chain is a pure function; the browser port chain-verify.js mirrors it. Tests: test_invariants.test_inv2_*, full test_verify.py suite. |
| INV-3 No consent-forging key on the server | The server holds no key whose compromise lets it forge a signer's consent. v1 has no per-signer signing keys; a link is fabricatable only by producing a block whose hash the next signer already committed (SHA-256; computationally infeasible). | Tests: test_invariants.test_inv3_*; code-grep confirms no signer private keys in src/. |
| INV-4 Offline verifiability | A holder can verify a closed artifact with no coordinator. | Verifier SPA + chain-verify.js run fully client-side; OTS proof is checkable against Bitcoin independently. Test: test_invariants.test_inv4_offline_verify_closed_artifact. |
| INV-5 No lock-in | A participant can export and verify independently of the coordinator, for as long as they keep the export — even if COSigna disappears. | Chain document is self-contained JSON; verify_chain accepts it directly; round-trips without loss. Test: test_invariants.test_inv5_export_roundtrip_verifies. |
Corrected 2026-08-18, replacing an earlier simplified table that overclaimed in two places (see the correction note at the end of this subsection). Written from the enemy's-eye view: assume the COSigna operator is compromised, the host seized, or the operator simply lying.
Two kinds of "cannot," never conflated. Some limits are mathematical (a hash preimage, an
AEAD tag, proof-of-work) — they hold against any adversary with the server's data and keys. Others
are structural (a route that does not exist, a key that is never transmitted) — they hold
against this deployed version of the software, enforced by code gates rather than physics. Neither
CANNOT below rests on a server-held key — a guarantee that did would be self-attestation wearing a
signature's clothes. Two keys the server does hold: the Phileos CORE-attestation key and the
witness key (phileos.py, witness.py) — every signature COSigna itself produces is inside the
blast radius of a seized host.
CAN:
/chain export, the anchor
submission, the close itself (invitation dispatch is explicit best-effort in service.py).store.py add_audit) — even for "secret" ceremonies (secret mode 404s
the public read-model; it changes nothing about what the server itself stores).doc_hash, and
(unless the organizer chose "omit/encrypt filename") the plaintext filename. It does not
hold the document body — see CANNOT #1.chain.py's block-hash function never includes the roster). There is no exposed reorder API,
but a malicious server needs none — it writes the DB directly. Confirmed gap, tracked as D1;
closing it (committing roster/order/window into the genesis chain link) is a scoped, ruled,
in-progress fix (NEOCORTEX engineering record) — not yet a shipped guarantee.auth.py) and act
as that participant at the HTTP layer. It still cannot produce that person's face under an E2E
ceremony key — see CANNOT #3.CANNOT:
tests/test_server_s5.py, tests/test_server_s4.py). This is enforced by route-absence
plus a code gate, not by mathematics — a future version could add an upload route back.tests/test_verifier_kernel_guard.py). This binds a presented pair — it is not by itself a
defence against a chain rebuilt wholesale before anchoring; see CANNOT #5.face_hash (and its blob) already held
within the same ceremony, since the content key is shared there.scripts/build_offline_verifier.py/cosigna-verifier-offline.html), which makes no network
request except an optional human-clickable mempool.space link. No COSigna endpoint, account, or
uptime is required to check a proof.prev; altering any earlier block breaks every later one. Against a holder who already has a
copy, or against a chain whose CLOSE hash is Bitcoin-confirmed via OpenTimestamps, a rewrite is
detectable. Two conditions are load-bearing: (a) anchoring is opt-in, off by default on the
create API; (b) OTS returns a pending status on submission and only becomes complete once
Bitcoin-confirmed — until then the anchor commits nothing an adversary must respect. Absent a
confirmed anchor and a counterparty's own copy, a server holding all the blocks can rebuild the
whole chain, including in a different order — see CAN #5.Honest boundary — three gaps this statement does not paper over. (1) Ordering/roster integrity (CAN #5): until D1 lands, "the server is blind" is true for the document body and for E2E faces, not yet for sequence. (2) Every signature COSigna makes is self-signed (CAN #9): the CORE attestation, envelope seal, and witness signature all use server-held keys — they carry weight against third parties and none against the operator. The only trust root outside the server is the Bitcoin anchor, which is opt-in and only binding once confirmed. (3) Document blindness, the strongest property, is structural rather than mathematical (CANNOT #1) — genuinely enforced by a test gate today, but a property of this version, not a law.
Correction note (2026-08-18): the prior table on this page claimed the server "cannot substitute the document or a face undetectably" and "cannot backdate closure past what OTS attests" without qualification. Both overclaimed — see CAN #5 (roster/order mutability, an open gap) and CANNOT #5 above (anchoring's two load-bearing conditions). This section replaces that table with the fuller, independently fact-checked statement above.
Cookie-free sessions. COSigna sets no cookies. Session state is held in localStorage as a bearer token; Set-Cookie and document.cookie are never used. This is an intentional product differentiator. Source: docs/VERSIONS.md (v0.105.0); enforced by STATUS.md invariant 12.
No third-party assets or analytics. Every asset (fonts, JS, CSS) is served from the same origin. No third-party analytics scripts, no CDN includes. Source: UX/DESIGN_UI_SPEC.md; UX/CLAUDE_DESIGN_BRIEF.md.
First-party telemetry only, DNT/GPC-respecting. All telemetry is first-party and identifier-free: the client-error beacon (/telemetry/client-error), the anonymous option-flip beacon (/telemetry/option), the k-anonymous performance RUM beacon (/telemetry/perf, k=20 display floor), the ephemeral-visit A/B beacon (/telemetry/ab), and — since v0.523.0 — server-side aggregate request accounting (counts by cyclic hour-of-day / coarse path family / status class, plus edge-derived country codes; the schema is structurally incapable of holding an IP, raw path, UA, or session id, and a test asserts it). Since v0.558.0 a second, DATED breakdown (day + hour, not just cyclic hour-of-day) is also recorded, retained 90 days, and read behind an always-on k=5 suppression floor with no way to disable it from outside — a stricter floor than the cyclic table needs, since a dated hour count can single out a person in a way a bare cyclic one cannot. The client-side beacons honour the browser Do-Not-Track signal and fire nothing when DNT=1; the server-side accounting honours both DNT: 1 and Sec-GPC: 1 (Global Privacy Control) — an opted-out request is not counted at all, even in aggregate (v0.523.1; the stricter reading, chosen deliberately), and this applies identically to the dated breakdown. None of it captures PII, capability tokens, session IDs, or URL fragments. Source: UX/libs/telemetry.js (inline DNT check, capability-token redaction); UX/libs/perf-beacon.js; src/cosigna/server.py (_privacy_opted_out, _record_traffic, _classify_path); tests/test_traffic_counters.py (DNT/GPC suppression + schema-has-no-identifier tests for the cyclic table — the dated table's own equivalent coverage is owed, see DPIA-GDPR-CNIL/DPIA_amendment_traffic_country_analytics_EN.md §7.1).
End-to-end face encryption. The cryptographic core is implemented and independently reviewed. Per ceremony, a 32-byte Content Key (CK) is generated in the initiator's browser. Each consent selfie is encrypted with AES-256-GCM (nonce || ciphertext, AAD = SHA-256 of the plaintext) before upload. The server stores ciphertext only; it never receives CK. CK travels in the URL fragment (#k=...) which browsers strip before the request is sent. An independent Opus review confirmed: AES-256-GCM correct, AAD binding correct, face_hash integrity preserved, Python/JS wire-compatible, no key/plaintext/timing leak. Status: crypto core AND browser wiring shipped (src/cosigna/facecrypto.py, UX/mobile-signer/facecrypto.js, 31 parity tests; all 3 SPAs encrypt/decrypt since v0.1.1). Source: docs/E2E_FACE_ENCRYPTION.md.
No biometric templates. COSigna stores raw consent selfies (or their E2E-encrypted ciphertext), never a biometric embedding or template. This is a locked architectural decision (Q4 Option A, 2026-05-28). Source: NEOCORTEX/_archive/Q4_biometric_template.md; STATUS.md invariant 5.
Hash is the contract. Every PDF reference travels with its SHA-256. No code path trusts a PDF without re-verifying. Source: CLAUDE.md § Working rules; STATUS.md invariant 3.
GDPR erasure = crypto-erasure. Deleting a ceremony's CK renders every consent selfie of that ceremony unrecoverable noise while the hash commitments (legal weight of the chain) remain untouched. Single key destruction erases all faces of a ceremony at once, provably. Source: docs/E2E_FACE_ENCRYPTION.md §6; src/cosigna/lifecycle.py.
Secrets never in git. No secret may appear in any tracked file. All production secrets (HMAC key, witness Ed25519 key, admin token) are injected at docker run via --env-file (never per individual -e flags, which expose values in process listings). A secret scan runs before every commit and before every deploy (scripts/secret_scan.py). Source: src/cosigna/server.py line 1: "No secrets in code (§16)".
Secrets rotation runbook. A documented rotation procedure covers the secret surfaces in priority order by blast radius: infrastructure credentials, app secrets (COSIGNA_SECRET / COSIGNA_ADMIN_TOKEN via scripts/rotate-secrets.sh), and the Ed25519 witness key (rotate only on suspected compromise; old proofs keep verifying against the old public key). Source: docs/SECRETS_ROTATION.md.
Admin surface gating. /admin/* endpoints require administrator authentication — in the console, an administrator's passkey session. Fails closed: with no administrator configured, the surface is disabled.
Capability token scoping. Every signer/initiator action requires an HMAC capability token scoped to (cid, kind, subject). Cross-actor escalation (a signer performing initiator actions) is blocked at the token level. Source: src/cosigna/auth.py; tests test_auth.test_signer_and_initiator_tokens_differ, test_server.test_signer_cannot_use_initiator_endpoint.
Input validation. All hash parameters are validated against ^[0-9a-f]{64}$ (path traversal impossible). No route takes a PDF (POST /documents was removed in v0.117, see CANNOT 1 above), so there is no upload-time PDF parse; pypdf only assembles output PDFs (court bundle, certified PDF, stamp page). Plaintext face uploads are magic-byte checked (JPEG, PNG or WebP, else 400; server.py:9188); an enc=aesgcm face is stored as opaque ciphertext and is not. Uploads are read in 1 MB chunks under a 10 MB cap (server.py:9158-9166). Source: src/cosigna/server.py _validate_hash, upload_face; tests test_server_s4.test_hash_path_traversal_rejected, test_server_s4.test_face_non_image_rejected, test_server_s5.test_post_documents_is_gone.
Transport encryption. TLS terminates at the edge reverse proxy, with automatically renewed certificates. Not enforced in application code (documented residual R3 in docs/THREAT_MODEL.md).
Deployment. Single-host alpha on one EU-hosted server. Server and worker run as Docker containers from a pinned image tag with a documented rollback path.
A signal, not a lock. The signer page offers a secondary text link, "This link isn't for me". Pressing it records an incident for the organizer and changes nothing else: the slot keeps its status, the ceremony is not halted, and no audit row is written. The link itself continues to work for whoever holds it. The organizer is told through a notice in their account, when the ceremony belongs to an account. Source: src/cosigna/server.py (not_for_me); src/cosigna/store.py (add_link_incident); tests tests/test_request_reissue.py and tests/test_link_incidents_concurrency.py.
A link can be replaced before any upload. The organizer can replace a signing link with a fresh one before any upload (signature, signing pad, attachment, qualified signature, or credential commitment). A replacement cannot take back the ceremony key, PIN or code already in the old link; prefer a code shared separately when links travel through shared places. Once anything has been uploaded, replacement is refused to preserve the audit trail, and unattached photos are not seen; the participant can withdraw, a non-required participant can be removed, or the ceremony can be cancelled. Once replaced, reminders reach only addresses the organizer typed or the new holder gives. Source: docs/THREAT_MODEL.md (R1, revocable links); src/cosigna/store.py (reissue_slot).
A false press only creates a notice. Someone who presses the button without being entitled to can do one thing: put a notice in front of the organizer. It cannot cancel, block or alter the ceremony, and it cannot stop the invited person from signing. Each source is rate-limited, a stranger can add a report only while the slot has none open; a signature re-opens earlier reports made on that same link, so the organizer sees them again, and the free-text note is dropped when it contains a link or a key, then erased after 90 days. Source: src/cosigna/store.py (add_link_incident, null_link_incident_note_logged); tests/test_link_incidents_concurrency.py.
Threat model. In manual mode, someone who obtains a signing link (and, for P1, also the document) cannot open the ceremony key without the code sent by another route, unless they spend about 1,000 GPU-years of offline computing for an even chance on one envelope. Per list: about 1,900 (English), 1,560 (French) and 1,200 (German) GPU-years for an even chance at the reference rate. The arithmetic: list size N (6,744, 6,411 and 6,004 words), N^4 possible codes, 650,000 PBKDF2-HMAC-SHA-256 iterations per guess, and the reference rate of about 1.11 × 10^10 iterations per second (hashcat v6.2.6-851, mode 10900, one RTX 5090, published 10 February 2025).
Rate reference. The figure depends on "the fastest single GPU on sale at the release date, measured by a public benchmark"; it is not a bound for every hardware. A 1,000-GPU attacker gets an even chance in about 1.2 to 1.9 years (at 650,000 iterations). A server-checked code would answer that attacker; it is research with no release date.
Residual risks. MCP connector links: the link alone opens the key; no document is needed. Key cards: possession of the card is enough. Ceremonies created before v0.617.0: for a scanned PDF, an image or a Markdown file, the link alone plus at most a million code guesses (about a minute on one GPU) opens the key; an automatic-mode link of that kind opens it directly. For a text PDF, the link and the document plus the same minute open it; an automatic-mode link plus the document opens it directly. These links also have no protection against a rewritten link. Re-sharing or closing a ceremony does not make an attacker forget a link already obtained.
Browser history. A signing link in browser history is the capability. The page keeps the key part in the address bar so a reload still works.
Revocation is not confidentiality. For every profile, re-sharing or a new code does not take back an envelope already obtained. If the ceremony key is compromised, a fresh ceremony protects new material, and material already disclosed cannot be recovered.
Word-list sources and licences. English from the EFF large word list (CC BY 3.0 US, attribution: Electronic Frontier Foundation, Joseph Bonneau). French from ulif/diceware wordlist_fr.txt (CC0-1.0). German from dys2p/wordlists-de de-7776-v1.txt (chosen licence CC0). Each list was curated here: length, cross-language duplicates, homophones, offensive and distressing words removed.
En mode manuel, une personne qui se procure un lien de signature (et, pour P1, aussi le document) ne peut pas ouvrir la clé de la cérémonie sans le code transmis par un autre canal, sauf à dépenser environ 1 000 années-GPU de calcul hors ligne pour avoir une chance sur deux d'ouvrir une enveloppe. Par liste : environ 1 900 (anglais), 1 560 (français) et 1 200 (allemand) années-GPU pour une chance sur deux, au débit de référence. Le calcul : taille de la liste N (6 744, 6 411 et 6 004 mots), N^4 codes possibles, 650 000 itérations de PBKDF2-HMAC-SHA-256 par essai, et le débit de référence d'environ 1,11 × 10^10 itérations par seconde (hashcat v6.2.6-851, mode 10900, une RTX 5090, publié le 10 février 2025).
Le chiffre dépend du « GPU unique le plus rapide en vente à la date de la version, mesuré par un banc d'essai public » ; ce n'est pas une borne pour tout matériel. Un attaquant disposant de 1 000 GPU a une chance sur deux en 1,2 à 1,9 an environ (à 650 000 itérations). Un code vérifié par le serveur répondrait à cet attaquant ; c'est de la recherche, sans date de sortie.
Liens du connecteur MCP : le lien seul ouvre la clé ; aucun document n'est nécessaire. Cartes de clé : la possession de la carte suffit. Cérémonies créées avant la v0.617.0 : pour un PDF scanné, une image ou un fichier Markdown, le lien seul et au plus un million d'essais de code (environ une minute sur un GPU) ouvrent la clé ; un lien en mode automatique de ce type l'ouvre directement. Pour un PDF texte, le lien et le document, plus cette même minute, l'ouvrent ; un lien en mode automatique et le document l'ouvrent directement. Ces liens ne sont pas non plus protégés contre une réécriture. Repartager ou clôturer une cérémonie ne fait pas oublier à un attaquant un lien déjà obtenu.
Un lien de signature qui reste dans l'historique du navigateur est la capacité elle-même : qui le retrouve peut s'en servir. La page garde la partie clé dans la barre d'adresse pour qu'un rechargement fonctionne encore.
Pour tous les profils, repartager un lien ou changer de code ne reprend pas une enveloppe déjà obtenue. Si la clé de la cérémonie est compromise, une nouvelle cérémonie protège le nouveau contenu ; ce qui a déjà été divulgué ne peut pas être récupéré.
Anglais : la grande liste de l'EFF (CC BY 3.0 US ; attribution : Electronic Frontier Foundation, Joseph Bonneau). Français : wordlist_fr.txt de ulif/diceware (CC0-1.0). Allemand : de-7776-v1.txt de dys2p/wordlists-de (licence retenue : CC0). Chaque liste a été retravaillée ici : longueur des mots, doublons entre langues, homophones, mots offensants ou pénibles retirés.
Im manuellen Modus kann jemand, der einen Signaturlink erhält (und, für P1, auch das Dokument), den Zeremonienschlüssel ohne den auf anderem Weg gesendeten Code nicht öffnen, es sei denn, er investiert etwa 1.000 GPU-Jahre Offline-Rechenzeit für eine Chance von 50 Prozent bei einem Umschlag. Je Liste: etwa 1.900 (Englisch), 1.560 (Französisch) und 1.200 (Deutsch) GPU-Jahre für eine Chance von 50 Prozent beim Referenzdurchsatz. Die Rechnung: Listengröße N (6.744, 6.411 und 6.004 Wörter), N^4 mögliche Codes, 650.000 PBKDF2-HMAC-SHA-256-Iterationen pro Versuch und der Referenzdurchsatz von etwa 1,11 × 10^10 Iterationen pro Sekunde (hashcat v6.2.6-851, Modus 10900, eine RTX 5090, veröffentlicht am 10. Februar 2025).
Die Zahl hängt vom „schnellsten einzelnen Grafikprozessor im Handel zum Veröffentlichungsdatum, gemessen mit einem öffentlichen Benchmark" ab; sie ist keine Grenze für jede Hardware. Ein Angreifer mit 1.000 GPUs hat bei 650.000 Iterationen eine Chance von 50 Prozent nach etwa 1,2 bis 1,9 Jahren. Ein vom Server geprüfter Code würde diesem Angreifer begegnen; das ist Forschung ohne Veröffentlichungstermin.
Links des MCP-Connectors: Der Link allein öffnet den Schlüssel; ein Dokument ist nicht nötig. Schlüsselkarten: Der Besitz der Karte genügt. Vor der v0.617.0 erstellte Zeremonien: Bei einem gescannten PDF, einem Bild oder einer Markdown-Datei öffnen der Link allein und höchstens eine Million Code-Versuche (etwa eine Minute auf einer GPU) den Schlüssel; ein solcher Link im automatischen Modus öffnet ihn direkt. Bei einem Text-PDF öffnen ihn der Link und das Dokument in derselben Minute; ein Link im automatischen Modus und das Dokument öffnen ihn direkt. Diese Links sind zudem nicht gegen ein Umschreiben geschützt. Eine Zeremonie erneut zu teilen oder zu schließen lässt einen Angreifer einen bereits erhaltenen Link nicht vergessen.
Ein Signaturlink im Browserverlauf ist die Berechtigung selbst: Wer ihn dort findet, kann ihn nutzen. Die Seite behält den Schlüsselteil in der Adressleiste, damit auch ein Neuladen noch funktioniert.
Bei jedem Profil nimmt das erneute Teilen eines Links oder ein neuer Code einen bereits erhaltenen Umschlag nicht zurück. Ist der Zeremonienschlüssel kompromittiert, schützt eine neue Zeremonie neues Material; bereits offengelegtes Material lässt sich nicht zurückholen.
Englisch: die große Wortliste der EFF (CC BY 3.0 US; Namensnennung: Electronic Frontier Foundation, Joseph Bonneau). Französisch: wordlist_fr.txt von ulif/diceware (CC0-1.0). Deutsch: de-7776-v1.txt von dys2p/wordlists-de (gewählte Lizenz: CC0). Jede Liste wurde hier überarbeitet: Wortlänge, Dubletten zwischen den Sprachen, Homophone sowie anstößige und belastende Wörter wurden entfernt.
| Control | Status | Notes |
|---|---|---|
| ✅ Hash-chain integrity (INV-1..5) | Shipped | adversarial suite in tests/test_invariants.py (the backend suite is the gate; a test count goes stale the day it is written) |
| ✅ No consent-forging key on server (INV-3) | Shipped | No signer private keys in src/; code-grep + test coverage |
| ✅ E2E face encryption — crypto core | Shipped | facecrypto.py + facecrypto.js, 31 parity tests, Opus-reviewed |
| ✅ No biometric templates | Shipped | Architectural lock; no template code path exists |
| ✅ Cookie-free sessions | Shipped | localStorage bearer; no Set-Cookie ever issued |
| ✅ No third-party assets / analytics | Shipped | Own-origin only; enforced by design spec + code review |
| ✅ DNT-respecting first-party telemetry | Shipped | UX/libs/telemetry.js; DNT check at load, token redaction |
| ✅ Secrets never in git | Shipped | --env-file injection; secret scan before every commit and every deploy |
| ✅ Secrets rotation runbook | Shipped | docs/SECRETS_ROTATION.md; scripts/rotate-secrets.sh |
| ✅ Admin surface gated | Shipped | Administrator authentication required; fails closed |
| ✅ Capability token scoping + cross-actor enforcement | Shipped | src/cosigna/auth.py; test suite |
| ✅ Input validation (path traversal, non-image face, size; no PDF upload route) | Shipped | _validate_hash; plaintext-face magic-byte check; POST /documents removed (v0.117) |
| ✅ Face-access token gating | Shipped | GET /faces/{hash} requires HMAC face token; test_face_retrieve_requires_token |
| ✅ Crypto-erasure (Art. 17) | Shipped | src/cosigna/lifecycle.py; CK-destruction design in docs/E2E_FACE_ENCRYPTION.md §6 |
| ✅ Offline verifiability (INV-4/5) | Shipped | Verifier SPA + chain-verify.js fully client-side; OTS / Bitcoin anchor |
| ✅ OpenTimestamps / Bitcoin anchor | Shipped | Background task; never blocks close; stub vs real distinguished by anchor_verified field |
| ✅ Admin authentication configured on the live deployment | Shipped | Confirmed on production: an unauthenticated /admin/users call is refused with 403, not the fail-closed 503 (2026-07-19) |
| ✅ Offsite backups | Shipped | scripts/backup-tier0.sh — WAL-safe nightly snapshot (systemd timer) + off-box copy; first restore proven 2026-07-27 (every closed ceremony on the box re-verified GREEN from the restored bytes) |
| ☐ Single-host deployment | Alpha state | One server, no failover |
| ☐ Token revocation / short-lived query tokens | Residual R1/R1b | Stateless HMAC tokens valid until secret rotates; a ?t= query token can still land in browser history and Referer headers (documented in docs/THREAT_MODEL.md), but the edge access log deletes the whole query string and redacts capability path segments (deploy/Caddyfile), so it no longer lands there; mitigation path: per-ceremony versioning or short-lived JWTs |
| ☐ SOC 2 Type II | Deferred | See §6 |
To report a security issue: security@cosigna.eu (PGP on request) or use the in-product /bug page (available at the live service URL), which routes directly to the operator.
We aim to acknowledge within 48 hours and to provide a status update within 7 days. There is no formal bug-bounty programme at this stage.
SOC 2 Type II attests that a service operator's controls around security, availability, processing integrity, confidentiality, and privacy operated effectively over an observation period — it is an audit of organisational and operational controls, not a certification of cryptographic architecture.
COSigna's blind-server architecture materially changes the risk calculus for several Trust Services Criteria (the server cannot produce plaintext documents or faces even under compulsion; consent integrity is mathematically enforced rather than procedurally attested), but it does not replace the audit: organisational controls around physical access, personnel, incident response, and vendor management are not covered by the zero-trust protocol and require a separate assessment.
The SOC 2 audit is deliberately deferred until the service is commercially gated — specifically, until Stripe live mode is active and the first paying cohort is onboarded (the move to the current production host completed 2026-07-06; being live there does not by itself end Private Alpha). Pursuing the audit before those gates would produce a report over an alpha-phase control environment that does not represent the production posture. The structural answer to the gap, in the interim, is this document.
Last updated: 2026-08-18 (Tier-1 survey item #7: replaced the simplified "can/cannot" table with the fact-checked adversarial statement — two prior overclaims corrected, the roster/order gap (D1) admitted openly rather than left silent). Prior update: 2026-08-04. Originally published: 2026-06-10. Version: v1.
↑ Back to top