-
Part 1 of 5 · Architecture
One database, enforced isolation
Each part of a document is stored separately, so a part you aren't cleared for is simply never sent to you.
Under the hood. A NestJS API and a Hocuspocus realtime server share one PostgreSQL database with forced row-level security. Every section of a briefing is its own Yjs document, so hiding a section means never syncing it at all.
-
Part 2 of 5 · Redaction
Hidden text never reaches the browser
The black bars aren't a disguise laid over the text. The text itself never arrives, and the tests prove it.
Under the hood. The API returns a bar rounded up to 40 characters, so even lengths don't leak. A Playwright test records every HTTP response and WebSocket frame and checks the hidden text appears in none of them.
-
Part 3 of 5 · Live permissions
Demoted mid-keystroke
Take away someone's access while they're typing, and their very next keystroke is refused.
Under the hood. Changes send NOTIFY inside their transaction. Open connections are locked read-only before the commit, re-checked after it, and resynced, so no edit lands after a demotion and no legitimate edit is lost.
-
Part 4 of 5 · Word-level classification
Mark words Secret, like making them bold
Select a few words and classify them, the way you'd make them bold. Readers without clearance see bars instead.
Under the hood. A classification is a Yjs formatting mark. A pre-update hook refuses marks above the sender's clearance; readers below a mark get a copy the server writes for their level.
-
Part 5 of 5 · Proof
More than 600 tests behind the bars
Every rule above has a test that tries to break it, and the tests are themselves checked by deliberately introducing bugs.
Under the hood. A generated authorization matrix of 441 requests, property tests over 500 random documents, browser tests with three users at once, and a 100% mutation score on the security-critical modules.
-
Redacted
Ready when you are
Still starting. It will open as soon as it's up.