dev.atfs.repo.listFiles
Schema Diff
+19 -1
Compatibility Analysis
Backward Compatible
No changes detected.
1
1
{
2
2
"id": "dev.atfs.repo.listFiles",
3
3
"defs": {
4
4
"main": {
5
5
"type": "query",
6
6
"output": {
7
7
"schema": {
8
8
"type": "object",
9
9
"required": [
10
10
"files"
11
11
],
12
12
"properties": {
13
13
"files": {
14
14
"type": "array",
15
15
"items": {
16
16
"ref": "dev.atfs.file",
17
17
"type": "ref"
18
-
}
18
+
},
19
+
"description": "Each entry's tags field (see dev.atfs.file) is a flat union: every tag borne by ANY of that file's claims, account-class and mirrored-server alike, with no indication of which claimant applied which — listFiles never discloses who pinned or tagged anything. Pass the `did` parameter above to scope both this listing and each entry's tags to one claimant's own claims instead."
19
20
},
20
21
"cursor": {
21
22
"type": "string",
22
23
"description": "Present only when this page filled up to the requested limit, meaning more files may follow. Its absence marks the final page."
23
24
}
24
25
}
25
26
},
26
27
"encoding": "application/json"
27
28
},
28
29
"parameters": {
29
30
"type": "params",
30
31
"properties": {
32
+
"did": {
33
+
"type": "string",
34
+
"format": "did",
35
+
"minLength": 1,
36
+
"description": "Restrict the listing to files where this DID holds at least one claim (account-class or mirrored-server), and scope both the reported `tags` and the `tag` filter below to just that DID's own claims, instead of the union across every claimant — this is how to ask the question the output otherwise never answers, since listFiles never says on its own which claimant applied a tag. `?did=X&tag=index` therefore means: files X claims, where X itself applied the tag index. Must look like a DID; anything else is `InvalidRequest`. Listing eligibility is unchanged — a file still needs an account-class claim from ANY claimant to appear at all, so naming a followed server's DID here returns only that server's files that ALSO carry a local account-class claim; content held only as a mirror stays unlisted regardless of `did`. Omit for the unscoped, all-claimants view. The cursor does NOT encode this parameter, so a paginated walk must resend the same `did` on every page, exactly as it must keep `limit` and `tag` stable."
37
+
},
38
+
"tag": {
39
+
"type": "array",
40
+
"items": {
41
+
"type": "string",
42
+
"maxLength": 128,
43
+
"minLength": 1,
44
+
"maxGraphemes": 128
45
+
},
46
+
"maxLength": 16,
47
+
"description": "Restrict the listing to files carrying every named tag — `?tag=index&tag=v0.1.0` lists only files tagged with both, ANDed rather than ORed. Plain strings. Without `did` above, a file matches when each named tag appears on at least one of its claims — any claimant, any class — so filtering deliberately doesn't ask who applied a tag, only whether it was applied; this is deliberate, not an oversight. With `did`, matching narrows to that one DID's own claims, so the two parameters together ask a single-claimant question. Omit `tag` for no filtering. The cursor does NOT encode which tags (or which did) produced it — it's a plain lexical cid comparison applied before any filtering, the same as it's applied before the account-claim check — so changing either between calls silently changes what the rest of the walk returns rather than erroring, and a caller paginating a filtered listing must resend the identical tag set (and did) on every page, exactly as it must keep limit stable. This is the same discipline an unfiltered walk already needs; filtering doesn't relax it. Bounded at 16 like a claim's own tag list, since no file can carry more than that and a longer filter could only ever match nothing."
48
+
},
31
49
"limit": {
32
50
"type": "integer",
33
51
"default": 500,
34
52
"maximum": 1000,
35
53
"minimum": 1,
36
54
"description": "Maximum number of files to return in this page."
37
55
},
38
56
"cursor": {
39
57
"type": "string",
40
58
"description": "Opaque resume token from a previous call's response. Omit to start from the beginning."
41
59
}
42
60
}
43
61
},
44
62
"description": "Enumerate every file this instance directly claims — the whole instance, not scoped to any one account, since atfs has no per-repo notion to scope by. This exists so another atfs instance can replicate pins: a follower walks every page, diffs the resulting cid set against its own mirror of this instance, dev.atfs.repo.pinFile whatever's new, and releases whatever's vanished. It's a poll rather than a subscription deliberately — the store keeps no event log, so there's nothing for a websocket-style firehose to replay, and a plain set-diff over current state already yields both pins and unpins with no history needed. Public and unauthenticated, unlike uploadFile/pinFile/deleteFile: every cid this instance pins is already announced to the IPFS DHT as a provider record and served at /ipfs/<cid>, so nothing here is secret, and an instance that has disabled uploads (no serviceDid configured) must still be enumerable. Only DIRECTLY claimed content is listed: a file must have been uploaded here or pinned here by one of this instance's accounts. Content this instance merely mirrors from an instance it follows is deliberately absent, so a mirror never re-exports what it mirrors — which is what makes an A-follows-B-follows-A pair converge instead of echoing, lets an origin's deletions propagate outward, and keeps mirroring non-transitive (follow each origin you actually want). The instance still serves mirrored content at /ipfs/<cid> and announces it to the DHT; it just doesn't advertise it here. A file mid-GC (its pin list has emptied but the bytes haven't been swept yet) or not yet indexed (a large blob whose UnixFS DAG hasn't finished building) is omitted from every page too — both are transient states that can appear or disappear between one poll and the next, so a follower should expect the set it sees to shift slightly poll to poll even with no new uploads, and should never treat a single absence as a deletion."
45
63
}
46
64
},
47
65
"$type": "com.atproto.lexicon.schema",
48
66
"lexicon": 1
49
67
}