@openvtc/trust-tasks 0.26.14 → 0.26.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. package/CHANGELOG.md +183 -0
  2. package/dist/_shared/components.d.ts +392 -1
  3. package/dist/_shared/components.d.ts.map +1 -1
  4. package/dist/index.d.ts +20 -0
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +20 -0
  7. package/dist/index.js.map +1 -1
  8. package/dist/rooms/_shared/0.1/personal-label.d.ts +16 -0
  9. package/dist/rooms/_shared/0.1/personal-label.d.ts.map +1 -0
  10. package/dist/rooms/_shared/0.1/personal-label.js +6 -0
  11. package/dist/rooms/_shared/0.1/personal-label.js.map +1 -0
  12. package/dist/rooms/_shared/0.1/room.d.ts +1 -1
  13. package/dist/rooms/_shared/0.1/room.d.ts.map +1 -1
  14. package/dist/rooms/blobs/get/0.1/payload.d.ts +4 -4
  15. package/dist/rooms/blobs/get/0.1/payload.js +2 -2
  16. package/dist/rooms/blobs/get/0.1/payload.js.map +1 -1
  17. package/dist/rooms/blobs/get/0.2/payload.d.ts +4 -4
  18. package/dist/rooms/blobs/get/0.2/payload.js +2 -2
  19. package/dist/rooms/blobs/get/0.2/payload.js.map +1 -1
  20. package/dist/rooms/blobs/upload/begin/0.1/payload.d.ts +4 -4
  21. package/dist/rooms/blobs/upload/begin/0.1/payload.js +2 -2
  22. package/dist/rooms/blobs/upload/begin/0.1/payload.js.map +1 -1
  23. package/dist/rooms/blobs/upload/begin/0.2/payload.d.ts +4 -4
  24. package/dist/rooms/blobs/upload/begin/0.2/payload.js +2 -2
  25. package/dist/rooms/blobs/upload/begin/0.2/payload.js.map +1 -1
  26. package/dist/rooms/epoch/chain/0.1/payload.d.ts +4 -4
  27. package/dist/rooms/epoch/chain/0.1/payload.js +2 -2
  28. package/dist/rooms/epoch/chain/0.1/payload.js.map +1 -1
  29. package/dist/rooms/epoch/commits/0.1/payload.d.ts +4 -4
  30. package/dist/rooms/epoch/commits/0.1/payload.js +2 -2
  31. package/dist/rooms/epoch/commits/0.1/payload.js.map +1 -1
  32. package/dist/rooms/epoch/mint/0.1/payload.d.ts +4 -4
  33. package/dist/rooms/epoch/mint/0.1/payload.js +2 -2
  34. package/dist/rooms/epoch/mint/0.1/payload.js.map +1 -1
  35. package/dist/rooms/epoch/prune/0.1/payload.d.ts +4 -4
  36. package/dist/rooms/epoch/prune/0.1/payload.js +2 -2
  37. package/dist/rooms/epoch/prune/0.1/payload.js.map +1 -1
  38. package/dist/rooms/info/0.1/payload.d.ts +4 -4
  39. package/dist/rooms/info/0.1/payload.js +2 -2
  40. package/dist/rooms/info/0.1/payload.js.map +1 -1
  41. package/dist/rooms/keys/act/0.4/payload.d.ts +546 -0
  42. package/dist/rooms/keys/act/0.4/payload.d.ts.map +1 -0
  43. package/dist/rooms/keys/act/0.4/payload.js +305 -0
  44. package/dist/rooms/keys/act/0.4/payload.js.map +1 -0
  45. package/dist/rooms/keys/label/0.1/payload.d.ts +757 -0
  46. package/dist/rooms/keys/label/0.1/payload.d.ts.map +1 -0
  47. package/dist/rooms/keys/label/0.1/payload.js +388 -0
  48. package/dist/rooms/keys/label/0.1/payload.js.map +1 -0
  49. package/dist/rooms/keys/list/0.2/payload.d.ts +667 -0
  50. package/dist/rooms/keys/list/0.2/payload.d.ts.map +1 -0
  51. package/dist/rooms/keys/list/0.2/payload.js +350 -0
  52. package/dist/rooms/keys/list/0.2/payload.js.map +1 -0
  53. package/dist/rooms/keys/present/0.2/payload.d.ts +4 -4
  54. package/dist/rooms/keys/present/0.2/payload.js +2 -2
  55. package/dist/rooms/keys/present/0.2/payload.js.map +1 -1
  56. package/dist/rooms/keys/profile/read/0.1/payload.d.ts +1652 -0
  57. package/dist/rooms/keys/profile/read/0.1/payload.d.ts.map +1 -0
  58. package/dist/rooms/keys/profile/read/0.1/payload.js +649 -0
  59. package/dist/rooms/keys/profile/read/0.1/payload.js.map +1 -0
  60. package/dist/rooms/keys/profile/write/0.1/payload.d.ts +583 -0
  61. package/dist/rooms/keys/profile/write/0.1/payload.d.ts.map +1 -0
  62. package/dist/rooms/keys/profile/write/0.1/payload.js +319 -0
  63. package/dist/rooms/keys/profile/write/0.1/payload.js.map +1 -0
  64. package/dist/rooms/owner/claim/0.1/payload.d.ts +4 -4
  65. package/dist/rooms/owner/claim/0.1/payload.js +2 -2
  66. package/dist/rooms/owner/claim/0.1/payload.js.map +1 -1
  67. package/dist/rooms/owner/group/remove/0.2/payload.d.ts +600 -0
  68. package/dist/rooms/owner/group/remove/0.2/payload.d.ts.map +1 -0
  69. package/dist/rooms/owner/group/remove/0.2/payload.js +310 -0
  70. package/dist/rooms/owner/group/remove/0.2/payload.js.map +1 -0
  71. package/dist/rooms/owner/revoke/0.1/payload.d.ts +1481 -0
  72. package/dist/rooms/owner/revoke/0.1/payload.d.ts.map +1 -0
  73. package/dist/rooms/owner/revoke/0.1/payload.js +811 -0
  74. package/dist/rooms/owner/revoke/0.1/payload.js.map +1 -0
  75. package/dist/rooms/owner/transfer/0.1/payload.d.ts +4 -4
  76. package/dist/rooms/owner/transfer/0.1/payload.js +2 -2
  77. package/dist/rooms/owner/transfer/0.1/payload.js.map +1 -1
  78. package/dist/rooms/records/curate/0.1/payload.d.ts +4 -4
  79. package/dist/rooms/records/curate/0.1/payload.js +2 -2
  80. package/dist/rooms/records/curate/0.1/payload.js.map +1 -1
  81. package/dist/rooms/records/get/0.1/payload.d.ts +4 -4
  82. package/dist/rooms/records/get/0.1/payload.js +2 -2
  83. package/dist/rooms/records/get/0.1/payload.js.map +1 -1
  84. package/dist/rooms/records/get/0.2/payload.d.ts +4 -4
  85. package/dist/rooms/records/get/0.2/payload.js +2 -2
  86. package/dist/rooms/records/get/0.2/payload.js.map +1 -1
  87. package/dist/rooms/records/list/0.1/payload.d.ts +4 -4
  88. package/dist/rooms/records/list/0.1/payload.js +2 -2
  89. package/dist/rooms/records/list/0.1/payload.js.map +1 -1
  90. package/dist/rooms/records/list/0.2/payload.d.ts +4 -4
  91. package/dist/rooms/records/list/0.2/payload.js +2 -2
  92. package/dist/rooms/records/list/0.2/payload.js.map +1 -1
  93. package/dist/rooms/records/put/0.1/payload.d.ts +4 -4
  94. package/dist/rooms/records/put/0.1/payload.js +2 -2
  95. package/dist/rooms/records/put/0.1/payload.js.map +1 -1
  96. package/dist/rooms/records/put/0.2/payload.d.ts +4 -4
  97. package/dist/rooms/records/put/0.2/payload.js +2 -2
  98. package/dist/rooms/records/put/0.2/payload.js.map +1 -1
  99. package/dist/rooms/revocations/get/0.1/payload.d.ts +905 -0
  100. package/dist/rooms/revocations/get/0.1/payload.d.ts.map +1 -0
  101. package/dist/rooms/revocations/get/0.1/payload.js +512 -0
  102. package/dist/rooms/revocations/get/0.1/payload.js.map +1 -0
  103. package/dist/rooms/revocations/put/0.1/payload.d.ts +1021 -0
  104. package/dist/rooms/revocations/put/0.1/payload.d.ts.map +1 -0
  105. package/dist/rooms/revocations/put/0.1/payload.js +583 -0
  106. package/dist/rooms/revocations/put/0.1/payload.js.map +1 -0
  107. package/dist/rooms/usage/0.1/payload.d.ts +4 -4
  108. package/dist/rooms/usage/0.1/payload.js +2 -2
  109. package/dist/rooms/usage/0.1/payload.js.map +1 -1
  110. package/dist/vtc/_shared/0.1/community-room.d.ts +1 -1
  111. package/dist/vtc/_shared/0.1/community-room.d.ts.map +1 -1
  112. package/dist/vtc/community/theme/show/0.1/payload.d.ts +238 -0
  113. package/dist/vtc/community/theme/show/0.1/payload.d.ts.map +1 -0
  114. package/dist/vtc/community/theme/show/0.1/payload.js +135 -0
  115. package/dist/vtc/community/theme/show/0.1/payload.js.map +1 -0
  116. package/dist/vtc/community/theme/update/0.1/payload.d.ts +286 -0
  117. package/dist/vtc/community/theme/update/0.1/payload.d.ts.map +1 -0
  118. package/dist/vtc/community/theme/update/0.1/payload.js +157 -0
  119. package/dist/vtc/community/theme/update/0.1/payload.js.map +1 -0
  120. package/dist/vtc/rooms/community/create/0.1/payload.d.ts +4 -4
  121. package/dist/vtc/rooms/community/create/0.1/payload.js +2 -2
  122. package/dist/vtc/rooms/community/create/0.1/payload.js.map +1 -1
  123. package/dist/vtc/rooms/community/create/0.2/payload.d.ts +989 -0
  124. package/dist/vtc/rooms/community/create/0.2/payload.d.ts.map +1 -0
  125. package/dist/vtc/rooms/community/create/0.2/payload.js +559 -0
  126. package/dist/vtc/rooms/community/create/0.2/payload.js.map +1 -0
  127. package/dist/vtc/rooms/community/create/0.3/payload.d.ts +1013 -0
  128. package/dist/vtc/rooms/community/create/0.3/payload.d.ts.map +1 -0
  129. package/dist/vtc/rooms/community/create/0.3/payload.js +577 -0
  130. package/dist/vtc/rooms/community/create/0.3/payload.js.map +1 -0
  131. package/dist/vtc/rooms/community/get/0.1/payload.d.ts +4 -4
  132. package/dist/vtc/rooms/community/get/0.1/payload.js +2 -2
  133. package/dist/vtc/rooms/community/get/0.1/payload.js.map +1 -1
  134. package/dist/vtc/rooms/community/get/0.2/payload.d.ts +887 -0
  135. package/dist/vtc/rooms/community/get/0.2/payload.d.ts.map +1 -0
  136. package/dist/vtc/rooms/community/get/0.2/payload.js +517 -0
  137. package/dist/vtc/rooms/community/get/0.2/payload.js.map +1 -0
  138. package/dist/vtc/rooms/community/list/0.1/payload.d.ts +4 -4
  139. package/dist/vtc/rooms/community/list/0.1/payload.js +2 -2
  140. package/dist/vtc/rooms/community/list/0.1/payload.js.map +1 -1
  141. package/dist/vtc/rooms/community/list/0.2/payload.d.ts +960 -0
  142. package/dist/vtc/rooms/community/list/0.2/payload.d.ts.map +1 -0
  143. package/dist/vtc/rooms/community/list/0.2/payload.js +544 -0
  144. package/dist/vtc/rooms/community/list/0.2/payload.js.map +1 -0
  145. package/dist/vtc/rooms/community/members/remove/0.2/payload.d.ts +681 -0
  146. package/dist/vtc/rooms/community/members/remove/0.2/payload.d.ts.map +1 -0
  147. package/dist/vtc/rooms/community/members/remove/0.2/payload.js +393 -0
  148. package/dist/vtc/rooms/community/members/remove/0.2/payload.js.map +1 -0
  149. package/dist/vtc/rooms/community/update/0.1/payload.d.ts +1013 -0
  150. package/dist/vtc/rooms/community/update/0.1/payload.d.ts.map +1 -0
  151. package/dist/vtc/rooms/community/update/0.1/payload.js +573 -0
  152. package/dist/vtc/rooms/community/update/0.1/payload.js.map +1 -0
  153. package/dist/vtc/rooms/community/update/0.2/payload.d.ts +1037 -0
  154. package/dist/vtc/rooms/community/update/0.2/payload.d.ts.map +1 -0
  155. package/dist/vtc/rooms/community/update/0.2/payload.js +593 -0
  156. package/dist/vtc/rooms/community/update/0.2/payload.js.map +1 -0
  157. package/dist/vtc/rooms/offers/list/0.1/payload.d.ts +4 -4
  158. package/dist/vtc/rooms/offers/list/0.1/payload.js +2 -2
  159. package/dist/vtc/rooms/offers/list/0.1/payload.js.map +1 -1
  160. package/dist/vtc/rooms/offers/list/0.2/payload.d.ts +736 -0
  161. package/dist/vtc/rooms/offers/list/0.2/payload.d.ts.map +1 -0
  162. package/dist/vtc/rooms/offers/list/0.2/payload.js +430 -0
  163. package/dist/vtc/rooms/offers/list/0.2/payload.js.map +1 -0
  164. package/package.json +1 -1
  165. package/src/_shared/components.ts +426 -1
  166. package/src/index.ts +20 -0
  167. package/src/rooms/_shared/0.1/personal-label.ts +17 -0
  168. package/src/rooms/_shared/0.1/room.ts +1 -1
  169. package/src/rooms/blobs/get/0.1/payload.ts +2 -2
  170. package/src/rooms/blobs/get/0.2/payload.ts +2 -2
  171. package/src/rooms/blobs/upload/begin/0.1/payload.ts +2 -2
  172. package/src/rooms/blobs/upload/begin/0.2/payload.ts +2 -2
  173. package/src/rooms/epoch/chain/0.1/payload.ts +2 -2
  174. package/src/rooms/epoch/commits/0.1/payload.ts +2 -2
  175. package/src/rooms/epoch/mint/0.1/payload.ts +2 -2
  176. package/src/rooms/epoch/prune/0.1/payload.ts +2 -2
  177. package/src/rooms/info/0.1/payload.ts +2 -2
  178. package/src/rooms/keys/act/0.4/payload.ts +380 -0
  179. package/src/rooms/keys/label/0.1/payload.ts +474 -0
  180. package/src/rooms/keys/list/0.2/payload.ts +412 -0
  181. package/src/rooms/keys/present/0.2/payload.ts +2 -2
  182. package/src/rooms/keys/profile/read/0.1/payload.ts +1617 -0
  183. package/src/rooms/keys/profile/write/0.1/payload.ts +388 -0
  184. package/src/rooms/owner/claim/0.1/payload.ts +2 -2
  185. package/src/rooms/owner/group/remove/0.2/payload.ts +415 -0
  186. package/src/rooms/owner/revoke/0.1/payload.ts +954 -0
  187. package/src/rooms/owner/transfer/0.1/payload.ts +2 -2
  188. package/src/rooms/records/curate/0.1/payload.ts +2 -2
  189. package/src/rooms/records/get/0.1/payload.ts +2 -2
  190. package/src/rooms/records/get/0.2/payload.ts +2 -2
  191. package/src/rooms/records/list/0.1/payload.ts +2 -2
  192. package/src/rooms/records/list/0.2/payload.ts +2 -2
  193. package/src/rooms/records/put/0.1/payload.ts +2 -2
  194. package/src/rooms/records/put/0.2/payload.ts +2 -2
  195. package/src/rooms/revocations/get/0.1/payload.ts +562 -0
  196. package/src/rooms/revocations/put/0.1/payload.ts +637 -0
  197. package/src/rooms/usage/0.1/payload.ts +2 -2
  198. package/src/vtc/_shared/0.1/community-room.ts +1 -1
  199. package/src/vtc/community/theme/show/0.1/payload.ts +170 -0
  200. package/src/vtc/community/theme/update/0.1/payload.ts +204 -0
  201. package/src/vtc/rooms/community/create/0.1/payload.ts +2 -2
  202. package/src/vtc/rooms/community/create/0.2/payload.ts +613 -0
  203. package/src/vtc/rooms/community/create/0.3/payload.ts +635 -0
  204. package/src/vtc/rooms/community/get/0.1/payload.ts +2 -2
  205. package/src/vtc/rooms/community/get/0.2/payload.ts +549 -0
  206. package/src/vtc/rooms/community/list/0.1/payload.ts +2 -2
  207. package/src/vtc/rooms/community/list/0.2/payload.ts +591 -0
  208. package/src/vtc/rooms/community/members/remove/0.2/payload.ts +439 -0
  209. package/src/vtc/rooms/community/update/0.1/payload.ts +629 -0
  210. package/src/vtc/rooms/community/update/0.2/payload.ts +653 -0
  211. package/src/vtc/rooms/offers/list/0.1/payload.ts +2 -2
  212. package/src/vtc/rooms/offers/list/0.2/payload.ts +473 -0
@@ -0,0 +1,954 @@
1
+ /**
2
+ * Generated by scripts/build-ts-bindings.mjs — DO NOT EDIT BY HAND.
3
+ * Source: specs/rooms/owner/revoke/0.1/payload.schema.json
4
+ */
5
+
6
+ import type { CredentialRevocation, DigestMultibase, Ext, RevocationEntry, RevocationHead, RevocationList, RoomRevocation, SubjectRevocation } from "../../../../_shared/components.js";
7
+
8
+
9
+ /**
10
+ * One withdrawal to add, discriminated by `kind` as a RevocationEntry is. It carries no `revokedAt`: the recipient stamps the time it signs, so that a subject or room entry withdraws exactly what the room had issued until then and nothing the caller dated.
11
+ */
12
+ export type Withdrawal = WithdrawCredential | WithdrawSubject | WithdrawRoom;
13
+
14
+ /**
15
+ * A room's owner asks their own agent to withdraw credentials the room issued: sign the room's next revocation list as the room, keep it, and deliver it to each host serving the room.
16
+ */
17
+ export interface RoomsOwnerRevokePayload {
18
+ /**
19
+ * The room whose credentials are withdrawn. The recipient signs as this room.
20
+ */
21
+ roomId: string;
22
+ /**
23
+ * Which held key signs as the room — named explicitly, as for rooms/owner/issue-authority, because nothing maps a DID to the key it was minted with. A key that is not one the room's DID document lists for `assertionMethod` produces a list every host refuses.
24
+ */
25
+ signingKeyId: string;
26
+ /**
27
+ * Every host serving the room, as DIDs: its primary, any mirror, and a host it is moving to. A withdrawal binds only the hosts that hold it, so a host left off this list honours what the room withdrew.
28
+ *
29
+ * @minItems 1
30
+ * @maxItems 8
31
+ */
32
+ hosts:
33
+ | [string]
34
+ | [string, string]
35
+ | [string, string, string]
36
+ | [string, string, string, string]
37
+ | [string, string, string, string, string]
38
+ | [string, string, string, string, string, string]
39
+ | [string, string, string, string, string, string, string]
40
+ | [string, string, string, string, string, string, string, string];
41
+ /**
42
+ * What to withdraw now. Absent or empty: sign nothing new, and deliver the list the recipient holds — how a host the room has moved to, or one that missed a delivery, is brought up to date.
43
+ *
44
+ * @maxItems 64
45
+ */
46
+ withdraw?: Withdrawal[];
47
+ /**
48
+ * Why, for the owner's own record. Never put into the list, which reaches every host: it MUST NOT carry personal data or a credential.
49
+ */
50
+ reason?: string;
51
+ /**
52
+ * Ecosystem-defined extension members per SPEC.md §4.5.1.
53
+ */
54
+ ext?: Ext;
55
+ }
56
+ export interface WithdrawCredential {
57
+ kind: "credential";
58
+ /**
59
+ * The `id` of the credential withdrawn.
60
+ */
61
+ credentialId: string;
62
+ /**
63
+ * OPTIONAL. The credential's own `validUntil`, after which the entry can be dropped.
64
+ */
65
+ until?: string;
66
+ }
67
+ export interface WithdrawSubject {
68
+ kind: "subject";
69
+ /**
70
+ * The party withdrawn: every credential naming them as subject or issuer that the room's chain gave them before now. Never the room.
71
+ */
72
+ subject: string;
73
+ /**
74
+ * OPTIONAL. When the last credential the room issued them expires, after which the entry can be dropped.
75
+ */
76
+ until?: string;
77
+ }
78
+ export interface WithdrawRoom {
79
+ kind: "room";
80
+ /**
81
+ * OPTIONAL. When the last credential the room issued before now expires.
82
+ */
83
+ until?: string;
84
+ }
85
+ /**
86
+ * Success response to rooms/owner/revoke. Type https://trusttasks.org/spec/rooms/owner/revoke/0.1#response. The list the recipient now holds for the room, and what each host did with it. A success says the list was signed and kept; only a delivery whose outcome is `accepted` says a host enforces it.
87
+ */
88
+ export interface RoomsOwnerRevokeResponsePayload {
89
+ roomId: string;
90
+ /**
91
+ * The room's current list, as signed. Returned so the owner holds a copy that does not depend on the recipient.
92
+ */
93
+ list: RevocationList;
94
+ head: RevocationHead;
95
+ /**
96
+ * One per host in the request, in its order.
97
+ *
98
+ * @minItems 1
99
+ * @maxItems 8
100
+ */
101
+ deliveries:
102
+ | [Delivery]
103
+ | [Delivery, Delivery]
104
+ | [Delivery, Delivery, Delivery]
105
+ | [Delivery, Delivery, Delivery, Delivery]
106
+ | [Delivery, Delivery, Delivery, Delivery, Delivery]
107
+ | [Delivery, Delivery, Delivery, Delivery, Delivery, Delivery]
108
+ | [Delivery, Delivery, Delivery, Delivery, Delivery, Delivery, Delivery]
109
+ | [Delivery, Delivery, Delivery, Delivery, Delivery, Delivery, Delivery, Delivery];
110
+ ext?: Ext;
111
+ }
112
+ /**
113
+ * What one host did with the list.
114
+ */
115
+ export interface Delivery {
116
+ host: string;
117
+ /**
118
+ * `accepted`: the host holds this list, or answered it as a repeat, and enforces it from `inForceAt`. `refused`: it answered and declined; its code is in `code`. `unreachable`: no answer, so the outcome is unknown — repeat the request with no `withdraw` to deliver again.
119
+ */
120
+ outcome: "accepted" | "refused" | "unreachable";
121
+ /**
122
+ * The head the host answered with. Present when `accepted`.
123
+ */
124
+ head?: RevocationHead;
125
+ /**
126
+ * When the host began enforcing the list. Present when `accepted`.
127
+ */
128
+ inForceAt?: string;
129
+ /**
130
+ * The host's error code. Present when `refused`.
131
+ */
132
+ code?: string;
133
+ }
134
+
135
+ /** Shared definitions this specification references, re-exported under the names it used to declare them with. */
136
+ export type { CredentialRevocation, DigestMultibase, Ext, RevocationEntry, RevocationHead, RevocationList, RoomRevocation, SubjectRevocation };
137
+
138
+ /** Trust Task type URI. */
139
+ export const TYPE_URI = "https://trusttasks.org/spec/rooms/owner/revoke/0.1" as const;
140
+
141
+ /** Stable alias for this specification's request payload shape. */
142
+ export type Payload = RoomsOwnerRevokePayload;
143
+
144
+ /** Trust Task response type URI (request type URI + "#response"). */
145
+ export const RESPONSE_TYPE_URI = "https://trusttasks.org/spec/rooms/owner/revoke/0.1#response" as const;
146
+
147
+ /** Stable alias for this specification's success-response payload shape. */
148
+ export type Response = RoomsOwnerRevokeResponsePayload;
149
+
150
+ /**
151
+ * This specification's payload schema, as a value.
152
+ *
153
+ * SPEC.md §7.2 item 2 is performed against this. It is shipped as data
154
+ * rather than only as a `.json` file because TypeScript types are erased
155
+ * at runtime: without a schema a consumer has nothing to validate, and
156
+ * every REQUIRED payload member is optional in practice. Cross-file
157
+ * `$ref`s are already inlined, so it needs no resolver.
158
+ */
159
+ export const PAYLOAD_SCHEMA = {
160
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
161
+ "$id": "https://trusttasks.org/spec/rooms/owner/revoke/0.1",
162
+ "title": "Rooms Owner Revoke — payload",
163
+ "description": "A room's owner asks their own agent to withdraw credentials the room issued: sign the room's next revocation list as the room, keep it, and deliver it to each host serving the room.",
164
+ "type": "object",
165
+ "additionalProperties": false,
166
+ "required": [
167
+ "roomId",
168
+ "signingKeyId",
169
+ "hosts"
170
+ ],
171
+ "properties": {
172
+ "roomId": {
173
+ "type": "string",
174
+ "minLength": 1,
175
+ "maxLength": 512,
176
+ "description": "The room whose credentials are withdrawn. The recipient signs as this room."
177
+ },
178
+ "signingKeyId": {
179
+ "type": "string",
180
+ "minLength": 1,
181
+ "maxLength": 256,
182
+ "description": "Which held key signs as the room — named explicitly, as for rooms/owner/issue-authority, because nothing maps a DID to the key it was minted with. A key that is not one the room's DID document lists for `assertionMethod` produces a list every host refuses."
183
+ },
184
+ "hosts": {
185
+ "type": "array",
186
+ "minItems": 1,
187
+ "maxItems": 8,
188
+ "uniqueItems": true,
189
+ "items": {
190
+ "type": "string",
191
+ "pattern": "^did:",
192
+ "maxLength": 2048
193
+ },
194
+ "description": "Every host serving the room, as DIDs: its primary, any mirror, and a host it is moving to. A withdrawal binds only the hosts that hold it, so a host left off this list honours what the room withdrew."
195
+ },
196
+ "withdraw": {
197
+ "type": "array",
198
+ "maxItems": 64,
199
+ "items": {
200
+ "$ref": "#/$defs/Withdrawal"
201
+ },
202
+ "description": "What to withdraw now. Absent or empty: sign nothing new, and deliver the list the recipient holds — how a host the room has moved to, or one that missed a delivery, is brought up to date."
203
+ },
204
+ "reason": {
205
+ "type": "string",
206
+ "minLength": 1,
207
+ "maxLength": 500,
208
+ "description": "Why, for the owner's own record. Never put into the list, which reaches every host: it MUST NOT carry personal data or a credential."
209
+ },
210
+ "ext": {
211
+ "$ref": "#/$defs/Ext",
212
+ "description": "Ecosystem-defined extension members per SPEC.md §4.5.1."
213
+ }
214
+ },
215
+ "$defs": {
216
+ "Withdrawal": {
217
+ "title": "Withdrawal",
218
+ "description": "One withdrawal to add, discriminated by `kind` as a RevocationEntry is. It carries no `revokedAt`: the recipient stamps the time it signs, so that a subject or room entry withdraws exactly what the room had issued until then and nothing the caller dated.",
219
+ "oneOf": [
220
+ {
221
+ "$ref": "#/$defs/WithdrawCredential"
222
+ },
223
+ {
224
+ "$ref": "#/$defs/WithdrawSubject"
225
+ },
226
+ {
227
+ "$ref": "#/$defs/WithdrawRoom"
228
+ }
229
+ ]
230
+ },
231
+ "WithdrawCredential": {
232
+ "title": "WithdrawCredential",
233
+ "type": "object",
234
+ "additionalProperties": false,
235
+ "required": [
236
+ "kind",
237
+ "credentialId"
238
+ ],
239
+ "properties": {
240
+ "kind": {
241
+ "const": "credential"
242
+ },
243
+ "credentialId": {
244
+ "type": "string",
245
+ "minLength": 1,
246
+ "maxLength": 2048,
247
+ "description": "The `id` of the credential withdrawn."
248
+ },
249
+ "until": {
250
+ "type": "string",
251
+ "format": "date-time",
252
+ "description": "OPTIONAL. The credential's own `validUntil`, after which the entry can be dropped."
253
+ }
254
+ }
255
+ },
256
+ "WithdrawSubject": {
257
+ "title": "WithdrawSubject",
258
+ "type": "object",
259
+ "additionalProperties": false,
260
+ "required": [
261
+ "kind",
262
+ "subject"
263
+ ],
264
+ "properties": {
265
+ "kind": {
266
+ "const": "subject"
267
+ },
268
+ "subject": {
269
+ "type": "string",
270
+ "pattern": "^did:",
271
+ "maxLength": 2048,
272
+ "description": "The party withdrawn: every credential naming them as subject or issuer that the room's chain gave them before now. Never the room."
273
+ },
274
+ "until": {
275
+ "type": "string",
276
+ "format": "date-time",
277
+ "description": "OPTIONAL. When the last credential the room issued them expires, after which the entry can be dropped."
278
+ }
279
+ }
280
+ },
281
+ "WithdrawRoom": {
282
+ "title": "WithdrawRoom",
283
+ "type": "object",
284
+ "additionalProperties": false,
285
+ "required": [
286
+ "kind"
287
+ ],
288
+ "properties": {
289
+ "kind": {
290
+ "const": "room"
291
+ },
292
+ "until": {
293
+ "type": "string",
294
+ "format": "date-time",
295
+ "description": "OPTIONAL. When the last credential the room issued before now expires."
296
+ }
297
+ }
298
+ },
299
+ "Delivery": {
300
+ "title": "Delivery",
301
+ "type": "object",
302
+ "additionalProperties": false,
303
+ "required": [
304
+ "host",
305
+ "outcome"
306
+ ],
307
+ "description": "What one host did with the list.",
308
+ "properties": {
309
+ "host": {
310
+ "type": "string",
311
+ "pattern": "^did:",
312
+ "maxLength": 2048
313
+ },
314
+ "outcome": {
315
+ "type": "string",
316
+ "enum": [
317
+ "accepted",
318
+ "refused",
319
+ "unreachable"
320
+ ],
321
+ "description": "`accepted`: the host holds this list, or answered it as a repeat, and enforces it from `inForceAt`. `refused`: it answered and declined; its code is in `code`. `unreachable`: no answer, so the outcome is unknown — repeat the request with no `withdraw` to deliver again."
322
+ },
323
+ "head": {
324
+ "$ref": "#/$defs/RevocationHead",
325
+ "description": "The head the host answered with. Present when `accepted`."
326
+ },
327
+ "inForceAt": {
328
+ "type": "string",
329
+ "format": "date-time",
330
+ "description": "When the host began enforcing the list. Present when `accepted`."
331
+ },
332
+ "code": {
333
+ "type": "string",
334
+ "maxLength": 128,
335
+ "description": "The host's error code. Present when `refused`."
336
+ }
337
+ }
338
+ },
339
+ "Response": {
340
+ "$anchor": "response",
341
+ "title": "Rooms Owner Revoke — response payload",
342
+ "description": "Success response to rooms/owner/revoke. Type https://trusttasks.org/spec/rooms/owner/revoke/0.1#response. The list the recipient now holds for the room, and what each host did with it. A success says the list was signed and kept; only a delivery whose outcome is `accepted` says a host enforces it.",
343
+ "type": "object",
344
+ "additionalProperties": false,
345
+ "required": [
346
+ "roomId",
347
+ "list",
348
+ "head",
349
+ "deliveries"
350
+ ],
351
+ "properties": {
352
+ "roomId": {
353
+ "type": "string",
354
+ "minLength": 1,
355
+ "maxLength": 512
356
+ },
357
+ "list": {
358
+ "$ref": "#/$defs/RevocationList",
359
+ "description": "The room's current list, as signed. Returned so the owner holds a copy that does not depend on the recipient."
360
+ },
361
+ "head": {
362
+ "$ref": "#/$defs/RevocationHead"
363
+ },
364
+ "deliveries": {
365
+ "type": "array",
366
+ "minItems": 1,
367
+ "maxItems": 8,
368
+ "items": {
369
+ "$ref": "#/$defs/Delivery"
370
+ },
371
+ "description": "One per host in the request, in its order."
372
+ },
373
+ "ext": {
374
+ "$ref": "#/$defs/Ext"
375
+ }
376
+ }
377
+ },
378
+ "Ext": {
379
+ "title": "Ext",
380
+ "description": "Vendor-namespaced extension object per SPEC.md §4.5.1. Each immediate key MUST be a reverse-DNS namespace; structure under each namespace is opaque to the framework.",
381
+ "type": "object",
382
+ "minProperties": 1,
383
+ "additionalProperties": true,
384
+ "propertyNames": {
385
+ "pattern": "^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)+$"
386
+ }
387
+ },
388
+ "RevocationHead": {
389
+ "title": "RevocationHead",
390
+ "type": "object",
391
+ "additionalProperties": false,
392
+ "required": [
393
+ "sequence",
394
+ "digest"
395
+ ],
396
+ "description": "Which `RevocationList` a party holds, without its entries: comparable between the room's key holder and a host, and between two hosts, without disclosing whom the room withdrew.",
397
+ "properties": {
398
+ "sequence": {
399
+ "type": "integer",
400
+ "minimum": 1,
401
+ "description": "The list's `sequence`."
402
+ },
403
+ "digest": {
404
+ "$ref": "#/$defs/DigestMultibase",
405
+ "description": "SHA-256 multihash of the list's RFC 8785 (JCS) canonicalization, `proof` included. Two parties holding one sequence with different digests have been given two lists the room signed at one sequence."
406
+ }
407
+ }
408
+ },
409
+ "DigestMultibase": {
410
+ "title": "DigestMultibase",
411
+ "description": "A cryptographic digest as a multibase-encoded multihash — the encoding the W3C Verifiable Credentials Data Model 2.0 defines for `digestMultibase`, and the one `did:webvh` uses for its SCID and entry hashes.\n\nMultihash carries the hash algorithm in-band, so the value is self-describing and the wire format survives an algorithm change without a schema revision; multibase does the same for the base encoding, so a verifier never infers base58 from base64url by context. A bare hex string or a `sha-256:`-style prefix hard-codes one algorithm into the wire contract and is non-conforming here.\n\nThis definition constrains the *encoding only*. What the digest is computed over is stated by each referencing field, because it differs legitimately: a digest over a JSON document is taken over its RFC 8785 (JCS) canonicalization, while a digest over an opaque artifact is taken over its bytes. A field whose input is a JSON document and which does not name a canonicalization is not reproducible.\n\nRestricted to the two multibase headers W3C Controlled Identifiers 1.0 §2.4 normatively requires — `z` (base58btc) and `u` (base64url-no-pad). CID permits others but states that \"interoperability is not guaranteed between implementations using such values\", and a registry whose purpose is interoperability should not mint digests a conforming verifier may be unable to read. The alphabets are enforced rather than assumed: base58btc excludes 0, O, I and l, and an earlier permissive pattern let three published examples carry digests that were not valid base58 at all. base58btc is RECOMMENDED, for consistency with `did:key` and `did:webvh`.",
412
+ "type": "string",
413
+ "minLength": 16,
414
+ "pattern": "^(z[1-9A-HJ-NP-Za-km-z]+|u[A-Za-z0-9_-]+)$",
415
+ "examples": [
416
+ "zQmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR"
417
+ ]
418
+ },
419
+ "RevocationList": {
420
+ "title": "RevocationList",
421
+ "type": "object",
422
+ "additionalProperties": false,
423
+ "required": [
424
+ "roomId",
425
+ "sequence",
426
+ "issuedAt",
427
+ "entries",
428
+ "proof"
429
+ ],
430
+ "description": "The room's own statement of which credentials it has withdrawn before they expire — signed by the room, cumulative, and numbered, so that it means the same thing at every host it is delivered to.\n\n**Why the room signs it, and why it is cumulative.** A host authorizes from credentials the room issued and keeps no roster; a withdrawal kept only as a host's own state would make the room unmovable and the host part of the membership. A list the room signed is room state: it moves with the room, any host it is delivered to reaches the same decision, and nothing a host invents can be mistaken for it. It is cumulative — every list carries every entry still in force — so a host holding any one list holds the room's whole withdrawal state, and a host that missed a list loses nothing once it receives a later one.\n\n**Producing.** The room's key holder builds the object without `proof` and signs it with a W3C Data Integrity proof whose `verificationMethod` is a key the room's DID document lists for `assertionMethod` and whose `proofPurpose` is `assertionMethod`. A producer MUST support `eddsa-jcs-2022`. Each list's `sequence` is exactly one greater than the last list the room signed, and the producer MUST NOT sign two different lists at one `sequence`.\n\n**Accepting.** A host MUST refuse a list unless: (1) `roomId` is the room it is delivered for; (2) `proof` verifies with a key of `roomId` listed for `assertionMethod` — a list signed by any other key, however valid the signature, is not the room's; (3) `sequence` is greater than that of the list it holds, or equal with an identical list (a repeat, answered as accepted and changing nothing); (4) it is **append-only** against the list it holds: every entry of the held list appears in it unchanged, unless that entry's `until` has passed. A list that lowers the sequence is a rollback and one that drops a live entry is a reinstatement nobody signed for, and both are refused; two different lists at one `sequence` is the room's key equivocating, and the host keeps the list it holds.\n\n**Applying.** A credential is revoked by an accepted list when any entry matches it (see `RevocationEntry`). An entry whose `until` has passed MAY be discarded by a host and omitted from later lists; no other entry is ever dropped.\n\n**Size.** A list is bounded at 4096 entries. A room that would exceed it uses a `room` entry, which withdraws everything issued before it and lets the room re-issue to those who remain.",
431
+ "properties": {
432
+ "roomId": {
433
+ "type": "string",
434
+ "minLength": 1,
435
+ "maxLength": 512,
436
+ "description": "The room whose credentials this list withdraws, exactly as on the wire. Signed, so a list cannot be replayed against another room."
437
+ },
438
+ "sequence": {
439
+ "type": "integer",
440
+ "minimum": 1,
441
+ "description": "The list's position in the room's sequence: exactly one greater than the last list the room signed. A host accepts only a list whose sequence is above the one it holds, which is what stops a host, a relayer or an attacker holding an old list from rolling the room's withdrawals back."
442
+ },
443
+ "issuedAt": {
444
+ "type": "string",
445
+ "format": "date-time",
446
+ "description": "When the room signed this list."
447
+ },
448
+ "entries": {
449
+ "type": "array",
450
+ "maxItems": 4096,
451
+ "items": {
452
+ "$ref": "#/$defs/RevocationEntry"
453
+ },
454
+ "description": "Every withdrawal still in force, in the order the room made them. Empty is valid: a room that has revoked nothing, or whose every entry has lapsed, can still state its sequence."
455
+ },
456
+ "proof": {
457
+ "type": "object",
458
+ "description": "The room's Data Integrity proof over every other member, made with a key the room's DID document lists for `assertionMethod`."
459
+ }
460
+ }
461
+ },
462
+ "RevocationEntry": {
463
+ "title": "RevocationEntry",
464
+ "description": "One withdrawal in a `RevocationList`, discriminated by `kind`.\n\n - `credential` withdraws one credential, named by its `id`. It matches the membership credential or any authority link whose `id` equals `credentialId`.\n - `subject` withdraws a party: every credential the room's chain gave them **before** `revokedAt`. It matches the membership credential or any authority link whose `credentialSubject` id **or** `issuer` is `subject` and whose `validFrom` is earlier than `revokedAt`. Matching the issuer as well as the subject withdraws what the party delegated before their removal, which no re-admission revives. A credential carrying no `validFrom` is treated as issued before every entry.\n - `room` withdraws every credential whose `validFrom` is earlier than `revokedAt`, whoever holds it. It is how a room resets access — after a compromise, or on a `private` room, where naming a party would disclose who was a member.\n\n**Keyed on time, so a party can come back.** A `subject` or `room` entry withdraws what was issued before it and nothing after, so a room that re-admits a removed party issues fresh credentials and they verify. A `credential` entry is permanent for that one credential, which nobody re-issues.\n\n**Tiers.** On a `private` room a host MUST refuse a list carrying a `credential` or `subject` entry: a presentation there withholds the credential and its subject, so such an entry is one the host cannot apply and a disclosure of who was in the room. Only `room` entries are permitted, and a host serving a `private` room MUST refuse any presentation for which it cannot establish that no credential in it has a `validFrom` earlier than the latest `room` entry's `revokedAt`.",
465
+ "oneOf": [
466
+ {
467
+ "$ref": "#/$defs/CredentialRevocation"
468
+ },
469
+ {
470
+ "$ref": "#/$defs/SubjectRevocation"
471
+ },
472
+ {
473
+ "$ref": "#/$defs/RoomRevocation"
474
+ }
475
+ ]
476
+ },
477
+ "RoomRevocation": {
478
+ "title": "RoomRevocation",
479
+ "type": "object",
480
+ "additionalProperties": false,
481
+ "required": [
482
+ "kind",
483
+ "revokedAt"
484
+ ],
485
+ "description": "Withdraws every credential whose `validFrom` is earlier than `revokedAt`, whoever holds it.",
486
+ "properties": {
487
+ "kind": {
488
+ "const": "room"
489
+ },
490
+ "revokedAt": {
491
+ "type": "string",
492
+ "format": "date-time",
493
+ "description": "When the room made this withdrawal."
494
+ },
495
+ "until": {
496
+ "type": "string",
497
+ "format": "date-time",
498
+ "description": "OPTIONAL. After this instant every credential the entry matches has expired anyway, so a host MAY discard the entry and the room MAY omit it from later lists. Absent means the entry is kept for as long as the room keeps a list."
499
+ }
500
+ }
501
+ },
502
+ "SubjectRevocation": {
503
+ "title": "SubjectRevocation",
504
+ "type": "object",
505
+ "additionalProperties": false,
506
+ "required": [
507
+ "kind",
508
+ "subject",
509
+ "revokedAt"
510
+ ],
511
+ "description": "Withdraws a party: every credential naming them as subject or issuer whose `validFrom` is earlier than `revokedAt`.",
512
+ "properties": {
513
+ "kind": {
514
+ "const": "subject"
515
+ },
516
+ "subject": {
517
+ "type": "string",
518
+ "pattern": "^did:",
519
+ "maxLength": 2048,
520
+ "description": "The party withdrawn. Never the room itself."
521
+ },
522
+ "revokedAt": {
523
+ "type": "string",
524
+ "format": "date-time",
525
+ "description": "When the room made this withdrawal."
526
+ },
527
+ "until": {
528
+ "type": "string",
529
+ "format": "date-time",
530
+ "description": "OPTIONAL. After this instant every credential the entry matches has expired anyway, so a host MAY discard the entry and the room MAY omit it from later lists. Absent means the entry is kept for as long as the room keeps a list."
531
+ }
532
+ }
533
+ },
534
+ "CredentialRevocation": {
535
+ "title": "CredentialRevocation",
536
+ "type": "object",
537
+ "additionalProperties": false,
538
+ "required": [
539
+ "kind",
540
+ "credentialId",
541
+ "revokedAt"
542
+ ],
543
+ "description": "Withdraws one credential — a membership credential or any authority link — by its `id`.",
544
+ "properties": {
545
+ "kind": {
546
+ "const": "credential"
547
+ },
548
+ "credentialId": {
549
+ "type": "string",
550
+ "minLength": 1,
551
+ "maxLength": 2048,
552
+ "description": "The `id` of the credential withdrawn, as `rooms/owner/issue-authority` and `rooms/owner/issue-membership` return it, or as an attenuated credential carries it."
553
+ },
554
+ "revokedAt": {
555
+ "type": "string",
556
+ "format": "date-time",
557
+ "description": "When the room made this withdrawal."
558
+ },
559
+ "until": {
560
+ "type": "string",
561
+ "format": "date-time",
562
+ "description": "OPTIONAL. After this instant every credential the entry matches has expired anyway, so a host MAY discard the entry and the room MAY omit it from later lists. Absent means the entry is kept for as long as the room keeps a list."
563
+ }
564
+ }
565
+ }
566
+ }
567
+ } as const;
568
+
569
+ /** As {@link PAYLOAD_SCHEMA}, for the success-response variant. */
570
+ export const RESPONSE_PAYLOAD_SCHEMA = {
571
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
572
+ "$ref": "#/$defs/Response",
573
+ "$defs": {
574
+ "Withdrawal": {
575
+ "title": "Withdrawal",
576
+ "description": "One withdrawal to add, discriminated by `kind` as a RevocationEntry is. It carries no `revokedAt`: the recipient stamps the time it signs, so that a subject or room entry withdraws exactly what the room had issued until then and nothing the caller dated.",
577
+ "oneOf": [
578
+ {
579
+ "$ref": "#/$defs/WithdrawCredential"
580
+ },
581
+ {
582
+ "$ref": "#/$defs/WithdrawSubject"
583
+ },
584
+ {
585
+ "$ref": "#/$defs/WithdrawRoom"
586
+ }
587
+ ]
588
+ },
589
+ "WithdrawCredential": {
590
+ "title": "WithdrawCredential",
591
+ "type": "object",
592
+ "additionalProperties": false,
593
+ "required": [
594
+ "kind",
595
+ "credentialId"
596
+ ],
597
+ "properties": {
598
+ "kind": {
599
+ "const": "credential"
600
+ },
601
+ "credentialId": {
602
+ "type": "string",
603
+ "minLength": 1,
604
+ "maxLength": 2048,
605
+ "description": "The `id` of the credential withdrawn."
606
+ },
607
+ "until": {
608
+ "type": "string",
609
+ "format": "date-time",
610
+ "description": "OPTIONAL. The credential's own `validUntil`, after which the entry can be dropped."
611
+ }
612
+ }
613
+ },
614
+ "WithdrawSubject": {
615
+ "title": "WithdrawSubject",
616
+ "type": "object",
617
+ "additionalProperties": false,
618
+ "required": [
619
+ "kind",
620
+ "subject"
621
+ ],
622
+ "properties": {
623
+ "kind": {
624
+ "const": "subject"
625
+ },
626
+ "subject": {
627
+ "type": "string",
628
+ "pattern": "^did:",
629
+ "maxLength": 2048,
630
+ "description": "The party withdrawn: every credential naming them as subject or issuer that the room's chain gave them before now. Never the room."
631
+ },
632
+ "until": {
633
+ "type": "string",
634
+ "format": "date-time",
635
+ "description": "OPTIONAL. When the last credential the room issued them expires, after which the entry can be dropped."
636
+ }
637
+ }
638
+ },
639
+ "WithdrawRoom": {
640
+ "title": "WithdrawRoom",
641
+ "type": "object",
642
+ "additionalProperties": false,
643
+ "required": [
644
+ "kind"
645
+ ],
646
+ "properties": {
647
+ "kind": {
648
+ "const": "room"
649
+ },
650
+ "until": {
651
+ "type": "string",
652
+ "format": "date-time",
653
+ "description": "OPTIONAL. When the last credential the room issued before now expires."
654
+ }
655
+ }
656
+ },
657
+ "Delivery": {
658
+ "title": "Delivery",
659
+ "type": "object",
660
+ "additionalProperties": false,
661
+ "required": [
662
+ "host",
663
+ "outcome"
664
+ ],
665
+ "description": "What one host did with the list.",
666
+ "properties": {
667
+ "host": {
668
+ "type": "string",
669
+ "pattern": "^did:",
670
+ "maxLength": 2048
671
+ },
672
+ "outcome": {
673
+ "type": "string",
674
+ "enum": [
675
+ "accepted",
676
+ "refused",
677
+ "unreachable"
678
+ ],
679
+ "description": "`accepted`: the host holds this list, or answered it as a repeat, and enforces it from `inForceAt`. `refused`: it answered and declined; its code is in `code`. `unreachable`: no answer, so the outcome is unknown — repeat the request with no `withdraw` to deliver again."
680
+ },
681
+ "head": {
682
+ "$ref": "#/$defs/RevocationHead",
683
+ "description": "The head the host answered with. Present when `accepted`."
684
+ },
685
+ "inForceAt": {
686
+ "type": "string",
687
+ "format": "date-time",
688
+ "description": "When the host began enforcing the list. Present when `accepted`."
689
+ },
690
+ "code": {
691
+ "type": "string",
692
+ "maxLength": 128,
693
+ "description": "The host's error code. Present when `refused`."
694
+ }
695
+ }
696
+ },
697
+ "Response": {
698
+ "$anchor": "response",
699
+ "title": "Rooms Owner Revoke — response payload",
700
+ "description": "Success response to rooms/owner/revoke. Type https://trusttasks.org/spec/rooms/owner/revoke/0.1#response. The list the recipient now holds for the room, and what each host did with it. A success says the list was signed and kept; only a delivery whose outcome is `accepted` says a host enforces it.",
701
+ "type": "object",
702
+ "additionalProperties": false,
703
+ "required": [
704
+ "roomId",
705
+ "list",
706
+ "head",
707
+ "deliveries"
708
+ ],
709
+ "properties": {
710
+ "roomId": {
711
+ "type": "string",
712
+ "minLength": 1,
713
+ "maxLength": 512
714
+ },
715
+ "list": {
716
+ "$ref": "#/$defs/RevocationList",
717
+ "description": "The room's current list, as signed. Returned so the owner holds a copy that does not depend on the recipient."
718
+ },
719
+ "head": {
720
+ "$ref": "#/$defs/RevocationHead"
721
+ },
722
+ "deliveries": {
723
+ "type": "array",
724
+ "minItems": 1,
725
+ "maxItems": 8,
726
+ "items": {
727
+ "$ref": "#/$defs/Delivery"
728
+ },
729
+ "description": "One per host in the request, in its order."
730
+ },
731
+ "ext": {
732
+ "$ref": "#/$defs/Ext"
733
+ }
734
+ }
735
+ },
736
+ "Ext": {
737
+ "title": "Ext",
738
+ "description": "Vendor-namespaced extension object per SPEC.md §4.5.1. Each immediate key MUST be a reverse-DNS namespace; structure under each namespace is opaque to the framework.",
739
+ "type": "object",
740
+ "minProperties": 1,
741
+ "additionalProperties": true,
742
+ "propertyNames": {
743
+ "pattern": "^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)+$"
744
+ }
745
+ },
746
+ "RevocationHead": {
747
+ "title": "RevocationHead",
748
+ "type": "object",
749
+ "additionalProperties": false,
750
+ "required": [
751
+ "sequence",
752
+ "digest"
753
+ ],
754
+ "description": "Which `RevocationList` a party holds, without its entries: comparable between the room's key holder and a host, and between two hosts, without disclosing whom the room withdrew.",
755
+ "properties": {
756
+ "sequence": {
757
+ "type": "integer",
758
+ "minimum": 1,
759
+ "description": "The list's `sequence`."
760
+ },
761
+ "digest": {
762
+ "$ref": "#/$defs/DigestMultibase",
763
+ "description": "SHA-256 multihash of the list's RFC 8785 (JCS) canonicalization, `proof` included. Two parties holding one sequence with different digests have been given two lists the room signed at one sequence."
764
+ }
765
+ }
766
+ },
767
+ "DigestMultibase": {
768
+ "title": "DigestMultibase",
769
+ "description": "A cryptographic digest as a multibase-encoded multihash — the encoding the W3C Verifiable Credentials Data Model 2.0 defines for `digestMultibase`, and the one `did:webvh` uses for its SCID and entry hashes.\n\nMultihash carries the hash algorithm in-band, so the value is self-describing and the wire format survives an algorithm change without a schema revision; multibase does the same for the base encoding, so a verifier never infers base58 from base64url by context. A bare hex string or a `sha-256:`-style prefix hard-codes one algorithm into the wire contract and is non-conforming here.\n\nThis definition constrains the *encoding only*. What the digest is computed over is stated by each referencing field, because it differs legitimately: a digest over a JSON document is taken over its RFC 8785 (JCS) canonicalization, while a digest over an opaque artifact is taken over its bytes. A field whose input is a JSON document and which does not name a canonicalization is not reproducible.\n\nRestricted to the two multibase headers W3C Controlled Identifiers 1.0 §2.4 normatively requires — `z` (base58btc) and `u` (base64url-no-pad). CID permits others but states that \"interoperability is not guaranteed between implementations using such values\", and a registry whose purpose is interoperability should not mint digests a conforming verifier may be unable to read. The alphabets are enforced rather than assumed: base58btc excludes 0, O, I and l, and an earlier permissive pattern let three published examples carry digests that were not valid base58 at all. base58btc is RECOMMENDED, for consistency with `did:key` and `did:webvh`.",
770
+ "type": "string",
771
+ "minLength": 16,
772
+ "pattern": "^(z[1-9A-HJ-NP-Za-km-z]+|u[A-Za-z0-9_-]+)$",
773
+ "examples": [
774
+ "zQmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR"
775
+ ]
776
+ },
777
+ "RevocationList": {
778
+ "title": "RevocationList",
779
+ "type": "object",
780
+ "additionalProperties": false,
781
+ "required": [
782
+ "roomId",
783
+ "sequence",
784
+ "issuedAt",
785
+ "entries",
786
+ "proof"
787
+ ],
788
+ "description": "The room's own statement of which credentials it has withdrawn before they expire — signed by the room, cumulative, and numbered, so that it means the same thing at every host it is delivered to.\n\n**Why the room signs it, and why it is cumulative.** A host authorizes from credentials the room issued and keeps no roster; a withdrawal kept only as a host's own state would make the room unmovable and the host part of the membership. A list the room signed is room state: it moves with the room, any host it is delivered to reaches the same decision, and nothing a host invents can be mistaken for it. It is cumulative — every list carries every entry still in force — so a host holding any one list holds the room's whole withdrawal state, and a host that missed a list loses nothing once it receives a later one.\n\n**Producing.** The room's key holder builds the object without `proof` and signs it with a W3C Data Integrity proof whose `verificationMethod` is a key the room's DID document lists for `assertionMethod` and whose `proofPurpose` is `assertionMethod`. A producer MUST support `eddsa-jcs-2022`. Each list's `sequence` is exactly one greater than the last list the room signed, and the producer MUST NOT sign two different lists at one `sequence`.\n\n**Accepting.** A host MUST refuse a list unless: (1) `roomId` is the room it is delivered for; (2) `proof` verifies with a key of `roomId` listed for `assertionMethod` — a list signed by any other key, however valid the signature, is not the room's; (3) `sequence` is greater than that of the list it holds, or equal with an identical list (a repeat, answered as accepted and changing nothing); (4) it is **append-only** against the list it holds: every entry of the held list appears in it unchanged, unless that entry's `until` has passed. A list that lowers the sequence is a rollback and one that drops a live entry is a reinstatement nobody signed for, and both are refused; two different lists at one `sequence` is the room's key equivocating, and the host keeps the list it holds.\n\n**Applying.** A credential is revoked by an accepted list when any entry matches it (see `RevocationEntry`). An entry whose `until` has passed MAY be discarded by a host and omitted from later lists; no other entry is ever dropped.\n\n**Size.** A list is bounded at 4096 entries. A room that would exceed it uses a `room` entry, which withdraws everything issued before it and lets the room re-issue to those who remain.",
789
+ "properties": {
790
+ "roomId": {
791
+ "type": "string",
792
+ "minLength": 1,
793
+ "maxLength": 512,
794
+ "description": "The room whose credentials this list withdraws, exactly as on the wire. Signed, so a list cannot be replayed against another room."
795
+ },
796
+ "sequence": {
797
+ "type": "integer",
798
+ "minimum": 1,
799
+ "description": "The list's position in the room's sequence: exactly one greater than the last list the room signed. A host accepts only a list whose sequence is above the one it holds, which is what stops a host, a relayer or an attacker holding an old list from rolling the room's withdrawals back."
800
+ },
801
+ "issuedAt": {
802
+ "type": "string",
803
+ "format": "date-time",
804
+ "description": "When the room signed this list."
805
+ },
806
+ "entries": {
807
+ "type": "array",
808
+ "maxItems": 4096,
809
+ "items": {
810
+ "$ref": "#/$defs/RevocationEntry"
811
+ },
812
+ "description": "Every withdrawal still in force, in the order the room made them. Empty is valid: a room that has revoked nothing, or whose every entry has lapsed, can still state its sequence."
813
+ },
814
+ "proof": {
815
+ "type": "object",
816
+ "description": "The room's Data Integrity proof over every other member, made with a key the room's DID document lists for `assertionMethod`."
817
+ }
818
+ }
819
+ },
820
+ "RevocationEntry": {
821
+ "title": "RevocationEntry",
822
+ "description": "One withdrawal in a `RevocationList`, discriminated by `kind`.\n\n - `credential` withdraws one credential, named by its `id`. It matches the membership credential or any authority link whose `id` equals `credentialId`.\n - `subject` withdraws a party: every credential the room's chain gave them **before** `revokedAt`. It matches the membership credential or any authority link whose `credentialSubject` id **or** `issuer` is `subject` and whose `validFrom` is earlier than `revokedAt`. Matching the issuer as well as the subject withdraws what the party delegated before their removal, which no re-admission revives. A credential carrying no `validFrom` is treated as issued before every entry.\n - `room` withdraws every credential whose `validFrom` is earlier than `revokedAt`, whoever holds it. It is how a room resets access — after a compromise, or on a `private` room, where naming a party would disclose who was a member.\n\n**Keyed on time, so a party can come back.** A `subject` or `room` entry withdraws what was issued before it and nothing after, so a room that re-admits a removed party issues fresh credentials and they verify. A `credential` entry is permanent for that one credential, which nobody re-issues.\n\n**Tiers.** On a `private` room a host MUST refuse a list carrying a `credential` or `subject` entry: a presentation there withholds the credential and its subject, so such an entry is one the host cannot apply and a disclosure of who was in the room. Only `room` entries are permitted, and a host serving a `private` room MUST refuse any presentation for which it cannot establish that no credential in it has a `validFrom` earlier than the latest `room` entry's `revokedAt`.",
823
+ "oneOf": [
824
+ {
825
+ "$ref": "#/$defs/CredentialRevocation"
826
+ },
827
+ {
828
+ "$ref": "#/$defs/SubjectRevocation"
829
+ },
830
+ {
831
+ "$ref": "#/$defs/RoomRevocation"
832
+ }
833
+ ]
834
+ },
835
+ "RoomRevocation": {
836
+ "title": "RoomRevocation",
837
+ "type": "object",
838
+ "additionalProperties": false,
839
+ "required": [
840
+ "kind",
841
+ "revokedAt"
842
+ ],
843
+ "description": "Withdraws every credential whose `validFrom` is earlier than `revokedAt`, whoever holds it.",
844
+ "properties": {
845
+ "kind": {
846
+ "const": "room"
847
+ },
848
+ "revokedAt": {
849
+ "type": "string",
850
+ "format": "date-time",
851
+ "description": "When the room made this withdrawal."
852
+ },
853
+ "until": {
854
+ "type": "string",
855
+ "format": "date-time",
856
+ "description": "OPTIONAL. After this instant every credential the entry matches has expired anyway, so a host MAY discard the entry and the room MAY omit it from later lists. Absent means the entry is kept for as long as the room keeps a list."
857
+ }
858
+ }
859
+ },
860
+ "SubjectRevocation": {
861
+ "title": "SubjectRevocation",
862
+ "type": "object",
863
+ "additionalProperties": false,
864
+ "required": [
865
+ "kind",
866
+ "subject",
867
+ "revokedAt"
868
+ ],
869
+ "description": "Withdraws a party: every credential naming them as subject or issuer whose `validFrom` is earlier than `revokedAt`.",
870
+ "properties": {
871
+ "kind": {
872
+ "const": "subject"
873
+ },
874
+ "subject": {
875
+ "type": "string",
876
+ "pattern": "^did:",
877
+ "maxLength": 2048,
878
+ "description": "The party withdrawn. Never the room itself."
879
+ },
880
+ "revokedAt": {
881
+ "type": "string",
882
+ "format": "date-time",
883
+ "description": "When the room made this withdrawal."
884
+ },
885
+ "until": {
886
+ "type": "string",
887
+ "format": "date-time",
888
+ "description": "OPTIONAL. After this instant every credential the entry matches has expired anyway, so a host MAY discard the entry and the room MAY omit it from later lists. Absent means the entry is kept for as long as the room keeps a list."
889
+ }
890
+ }
891
+ },
892
+ "CredentialRevocation": {
893
+ "title": "CredentialRevocation",
894
+ "type": "object",
895
+ "additionalProperties": false,
896
+ "required": [
897
+ "kind",
898
+ "credentialId",
899
+ "revokedAt"
900
+ ],
901
+ "description": "Withdraws one credential — a membership credential or any authority link — by its `id`.",
902
+ "properties": {
903
+ "kind": {
904
+ "const": "credential"
905
+ },
906
+ "credentialId": {
907
+ "type": "string",
908
+ "minLength": 1,
909
+ "maxLength": 2048,
910
+ "description": "The `id` of the credential withdrawn, as `rooms/owner/issue-authority` and `rooms/owner/issue-membership` return it, or as an attenuated credential carries it."
911
+ },
912
+ "revokedAt": {
913
+ "type": "string",
914
+ "format": "date-time",
915
+ "description": "When the room made this withdrawal."
916
+ },
917
+ "until": {
918
+ "type": "string",
919
+ "format": "date-time",
920
+ "description": "OPTIONAL. After this instant every credential the entry matches has expired anyway, so a host MAY discard the entry and the room MAY omit it from later lists. Absent means the entry is kept for as long as the room keeps a list."
921
+ }
922
+ }
923
+ }
924
+ }
925
+ } as const;
926
+
927
+ /**
928
+ * SPEC.md §7.2 policy for the request variant, from this specification's
929
+ * front matter. Pass to `consumeInbound` — items 5b, 7 and 8 are
930
+ * per-specification and cannot be derived from the document alone, and
931
+ * item 2 needs the schema this carries.
932
+ */
933
+ export const SPEC = {
934
+ typeUri: TYPE_URI,
935
+ isBearer: false,
936
+ isProofRequired: true,
937
+ isRecipientRequired: true,
938
+ isIssuedAtRequired: true,
939
+ payloadSchema: PAYLOAD_SCHEMA,
940
+ } as const;
941
+
942
+ /**
943
+ * SPEC.md §7.2 policy for the success-response variant. `isRecipientRequired`
944
+ * tracks the *issuer* party's requirement because a response swaps the
945
+ * parties (§7.3 item 5).
946
+ */
947
+ export const RESPONSE_SPEC = {
948
+ typeUri: RESPONSE_TYPE_URI,
949
+ isBearer: false,
950
+ isProofRequired: true,
951
+ isRecipientRequired: true,
952
+ isIssuedAtRequired: true,
953
+ payloadSchema: RESPONSE_PAYLOAD_SCHEMA,
954
+ } as const;