Security architecture

Where each control is enforced, and what is not yet proven.

This page is written for the person in the evaluation who asks how rather than whether: which component enforces the organization boundary, what stops the audit trail being edited, and what an upload does when the scanner is unreachable. Each mechanism below is a property of the shipped build. Where something is implemented but not yet proven in operation, it says so and says why.

The shape of it

Two principles, applied consistently enough to be checkable.

Fail closed. When a control cannot do its job, the action is refused rather than allowed. An upload that cannot be scanned is rejected; a signature whose stored bytes no longer match their digest is not bound; a workspace whose free space cannot be measured is treated as full. There is no setting that turns any of those around, because a half-configured security control that appears to work is the kind that reaches production.

One definition per rule. Each rule is enforced in exactly one place, where the consequence happens. A second copy of a lifecycle rule is a second thing to get wrong — and the two copies disagree silently, which is the failure nobody notices until an auditor does.

Neither principle is a claim about outcomes. They are the reasons the mechanisms below are shaped the way they are, and they are the properties worth testing if you evaluate the product.

Control by control

What is enforced, where, and in what state.

  1. Which organization a request belongs to is decided twice, independently

    The worryOne organization’s documents reaching another is the failure that cannot be apologized for. A filter in application code is one mistake away from being left off a query.

    DocumentSynthEach organization has its own address, and which environment a request belongs to is resolved from that address before anyone is authenticated — there is no other selector, so there is nothing for a request to assert. The boundary is then enforced again in PostgreSQL by row-level security: every tenant table carries row-level security forced, and each policy reads the tenant bound to the connection rather than anything the query supplies. The role the application connects as is not a superuser, does not hold the privilege that bypasses those policies, and owns no table — which is the part that makes the rest hold, because a table’s owner is exempt from its own policies.

  2. The audit ledger cannot be edited by anyone, including us

    The worryAn audit trail that the vendor, a support script or a migration can rewrite is a log. Evidence has to be something nobody can quietly correct.

    DocumentSynthEvery state change appends an audit event as it happens, and each event is hash-chained to the one before it within that organization, so removing or altering a row breaks the chain and the break is detectable rather than silent. Update, delete and truncate on the audit ledger and on the signature ledger are refused by database triggers, which apply to every role — not by a permission grant, which would protect against one role and leave the table’s owner and any superuser able to rewrite history. Per-document history is read from that same ledger, so there is no second, editable table that could disagree with it. A mistaken record is corrected by appending a correcting event, never by editing one.

  3. A signature is bound to the exact bytes that were signed

    The worryA signature that points at “the document” rather than at one version of it is worth nothing the moment the document changes.

    DocumentSynthA signature records the document, the specific version, and the content hash of that version’s bytes, alongside the signer’s name and title as they stood at that moment, the meaning of the signature, and the full text of the signing statement that was accepted. Signing requires re-authentication with a second factor at the moment of signing — a live session is not enough, and that gate is not configurable by the organization. Before the signature is bound, the stored bytes are re-hashed and checked against the recorded digest; afterwards the version is frozen and every content mutator refuses. The binding is re-verified whenever a signature is displayed, and a mismatch is surfaced as unverifiable rather than presented as a signature we cannot substantiate.

  4. An upload that cannot be scanned is refused, not accepted

    The worryMost systems fail open when a scanner is down, because refusing uploads is visible and accepting unscanned ones is not.

    DocumentSynthEvery upload runs the same ordered stages and there is no configuration that skips one: authorization, a size ceiling, content-based type validation where the file’s own bytes decide and never the extension or the browser-supplied type, a malware scan, a SHA-256 of the exact stored bytes, and only then the version and its audit event, written in one transaction. The scan is fail-closed: infected is a rejection and could not be scanned is also a rejection. Nothing the client sends is trusted as a storage path, a content type or an organization.

  5. Every read of a document passes through authorization

    The worryA link that works for anyone who has the link is a permission that outlives the decision that granted it.

    DocumentSynthDocument bytes are always streamed through the application, which authorizes the request every time. No pre-signed storage URL is ever generated, so there is no link that keeps working after the permission behind it is withdrawn, and storage credentials never reach a browser. Objects are stored under an opaque key the client never sees and cannot influence. Storage is provider-independent: each version records the provider it was written to, and each provider’s real capabilities — including whether it encrypts at rest unconditionally or needs to be asked — are declared in the build and asserted at startup, rather than discovered by sending a request and swallowing the error.

  6. The components that handle your documents have no route to the internet

    The worryA parser vulnerability in a document converter becomes an exfiltration channel the moment the process that holds the keys can open an outbound connection.

    DocumentSynthThe services that convert, scan and serve documents sit on networks with no route off the host. Each reaches exactly one proxy, and that proxy permits two specific destinations — one per client, never the other client’s — with everything else denied and logged. Adding a destination is a reviewed edit to a configuration file in the release, not a setting anybody can widen in a hurry. The proxy sees only an encrypted tunnel: it holds no credential of its own and never sees a message body.

  7. Exactly one version is in force, and the database is what guarantees it

    The worryTwo “current” versions of a procedure is not a display bug. It is two groups of people doing the work differently and both believing they are correct.

    DocumentSynthA revision adds a version and never edits one. The previous version is marked superseded rather than removed, so it stays in the record and cannot be mistaken for the current one, and a database constraint — not application code — enforces that at most one version of a document is effective at any time. A version becomes effective when its approval completes; scheduling a future effective date is not supported.

  8. Backup is implemented; a restore has never been rehearsedPlanned

    The worryEveryone has a backup. The question that matters is whether anyone has ever restored from it and opened the result.

    DocumentSynthThe mechanism is in the build: a database dump, an encrypted copy of document objects, and a reconciler that refuses to report a run as successful unless its output is actually restorable. What does not exist yet is the evidence that matters — no restore has been performed into an isolated environment and verified, and the schedule that would make it run unattended is an operator step rather than part of the product. Until a restore has been rehearsed and a restored document’s hash checked, this is stated as a mechanism and not as a guarantee, and it is not offered as a service commitment.

  9. Retention, legal hold and disposition are not implementedNot built

    The worryDocument control and records retention are usually bought together, and a system that is silent about the second is often assumed to do it.

    DocumentSynthThere are no per-document retention periods, no retention schedules, no legal hold and no disposition process. A document can be retired with a recorded reason, and retirement keeps the record rather than removing it — which is withdrawal, not disposition. If your quality system defines retention by document type and expects the system to enforce it, DocumentSynth does not do that today.

What is not verified

No certification, no audit, and no restore rehearsal.

An evaluation will ask for these. Stating them here costs a section and saves a call that ends in disappointment.

  • DocumentSynth holds no certification and claims none. There is no SOC 2 report, no ISO 27001 certificate, no HIPAA attestation and no FDA submission of any kind. None of those has been pursued. Any supplier implying that its software makes your organization compliant is selling something it cannot deliver — certification is granted to an organization, after an audit of what its people actually do.
  • No third-party security assessment or penetration test has been performed. The mechanisms on this page are implemented and covered by the project’s own automated tests. That is not the same as having been attacked by somebody competent and paid to try, and this page does not present it as such.
  • No restore has ever been performed. See Continuity above. The backup mechanism exists; the rehearsal that would make it a guarantee has not happened.
  • Validation is yours to perform. DocumentSynth implements mechanisms. Whether a given record satisfies a given requirement for your organization is your assessment to make, usually as part of your own validation activity, and we will support it with the detail on this page rather than with a certificate.

If a control you need is missing from this page, it is missing because it could not be stated accurately — not as an omission for brevity. Write to the security address in the footer and the answer will be the same one given here.