Where we actually stand
Termsroom exists to hold the record of a negotiation between two parties who do not fully trust each other. That only works if neither of them has to take our word for anything. This page says what is certified, what is not yet, and how to check the rest yourself.
Certification status
Termsroom does not yet hold a SOC 2 report. Our Type I audit is scheduled for October 2026 and the Type II observation window runs to January 2027, with the report expected in February 2027. A SOC 2 Type II observation window is a minimum of three months and cannot be backdated, which is why no vendor can produce one faster.
What we can show you today is the controls themselves, running, and the evidence that they are. Everything below is live.
Vendor assessment
completedself assessment, not a certificationTermsroom has completed a HECVAT 4 self assessment, version 4.1.6. It covers security, privacy, IT accessibility and artificial intelligence, and it is available to any institution on request. We do not ask for a non disclosure agreement first, because nothing in it is commercially sensitive and the community that maintains it takes the view that institutions should not have to sign for it.
Being precise about what that is: the Higher Education Community Vendor Assessment Toolkit is a questionnaire a vendor completes about itself. There is no auditor, no pass mark and no scoring authority, and EDUCAUSE, which maintains it, describes the answers as self attested. It is a way to give your reviewers what they need in a format they already know, while the SOC 2 work above runs its course. It is not a certification and we will not describe it as one.
It is recognised in Canadian higher education. The University of Toronto lists a HECVAT among the vendor security documents its information risk assessment accepts, and CANARIE, the national research and education network, reviewed one during its own procurement.
What that does not mean, since this page exists to be exact rather than flattering: no institution has assessed Termsroom against ours. Toronto runs its own risk assessment under ISO 27005 and NIST 800-39, and a HECVAT is an input to it rather than a substitute for it. Naming them here says that the format is accepted, and nothing more.
To request it, or a privacy impact assessment pack for an Ontario institution: security@termsroom.com.
Controls running right now
Each of these ran a query against the live system when this page loaded at 04:28 UTC, and each could have come back red. Your own security team can run every one of them against your own data. The query is printed beneath each result.
No unclassified data
OperatingCC8.1 · C1.1Every column in the database is declared and classified. Nothing has been added that we have not accounted for.
Zero unclassified columns.
select * from tr_uninventoried_columns()Audit record unaltered
OperatingCC7.2 · CC7.3The full history of who did what is hash-chained and append-only. If any entry had been edited or removed, this check would fail.
66 entries verified.
select * from tr_verify_audit_chain()No cross-party access
Not measuredCC6.1 · C1.1Nobody from the other side of a negotiation has ever read your caucus material. Each party can run this query against their own data.
Sign in to run this against your own organisation.
select * from tr_cross_party_access(:org)Organisational storage only
OperatingC1.1 · CC6.1Every connected storage location is a corporate, union or government tenant. Personal accounts are refused, not warned about.
All active connections validated as organisational.
select count(*) from storage_connections where status='active' and not is_organisationalDistribution records entitlement, not content
OperatingC1.1 · CC6.1A recipient row says that a named person was entitled to a named document and whether they have seen it. It never carries the document.
No distribution holds anything it should not.
select * from tr_verify_distribution_custody()Closing records reach both parties
OperatingC1.1 · CC7.2When a negotiation closes, the closing record is written into each side's own storage and only a pointer and a hash are kept here. A closure marked as reported with fewer than two copies has not delivered what it claims.
Every closed negotiation delivered a record to both sides.
select * from tr_verify_closure_custody()Sealed risks stay sealed
OperatingC1.1 · CC6.1A risk raised in a caucus is visible only in that caucus. Making it visible to the other side moves it to the shared table and is recorded as a disclosure, so a risk marked as shared while still sitting in a caucus is an anomaly.
No risk is visible anywhere it was not deliberately disclosed.
select * from tr_verify_risk_custody()Connected to the declared database
OperatingCC6.1 · CC8.1This deployment is talking to the database this product is supposed to use, in the region we say it is in.
Project xvsejdzvsyqoimxkxjxq, Supabase, ca-central-1.
NEXT_PUBLIC_SUPABASE_URL compared against supabase/expected-project.json
Properties of how it is built
These are not measurements. They are statements about the schema and the deployment, true when written and verifiable by reading the migrations, but nothing queried them when this page loaded. We keep them in their own list so that nothing above is doing work it has not done.
No document content stored
OperatingC1.1No clause text is stored. Numeric magnitudes extracted from a clause are: the money amounts, percentages and quantities a comparison needs in order to say that a threshold moved. Those are in the database, the sentences around them are not.
Enforced at the schema level by a check constraint on data_inventory. Separately, clauses.features retains the money amounts, percentages and quantities extracted from a clause, and clause_changes.deltas retains their before and after values. Clause text itself is never stored.
check constraint no_document_content on data_inventory (class <> 'content'), and clauses.features as written by lib/diff/features.tsRow-level security on every table
OperatingCC6.1 · CC6.3Authorisation is enforced by the database, not by the application. There is no query path that bypasses it.
Writes go through SECURITY DEFINER functions rather than through permissive policies. The application never queries user data with the service-role key.
alter table … enable row level security on every table in the public schemaAudit log is append-only
OperatingCC7.2Tamper-evident: any alteration is detectable by a party holding a previously issued head hash. Before update and before delete triggers refuse every role, including ours.
Enforced by triggers in migration 0001 and exercised by the test suite.
before update / before delete triggers raise an exception for every roleTransport and browser hardening
OperatingCC6.6 · CC6.7HSTS with preload, strict referrer policy, content-type and framing protection on every response.
Applied to all routes; Teams frame policy scoped to Microsoft origins only.
next.config.mjs security headers
What we hold, and what we never hold
We hold
- Pointers to where a document sits in your own storage
- SHA-256 hashes proving which bytes were tabled
- Clause position, depth and word counts
- Findings, such as that clause 12.4 changed substantively
- Who did what, when, from where
- Text you typed into Termsroom, such as a risk title
- An encrypted credential, on the one storage path where you give us one. See the table below
We never hold
- Document bytes, in any table, ever
- Clause text or headings from your agreement
- The closing record produced when a negotiation ends, which is written into both parties’ storage instead
- A credential you did not deliberately give us
- The keys your own storage encrypts itself with, on either path
Every column in our database carries a declared classification, and the classification that would permit document content is forbidden by a database constraint. A column added without one fails our build.
Credentials, per storage path
We used to say, flatly, that Termsroom held no credential into your storage. That was true when SharePoint was the only option and it is no longer true of every option, so the claim is now made per path rather than in general. This table is rendered from the same file the product reads, so it cannot fall behind the code.
| Storage path | Credential held | What we hold | If you revoke |
|---|---|---|---|
| SharePoint or OneDrive for Business | No | Tenant id, site id, drive id, folder name, and the validation report. No credential of any kind. | Your administrator deletes the Sites.Selected grant on the site. Access stops immediately and needs no contact with us. There is no credential left over on our side, because there never was one. |
| S3 compatible bucket, your keys | Yes, encrypted | Endpoint, region, bucket, prefix, access key id, the validation report, and a vault reference to the secret access key. The secret itself is readable only by the service role. | You delete or rotate the key in your own console. Access stops at once. Disconnecting in Termsroom retires the connection; ask us to purge the vault entry and we will, but rotating the key is what actually ends access and it does not need us. |
| Google Drivecoming soon, not built | No | Nothing. There is no implementation. | Not applicable yet. |
The two paths compared in full, including what a reviewer should check on each, are on the storage options page. A stored secret is encrypted into the database vault on arrival, is readable only by the service that moves bytes, and is never shown again, not even to the person who pasted it.
Check us yourself
Five queries either party can run against their own data, without our involvement.
What do you hold about us?
select * from tr_custody_manifest(:org)Who has accessed our material?
select * from tr_access_report(:org)Has the other side ever seen our caucus?
select * from tr_cross_party_access(:org) -- must return zero rowsIs every storage claim on this page still true?
select * from tr_verify_storage_claims() -- must return zero rowsHas the record been altered?
curl -O https://termsroom.com/verify.mjs && node verify.mjs <your export> # no account, no networkThe anchor
Where every audit record begins
ebdbbaedbb881c9055d6831850ec1d6928f4ecb908dffe922f01ff434ba24ed8Each party’s record is a chain of hashes beginning from this one value, the same for every customer. Your exported file carries an anchor of its own. Compare the two before you trust the verification, because a file with its first entries removed would still verify against the anchor it was shipped with. Checking it against a value published somewhere the file cannot reach is the whole point.
It reveals nothing. It is a hash of hashes, and no event, party or count can be recovered from it, which is why it can sit on a public page.
Compliance roadmap
These are commitments with dates, not aspirations. We are content to have them written into a contract.
Security controls built into the product
DoneCompleteRow-level security on every table, append-only hash-chained audit log per organisation, customer-held storage, caucus separation enforced by the database rather than by the interface, organisational-account enforcement.
Verifiable in the running system. See the live checks above.
Data custody model documented and independently verifiable
DoneCompleteEvery column classified; the verification queries published so each party can audit us without our help. Where a storage path means we hold a credential, that is stated per path rather than averaged into a general claim.
Data custody statement, available below.
Independent penetration test
PlannedSeptember 2026Third-party application and infrastructure test, with the summary letter available to customers under NDA.
SOC 2 Type I report
PlannedOctober 2026An independent CPA firm attests that the controls are suitably designed as at a point in time. This is the first report we can actually hand over.
SOC 2 Type II observation window
PlannedOctober 2026 to January 2027A three-month period during which the auditor observes the controls operating. It cannot be shortened or backdated, which is why Type II is not available before then.
SOC 2 Type II report
PlannedFebruary 2027Attestation that the controls operated effectively throughout the window. Shared with customers under NDA, then annually.
ISO 27001 certification
PlannedUnder reviewAssessed after Type II, subject to demand. Roughly 80% of the controls overlap, so the incremental cost is modest.
What is built
Everything here runs today, with the route, the migration and the test named beside it so you can check rather than take our word. The forward plan is not published here; ask and we will talk it through, including the dates.
Drag a document in, with no terminal
DoneSeptember 2026The browser fingerprints the file and sends it straight into your own storage. Termsroom reads it back and records what actually landed, so the fingerprint on the record is one we computed rather than one a party asserted. The copy into the other side's storage then happens on its own and is retried until it verifies.
app/app/rooms/[roomId]/table-document.tsx and app/api/versions/placement. The copy into the other side’s storage is app/api/versions/[id]/mirror and lib/storage/copy-out.ts.
OneDrive for Business named and accepted
DoneSeptember 2026Accepted alongside a SharePoint site library, and labelled as what it is. A OneDrive drive belongs to one person, so a bargaining record placed there follows their retention and leaves when they do; the connection says so rather than leaving it to be discovered.
lib/storage/sharepoint.ts accepts driveType "business" and writes the caution onto the connection rather than onto a screen somebody may not read.
A shared view, and a view for your own side
DoneSeptember 2026One screen both parties read identically: items by status, versions tabled and whether both sides hold a verified copy, sittings, protocol, what is outstanding and from whom. Separately, a sealed view of your own mandate position, costing and risks. Two routes with two data sources, because a screen that mixed them is the one place a mandate figure could reach the wrong reader.
app/app/negotiations/[id]/dashboard and .../your-side, with tests/shared-dashboard-db.test.ts and tests/side-dashboard-db.test.ts. Shipped ahead of the published Q4 2026 date.
Every bargaining unit in one place
DoneSeptember 2026An institution running eight bargaining units sees all eight on one screen: unit, counterparty, agreement expiry, where each round has reached and what is outstanding. Reached from the account navigation rather than from a button partway down one negotiation.
app/app/portfolio with tests/portfolio-db.test.ts. Shipped ahead of the published Q4 2026 date.
Storage chosen per room
DoneSeptember 2026A caucus can sit on a different storage location from the shared table, so an institution can put caucus material under its own retention rule or legal hold without moving the shared record. Versions already tabled stay where they were written and remain readable, so changing a room’s location affects what happens next rather than what already happened.
supabase/migrations/0060_room_storage.sql with tests/room-storage-db.test.ts. Shipped ahead of the published Q1 2027 date.
Sub-rooms inside a caucus
DoneSeptember 2026An outside actuary or counsel brought in for one item joins a sub-room inside the caucus rather than the caucus itself, so they do not see the mandate discussion. The separation is a database policy on the same model as the caucus boundary, not a filter applied by a screen.
supabase/migrations/0061_sub_rooms.sql and app/app/rooms/[roomId]/sub-rooms-panel.tsx, with tests/sub-rooms-db.test.ts. Shipped ahead of the published Q1 2027 date.
Sub-processors
Your documents live in storage you own. Where that is your Microsoft tenant, it is the one row below marked as holding documents. Where it is your own bucket, the provider is yours rather than ours, you contracted with them directly, and they do not appear in this table at all.
| Service | Role | Location | Attestation | Holds documents |
|---|---|---|---|---|
| Vercel | Application hosting and delivery | Configurable region | SOC 2 Type II | No |
| Supabase | Database, authentication, the negotiation record | Canada (ca-central-1) | SOC 2 Type II | No |
| Twilio | Phone verification at sign-in | United States | SOC 2 Type II, ISO 27001 | No |
| Resend | Sending invitations and reminders by email. A reference, a name and a link, never a document | United States | SOC 2 Type II | No |
| Paddle | Payments and merchant of record. Billing details go to Paddle and never to us | United Kingdom and European Union | PCI DSS Level 1, SOC 2 Type II | No |
| Microsoft | Your own tenant: Entra, Teams, SharePoint | Your tenant, your region | Your existing agreement with Microsoft | Yes, yours |
Four limitations we would rather you heard from us
- We see documents transiently. Two things need the text in server memory: comparing two versions, and indexing a tabled one, which reads the file back from your own storage. Neither writes it to disk, to the database or to any cache, and the process holds no state, but “never stored” is not the same as “never seen”. What you get for it is that the fingerprint on an indexed version is one we computed rather than one somebody typed, and an index is only ever built from bytes whose digest matches what was entered. A customer-side agent that does this inside your own tenant is on the roadmap.
- On one storage path we hold a key to your bucket. If you connect S3 compatible storage with your own API keys, we hold the secret access key, encrypted, for as long as the connection is active. Scope the key to one prefix, and rotate it when you want us out. The SharePoint path carries no such credential.
- We cannot trace a leaked page of your document. Per-recipient watermarking is on the roadmap and is not built. What we hold today is who was sent which version and when they acknowledged it, which tells you the population a leak came from, not the person. When watermarking ships it will be a deterrent rather than a control: it defeats the careless forward and the photographed screen, and it does not stop somebody retyping a clause.
- Metadata is not nothing. Clause counts, the timing of changes and who read what are genuinely informative. We hold them because the product cannot work otherwise, and we log every access to them.
How we prove a document has not changed
The checks above establish that the record has not been altered. The companion question, how anyone knows the agreement in front of them is the one that was agreed, is answered by a fingerprint recorded against every version rather than by us keeping a copy. What that is, what it does not prove, and why a reviewer in Canada, the United States or Europe accepts it, is set out on the document integrity page.
The evidence behind this page
This page states what is true and gives away nothing a trial account would not show you. The material behind it is not published, because we would rather know who holds it than have it circulate. Ask, and a person replies.