mindoodb 0.0.50 → 0.0.53

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 (198) hide show
  1. package/README-server.md +11 -2
  2. package/dist/appendonlystores/network/ClientNetworkContentAddressedStore.d.ts +13 -1
  3. package/dist/appendonlystores/network/ClientNetworkContentAddressedStore.d.ts.map +1 -1
  4. package/dist/appendonlystores/network/ClientNetworkContentAddressedStore.js +45 -20
  5. package/dist/appendonlystores/network/ClientNetworkContentAddressedStore.js.map +1 -1
  6. package/dist/appendonlystores/network/HttpTransport.d.ts +2 -0
  7. package/dist/appendonlystores/network/HttpTransport.d.ts.map +1 -1
  8. package/dist/appendonlystores/network/HttpTransport.js +6 -62
  9. package/dist/appendonlystores/network/HttpTransport.js.map +1 -1
  10. package/dist/appendonlystores/network/ServerNetworkContentAddressedStore.d.ts +24 -0
  11. package/dist/appendonlystores/network/ServerNetworkContentAddressedStore.d.ts.map +1 -1
  12. package/dist/appendonlystores/network/ServerNetworkContentAddressedStore.js +75 -24
  13. package/dist/appendonlystores/network/ServerNetworkContentAddressedStore.js.map +1 -1
  14. package/dist/browser/index.mjs +72 -0
  15. package/dist/core/BaseMindooDB.d.ts +89 -14
  16. package/dist/core/BaseMindooDB.d.ts.map +1 -1
  17. package/dist/core/BaseMindooDB.js +692 -201
  18. package/dist/core/BaseMindooDB.js.map +1 -1
  19. package/dist/core/BaseMindooTenant.d.ts +59 -7
  20. package/dist/core/BaseMindooTenant.d.ts.map +1 -1
  21. package/dist/core/BaseMindooTenant.js +427 -90
  22. package/dist/core/BaseMindooTenant.js.map +1 -1
  23. package/dist/core/BaseMindooTenantDirectory.d.ts +61 -9
  24. package/dist/core/BaseMindooTenantDirectory.d.ts.map +1 -1
  25. package/dist/core/BaseMindooTenantDirectory.js +363 -35
  26. package/dist/core/BaseMindooTenantDirectory.js.map +1 -1
  27. package/dist/core/BaseMindooTenantFactory.d.ts +17 -1
  28. package/dist/core/BaseMindooTenantFactory.d.ts.map +1 -1
  29. package/dist/core/BaseMindooTenantFactory.js +292 -16
  30. package/dist/core/BaseMindooTenantFactory.js.map +1 -1
  31. package/dist/core/accesscontrol/DirectoryStateNode.d.ts +68 -1
  32. package/dist/core/accesscontrol/DirectoryStateNode.d.ts.map +1 -1
  33. package/dist/core/accesscontrol/DirectoryStateNode.js +157 -4
  34. package/dist/core/accesscontrol/DirectoryStateNode.js.map +1 -1
  35. package/dist/core/accesscontrol/directoryProjection.d.ts.map +1 -1
  36. package/dist/core/accesscontrol/directoryProjection.js +14 -5
  37. package/dist/core/accesscontrol/directoryProjection.js.map +1 -1
  38. package/dist/core/accesscontrol/grantKeys.d.ts +17 -14
  39. package/dist/core/accesscontrol/grantKeys.d.ts.map +1 -1
  40. package/dist/core/accesscontrol/grantKeys.js +51 -21
  41. package/dist/core/accesscontrol/grantKeys.js.map +1 -1
  42. package/dist/core/accesscontrol/types.d.ts +13 -7
  43. package/dist/core/accesscontrol/types.d.ts.map +1 -1
  44. package/dist/core/accesscontrol/types.js +16 -10
  45. package/dist/core/accesscontrol/types.js.map +1 -1
  46. package/dist/core/appendonlystores/network/AuthenticationService.d.ts +7 -0
  47. package/dist/core/appendonlystores/network/AuthenticationService.d.ts.map +1 -1
  48. package/dist/core/appendonlystores/network/AuthenticationService.js +70 -14
  49. package/dist/core/appendonlystores/network/AuthenticationService.js.map +1 -1
  50. package/dist/core/appendonlystores/network/entryWireCodec.d.ts +51 -0
  51. package/dist/core/appendonlystores/network/entryWireCodec.d.ts.map +1 -0
  52. package/dist/core/appendonlystores/network/entryWireCodec.js +93 -0
  53. package/dist/core/appendonlystores/network/entryWireCodec.js.map +1 -0
  54. package/dist/core/builtinDbInvariants.d.ts +53 -0
  55. package/dist/core/builtinDbInvariants.d.ts.map +1 -0
  56. package/dist/core/builtinDbInvariants.js +147 -0
  57. package/dist/core/builtinDbInvariants.js.map +1 -0
  58. package/dist/core/copy/feasibility.d.ts.map +1 -1
  59. package/dist/core/copy/feasibility.js +3 -0
  60. package/dist/core/copy/feasibility.js.map +1 -1
  61. package/dist/core/copy/flatten.d.ts.map +1 -1
  62. package/dist/core/copy/flatten.js +7 -2
  63. package/dist/core/copy/flatten.js.map +1 -1
  64. package/dist/core/copy/host.d.ts +5 -0
  65. package/dist/core/copy/host.d.ts.map +1 -1
  66. package/dist/core/copy/preflight.d.ts.map +1 -1
  67. package/dist/core/copy/preflight.js +7 -1
  68. package/dist/core/copy/preflight.js.map +1 -1
  69. package/dist/core/copy/types.d.ts +8 -1
  70. package/dist/core/copy/types.d.ts.map +1 -1
  71. package/dist/core/crypto/EntrySignature.d.ts +8 -2
  72. package/dist/core/crypto/EntrySignature.d.ts.map +1 -1
  73. package/dist/core/crypto/EntrySignature.js +14 -5
  74. package/dist/core/crypto/EntrySignature.js.map +1 -1
  75. package/dist/core/crypto/MindooDocSigner.d.ts.map +1 -1
  76. package/dist/core/crypto/MindooDocSigner.js +11 -2
  77. package/dist/core/crypto/MindooDocSigner.js.map +1 -1
  78. package/dist/core/crypto/RSAEncryption.d.ts +19 -0
  79. package/dist/core/crypto/RSAEncryption.d.ts.map +1 -1
  80. package/dist/core/crypto/RSAEncryption.js +36 -3
  81. package/dist/core/crypto/RSAEncryption.js.map +1 -1
  82. package/dist/core/crypto/privateKeyEncryption.js +1 -1
  83. package/dist/core/crypto/privateKeyEncryption.js.map +1 -1
  84. package/dist/core/crypto/rsaOaep3072.d.ts +12 -0
  85. package/dist/core/crypto/rsaOaep3072.d.ts.map +1 -0
  86. package/dist/core/crypto/rsaOaep3072.js +30 -0
  87. package/dist/core/crypto/rsaOaep3072.js.map +1 -0
  88. package/dist/core/databaseIdValidation.d.ts +23 -0
  89. package/dist/core/databaseIdValidation.d.ts.map +1 -1
  90. package/dist/core/databaseIdValidation.js +59 -1
  91. package/dist/core/databaseIdValidation.js.map +1 -1
  92. package/dist/core/index.d.ts +9 -2
  93. package/dist/core/index.d.ts.map +1 -1
  94. package/dist/core/index.js +40 -4
  95. package/dist/core/index.js.map +1 -1
  96. package/dist/core/join/deviceJoinBootstrap.d.ts +23 -0
  97. package/dist/core/join/deviceJoinBootstrap.d.ts.map +1 -0
  98. package/dist/core/join/deviceJoinBootstrap.js +37 -0
  99. package/dist/core/join/deviceJoinBootstrap.js.map +1 -0
  100. package/dist/core/keys/KeyBag.d.ts +20 -2
  101. package/dist/core/keys/KeyBag.d.ts.map +1 -1
  102. package/dist/core/keys/KeyBag.js +22 -10
  103. package/dist/core/keys/KeyBag.js.map +1 -1
  104. package/dist/core/logging/MindooLogger.d.ts.map +1 -1
  105. package/dist/core/logging/MindooLogger.js +65 -40
  106. package/dist/core/logging/MindooLogger.js.map +1 -1
  107. package/dist/core/tenantIdValidation.d.ts.map +1 -1
  108. package/dist/core/tenantIdValidation.js +1 -1
  109. package/dist/core/tenantIdValidation.js.map +1 -1
  110. package/dist/core/tenantSetup.d.ts +109 -0
  111. package/dist/core/tenantSetup.d.ts.map +1 -0
  112. package/dist/core/tenantSetup.js +250 -0
  113. package/dist/core/tenantSetup.js.map +1 -0
  114. package/dist/core/types.d.ts +333 -43
  115. package/dist/core/types.d.ts.map +1 -1
  116. package/dist/core/types.js +27 -9
  117. package/dist/core/types.js.map +1 -1
  118. package/dist/core/uri/joinRequestUri.d.ts +37 -0
  119. package/dist/core/uri/joinRequestUri.d.ts.map +1 -0
  120. package/dist/core/uri/joinRequestUri.js +168 -0
  121. package/dist/core/uri/joinRequestUri.js.map +1 -0
  122. package/dist/core/userid/canonicalUsername.d.ts +66 -0
  123. package/dist/core/userid/canonicalUsername.d.ts.map +1 -0
  124. package/dist/core/userid/canonicalUsername.js +235 -0
  125. package/dist/core/userid/canonicalUsername.js.map +1 -0
  126. package/dist/core/userid/index.d.ts +9 -0
  127. package/dist/core/userid/index.d.ts.map +1 -1
  128. package/dist/core/userid/index.js +14 -0
  129. package/dist/core/userid/index.js.map +1 -1
  130. package/dist/core/userkeys/UserKeyDocument.d.ts +50 -0
  131. package/dist/core/userkeys/UserKeyDocument.d.ts.map +1 -0
  132. package/dist/core/userkeys/UserKeyDocument.js +145 -0
  133. package/dist/core/userkeys/UserKeyDocument.js.map +1 -0
  134. package/dist/core/userkeys/UserKeyManager.d.ts +170 -0
  135. package/dist/core/userkeys/UserKeyManager.d.ts.map +1 -0
  136. package/dist/core/userkeys/UserKeyManager.js +1277 -0
  137. package/dist/core/userkeys/UserKeyManager.js.map +1 -0
  138. package/dist/core/userkeys/fingerprint.d.ts +17 -0
  139. package/dist/core/userkeys/fingerprint.d.ts.map +1 -0
  140. package/dist/core/userkeys/fingerprint.js +59 -0
  141. package/dist/core/userkeys/fingerprint.js.map +1 -0
  142. package/dist/core/userkeys/index.d.ts +11 -0
  143. package/dist/core/userkeys/index.d.ts.map +1 -0
  144. package/dist/core/userkeys/index.js +49 -0
  145. package/dist/core/userkeys/index.js.map +1 -0
  146. package/dist/core/userkeys/recipients.d.ts +51 -0
  147. package/dist/core/userkeys/recipients.d.ts.map +1 -0
  148. package/dist/core/userkeys/recipients.js +292 -0
  149. package/dist/core/userkeys/recipients.js.map +1 -0
  150. package/dist/core/userkeys/resolveUserKeyDocument.d.ts +21 -0
  151. package/dist/core/userkeys/resolveUserKeyDocument.d.ts.map +1 -0
  152. package/dist/core/userkeys/resolveUserKeyDocument.js +98 -0
  153. package/dist/core/userkeys/resolveUserKeyDocument.js.map +1 -0
  154. package/dist/core/userkeys/sealedCrypto.d.ts +21 -0
  155. package/dist/core/userkeys/sealedCrypto.d.ts.map +1 -0
  156. package/dist/core/userkeys/sealedCrypto.js +79 -0
  157. package/dist/core/userkeys/sealedCrypto.js.map +1 -0
  158. package/dist/core/userkeys/sealedTypes.d.ts +72 -0
  159. package/dist/core/userkeys/sealedTypes.d.ts.map +1 -0
  160. package/dist/core/userkeys/sealedTypes.js +14 -0
  161. package/dist/core/userkeys/sealedTypes.js.map +1 -0
  162. package/dist/core/userkeys/types.d.ts +70 -0
  163. package/dist/core/userkeys/types.d.ts.map +1 -0
  164. package/dist/core/userkeys/types.js +48 -0
  165. package/dist/core/userkeys/types.js.map +1 -0
  166. package/dist/core/userkeys/validateUserKeyDocument.d.ts +19 -0
  167. package/dist/core/userkeys/validateUserKeyDocument.d.ts.map +1 -0
  168. package/dist/core/userkeys/validateUserKeyDocument.js +42 -0
  169. package/dist/core/userkeys/validateUserKeyDocument.js.map +1 -0
  170. package/dist/core/utils/idGeneration.d.ts +39 -20
  171. package/dist/core/utils/idGeneration.d.ts.map +1 -1
  172. package/dist/core/utils/idGeneration.js +82 -62
  173. package/dist/core/utils/idGeneration.js.map +1 -1
  174. package/dist/core/utils/index.d.ts +1 -1
  175. package/dist/core/utils/index.d.ts.map +1 -1
  176. package/dist/core/utils/index.js +4 -1
  177. package/dist/core/utils/index.js.map +1 -1
  178. package/dist/node/server/CapabilityMatcher.d.ts +5 -0
  179. package/dist/node/server/CapabilityMatcher.d.ts.map +1 -1
  180. package/dist/node/server/CapabilityMatcher.js +10 -1
  181. package/dist/node/server/CapabilityMatcher.js.map +1 -1
  182. package/dist/node/server/DeviceDiscoveryService.d.ts +36 -0
  183. package/dist/node/server/DeviceDiscoveryService.d.ts.map +1 -0
  184. package/dist/node/server/DeviceDiscoveryService.js +165 -0
  185. package/dist/node/server/DeviceDiscoveryService.js.map +1 -0
  186. package/dist/node/server/MindooDBServer.d.ts +13 -0
  187. package/dist/node/server/MindooDBServer.d.ts.map +1 -1
  188. package/dist/node/server/MindooDBServer.js +99 -61
  189. package/dist/node/server/MindooDBServer.js.map +1 -1
  190. package/dist/node/server/SystemAdminAuth.d.ts +7 -0
  191. package/dist/node/server/SystemAdminAuth.d.ts.map +1 -1
  192. package/dist/node/server/SystemAdminAuth.js +4 -1
  193. package/dist/node/server/SystemAdminAuth.js.map +1 -1
  194. package/dist/node/server/TenantManager.d.ts +29 -0
  195. package/dist/node/server/TenantManager.d.ts.map +1 -1
  196. package/dist/node/server/TenantManager.js +146 -7
  197. package/dist/node/server/TenantManager.js.map +1 -1
  198. package/package.json +5 -5
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Tenant setup document helpers.
3
+ *
4
+ * The singleton directory document `tenantsetup` is encrypted under
5
+ * `$publicinfos` so it syncs to every member (and to the sync server). The
6
+ * human-readable tenant label itself is field-encrypted under the tenant
7
+ * `default` key (`label_encrypted` / `label_encrypted_key`) so the server
8
+ * cannot read the display name — same pattern as `user_details_encrypted`
9
+ * on grant documents.
10
+ *
11
+ * The document also records the tenant's administrators. An admin holds no
12
+ * `grantaccess` document of its own, so without this list a member can only
13
+ * name the administration key by its fingerprint. Each entry carries the
14
+ * admin's name field-encrypted under `default` plus its device key pairs in
15
+ * the very same `userKeyPairs` shape a grant uses (docs/accesscontrol.md
16
+ * §6.5), so the same helpers read and write both, and additional admins or
17
+ * admin devices can be appended later.
18
+ */
19
+ import { GrantKeyPair, MindooDB, MindooTenant, TENANT_SETUP_DOC_ID, SigningKeyPair } from "./types";
20
+ export { TENANT_SETUP_DOC_ID };
21
+ /**
22
+ * One administrator as stored on the `tenantsetup` document. The name is
23
+ * field-encrypted under `default`; the device keys use the canonical
24
+ * `userKeyPairs` list of a grant document so both can be parsed by
25
+ * {@link extractKeyPairs}.
26
+ */
27
+ export interface TenantAdministratorData {
28
+ /** Base64 AES-GCM ciphertext of the canonical username under `default`. */
29
+ username_encrypted?: string;
30
+ /** Key id used for `username_encrypted`; always `"default"`. */
31
+ username_encrypted_key?: string;
32
+ /** This admin's device key pairs, same shape as a grant's `userKeyPairs`. */
33
+ userKeyPairs?: unknown;
34
+ /** Trusted time (ms since Unix epoch) at which the entry was first written. */
35
+ addedAt?: number;
36
+ }
37
+ export interface TenantSetupData {
38
+ /**
39
+ * @deprecated Legacy plaintext label. New writes use `label_encrypted`.
40
+ * Still read for older tenants until the next admin write migrates them.
41
+ */
42
+ label?: string;
43
+ /** Base64 AES-GCM ciphertext of the UTF-8 label under `default`. */
44
+ label_encrypted?: string;
45
+ /** Key id used for `label_encrypted`; always `"default"`. */
46
+ label_encrypted_key?: string;
47
+ /** The tenant's administrators, oldest first. */
48
+ administrators?: TenantAdministratorData[];
49
+ }
50
+ /** An administrator entry with its name decrypted, as read by callers. */
51
+ export interface TenantAdministrator {
52
+ /**
53
+ * Canonical username. Absent when the reader has no `default` key (e.g. a
54
+ * device that joined but has not imported the tenant key yet).
55
+ */
56
+ username?: string;
57
+ /** The admin's device key pairs (§6.5), active ones first. */
58
+ keyPairs: GrantKeyPair[];
59
+ addedAt?: number;
60
+ }
61
+ /**
62
+ * Read the tenant label from the directory database's `tenantsetup` document.
63
+ * Requires the tenant `default` key to decrypt `label_encrypted`. Returns
64
+ * `undefined` when the document is missing, the key is absent, or there is no
65
+ * label. Legacy plaintext `label` is still accepted for older tenants.
66
+ */
67
+ export declare function readTenantSetupLabel(directoryDb: MindooDB, tenant: MindooTenant): Promise<string | undefined>;
68
+ /**
69
+ * Create or update the `tenantsetup` document with the given label.
70
+ * Must be signed with the tenant admin signing key. Stores the label as
71
+ * `label_encrypted` under the tenant `default` key and clears any legacy
72
+ * plaintext `label` field.
73
+ */
74
+ export declare function writeTenantSetupLabel(directoryDb: MindooDB, label: string, adminSigningKeyPair: SigningKeyPair, adminSigningKeyPassword: string, tenant: MindooTenant): Promise<void>;
75
+ /**
76
+ * The tenant's administrators from the `tenantsetup` document, oldest first.
77
+ * Names need the tenant `default` key; entries whose name cannot be decrypted
78
+ * are still returned (with their key pairs) so callers can at least match a
79
+ * signing key. Returns an empty list for tenants created before this field.
80
+ */
81
+ export declare function readTenantSetupAdministrators(directoryDb: MindooDB, tenant: MindooTenant): Promise<TenantAdministrator[]>;
82
+ /**
83
+ * Record an administrator on the `tenantsetup` document: its name
84
+ * field-encrypted under `default` plus its device key pairs. Must be signed
85
+ * with the tenant admin signing key.
86
+ *
87
+ * An entry for the same admin — matched by name, or by sharing a signing key
88
+ * when the name is unreadable — is updated in place and has its key pairs
89
+ * merged, so passing only a new pair enrolls another device of an admin that is
90
+ * already listed. Otherwise a new entry is appended. Idempotent when called
91
+ * again with the same name and keys.
92
+ */
93
+ export declare function writeTenantSetupAdministrator(directoryDb: MindooDB, administrator: {
94
+ username: string;
95
+ keyPairs: GrantKeyPair[];
96
+ }, adminSigningKeyPair: SigningKeyPair, adminSigningKeyPassword: string, tenant: MindooTenant): Promise<void>;
97
+ /**
98
+ * Record an administrator only when it is missing from `tenantsetup`, and
99
+ * report whether a write happened. Tenants created before the
100
+ * `administrators` field have no entry at all, and a grant is a natural moment
101
+ * to heal that: the admin proves its identity and its keys there anyway. The
102
+ * check keeps repeated grants from appending a no-op revision to the
103
+ * append-only store.
104
+ */
105
+ export declare function ensureTenantSetupAdministrator(directoryDb: MindooDB, administrator: {
106
+ username: string;
107
+ keyPairs: GrantKeyPair[];
108
+ }, adminSigningKeyPair: SigningKeyPair, adminSigningKeyPassword: string, tenant: MindooTenant): Promise<boolean>;
109
+ //# sourceMappingURL=tenantSetup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenantSetup.d.ts","sourceRoot":"","sources":["../../src/core/tenantSetup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAEL,YAAY,EACZ,QAAQ,EACR,YAAY,EAEZ,mBAAmB,EACnB,cAAc,EACf,MAAM,SAAS,CAAC;AAOjB,OAAO,EAAE,mBAAmB,EAAE,CAAC;AAE/B;;;;;GAKG;AACH,MAAM,WAAW,uBAAuB;IACtC,2EAA2E;IAC3E,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,gEAAgE;IAChE,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,6EAA6E;IAC7E,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,+EAA+E;IAC/E,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oEAAoE;IACpE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,6DAA6D;IAC7D,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,iDAAiD;IACjD,cAAc,CAAC,EAAE,uBAAuB,EAAE,CAAC;CAC5C;AAED,0EAA0E;AAC1E,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8DAA8D;IAC9D,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAsDD;;;;;GAKG;AACH,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,QAAQ,EACrB,MAAM,EAAE,YAAY,GACnB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAoB7B;AAED;;;;;GAKG;AACH,wBAAsB,qBAAqB,CACzC,WAAW,EAAE,QAAQ,EACrB,KAAK,EAAE,MAAM,EACb,mBAAmB,EAAE,cAAc,EACnC,uBAAuB,EAAE,MAAM,EAC/B,MAAM,EAAE,YAAY,GACnB,OAAO,CAAC,IAAI,CAAC,CAaf;AAsCD;;;;;GAKG;AACH,wBAAsB,6BAA6B,CACjD,WAAW,EAAE,QAAQ,EACrB,MAAM,EAAE,YAAY,GACnB,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAwBhC;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,6BAA6B,CACjD,WAAW,EAAE,QAAQ,EACrB,aAAa,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,YAAY,EAAE,CAAA;CAAE,EAC7D,mBAAmB,EAAE,cAAc,EACnC,uBAAuB,EAAE,MAAM,EAC/B,MAAM,EAAE,YAAY,GACnB,OAAO,CAAC,IAAI,CAAC,CAkDf;AAED;;;;;;;GAOG;AACH,wBAAsB,8BAA8B,CAClD,WAAW,EAAE,QAAQ,EACrB,aAAa,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,YAAY,EAAE,CAAA;CAAE,EAC7D,mBAAmB,EAAE,cAAc,EACnC,uBAAuB,EAAE,MAAM,EAC/B,MAAM,EAAE,YAAY,GACnB,OAAO,CAAC,OAAO,CAAC,CA2BlB"}
@@ -0,0 +1,250 @@
1
+ "use strict";
2
+ /**
3
+ * Tenant setup document helpers.
4
+ *
5
+ * The singleton directory document `tenantsetup` is encrypted under
6
+ * `$publicinfos` so it syncs to every member (and to the sync server). The
7
+ * human-readable tenant label itself is field-encrypted under the tenant
8
+ * `default` key (`label_encrypted` / `label_encrypted_key`) so the server
9
+ * cannot read the display name — same pattern as `user_details_encrypted`
10
+ * on grant documents.
11
+ *
12
+ * The document also records the tenant's administrators. An admin holds no
13
+ * `grantaccess` document of its own, so without this list a member can only
14
+ * name the administration key by its fingerprint. Each entry carries the
15
+ * admin's name field-encrypted under `default` plus its device key pairs in
16
+ * the very same `userKeyPairs` shape a grant uses (docs/accesscontrol.md
17
+ * §6.5), so the same helpers read and write both, and additional admins or
18
+ * admin devices can be appended later.
19
+ */
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ exports.TENANT_SETUP_DOC_ID = void 0;
22
+ exports.readTenantSetupLabel = readTenantSetupLabel;
23
+ exports.writeTenantSetupLabel = writeTenantSetupLabel;
24
+ exports.readTenantSetupAdministrators = readTenantSetupAdministrators;
25
+ exports.writeTenantSetupAdministrator = writeTenantSetupAdministrator;
26
+ exports.ensureTenantSetupAdministrator = ensureTenantSetupAdministrator;
27
+ const types_1 = require("./types");
28
+ Object.defineProperty(exports, "TENANT_SETUP_DOC_ID", { enumerable: true, get: function () { return types_1.TENANT_SETUP_DOC_ID; } });
29
+ const encryptedFields_1 = require("./crypto/encryptedFields");
30
+ const grantKeys_1 = require("./accesscontrol/grantKeys");
31
+ const DirectoryStateNode_1 = require("./accesscontrol/DirectoryStateNode");
32
+ const canonicalUsername_1 = require("./userid/canonicalUsername");
33
+ const timeSource_1 = require("./utils/timeSource");
34
+ function uint8ArrayToBase64(bytes) {
35
+ let binary = "";
36
+ for (let i = 0; i < bytes.length; i++) {
37
+ binary += String.fromCharCode(bytes[i]);
38
+ }
39
+ return btoa(binary);
40
+ }
41
+ /** Field-encrypt a string under the tenant `default` key. */
42
+ async function encryptUnderDefaultKey(tenant, value) {
43
+ const encrypted = await tenant.encryptPayload(new TextEncoder().encode(value), types_1.DEFAULT_TENANT_KEY_ID);
44
+ return uint8ArrayToBase64(encrypted);
45
+ }
46
+ /**
47
+ * Apply a mutation to the `tenantsetup` document, creating it (under
48
+ * `$publicinfos`) when it does not exist yet. Must be signed with the tenant
49
+ * admin signing key.
50
+ */
51
+ async function changeTenantSetup(directoryDb, adminSigningKeyPair, adminSigningKeyPassword, mutate) {
52
+ let doc;
53
+ try {
54
+ doc = await directoryDb.getDocument(types_1.TENANT_SETUP_DOC_ID);
55
+ }
56
+ catch {
57
+ doc = await directoryDb.createDocument({
58
+ id: types_1.TENANT_SETUP_DOC_ID,
59
+ signingKeyPair: adminSigningKeyPair,
60
+ signingKeyPassword: adminSigningKeyPassword,
61
+ decryptionKeyId: types_1.PUBLIC_INFOS_KEY_ID,
62
+ });
63
+ }
64
+ await directoryDb.changeDoc(doc, (d) => {
65
+ mutate(d.getData());
66
+ }, {
67
+ signingKeyPair: adminSigningKeyPair,
68
+ signingKeyPassword: adminSigningKeyPassword,
69
+ });
70
+ }
71
+ /**
72
+ * Read the tenant label from the directory database's `tenantsetup` document.
73
+ * Requires the tenant `default` key to decrypt `label_encrypted`. Returns
74
+ * `undefined` when the document is missing, the key is absent, or there is no
75
+ * label. Legacy plaintext `label` is still accepted for older tenants.
76
+ */
77
+ async function readTenantSetupLabel(directoryDb, tenant) {
78
+ try {
79
+ const doc = await directoryDb.getDocument(types_1.TENANT_SETUP_DOC_ID);
80
+ const data = doc.getData();
81
+ const decrypted = await (0, encryptedFields_1.decryptEncryptedField)(tenant, data, "label_encrypted");
82
+ if (typeof decrypted === "string") {
83
+ const trimmed = decrypted.trim();
84
+ if (trimmed.length > 0)
85
+ return trimmed;
86
+ }
87
+ // Legacy: plaintext label written before field encryption.
88
+ if (typeof data.label === "string") {
89
+ const trimmed = data.label.trim();
90
+ return trimmed.length > 0 ? trimmed : undefined;
91
+ }
92
+ }
93
+ catch {
94
+ // Document missing or unreadable.
95
+ }
96
+ return undefined;
97
+ }
98
+ /**
99
+ * Create or update the `tenantsetup` document with the given label.
100
+ * Must be signed with the tenant admin signing key. Stores the label as
101
+ * `label_encrypted` under the tenant `default` key and clears any legacy
102
+ * plaintext `label` field.
103
+ */
104
+ async function writeTenantSetupLabel(directoryDb, label, adminSigningKeyPair, adminSigningKeyPassword, tenant) {
105
+ const trimmed = label.trim();
106
+ if (!trimmed) {
107
+ throw new Error("Tenant label must be a non-empty string");
108
+ }
109
+ const labelEncrypted = await encryptUnderDefaultKey(tenant, trimmed);
110
+ await changeTenantSetup(directoryDb, adminSigningKeyPair, adminSigningKeyPassword, (data) => {
111
+ data.label_encrypted = labelEncrypted;
112
+ data.label_encrypted_key = types_1.DEFAULT_TENANT_KEY_ID;
113
+ delete data.label;
114
+ });
115
+ }
116
+ /** Normalize a stored administrator entry into a plain, writable object. */
117
+ function normalizeAdministratorEntry(entry) {
118
+ if (!entry || typeof entry !== "object")
119
+ return null;
120
+ const record = entry;
121
+ const pairs = (0, grantKeys_1.extractKeyPairs)(record);
122
+ if (pairs.length === 0)
123
+ return null;
124
+ const normalized = { userKeyPairs: pairs.map(toStoredKeyPair) };
125
+ if (typeof record.username_encrypted === "string" && record.username_encrypted) {
126
+ normalized.username_encrypted = record.username_encrypted;
127
+ normalized.username_encrypted_key =
128
+ typeof record.username_encrypted_key === "string" && record.username_encrypted_key
129
+ ? record.username_encrypted_key
130
+ : types_1.DEFAULT_TENANT_KEY_ID;
131
+ }
132
+ if (typeof record.addedAt === "number")
133
+ normalized.addedAt = record.addedAt;
134
+ return normalized;
135
+ }
136
+ /** A {@link GrantKeyPair} reduced to the fields stored on the document. */
137
+ function toStoredKeyPair(pair) {
138
+ const stored = {
139
+ signingPublicKey: pair.signingPublicKey,
140
+ encryptionPublicKey: pair.encryptionPublicKey,
141
+ };
142
+ if (pair.label)
143
+ stored.label = pair.label;
144
+ if (typeof pair.addedAt === "number")
145
+ stored.addedAt = pair.addedAt;
146
+ return stored;
147
+ }
148
+ function administratorEntries(data) {
149
+ if (!Array.isArray(data.administrators))
150
+ return [];
151
+ return data.administrators
152
+ .map(normalizeAdministratorEntry)
153
+ .filter((entry) => entry !== null);
154
+ }
155
+ /**
156
+ * The tenant's administrators from the `tenantsetup` document, oldest first.
157
+ * Names need the tenant `default` key; entries whose name cannot be decrypted
158
+ * are still returned (with their key pairs) so callers can at least match a
159
+ * signing key. Returns an empty list for tenants created before this field.
160
+ */
161
+ async function readTenantSetupAdministrators(directoryDb, tenant) {
162
+ let entries = [];
163
+ try {
164
+ const doc = await directoryDb.getDocument(types_1.TENANT_SETUP_DOC_ID);
165
+ entries = administratorEntries(doc.getData());
166
+ }
167
+ catch {
168
+ return [];
169
+ }
170
+ const administrators = [];
171
+ for (const entry of entries) {
172
+ const decrypted = await (0, encryptedFields_1.decryptEncryptedField)(tenant, entry, "username_encrypted");
173
+ const username = typeof decrypted === "string" ? decrypted.trim() : "";
174
+ administrators.push({
175
+ ...(username ? { username } : {}),
176
+ keyPairs: (0, grantKeys_1.extractKeyPairs)(entry),
177
+ ...(typeof entry.addedAt === "number" ? { addedAt: entry.addedAt } : {}),
178
+ });
179
+ }
180
+ return administrators;
181
+ }
182
+ /**
183
+ * Record an administrator on the `tenantsetup` document: its name
184
+ * field-encrypted under `default` plus its device key pairs. Must be signed
185
+ * with the tenant admin signing key.
186
+ *
187
+ * An entry for the same admin — matched by name, or by sharing a signing key
188
+ * when the name is unreadable — is updated in place and has its key pairs
189
+ * merged, so passing only a new pair enrolls another device of an admin that is
190
+ * already listed. Otherwise a new entry is appended. Idempotent when called
191
+ * again with the same name and keys.
192
+ */
193
+ async function writeTenantSetupAdministrator(directoryDb, administrator, adminSigningKeyPair, adminSigningKeyPassword, tenant) {
194
+ const username = administrator.username.trim();
195
+ if (!username) {
196
+ throw new Error("Administrator username must be a non-empty string");
197
+ }
198
+ const incoming = administrator.keyPairs.filter((pair) => pair.signingPublicKey.trim().length > 0);
199
+ if (incoming.length === 0) {
200
+ throw new Error("Administrator must have at least one signing key");
201
+ }
202
+ const usernameEncrypted = await encryptUnderDefaultKey(tenant, username);
203
+ const now = (0, timeSource_1.semanticNow)();
204
+ // Names are only comparable after decryption, which cannot happen inside the
205
+ // synchronous document mutation below.
206
+ const existingIndex = (await readTenantSetupAdministrators(directoryDb, tenant)).findIndex((entry) => entry.username
207
+ ? (0, canonicalUsername_1.usernamesEqual)(entry.username, username)
208
+ : entry.keyPairs.some((pair) => incoming.some((candidate) => (0, DirectoryStateNode_1.signingKeysEqual)(pair.signingPublicKey, candidate.signingPublicKey))));
209
+ await changeTenantSetup(directoryDb, adminSigningKeyPair, adminSigningKeyPassword, (data) => {
210
+ const entries = administratorEntries(data);
211
+ const target = existingIndex >= 0 ? entries[existingIndex] ?? { addedAt: now } : { addedAt: now };
212
+ const merged = (0, grantKeys_1.mergeKeyPairs)((0, grantKeys_1.extractKeyPairs)(target), incoming.map((pair) => ({ ...pair, addedAt: pair.addedAt ?? now })));
213
+ const next = {
214
+ username_encrypted: usernameEncrypted,
215
+ username_encrypted_key: types_1.DEFAULT_TENANT_KEY_ID,
216
+ userKeyPairs: merged.map(toStoredKeyPair),
217
+ addedAt: typeof target.addedAt === "number" ? target.addedAt : now,
218
+ };
219
+ if (existingIndex >= 0 && existingIndex < entries.length) {
220
+ entries[existingIndex] = next;
221
+ }
222
+ else {
223
+ entries.push(next);
224
+ }
225
+ data.administrators = entries;
226
+ });
227
+ }
228
+ /**
229
+ * Record an administrator only when it is missing from `tenantsetup`, and
230
+ * report whether a write happened. Tenants created before the
231
+ * `administrators` field have no entry at all, and a grant is a natural moment
232
+ * to heal that: the admin proves its identity and its keys there anyway. The
233
+ * check keeps repeated grants from appending a no-op revision to the
234
+ * append-only store.
235
+ */
236
+ async function ensureTenantSetupAdministrator(directoryDb, administrator, adminSigningKeyPair, adminSigningKeyPassword, tenant) {
237
+ const username = administrator.username.trim();
238
+ if (!username) {
239
+ throw new Error("Administrator username must be a non-empty string");
240
+ }
241
+ const recorded = await readTenantSetupAdministrators(directoryDb, tenant);
242
+ const isComplete = recorded.some((entry) => entry.username !== undefined &&
243
+ (0, canonicalUsername_1.usernamesEqual)(entry.username, username) &&
244
+ administrator.keyPairs.every((candidate) => entry.keyPairs.some((pair) => (0, DirectoryStateNode_1.signingKeysEqual)(pair.signingPublicKey, candidate.signingPublicKey))));
245
+ if (isComplete)
246
+ return false;
247
+ await writeTenantSetupAdministrator(directoryDb, administrator, adminSigningKeyPair, adminSigningKeyPassword, tenant);
248
+ return true;
249
+ }
250
+ //# sourceMappingURL=tenantSetup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenantSetup.js","sourceRoot":"","sources":["../../src/core/tenantSetup.ts"],"names":[],"mappings":"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"}