From c16a573aba42f380f46a4408729d9dd426cb2b8e Mon Sep 17 00:00:00 2001 From: naturzukunft Date: Mon, 16 Mar 2026 10:22:31 +0100 Subject: [PATCH] Add FEP-db70: RemoveAll Collection Activity (#781) This FEP defines a RemoveAll activity for batch-removing items from an ActivityPub collection. While ActivityPub defines Remove for single items, there is no mechanism for removing multiple or all items at once. - New activity type RemoveAll for batch removal from any collection - Optional FEP-34c1 filter to selectively remove items matching criteria (by type, date, actor) - Without filter, all items are removed - Use cases: "mark all as read", clearing old items, filtered batch removal Co-authored-by: automation Reviewed-on: https://codeberg.org/fediverse/fep/pulls/781 Co-authored-by: naturzukunft Co-committed-by: naturzukunft --- fep/db70/fep-db70.jsonld | 16 ++++ fep/db70/fep-db70.md | 186 +++++++++++++++++++++++++++++++++++++++ fep/db70/fep-db70.ttl | 37 ++++++++ 3 files changed, 239 insertions(+) create mode 100644 fep/db70/fep-db70.jsonld create mode 100644 fep/db70/fep-db70.md create mode 100644 fep/db70/fep-db70.ttl diff --git a/fep/db70/fep-db70.jsonld b/fep/db70/fep-db70.jsonld new file mode 100644 index 0000000..99c0960 --- /dev/null +++ b/fep/db70/fep-db70.jsonld @@ -0,0 +1,16 @@ +{ + "_comment": [ + "JSON-LD Context for FEP-db70: RemoveAll Collection Activity.", + "", + "Defines the RemoveAll activity type and the filter property", + "for batch-removing items from ActivityPub collections.", + "", + "See: https://w3id.org/fep/db70" + ], + "@context": { + "fepdb70": "https://w3id.org/fep/db70#", + + "RemoveAll": "fepdb70:RemoveAll", + "filter": {"@id": "fepdb70:filter", "@type": "@id"} + } +} diff --git a/fep/db70/fep-db70.md b/fep/db70/fep-db70.md new file mode 100644 index 0000000..41db255 --- /dev/null +++ b/fep/db70/fep-db70.md @@ -0,0 +1,186 @@ +--- +slug: "db70" +authors: Fred Hauschel <@naturzukunft2026@mastodon.social> +status: DRAFT +dateReceived: 2026-03-15 +discussionsTo: https://socialhub.activitypub.rocks/t/fep-db70-removeall-collection-activity/8569 +--- +# FEP-db70: RemoveAll Collection Activity + +## Summary + +This FEP defines a `RemoveAll` activity for batch-removing items from an ActivityPub collection. While the [ActivityPub] specification defines `Remove` for removing a single item from a collection, there is no mechanism for removing multiple or all items at once. `RemoveAll` fills this gap. It supports an optional [FEP-34c1] filter to selectively remove items matching specific criteria (e.g. by type, by date, or by actor). Without a filter, all items are removed. `RemoveAll` is a generic collection operation — it can be used with any collection type, not just inboxes or notification collections. + +## Motivation + +ActivityPub's `Remove` activity targets a single `object` within a `target` collection. For collections that can grow large, clients need a way to batch-remove items without sending individual `Remove` activities for each item. Common use cases include: + +- "Mark all as read" in a notification collection ([FEP-34ec]) +- Clearing old items from a collection +- Removing all items matching a specific filter (e.g. all items of a certain type) + +Without a batch operation, a client must first fetch all items, then send individual `Remove` activities — which is both slow and prone to race conditions. + +## Specification + +### 1. The `RemoveAll` Activity + +`RemoveAll` is a new activity type that removes multiple items from a target collection. + +```json +{ + "@context": [ + "https://www.w3.org/ns/activitystreams", + "https://w3id.org/fep/db70" + ], + "type": "RemoveAll", + "actor": "https://example.com/actors/bob", + "target": "https://example.com/actors/bob/notifications" +} +``` + +#### Properties + +| Property | Type | Required | Description | +|----------|------|----------|-------------| +| `type` | String | MUST | `RemoveAll` | +| `actor` | IRI | MUST | The actor performing the operation | +| `target` | IRI | MUST | The collection to remove items from | +| `filter` | FilterRequest | MAY | A [FEP-34c1] filter to select which items to remove | + +Without a `filter`, the server MUST remove all items from the target collection. + +### 2. Filtered RemoveAll (with FEP-34c1) + +When a `filter` property is present, only items matching the filter are removed. The filter uses the [FEP-34c1] `FilterRequest` format with [TREE] relations. + +**Remove all items matching a specific property value:** + +```json +{ + "@context": [ + "https://www.w3.org/ns/activitystreams", + "https://w3id.org/fep/db70", + "https://w3id.org/fep/34c1", + "https://w3id.org/tree" + ], + "type": "RemoveAll", + "actor": "https://example.com/actors/bob", + "target": "https://example.com/actors/bob/some-collection", + "filter": { + "type": "FilterRequest", + "relation": [ + { + "type": "EqualToRelation", + "path": { "@id": "rdf:type" }, + "value": { "@id": "as:Create" } + } + ] + } +} +``` + +**Remove all items older than a given date:** + +```json +{ + "type": "RemoveAll", + "actor": "https://example.com/actors/bob", + "target": "https://example.com/actors/bob/some-collection", + "filter": { + "type": "FilterRequest", + "relation": [ + { + "type": "LessThanRelation", + "path": { "@id": "as:published" }, + "value": { "@value": "2026-02-17T00:00:00Z", "@type": "xsd:dateTime" } + } + ] + } +} +``` + +**Combine multiple filter criteria (AND):** + +```json +{ + "type": "RemoveAll", + "actor": "https://example.com/actors/bob", + "target": "https://example.com/actors/bob/some-collection", + "filter": { + "type": "FilterRequest", + "relation": [ + { + "type": "EqualToRelation", + "path": { "@id": "rdf:type" }, + "value": { "@id": "as:Create" } + }, + { + "type": "LessThanRelation", + "path": { "@id": "as:published" }, + "value": { "@value": "2026-02-17T00:00:00Z", "@type": "xsd:dateTime" } + } + ] + } +} +``` + +Multiple `relation` entries are combined with AND — all criteria must match for an item to be removed. + +### 3. Server Behavior + +- The server MUST remove all matching items from the target collection +- The server MUST verify that the `actor` is authorized to modify the target collection +- If the target collection does not exist, the server MUST respond with `404 Not Found` +- Unauthorized requests MUST be rejected with `401 Unauthorized` +- Whether removed items are deleted or archived is determined by the collection's semantics (e.g. [FEP-34ec] specifies that removed notifications MUST be deleted) + +### 4. Response + +The server SHOULD respond with `200 OK` and the number of removed items: + +```json +{ + "@context": "https://www.w3.org/ns/activitystreams", + "summary": "Removed 12 items from the collection" +} +``` + +## Security Considerations + +- `RemoveAll` without a filter removes all items from a collection. Servers SHOULD ensure that the actor is authorized for the target collection. +- Servers SHOULD implement rate limiting for `RemoveAll` operations. + +## Conformance + +A conforming server MUST: +- Process `RemoveAll` activities targeting a collection owned by the actor +- Remove all items when no `filter` is present +- Remove only matching items when a [FEP-34c1] `filter` is present + +A conforming server SHOULD: +- Support [FEP-34c1] `FilterRequest` in the `filter` property + +## Implementations + +- [ChangingGraph](https://changinggraph.org) (reference implementation, in progress) + +## References + +- Christine Lemmer-Webber, Jessica Tallon, Erin Shepherd, Amy Guy, Evan Prodromou, [ActivityPub], 2018 +- James M Snell, Evan Prodromou, [Activity Streams 2.0], 2017 +- naturzukunft, [FEP-34c1: Collection Filtering using TREE Hypermedia], 2025 +- naturzukunft, [FEP-34ec: Notification Collection Endpoint], 2026 +- [TREE Hypermedia Vocabulary][TREE] + +[ActivityPub]: https://www.w3.org/TR/activitypub/ +[Activity Streams 2.0]: https://www.w3.org/TR/activitystreams-core/ +[FEP-34c1]: https://codeberg.org/fediverse/fep/src/branch/main/fep/34c1/fep-34c1.md +[FEP-34ec]: https://codeberg.org/fediverse/fep/src/branch/main/fep/34ec/fep-34ec.md +[TREE]: https://treecg.github.io/specification/ + +## Copyright + +CC0 1.0 Universal (CC0 1.0) Public Domain Dedication + +To the extent possible under law, the authors of this Fediverse Enhancement Proposal have waived all copyright and related or neighboring rights to this work. diff --git a/fep/db70/fep-db70.ttl b/fep/db70/fep-db70.ttl new file mode 100644 index 0000000..2df1a37 --- /dev/null +++ b/fep/db70/fep-db70.ttl @@ -0,0 +1,37 @@ +# FEP-db70: RemoveAll Collection Activity +# +# RDFS/OWL ontology for the FEP-db70 vocabulary terms. +# This is a reference artefact — NOT loaded at runtime. +# It documents the classes and properties defined by FEP-db70. +# +# See: https://w3id.org/fep/db70 + +@prefix fepdb70: . +@prefix fep34c1: . +@prefix as: . +@prefix rdfs: . +@prefix owl: . + +# ── Ontology metadata ──────────────────────────────────────────────── + + + a owl:Ontology ; + rdfs:label "FEP-db70 RemoveAll Collection Activity Vocabulary" ; + rdfs:comment "Defines the RemoveAll activity for batch-removing items from ActivityPub collections." . + +# ── Classes ────────────────────────────────────────────────────────── + +fepdb70:RemoveAll + a rdfs:Class ; + rdfs:subClassOf as:Activity ; + rdfs:label "RemoveAll" ; + rdfs:comment "Removes all (or filtered) items from a target collection. Supports optional FEP-34c1 filtering." . + +# ── Properties ─────────────────────────────────────────────────────── + +fepdb70:filter + a owl:ObjectProperty ; + rdfs:label "filter" ; + rdfs:comment "An optional FEP-34c1 FilterRequest that selects which items to remove. Without a filter, all items are removed." ; + rdfs:domain fepdb70:RemoveAll ; + rdfs:range fep34c1:FilterRequest .