Celistra security model
Identity
The daemon accepts two auth paths:
- Firebase ID token. Signature verified offline against Google's JWKS (cached locally with rotation).
audmatches our project;issmatchessecuretoken.google.com;expis in the future. - 256-bit machine secret. Legacy fallback for the daemon's internal use. Constant-time compared.
Pairing: cryptographically-random 16-byte tokens minted by the tray, single-use, 600-second TTL, constant-time compared. Discussed in detail in Pair a machine in 30 seconds without SSH keys.
Network
Daemon binds to 127.0.0.1:33120 exclusively — never 0.0.0.0. Off-LAN traffic flows through an outbound bore tunnel to mail.ujex.dev:7000. nginx terminates TLS with Let's Encrypt; CAA pinned to LE plus four other named CAs.
Tunnel admission: Firebase-gated token rotated via Firestore. The frpc binary inside the .app is SHA-256 verified at exec — a swap-attack is refused, not executed.
Sandbox
Every spawned agent is wrapped in sandbox-exec -f <profile> with a Seatbelt profile generated from a capability token bundle. Default policy: workspace-write, read-anywhere, network, subprocess. Per-agent grants in versioned JSON. Linux uses bubblewrap with the same capability mapping. Detailed: Sandboxing Claude Code on macOS.
Audit
Hash-chained log: row.hash = sha256(prev.hash || row.body). Hourly verifier. Tamper-evident by construction. Detailed: The audit log every agent needs.
Revocation
Tray menu → Revoke all sessions calls a Cloud Function that runs admin.auth().revokeRefreshTokens(uid) against the user's Firebase account. Existing ID tokens expire within 1 hour; refresh tokens are immediately dead.
Threat model
In scope: a malicious user on the LAN trying to drive the daemon (blocked: loopback bind + auth). A swapped frpc binary (blocked: SHA-256 check). A prompt-injected agent trying to write outside its workspace (blocked: kernel sandbox). A stolen device (mitigation: revoke-all-sessions).
Not in scope: a compromise of the user's macOS account (game over). A prompt-injected agent making bad commits within its workspace (sandbox is a containment story, not a behavior story). DNS exfiltration via permitted network capability.
Reporting issues
Email security@celistra.dev. PGP key on the page. We respond within 48h.
FAQ
Where does data live?
Metadata in Firestore (your Firebase project). PTY streams in real time, not persisted server-side. 30-day history is local SQLite on the daemon's disk.
Can the daemon be reached over LAN from another box?
No — bound to loopback only. The 'remote daemon' use case (laptop dashboard, Pi daemon) goes via the tunnel.
Is the tunnel relay logged?
nginx access log only. No request bodies, no PTY content.