eleven / messenger Public

Clone
git clone https://amadan.net/eleven/messenger

Plain git — no account needed to clone.

Download

Download this file

1{
2 "description": "Group-apps registry vectors: which trusted first-party apps a group chat has added. The registry is fold state from wire events in the group's own encrypted log — the server never learns which app was added. Source of truth: web/static/apps.js (the groupapps system app).",
3 "app": "groupapps",
4 "source": "web/static/apps.js (installsApp — one registry for every shared place; this file pins its groupapps event family)",
5 "state_shape": {
6 "apps": [
7 {
8 "id": "string (the added app's name, e.g. \"todo\")",
9 "by": "string (sender name)",
10 "ts": "number (epoch ms)"
11 }
12 ]
13 },
14 "notes": [
15 "The item id IS the app name, so a duplicate add (any member, any refold) is a no-op and a remove needs no lookup.",
16 "Unknown app names fold into state unchanged in shape — clients filter to registered, groupCapable apps at READ time (groupAppsFor), so old and new clients converge on the same log.",
17 "Chat projection: the group fold prefixes the actor's name onto the projection text, so the rendered action line is e.g. \"Ana added To-do to this chat\". The expected_chat_projection below is the raw groupFeedMessage() output, pre-prefix — same convention as todo.json (whose companion app projects via chatMessage instead).",
18 "An app's own events posted into a group thread fold with the app's ordinary vectors (todo.json etc.) — same events, same reducer, keyed by the group thread instead of the personal one."
19 ],
20 "vectors": [
21 {
22 "name": "groupapps_add",
23 "description": "A member adds a trusted app to the group.",
24 "event": {
25 "type": "groupapps.add",
26 "app": "todo",
27 "name": "Ana",
28 "ts": 1700000000000
29 },
30 "expected_state_update": {
31 "apps": [
32 {
33 "id": "todo",
34 "by": "Ana",
35 "ts": 1700000000000
36 }
37 ]
38 },
39 "expected_chat_projection": {
40 "text": "added To-do to this chat",
41 "action": true
42 }
43 },
44 {
45 "name": "groupapps_add_duplicate",
46 "description": "Re-adding an already-added app is a no-op (idempotent by app name).",
47 "event": {
48 "type": "groupapps.add",
49 "app": "todo",
50 "name": "Bob",
51 "ts": 1700000005000
52 },
53 "initial_state": {
54 "apps": [
55 {
56 "id": "todo",
57 "by": "Ana",
58 "ts": 1700000000000
59 }
60 ]
61 },
62 "expected_state_update": {
63 "apps": [
64 {
65 "id": "todo",
66 "by": "Ana",
67 "ts": 1700000000000
68 }
69 ]
70 },
71 "note": "The original add's attribution is kept — a duplicate never rewrites by/ts."
72 },
73 {
74 "name": "groupapps_remove",
75 "description": "A member removes an added app from the group.",
76 "event": {
77 "type": "groupapps.remove",
78 "app": "todo",
79 "name": "Ana",
80 "ts": 1700000010000
81 },
82 "initial_state": {
83 "apps": [
84 {
85 "id": "todo",
86 "by": "Ana",
87 "ts": 1700000000000
88 }
89 ]
90 },
91 "expected_state_update": {
92 "apps": []
93 },
94 "expected_chat_projection": {
95 "text": "removed To-do from this chat",
96 "action": true
97 }
98 },
99 {
100 "name": "groupapps_add_malformed",
101 "description": "An add with no app name (malformed or hostile) folds to a no-op, never a crash.",
102 "event": {
103 "type": "groupapps.add",
104 "name": "Mallory",
105 "ts": 1700000020000
106 },
107 "initial_state": {
108 "apps": []
109 },
110 "expected_state_update": {
111 "apps": []
112 }
113 },
114 {
115 "name": "groupapps_remove_missing",
116 "description": "Removing an app that isn't added (a cancel racing a remove, a refold) is a no-op.",
117 "event": {
118 "type": "groupapps.remove",
119 "app": "todo",
120 "name": "Ana",
121 "ts": 1700000030000
122 },
123 "initial_state": {
124 "apps": []
125 },
126 "expected_state_update": {
127 "apps": []
128 }
129 }
130 ]
131}
132