fab0 privacy notice
This notice describes fab0 from version v0.3.0. It was last changed on 9 November 2026.
Until v0.3.0 is released, the only account that uses fab0's production service is fabtend's own.
Who we are and how to reach us
fab0 is a product of fabtend. fabtend runs fab0 and is the controller of the personal data this notice describes. In this notice, "the operator" is fabtend.
Write to privacy@fab0.dev with any question about this notice or about your data: to ask what fab0 holds about you, to have it corrected or deleted, to object to its use, or to ask for a copy. You may also complain to a data protection authority.
What fab0 is
fab0 is a pipeline driver and the record of its runs, offered as a service. A pipeline is a state machine its user writes as code. fab0 holds each run's state, calls each step at an endpoint the user owns (their own service, an agent's endpoint, or a person's queue), moves the run on when a signal arrives, and keeps the run's record. fab0 decides nothing for its users: it does not judge, approve, merge or label their work.
An account on GitHub, an organization or a person, uses fab0 by installing the fab0 GitHub App. That account is a tenant. The App only reads: repository metadata, issues, pull requests, and the one file .fab0/pipelines.yml. People sign in to fab0 with GitHub, through a remote MCP server for their AI assistants and the same operations over a REST API. A person who can reach one of the tenant's installed repositories is one of its members.
What fab0 keeps
fab0 keeps what it needs to run its tenants' pipelines and to be the record of their runs, which is the service a tenant installs it for. This table is everything it keeps, where, and for how long.
| Data | Store | Where | Kept |
|---|---|---|---|
| A run's record: the inputs it took, its signals, transitions and attempts with their outputs, usage, cost and telemetry, its state and data | the run's Durable Object | EU | while the tenant is installed; deleted 30 days after an uninstall, or when an admin asks once the run's tree has ended |
| The tenant: its installation, repositories, pipelines and their versions, its members' GitHub logins and ids, and the index of its runs | the tenant's Durable Object | EU | while the tenant is installed, a pipeline version that is neither active nor used by an active run 30 days; deleted 30 days after an uninstall |
| Executor secrets, encrypted | the tenant's Durable Object | EU | until replaced or deleted; deleted at an uninstall |
| Applied webhook delivery ids, with each delivery's event and sender's login | the tenant's Durable Object | EU | 7 days |
| Webhook bodies as GitHub sent them | R2 bucket payloads |
EU | 30 days |
| Event references: a delivery's ids and flat fields | Queues | EU | until consumed, at most 4 days |
| The catalogue: ids, pipeline and state names, statuses, times and cost totals | D1 catalog |
EU | as the record and the tenant |
| Metrics: one point per transition, with the tenant, run, pipeline, states, signal name and duration | Analytics Engine | not pinned | 3 months |
| Logs: ids, codes and numbers | R2 bucket fab0-logs |
EU | 30 days |
| Sign-in grants: a person's GitHub user id, hashed tokens, and their tenants and GitHub tokens encrypted | KV | not pinned | an access token 1 hour; a grant 30 days after its last refresh |
| Pages: a dead letter's run or delivery id | the operator's mailbox | not pinned | as long as the operator keeps them |
Mail sent to privacy@fab0.dev |
the operator's mailbox | not pinned | as long as the operator needs it to answer |
"EU" is Cloudflare's EU jurisdiction: the data is stored in the European Union. A period is when the data is deleted: by a storage rule, a queue's retention, an expiry, Analytics Engine's own retention, or the deletions described below.
The personal data in it: the GitHub logins and ids of a tenant's members, and of the person who caused each GitHub event; a signed-in person's GitHub user id; and a tenant's own id, which identifies a person when the tenant is a person's account. A run's record also holds what the tenant's people, agents and services send into it: signals and their reasons, and each step's outputs. fab0 keeps them as sent, and what they contain is the tenant's choice.
What fab0 never keeps
- No secret in clear. The secrets a tenant sets for its endpoints are encrypted under a key for that tenant, and are sent only to the origin each was set for. A GitHub token a person presents to set secrets or delete records is sent to GitHub once to learn who they are, and is not stored. The GitHub tokens of a person's sign-in are kept encrypted in their sign-in grant.
- No prices of its own. The usage and cost in a run's record are what the tenant's endpoints report. fab0 prices nothing, and a cost no one reported stays unknown.
- No content in its catalogue, metrics or logs. They hold ids, names of pipelines and states, statuses, times, codes and numbers. No payload, step output, issue or pull request text, commit message, secret, or person's name or email is written to them.
- Nothing from this site. These pages set no cookie, run no script, take no input, and load nothing from another site. fab0 adds no analytics to them.
Where it is kept and who provides it
Cloudflare hosts fab0: its programs, Durable Objects, D1 database, R2 buckets, queues, key-value store, Analytics Engine, and the mail routing of privacy@fab0.dev. Every store marked "EU" in the table is in Cloudflare's EU jurisdiction. The rows marked "not pinned" are not: Analytics Engine and the sign-in grants may be stored outside the European Union. Where fab0's programs run is not controlled either: Cloudflare may run them, and process the data that passes through them, outside the European Union.
The operator's mailbox receives the mail sent to privacy@fab0.dev, and fab0's alerts to the operator, which hold a run's or a delivery's id. It is not pinned to the European Union either.
GitHub is where the events and the sign-ins come from: the App receives the events of the repositories it is installed on, and people sign in with their GitHub account. fab0 writes nothing to GitHub.
When a step fires, fab0 calls the endpoint the tenant's pipeline names, authorized by the tenant's secret, and sends it one id. That endpoint belongs to the tenant or to a service the tenant chose, and reads the step through fab0's API with that id. What it does with what it reads is the tenant's choice.
Who can read it
A tenant's members read its runs and their records through fab0's API, after signing in with GitHub. An admin of one of the tenant's installed repositories can also change its pipelines, set its secrets and delete its records. No one reads a secret's value back.
The operator reads ids, codes and numbers in the logs and metrics to keep fab0 running, and can reach every store through its Cloudflare account to repair the service. It reads a tenant's data only for that, or when the tenant asks.
How it is deleted
When a tenant uninstalls the App, its secrets are deleted at once and its active runs are cancelled. 30 days later, every run of the tenant, its records, its rows in the catalogue and the tenant itself are deleted. If the App is installed again on the same account within those 30 days, nothing more is deleted: the runs, their records and the pipelines are kept.
While the App is installed, an admin of one of the tenant's installed repositories can delete the tenant's records with one call, using their own GitHub token:
curl -fsS -X DELETE "https://mcp.fab0.dev/api/v1/records?tenant=$TENANT" -H "Authorization: Bearer $(gh auth token)"
Before it, set TENANT in your shell to the id of the GitHub account that installed the App, which fab0's whoami tool shows as tenants[].id. The call deletes every run tree of the tenant whose runs have all ended, within minutes: a run and the child runs it started, at every depth, with their records and catalogue rows. It keeps every tree that has a run still active, and the tenant's pipelines, members and secrets. It answers how many runs are being deleted and how many are kept. Calling it again is harmless.
To delete everything at once, delete the records, then uninstall the App: the rest goes 30 days later. The other stores keep their own periods, given in the table: webhook bodies 30 days, delivery ids 7 days, logs 30 days and metrics 3 months, the last two holding ids only. A sign-in grant expires 30 days after it was last refreshed. To have anything else deleted, write to privacy@fab0.dev.
Changes to this notice
When what fab0 keeps, where, or for how long changes, this notice changes with it, and its date above changes. The notice is published from the same source as fab0's releases, which keeps it equal to fab0's own design.