Trust
Security
Pure Alacrity is offline capable and cloud native: your productions are held on your own device, and every cloud, Google or AI feature is opt-in and asks for as little access as it can. This page explains how we protect the parts that leave your device, and where the limits are.
Contents
- Architecture
- In transit
- At rest
- Identity and access
- Google access
- Website protections
- Known limits
- What you can do
- Report a vulnerability
- If something goes wrong
Optional product analytics requires explicit consent and honors GPC and Do Not Track. A fixed event schema excludes confidential production content and Google data. Configured PostHog capture uses the server HTTP API; no browser analytics SDK, replay, heatmaps or automatic person identification is used. Account support or billing roles must not grant production-content access. Scoped professional-service access is separate from ordinary account administration. The cloud copy is not end-to-end encrypted, and no SOC 2 certification is claimed.
1. Architecture
The app is a single web application that runs in your browser, and also as a downloadable file, an Android app and a desktop app. Your work is stored in the browser on your device. Cloud Mode synchronizes productions to Firebase; device workspaces also support disconnected work. Even then the data is held in your own space in Google Firebase, in the Firebase project operated for this service.
Our own server (a Cloudflare Worker) does three things:
- serves the app;
- relays public news feeds from an allow-list of hosts;
- receives anonymous usage statistics that never contain your content.
2. In transit
- Every connection uses HTTPS/TLS. Plain HTTP requests are redirected to HTTPS.
- The site sends
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload, so browsers refuse an unencrypted connection. - Calls to Firebase, Google APIs and AI providers go directly from your device to that service over TLS.
3. At rest
| Data | Protection |
|---|---|
| Productions and settings in your browser | Stored by the browser on your device. Not encrypted by the app; protected by your operating-system account and browser profile. |
| Vault: sealed files | AES-256-GCM through WebCrypto, with a random 256-bit key per production and a fresh random 96-bit IV per file. Cloud Mode and shared productions never receive the key or the sealed bytes. |
| Cloud Mode copy | Held by Google Firebase, encrypted at rest by Google. Client access is constrained by database and file permissions. Infrastructure administrators and privileged backend identities require separate access controls; this is not zero-knowledge storage. |
| E-signature links | The document is encrypted with AES-256-GCM. The key travels in the link's # fragment, which browsers never send to a server. |
| Role passcodes for shared productions | Salted SHA-256 hashes in the database. |
| Google access tokens | Held in the open tab's memory only, never written to storage. They end when you close the tab. |
| Search index | Computed on your device from data already there, and held in memory and in IndexedDB scoped to the workspace. End session and Erase workspace remove it. It is built through one reader that refuses the Google Calendar cache, Vault keys and anything token-like, and it copies no contact details or confidential fields. Links to an item carry identifiers only; an id made from a name travels as an opaque token, and opening a link still needs access to the workspace that holds the data. |
4. Identity and access
- Cloud Mode signs in with Google through Firebase Authentication. The app initializes Firebase App Check with reCAPTCHA v3 and token auto-refresh. Service enforcement is configured in Firebase; App Check does not replace production authorization.
- Shared productions and live rooms are protected by database rules that require membership before any read or write.
- Access levels are enforced by the database. Viewer, commenter and editor levels, closed areas (such as the budget, contracts and contact details), access end dates and the blocked list are checked by the database rules for each piece of production data, not just hidden in the app. Nobody can raise their own level; a code join can never get more than the level the owner set for the link; and a restricted production refuses code joins.
- Removing someone takes effect at once. It deletes their membership, blocks them from rejoining by code, and the database cancels any data streams they still have open.
- The join code is a credential: anyone who holds it joins at the link's level. Set general access to Restricted or reset the code to cut access.
- Anonymous crew sign-ins can't own productions or write backups.
- Live rooms without an account use an anonymous Firebase sign-in and a join code. Presence is removed when you disconnect.
5. Least-privilege Google access
- Google Drive uses only
drive.file. The app can reach files it created (your backups) and files you pick yourself in Google's picker, and nothing else in your Drive. - Google Calendar uses
calendar.eventsto publish and show events, andcalendar.calendarlist.readonlyto list your calendars. Events read from Google are kept only on your device and never sent to our servers, Cloud Mode, AI providers or analytics. - YouTube uses
youtube.uploadto upload an edition you publish,youtube.readonlyto show your recent uploads and their statistics, andyoutube.force-sslonly when you add captions to an upload. Each is asked for when you first use that feature, and channel statistics stay in the tab's memory. - Each feature asks separately, the first time it is needed, and holds its own token with only its own scopes.
- Disconnecting in System → Google revokes the permission at Google. You can also revoke it at myaccount.google.com/permissions.
See the privacy policy for exactly what each permission is used for.
6. Website protections
- Content Security Policy: an allow-list of where scripts, frames and connections may come from, sent as a header, the same for every page of the app. Pages may not be framed by other sites. The app's code is served only from this site; no new host is allowed for it. Each release's files are named by their content, so a cached file cannot be swapped for another.
- Security headers:
X-Content-Type-Options: nosniffReferrer-Policy: strict-origin-when-cross-originCross-Origin-Opener-Policy: same-origin-allow-popups- a restrictive
Permissions-Policy
- Rate limiting: 120 requests a minute per address, and 15 once a client behaves like a scanner. Over the limit returns 429 with Retry-After. Cloudflare's network absorbs floods.
- Scanner and injection blocking: requests for server files, backups, keys, dotfiles and common exploit paths get a 404 or 403. Injection patterns in queries are rejected.
- The feed relay fetches only from an allow-list of news, union and guild hosts.
7. Known limits
We would rather tell you where the app is weaker than it should be:
- The app runs inline scripts, and the PDF engine needs
eval. The Content Security Policy therefore allows'unsafe-inline'and'unsafe-eval'for scripts, which weakens its protection against injected code. - Your workspace in the browser is not encrypted by the app, apart from Vault files. Anyone who can open your browser profile can read it. The app has no PIN lock.
- In Cloud Mode, AI provider keys and webhook addresses you saved are currently included in your cloud copy. Use keys made only for this app.
- Backup files (Drive, downloads, exports) are plain JSON that include everything, Vault keys and AI keys too. Treat a backup like the production itself.
- The Cloud Mode copy is not end-to-end encrypted. Firebase encrypts it at rest, and database rules decide who can read it.
- Some sharing controls are enforced only in the app, not by the database: department views, on-set room actions, the "viewers can download, print and copy" switch, and hiding single fields inside a list. Someone who can legitimately read data can still copy it by other means.
8. What you can do
- Lock your device and use your own browser profile. On a shared computer, end the local session when you're done.
- Keep regular backups, and store backup files somewhere private.
- Create AI provider keys just for Pure Alacrity, with spending limits.
- Disconnect Google services you no longer use.
- Run the checkup in System → Security inside the app.
9. Report a vulnerability
If you find a security problem, email pure@dcalacrity.com with what you found and how to reproduce it. Please don't access other people's data, disrupt the service, or make the issue public before we have had a reasonable chance to fix it.
- A person who builds the app reads every report. We aim to acknowledge within five working days.
- We will tell you our assessment of severity and a fix date for anything real.
- We will credit you in the changelog if you would like.
We will not take legal action against good-faith research that follows these guidelines.
10. If something goes wrong
If we learn of a security incident that affects your personal data, we will investigate, contain it, and notify affected users and authorities as the law requires, without undue delay. We will tell you what happened, what data was involved and what you can do.
Recording and scoped service foundations
Take audio capture is user initiated, visibly indicated and saved as recoverable device chunks. This release does not upload recordings or start cloud transcription. Local transcript corrections create new versions. Recording policy acknowledgments are separate from analytics consent.
Candidate backend service code requires Firebase identity, existing App Check, current production authorization and explicit resource grants for optional jobs. It remains disabled pending staging validation and provider configuration. Candidate Storage rules and their membership mirror require coordinated deployment; current production enforcement has not been verified here. Existing download-token URLs require separate revocation.