@forgesworn/fold-kit 0.8.0 → 0.9.0
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.
- package/README.md +10 -0
- package/dist/epoch.d.ts +8 -0
- package/dist/epoch.js +5 -0
- package/dist/invitation.d.ts +10 -2
- package/dist/invitation.js +9 -4
- package/dist/member-epoch.d.ts +2 -0
- package/dist/member-epoch.js +2 -0
- package/dist/persistent-invitation.d.ts +7 -0
- package/dist/persistent-invitation.js +11 -1
- package/llms.txt +1 -0
- package/package.json +3 -1
- package/vectors/destruct-vectors.json +675 -0
package/README.md
CHANGED
|
@@ -126,6 +126,16 @@ the rest).
|
|
|
126
126
|
`requestPersistentRoomAdmission` keeps the relays of the newest signed
|
|
127
127
|
copy that names any. `isInvitationRelays`, `requireInvitationRelays` and
|
|
128
128
|
`MAX_INVITATION_RELAYS` are the rule
|
|
129
|
+
- Self-destructing rooms (`docs/room-destruct.md`): pass `destruct: true`
|
|
130
|
+
and the encrypted body carries it after `ends` (no end needed: the room
|
|
131
|
+
then self-destructs when its authority closes it). The decoder returns
|
|
132
|
+
`destruct: true` and refuses the envelope on any other value;
|
|
133
|
+
`requestPersistentRoomAdmission` keeps it if any signed copy says it.
|
|
134
|
+
`encodeInvitationRetirement({ ended: true, destruct: true })` and
|
|
135
|
+
`encodeRekeyEvent({ closed: true, destruct: true })` carry it when the
|
|
136
|
+
room ends early, read back by `decodeInvitationRetirementNotice`,
|
|
137
|
+
`RekeyNotice.destruct` and `RekeyEvidence.destruct`. Vectors:
|
|
138
|
+
`vectors/destruct-vectors.json`
|
|
129
139
|
- `withExpiration`, `isRoomEnds`, `requireRoomEnds`, `MAX_ROOM_ENDS_SECONDS` -
|
|
130
140
|
the conference-room expiration rule: add the end as an `expiration` tag,
|
|
131
141
|
keep an earlier one, lower a later one. `encodeInvitationRetirement` takes
|
package/dist/epoch.d.ts
CHANGED
|
@@ -111,6 +111,10 @@ export interface EncodeRekeyOptions {
|
|
|
111
111
|
/** True when the room is being closed: nobody is kept, and the event
|
|
112
112
|
* says so rather than leaving everybody to wonder. */
|
|
113
113
|
closed?: boolean;
|
|
114
|
+
/** The room being closed self-destructs: every device deletes what it
|
|
115
|
+
* wrote and forgets the room. Inside the encrypted body. Refused
|
|
116
|
+
* without `closed`. Omitted, the event is byte-identical to before. */
|
|
117
|
+
destruct?: boolean;
|
|
114
118
|
/** Mark this as a scheduled turn of the key rather than a removal, so
|
|
115
119
|
* clients can let it pass quietly. Refused with a removal or a close: a
|
|
116
120
|
* rekey that removes somebody is never quiet. Omitted, the event is
|
|
@@ -144,6 +148,10 @@ export interface RekeyNotice {
|
|
|
144
148
|
removed: string[];
|
|
145
149
|
by?: string;
|
|
146
150
|
closed: boolean;
|
|
151
|
+
/** True when the closed room self-destructs. Absent unless `closed`:
|
|
152
|
+
* beside an open room the flag is not believed, and the rekey is read
|
|
153
|
+
* as if it were not there. */
|
|
154
|
+
destruct?: true;
|
|
147
155
|
/** True for a scheduled turn of the key: nobody removed, the room still
|
|
148
156
|
* open. What lets a client move on without saying so. Absent when the
|
|
149
157
|
* body contradicts itself, so a removal is always announced. */
|
package/dist/epoch.js
CHANGED
|
@@ -145,6 +145,8 @@ export function encodeRekeyEvent(opts) {
|
|
|
145
145
|
const removed = [...new Set(opts.removed.map((p) => requireHex32(p, 'removed participant')))].sort();
|
|
146
146
|
if (opts.scheduled && (removed.length > 0 || opts.closed))
|
|
147
147
|
throw new Error('a scheduled rekey removes nobody and does not close the room');
|
|
148
|
+
if (opts.destruct && !opts.closed)
|
|
149
|
+
throw new Error('only a closing rekey can self-destruct the room');
|
|
148
150
|
const keys = {};
|
|
149
151
|
const sealed = { v: 1, secret: base64urlnopad.encode(opts.next.secret) };
|
|
150
152
|
const plaintext = JSON.stringify(sealed);
|
|
@@ -159,6 +161,7 @@ export function encodeRekeyEvent(opts) {
|
|
|
159
161
|
removed,
|
|
160
162
|
...(opts.by !== undefined ? { by: requireHex32(opts.by, 'admin') } : {}),
|
|
161
163
|
...(opts.closed ? { closed: true } : {}),
|
|
164
|
+
...(opts.destruct ? { destruct: true } : {}),
|
|
162
165
|
...(opts.scheduled ? { scheduled: true } : {}),
|
|
163
166
|
...(opts.commit ? { commit: epochCommitment(roomId, epoch, opts.next.secret) } : {}),
|
|
164
167
|
...(opts.members !== undefined ? { members: memberListOf(opts.members, removed) } : {}),
|
|
@@ -226,6 +229,8 @@ export function decodeRekeyEvent(event, opts) {
|
|
|
226
229
|
};
|
|
227
230
|
if (typeof body.by === 'string' && HEX64.test(body.by))
|
|
228
231
|
notice.by = normaliseHex(body.by);
|
|
232
|
+
if (body.destruct === true && notice.closed)
|
|
233
|
+
notice.destruct = true;
|
|
229
234
|
if (body.scheduled === true && notice.removed.length === 0 && !notice.closed)
|
|
230
235
|
notice.scheduled = true;
|
|
231
236
|
const members = readMemberList(body.members);
|
package/dist/invitation.d.ts
CHANGED
|
@@ -165,6 +165,12 @@ export interface EncodeInvitationRetirementOptions {
|
|
|
165
165
|
/** The room itself was ended, not just this link replaced. Additive: a
|
|
166
166
|
* reader that predates it still sees an ordinary retirement. */
|
|
167
167
|
ended?: boolean;
|
|
168
|
+
/** The ended room self-destructs: every device deletes what it wrote and
|
|
169
|
+
* forgets the room. Only beside `ended`, else it throws. Unlike the
|
|
170
|
+
* invitation's own flag this content is not encrypted: it says no more
|
|
171
|
+
* than `ended` does about a link nobody outside the room can name.
|
|
172
|
+
* Omitted or false, the event is byte-identical to 0.8.0's. */
|
|
173
|
+
destruct?: boolean;
|
|
168
174
|
/** A conference room's end, in unix seconds: the tombstone carries the
|
|
169
175
|
* same NIP-40 expiration as the invitation it retires, and lapses with it. */
|
|
170
176
|
endsAt?: number;
|
|
@@ -176,10 +182,12 @@ export declare function encodeInvitationRetirement(opts: EncodeInvitationRetirem
|
|
|
176
182
|
/** A valid tombstone never expires: invitation ids are random and unique,
|
|
177
183
|
* and a retired bearer must not become usable again after a timeout. */
|
|
178
184
|
export declare function decodeInvitationRetirement(event: Event, invitation: RoomInvitation): boolean;
|
|
179
|
-
/** A valid retirement,
|
|
180
|
-
*
|
|
185
|
+
/** A valid retirement, whether it says the room was ended, and whether the
|
|
186
|
+
* ended room self-destructs (`destruct`, believed only beside `ended`).
|
|
187
|
+
* Undefined for anything that is not a valid retirement of this invitation. */
|
|
181
188
|
export declare function decodeInvitationRetirementNotice(event: Event, invitation: RoomInvitation): {
|
|
182
189
|
ended: boolean;
|
|
190
|
+
destruct?: true;
|
|
183
191
|
} | undefined;
|
|
184
192
|
/** The error a joiner rejects with on a retirement. */
|
|
185
193
|
export declare function retirementError(notice: {
|
package/dist/invitation.js
CHANGED
|
@@ -279,11 +279,13 @@ export function encodeInvitationRetirement(opts) {
|
|
|
279
279
|
if (!hexEquals(getPublicKey(opts.inviterSk), opts.invitation.inviter)) {
|
|
280
280
|
throw new Error('only the root inviter can retire an invitation');
|
|
281
281
|
}
|
|
282
|
+
if (opts.destruct && !opts.ended)
|
|
283
|
+
throw new Error('only an ended room can self-destruct');
|
|
282
284
|
return finalizeEvent({
|
|
283
285
|
kind: KINDS.INVITATION_RETIREMENT,
|
|
284
286
|
created_at: opts.now,
|
|
285
287
|
tags: withExpiration([['d', deriveInvitationId(opts.invitation)]], opts.endsAt),
|
|
286
|
-
content: JSON.stringify(opts.ended ? { v: 1, ended: true } : { v: 1 }),
|
|
288
|
+
content: JSON.stringify(opts.ended ? (opts.destruct ? { v: 1, ended: true, destruct: true } : { v: 1, ended: true }) : { v: 1 }),
|
|
287
289
|
}, opts.inviterSk);
|
|
288
290
|
}
|
|
289
291
|
/** A valid tombstone never expires: invitation ids are random and unique,
|
|
@@ -291,8 +293,9 @@ export function encodeInvitationRetirement(opts) {
|
|
|
291
293
|
export function decodeInvitationRetirement(event, invitation) {
|
|
292
294
|
return decodeInvitationRetirementNotice(event, invitation) !== undefined;
|
|
293
295
|
}
|
|
294
|
-
/** A valid retirement,
|
|
295
|
-
*
|
|
296
|
+
/** A valid retirement, whether it says the room was ended, and whether the
|
|
297
|
+
* ended room self-destructs (`destruct`, believed only beside `ended`).
|
|
298
|
+
* Undefined for anything that is not a valid retirement of this invitation. */
|
|
296
299
|
export function decodeInvitationRetirementNotice(event, invitation) {
|
|
297
300
|
try {
|
|
298
301
|
if (event.kind !== KINDS.INVITATION_RETIREMENT)
|
|
@@ -304,7 +307,9 @@ export function decodeInvitationRetirementNotice(event, invitation) {
|
|
|
304
307
|
if (event.tags.find((tag) => tag[0] === 'd')?.[1] !== deriveInvitationId(invitation))
|
|
305
308
|
return undefined;
|
|
306
309
|
const body = JSON.parse(event.content);
|
|
307
|
-
|
|
310
|
+
if (body.v !== 1)
|
|
311
|
+
return undefined;
|
|
312
|
+
return body.ended === true && body.destruct === true ? { ended: true, destruct: true } : { ended: body.ended === true };
|
|
308
313
|
}
|
|
309
314
|
catch {
|
|
310
315
|
return undefined;
|
package/dist/member-epoch.d.ts
CHANGED
|
@@ -59,6 +59,8 @@ export interface RekeyEvidence {
|
|
|
59
59
|
epoch: number;
|
|
60
60
|
removed: string[];
|
|
61
61
|
closed: boolean;
|
|
62
|
+
/** The closed room self-destructs: see `RekeyNotice.destruct`. */
|
|
63
|
+
destruct?: true;
|
|
62
64
|
/** A scheduled turn of the key: see `RekeyNotice.scheduled`. */
|
|
63
65
|
scheduled?: true;
|
|
64
66
|
/** The epoch commitment, when the authority wrote one. */
|
package/dist/member-epoch.js
CHANGED
|
@@ -117,6 +117,8 @@ export function readRekeyEvidence(event, opts) {
|
|
|
117
117
|
removed: [...new Set(body.removed.map(normaliseHex))].sort(),
|
|
118
118
|
closed: body.closed === true,
|
|
119
119
|
};
|
|
120
|
+
if (body.destruct === true && evidence.closed)
|
|
121
|
+
evidence.destruct = true;
|
|
120
122
|
if (body.scheduled === true && evidence.removed.length === 0 && !evidence.closed)
|
|
121
123
|
evidence.scheduled = true;
|
|
122
124
|
if (typeof body.commit === 'string' && HEX64.test(body.commit))
|
|
@@ -13,6 +13,9 @@ export interface PersistentRoomAdmission {
|
|
|
13
13
|
/** The room's own relays, as its inviter signed them: every member's pool
|
|
14
14
|
* includes them. Absent from an invitation written before 0.4.0. */
|
|
15
15
|
relays?: string[];
|
|
16
|
+
/** The room self-destructs: when it ends, every device deletes what it
|
|
17
|
+
* wrote and forgets the room. Absent for a room that simply ends. */
|
|
18
|
+
destruct?: true;
|
|
16
19
|
}
|
|
17
20
|
/** Publish once before sharing. The link plus this envelope is a durable
|
|
18
21
|
* bearer capability: anybody holding both can learn epoch 0. Retirement
|
|
@@ -30,6 +33,10 @@ export declare function encodePersistentInvitation(opts: {
|
|
|
30
33
|
* form (see `isInvitationRelays`), else it throws. Omitted, the body is
|
|
31
34
|
* byte-identical to 0.3.0's. */
|
|
32
35
|
relays?: readonly string[];
|
|
36
|
+
/** The room self-destructs when it ends, by its time or by its authority
|
|
37
|
+
* closing it. Written inside the encrypted body only, never as a tag.
|
|
38
|
+
* Omitted or false, the event is byte-identical to 0.8.0's. */
|
|
39
|
+
destruct?: boolean;
|
|
33
40
|
}): Event;
|
|
34
41
|
export declare function decodePersistentInvitation(event: Event, invitation: RoomInvitation): PersistentRoomAdmission | null;
|
|
35
42
|
/** Fetch the signed envelope and retirement in ONE stored-event query.
|
|
@@ -30,7 +30,7 @@ export function encodePersistentInvitation(opts) {
|
|
|
30
30
|
created_at: opts.now,
|
|
31
31
|
tags: ends === undefined ? [['d', deriveInvitationId(opts.invitation)]] : [['d', deriveInvitationId(opts.invitation)], ['expiration', String(ends)]],
|
|
32
32
|
content: nip44.v2.encrypt(JSON.stringify({
|
|
33
|
-
v: 3, room, secret: base64urlnopad.encode(opts.roomSecret), ...(ends === undefined ? {} : { ends }), ...(relays === undefined ? {} : { relays }),
|
|
33
|
+
v: 3, room, secret: base64urlnopad.encode(opts.roomSecret), ...(ends === undefined ? {} : { ends }), ...(opts.destruct ? { destruct: true } : {}), ...(relays === undefined ? {} : { relays }),
|
|
34
34
|
}), welcomeKey(opts.invitation)),
|
|
35
35
|
}, opts.inviterSk);
|
|
36
36
|
}
|
|
@@ -62,9 +62,15 @@ export function decodePersistentInvitation(event, invitation) {
|
|
|
62
62
|
// would write; a malformed one refuses the envelope rather than half of it.
|
|
63
63
|
if (body.relays !== undefined && !isInvitationRelays(body.relays))
|
|
64
64
|
return null;
|
|
65
|
+
// Self-destruct is `true` or absent; anything else is a malformed
|
|
66
|
+
// envelope, refused as a malformed end is.
|
|
67
|
+
if (body.destruct !== undefined && body.destruct !== true)
|
|
68
|
+
return null;
|
|
65
69
|
const admission = ends === undefined ? { secret, persistent: true, epoch: 0 } : { secret, persistent: true, epoch: 0, endsAt: ends };
|
|
66
70
|
if (body.relays !== undefined)
|
|
67
71
|
admission.relays = [...body.relays];
|
|
72
|
+
if (body.destruct === true)
|
|
73
|
+
admission.destruct = true;
|
|
68
74
|
return admission;
|
|
69
75
|
}
|
|
70
76
|
catch {
|
|
@@ -119,6 +125,10 @@ export function requestPersistentRoomAdmission(opts) {
|
|
|
119
125
|
// end stands, so a stale copy can never keep a room open longer.
|
|
120
126
|
if (admission?.endsAt !== undefined && (decoded.endsAt === undefined || decoded.endsAt > admission.endsAt))
|
|
121
127
|
decoded.endsAt = admission.endsAt;
|
|
128
|
+
// Two signed copies that disagree on self-destruct: it sticks, for
|
|
129
|
+
// the same reason, so a stale copy can never keep a room's content.
|
|
130
|
+
if (admission?.destruct)
|
|
131
|
+
decoded.destruct = true;
|
|
122
132
|
// Two signed copies that disagree on the room's relays: the newest
|
|
123
133
|
// copy that names any stands. A copy naming none (an older writer)
|
|
124
134
|
// says nothing about them, and on equal timestamps the first heard stays.
|
package/llms.txt
CHANGED
|
@@ -68,6 +68,7 @@ Not yet published to npm under this API. Until it is, pin an immutable Git commi
|
|
|
68
68
|
- `requestPersistentRoomAdmission(opts)` - joins from stored admission alone, no live desk needed
|
|
69
69
|
- Conference rooms: `encodePersistentInvitation({ ..., endsAt })` puts `ends` in the body and `['expiration', String(endsAt)]` on the 1463; `decodePersistentInvitation` returns `endsAt` and is null when an `expiration` tag disagrees with the body; `encodeInvitationRetirement({ ..., endsAt })` tags the 1461 the same way
|
|
70
70
|
- Room relays: `encodePersistentInvitation({ ..., relays })` puts the room's own relays (1-8 distinct canonical `wss://host/` URLs, else it throws) in the body after `ends`; the decoder returns `relays` and is null on a malformed list; `requestPersistentRoomAdmission` keeps the newest signed copy's list (a copy without one says nothing); `isInvitationRelays`, `requireInvitationRelays`, `MAX_INVITATION_RELAYS` (8)
|
|
71
|
+
- Self-destructing rooms (see `docs/room-destruct.md`): `encodePersistentInvitation({ ..., destruct: true })` puts `"destruct": true` in the encrypted body after `ends` (valid without `ends`), never a tag; `decodePersistentInvitation` returns `destruct: true` and is null when the field is present and not `true`; `requestPersistentRoomAdmission` keeps `destruct` if any valid copy carries it (sticky, like the earliest `ends`). `encodeInvitationRetirement({ ..., ended: true, destruct: true })` writes `{"v":1,"ended":true,"destruct":true}` (plain JSON, like `ended`) and throws on `destruct` without `ended`; `decodeInvitationRetirementNotice` returns `{ ended, destruct?: true }`, believing `destruct` only beside `ended`. `encodeRekeyEvent({ ..., closed: true, destruct: true })` writes it in the encrypted body after `closed` and throws without `closed`; `RekeyNotice.destruct` / `RekeyEvidence.destruct` are set only on a closing body, and a flag on an open rekey is dropped, not refused. Without the flag every event is byte-identical to 0.8.0, and a 0.8.0 reader ignores it
|
|
71
72
|
- `withExpiration(tags, expiresAt?)` - NIP-40 rule for a room that ends: add the tag, keep an earlier one, lower a later one; `isRoomEnds`, `requireRoomEnds(endsAt, now)`, `MAX_ROOM_ENDS_SECONDS` (30 days)
|
|
72
73
|
- Epoch encoders (`encodeRekeyEvent`, `encodeEpochRequest`, `encodeEpochGrant`) and `hostRoomEpoch` / `requestRoomEpoch` take `expiresAt?` for a conference room
|
|
73
74
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forgesworn/fold-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Circle primitives for private Nostr groups nobody operates: epoch keys, link invites, removal by rekey, device credentials.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"vectors/member-epoch-vectors.json",
|
|
24
24
|
"vectors/seal-vectors.json",
|
|
25
25
|
"vectors/schedule-vectors.json",
|
|
26
|
+
"vectors/destruct-vectors.json",
|
|
26
27
|
"LICENSE",
|
|
27
28
|
"README.md",
|
|
28
29
|
"llms.txt"
|
|
@@ -37,6 +38,7 @@
|
|
|
37
38
|
"generate-member-epoch": "node scripts/generate-member-epoch.mjs",
|
|
38
39
|
"generate-seal": "node scripts/generate-seal.mjs",
|
|
39
40
|
"generate-schedule": "node scripts/generate-schedule.mjs",
|
|
41
|
+
"generate-destruct": "node scripts/generate-destruct.mjs",
|
|
40
42
|
"bundle-check": "node scripts/bundle-check.mjs",
|
|
41
43
|
"tarball-smoke": "node scripts/tarball-smoke.mjs",
|
|
42
44
|
"vectors": "vitest run vectors/",
|
|
@@ -0,0 +1,675 @@
|
|
|
1
|
+
{
|
|
2
|
+
"protocolVersion": "kithmoot/v1",
|
|
3
|
+
"generatedBy": "scripts/generate-destruct.mjs (forgesworn/fold-kit)",
|
|
4
|
+
"nostrToolsVersion": "2.25.0",
|
|
5
|
+
"groups": {
|
|
6
|
+
"destruct": [
|
|
7
|
+
{
|
|
8
|
+
"name": "destruct-invitation",
|
|
9
|
+
"kind": "positive",
|
|
10
|
+
"note": "A kind-1463 group invitation for a conference room that self-destructs: `\"destruct\": true` inside the encrypted body, after `ends` and before `relays` (body order v, room, secret, ends, destruct, relays), and never as a tag, so a relay cannot tell it from any other invitation. A reader accepts the flag only as `true` (see `destruct-invitation-malformed`) and reports it as `destruct: true` on the admission. `randomHex`: the body nonce, the aux-rand. `unflagged` is the same invitation with the same draws and no flag, which is every invitation before 0.9.0: its body is `bodyJson` without `\"destruct\":true,`. `oldReader` is what a 0.8.0 reader makes of the flagged event: the same admission without `destruct`, so an old client joins and ends the room the old way.",
|
|
11
|
+
"input": {
|
|
12
|
+
"invitation": {
|
|
13
|
+
"bearerHex": "63da81a93ddf0a90ae34ed2b24bb91e664383e117bcacec5cc05e0da5d3d2612",
|
|
14
|
+
"inviter": "66df4b7febed3972515d9f663fe00a8ef9b2c69fbcb6bee3f5587b5d0b96605e",
|
|
15
|
+
"persistent": true
|
|
16
|
+
},
|
|
17
|
+
"inviterSkHex": "a090036fcabc0a442fc1eaa5afc5c7ddda6f95c6bf8fe1f7b3b69589e621d643",
|
|
18
|
+
"roomSecretHex": "76da765650f119b64a4c908c490992d125626bd272c90b8b3362010892356e28",
|
|
19
|
+
"roomId": "629cb9accf2af03a0da629f4cf0e2a8a88d2e127208116f0e849c107e21c51f6",
|
|
20
|
+
"createdAt": 1800000000,
|
|
21
|
+
"endsAt": 1800086400,
|
|
22
|
+
"relays": [
|
|
23
|
+
"wss://relay.example.com/"
|
|
24
|
+
],
|
|
25
|
+
"event": {
|
|
26
|
+
"id": "526ed7535a2ead66313654f6b97a86af4d827af11b005ce2d248c675097d5c78",
|
|
27
|
+
"pubkey": "66df4b7febed3972515d9f663fe00a8ef9b2c69fbcb6bee3f5587b5d0b96605e",
|
|
28
|
+
"created_at": 1800000000,
|
|
29
|
+
"kind": 1463,
|
|
30
|
+
"tags": [
|
|
31
|
+
[
|
|
32
|
+
"d",
|
|
33
|
+
"3bbaca427676d0f5a796278a86bf2166d8f66e7abd09d40caa6581f1e7454914"
|
|
34
|
+
],
|
|
35
|
+
[
|
|
36
|
+
"expiration",
|
|
37
|
+
"1800086400"
|
|
38
|
+
]
|
|
39
|
+
],
|
|
40
|
+
"content": "AhKIoHqYG4uOcnjHZ/7EHKpG1oknjFfGX/gvvT2u9PAIJYXCDlIPSvR5TutkG+Nx5hGvco9Z/C40vaXhVi4PNy7fETWGqCb+hFLpnZokAB2a2111Zc42hFUOrLnmahl6LXJdVtkgesGXnYe9LrskUR+PekcO+GazVPxDc7TOZRaCPd6tWLB37U+1o7w+jhyBPHZvurz59i7EqCK4cYgQox03i7JlXxOvT9I6ebQJJM5f1Z6zYmvuPIWMklHJEnJAGFFQ9JkhX3yQlTlYjhRn3e+B1ct3mAxFL5qoWBWXZ4TtTo4bINzqVBHWpnLmvZjhXBhGTVDJc6H8+azqOVhEqktzvIcn+TAGzVX5rywXlR3ZgNVLORtp/k70KakDt1dkKIp5",
|
|
41
|
+
"sig": "3db32e6460f29f804c3502a4156bec06d00ee4fa3f6e29c57193149d50d3c71075cfa930a981f89dd9919791d073c795a0f039a0061f0c1e9b18e19ea44f2afd"
|
|
42
|
+
},
|
|
43
|
+
"randomHex": [
|
|
44
|
+
"1288a07a981b8b8e7278c767fec41caa46d689278c57c65ff82fbd3daef4f008",
|
|
45
|
+
"e70b320ea3f8ea2efc3b6120d3a07908ee32f1d438332c02513ef5dde2d30d7e"
|
|
46
|
+
],
|
|
47
|
+
"unflagged": {
|
|
48
|
+
"event": {
|
|
49
|
+
"id": "5b31789aca6f969e7472688636bd8ad236eb79a572f2b80793bfc1ac75288870",
|
|
50
|
+
"pubkey": "66df4b7febed3972515d9f663fe00a8ef9b2c69fbcb6bee3f5587b5d0b96605e",
|
|
51
|
+
"created_at": 1800000000,
|
|
52
|
+
"kind": 1463,
|
|
53
|
+
"tags": [
|
|
54
|
+
[
|
|
55
|
+
"d",
|
|
56
|
+
"3bbaca427676d0f5a796278a86bf2166d8f66e7abd09d40caa6581f1e7454914"
|
|
57
|
+
],
|
|
58
|
+
[
|
|
59
|
+
"expiration",
|
|
60
|
+
"1800086400"
|
|
61
|
+
]
|
|
62
|
+
],
|
|
63
|
+
"content": "AhKIoHqYG4uOcnjHZ/7EHKpG1oknjFfGX/gvvT2u9PAIJZXCDlIPSvR5TutkG+Nx5hGvco9Z/C40vaXhVi4PNy7fETWGqCb+hFLpnZokAB2a2111Zc42hFUOrLnmahl6LXJdVtkgesGXnYe9LrskUR+PekcO+GazVPxDc7TOZRaCPd6tWLB37U+1o7w+jhyBPHZvurz59i7EqCK4cYgQox03i7JlXxOvT9I6ebQJJM5f1Z6zYmvuPIWMklHJEmRAB0Rb8thvJmSTlD8HjRln3e+B1ZYw2jYKKIW+TFnXeM6jcopWJM9Fcgn6nvuxBCDzIw8Cd4g8OKdKXeX9664RPqCRCA==",
|
|
64
|
+
"sig": "36a5dc73f330985626d91edaabd1a2fa6f3a27b885834fa6d8f4895f04a6dfe772feff95b79be0c20b15e878869844acf32189968191cbf209767622367824e0"
|
|
65
|
+
},
|
|
66
|
+
"randomHex": [
|
|
67
|
+
"1288a07a981b8b8e7278c767fec41caa46d689278c57c65ff82fbd3daef4f008",
|
|
68
|
+
"e70b320ea3f8ea2efc3b6120d3a07908ee32f1d438332c02513ef5dde2d30d7e"
|
|
69
|
+
]
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
"output": {
|
|
73
|
+
"bodyJson": "{\"v\":3,\"room\":\"629cb9accf2af03a0da629f4cf0e2a8a88d2e127208116f0e849c107e21c51f6\",\"secret\":\"dtp2VlDxGbZKTJCMSQmS0SVia9JyyQuLM2IBCJI1big\",\"ends\":1800086400,\"destruct\":true,\"relays\":[\"wss://relay.example.com/\"]}",
|
|
74
|
+
"unflaggedBodyJson": "{\"v\":3,\"room\":\"629cb9accf2af03a0da629f4cf0e2a8a88d2e127208116f0e849c107e21c51f6\",\"secret\":\"dtp2VlDxGbZKTJCMSQmS0SVia9JyyQuLM2IBCJI1big\",\"ends\":1800086400,\"relays\":[\"wss://relay.example.com/\"]}",
|
|
75
|
+
"admission": {
|
|
76
|
+
"secretHex": "76da765650f119b64a4c908c490992d125626bd272c90b8b3362010892356e28",
|
|
77
|
+
"persistent": true,
|
|
78
|
+
"epoch": 0,
|
|
79
|
+
"endsAt": 1800086400,
|
|
80
|
+
"relays": [
|
|
81
|
+
"wss://relay.example.com/"
|
|
82
|
+
],
|
|
83
|
+
"destruct": true
|
|
84
|
+
},
|
|
85
|
+
"unflaggedAdmission": {
|
|
86
|
+
"secretHex": "76da765650f119b64a4c908c490992d125626bd272c90b8b3362010892356e28",
|
|
87
|
+
"persistent": true,
|
|
88
|
+
"epoch": 0,
|
|
89
|
+
"endsAt": 1800086400,
|
|
90
|
+
"relays": [
|
|
91
|
+
"wss://relay.example.com/"
|
|
92
|
+
]
|
|
93
|
+
},
|
|
94
|
+
"oldReader": {
|
|
95
|
+
"secretHex": "76da765650f119b64a4c908c490992d125626bd272c90b8b3362010892356e28",
|
|
96
|
+
"persistent": true,
|
|
97
|
+
"epoch": 0,
|
|
98
|
+
"endsAt": 1800086400,
|
|
99
|
+
"relays": [
|
|
100
|
+
"wss://relay.example.com/"
|
|
101
|
+
]
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"name": "destruct-invitation-no-end",
|
|
107
|
+
"kind": "positive",
|
|
108
|
+
"note": "A group invitation with `destruct` and no `ends`: valid. The room has no fixed end and self-destructs when its authority closes it. No expiration tag, as for any group with no end. `randomHex`: the body nonce, the aux-rand.",
|
|
109
|
+
"input": {
|
|
110
|
+
"invitation": {
|
|
111
|
+
"bearerHex": "63da81a93ddf0a90ae34ed2b24bb91e664383e117bcacec5cc05e0da5d3d2612",
|
|
112
|
+
"inviter": "66df4b7febed3972515d9f663fe00a8ef9b2c69fbcb6bee3f5587b5d0b96605e",
|
|
113
|
+
"persistent": true
|
|
114
|
+
},
|
|
115
|
+
"inviterSkHex": "a090036fcabc0a442fc1eaa5afc5c7ddda6f95c6bf8fe1f7b3b69589e621d643",
|
|
116
|
+
"roomSecretHex": "76da765650f119b64a4c908c490992d125626bd272c90b8b3362010892356e28",
|
|
117
|
+
"roomId": "629cb9accf2af03a0da629f4cf0e2a8a88d2e127208116f0e849c107e21c51f6",
|
|
118
|
+
"createdAt": 1800000000,
|
|
119
|
+
"event": {
|
|
120
|
+
"id": "824d7c025cda000955e697611ac8715cd04260bb71ac2b189325d421f5cc977b",
|
|
121
|
+
"pubkey": "66df4b7febed3972515d9f663fe00a8ef9b2c69fbcb6bee3f5587b5d0b96605e",
|
|
122
|
+
"created_at": 1800000000,
|
|
123
|
+
"kind": 1463,
|
|
124
|
+
"tags": [
|
|
125
|
+
[
|
|
126
|
+
"d",
|
|
127
|
+
"3bbaca427676d0f5a796278a86bf2166d8f66e7abd09d40caa6581f1e7454914"
|
|
128
|
+
]
|
|
129
|
+
],
|
|
130
|
+
"content": "Ar2/gSpXQYq/bOeYByDqnIjpXz+MkD5ZeS3d/zm3xXgfbKpwDAY4YHFki6YgOB91OIoom0qFYQ/7L3hykgYI+5sjoFHReBK5T4tdM2RZsUsuNGztNC6PHuCuxWoR3t1+li3Xk0GW1s5RjbGjWAHFMl/3/HGj9zTaLwgfwy1T61bLlcLYxhtRkF6IHHsNegpjRP6fiq3cGY661hG3+PkcOTjIDtSZdvzPG7KbvZmuFXBJ611pApyK8VfZICk+mC2ls9Gj609S2guZoBntEnQdAmsSK9st+UXeVtMR18850DlKLgY=",
|
|
131
|
+
"sig": "c576a3a1e3149b723136ced230d5934e2f1fb18abaaba95a88069f9db0f62edc92472881a772e133a580b264d3ad64e3242afaca0114ee7b22a9117825c341b3"
|
|
132
|
+
},
|
|
133
|
+
"randomHex": [
|
|
134
|
+
"bdbf812a57418abf6ce7980720ea9c88e95f3f8c903e59792dddff39b7c5781f",
|
|
135
|
+
"556b37bc374f271443b645f473fe0fc07ef5384c628e3a14cc936136f8dccb3d"
|
|
136
|
+
]
|
|
137
|
+
},
|
|
138
|
+
"output": {
|
|
139
|
+
"bodyJson": "{\"v\":3,\"room\":\"629cb9accf2af03a0da629f4cf0e2a8a88d2e127208116f0e849c107e21c51f6\",\"secret\":\"dtp2VlDxGbZKTJCMSQmS0SVia9JyyQuLM2IBCJI1big\",\"destruct\":true}",
|
|
140
|
+
"admission": {
|
|
141
|
+
"secretHex": "76da765650f119b64a4c908c490992d125626bd272c90b8b3362010892356e28",
|
|
142
|
+
"persistent": true,
|
|
143
|
+
"epoch": 0,
|
|
144
|
+
"destruct": true
|
|
145
|
+
},
|
|
146
|
+
"oldReader": {
|
|
147
|
+
"secretHex": "76da765650f119b64a4c908c490992d125626bd272c90b8b3362010892356e28",
|
|
148
|
+
"persistent": true,
|
|
149
|
+
"epoch": 0
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
"name": "destruct-invitation-malformed",
|
|
155
|
+
"kind": "negative",
|
|
156
|
+
"note": "Group invitations signed by the inviter whose body carries `destruct` as something other than `true`: `false`, the string `\"true\"`, `1`, `null`. Built by hand (`bodyJson`, then `randomHex`: the body nonce, the aux-rand). A reader refuses each envelope outright (null), as it refuses a malformed `ends`. A 0.8.0 reader, which never looks at the field, still admits each one (`oldReader`).",
|
|
157
|
+
"input": {
|
|
158
|
+
"invitation": {
|
|
159
|
+
"bearerHex": "63da81a93ddf0a90ae34ed2b24bb91e664383e117bcacec5cc05e0da5d3d2612",
|
|
160
|
+
"inviter": "66df4b7febed3972515d9f663fe00a8ef9b2c69fbcb6bee3f5587b5d0b96605e",
|
|
161
|
+
"persistent": true
|
|
162
|
+
},
|
|
163
|
+
"inviterSkHex": "a090036fcabc0a442fc1eaa5afc5c7ddda6f95c6bf8fe1f7b3b69589e621d643",
|
|
164
|
+
"roomSecretHex": "76da765650f119b64a4c908c490992d125626bd272c90b8b3362010892356e28",
|
|
165
|
+
"roomId": "629cb9accf2af03a0da629f4cf0e2a8a88d2e127208116f0e849c107e21c51f6",
|
|
166
|
+
"cases": {
|
|
167
|
+
"false": {
|
|
168
|
+
"event": {
|
|
169
|
+
"id": "99bb8b1f573f4c0bf83a43e7f9d22fb3d5798dc1c6f34a897afd0e5c33341482",
|
|
170
|
+
"pubkey": "66df4b7febed3972515d9f663fe00a8ef9b2c69fbcb6bee3f5587b5d0b96605e",
|
|
171
|
+
"created_at": 1800000000,
|
|
172
|
+
"kind": 1463,
|
|
173
|
+
"tags": [
|
|
174
|
+
[
|
|
175
|
+
"d",
|
|
176
|
+
"3bbaca427676d0f5a796278a86bf2166d8f66e7abd09d40caa6581f1e7454914"
|
|
177
|
+
]
|
|
178
|
+
],
|
|
179
|
+
"content": "Auri0a+JHb2EUxVXoLZ7pCtFilbL6S8+xF0q5zBJKVpeaRq0c86+ZnMcHmfp+5tm/DX+XdKXmX9yOMLz8mkKt3n2ZJg+GgnC/t1L0LlokgaVH4CPGT8+C7yTiJFIFdNF6c76Ta+t2cZuatA+PQTHruBDafFG8BvTYpWeEHlyiYrdbRplFg4jso37JisPZB2g48GLKwQQHR1qjyfKd+nKPqFbG3mDVe82ISAntabZz855S3fqzMW+roGKb8tksDe4SS2Zqvg0pozhgxCaTw1gC92loFh6DSDltz/vyZR9pYcMwQ0=",
|
|
180
|
+
"sig": "614e6bd4dd94ce5569c157bd00f3afdac875656eb0beac417aa7544c82673eafd4c7941a1bace18268a4e374e2ed3e2231df32d15e5d63633347bd3e62a2bc53"
|
|
181
|
+
},
|
|
182
|
+
"randomHex": [
|
|
183
|
+
"eae2d1af891dbd84531557a0b67ba42b458a56cbe92f3ec45d2ae73049295a5e",
|
|
184
|
+
"ced40f26ae7e9c2907fbdce2991a8daacefb7739c0780b4e186f4d07f2775ea8"
|
|
185
|
+
],
|
|
186
|
+
"bodyJson": "{\"v\":3,\"room\":\"629cb9accf2af03a0da629f4cf0e2a8a88d2e127208116f0e849c107e21c51f6\",\"secret\":\"dtp2VlDxGbZKTJCMSQmS0SVia9JyyQuLM2IBCJI1big\",\"destruct\":false}"
|
|
187
|
+
},
|
|
188
|
+
"string": {
|
|
189
|
+
"event": {
|
|
190
|
+
"id": "e00d2125c88e132c21ce1519d17cdd541467240210dc4c5fc9520b2c495a8f96",
|
|
191
|
+
"pubkey": "66df4b7febed3972515d9f663fe00a8ef9b2c69fbcb6bee3f5587b5d0b96605e",
|
|
192
|
+
"created_at": 1800000000,
|
|
193
|
+
"kind": 1463,
|
|
194
|
+
"tags": [
|
|
195
|
+
[
|
|
196
|
+
"d",
|
|
197
|
+
"3bbaca427676d0f5a796278a86bf2166d8f66e7abd09d40caa6581f1e7454914"
|
|
198
|
+
]
|
|
199
|
+
],
|
|
200
|
+
"content": "AoSjS3R7pOmM6LqSsTwJC38zSylOxll/zIGx620jEFSMCxtmiegakh9oyofzUB5yncm6wHTAC9xjNh9PrfN2U3L3XHo0Wi5RcqKT6kPvYLKFzbKlXefM1V3uxiaFLsAW3sErkOIWKbC7+4ZVW8LDQv58PKeXPY9E68qxq78Wbbd9i1RW1dSdmZzBhGDIQB5xRP+sZXwtXEhnaL84lE4vXwGJI87eWMC0iC8vAiKiiuQfldgDqzyhHYZjE3IHAYX2nAqmD0PdEwOBj1fsjrb7g0hs+LPnXqNiP22SsyEIlqk1OH8=",
|
|
201
|
+
"sig": "fc52b06b5d089bb6837f6cb4fd501927abcd5cf8973f0a48946ee0912e74ad63c9a8588a47f328b6e1030a1204333a37ce6d8d6d72b114893a85392b2426253f"
|
|
202
|
+
},
|
|
203
|
+
"randomHex": [
|
|
204
|
+
"84a34b747ba4e98ce8ba92b13c090b7f334b294ec6597fcc81b1eb6d2310548c",
|
|
205
|
+
"b4114d68af4779911af998dd2d43e56db75fd2e686e8bf63e43cdabc2755ed1d"
|
|
206
|
+
],
|
|
207
|
+
"bodyJson": "{\"v\":3,\"room\":\"629cb9accf2af03a0da629f4cf0e2a8a88d2e127208116f0e849c107e21c51f6\",\"secret\":\"dtp2VlDxGbZKTJCMSQmS0SVia9JyyQuLM2IBCJI1big\",\"destruct\":\"true\"}"
|
|
208
|
+
},
|
|
209
|
+
"number": {
|
|
210
|
+
"event": {
|
|
211
|
+
"id": "f97f3de9b8b1227b9fe5f911dfaab269f5a6927df6f612688b9fd934ca87cc09",
|
|
212
|
+
"pubkey": "66df4b7febed3972515d9f663fe00a8ef9b2c69fbcb6bee3f5587b5d0b96605e",
|
|
213
|
+
"created_at": 1800000000,
|
|
214
|
+
"kind": 1463,
|
|
215
|
+
"tags": [
|
|
216
|
+
[
|
|
217
|
+
"d",
|
|
218
|
+
"3bbaca427676d0f5a796278a86bf2166d8f66e7abd09d40caa6581f1e7454914"
|
|
219
|
+
]
|
|
220
|
+
],
|
|
221
|
+
"content": "AmHcx8yLgRa/Oa+sIw47P4MwMV2AuEORn1XSQQWV+oz4Fgbj3HSNanTE2MC8iV4j4w3UmHrLA62SV7Plti2xjDwhYJTW+XJMLu2on/PS/lt/Kl2XvAHXnHrJ/gNSma+JpJyL/YIW3aNbaWp/yHQossFjr+t7A7Ej3oz6tHdrdaaQpH1vfyg44hC+T0dlKr+0xZg23Is4Uf0TsM287oNru2JhV6+CqET4MGpUaFvxKulSRQpvX+tZPHwSQHplf+lFvHvZUpErDzqhS8tmH34VEIhCPnT25mpu8NKBr3HN0xyrl+8=",
|
|
222
|
+
"sig": "cd714956b3e96a6deccc1654ff823de404cfb85d548c0f9b478c35e0507dff960b146a56f41a34ccf59192d255ca488a216edc3c4b261508fe86c2e1fc5f4133"
|
|
223
|
+
},
|
|
224
|
+
"randomHex": [
|
|
225
|
+
"61dcc7cc8b8116bf39afac230e3b3f8330315d80b843919f55d2410595fa8cf8",
|
|
226
|
+
"cc4d068aff3fa914a212bf68ed39d9b402c2f7bc8c540acb490b3d017f476ac9"
|
|
227
|
+
],
|
|
228
|
+
"bodyJson": "{\"v\":3,\"room\":\"629cb9accf2af03a0da629f4cf0e2a8a88d2e127208116f0e849c107e21c51f6\",\"secret\":\"dtp2VlDxGbZKTJCMSQmS0SVia9JyyQuLM2IBCJI1big\",\"destruct\":1}"
|
|
229
|
+
},
|
|
230
|
+
"null": {
|
|
231
|
+
"event": {
|
|
232
|
+
"id": "a31ba9cf7106813bd2d01de861e7f612be29adcbc84879fed99bb3b0b98d536e",
|
|
233
|
+
"pubkey": "66df4b7febed3972515d9f663fe00a8ef9b2c69fbcb6bee3f5587b5d0b96605e",
|
|
234
|
+
"created_at": 1800000000,
|
|
235
|
+
"kind": 1463,
|
|
236
|
+
"tags": [
|
|
237
|
+
[
|
|
238
|
+
"d",
|
|
239
|
+
"3bbaca427676d0f5a796278a86bf2166d8f66e7abd09d40caa6581f1e7454914"
|
|
240
|
+
]
|
|
241
|
+
],
|
|
242
|
+
"content": "AsvyriQzQy6dRH/yC3e8fNvxU5i/lR8OixB3yVytXzq7+3SYS4KZzKfQYNzSndix9QQYHUgO2S5euVOTo19DMCbpC1IrnIL4UfFWgSx4XqzFfQGQ4UtXO9S+gRJjzkyJHrvNETeIrotXcAABG1Mo/gr6nHhhAMw1+YiPH9RJMFwb8djuBjfVriwEQwq6IFn8IctDDy9DA8Ami8zNVxcX9Fn1Iw0JHZsLpMN7xC4DMEW35IxUHg0kRB2sLPTfv8+DChAmWHj4vk737sIQqJ1cSuuBm7G1w6Olo0ybM7eJAt9YWhI=",
|
|
243
|
+
"sig": "f828a69d9e58c976180f848142d154faf4c0338d09cf74fb92597ab89a63a49cd12f38f145658dc3ce84e80a1df83c083263da5d548debfd6bdf744a763a4001"
|
|
244
|
+
},
|
|
245
|
+
"randomHex": [
|
|
246
|
+
"cbf2ae2433432e9d447ff20b77bc7cdbf15398bf951f0e8b1077c95cad5f3abb",
|
|
247
|
+
"006a1daf9bd649cd57d2e5cbf4c51a8549fb5bfbd0035fdbac1d89be0a76b3e2"
|
|
248
|
+
],
|
|
249
|
+
"bodyJson": "{\"v\":3,\"room\":\"629cb9accf2af03a0da629f4cf0e2a8a88d2e127208116f0e849c107e21c51f6\",\"secret\":\"dtp2VlDxGbZKTJCMSQmS0SVia9JyyQuLM2IBCJI1big\",\"destruct\":null}"
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
},
|
|
253
|
+
"output": {
|
|
254
|
+
"admission": {
|
|
255
|
+
"false": null,
|
|
256
|
+
"string": null,
|
|
257
|
+
"number": null,
|
|
258
|
+
"null": null
|
|
259
|
+
},
|
|
260
|
+
"oldReader": {
|
|
261
|
+
"false": {
|
|
262
|
+
"secretHex": "76da765650f119b64a4c908c490992d125626bd272c90b8b3362010892356e28",
|
|
263
|
+
"persistent": true,
|
|
264
|
+
"epoch": 0
|
|
265
|
+
},
|
|
266
|
+
"string": {
|
|
267
|
+
"secretHex": "76da765650f119b64a4c908c490992d125626bd272c90b8b3362010892356e28",
|
|
268
|
+
"persistent": true,
|
|
269
|
+
"epoch": 0
|
|
270
|
+
},
|
|
271
|
+
"number": {
|
|
272
|
+
"secretHex": "76da765650f119b64a4c908c490992d125626bd272c90b8b3362010892356e28",
|
|
273
|
+
"persistent": true,
|
|
274
|
+
"epoch": 0
|
|
275
|
+
},
|
|
276
|
+
"null": {
|
|
277
|
+
"secretHex": "76da765650f119b64a4c908c490992d125626bd272c90b8b3362010892356e28",
|
|
278
|
+
"persistent": true,
|
|
279
|
+
"epoch": 0
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
"name": "destruct-invitation-copies",
|
|
286
|
+
"kind": "positive",
|
|
287
|
+
"note": "Two signed copies of one group invitation that disagree: `older` (created_at NOW) self-destructs, `newer` (NOW + 60) names the room relays and has no flag. `requestPersistentRoomAdmission` hears both and admits with `destruct: true` in either order (`olderFirst`, `newerFirst`; `alone` is each copy read by itself): self-destruct is sticky, as the earlier `ends` is, so a stale or careless copy can never keep a room's content alive. The relays still come from the newest copy that names any. `randomHex` on each: the body nonce, the aux-rand.",
|
|
288
|
+
"input": {
|
|
289
|
+
"invitation": {
|
|
290
|
+
"bearerHex": "63da81a93ddf0a90ae34ed2b24bb91e664383e117bcacec5cc05e0da5d3d2612",
|
|
291
|
+
"inviter": "66df4b7febed3972515d9f663fe00a8ef9b2c69fbcb6bee3f5587b5d0b96605e",
|
|
292
|
+
"persistent": true
|
|
293
|
+
},
|
|
294
|
+
"inviterSkHex": "a090036fcabc0a442fc1eaa5afc5c7ddda6f95c6bf8fe1f7b3b69589e621d643",
|
|
295
|
+
"roomSecretHex": "76da765650f119b64a4c908c490992d125626bd272c90b8b3362010892356e28",
|
|
296
|
+
"roomId": "629cb9accf2af03a0da629f4cf0e2a8a88d2e127208116f0e849c107e21c51f6",
|
|
297
|
+
"older": {
|
|
298
|
+
"event": {
|
|
299
|
+
"id": "bf927b24f6956b3b51c4db990fb34e194e33efe3e1c9c43aa51653e41c52f9db",
|
|
300
|
+
"pubkey": "66df4b7febed3972515d9f663fe00a8ef9b2c69fbcb6bee3f5587b5d0b96605e",
|
|
301
|
+
"created_at": 1800000000,
|
|
302
|
+
"kind": 1463,
|
|
303
|
+
"tags": [
|
|
304
|
+
[
|
|
305
|
+
"d",
|
|
306
|
+
"3bbaca427676d0f5a796278a86bf2166d8f66e7abd09d40caa6581f1e7454914"
|
|
307
|
+
]
|
|
308
|
+
],
|
|
309
|
+
"content": "AjHpz19NgPNarY9R7eWHpy4k3zsjLXvATwVknx+DPW05EKLaaWW/XgjOw8aPMVwqt1ZaolyOMT6s2gUerWCaEIp38NjKsirkNmpKCw3cd3Ouzzu2nn5+QgGJAMH3OaZSRu4Zu9b/VqO/HhMrWQ92XILwuutTn+BrrwoJmG4V571RpS866L0XM9JE2Mkup/zuzZvmhoqQC30fwUMqlNvWilAuJF9MVW0nzw0+nVBXQkf3mQZmDAa053Jfpi4UJ3ENu1TMZ73r/LDlgFlavIhC7eS7DRwb3/Kl75hVhdfFv1O7R6A=",
|
|
310
|
+
"sig": "ab8d460d5d571859ad59d7ec17675f2a9c63abed76c09837626c7ef548f455959ca63168af56ab9122ffa54e8a84ecdb176ca252822f48d7b7faa511c9cb61e3"
|
|
311
|
+
},
|
|
312
|
+
"randomHex": [
|
|
313
|
+
"31e9cf5f4d80f35aad8f51ede587a72e24df3b232d7bc04f05649f1f833d6d39",
|
|
314
|
+
"aed5df214155aefbdd54cdf7eb415014ba000d9a4f1f787e09f17ec5d03cd3f4"
|
|
315
|
+
]
|
|
316
|
+
},
|
|
317
|
+
"newer": {
|
|
318
|
+
"event": {
|
|
319
|
+
"id": "50457bca51dd68b0d15cb16c5d3ebe7c5e748e3ea460edf204900f73de9dd074",
|
|
320
|
+
"pubkey": "66df4b7febed3972515d9f663fe00a8ef9b2c69fbcb6bee3f5587b5d0b96605e",
|
|
321
|
+
"created_at": 1800000060,
|
|
322
|
+
"kind": 1463,
|
|
323
|
+
"tags": [
|
|
324
|
+
[
|
|
325
|
+
"d",
|
|
326
|
+
"3bbaca427676d0f5a796278a86bf2166d8f66e7abd09d40caa6581f1e7454914"
|
|
327
|
+
]
|
|
328
|
+
],
|
|
329
|
+
"content": "AiSsGzVre7NuU2R1ilNei7Np9z/Rg1ijlatOwpbs8s31YE9g/IDAm9iTlkZlezUCRz4et94GEr1h38NGMjTWbQzLYn10jhxy0+o4sUXP1DNLVIBkIMShLReqDxQC7sC/pDHxplHslGnB8CBxfEafsMQLv8A8UxWp7NZio7sGCNe6a95ZazFqokLImMrmJpjkqCbIFqzGzoH6HElvEVKMWTSS4YpGLYk2tjH7h8KlJYoxr3jPV5dAOKLCwAGMJ2LWGs9DLfIjWmdPnSPQPdQK214ZsNuPst1ObckGmb88UozIpW/ppOr5uS7q7eFSyYq/tJVJAlmQUVuih6pi4L7ZBJC0AQ==",
|
|
330
|
+
"sig": "450526ef0933591e9e3af2cddaf7936dc43247f8ab5427bd65fbd55c2b62a0710aabc25e70515f4216c41df14a636c0cf6a3d3006f8750c1ef43c680d2f6aafb"
|
|
331
|
+
},
|
|
332
|
+
"randomHex": [
|
|
333
|
+
"24ac1b356b7bb36e5364758a535e8bb369f73fd18358a395ab4ec296ecf2cdf5",
|
|
334
|
+
"f7c71d2ef1e5e0ca0962d40476ace63fb43012c671ba6e6a7c9130060beda77b"
|
|
335
|
+
]
|
|
336
|
+
}
|
|
337
|
+
},
|
|
338
|
+
"output": {
|
|
339
|
+
"olderFirst": {
|
|
340
|
+
"secretHex": "76da765650f119b64a4c908c490992d125626bd272c90b8b3362010892356e28",
|
|
341
|
+
"persistent": true,
|
|
342
|
+
"epoch": 0,
|
|
343
|
+
"relays": [
|
|
344
|
+
"wss://relay.example.com/"
|
|
345
|
+
],
|
|
346
|
+
"destruct": true
|
|
347
|
+
},
|
|
348
|
+
"newerFirst": {
|
|
349
|
+
"secretHex": "76da765650f119b64a4c908c490992d125626bd272c90b8b3362010892356e28",
|
|
350
|
+
"persistent": true,
|
|
351
|
+
"epoch": 0,
|
|
352
|
+
"relays": [
|
|
353
|
+
"wss://relay.example.com/"
|
|
354
|
+
],
|
|
355
|
+
"destruct": true
|
|
356
|
+
},
|
|
357
|
+
"alone": {
|
|
358
|
+
"older": {
|
|
359
|
+
"secretHex": "76da765650f119b64a4c908c490992d125626bd272c90b8b3362010892356e28",
|
|
360
|
+
"persistent": true,
|
|
361
|
+
"epoch": 0,
|
|
362
|
+
"destruct": true
|
|
363
|
+
},
|
|
364
|
+
"newer": {
|
|
365
|
+
"secretHex": "76da765650f119b64a4c908c490992d125626bd272c90b8b3362010892356e28",
|
|
366
|
+
"persistent": true,
|
|
367
|
+
"epoch": 0,
|
|
368
|
+
"relays": [
|
|
369
|
+
"wss://relay.example.com/"
|
|
370
|
+
]
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
},
|
|
375
|
+
{
|
|
376
|
+
"name": "destruct-retirement",
|
|
377
|
+
"kind": "positive",
|
|
378
|
+
"note": "A kind-1461 retirement of the invitation above, saying the room was ended and self-destructs: content `{\"v\":1,\"ended\":true,\"destruct\":true}`. This content is plain JSON, not encrypted, as `ended` always was; the `d` tag is the invitation id, which nobody without the link can tie to a room. A reader reports `{ ended: true, destruct: true }`. `randomHex`: the aux-rand. `unflagged` is the same retirement with the same draw and no flag (0.8.0's `ended` retirement). `oldReader`: a 0.8.0 reader sees an ordinary ended room.",
|
|
379
|
+
"input": {
|
|
380
|
+
"invitation": {
|
|
381
|
+
"bearerHex": "63da81a93ddf0a90ae34ed2b24bb91e664383e117bcacec5cc05e0da5d3d2612",
|
|
382
|
+
"inviter": "66df4b7febed3972515d9f663fe00a8ef9b2c69fbcb6bee3f5587b5d0b96605e",
|
|
383
|
+
"persistent": true
|
|
384
|
+
},
|
|
385
|
+
"inviterSkHex": "a090036fcabc0a442fc1eaa5afc5c7ddda6f95c6bf8fe1f7b3b69589e621d643",
|
|
386
|
+
"createdAt": 1800003600,
|
|
387
|
+
"event": {
|
|
388
|
+
"id": "88503f949adc9ef36f283cb5956f6d6e19267c9c3873508dafb4f1e07178b1ff",
|
|
389
|
+
"pubkey": "66df4b7febed3972515d9f663fe00a8ef9b2c69fbcb6bee3f5587b5d0b96605e",
|
|
390
|
+
"created_at": 1800003600,
|
|
391
|
+
"kind": 1461,
|
|
392
|
+
"tags": [
|
|
393
|
+
[
|
|
394
|
+
"d",
|
|
395
|
+
"3bbaca427676d0f5a796278a86bf2166d8f66e7abd09d40caa6581f1e7454914"
|
|
396
|
+
]
|
|
397
|
+
],
|
|
398
|
+
"content": "{\"v\":1,\"ended\":true,\"destruct\":true}",
|
|
399
|
+
"sig": "e71b9f81f82c7c683ffc0d52d97396a6d5780e78163b84bfd5ede41b3ec126e11811a555b30382fe544add45eaf149a83f58f8011dacdb0fae3ee0e0070d5e91"
|
|
400
|
+
},
|
|
401
|
+
"randomHex": [
|
|
402
|
+
"a949d71b4873256ad433d5d1de0e9551b2f44fa63becdfef2554843e8dcc9b2e"
|
|
403
|
+
],
|
|
404
|
+
"unflagged": {
|
|
405
|
+
"event": {
|
|
406
|
+
"id": "f7cba6d0721398ba9b6f5d79e16600da534c990f223db68291e68dc1e30e3c98",
|
|
407
|
+
"pubkey": "66df4b7febed3972515d9f663fe00a8ef9b2c69fbcb6bee3f5587b5d0b96605e",
|
|
408
|
+
"created_at": 1800003600,
|
|
409
|
+
"kind": 1461,
|
|
410
|
+
"tags": [
|
|
411
|
+
[
|
|
412
|
+
"d",
|
|
413
|
+
"3bbaca427676d0f5a796278a86bf2166d8f66e7abd09d40caa6581f1e7454914"
|
|
414
|
+
]
|
|
415
|
+
],
|
|
416
|
+
"content": "{\"v\":1,\"ended\":true}",
|
|
417
|
+
"sig": "e299e745d62ac489a69566d557584bccabbe932aaaba15ad2ce53f7251317c3e8393c334a15f76e2746a5e310f5070f78b109d10317f326dd11f04a6c23d7067"
|
|
418
|
+
},
|
|
419
|
+
"randomHex": [
|
|
420
|
+
"a949d71b4873256ad433d5d1de0e9551b2f44fa63becdfef2554843e8dcc9b2e"
|
|
421
|
+
]
|
|
422
|
+
}
|
|
423
|
+
},
|
|
424
|
+
"output": {
|
|
425
|
+
"notice": {
|
|
426
|
+
"ended": true,
|
|
427
|
+
"destruct": true
|
|
428
|
+
},
|
|
429
|
+
"unflaggedNotice": {
|
|
430
|
+
"ended": true
|
|
431
|
+
},
|
|
432
|
+
"oldReader": {
|
|
433
|
+
"ended": true
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
},
|
|
437
|
+
{
|
|
438
|
+
"name": "destruct-retirement-not-ended",
|
|
439
|
+
"kind": "negative",
|
|
440
|
+
"note": "A retirement signed by the inviter whose content is `{\"v\":1,\"destruct\":true}`: a flag without `ended`. The encoder refuses it (`encoder`), so it is built by hand (`randomHex`: the aux-rand). A reader still honours the retirement, since a retired link must stay retired, and does not believe the flag: `{ ended: false }`.",
|
|
441
|
+
"input": {
|
|
442
|
+
"invitation": {
|
|
443
|
+
"bearerHex": "63da81a93ddf0a90ae34ed2b24bb91e664383e117bcacec5cc05e0da5d3d2612",
|
|
444
|
+
"inviter": "66df4b7febed3972515d9f663fe00a8ef9b2c69fbcb6bee3f5587b5d0b96605e",
|
|
445
|
+
"persistent": true
|
|
446
|
+
},
|
|
447
|
+
"event": {
|
|
448
|
+
"id": "65c29f31e3520b2ee8ea981904a48edb8ee75a39b841710d68a9f124b1caa08b",
|
|
449
|
+
"pubkey": "66df4b7febed3972515d9f663fe00a8ef9b2c69fbcb6bee3f5587b5d0b96605e",
|
|
450
|
+
"created_at": 1800003600,
|
|
451
|
+
"kind": 1461,
|
|
452
|
+
"tags": [
|
|
453
|
+
[
|
|
454
|
+
"d",
|
|
455
|
+
"3bbaca427676d0f5a796278a86bf2166d8f66e7abd09d40caa6581f1e7454914"
|
|
456
|
+
]
|
|
457
|
+
],
|
|
458
|
+
"content": "{\"v\":1,\"destruct\":true}",
|
|
459
|
+
"sig": "519018291651ba182de5f1d34355539fdaed555f35863e97030a2613a4b536700481a83b6aeecf4acbbdb74e28b2a3ba73a8ab7996e5a15b506ac19792bde684"
|
|
460
|
+
},
|
|
461
|
+
"randomHex": [
|
|
462
|
+
"7e483c437263f98c287eb2c2a76ab6ad25f2c306cfeaa5e2d86f0c4a6b93931d"
|
|
463
|
+
],
|
|
464
|
+
"bodyJson": "{\"v\":1,\"destruct\":true}"
|
|
465
|
+
},
|
|
466
|
+
"output": {
|
|
467
|
+
"encoder": "refused",
|
|
468
|
+
"notice": {
|
|
469
|
+
"ended": false
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
},
|
|
473
|
+
{
|
|
474
|
+
"name": "destruct-closure",
|
|
475
|
+
"kind": "positive",
|
|
476
|
+
"note": "A kind-1462 rekey from epoch 1 to 2 that closes the room and self-destructs it: `\"closed\": true, \"destruct\": true` inside the body encrypted to epoch 1 (body order v, epoch, removed, closed, destruct, keys), and never as a tag. A closure seals the new secret to nobody, so `keys` is empty and the only draws are `randomHex`: the body nonce, the aux-rand. `unflagged` is the same closure with the same draws and no flag (every closure before 0.9.0). `notice` is `decodeRekeyEvent`, `evidence` is `readRekeyEvidence`; both report `destruct`. `oldReader`: a 0.8.0 reader sees an ordinary close.",
|
|
477
|
+
"input": {
|
|
478
|
+
"roomId": "629cb9accf2af03a0da629f4cf0e2a8a88d2e127208116f0e849c107e21c51f6",
|
|
479
|
+
"authority": "66df4b7febed3972515d9f663fe00a8ef9b2c69fbcb6bee3f5587b5d0b96605e",
|
|
480
|
+
"authoritySkHex": "a090036fcabc0a442fc1eaa5afc5c7ddda6f95c6bf8fe1f7b3b69589e621d643",
|
|
481
|
+
"previous": {
|
|
482
|
+
"epoch": 1,
|
|
483
|
+
"secretHex": "0f01eb2bc987461c1d130d1fd592156e3098a2f970dfd67057f5eeaa4bf812e4"
|
|
484
|
+
},
|
|
485
|
+
"next": {
|
|
486
|
+
"epoch": 2,
|
|
487
|
+
"secretHex": "9fdaac66de22f73960879abf83e9065bc882ba84440800c96418b27e4dfaec05"
|
|
488
|
+
},
|
|
489
|
+
"recipients": [
|
|
490
|
+
"b7229740b568be30f7307667afc9d23a292b9efa8dffbc6dbfc4a014048fb797"
|
|
491
|
+
],
|
|
492
|
+
"deviceSkHex": "2ace7e7b383f931a0d45b2bc74df1262d356ec4a7137d88792e89b664828d698",
|
|
493
|
+
"createdAt": 1800003600,
|
|
494
|
+
"event": {
|
|
495
|
+
"id": "37458191b69ad786b091c3b695507a52a0b8596431f286d7a44daf91b7a7398a",
|
|
496
|
+
"pubkey": "66df4b7febed3972515d9f663fe00a8ef9b2c69fbcb6bee3f5587b5d0b96605e",
|
|
497
|
+
"created_at": 1800003600,
|
|
498
|
+
"kind": 1462,
|
|
499
|
+
"tags": [
|
|
500
|
+
[
|
|
501
|
+
"d",
|
|
502
|
+
"629cb9accf2af03a0da629f4cf0e2a8a88d2e127208116f0e849c107e21c51f6"
|
|
503
|
+
],
|
|
504
|
+
[
|
|
505
|
+
"epoch",
|
|
506
|
+
"2"
|
|
507
|
+
]
|
|
508
|
+
],
|
|
509
|
+
"content": "AhOnbBRNMDzM9miIeGKbl2Dua0UpbT7Ifq5pljxTcm/R4wocpZDmpbWrmCHysCzurnZABNn7QFp3ZzwJzSRv7zyQlWFjWaNHEi0W4yYV3cjp3EE4Sfq+iPy8bKAmXjq2VDqlnVoiV1VMSsJN3pivf/gviJ3SJX18QZUR0XHMN0hZ0C41InAxa5whdgycHfKNHoRP7cVh6Gan3JBRU06GCAQcSQ==",
|
|
510
|
+
"sig": "781c78fc9fc9ec22b9b0eb37110a4794f27fef05bba9ae0c99323bed3c6f61c546dee16dc19fb37382c93e0dff3345c28f1cb2f4e9411c61811d820c1dbe6f1d"
|
|
511
|
+
},
|
|
512
|
+
"randomHex": [
|
|
513
|
+
"13a76c144d303cccf6688878629b9760ee6b45296d3ec87eae69963c53726fd1",
|
|
514
|
+
"3b0382104a935d062308889ecba5aca4d961b92670de5a7c0940e1415d0c7c30"
|
|
515
|
+
],
|
|
516
|
+
"unflagged": {
|
|
517
|
+
"event": {
|
|
518
|
+
"id": "88c5d00afcdba39ed0f771642f18ff390168509116cedf1e6bf6f3993fc79290",
|
|
519
|
+
"pubkey": "66df4b7febed3972515d9f663fe00a8ef9b2c69fbcb6bee3f5587b5d0b96605e",
|
|
520
|
+
"created_at": 1800003600,
|
|
521
|
+
"kind": 1462,
|
|
522
|
+
"tags": [
|
|
523
|
+
[
|
|
524
|
+
"d",
|
|
525
|
+
"629cb9accf2af03a0da629f4cf0e2a8a88d2e127208116f0e849c107e21c51f6"
|
|
526
|
+
],
|
|
527
|
+
[
|
|
528
|
+
"epoch",
|
|
529
|
+
"2"
|
|
530
|
+
]
|
|
531
|
+
],
|
|
532
|
+
"content": "AhOnbBRNMDzM9miIeGKbl2Dua0UpbT7Ifq5pljxTcm/R43ocpZDmpbWrmCHysCzurnZABNn7QFp3ZzwJzSRv7zyQlWFjWaNHEi0W4yYV3cjm3Es/GbWmgaOGGNJTOxaUP1/cxa5YK7MiGMSmucDORDd1IQZy1aTeyii0eGDaRCofQvA=",
|
|
533
|
+
"sig": "cd0c9a216f9d46ffca874bf5aed2c64d5216b2e36b87b0900c588fcd00d833bbe0698f2e7cc46ef96e9988277beaa1028f777cd6d59f8bfb2c4fb4d570ab69d2"
|
|
534
|
+
},
|
|
535
|
+
"randomHex": [
|
|
536
|
+
"13a76c144d303cccf6688878629b9760ee6b45296d3ec87eae69963c53726fd1",
|
|
537
|
+
"3b0382104a935d062308889ecba5aca4d961b92670de5a7c0940e1415d0c7c30"
|
|
538
|
+
]
|
|
539
|
+
}
|
|
540
|
+
},
|
|
541
|
+
"output": {
|
|
542
|
+
"bodyJson": "{\"v\":1,\"epoch\":2,\"removed\":[],\"closed\":true,\"destruct\":true,\"keys\":{}}",
|
|
543
|
+
"unflaggedBodyJson": "{\"v\":1,\"epoch\":2,\"removed\":[],\"closed\":true,\"keys\":{}}",
|
|
544
|
+
"notice": {
|
|
545
|
+
"epoch": 2,
|
|
546
|
+
"removed": [],
|
|
547
|
+
"closed": true,
|
|
548
|
+
"destruct": true,
|
|
549
|
+
"at": 1800003600
|
|
550
|
+
},
|
|
551
|
+
"evidence": {
|
|
552
|
+
"epoch": 2,
|
|
553
|
+
"removed": [],
|
|
554
|
+
"closed": true,
|
|
555
|
+
"destruct": true
|
|
556
|
+
},
|
|
557
|
+
"unflaggedNotice": {
|
|
558
|
+
"epoch": 2,
|
|
559
|
+
"removed": [],
|
|
560
|
+
"closed": true,
|
|
561
|
+
"at": 1800003600
|
|
562
|
+
},
|
|
563
|
+
"oldReader": {
|
|
564
|
+
"epoch": 2,
|
|
565
|
+
"removed": [],
|
|
566
|
+
"closed": true,
|
|
567
|
+
"at": 1800003600
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
},
|
|
571
|
+
{
|
|
572
|
+
"name": "destruct-rekey-open",
|
|
573
|
+
"kind": "negative",
|
|
574
|
+
"note": "Two rekeys from epoch 1 to 2, signed by the authority, whose bodies carry `destruct` without `closed`: beside a removal (`withRemoval`) and beside the scheduled marker (`withScheduled`). The encoder refuses both (`encoder`), so they are built by hand (`bodyJson`, then `randomHex`: the body nonce, the aux-rand). A reader still reads each rekey, so the removal is announced and the device moves on, and does not believe the flag: it is absent from `notice` and `evidence`.",
|
|
575
|
+
"input": {
|
|
576
|
+
"roomId": "629cb9accf2af03a0da629f4cf0e2a8a88d2e127208116f0e849c107e21c51f6",
|
|
577
|
+
"authority": "66df4b7febed3972515d9f663fe00a8ef9b2c69fbcb6bee3f5587b5d0b96605e",
|
|
578
|
+
"previous": {
|
|
579
|
+
"epoch": 1,
|
|
580
|
+
"secretHex": "0f01eb2bc987461c1d130d1fd592156e3098a2f970dfd67057f5eeaa4bf812e4"
|
|
581
|
+
},
|
|
582
|
+
"deviceSkHex": "2ace7e7b383f931a0d45b2bc74df1262d356ec4a7137d88792e89b664828d698",
|
|
583
|
+
"withRemoval": {
|
|
584
|
+
"event": {
|
|
585
|
+
"id": "86e6fd76b5ffd82d455130760697f4b81022123750803cfa2d40a6751579ec88",
|
|
586
|
+
"pubkey": "66df4b7febed3972515d9f663fe00a8ef9b2c69fbcb6bee3f5587b5d0b96605e",
|
|
587
|
+
"created_at": 1800000000,
|
|
588
|
+
"kind": 1462,
|
|
589
|
+
"tags": [
|
|
590
|
+
[
|
|
591
|
+
"d",
|
|
592
|
+
"629cb9accf2af03a0da629f4cf0e2a8a88d2e127208116f0e849c107e21c51f6"
|
|
593
|
+
],
|
|
594
|
+
[
|
|
595
|
+
"epoch",
|
|
596
|
+
"2"
|
|
597
|
+
]
|
|
598
|
+
],
|
|
599
|
+
"content": "Apee+KxMVIt4qxTDWlRzJE+t5N2mWq+KOdlTakLIH3L2Z6ibR4g0cAOAuPPHVtmavPV9m5xySfg3jBwV3bG6mdoSTKbzURzy0WvBRNjVKL8xovNTae2nMMxN5Pe6G27gnHpJ7Rd/zQtiTT0VlLLvPpuxLZAhuPhMGh73N8Lx3qeuCquspdQ7vab5Y3qAOEHTNIzN5gMYao9m7+zNjDjPp7HfeeWuA1wbe4XAz/xYEacvP2UypRVIL8UtOhJggFHzbIKB",
|
|
600
|
+
"sig": "8d4f94c1500929bacbb060760e5eadecabdb04ef15ae88de97af3ca3fc10803346d5de8baf2c3afd2087cc341d9ceed8c0bb2de40cf51eabaff950a35d81dd65"
|
|
601
|
+
},
|
|
602
|
+
"randomHex": [
|
|
603
|
+
"979ef8ac4c548b78ab14c35a5473244fade4dda65aaf8a39d9536a42c81f72f6",
|
|
604
|
+
"9749a08bd8414bac8d9cd070954da2e0f3e879b0221a0da9506576e56ab0e04c"
|
|
605
|
+
],
|
|
606
|
+
"bodyJson": "{\"v\":1,\"epoch\":2,\"removed\":[\"e795ed3fc0ba9cd6635f68e50a6123c15fb0b947b4030ae40b2768b08e27b827\"],\"destruct\":true,\"keys\":{}}"
|
|
607
|
+
},
|
|
608
|
+
"withScheduled": {
|
|
609
|
+
"event": {
|
|
610
|
+
"id": "ec2c2987c0a28287e39b35de0ff7bf247640e061c46fd8a049ebb76932e1e584",
|
|
611
|
+
"pubkey": "66df4b7febed3972515d9f663fe00a8ef9b2c69fbcb6bee3f5587b5d0b96605e",
|
|
612
|
+
"created_at": 1800000000,
|
|
613
|
+
"kind": 1462,
|
|
614
|
+
"tags": [
|
|
615
|
+
[
|
|
616
|
+
"d",
|
|
617
|
+
"629cb9accf2af03a0da629f4cf0e2a8a88d2e127208116f0e849c107e21c51f6"
|
|
618
|
+
],
|
|
619
|
+
[
|
|
620
|
+
"epoch",
|
|
621
|
+
"2"
|
|
622
|
+
]
|
|
623
|
+
],
|
|
624
|
+
"content": "AoH8yCso6ZNKjV9SGxSnVlzR7LBTCbHgXvGBp1BdAEwp67WbwBnUhdIYTE3OJMrwTRKpkbHSAbSL/HuLaXKNQ6QauW0MGXITkcOTX6ASQM2LMMtHHI7qP0xh8aAxUUzZWlB2M6k9A0Zdp1g0XQDo1Zq5ag4XEHoPmz++SnbM1APZs+ymM6U2bGEcgb4HZ9FVpGxZ/+LgM09t7uv+NQgLlwIwIA==",
|
|
625
|
+
"sig": "816c0323a3dbd9a5d7a40096b500bf62534b4a8909c14723ea27469a9c10be613b89d83e0176729c3cf45494b62d89e809c112e5385518d3ca0085e0cad44018"
|
|
626
|
+
},
|
|
627
|
+
"randomHex": [
|
|
628
|
+
"81fcc82b28e9934a8d5f521b14a7565cd1ecb05309b1e05ef181a7505d004c29",
|
|
629
|
+
"bb35e9d71648525a76693a2eb68580502684d0456c67c66d37eb0136343d9911"
|
|
630
|
+
],
|
|
631
|
+
"bodyJson": "{\"v\":1,\"epoch\":2,\"removed\":[],\"destruct\":true,\"scheduled\":true,\"keys\":{}}"
|
|
632
|
+
}
|
|
633
|
+
},
|
|
634
|
+
"output": {
|
|
635
|
+
"encoder": {
|
|
636
|
+
"withRemoval": "refused",
|
|
637
|
+
"withScheduled": "refused"
|
|
638
|
+
},
|
|
639
|
+
"withRemoval": {
|
|
640
|
+
"notice": {
|
|
641
|
+
"epoch": 2,
|
|
642
|
+
"removed": [
|
|
643
|
+
"e795ed3fc0ba9cd6635f68e50a6123c15fb0b947b4030ae40b2768b08e27b827"
|
|
644
|
+
],
|
|
645
|
+
"closed": false,
|
|
646
|
+
"at": 1800000000
|
|
647
|
+
},
|
|
648
|
+
"evidence": {
|
|
649
|
+
"epoch": 2,
|
|
650
|
+
"removed": [
|
|
651
|
+
"e795ed3fc0ba9cd6635f68e50a6123c15fb0b947b4030ae40b2768b08e27b827"
|
|
652
|
+
],
|
|
653
|
+
"closed": false
|
|
654
|
+
}
|
|
655
|
+
},
|
|
656
|
+
"withScheduled": {
|
|
657
|
+
"notice": {
|
|
658
|
+
"epoch": 2,
|
|
659
|
+
"removed": [],
|
|
660
|
+
"closed": false,
|
|
661
|
+
"scheduled": true,
|
|
662
|
+
"at": 1800000000
|
|
663
|
+
},
|
|
664
|
+
"evidence": {
|
|
665
|
+
"epoch": 2,
|
|
666
|
+
"removed": [],
|
|
667
|
+
"closed": false,
|
|
668
|
+
"scheduled": true
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
]
|
|
674
|
+
}
|
|
675
|
+
}
|