Skip to content

Data and privacy

Verified against v0.10.0 · internal/db/migrations, internal/store/users.go, web/src/lib/notificationAudio.ts

Parley stores very little about people, mostly because it never asks. In its default mode there is no account, no email address and no password.

Table Field What it is
users id A generated UUID. Public — it is broadcast to everyone in a room
users name Up to 64 characters. Self-chosen, or derived from an identity-provider claim
users issuer, subject Only for federated sign-in: which provider vouched for you, and your opaque id there. Empty for anonymous users
users avatar_icon The avatar you picked, as one short opaque id (≤32 characters). Empty until you choose one. Public — shown to everyone in a room. Removed with the account: it is a column on the users row, not a separate record
users avatar_accessory Retired in v0.5.1: no longer written or read, and dropped by a later migration
users notification_sounds Whether this user enabled local notification sounds. False by default and never included in rosters or session payloads
users created_at Timestamp
session_tokens token_hash SHA-256 of the bearer token. The token itself is never stored
session_tokens user_id, created_at, last_used_at Which account, and when it was last seen
members space_id, user_id, spectator, last_seen_at Which rooms you have joined
session_presence session_id, user_id, replica_id, seen_at Which session you have a socket open on, and which replica is serving it. Written while you are connected, deleted when you disconnect, and swept once it ages past the presence window (~100s). It is what the space page counts to say “3 here”

No email address is stored, even when signing in through a provider that supplies one — an email is used only to derive a display name, and then discarded. There is no avatar URL and no uploaded image — an avatar is a colour derived from your user id plus, optionally, two ids naming a shape you picked from the built-in set — and no IP address column anywhere.

Everything else is what a team types: session titles, story titles and references, notes up to 2000 characters, votes, and standup entries of up to 2000 characters each.

Treat this as the sensitive data. A story note is where somebody writes the customer’s name or the reason a deadline slipped. It is stored as plain text in Postgres, and it is what a database dump mostly contains.

Nothing, unless you configure it. Parley has no telemetry, no analytics, no crash reporting and no update check.

Notification cues are synthesized in the browser with Web Audio. They use no audio files and make no network request. The server stores only the on/off preference.

In the default open mode it makes no outbound network calls at all. With AUTH_MODE=oidc it calls the identity provider you named and nothing else: the discovery document, the signing keys, and a token exchange per sign-in. The first two are fetched once and cached for the life of the process, so a warm process makes one call per sign-in, not three.

CapabilityStatusWhat to do instead
Retention policyNot builtApplication records are not automatically deleted. Session tokens are the exception: they expire on the configured lifetimes and their rows are swept hourly.
Account deletionNot builtThere is no endpoint. DELETE /api/me ends a session, it does not delete the account. Deleting a users row must be done in SQL, and see the caveat below — it is not a clean cascade.
Per-space export or erasureNot builtExport sessions to CSV individually; erase with SQL against the documented schema.
Expired token cleanupBuilt inAn hourly background pass deletes session_tokens rows past either SESSION_IDLE_TTL or SESSION_MAX_TTL, so the table does not grow without bound.
Encryption at restNot builtParley encrypts nothing itself. Use an encrypted volume or your database provider's encryption.
TelemetryOut of scopeThere is none, and adding it is not planned.

If you need to answer a data-subject request

Section titled “If you need to answer a data-subject request”

There is no tooling for it. In practice: users gives you the person’s row, members the spaces they joined, and their content is reachable by user_id from votes and standup_entries.

members, session_tokens, session_presence, votes and standup_entries all cascade on delete, so removing the users row takes them with it.

Verify against the schema before running anything destructive, and take a backup first.