Skip to content
quarry Artifact [0e7d27bb4b]
Login

Artifact [0e7d27bb4b]

Artifact 0e7d27bb4b9632ee22d08e98daf6d1c1676157b643de62315b1ca0098251ccf9:


- Feature Name: `takedown-and-legal-hold` (a site admin disables a
  repository on a notice, or puts it on legal hold, without destroying
  it; every surface answers 451, the owner is told why, and every step
  is logged)
- Start Date: 2026-10-16
- Status: Draft. Decisions settled by the owner on 2026-10-16 (see
  [Decisions](#decisions)). Not built.
- Depends on: RFC 0016 (the repository's bucket binding), RFC 0021
  (forge agents and the site token), #318 (a site admin holds no letters
  on other people's repositories), #933 (the fleet row's stop-serving
  and delete)
- Related: #359 (restrict zeitgeist's deletes of other people's
  repositories)

## Summary
[summary]: #summary

A site admin can take a repository down in two strengths. **Disabled**
is for a notice about the content, copyright above all: the repository
answers 451 to everybody except its own admins, who keep reading and
writing so they can remove what was reported and ask for it back.
**Legal hold** is for material that must be kept as evidence and shown
to nobody, child abuse material or a law-enforcement request: the
repository answers 451 to everybody including its owner, takes no
writes, and can be neither deleted nor un-served until the hold is
lifted. Both are reversible, keep the store byte for byte, tell the
owner the reason in writing, and write a row to a takedown log that
outlives the repository. Housekeeping delete (#933) stays a separate
act and is refused while either is in force.

The rest of what the law asks is process, not code: a designated DMCA
agent, a notice address and form, a counter-notice path, a
repeat-infringer policy and an NCMEC runbook. They are listed under
[Process](#process) so the code and the paperwork land together.

## Why
[why]: #why

The operator is an individual in the United States, and the forge is
hosted in the EU and open to EU users.

- **DMCA §512(c)** shields the operator from users' copyright
  infringement only if the forge has a designated agent registered with
  the Copyright Office, removes or disables reported material
  expeditiously on a valid notice, restores it 10 to 14 business days
  after a counter-notice unless the claimant files suit, and has and
  enforces a repeat-infringer policy. Without them the operator is
  personally liable.
- **18 USC 2258A** (with the REPORT Act, 2024) requires a provider who
  learns of apparent child sexual abuse material to report it to the
  NCMEC CyberTipline and to preserve it, and what goes with it, for one
  year. Scanning is not required. Deleting it is the wrong act; making
  it unreachable and keeping it is the right one.
- **Section 230** covers most other user content with no setup, but not
  copyright and not federal crime, which is why the two above exist.
- **The host's terms.** Hetzner forwards abuse complaints with a
  deadline and can block or terminate the server. A fast, reversible
  disable is what answers one in time.
- **The EU Digital Services Act** applies to a service offered to EU
  users. Its hosting duties are a notice mechanism (Art. 16) and a
  statement of reasons to the affected user (Art. 17); both are cheap
  and are the same shape as the DMCA process, so they are built in.
- **The EU terrorist-content regulation** can order removal within one
  hour. A disable that takes one click and no deploy meets it.

What the forge has today does not meet these. Stop serving deletes the
registration row and its settings, so it is not reversible as a
takedown; delete destroys evidence; neither tells the owner anything;
and nothing is logged beyond the ops history.

## Decisions
[decisions]: #decisions

Settled by the owner on 2026-10-16.

1. **The operator is an individual in the USA.** US law sets the
   obligations; the EU rules are met because they are cheap and match.
2. **Two strengths, disabled and legal hold.** The owner of a disabled
   repository keeps access; nobody but a site admin reaches one on hold.
3. **Housekeeping delete stays.** A site admin deletes abandoned and
   test repositories from the fleet (#933). It is a separate act from a
   takedown and is refused while a repository is disabled or on hold.

## The two strengths
[strengths]: #the-two-strengths

| | Disabled | Legal hold |
|---|---|---|
| For | a notice about the content: copyright, a host complaint, other unlawful content, a terms breach | child abuse material, a preservation request, a law-enforcement order |
| Anonymous readers and other accounts | 451 on every surface | 451 on every surface |
| The repository's own admins (`a`) | read, clone, pull and push as before, with a banner naming the notice | 451, with a page saying the repository is held and nothing else |
| Writes | allowed for its admins, so they can remove what was reported | refused for everybody, so the evidence does not change |
| Mirror pulls (inbound) and mirror pushes (RFC 0022) | paused | paused |
| Webhooks and CI | paused | paused |
| Delete and stop serving | refused | refused |
| Who sets and lifts it | a site admin, person or site token | a site admin person only; a site token may neither set nor lift it |
| Store and settings | kept untouched | kept untouched |

Both are a state on the repository's row, not a new registration, so
lifting one puts the repository back exactly as it was. A held
repository's store is excluded from any cleanup or compaction the forge
runs, so its bytes stay as they were when the hold was set.

A site token may disable, because a host complaint or a removal order
needs an answer in minutes and an agent may be the one awake. It may not
place or lift a legal hold, because that is a judgment about evidence
and about reporting to the authorities, and it is the operator's to
make.

## Every surface
[surfaces]: #every-surface

451 Unavailable For Legal Reasons, with a body saying the repository is
unavailable for legal reasons and, for a disabled one, the notice's
category and date. The status is the one RFC 7725 defines for exactly
this, and it tells a crawler and a cache that the absence is
deliberate.

- **Web**: every page under `/r/<name>/`, its feeds and its badges.
- **API**: every op naming the repository, for anybody the table above
  shuts out.
- **Sync**: clone, pull and push at the sync front, for the same
  people. A refused sync carries the same sentence as its error.
- **Listings and search**: the repository leaves explore, search
  results, the owner's public profile and the home page's lists while
  it is down. Its own admins still see it on their own pages, marked.
- **Files in the bucket**: the bytes of uv files and attachments live in
  the bucket the repository's admin bound (RFC 0016), not in a forge
  bucket. Quarry stops serving and linking them through every quarry
  URL. It does not delete bytes in somebody else's bucket; if the
  binding's public base is the admin's own domain, what that domain
  serves is theirs, and the statement of reasons says so.
- **The edge cache**: on disable and on hold the forge purges
  Cloudflare's cache for the zone, so nothing already cached keeps
  answering. The free plan purges by URL or everything, not by prefix,
  so it purges everything; a takedown is rare and the cache refills.
  The zone token is a sealed forge setting; without one the takedown
  still applies and the fleet says the cache was not purged and must
  be purged by hand.

## The owner is told
[owner]: #the-owner-is-told

On disable the forge sends the repository's owner, and each of its
admins with an email, a statement of reasons: what was taken down, the
strength, the category, the date, the notice's reference, what was
reported as unlawful (the URLs and the claimed work, for copyright),
and what they can do: remove the material and ask for review, or file a
counter-notice. The same text is the banner on a disabled repository.

On legal hold the owner is told only that the repository is unavailable
for legal reasons. Saying more can warn a person under investigation
and get in the way of it, and the DSA's duty to give reasons yields to
that; the statement says what may be said and no more.

## The takedown log
[log]: #the-takedown-log

An append-only table, one row per act: the repository name, its owner
at the time, the strength, the category, the notice reference, the
actor and via (person, token, agent), the reason text, and when. The
acts are disable, hold, restore, lift, counter-notice received, and
reported to NCMEC (with the CyberTipline report number). Rows are never
updated or deleted, and they survive the repository's deletion, because
they are the repeat-infringer record and the evidence that the forge
acted on time. The fleet shows them as a Takedowns tab.

## Notices and counter-notices
[notices]: #notices-and-counter-notices

A public page, `/legal`, names the DMCA agent and the abuse address, and
links a notice form. The form asks for what DMCA §512(c)(3) and DSA
Art. 16 both require: who is reporting and how to reach them, the
URLs, the work or law claimed, the explanation, the good-faith
statement and the statement that it is accurate, and a signature (a
typed full name). A submitted notice lands in the fleet's Takedowns tab
as an open notice and mails the site admins. The form takes nothing
else and sends nothing to the reporter but an acknowledgement.

A notice is not acted on by itself. A site admin reads it and disables
or declines, and the decision is logged with the notice.

The owner of a disabled repository files a counter-notice from its
banner, with the DMCA's elements (the statement under penalty of
perjury that it was removed by mistake, consent to jurisdiction, a
signature). It is logged, mailed to the site admins, and the Takedowns
tab shows the window: the earliest restore date (10 business days on)
and the latest (14). The forge forwards the counter-notice to the
claimant from the site admins' address. On the earliest date the row
shows as due; a site admin restores it unless the claimant has said
they have filed suit. Restoring is never automatic, because "they filed
suit" arrives as an email the forge cannot read.

## Repeat infringers
[repeat]: #repeat-infringers

Each upheld copyright takedown, one that was not restored on a
counter-notice, counts against the repository's owner at the time. At
three in twelve months the fleet's people page marks the account, and
the policy on `/legal` says the account will then be disabled. The
decision to disable the account stays a site admin's, through the
existing account controls, and is logged here too.

## Process
[process]: #process

The paperwork, which ships with rung 1 so the code is never ahead of
it:

- Register the forge's designated DMCA agent with the Copyright Office
  (`dmca.copyright.gov`, $6, renewed every three years), with a P.O.
  box or agent service rather than a home address.
- Open `[email protected]`, name it on `/legal`, and set it as the
  abuse contact for the Hetzner server.
- Write the `/legal` page: the agent, the address, the notice form, the
  counter-notice process, the repeat-infringer policy, and the
  statement that apparent child abuse material is reported to NCMEC.
- An NCMEC runbook in the operator wiki: place a legal hold, do not
  open or copy the material beyond what identifying it needs, file the
  CyberTipline report, record its number on the hold, keep the hold at
  least one year and longer when law enforcement asks, and only then
  lift the hold and delete.
- Turn on Cloudflare's CSAM Scanning Tool for the zone. It is free, it
  flags matches and notifies, and it is the one scanning the forge
  does.

## Not in this RFC
[not]: #not-in-this-rfc

- **Disabling one file or one check-in.** Taking down a single path
  without the whole repository needs zit to refuse to serve named
  artifacts in sync, the way fossil's shun does. That is a zit change
  (zit is ours) and its own RFC. Until then a takedown is the whole
  repository, which is also what large forges do on a DMCA notice.
- **Purging history from other people's clones.** A clone made before
  the takedown is out of the forge's reach. Deleting the repository is
  the forge's purge; nothing more is possible or claimed.
- **Automatic scanning beyond the edge tool.** Not required, and not
  done.

## Build order
[build]: #build-order

| Rung | Work |
|---|---|
| 1 | The hold state on the repository row, `repo.disable`, `repo.hold`, `repo.restore` and `repo.lift` ops, the takedown log, 451 on web, API and sync per the table, delete and stop serving refused under either, the fleet row's actions, the site token's limits; the process items above |
| 2 | Listings and search, bucket files unlinked, the Cloudflare purge and its sealed token, webhooks, CI and mirrors paused |
| 3 | The statement of reasons by mail and banner, `/legal`, the notice form, the Takedowns tab |
| 4 | Counter-notices and their window, the repeat-infringer count and mark |

## Testing
[testing]: #testing

- Disabled: anonymous, another account and a site token without a grant
  get 451 on a page, an API op and a clone; the repository's admin
  pulls, pushes and sees the banner. Restore returns every surface to
  200 with the store and settings unchanged.
- Legal hold: the owner gets 451 everywhere and a push is refused; a
  site token can neither place nor lift a hold; delete and stop serving
  are refused under either strength and say why.
- The store's bytes are identical before a hold and after it is lifted.
- The takedown log gains one row per act, rejects updates, and keeps its
  rows after the repository is deleted.
- A held repository leaves explore and search, and a bucket file's
  quarry URL answers 451.
- The Cloudflare purge is called on disable and hold against a stub,
  and a missing token is reported on the fleet, not hidden.
- A counter-notice shows its earliest and latest restore dates in
  business days; three upheld copyright takedowns in twelve months mark
  the owner, and two do not.