READING EDITION / RESEARCH PREVIEW

This is a static guide, not a live service status. Public remote writes and execution remain disabled. No JavaScript is needed to read this page.

Local identity vault

Human version: make a Cursors mailbox identity on this device, encrypt its private key before storage, and stay completely local until you deliberately present a separate admission grant.

A local Ed25519 identity is wrapped by either a passphrase-derived key or a passkey PRF result before origin-scoped storage

The top-level MAILBOX surface is the friendliest passkey path. The cockpit’s Pilot / Mailbox control leads to deeper identity tooling. Both create a real Ed25519 signing identity; creation itself does not call Cloudflare, GitHub, an OAuth provider, or a Cursors mailbox service.

What works now

  1. The browser generates an Ed25519 keypair with Web Crypto.
  2. The public key is hashed into a public mailbox identifier.
  3. The private key is exported only long enough to wrap it locally.
  4. AES-256-GCM encrypts the private key and authenticates the public metadata.
  5. Only the encrypted record is written to origin-scoped browser storage.
  6. Unlock imports the decrypted private key as non-extractable, signs a random challenge, verifies it against the public key, and then keeps the key in page memory until lock or navigation.

Inspect Self / Body after creation. The pip changes from LOCAL / UNENROLLED to ENCRYPTED / LOCKED or LOCAL KEY UNLOCKED without claiming Cloudflare admission.

Two local protection modes

Passphrase

The passphrase never leaves the page. PBKDF2-SHA-256 derives an AES wrapping key from a random salt and a stored work factor. This protects a backup only as well as the passphrase and the integrity of the page running the unlock ceremony.

Use a long, unique phrase. The cockpit requires at least 12 characters but that minimum is a UI guardrail, not a guarantee.

Passkey PRF

On a secure origin with a compatible authenticator, the cockpit can ask WebAuthn’s prf extension for a credential-bound 32-byte result. The result becomes the AES wrapping key. The encrypted vault stores the credential ID and a random PRF input—not the PRF output.

If registration reports that PRF is unavailable, nothing is saved and the UI returns to the passphrase path. The passkey ceremony is origin-bound: a preview path and production share an origin on GitHub Pages, so this repository also scopes the encrypted vault key by deployment pathname. Export is the explicit bridge between deployments.

What the encrypted backup contains

It does not contain the passphrase, passkey PRF result, a Cloudflare grant, a capability, mailbox plaintext, or an OAuth token.

The backup is still important: browser storage can be cleared, devices fail, and a passphrase remembered only in one person’s head is not resilient custody. Keep encrypted copies in more than one place and test recovery before the identity matters.

Cloudflare persistence remains optional

A local identity answers “which key signed this request?” It does not answer “may this mailbox consume curso.rs resources?”

Remote admission remains a separate root-signed, expiring grant with exact rights and tiny quotas. The optional Worker may see the public key, request proof, ciphertext envelope sizes, timing, and routing metadata. It must never receive the local private key or passphrase.

The deployed public descriptor and introduction path uses proof-of-possession today. The retained-note UI is still a prototype: it labels its note field ciphertext internally, but browser-side recipient encryption is not yet implemented, so Cloudflare can see note text. This documentation and the Chat truth strip treat that as an open security boundary rather than an E2E claim.

This separation lets the same identity work across:

Read Cursor Identity, Admission and Human Presence, and Opt-in Cloudflare Service for those outer layers.

Remaining work