@weaveprotocol/core 0.1.1 → 0.2.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.
Files changed (183) hide show
  1. package/README.md +264 -42
  2. package/dist/identity/contact-key.d.ts +42 -0
  3. package/dist/identity/contact-key.d.ts.map +1 -0
  4. package/dist/identity/contact-key.js +133 -0
  5. package/dist/identity/contact-key.js.map +1 -0
  6. package/dist/index.d.ts +16 -7
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +10 -5
  9. package/dist/index.js.map +1 -1
  10. package/dist/network/mesh.d.ts +6 -0
  11. package/dist/network/mesh.d.ts.map +1 -1
  12. package/dist/network/mesh.js +11 -1
  13. package/dist/network/mesh.js.map +1 -1
  14. package/dist/network/multi-signaling.d.ts +12 -2
  15. package/dist/network/multi-signaling.d.ts.map +1 -1
  16. package/dist/network/multi-signaling.js +86 -14
  17. package/dist/network/multi-signaling.js.map +1 -1
  18. package/dist/network/peer-auth.d.ts +50 -16
  19. package/dist/network/peer-auth.d.ts.map +1 -1
  20. package/dist/network/peer-auth.js +52 -15
  21. package/dist/network/peer-auth.js.map +1 -1
  22. package/dist/node/carrier.d.ts +87 -0
  23. package/dist/node/carrier.d.ts.map +1 -1
  24. package/dist/node/carrier.js +180 -59
  25. package/dist/node/carrier.js.map +1 -1
  26. package/dist/node/copy.d.ts.map +1 -1
  27. package/dist/node/copy.js +6 -3
  28. package/dist/node/copy.js.map +1 -1
  29. package/dist/node/host.d.ts +117 -0
  30. package/dist/node/host.d.ts.map +1 -0
  31. package/dist/node/host.js +192 -0
  32. package/dist/node/host.js.map +1 -0
  33. package/dist/node/index.d.ts +6 -2
  34. package/dist/node/index.d.ts.map +1 -1
  35. package/dist/node/index.js +1 -0
  36. package/dist/node/index.js.map +1 -1
  37. package/dist/node/node.d.ts.map +1 -1
  38. package/dist/node/node.js +640 -25
  39. package/dist/node/node.js.map +1 -1
  40. package/dist/node/space-runtime.d.ts +42 -25
  41. package/dist/node/space-runtime.d.ts.map +1 -1
  42. package/dist/node/space-runtime.js +734 -35
  43. package/dist/node/space-runtime.js.map +1 -1
  44. package/dist/node/types.d.ts +269 -3
  45. package/dist/node/types.d.ts.map +1 -1
  46. package/dist/privacy/space-encryption.d.ts +16 -0
  47. package/dist/privacy/space-encryption.d.ts.map +1 -1
  48. package/dist/privacy/space-encryption.js +40 -0
  49. package/dist/privacy/space-encryption.js.map +1 -1
  50. package/dist/query/engine.js +1 -1
  51. package/dist/query/engine.js.map +1 -1
  52. package/dist/query/types.d.ts +7 -0
  53. package/dist/query/types.d.ts.map +1 -1
  54. package/dist/query/types.js.map +1 -1
  55. package/dist/react/use-query.d.ts +1 -1
  56. package/dist/react/use-query.d.ts.map +1 -1
  57. package/dist/records/topics.d.ts +21 -0
  58. package/dist/records/topics.d.ts.map +1 -0
  59. package/dist/records/topics.js +86 -0
  60. package/dist/records/topics.js.map +1 -0
  61. package/dist/schema/collection-def.d.ts +7 -0
  62. package/dist/schema/collection-def.d.ts.map +1 -1
  63. package/dist/schema/collection-def.js +4 -0
  64. package/dist/schema/collection-def.js.map +1 -1
  65. package/dist/schema/expression.d.ts +2 -0
  66. package/dist/schema/expression.d.ts.map +1 -1
  67. package/dist/schema/expression.js +1 -0
  68. package/dist/schema/expression.js.map +1 -1
  69. package/dist/schemas/contacts.d.ts +77 -0
  70. package/dist/schemas/contacts.d.ts.map +1 -0
  71. package/dist/schemas/contacts.js +35 -0
  72. package/dist/schemas/contacts.js.map +1 -0
  73. package/dist/schemas/index.d.ts +2 -0
  74. package/dist/schemas/index.d.ts.map +1 -1
  75. package/dist/schemas/index.js +1 -0
  76. package/dist/schemas/index.js.map +1 -1
  77. package/dist/session/auth.d.ts.map +1 -1
  78. package/dist/session/auth.js +14 -3
  79. package/dist/session/auth.js.map +1 -1
  80. package/dist/session/connect.d.ts +25 -1
  81. package/dist/session/connect.d.ts.map +1 -1
  82. package/dist/session/connect.js +9 -2
  83. package/dist/session/connect.js.map +1 -1
  84. package/dist/session/hosting.d.ts +155 -0
  85. package/dist/session/hosting.d.ts.map +1 -0
  86. package/dist/session/hosting.js +160 -0
  87. package/dist/session/hosting.js.map +1 -0
  88. package/dist/space/account-registry.d.ts +6 -0
  89. package/dist/space/account-registry.d.ts.map +1 -1
  90. package/dist/space/account-registry.js +16 -4
  91. package/dist/space/account-registry.js.map +1 -1
  92. package/dist/space/notify.d.ts +88 -0
  93. package/dist/space/notify.d.ts.map +1 -0
  94. package/dist/space/notify.js +127 -0
  95. package/dist/space/notify.js.map +1 -0
  96. package/dist/space/pass.d.ts +6 -0
  97. package/dist/space/pass.d.ts.map +1 -1
  98. package/dist/space/pass.js +5 -2
  99. package/dist/space/pass.js.map +1 -1
  100. package/dist/space/roles.d.ts +71 -0
  101. package/dist/space/roles.d.ts.map +1 -1
  102. package/dist/space/roles.js +114 -0
  103. package/dist/space/roles.js.map +1 -1
  104. package/dist/space/space-access.d.ts +24 -0
  105. package/dist/space/space-access.d.ts.map +1 -1
  106. package/dist/space/space-access.js +24 -0
  107. package/dist/space/space-access.js.map +1 -1
  108. package/dist/space/space-manager.d.ts +35 -1
  109. package/dist/space/space-manager.d.ts.map +1 -1
  110. package/dist/space/space-manager.js +72 -25
  111. package/dist/space/space-manager.js.map +1 -1
  112. package/dist/storage/blob/memory.d.ts +9 -0
  113. package/dist/storage/blob/memory.d.ts.map +1 -0
  114. package/dist/storage/blob/memory.js +20 -0
  115. package/dist/storage/blob/memory.js.map +1 -0
  116. package/dist/storage/blob/s3.d.ts +16 -0
  117. package/dist/storage/blob/s3.d.ts.map +1 -0
  118. package/dist/storage/blob/s3.js +86 -0
  119. package/dist/storage/blob/s3.js.map +1 -0
  120. package/dist/storage/blob-store.d.ts +26 -0
  121. package/dist/storage/blob-store.d.ts.map +1 -0
  122. package/dist/storage/blob-store.js +2 -0
  123. package/dist/storage/blob-store.js.map +1 -0
  124. package/dist/storage/encrypted-adapter.d.ts +3 -3
  125. package/dist/storage/encrypted-adapter.js +3 -3
  126. package/dist/storage/folder-adapter.d.ts +8 -8
  127. package/dist/storage/folder-adapter.d.ts.map +1 -1
  128. package/dist/storage/folder-adapter.js +7 -7
  129. package/dist/storage/folder-reconcile.d.ts +12 -14
  130. package/dist/storage/folder-reconcile.d.ts.map +1 -1
  131. package/dist/storage/folder-reconcile.js +20 -14
  132. package/dist/storage/folder-reconcile.js.map +1 -1
  133. package/dist/storage/index.d.ts +0 -1
  134. package/dist/storage/index.d.ts.map +1 -1
  135. package/dist/storage/index.js +0 -1
  136. package/dist/storage/index.js.map +1 -1
  137. package/dist/storage/indexeddb-adapter.d.ts.map +1 -1
  138. package/dist/storage/indexeddb-adapter.js +8 -9
  139. package/dist/storage/indexeddb-adapter.js.map +1 -1
  140. package/dist/storage/mirror.d.ts +68 -0
  141. package/dist/storage/mirror.d.ts.map +1 -0
  142. package/dist/storage/mirror.js +174 -0
  143. package/dist/storage/mirror.js.map +1 -0
  144. package/dist/storage/segment.d.ts +20 -0
  145. package/dist/storage/segment.d.ts.map +1 -0
  146. package/dist/storage/segment.js +27 -0
  147. package/dist/storage/segment.js.map +1 -0
  148. package/dist/storage/storage-provider.d.ts +36 -40
  149. package/dist/storage/storage-provider.d.ts.map +1 -1
  150. package/dist/storage/storage-provider.js +208 -117
  151. package/dist/storage/storage-provider.js.map +1 -1
  152. package/dist/sync/index.d.ts +1 -1
  153. package/dist/sync/index.d.ts.map +1 -1
  154. package/dist/sync/index.js +1 -1
  155. package/dist/sync/index.js.map +1 -1
  156. package/dist/sync/negentropy.d.ts +68 -0
  157. package/dist/sync/negentropy.d.ts.map +1 -0
  158. package/dist/sync/negentropy.js +379 -0
  159. package/dist/sync/negentropy.js.map +1 -0
  160. package/dist/sync/sync-engine.d.ts +45 -13
  161. package/dist/sync/sync-engine.d.ts.map +1 -1
  162. package/dist/sync/sync-engine.js +290 -207
  163. package/dist/sync/sync-engine.js.map +1 -1
  164. package/dist/sync/sync-messages.d.ts +42 -32
  165. package/dist/sync/sync-messages.d.ts.map +1 -1
  166. package/dist/sync/sync-messages.js +1 -1
  167. package/dist/sync/sync-messages.js.map +1 -1
  168. package/dist/types.d.ts +9 -0
  169. package/dist/types.d.ts.map +1 -1
  170. package/dist/types.js.map +1 -1
  171. package/dist/utils/hash.d.ts +9 -0
  172. package/dist/utils/hash.d.ts.map +1 -1
  173. package/dist/utils/hash.js +33 -0
  174. package/dist/utils/hash.js.map +1 -1
  175. package/package.json +9 -3
  176. package/dist/storage/mst.d.ts +0 -121
  177. package/dist/storage/mst.d.ts.map +0 -1
  178. package/dist/storage/mst.js +0 -402
  179. package/dist/storage/mst.js.map +0 -1
  180. package/dist/sync/anti-entropy.d.ts +0 -49
  181. package/dist/sync/anti-entropy.d.ts.map +0 -1
  182. package/dist/sync/anti-entropy.js +0 -62
  183. package/dist/sync/anti-entropy.js.map +0 -1
@@ -0,0 +1,160 @@
1
+ import { createP256Provider } from '../identity/crypto-p256.js';
2
+ import { didToPublicKey, publicKeyToDid, P256_MULTICODEC } from '../identity/did.js';
3
+ import { base64UrlDecode, base64UrlEncode, utf8Encode } from '../utils/encoding.js';
4
+ import { sha256 } from '../utils/hash.js';
5
+ /** Where the account keeps the hosts it uses, in its registry: one record each */
6
+ export const HOSTING_COLLECTION = 'sys.hosting';
7
+ /** How far a signed request's time may be from the host's, in seconds */
8
+ export const REQUEST_WINDOW_SECONDS = 300;
9
+ /** A fresh seed for a subscription key */
10
+ export function newSubscriptionSeed() {
11
+ return globalThis.crypto.getRandomValues(new Uint8Array(32));
12
+ }
13
+ /** The subscription key a seed stands for */
14
+ export async function subscriptionKey(seed, provider = createP256Provider()) {
15
+ const pair = await provider.deriveKeyPairFromSeed(seed);
16
+ return { did: publicKeyToDid(await provider.exportPublicKey(pair.publicKey), P256_MULTICODEC), privateKey: pair.privateKey };
17
+ }
18
+ async function requestText(method, path, at, body) {
19
+ const bodyHash = base64UrlEncode(await sha256(utf8Encode(body)));
20
+ return utf8Encode(`weave-host/v1\n${method.toUpperCase()}\n${path}\n${at}\n${bodyHash}`);
21
+ }
22
+ /**
23
+ * The `Authorization` header for a request.
24
+ * @param path The path and query, as the host will see it
25
+ */
26
+ export async function signRequest(key, method, path, body = '', provider = createP256Provider(), at = Math.floor(Date.now() / 1000)) {
27
+ const sig = base64UrlEncode(await provider.sign(key.privateKey, await requestText(method, path, at, body)));
28
+ return `Weave did=${key.did}, at=${at}, sig=${sig}`;
29
+ }
30
+ /**
31
+ * Which subscription signed a request, or null when it isn't signed, is
32
+ * signed by someone else, or too far from now.
33
+ */
34
+ export async function verifyRequest(header, method, path, body, provider = createP256Provider(), now = Math.floor(Date.now() / 1000)) {
35
+ const match = /^Weave did=(did:key:z[1-9A-HJ-NP-Za-km-z]{1,120}), at=(\d{1,12}), sig=([A-Za-z0-9_-]{1,200})$/.exec(header ?? '');
36
+ if (!match)
37
+ return null;
38
+ const [, did, atText, sig] = match;
39
+ const at = Number(atText);
40
+ if (Math.abs(now - at) > REQUEST_WINDOW_SECONDS)
41
+ return null;
42
+ try {
43
+ const publicKey = await provider.importPublicKey(didToPublicKey(did).publicKeyBytes);
44
+ return (await provider.verify(publicKey, base64UrlDecode(sig), await requestText(method, path, at, body))) ? did : null;
45
+ }
46
+ catch {
47
+ return null;
48
+ }
49
+ }
50
+ /** Where a host's description is */
51
+ export const HOST_DESCRIPTION_PATH = '/.well-known/weave-host';
52
+ /** How long a pay link works, in seconds */
53
+ export const PAY_LINK_SECONDS = 3600;
54
+ const statusText = (payload) => utf8Encode(`weave-host-status/v1\n${payload}`);
55
+ const payText = (host, subscription, at) => utf8Encode(`weave-pay/v1\n${host}\n${subscription}\n${at}`);
56
+ /** Signs a status with the host's key */
57
+ export async function signStatus(status, privateKey, provider = createP256Provider()) {
58
+ const payload = JSON.stringify(status);
59
+ return { payload, sig: base64UrlEncode(await provider.sign(privateKey, statusText(payload))) };
60
+ }
61
+ /** The status a signed one says, when `host` signed it; null when it didn't */
62
+ export async function readStatus(signed, host, provider = createP256Provider()) {
63
+ try {
64
+ const publicKey = await provider.importPublicKey(didToPublicKey(host).publicKeyBytes);
65
+ if (!(await provider.verify(publicKey, base64UrlDecode(signed.sig), statusText(signed.payload))))
66
+ return null;
67
+ const status = JSON.parse(signed.payload);
68
+ return status.host === host ? status : null;
69
+ }
70
+ catch {
71
+ return null;
72
+ }
73
+ }
74
+ /**
75
+ * A link to a host's pay page that lets whoever opens it pay for one
76
+ * subscription, at that host only, for an hour. The signature is in the
77
+ * fragment, which browsers never send to a server.
78
+ * @param pay The pay page's address, absolute
79
+ * @param host The host's key
80
+ */
81
+ export async function payLink(pay, host, key, provider = createP256Provider(), at = Math.floor(Date.now() / 1000)) {
82
+ const sig = base64UrlEncode(await provider.sign(key.privateKey, payText(host, key.did, at)));
83
+ const url = new URL(pay);
84
+ url.hash = new URLSearchParams({ s: key.did, at: String(at), sig }).toString();
85
+ return url.toString();
86
+ }
87
+ /**
88
+ * The subscription a pay page's call is for — its `Authorization: WeavePay
89
+ * s=…, at=…, sig=…` header, from a pay link to this host (`host`, its key)
90
+ * that is less than an hour old. Null otherwise.
91
+ */
92
+ export async function verifyPayLink(header, host, provider = createP256Provider(), now = Math.floor(Date.now() / 1000)) {
93
+ const match = /^WeavePay s=(did:key:z[1-9A-HJ-NP-Za-km-z]{1,120}), at=(\d{1,12}), sig=([A-Za-z0-9_-]{1,200})$/.exec(header ?? '');
94
+ if (!match)
95
+ return null;
96
+ const [, did, atText, sig] = match;
97
+ const at = Number(atText);
98
+ if (now - at > PAY_LINK_SECONDS || at - now > REQUEST_WINDOW_SECONDS)
99
+ return null;
100
+ try {
101
+ const publicKey = await provider.importPublicKey(didToPublicKey(did).publicKeyBytes);
102
+ return (await provider.verify(publicKey, base64UrlDecode(sig), payText(host, did, at))) ? did : null;
103
+ }
104
+ catch {
105
+ return null;
106
+ }
107
+ }
108
+ /** Why a host said no: its status code, and what it said */
109
+ export class HostError extends Error {
110
+ status;
111
+ constructor(status, message) {
112
+ super(message);
113
+ this.status = status;
114
+ }
115
+ }
116
+ async function answerOf(response) {
117
+ const answer = (await response.json().catch(() => ({})));
118
+ if (!response.ok)
119
+ throw new HostError(response.status, answer.error ?? `The host answered ${response.status}`);
120
+ return answer;
121
+ }
122
+ /**
123
+ * What a host at an address says about itself.
124
+ * @param url The host's address, https://
125
+ */
126
+ export async function describeHost(url) {
127
+ const description = await answerOf(await fetch(`${url.replace(/\/+$/, '')}${HOST_DESCRIPTION_PATH}`));
128
+ if (description.weave !== 'host/1' || typeof description.did !== 'string' || !description.did.startsWith('did:key:')) {
129
+ throw new Error("That address doesn't answer as a Weave host");
130
+ }
131
+ return description;
132
+ }
133
+ /**
134
+ * A client for one host, signing as one subscription.
135
+ * @param url The host's address, https://
136
+ * @param host The host's key: every status must be signed by it
137
+ */
138
+ export function createHostClient(url, host, key, provider = createP256Provider()) {
139
+ const base = url.replace(/\/+$/, '');
140
+ async function call(method, path, body) {
141
+ const text = body === undefined ? '' : JSON.stringify(body);
142
+ const headers = { authorization: await signRequest(key, method, path, text, provider) };
143
+ if (body !== undefined)
144
+ headers['content-type'] = 'application/json';
145
+ return answerOf(await fetch(`${base}${path}`, { method, headers, ...(body === undefined ? {} : { body: text }) }));
146
+ }
147
+ const checked = async (receipt) => {
148
+ const status = await readStatus(receipt, host, provider);
149
+ if (!status || status.subscription !== key.did)
150
+ throw new Error("The host's answer isn't signed by the host this account uses");
151
+ return { status, receipt };
152
+ };
153
+ const mine = `/host/subscriptions/${encodeURIComponent(key.did)}`;
154
+ return Object.freeze({
155
+ status: async () => checked(await call('GET', mine)),
156
+ attach: async (account, invite) => checked(await call('PUT', `${mine}/carry`, { account, invite })),
157
+ detach: async () => void (await call('DELETE', `${mine}/carry`)),
158
+ });
159
+ }
160
+ //# sourceMappingURL=hosting.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hosting.js","sourceRoot":"","sources":["../../src/session/hosting.ts"],"names":[],"mappings":"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"}
@@ -61,4 +61,10 @@ export interface Carrier {
61
61
  * @param owner The account's DID
62
62
  */
63
63
  export declare function deriveAccountRegistry(accountKey: Uint8Array, owner: string, provider?: CryptoProvider): Promise<SpaceRecord>;
64
+ /**
65
+ * The account's contacts space, derived the same way: one `std.contact` per
66
+ * person (`schemas/contacts.ts`). Its own space, not part of the registry, so
67
+ * an app can be given the contacts without the whole account.
68
+ */
69
+ export declare function deriveContactsSpace(accountKey: Uint8Array, owner: string, provider?: CryptoProvider): Promise<SpaceRecord>;
64
70
  //# sourceMappingURL=account-registry.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"account-registry.d.ts","sourceRoot":"","sources":["../../src/space/account-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,EAAE,cAAc,EAAS,MAAM,aAAa,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAQtD;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,eAAe,CAAC;AAElD;;;GAGG;AACH,eAAO,MAAM,kBAAkB,gBAAgB,CAAC;AAEhD,kEAAkE;AAClE,eAAO,MAAM,WAAW,YAAY,CAAC;AAErC,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,wGAAwG;AACxG,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,gBAAgB,CAAC;AAEhD,8BAA8B;AAC9B,MAAM,WAAW,OAAO;IACtB,qCAAqC;IACrC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,uFAAuF;IACvF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,oDAAoD;IACpD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,4BAA4B;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAYD;;;;GAIG;AACH,wBAAsB,qBAAqB,CACzC,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,MAAM,EACb,QAAQ,GAAE,cAAqC,GAC9C,OAAO,CAAC,WAAW,CAAC,CA8BtB"}
1
+ {"version":3,"file":"account-registry.d.ts","sourceRoot":"","sources":["../../src/space/account-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,EAAE,cAAc,EAAS,MAAM,aAAa,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAQtD;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,eAAe,CAAC;AAElD;;;GAGG;AACH,eAAO,MAAM,kBAAkB,gBAAgB,CAAC;AAEhD,kEAAkE;AAClE,eAAO,MAAM,WAAW,YAAY,CAAC;AAErC,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,wGAAwG;AACxG,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,gBAAgB,CAAC;AAEhD,8BAA8B;AAC9B,MAAM,WAAW,OAAO;IACtB,qCAAqC;IACrC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,uFAAuF;IACvF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,oDAAoD;IACpD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,4BAA4B;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAYD;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,MAAM,EACb,QAAQ,GAAE,cAAqC,GAC9C,OAAO,CAAC,WAAW,CAAC,CAEtB;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,MAAM,EACb,QAAQ,GAAE,cAAqC,GAC9C,OAAO,CAAC,WAAW,CAAC,CAEtB"}
@@ -32,9 +32,21 @@ async function expand(accountKey, info) {
32
32
  * @param accountKey The account's vault key bytes (`deriveVaultKeyBytes(seed)`)
33
33
  * @param owner The account's DID
34
34
  */
35
- export async function deriveAccountRegistry(accountKey, owner, provider = createP256Provider()) {
36
- const nonce = base64UrlEncode((await expand(accountKey, 'weave/account-registry/nonce/v1')).subarray(0, 12));
37
- const keyBytes = await expand(accountKey, 'weave/account-registry/key/v1');
35
+ export function deriveAccountRegistry(accountKey, owner, provider = createP256Provider()) {
36
+ return deriveAccountSpace(accountKey, owner, 'weave/account-registry', 'Account registry', provider);
37
+ }
38
+ /**
39
+ * The account's contacts space, derived the same way: one `std.contact` per
40
+ * person (`schemas/contacts.ts`). Its own space, not part of the registry, so
41
+ * an app can be given the contacts without the whole account.
42
+ */
43
+ export function deriveContactsSpace(accountKey, owner, provider = createP256Provider()) {
44
+ return deriveAccountSpace(accountKey, owner, 'weave/contacts', 'Contacts', provider);
45
+ }
46
+ /** A private space only the account can find: its key and nonce derived from the vault key under `label`. */
47
+ async function deriveAccountSpace(accountKey, owner, label, name, provider) {
48
+ const nonce = base64UrlEncode((await expand(accountKey, `${label}/nonce/v1`)).subarray(0, 12));
49
+ const keyBytes = await expand(accountKey, `${label}/key/v1`);
38
50
  const cryptoKey = await globalThis.crypto.subtle.importKey('raw', keyBytes, { name: 'AES-GCM', length: 256 }, true, [
39
51
  'encrypt',
40
52
  'decrypt',
@@ -59,7 +71,7 @@ export async function deriveAccountRegistry(accountKey, owner, provider = create
59
71
  const space = Object.freeze({
60
72
  id: await spaceIdOf(spaceGenesis(fixed)),
61
73
  ...fixed,
62
- name: 'Account registry',
74
+ name,
63
75
  });
64
76
  return { space, key, invite: null, role: solo.creatorRole };
65
77
  }
@@ -1 +1 @@
1
- {"version":3,"file":"account-registry.js","sourceRoot":"","sources":["../../src/space/account-registry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"account-registry.js","sourceRoot":"","sources":["../../src/space/account-registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * @module space/notify
3
+ * Subscriptions: "let me know when…", across spaces, by nodes that can't read.
4
+ *
5
+ * A person says what they want to hear about — new records in a collection,
6
+ * in some spaces or all of them, perhaps only those with a topic value
7
+ * ("mentions me", "in #design"), perhaps only other people's. That is kept in
8
+ * the account registry, sealed, value and all (`NOTIFY_COLLECTION`).
9
+ *
10
+ * The account's carriers — its extension, its hosts — are the ones online to
11
+ * notice, and they can't read. So every device holding the account key copies
12
+ * each subscription into each carry space with the value replaced by that
13
+ * space's topic tag (`records/topics.ts`): a carrier learns "tag X, in Club",
14
+ * never what X stands for. It matches arriving records by space, collection,
15
+ * author and tag, all on the outside of a record, and says so; the extension
16
+ * shows a notification. The label is the person's own words, shown as is.
17
+ *
18
+ * The same split as a query in a space held in part (BLOCK-22): the part a
19
+ * blind node can check runs there, the rest where the keys are.
20
+ */
21
+ import type { Expression } from '../types.js';
22
+ import type { SpaceKey } from '../privacy/space-encryption.js';
23
+ /** Subscriptions as the person made them, in the account registry: key `notify:<id>` */
24
+ export declare const NOTIFY_COLLECTION = "sys.notify";
25
+ /** Subscriptions as a carrier holds them, in its carry space: the same key, values replaced by tags */
26
+ export declare const SUBSCRIPTION_COLLECTION = "sys.subscription";
27
+ /** Spaces a subscription looks at: every space of the account, or these */
28
+ export type NotifySpaces = 'all' | ReadonlyArray<string>;
29
+ /** A subscription as the person made it */
30
+ export interface NotifyWhen {
31
+ /** What the notification says, in the person's words: "Mentioned in Club" */
32
+ readonly label: string;
33
+ /** New records in this collection */
34
+ readonly collection: string;
35
+ readonly spaces: NotifySpaces;
36
+ /** Only records whose topic field holds this value — `{ field: 'mentions', value: <my did> }` */
37
+ readonly topic?: {
38
+ readonly field: string;
39
+ readonly value: string | number | boolean;
40
+ };
41
+ /** Only records other people wrote. Default true. */
42
+ readonly others?: boolean;
43
+ /** Where clicking the notification goes: an app's address. Default: the account home. */
44
+ readonly open?: string;
45
+ /** Kept, but quiet */
46
+ readonly paused?: boolean;
47
+ /** When it was made: nothing written before it notifies */
48
+ readonly since: string;
49
+ }
50
+ /** A subscription as a carrier holds it: no values, only tags */
51
+ export interface CarriedSubscription {
52
+ readonly v: 1;
53
+ readonly label: string;
54
+ readonly collection: string;
55
+ readonly spaces: NotifySpaces;
56
+ /** Per space: a record matches when it carries any of these. Absent: no topic, every record matches. */
57
+ readonly tags?: Readonly<Record<string, ReadonlyArray<string>>>;
58
+ readonly others: boolean;
59
+ readonly open?: string;
60
+ readonly paused: boolean;
61
+ readonly since: string;
62
+ }
63
+ /** Why a subscription can't be kept, or null */
64
+ export declare function checkNotify(when: unknown): string | null;
65
+ /** A space the account follows, as far as a subscription needs: its id, and its current key when private */
66
+ export interface NotifySpace {
67
+ readonly id: string;
68
+ readonly key: SpaceKey | null;
69
+ readonly visibility: 'public' | 'private';
70
+ }
71
+ /**
72
+ * What a carrier gets: the subscription with its value replaced by each
73
+ * space's tag. A private space whose key this device doesn't hold gets none,
74
+ * so it never matches — better quiet than wrong.
75
+ */
76
+ export declare function carriedFor(when: NotifyWhen, spaces: ReadonlyArray<NotifySpace>): Promise<CarriedSubscription>;
77
+ /** A carried subscription as read back from a carry space, or null when it isn't one */
78
+ export declare function readCarried(body: unknown): CarriedSubscription | null;
79
+ /** Who a version was written for: the account at the root of its note, else its own key */
80
+ export declare function rootOf(version: Expression): string;
81
+ /** How long after it was written a record may still notify: a carrier catching up on last week stays quiet */
82
+ export declare const NOTIFY_WITHIN_MS: number;
83
+ /**
84
+ * Whether a record that just arrived in a space is one a subscription asks
85
+ * about — decided from its outside alone.
86
+ */
87
+ export declare function matchesSubscription(sub: CarriedSubscription, spaceId: string, version: Expression, account: string, now?: number): boolean;
88
+ //# sourceMappingURL=notify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notify.d.ts","sourceRoot":"","sources":["../../src/space/notify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAI/D,wFAAwF;AACxF,eAAO,MAAM,iBAAiB,eAAe,CAAC;AAC9C,uGAAuG;AACvG,eAAO,MAAM,uBAAuB,qBAAqB,CAAC;AAE1D,2EAA2E;AAC3E,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;AAEzD,2CAA2C;AAC3C,MAAM,WAAW,UAAU;IACzB,6EAA6E;IAC7E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,qCAAqC;IACrC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,iGAAiG;IACjG,QAAQ,CAAC,KAAK,CAAC,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IACvF,qDAAqD;IACrD,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,yFAAyF;IACzF,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,sBAAsB;IACtB,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,2DAA2D;IAC3D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,iEAAiE;AACjE,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC;IACd,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,wGAAwG;IACxG,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAChE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAID,gDAAgD;AAChD,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAyBxD;AAED,4GAA4G;AAC5G,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,GAAG,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,QAAQ,GAAG,SAAS,CAAC;CAC3C;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAsBnH;AAED,wFAAwF;AACxF,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG,mBAAmB,GAAG,IAAI,CAUrE;AAED,2FAA2F;AAC3F,wBAAgB,MAAM,CAAC,OAAO,EAAE,UAAU,GAAG,MAAM,CAOlD;AAED,8GAA8G;AAC9G,eAAO,MAAM,gBAAgB,QAAsB,CAAC;AAEpD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,SAAa,GAAG,OAAO,CAY9I"}
@@ -0,0 +1,127 @@
1
+ import { parseUCAN } from '../identity/ucan.js';
2
+ import { checkTopics, topicKey, topicTag } from '../records/topics.js';
3
+ /** Subscriptions as the person made them, in the account registry: key `notify:<id>` */
4
+ export const NOTIFY_COLLECTION = 'sys.notify';
5
+ /** Subscriptions as a carrier holds them, in its carry space: the same key, values replaced by tags */
6
+ export const SUBSCRIPTION_COLLECTION = 'sys.subscription';
7
+ const COLLECTION = /^[a-z][a-z0-9-]*(\.[a-z0-9-]+)+$/;
8
+ /** Why a subscription can't be kept, or null */
9
+ export function checkNotify(when) {
10
+ const w = when;
11
+ if (typeof w !== 'object' || w === null)
12
+ return 'A subscription must be an object';
13
+ if (typeof w.label !== 'string' || !w.label.trim() || w.label.length > 120)
14
+ return 'label is what the notification says: some text, at most 120 characters';
15
+ if (typeof w.collection !== 'string' || !COLLECTION.test(w.collection) || w.collection.startsWith('sys.'))
16
+ return 'collection must be one of the space’s collections, like "app.chat.message"';
17
+ if (w.spaces !== 'all' && !(Array.isArray(w.spaces) && w.spaces.length > 0 && w.spaces.length <= 256 && w.spaces.every((s) => typeof s === 'string'))) {
18
+ return 'spaces must be "all" or a list of space ids';
19
+ }
20
+ if (w.topic !== undefined) {
21
+ const t = w.topic;
22
+ if (typeof t !== 'object' || t === null || typeof t.field !== 'string' || checkTopics([t.field]) !== null)
23
+ return 'topic.field must be a field name';
24
+ if (!['string', 'number', 'boolean'].includes(typeof t.value))
25
+ return 'topic.value must be text, a number or yes/no';
26
+ }
27
+ if (w.others !== undefined && typeof w.others !== 'boolean')
28
+ return 'others must be true or false';
29
+ if (w.paused !== undefined && typeof w.paused !== 'boolean')
30
+ return 'paused must be true or false';
31
+ if (w.open !== undefined) {
32
+ try {
33
+ const url = new URL(w.open);
34
+ if (url.protocol !== 'https:' && !(url.protocol === 'http:' && ['localhost', '127.0.0.1'].includes(url.hostname)))
35
+ return 'open must be an https:// address';
36
+ }
37
+ catch {
38
+ return 'open must be a web address';
39
+ }
40
+ }
41
+ if (typeof w.since !== 'string' || !Number.isFinite(Date.parse(w.since)))
42
+ return 'since must be a date';
43
+ return null;
44
+ }
45
+ /**
46
+ * What a carrier gets: the subscription with its value replaced by each
47
+ * space's tag. A private space whose key this device doesn't hold gets none,
48
+ * so it never matches — better quiet than wrong.
49
+ */
50
+ export async function carriedFor(when, spaces) {
51
+ let tags;
52
+ if (when.topic) {
53
+ tags = {};
54
+ const looked = when.spaces === 'all' ? spaces : spaces.filter((s) => when.spaces.includes(s.id));
55
+ for (const space of looked) {
56
+ if (space.visibility === 'private' && !space.key)
57
+ continue;
58
+ const key = await topicKey(space.visibility === 'private' ? { spaceKey: space.key.key } : { spaceId: space.id });
59
+ tags[space.id] = [await topicTag(key, when.collection, when.topic.field, when.topic.value)];
60
+ }
61
+ }
62
+ return {
63
+ v: 1,
64
+ label: when.label,
65
+ collection: when.collection,
66
+ spaces: when.spaces,
67
+ ...(tags ? { tags } : {}),
68
+ others: when.others ?? true,
69
+ ...(when.open ? { open: when.open } : {}),
70
+ paused: when.paused ?? false,
71
+ since: when.since,
72
+ };
73
+ }
74
+ /** A carried subscription as read back from a carry space, or null when it isn't one */
75
+ export function readCarried(body) {
76
+ const b = body;
77
+ if (typeof b !== 'object' || b === null || b.v !== 1)
78
+ return null;
79
+ const problem = checkNotify({ ...b, others: b.others, topic: undefined });
80
+ if (problem)
81
+ return null;
82
+ if (b.tags !== undefined) {
83
+ if (typeof b.tags !== 'object' || b.tags === null)
84
+ return null;
85
+ for (const list of Object.values(b.tags))
86
+ if (!Array.isArray(list) || !list.every((t) => typeof t === 'string'))
87
+ return null;
88
+ }
89
+ return b;
90
+ }
91
+ /** Who a version was written for: the account at the root of its note, else its own key */
92
+ export function rootOf(version) {
93
+ if (!version.proof)
94
+ return version.author;
95
+ try {
96
+ return parseUCAN(version.proof).payload.iss;
97
+ }
98
+ catch {
99
+ return version.author;
100
+ }
101
+ }
102
+ /** How long after it was written a record may still notify: a carrier catching up on last week stays quiet */
103
+ export const NOTIFY_WITHIN_MS = 24 * 60 * 60 * 1000;
104
+ /**
105
+ * Whether a record that just arrived in a space is one a subscription asks
106
+ * about — decided from its outside alone.
107
+ */
108
+ export function matchesSubscription(sub, spaceId, version, account, now = Date.now()) {
109
+ if (sub.paused || version.collection !== sub.collection)
110
+ return false;
111
+ if (version.seq !== 0 || version.deleted)
112
+ return false;
113
+ if (sub.spaces !== 'all' && !sub.spaces.includes(spaceId))
114
+ return false;
115
+ const written = Date.parse(version.createdAt);
116
+ if (!Number.isFinite(written) || written < Date.parse(sub.since) || now - written > NOTIFY_WITHIN_MS)
117
+ return false;
118
+ if (sub.others && rootOf(version) === account)
119
+ return false;
120
+ if (sub.tags) {
121
+ const wanted = sub.tags[spaceId];
122
+ if (!wanted?.length || !version.tags?.some((tag) => wanted.includes(tag)))
123
+ return false;
124
+ }
125
+ return true;
126
+ }
127
+ //# sourceMappingURL=notify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notify.js","sourceRoot":"","sources":["../../src/space/notify.ts"],"names":[],"mappings":"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"}
@@ -39,6 +39,12 @@ export interface SpacePass {
39
39
  readonly space: Space;
40
40
  /** A private space's read key seed, base64url. Absent for a public space. */
41
41
  readonly read?: string;
42
+ /**
43
+ * The public half of that read key, once the space's key has changed since
44
+ * it began. Then the space itself can't vouch for it — the space's history
45
+ * does, and a read key it doesn't name gets the carrier nowhere.
46
+ */
47
+ readonly readKey?: string;
42
48
  }
43
49
  /** A pass, checked and ready to open a space with */
44
50
  export interface OpenedPass {
@@ -1 +1 @@
1
- {"version":3,"file":"pass.d.ts","sourceRoot":"","sources":["../../src/space/pass.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAA+C,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAInG,yCAAyC;AACzC,eAAO,MAAM,eAAe,aAAa,CAAC;AAE1C;;;GAGG;AACH,eAAO,MAAM,gBAAgB,iBAAiB,CAAC;AAE/C,wBAAwB;AACxB,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC;IACd,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,6EAA6E;IAC7E,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,qDAAqD;AACrD,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CAAC;CACpC;AAED,uCAAuC;AACvC,wBAAsB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAG9D;AAED;;;GAGG;AACH,wBAAsB,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC,CAItE;AAED;;;;GAIG;AACH,wBAAsB,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAYnG;AAED,2EAA2E;AAC3E,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,WAAW,CAE3D"}
1
+ {"version":3,"file":"pass.d.ts","sourceRoot":"","sources":["../../src/space/pass.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAA+C,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAKnG,yCAAyC;AACzC,eAAO,MAAM,eAAe,aAAa,CAAC;AAE1C;;;GAGG;AACH,eAAO,MAAM,gBAAgB,iBAAiB,CAAC;AAE/C,wBAAwB;AACxB,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC;IACd,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,6EAA6E;IAC7E,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,qDAAqD;AACrD,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CAAC;CACpC;AAED,uCAAuC;AACvC,wBAAsB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAG9D;AAED;;;GAGG;AACH,wBAAsB,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC,CAMtE;AAED;;;;GAIG;AACH,wBAAsB,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAYnG;AAED,2EAA2E;AAC3E,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,WAAW,CAE3D"}
@@ -1,6 +1,7 @@
1
1
  import { checkSpace, deriveReadSeed, readKeyFromSeed } from './space-access.js';
2
2
  import { base64UrlDecode, base64UrlEncode, utf8Encode } from '../utils/encoding.js';
3
3
  import { sha256 } from '../utils/hash.js';
4
+ import { createP256Provider } from '../identity/crypto-p256.js';
4
5
  /** Where passes live in a carry space */
5
6
  export const PASS_COLLECTION = 'sys.pass';
6
7
  /**
@@ -22,7 +23,9 @@ export async function makePass(record) {
22
23
  return { v: 1, space: record.space };
23
24
  if (!record.key)
24
25
  throw new Error(`"${record.space.name}" is held here without its key, so it cannot be passed on`);
25
- return { v: 1, space: record.space, read: base64UrlEncode(await deriveReadSeed(record.key)) };
26
+ const seed = await deriveReadSeed(record.key);
27
+ const pass = { v: 1, space: record.space, read: base64UrlEncode(seed) };
28
+ return record.key.id === record.space.encryptionKeyId ? pass : { ...pass, readKey: (await readKeyFromSeed(seed, createP256Provider())).did };
26
29
  }
27
30
  /**
28
31
  * Checks a pass someone handed over: the space must hash to its id, and the
@@ -41,7 +44,7 @@ export async function openPass(value, provider) {
41
44
  return null;
42
45
  try {
43
46
  const read = await readKeyFromSeed(base64UrlDecode(pass.read), provider);
44
- return read.did === pass.space.readKey ? { space: pass.space, read } : null;
47
+ return read.did === pass.space.readKey || (pass.readKey !== undefined && read.did === pass.readKey) ? { space: pass.space, read } : null;
45
48
  }
46
49
  catch {
47
50
  return null;
@@ -1 +1 @@
1
- {"version":3,"file":"pass.js","sourceRoot":"","sources":["../../src/space/pass.ts"],"names":[],"mappings":"AA2BA,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,eAAe,EAAqB,MAAM,mBAAmB,CAAC;AACnG,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACpF,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,yCAAyC;AACzC,MAAM,CAAC,MAAM,eAAe,GAAG,UAAU,CAAC;AAE1C;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,cAAc,CAAC;AAgB/C,uCAAuC;AACvC,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,OAAe;IAC3C,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;IACjD,OAAO,QAAQ,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;AACvG,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,MAAmB;IAChD,IAAI,MAAM,CAAC,KAAK,CAAC,UAAU,KAAK,QAAQ;QAAE,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC;IAC/E,IAAI,CAAC,MAAM,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,2DAA2D,CAAC,CAAC;IACnH,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,eAAe,CAAC,MAAM,cAAc,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;AAChG,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,KAAc,EAAE,QAAwB;IACrE,MAAM,IAAI,GAAG,KAAkC,CAAC;IAChD,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACtD,IAAI,CAAC,MAAM,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACzD,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU,KAAK,QAAQ;QAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACjF,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC/C,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,eAAe,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,CAAC;QACzE,OAAO,IAAI,CAAC,GAAG,KAAK,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,aAAa,CAAC,IAAgB;IAC5C,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;AACrF,CAAC"}
1
+ {"version":3,"file":"pass.js","sourceRoot":"","sources":["../../src/space/pass.ts"],"names":[],"mappings":"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"}