net.anisota.graph.scopedMute
Schema Diff
+4 -0
Compatibility Analysis
Backward Compatible
Backward compatible. 2 non-breaking changes.
Non-Breaking Changes (2)
- AddedVertex AddedVertex { vertex_id: "net.anisota.graph.scopedMute:body.appView" }
- AddedEdge AddedEdge { src: "net.anisota.graph.scopedMute:body", tgt: "net.anisota.graph.scopedMute:body.appView", kind: "prop", name: Some("appView") }
Migration Guidance
Added Elements
AddedVertex { vertex_id: "net.anisota.graph.scopedMute:body.appView" }
Additional Notes
- Non-breaking: AddedEdge { src: "net.anisota.graph.scopedMute:body", tgt: "net.anisota.graph.scopedMute:body.appView", kind: "prop", name: Some("appView") }
1
1
{
2
2
"id": "net.anisota.graph.scopedMute",
3
3
"defs": {
4
4
"main": {
5
5
"key": "literal:self",
6
6
"type": "record",
7
7
"record": {
8
8
"type": "object",
9
9
"required": [
10
10
"subjects",
11
11
"createdAt"
12
12
],
13
13
"properties": {
14
+
"appView": {
15
+
"type": "string",
16
+
"description": "The AppView these mutes were last verified against (e.g. 'bluesky', 'blacksky', 'custom'). Native mutes are held per-AppView, so an index written while reading one AppView says nothing about another; without this, verifying the index against a different AppView reads 'that AppView does not hold this mute' as 'the reader lifted this mute' and deletes it."
17
+
},
14
18
"subjects": {
15
19
"type": "array",
16
20
"items": {
17
21
"ref": "#scopedMuteEntry",
18
22
"type": "ref"
19
23
},
20
24
"maxLength": 1000,
21
25
"description": "The accounts currently carrying a native scoped mute."
22
26
},
23
27
"createdAt": {
24
28
"type": "string",
25
29
"format": "datetime",
26
30
"description": "When this index was first written"
27
31
},
28
32
"updatedAt": {
29
33
"type": "string",
30
34
"format": "datetime",
31
35
"description": "When this index was last reconciled or edited"
32
36
}
33
37
}
34
38
},
35
39
"description": "An index of the accounts whose reposts or quote posts the viewer has muted through Bluesky's native scoped mute (app.bsky.graph.muteActor with onlyReposts / onlyQuoteposts). Bluesky stores the mute itself, but app.bsky.graph.getMutes returns only fully muted accounts, so a scoped mute is otherwise discoverable only by loading each profile. This record lets Anisota list and undo them, and enforce them client-side on unauthenticated reads where no viewer state comes back. It is a cache, not the source of truth: entries are reconciled against viewerState.mutedOnlyReposts / mutedOnlyQuoteposts and dropped when the server disagrees."
36
40
},
37
41
"scopedMuteEntry": {
38
42
"type": "object",
39
43
"required": [
40
44
"subject"
41
45
],
42
46
"properties": {
43
47
"subject": {
44
48
"type": "string",
45
49
"format": "did",
46
50
"description": "DID of the scope-muted account"
47
51
},
48
52
"createdAt": {
49
53
"type": "string",
50
54
"format": "datetime",
51
55
"description": "When this scoped mute was set from Anisota"
52
56
},
53
57
"onlyReposts": {
54
58
"type": "boolean",
55
59
"default": false,
56
60
"description": "Their reposts are muted"
57
61
},
58
62
"onlyQuoteposts": {
59
63
"type": "boolean",
60
64
"default": false,
61
65
"description": "Their quote posts are muted"
62
66
}
63
67
},
64
68
"description": "One account's native scoped mute. At least one scope flag is true — an entry with neither is a full mute or no mute at all, and does not belong here."
65
69
}
66
70
},
67
71
"$type": "com.atproto.lexicon.schema",
68
72
"lexicon": 1
69
73
}