Security and limits
Authentication
- One-time code by email (Better Auth): expires in 5 minutes, 3 attempts, codes stored hashed, rate-limited sending.
- SSO OIDC per domain. Only platform administrators register a provider, after checking that the organization owns the domain: otherwise a provider could issue emails for a domain that is not its own. Better Auth's registration routes are not exposed.
- 7-day web sessions in
HttpOnlycookies. No header alone is enough to impersonate someone. - VS Code connection via approval in the browser, comparing a code displayed on both sides. The token stays encrypted in VS Code's secret storage; the server keeps only its SHA-256 fingerprint. 30-day sessions, revocable.
Data
| Data | Where | Note |
|---|---|---|
| Organizations, members, invitations, groups, themes, versions, validation reports, preferences, hashed sessions, SSO providers, activity log | SQLite database (Cloudflare D1) | Published versions immutable (SQL constraint) |
| Published CSS | Platform storage (Cloudflare R2) or organization storage (S3-compatible, Azure Blob) | Never public: the server returns the CSS after checking rights |
| Storage credentials | Database, encrypted (AES-GCM) | Never returned; storage addresses HTTPS only |
| CSS sent to the AI assistant | Claude API (Anthropic) | Only if the organization enables it; embedded images and fonts stripped before sending |
| Markdown presentations and their images | Nowhere | They stay on users' machines |
Theme checks
Every theme goes through the theme validator, the same one in the editor, on the server and in the extension:
- CSS read by a real parser: checks apply to decoded values, so an escape sequence cannot hide a URL;
- no external resources: only images and fonts embedded as base64
data:, whose first bytes match the declared type; - no SVG, no
@importexcept for themes built into Marp, no</style, no legacy script mechanisms; - every Core v1 class must have an effect, and the geometry of the control slides is checked in a browser.
There is no size limit as a rule: embedded images make the CSS grow. Only the technical limit of a request (64 MB) remains.
The preview is displayed in an isolated iframe, without scripts or network. On the extension side, the organization, name, version and SHA-256 fingerprint of the CSS are verified before installation, then the validator is applied.
What permissions do not do
- A revocation does not erase copies already downloaded and does not prevent their offline use. Permissions govern distribution.
- Geometry (validator stage 6) is measured by the editor's browser: someone who forged their report could only publish in their own organization. Security (stages 1 to 3) is always checked by the server.
Currently out of scope
Storage or collaborative editing of presentations, remote PDF/PPTX rendering, visual theme editor, automatic embedding of images and fonts (imported CSS must already be self-contained), invitations by link, organization deletion, directory synchronization (SCIM), billing.
Before going to production
Open items, to be handled with the final account and domain: email sender domain, request rate limits, database backups, cleanup of orphaned files (replaced drafts) in storage, review of the Ukrainian and Arabic translations.