Data portability and the right to be forgotten
Kernel is a system of record, and a system of record has to let its data leave — whole, and on demand — and has to let a person be removed from it without destroying the record of what they did. This page says exactly what each of the three portability features does, what it keeps, and what it erases.
Organization export
kernel org export, and the Export page under an organization's settings, produce a
single tar archive of the whole organization: its projects, work items, the dependency
graph, sessions and their workspace file lists, decisions, blockers, approvals, handoffs,
outcomes, artifact metadata, the full event history, members, memberships, invitations, API
tokens (metadata only), webhooks (metadata only), machines, runtimes, saved filters, work
templates, artifact types and the daily analytics rollups.
Inside the archive:
manifest.json— the format version, agenerated_attimestamp, the organization's id, slug and name, and for every collection its row count and a SHA-256 of its file, so the archive is self-describing and verifiable.collections/<name>.jsonl— one JSON object per row, one collection per file.
Two guarantees hold:
- Deterministic. Two exports of unchanged data are byte-for-byte identical apart from the
manifest's
generated_at. Every collection is ordered by a stable key, JSON keys are sorted, and the tar's per-entry metadata is fixed. You can diff two backups and see only what actually changed. - No secrets. The archive contains no password hashes, no API-token secrets or hashes, no webhook signing secrets, no session cookies, no machine-enrolment secrets and no runtime credentials. Each collection is read through an explicit column allowlist, so a secret is never read in the first place — not merely omitted by luck.
Only an owner may export, and only an unconfined credential: a token restricted to a few projects is refused, because a whole-organization dump is not a project-scoped act.
Work export and import
kernel work export writes a project's work items and the graph between them as one portable
JSON document; kernel work import pours such a document into a project — the same one, or a
different one.
Import remaps every id. Each item is created fresh, with a new key and a new id; the
parent links and the blocks / related_to dependencies are rewritten to the new ids, so the
graph is preserved between the new rows. Nothing is ever overwritten — import only creates —
and each new item records where it came from under custom_fields.imported_from.
A document whose graph would form a cycle (through parent links, through blocks
dependencies, or through the two together) is refused before anything is written, using the
same cycle check the live work graph uses.
User export, then anonymisation
A person can get their own data out, and then be removed. The two happen in that order, and the export is always generated before anything is deleted.
Export (GET .../members/{id}/export, allowed to the member themselves or an owner) returns
the person's profile and the rows that are theirs: the work they created or own, the decisions
they made, the approvals they decided, and the events they are the actor of.
Anonymisation then makes the person gone while keeping the record whole. This is deletion by reassignment to a tombstone, not row removal, stated plainly:
What is erased — the person:
- their account (the user row), their display name, their email;
- their password;
- their browser sessions and their personal API tokens;
- their email wherever it was stored as content (invitation records, event payloads);
- their membership of the organization.
What is kept — the record:
- every work item they created or owned, every decision they made, every blocker, approval, outcome, artifact, handoff and event they were the actor of;
- these rows stay exactly where they were, with the person replaced by a single sentinel
tombstone user shown as
deleted user.
The audit of who approved what, decided what and created what therefore survives the person — because that record is the product. A hole where a person used to be tells a reader less than "a user who is no longer here"; anonymisation leaves the second, never the first.
Anonymisation is scoped to one organization and is refused for a person who is a member of another organization (so no row of theirs is stranded elsewhere, pointing at a user who no longer exists), for the last owner of an organization, and for any project-confined credential.