CHIRP // AUTHv0.4.1
CHIRP · AUTH // PRIVACY

Privacy
in plain text.

Last updated 2026-05-28. Chirp is operated by Stackwell Labs LLC. Questions: privacy@chirpauth.com.

What we collect

There are three places data can live: on our servers, on your device, or nowhere. Here's what is in each.

Stored on our servers

Here is everything we would return if you asked for a copy of your data, after signing up as janesmith@example.com, registering a passkey, signing into one app, and using the service for a few minutes. In our database the same information is split across several rows; we have combined it here for clarity.

{
  "user": {
    "user_id":    "usr_a3f7c891b4e84d2c9f6012345678901a",
    "email":      "janesmith@example.com",
    "created_at": "2026-05-28T21:14:00Z"
  },
  "passkeys": [
    {
      "passkey_id":    "pk_a3f7c891b4e84d2c9f6012345678901a",
      "derived_name":  "Passkey on macOS",
      "custom_label":  null,
      "public_key":    "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgK...",
      "created_at":    "2026-05-28T21:15:00Z",
      "last_used_at":  "2026-05-28T22:30:00Z"
    }
  ],
  "sessions": [
    {
      "token":        "bs_a3f7c891...90ab",
      "created_at":   "2026-05-28T21:14:00Z",
      "last_seen_at": "2026-05-28T22:30:00Z",
      "expires_at":   "2026-06-27T21:14:00Z"
    }
  ],
  "consents": [
    {
      "app_id":      "pigeon",
      "scopes":      ["openid"],
      "approved_at": "2026-05-28T21:16:00Z"
    }
  ],
  "events": [
    {
      "event":    "login.success",
      "at":       "2026-05-28T21:14:00Z",
      "result":   "success",
      "detail":   "id_token",
      "trace_id": "trc_d2f3e4..."
    },
    {
      "event":  "login.email_step.started",
      "at":     "2026-05-28T21:13:50Z",
      "detail": ""
    }
  ]
}

Each field broken out:

Field Example What it is How long
user.user_id usr_a3f7c891… Opaque random account id. Internal stable handle that survives email changes; not derived from your email. Until you delete your account.
user.email janesmith@example.com The identifier you sign in with. Where we send magic-link emails. Until you delete your account.
user.created_at 2026-05-28T21:14:00Z When you first signed up. Until you delete your account.
passkeys[] { derived_name, custom_label, public_key, dates } A passkey you registered. derived_name is auto-set at registration time to one of a small fixed list ("Passkey on macOS", "Passkey on iOS", etc.), computed from the OS family in your User-Agent. The raw User-Agent is read once for this and then discarded. custom_label is null by default; only populated if you explicitly rename the passkey on the account page. The public key is what we verify your sign-in signatures against; the private key never leaves your device. Until you remove the passkey.
sessions[] { token, dates } A browser session record — one per browser you have signed in from. Lets you stay signed in and lets you list and revoke sessions. No IP or browser fingerprint is attached. 30 days absolute, 14-day idle — whichever first.
consents[] { app_id, scopes, approved_at } A relying app you have approved and the scopes you granted. Saved so we do not re-prompt on every sign-in. Until you revoke consent.
events[] (security) { event, at, result, detail, trace_id } Sign-ins, account changes, passkey additions, etc. For incident response and your security audit on the account page. detail is a short fixed token like "id_token" or "ses", never a free-form string. No IP or browser fingerprint. 30 days.
events[] (trace) { event, at, detail } Per-request diagnostic trace, for debugging when something goes wrong. The trace id (shown on error pages) is the storage key, not a stored field. No IP or browser fingerprint. 14 days.
pending_magic_link (transient) not present in this snapshot A row that exists only between your clicking "send me a sign-in link" and your clicking the link in the email. Lets us verify the click came from the right inbox. Usable more than once within the window, then deleted after 10 minutes — not consumed when you click it.
rate_limit_counter (transient) RL#login.email#sha256(your_ip)#1748468040 A per-IP counter that lets us reject brute-force sign-in floods. Your IP is SHA-256 hashed before becoming part of the key; we never store the raw IP. Auto-deleted after 2 minutes.

Stored only on your device

These live on your laptop, phone, or hardware key, and never reach our servers.

Not stored anywhere

Why we collect it

Only to operate the sign-in service: authenticate you, issue tokens to the application you chose, let you manage your sessions and passkeys, prevent abuse, and respond to security incidents. We do not sell, share, or use this data for advertising or profiling.

Who we share it with

When you complete a sign-in to a relying application, we issue that application an ID token containing only a pairwise subject identifier (unique to that application) and the standard OIDC claims. We never share your email address with the application — there is no email scope and the token carries no email claim. The relying application then becomes a separate data controller for what it does with the identifier — check its own privacy policy.

We use a small number of infrastructure providers as data processors: Amazon Web Services (compute, storage, and outbound email via SES) and Route 53 (DNS). They process data on our instructions; they do not receive your data for their own use.

How long we keep it

Account records (email, registered passkeys) are kept while your account exists. Sessions last up to 30 days from creation, with a 14-day idle timeout, and are deleted automatically after either limit. Security event logs (sign-in successes, failures, account changes) are kept for 30 days. Per-request diagnostic logs are kept for 14 days. In-flight magic links expire and are deleted within 10 minutes.

Your choices

If you are in the EU/UK or California, the GDPR / CCPA give you specific rights (access, deletion, correction, portability). Deletion is self-serve from your account page; for data export or any request you can’t complete yourself, email privacy@chirpauth.com.

Cookies

We set one essential cookie: a random session token, used solely as a lookup key for your server-side session. It contains no personal information — not your email, not your name, not your account id, not even when it expires. We do not use analytics, advertising, or third-party cookies.

Here is exactly what the cookie looks like if you sign in as janesmith@example.com:

chirp_auth_session=bs_a3f7c891b4e84d2c9f6012345678901a_d4e5f6789012345678901234567890ab; Path=/; Max-Age=2592000; HttpOnly; SameSite=Lax; Secure

Each piece broken out:

Key Value What it is Why it's here
chirp_auth_session bs_a3f7c891…90ab The cookie's name and opaque value. The value is a 244-bit random server-side lookup key. Nothing about you (no email, no account id) is encoded in it.
Path / URL-path scope within the origin. Sent on every request to signin.chirpauth.com — never to other origins, never to the relying apps you sign in to.
Max-Age 2592000 Lifetime in seconds (30 days). Browser auto-deletes after. The server independently expires sessions after 14 days of inactivity, so an old cookie can stop working before this clock runs out.
HttpOnly Hidden from JavaScript. Blocks the most common cookie-theft vector: a cross-site-scripting bug on any page reading the cookie via document.cookie.
SameSite Lax Cross-origin send rule. Sent on top-level navigations (so OIDC sign-in redirects work) but not on third-party POSTs (CSRF protection).
Secure HTTPS-only. Cookie is never transmitted over plain HTTP.

When Jane signs out, we delete her session row from the server and instruct her browser to clear the cookie. The token stops working immediately, even if a copy of it had been intercepted somewhere — because the lookup target is gone.

Security

All traffic is HTTPS. Magic links are short-lived. Passkey private keys never leave your device. We rotate signing keys and publish JWKS at /.well-known/openid-configuration. To report a security issue, email abuse@chirpauth.com.

Changes

If we change this policy in a way that materially expands what we collect or share, we’ll update the date above and notify active accounts by email at least 14 days before the change takes effect.