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
"$type": "com.atproto.lexicon.schema",
3
3
"defs": {
4
4
"main": {
5
5
"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.",
6
6
"key": "literal:self",
7
7
"record": {
8
8
"properties": {
9
+
"appView": {
10
+
"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.",
11
+
"type": "string"
12
+
},
9
13
"createdAt": {
10
14
"description": "When this index was first written",
11
15
"format": "datetime",
12
16
"type": "string"
13
17
},
14
18
"subjects": {
15
19
"description": "The accounts currently carrying a native scoped mute.",
16
20
"items": {
17
21
"ref": "#scopedMuteEntry",
18
22
"type": "ref"
19
23
},
20
24
"maxLength": 1000,
21
25
"type": "array"
22
26
},
23
27
"updatedAt": {
24
28
"description": "When this index was last reconciled or edited",
25
29
"format": "datetime",
26
30
"type": "string"
27
31
}
28
32
},
29
33
"required": [
30
34
"subjects",
31
35
"createdAt"
32
36
],
33
37
"type": "object"
34
38
},
35
39
"type": "record"
36
40
},
37
41
"scopedMuteEntry": {
38
42
"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.",
39
43
"properties": {
40
44
"createdAt": {
41
45
"description": "When this scoped mute was set from Anisota",
42
46
"format": "datetime",
43
47
"type": "string"
44
48
},
45
49
"onlyQuoteposts": {
46
50
"default": false,
47
51
"description": "Their quote posts are muted",
48
52
"type": "boolean"
49
53
},
50
54
"onlyReposts": {
51
55
"default": false,
52
56
"description": "Their reposts are muted",
53
57
"type": "boolean"
54
58
},
55
59
"subject": {
56
60
"description": "DID of the scope-muted account",
57
61
"format": "did",
58
62
"type": "string"
59
63
}
60
64
},
61
65
"required": [
62
66
"subject"
63
67
],
64
68
"type": "object"
65
69
}
66
70
},
67
71
"id": "net.anisota.graph.scopedMute",
68
72
"lexicon": 1
69
73
}