@weaveprotocol/core 0.1.2 → 0.2.1

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 (199) hide show
  1. package/README.md +322 -45
  2. package/dist/doors/doors.d.ts +139 -0
  3. package/dist/doors/doors.d.ts.map +1 -0
  4. package/dist/doors/doors.js +210 -0
  5. package/dist/doors/doors.js.map +1 -0
  6. package/dist/doors/index.d.ts +9 -0
  7. package/dist/doors/index.d.ts.map +1 -0
  8. package/dist/doors/index.js +7 -0
  9. package/dist/doors/index.js.map +1 -0
  10. package/dist/identity/contact-key.d.ts +68 -0
  11. package/dist/identity/contact-key.d.ts.map +1 -0
  12. package/dist/identity/contact-key.js +185 -0
  13. package/dist/identity/contact-key.js.map +1 -0
  14. package/dist/index.d.ts +16 -7
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +10 -5
  17. package/dist/index.js.map +1 -1
  18. package/dist/network/index.d.ts +2 -0
  19. package/dist/network/index.d.ts.map +1 -1
  20. package/dist/network/index.js +1 -0
  21. package/dist/network/index.js.map +1 -1
  22. package/dist/network/mailbox.d.ts +49 -0
  23. package/dist/network/mailbox.d.ts.map +1 -0
  24. package/dist/network/mailbox.js +125 -0
  25. package/dist/network/mailbox.js.map +1 -0
  26. package/dist/network/mesh.d.ts +6 -0
  27. package/dist/network/mesh.d.ts.map +1 -1
  28. package/dist/network/mesh.js +11 -1
  29. package/dist/network/mesh.js.map +1 -1
  30. package/dist/network/multi-signaling.d.ts +12 -2
  31. package/dist/network/multi-signaling.d.ts.map +1 -1
  32. package/dist/network/multi-signaling.js +86 -14
  33. package/dist/network/multi-signaling.js.map +1 -1
  34. package/dist/network/peer-auth.d.ts +50 -16
  35. package/dist/network/peer-auth.d.ts.map +1 -1
  36. package/dist/network/peer-auth.js +52 -15
  37. package/dist/network/peer-auth.js.map +1 -1
  38. package/dist/node/carrier.d.ts +87 -0
  39. package/dist/node/carrier.d.ts.map +1 -1
  40. package/dist/node/carrier.js +180 -59
  41. package/dist/node/carrier.js.map +1 -1
  42. package/dist/node/copy.d.ts.map +1 -1
  43. package/dist/node/copy.js +6 -3
  44. package/dist/node/copy.js.map +1 -1
  45. package/dist/node/host.d.ts +117 -0
  46. package/dist/node/host.d.ts.map +1 -0
  47. package/dist/node/host.js +192 -0
  48. package/dist/node/host.js.map +1 -0
  49. package/dist/node/index.d.ts +6 -2
  50. package/dist/node/index.d.ts.map +1 -1
  51. package/dist/node/index.js +1 -0
  52. package/dist/node/index.js.map +1 -1
  53. package/dist/node/node.d.ts.map +1 -1
  54. package/dist/node/node.js +958 -25
  55. package/dist/node/node.js.map +1 -1
  56. package/dist/node/space-runtime.d.ts +42 -25
  57. package/dist/node/space-runtime.d.ts.map +1 -1
  58. package/dist/node/space-runtime.js +734 -35
  59. package/dist/node/space-runtime.js.map +1 -1
  60. package/dist/node/types.d.ts +375 -3
  61. package/dist/node/types.d.ts.map +1 -1
  62. package/dist/privacy/space-encryption.d.ts +16 -0
  63. package/dist/privacy/space-encryption.d.ts.map +1 -1
  64. package/dist/privacy/space-encryption.js +40 -0
  65. package/dist/privacy/space-encryption.js.map +1 -1
  66. package/dist/query/engine.js +1 -1
  67. package/dist/query/engine.js.map +1 -1
  68. package/dist/query/types.d.ts +7 -0
  69. package/dist/query/types.d.ts.map +1 -1
  70. package/dist/query/types.js.map +1 -1
  71. package/dist/react/use-query.d.ts +1 -1
  72. package/dist/react/use-query.d.ts.map +1 -1
  73. package/dist/records/topics.d.ts +21 -0
  74. package/dist/records/topics.d.ts.map +1 -0
  75. package/dist/records/topics.js +86 -0
  76. package/dist/records/topics.js.map +1 -0
  77. package/dist/schema/collection-def.d.ts +7 -0
  78. package/dist/schema/collection-def.d.ts.map +1 -1
  79. package/dist/schema/collection-def.js +4 -0
  80. package/dist/schema/collection-def.js.map +1 -1
  81. package/dist/schema/expression.d.ts +2 -0
  82. package/dist/schema/expression.d.ts.map +1 -1
  83. package/dist/schema/expression.js +1 -0
  84. package/dist/schema/expression.js.map +1 -1
  85. package/dist/schemas/contacts.d.ts +214 -0
  86. package/dist/schemas/contacts.d.ts.map +1 -0
  87. package/dist/schemas/contacts.js +98 -0
  88. package/dist/schemas/contacts.js.map +1 -0
  89. package/dist/schemas/index.d.ts +2 -0
  90. package/dist/schemas/index.d.ts.map +1 -1
  91. package/dist/schemas/index.js +1 -0
  92. package/dist/schemas/index.js.map +1 -1
  93. package/dist/session/auth.d.ts.map +1 -1
  94. package/dist/session/auth.js +15 -3
  95. package/dist/session/auth.js.map +1 -1
  96. package/dist/session/connect.d.ts +25 -1
  97. package/dist/session/connect.d.ts.map +1 -1
  98. package/dist/session/connect.js +9 -2
  99. package/dist/session/connect.js.map +1 -1
  100. package/dist/session/hosting.d.ts +155 -0
  101. package/dist/session/hosting.d.ts.map +1 -0
  102. package/dist/session/hosting.js +160 -0
  103. package/dist/session/hosting.js.map +1 -0
  104. package/dist/space/account-registry.d.ts +6 -0
  105. package/dist/space/account-registry.d.ts.map +1 -1
  106. package/dist/space/account-registry.js +16 -4
  107. package/dist/space/account-registry.js.map +1 -1
  108. package/dist/space/notify.d.ts +88 -0
  109. package/dist/space/notify.d.ts.map +1 -0
  110. package/dist/space/notify.js +127 -0
  111. package/dist/space/notify.js.map +1 -0
  112. package/dist/space/pass.d.ts +6 -0
  113. package/dist/space/pass.d.ts.map +1 -1
  114. package/dist/space/pass.js +5 -2
  115. package/dist/space/pass.js.map +1 -1
  116. package/dist/space/roles.d.ts +71 -0
  117. package/dist/space/roles.d.ts.map +1 -1
  118. package/dist/space/roles.js +114 -0
  119. package/dist/space/roles.js.map +1 -1
  120. package/dist/space/space-access.d.ts +24 -0
  121. package/dist/space/space-access.d.ts.map +1 -1
  122. package/dist/space/space-access.js +24 -0
  123. package/dist/space/space-access.js.map +1 -1
  124. package/dist/space/space-manager.d.ts +35 -1
  125. package/dist/space/space-manager.d.ts.map +1 -1
  126. package/dist/space/space-manager.js +72 -25
  127. package/dist/space/space-manager.js.map +1 -1
  128. package/dist/storage/blob/memory.d.ts +9 -0
  129. package/dist/storage/blob/memory.d.ts.map +1 -0
  130. package/dist/storage/blob/memory.js +20 -0
  131. package/dist/storage/blob/memory.js.map +1 -0
  132. package/dist/storage/blob/s3.d.ts +16 -0
  133. package/dist/storage/blob/s3.d.ts.map +1 -0
  134. package/dist/storage/blob/s3.js +86 -0
  135. package/dist/storage/blob/s3.js.map +1 -0
  136. package/dist/storage/blob-store.d.ts +26 -0
  137. package/dist/storage/blob-store.d.ts.map +1 -0
  138. package/dist/storage/blob-store.js +2 -0
  139. package/dist/storage/blob-store.js.map +1 -0
  140. package/dist/storage/encrypted-adapter.d.ts +3 -3
  141. package/dist/storage/encrypted-adapter.js +3 -3
  142. package/dist/storage/folder-adapter.d.ts +8 -8
  143. package/dist/storage/folder-adapter.d.ts.map +1 -1
  144. package/dist/storage/folder-adapter.js +7 -7
  145. package/dist/storage/folder-reconcile.d.ts +12 -14
  146. package/dist/storage/folder-reconcile.d.ts.map +1 -1
  147. package/dist/storage/folder-reconcile.js +20 -14
  148. package/dist/storage/folder-reconcile.js.map +1 -1
  149. package/dist/storage/index.d.ts +0 -1
  150. package/dist/storage/index.d.ts.map +1 -1
  151. package/dist/storage/index.js +0 -1
  152. package/dist/storage/index.js.map +1 -1
  153. package/dist/storage/indexeddb-adapter.d.ts.map +1 -1
  154. package/dist/storage/indexeddb-adapter.js +8 -9
  155. package/dist/storage/indexeddb-adapter.js.map +1 -1
  156. package/dist/storage/mirror.d.ts +68 -0
  157. package/dist/storage/mirror.d.ts.map +1 -0
  158. package/dist/storage/mirror.js +174 -0
  159. package/dist/storage/mirror.js.map +1 -0
  160. package/dist/storage/segment.d.ts +20 -0
  161. package/dist/storage/segment.d.ts.map +1 -0
  162. package/dist/storage/segment.js +27 -0
  163. package/dist/storage/segment.js.map +1 -0
  164. package/dist/storage/storage-provider.d.ts +36 -40
  165. package/dist/storage/storage-provider.d.ts.map +1 -1
  166. package/dist/storage/storage-provider.js +208 -117
  167. package/dist/storage/storage-provider.js.map +1 -1
  168. package/dist/sync/index.d.ts +1 -1
  169. package/dist/sync/index.d.ts.map +1 -1
  170. package/dist/sync/index.js +1 -1
  171. package/dist/sync/index.js.map +1 -1
  172. package/dist/sync/negentropy.d.ts +68 -0
  173. package/dist/sync/negentropy.d.ts.map +1 -0
  174. package/dist/sync/negentropy.js +379 -0
  175. package/dist/sync/negentropy.js.map +1 -0
  176. package/dist/sync/sync-engine.d.ts +45 -13
  177. package/dist/sync/sync-engine.d.ts.map +1 -1
  178. package/dist/sync/sync-engine.js +290 -207
  179. package/dist/sync/sync-engine.js.map +1 -1
  180. package/dist/sync/sync-messages.d.ts +42 -32
  181. package/dist/sync/sync-messages.d.ts.map +1 -1
  182. package/dist/sync/sync-messages.js +1 -1
  183. package/dist/sync/sync-messages.js.map +1 -1
  184. package/dist/types.d.ts +9 -0
  185. package/dist/types.d.ts.map +1 -1
  186. package/dist/types.js.map +1 -1
  187. package/dist/utils/hash.d.ts +9 -0
  188. package/dist/utils/hash.d.ts.map +1 -1
  189. package/dist/utils/hash.js +33 -0
  190. package/dist/utils/hash.js.map +1 -1
  191. package/package.json +8 -3
  192. package/dist/storage/mst.d.ts +0 -121
  193. package/dist/storage/mst.d.ts.map +0 -1
  194. package/dist/storage/mst.js +0 -402
  195. package/dist/storage/mst.js.map +0 -1
  196. package/dist/sync/anti-entropy.d.ts +0 -49
  197. package/dist/sync/anti-entropy.d.ts.map +0 -1
  198. package/dist/sync/anti-entropy.js +0 -62
  199. package/dist/sync/anti-entropy.js.map +0 -1
@@ -0,0 +1,139 @@
1
+ /**
2
+ * @module doors
3
+ * Doors: how someone you share no space with can ask to become your contact.
4
+ *
5
+ * A DID is a name, not an address — knowing it must not be enough to reach
6
+ * you. A **door** is an address you hand out on purpose, and can close:
7
+ *
8
+ * - a **door key**, derived from your contact key and the door's id
9
+ * (`deriveDoorKeyBytes`), which says nothing about the account behind it,
10
+ * and a **signing key** beside it (`deriveDoorSignKeyBytes`) that proves
11
+ * ownership of the door — to a relay clearing its mailbox, and to a knocker
12
+ * when you answer;
13
+ * - the **relays** whose mailboxes hold knocks on it — two or three, chosen by
14
+ * you, so no one relay can shut it.
15
+ *
16
+ * Both travel in a **door code** (a link, a QR code, a line in a bio). Someone
17
+ * with it **knocks**: makes a private space for the two of you, and leaves its
18
+ * invite, sealed to the door key, in the door's mailboxes. The knock is signed
19
+ * by the knocker's session key under their account's note, like a record, so
20
+ * it proves who knocked before anyone joins anything. Opening the door is
21
+ * joining that space.
22
+ *
23
+ * ```
24
+ * code = base64url(JSON { v: 1, key, sign, relays, name? })
25
+ * topic = base64url(SHA-256("weave/door-topic/v1|" + sign))
26
+ * knock = sealFor(key, { body, sig }, "weave/knock/v1|" + key)
27
+ * body = { v: 1, door: key, from, name, invite, note?, at, session, proof }
28
+ * sig = session key signs canonical(body)
29
+ * ```
30
+ *
31
+ * The relay sees a topic and a sealed blob: not whose door it is, not who
32
+ * knocked, not what they said. See `docs/spec/07-doors.md`.
33
+ */
34
+ import type { CryptoProvider } from '../types.js';
35
+ /** A door names at most this many relays: enough that one going away doesn't matter */
36
+ export declare const MAX_DOOR_RELAYS = 3;
37
+ /** How long a knock waits in a mailbox, and so how old one may be when opened */
38
+ export declare const KNOCK_TTL_SECONDS: number;
39
+ /**
40
+ * How far a knock's own time may be from when the relay took it. A knock is
41
+ * dropped as soon as it is signed, so its time is checked against the relay's
42
+ * — which the knocker can't choose — and a note that ran out can't be used by
43
+ * dating a knock back to when it was good.
44
+ */
45
+ export declare const KNOCK_DROP_WINDOW_SECONDS = 600;
46
+ /** What a door code says: where to knock, and whose door the owner says it is */
47
+ export interface DoorCode {
48
+ readonly v: 1;
49
+ /** The door key's public half: a compressed P-256 point, base64url. Knocks are sealed to it. */
50
+ readonly key: string;
51
+ /** The door's signing key's public half, likewise. Its hash is the door's topic. */
52
+ readonly sign: string;
53
+ /** Relays whose mailboxes hold knocks on it, 1–3 */
54
+ readonly relays: ReadonlyArray<string>;
55
+ /** Who the owner says they are — shown to the knocker, and proves nothing */
56
+ readonly name?: string;
57
+ }
58
+ /** What a knock carries, signed by the knocker's session key */
59
+ export interface KnockBody {
60
+ readonly v: 1;
61
+ /** The door knocked on: its key. Binds the knock to this door. */
62
+ readonly door: string;
63
+ /** The knocker's account */
64
+ readonly from: string;
65
+ /** The name they give */
66
+ readonly name: string;
67
+ /** The invite to the space for two they made */
68
+ readonly invite: string;
69
+ readonly note?: string;
70
+ /** When it was signed, Unix seconds */
71
+ readonly at: number;
72
+ /** The session key that signed it */
73
+ readonly session: string;
74
+ /** The note from `from` to `session`: a UCAN whose chain ends at `from` */
75
+ readonly proof: string;
76
+ }
77
+ /** A knock that opened and checked out */
78
+ export interface OpenedKnock {
79
+ readonly from: string;
80
+ readonly name: string;
81
+ readonly note?: string;
82
+ readonly invite: string;
83
+ /** The id of the space for two */
84
+ readonly pairSpace: string;
85
+ /** When it was signed, ms */
86
+ readonly at: number;
87
+ }
88
+ /** Cuts text to at most `max` characters without splitting one (a surrogate pair stays whole) */
89
+ export declare function clip(text: string, max: number): string;
90
+ /** Encodes a door code: what goes in a link or a QR code */
91
+ export declare function encodeDoorCode(code: Omit<DoorCode, 'v'>): string;
92
+ /**
93
+ * Reads a door code, or a link carrying one after `#door=` or `door=`.
94
+ * @throws When it isn't one, saying why
95
+ */
96
+ export declare function parseDoorCode(text: string): DoorCode;
97
+ /** Why a value is not a door code, or null */
98
+ export declare function checkDoorCode(value: unknown): string | null;
99
+ /**
100
+ * The mailbox topic of a door: a hash of its signing key. The relay can't tell
101
+ * whose door it is, and can check that whoever clears it holds that key.
102
+ */
103
+ export declare function doorTopic(sign: string): Promise<string>;
104
+ /**
105
+ * What a door's owner signs to clear knocks from a relay's mailbox: the topic,
106
+ * the relay's one-time challenge, and which knocks (`*` for all of them).
107
+ */
108
+ export declare const purgeMessage: (topic: string, nonce: string, ids: ReadonlyArray<string> | null) => Uint8Array<ArrayBufferLike>;
109
+ /** Signs a relay's purge challenge with the door's signing key */
110
+ export declare function signPurge(signKey: Uint8Array, topic: string, nonce: string, ids: ReadonlyArray<string> | null): Promise<string>;
111
+ export declare function signAnswer(signKey: Uint8Array, pairSpace: string, did: string): Promise<string>;
112
+ export declare function checkAnswer(sign: string, pairSpace: string, did: string, signature: string): Promise<boolean>;
113
+ /** A knock's id: the hash of its sealed blob, as relays file it */
114
+ export declare function knockId(blob: string): Promise<string>;
115
+ /**
116
+ * Makes a knock: the body, signed by the session key, sealed to the door key.
117
+ * @returns The sealed blob, for relays' mailboxes
118
+ */
119
+ export declare function sealKnock(door: string, knock: {
120
+ readonly from: string;
121
+ readonly name: string;
122
+ readonly invite: string;
123
+ readonly note?: string;
124
+ }, session: {
125
+ readonly did: string;
126
+ readonly key: CryptoKey;
127
+ readonly proof: string;
128
+ }, provider: CryptoProvider): Promise<string>;
129
+ /**
130
+ * Opens a knock left on a door, and checks it through: sealed to this door;
131
+ * signed by a session key that its account's note vouches for, for the whole
132
+ * account and not by an agent; signed when the relay took it; recent; and
133
+ * carrying an invite to a private space that account made.
134
+ * @param doorKey The door key's private scalar (`deriveDoorKeyBytes`)
135
+ * @param receivedAt When the relay took it, ms, as `fetch` says
136
+ * @returns The knock, or null when it is anything less
137
+ */
138
+ export declare function openKnock(doorKey: Uint8Array, blob: string, receivedAt: number, provider: CryptoProvider): Promise<OpenedKnock | null>;
139
+ //# sourceMappingURL=doors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doors.d.ts","sourceRoot":"","sources":["../../src/doors/doors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,210 @@
1
+ import { contactKeyPair, contactPublicKey, isContactPublicKey, openSealed, sealFor, signWithScalar, verifyWithPoint } from '../identity/contact-key.js';
2
+ import { didToPublicKey } from '../identity/did.js';
3
+ import { resolveDelegationRoot, UCAN_CLOCK_SKEW_SECONDS } from '../identity/ucan.js';
4
+ import { isAgentNote } from '../identity/agent-note.js';
5
+ import { canonicalize } from '../schema/expression.js';
6
+ import { parseSpaceInvite } from '../space/space-manager.js';
7
+ import { checkSpace } from '../space/space-access.js';
8
+ import { checkRelays } from '../space/roles.js';
9
+ import { sha256 } from '../utils/hash.js';
10
+ import { base64UrlDecode, base64UrlEncode, utf8Decode, utf8Encode } from '../utils/encoding.js';
11
+ /** A door names at most this many relays: enough that one going away doesn't matter */
12
+ export const MAX_DOOR_RELAYS = 3;
13
+ /** How long a knock waits in a mailbox, and so how old one may be when opened */
14
+ export const KNOCK_TTL_SECONDS = 14 * 24 * 3600;
15
+ /**
16
+ * How far a knock's own time may be from when the relay took it. A knock is
17
+ * dropped as soon as it is signed, so its time is checked against the relay's
18
+ * — which the knocker can't choose — and a note that ran out can't be used by
19
+ * dating a knock back to when it was good.
20
+ */
21
+ export const KNOCK_DROP_WINDOW_SECONDS = 600;
22
+ const MAX_NAME = 64;
23
+ const MAX_NOTE = 2000;
24
+ const MAX_INVITE = 6000;
25
+ const MAX_PROOF = 4096;
26
+ /** Cuts text to at most `max` characters without splitting one (a surrogate pair stays whole) */
27
+ export function clip(text, max) {
28
+ const chars = Array.from(text);
29
+ return chars.length <= max ? text : chars.slice(0, max).join('');
30
+ }
31
+ /** Encodes a door code: what goes in a link or a QR code */
32
+ export function encodeDoorCode(code) {
33
+ const problem = checkDoorCode({ v: 1, ...code });
34
+ if (problem)
35
+ throw new Error(problem);
36
+ return base64UrlEncode(utf8Encode(canonicalize({ v: 1, key: code.key, sign: code.sign, relays: [...code.relays], ...(code.name ? { name: code.name } : {}) })));
37
+ }
38
+ /**
39
+ * Reads a door code, or a link carrying one after `#door=` or `door=`.
40
+ * @throws When it isn't one, saying why
41
+ */
42
+ export function parseDoorCode(text) {
43
+ const trimmed = text.trim();
44
+ const found = /(?:^|[#?&])door=([A-Za-z0-9_-]+)/.exec(trimmed);
45
+ const raw = found ? found[1] : trimmed;
46
+ let parsed;
47
+ try {
48
+ parsed = JSON.parse(utf8Decode(base64UrlDecode(raw)));
49
+ }
50
+ catch {
51
+ throw new Error('That is not a door code — it may be cut short.');
52
+ }
53
+ const problem = checkDoorCode(parsed);
54
+ if (problem)
55
+ throw new Error(`That door code doesn't work: ${problem}`);
56
+ const code = parsed;
57
+ return Object.freeze({ v: 1, key: code.key, sign: code.sign, relays: Object.freeze([...code.relays]), ...(code.name ? { name: code.name } : {}) });
58
+ }
59
+ /** Why a value is not a door code, or null */
60
+ export function checkDoorCode(value) {
61
+ const code = value;
62
+ if (!code || typeof code !== 'object' || code.v !== 1)
63
+ return 'it is not a version 1 door';
64
+ if (!isContactPublicKey(code.key))
65
+ return 'its key is not a P-256 public key';
66
+ if (!isContactPublicKey(code.sign) || code.sign === code.key)
67
+ return 'its signing key is not a P-256 public key of its own';
68
+ if (!Array.isArray(code.relays) || code.relays.length === 0 || code.relays.length > MAX_DOOR_RELAYS) {
69
+ return `it names 1–${MAX_DOOR_RELAYS} relays`;
70
+ }
71
+ const relays = checkRelays(code.relays);
72
+ if (relays)
73
+ return relays;
74
+ if (code.name !== undefined && (typeof code.name !== 'string' || Array.from(code.name).length > MAX_NAME))
75
+ return `its name is text of at most ${MAX_NAME} characters`;
76
+ return null;
77
+ }
78
+ /**
79
+ * The mailbox topic of a door: a hash of its signing key. The relay can't tell
80
+ * whose door it is, and can check that whoever clears it holds that key.
81
+ */
82
+ export async function doorTopic(sign) {
83
+ return base64UrlEncode(await sha256(utf8Encode(`weave/door-topic/v1|${sign}`)));
84
+ }
85
+ /**
86
+ * What a door's owner signs to clear knocks from a relay's mailbox: the topic,
87
+ * the relay's one-time challenge, and which knocks (`*` for all of them).
88
+ */
89
+ export const purgeMessage = (topic, nonce, ids) => utf8Encode(`weave/door-purge/v1|${topic}|${nonce}|${ids ? [...ids].sort().join(',') : '*'}`);
90
+ /** Signs a relay's purge challenge with the door's signing key */
91
+ export function signPurge(signKey, topic, nonce, ids) {
92
+ return signWithScalar(signKey, purgeMessage(topic, nonce, ids));
93
+ }
94
+ /**
95
+ * The answer to a knock: the door's owner, signing with the door's signing key
96
+ * that the account which joined the space for two is theirs. Without it,
97
+ * whoever joined first — someone the invite was passed on to — would be taken
98
+ * for the person behind the door.
99
+ */
100
+ const answerMessage = (pairSpace, did) => utf8Encode(`weave/knock-answer/v1|${pairSpace}|${did}`);
101
+ export function signAnswer(signKey, pairSpace, did) {
102
+ return signWithScalar(signKey, answerMessage(pairSpace, did));
103
+ }
104
+ export function checkAnswer(sign, pairSpace, did, signature) {
105
+ return verifyWithPoint(sign, answerMessage(pairSpace, did), signature);
106
+ }
107
+ /** A knock's id: the hash of its sealed blob, as relays file it */
108
+ export async function knockId(blob) {
109
+ return base64UrlEncode(await sha256(utf8Encode(blob)));
110
+ }
111
+ const knockContext = (door) => `weave/knock/v1|${door}`;
112
+ /**
113
+ * Makes a knock: the body, signed by the session key, sealed to the door key.
114
+ * @returns The sealed blob, for relays' mailboxes
115
+ */
116
+ export async function sealKnock(door, knock, session, provider) {
117
+ const note = knock.note ? clip(knock.note.trim(), MAX_NOTE) : undefined;
118
+ const body = {
119
+ v: 1,
120
+ door,
121
+ from: knock.from,
122
+ name: clip(knock.name.trim(), MAX_NAME) || 'Someone',
123
+ invite: knock.invite,
124
+ ...(note ? { note } : {}),
125
+ at: Math.floor(Date.now() / 1000),
126
+ session: session.did,
127
+ proof: session.proof,
128
+ };
129
+ const sig = base64UrlEncode(await provider.sign(session.key, utf8Encode(canonicalize(body))));
130
+ return sealFor(door, { body, sig }, knockContext(door));
131
+ }
132
+ /**
133
+ * Opens a knock left on a door, and checks it through: sealed to this door;
134
+ * signed by a session key that its account's note vouches for, for the whole
135
+ * account and not by an agent; signed when the relay took it; recent; and
136
+ * carrying an invite to a private space that account made.
137
+ * @param doorKey The door key's private scalar (`deriveDoorKeyBytes`)
138
+ * @param receivedAt When the relay took it, ms, as `fetch` says
139
+ * @returns The knock, or null when it is anything less
140
+ */
141
+ export async function openKnock(doorKey, blob, receivedAt, provider) {
142
+ const door = contactPublicKey(doorKey);
143
+ const opened = (await openSealed((await contactKeyPair(doorKey)).privateKey, blob, knockContext(door)));
144
+ const body = opened?.body;
145
+ if (!body || typeof opened.sig !== 'string')
146
+ return null;
147
+ if (body.v !== 1 || body.door !== door)
148
+ return null;
149
+ if (typeof body.from !== 'string' || typeof body.session !== 'string' || typeof body.name !== 'string')
150
+ return null;
151
+ if (Array.from(body.name).length > MAX_NAME)
152
+ return null;
153
+ if (typeof body.invite !== 'string' || body.invite.length > MAX_INVITE)
154
+ return null;
155
+ if (typeof body.proof !== 'string' || body.proof.length > MAX_PROOF)
156
+ return null;
157
+ if (body.note !== undefined && (typeof body.note !== 'string' || Array.from(body.note).length > MAX_NOTE))
158
+ return null;
159
+ if (!Number.isSafeInteger(body.at) || !Number.isFinite(receivedAt))
160
+ return null;
161
+ const now = Math.floor(Date.now() / 1000);
162
+ if (body.at > now + UCAN_CLOCK_SKEW_SECONDS || body.at < now - KNOCK_TTL_SECONDS)
163
+ return null;
164
+ // Signed when it was dropped, not dated back to when a note was still good.
165
+ const dropped = Math.floor(receivedAt / 1000);
166
+ if (body.at > dropped + UCAN_CLOCK_SKEW_SECONDS || body.at < dropped - KNOCK_DROP_WINDOW_SECONDS)
167
+ return null;
168
+ // Signed by the session key it names…
169
+ let signed = false;
170
+ try {
171
+ const key = await provider.importPublicKey(didToPublicKey(body.session).publicKeyBytes);
172
+ signed = await provider.verify(key, base64UrlDecode(opened.sig), utf8Encode(canonicalize(body)));
173
+ }
174
+ catch {
175
+ return null;
176
+ }
177
+ if (!signed)
178
+ return null;
179
+ // …which the account it claims had delegated to when it signed. Agents never knock.
180
+ if (isAgentNote(body.proof))
181
+ return null;
182
+ const chain = await resolveDelegationRoot(body.proof, () => null, provider, { at: body.at }).catch(() => null);
183
+ if (!chain?.valid || chain.audience !== body.session || chain.rootDid !== body.from)
184
+ return null;
185
+ // Knocking makes a space and hands out its invite: only a note for the whole
186
+ // account, to write, may. An app given one space, or only to read, may not.
187
+ if (!chain.capabilities.some((capability) => capability.with === '*' && (capability.can === 'expression/*' || capability.can === '*')))
188
+ return null;
189
+ // A private space the knocker made, with its key: anything else isn't a space for two from them.
190
+ let invited;
191
+ try {
192
+ invited = parseSpaceInvite(body.invite);
193
+ }
194
+ catch {
195
+ return null;
196
+ }
197
+ if (invited.space.creator !== body.from || invited.space.visibility !== 'private' || !invited.key)
198
+ return null;
199
+ if ((await checkSpace(invited.space)) !== null)
200
+ return null;
201
+ return Object.freeze({
202
+ from: body.from,
203
+ name: clip(body.name, MAX_NAME) || 'Someone',
204
+ ...(body.note ? { note: body.note } : {}),
205
+ invite: body.invite,
206
+ pairSpace: invited.space.id,
207
+ at: body.at * 1000,
208
+ });
209
+ }
210
+ //# sourceMappingURL=doors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doors.js","sourceRoot":"","sources":["../../src/doors/doors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @module doors
3
+ * Doors and knocks — see `doors.ts`, and `node.doors` for the API an app uses.
4
+ */
5
+ export { encodeDoorCode, parseDoorCode, checkDoorCode, doorTopic, knockId, sealKnock, openKnock, signPurge, purgeMessage, signAnswer, checkAnswer, clip, KNOCK_DROP_WINDOW_SECONDS, MAX_DOOR_RELAYS, KNOCK_TTL_SECONDS, } from './doors.js';
6
+ export type { DoorCode, KnockBody, OpenedKnock } from './doors.js';
7
+ export { createMailboxClient } from '../network/mailbox.js';
8
+ export type { MailboxClient, MailboxOptions, MailItem } from '../network/mailbox.js';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/doors/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EACL,cAAc,EACd,aAAa,EACb,aAAa,EACb,SAAS,EACT,OAAO,EACP,SAAS,EACT,SAAS,EACT,SAAS,EACT,YAAY,EACZ,UAAU,EACV,WAAW,EACX,IAAI,EACJ,yBAAyB,EACzB,eAAe,EACf,iBAAiB,GAClB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @module doors
3
+ * Doors and knocks — see `doors.ts`, and `node.doors` for the API an app uses.
4
+ */
5
+ export { encodeDoorCode, parseDoorCode, checkDoorCode, doorTopic, knockId, sealKnock, openKnock, signPurge, purgeMessage, signAnswer, checkAnswer, clip, KNOCK_DROP_WINDOW_SECONDS, MAX_DOOR_RELAYS, KNOCK_TTL_SECONDS, } from './doors.js';
6
+ export { createMailboxClient } from '../network/mailbox.js';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/doors/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EACL,cAAc,EACd,aAAa,EACb,aAAa,EACb,SAAS,EACT,OAAO,EACP,SAAS,EACT,SAAS,EACT,SAAS,EACT,YAAY,EACZ,UAAU,EACV,WAAW,EACX,IAAI,EACJ,yBAAyB,EACzB,eAAe,EACf,iBAAiB,GAClB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,68 @@
1
+ export interface ContactKeyPair {
2
+ /** The public half: a compressed P-256 point, base64url. What goes on a profile. */
3
+ readonly publicKey: string;
4
+ /** The private half, for opening what was sealed to the public one. Not extractable. */
5
+ readonly privateKey: CryptoKey;
6
+ }
7
+ /**
8
+ * The contact key's private scalar, from the account seed — 32 bytes. This is
9
+ * what an account home hands an app it lets handle contacts.
10
+ */
11
+ export declare function deriveContactKeyBytes(seed: Uint8Array): Promise<Uint8Array>;
12
+ /**
13
+ * An account's **member key** for one space: the same kind of key pair, derived
14
+ * from the account's vault key and the space id. When a private space's key
15
+ * changes, the new key is sealed to each member's member key (`sys.box`).
16
+ *
17
+ * One per space, not one per account, so an account home can hand an app the
18
+ * member keys for exactly the spaces it grants — and a new space key reaches
19
+ * that app without it holding anything that opens other spaces' keys.
20
+ * @param accountKey The vault key bytes (`deriveVaultKeyBytes(seed)`)
21
+ */
22
+ export declare function deriveMemberKeyBytes(accountKey: Uint8Array, spaceId: string): Promise<Uint8Array>;
23
+ /**
24
+ * A **door key**: the key a door's knocks are sealed to (`doors/doors.ts`).
25
+ * Derived from the contact key and the door's id, so every device and app
26
+ * holding the contact key opens the same doors, and a new door is a new id.
27
+ *
28
+ * Not the contact key itself: that one's public half is on your profile in
29
+ * every space you write in, and a door is handed to people who may not know
30
+ * who you are yet. A door key says nothing about the account behind it.
31
+ * @param contactKey The contact key's private scalar (`deriveContactKeyBytes`)
32
+ * @param doorId The door's id, as its `std.door` record names it
33
+ */
34
+ export declare function deriveDoorKeyBytes(contactKey: Uint8Array, doorId: string): Promise<Uint8Array>;
35
+ /**
36
+ * A door's **signing key**: what proves you own a door, without saying whose
37
+ * it is — to a relay, when clearing the door's mailbox, and to someone who
38
+ * knocked, when you answer. Separate from the door key, which only opens
39
+ * knocks: one key should not both sign and decrypt.
40
+ */
41
+ export declare function deriveDoorSignKeyBytes(contactKey: Uint8Array, doorId: string): Promise<Uint8Array>;
42
+ /**
43
+ * Signs with a P-256 private scalar: ECDSA over SHA-256, 64 bytes r ‖ s,
44
+ * base64url — for door signing keys.
45
+ */
46
+ export declare function signWithScalar(secret: Uint8Array, data: Uint8Array): Promise<string>;
47
+ /** Checks what `signWithScalar` signed, against a compressed public key (base64url) */
48
+ export declare function verifyWithPoint(publicKey: string, data: Uint8Array, signature: string): Promise<boolean>;
49
+ /** The public half, from the private scalar */
50
+ export declare function contactPublicKey(secret: Uint8Array): string;
51
+ /** Whether a string is a contact key's public half: a point on P-256 */
52
+ export declare function isContactPublicKey(value: unknown): value is string;
53
+ /** The key pair, from the private scalar (`deriveContactKeyBytes`) */
54
+ export declare function contactKeyPair(secret: Uint8Array): Promise<ContactKeyPair>;
55
+ /**
56
+ * Seals a value so only the holder of a contact key can open it.
57
+ * @param recipient The contact key's public half, as a profile carries it
58
+ * @param value Anything JSON can carry
59
+ * @param context What the sealed value belongs to; opening needs the same
60
+ * @returns base64url: the ephemeral public point, the IV, and the ciphertext
61
+ */
62
+ export declare function sealFor(recipient: string, value: unknown, context: string): Promise<string>;
63
+ /**
64
+ * Opens what `sealFor` sealed.
65
+ * @returns The value, or null when it was not sealed for this key, or for this context, or was changed
66
+ */
67
+ export declare function openSealed(privateKey: CryptoKey, sealed: string, context: string): Promise<unknown>;
68
+ //# sourceMappingURL=contact-key.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contact-key.d.ts","sourceRoot":"","sources":["../../src/identity/contact-key.ts"],"names":[],"mappings":"AAoCA,MAAM,WAAW,cAAc;IAC7B,oFAAoF;IACpF,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,wFAAwF;IACxF,QAAQ,CAAC,UAAU,EAAE,SAAS,CAAC;CAChC;AAYD;;;GAGG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAEjF;AAED;;;;;;;;;GASG;AACH,wBAAsB,oBAAoB,CAAC,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAEvG;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,kBAAkB,CAAC,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAEpG;AAED;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAAC,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAExG;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAiB1F;AAED,uFAAuF;AACvF,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQ9G;AAED,+CAA+C;AAC/C,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAE3D;AAED,wEAAwE;AACxE,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAQlE;AAED,sEAAsE;AACtE,wBAAsB,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,cAAc,CAAC,CAiBhF;AASD;;;;;;GAMG;AACH,wBAAsB,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAqBjG;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAAC,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CA2BzG"}