was-teaching-server 0.9.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 (295) hide show
  1. package/CHANGELOG.md +1432 -0
  2. package/LICENSE +661 -0
  3. package/README.md +305 -0
  4. package/common/css/materialize.1.0.0.min.css +13 -0
  5. package/dist/auth-header-hooks.d.ts +84 -0
  6. package/dist/auth-header-hooks.d.ts.map +1 -0
  7. package/dist/auth-header-hooks.js +136 -0
  8. package/dist/auth-header-hooks.js.map +1 -0
  9. package/dist/authorize.d.ts +45 -0
  10. package/dist/authorize.d.ts.map +1 -0
  11. package/dist/authorize.js +76 -0
  12. package/dist/authorize.js.map +1 -0
  13. package/dist/backends/filesystem.d.ts +1179 -0
  14. package/dist/backends/filesystem.d.ts.map +1 -0
  15. package/dist/backends/filesystem.js +2727 -0
  16. package/dist/backends/filesystem.js.map +1 -0
  17. package/dist/backends/postgres.d.ts +833 -0
  18. package/dist/backends/postgres.d.ts.map +1 -0
  19. package/dist/backends/postgres.js +2164 -0
  20. package/dist/backends/postgres.js.map +1 -0
  21. package/dist/backends/postgresSchema.d.ts +36 -0
  22. package/dist/backends/postgresSchema.d.ts.map +1 -0
  23. package/dist/backends/postgresSchema.js +203 -0
  24. package/dist/backends/postgresSchema.js.map +1 -0
  25. package/dist/config.default.d.ts +360 -0
  26. package/dist/config.default.d.ts.map +1 -0
  27. package/dist/config.default.js +493 -0
  28. package/dist/config.default.js.map +1 -0
  29. package/dist/corsProxy.d.ts +45 -0
  30. package/dist/corsProxy.d.ts.map +1 -0
  31. package/dist/corsProxy.js +278 -0
  32. package/dist/corsProxy.js.map +1 -0
  33. package/dist/digest.d.ts +45 -0
  34. package/dist/digest.d.ts.map +1 -0
  35. package/dist/digest.js +174 -0
  36. package/dist/digest.js.map +1 -0
  37. package/dist/errors.d.ts +654 -0
  38. package/dist/errors.d.ts.map +1 -0
  39. package/dist/errors.js +960 -0
  40. package/dist/errors.js.map +1 -0
  41. package/dist/index.d.ts +22 -0
  42. package/dist/index.d.ts.map +1 -0
  43. package/dist/index.js +21 -0
  44. package/dist/index.js.map +1 -0
  45. package/dist/lib/atomicFile.d.ts +61 -0
  46. package/dist/lib/atomicFile.d.ts.map +1 -0
  47. package/dist/lib/atomicFile.js +150 -0
  48. package/dist/lib/atomicFile.js.map +1 -0
  49. package/dist/lib/backendRegistry.d.ts +59 -0
  50. package/dist/lib/backendRegistry.d.ts.map +1 -0
  51. package/dist/lib/backendRegistry.js +92 -0
  52. package/dist/lib/backendRegistry.js.map +1 -0
  53. package/dist/lib/backendUsage.d.ts +28 -0
  54. package/dist/lib/backendUsage.d.ts.map +1 -0
  55. package/dist/lib/backendUsage.js +55 -0
  56. package/dist/lib/backendUsage.js.map +1 -0
  57. package/dist/lib/backends.d.ts +142 -0
  58. package/dist/lib/backends.d.ts.map +1 -0
  59. package/dist/lib/backends.js +272 -0
  60. package/dist/lib/backends.js.map +1 -0
  61. package/dist/lib/blindedIndex.d.ts +156 -0
  62. package/dist/lib/blindedIndex.d.ts.map +1 -0
  63. package/dist/lib/blindedIndex.js +338 -0
  64. package/dist/lib/blindedIndex.js.map +1 -0
  65. package/dist/lib/collectionDescription.d.ts +33 -0
  66. package/dist/lib/collectionDescription.d.ts.map +1 -0
  67. package/dist/lib/collectionDescription.js +21 -0
  68. package/dist/lib/collectionDescription.js.map +1 -0
  69. package/dist/lib/cursor.d.ts +18 -0
  70. package/dist/lib/cursor.d.ts.map +1 -0
  71. package/dist/lib/cursor.js +50 -0
  72. package/dist/lib/cursor.js.map +1 -0
  73. package/dist/lib/edvEnvelope.d.ts +50 -0
  74. package/dist/lib/edvEnvelope.d.ts.map +1 -0
  75. package/dist/lib/edvEnvelope.js +106 -0
  76. package/dist/lib/edvEnvelope.js.map +1 -0
  77. package/dist/lib/encryption.d.ts +192 -0
  78. package/dist/lib/encryption.d.ts.map +1 -0
  79. package/dist/lib/encryption.js +383 -0
  80. package/dist/lib/encryption.js.map +1 -0
  81. package/dist/lib/etag.d.ts +33 -0
  82. package/dist/lib/etag.d.ts.map +1 -0
  83. package/dist/lib/etag.js +36 -0
  84. package/dist/lib/etag.js.map +1 -0
  85. package/dist/lib/exportManifest.d.ts +29 -0
  86. package/dist/lib/exportManifest.d.ts.map +1 -0
  87. package/dist/lib/exportManifest.js +77 -0
  88. package/dist/lib/exportManifest.js.map +1 -0
  89. package/dist/lib/importTar.d.ts +81 -0
  90. package/dist/lib/importTar.d.ts.map +1 -0
  91. package/dist/lib/importTar.js +301 -0
  92. package/dist/lib/importTar.js.map +1 -0
  93. package/dist/lib/isJson.d.ts +16 -0
  94. package/dist/lib/isJson.d.ts.map +1 -0
  95. package/dist/lib/isJson.js +17 -0
  96. package/dist/lib/isJson.js.map +1 -0
  97. package/dist/lib/keyEpoch.d.ts +38 -0
  98. package/dist/lib/keyEpoch.d.ts.map +1 -0
  99. package/dist/lib/keyEpoch.js +75 -0
  100. package/dist/lib/keyEpoch.js.map +1 -0
  101. package/dist/lib/keyedMutex.d.ts +28 -0
  102. package/dist/lib/keyedMutex.d.ts.map +1 -0
  103. package/dist/lib/keyedMutex.js +45 -0
  104. package/dist/lib/keyedMutex.js.map +1 -0
  105. package/dist/lib/kmsModule.d.ts +62 -0
  106. package/dist/lib/kmsModule.d.ts.map +1 -0
  107. package/dist/lib/kmsModule.js +327 -0
  108. package/dist/lib/kmsModule.js.map +1 -0
  109. package/dist/lib/kmsRecordCipher.d.ts +82 -0
  110. package/dist/lib/kmsRecordCipher.d.ts.map +1 -0
  111. package/dist/lib/kmsRecordCipher.js +226 -0
  112. package/dist/lib/kmsRecordCipher.js.map +1 -0
  113. package/dist/lib/pagination.d.ts +19 -0
  114. package/dist/lib/pagination.d.ts.map +1 -0
  115. package/dist/lib/pagination.js +21 -0
  116. package/dist/lib/pagination.js.map +1 -0
  117. package/dist/lib/paths.d.ts +273 -0
  118. package/dist/lib/paths.d.ts.map +1 -0
  119. package/dist/lib/paths.js +270 -0
  120. package/dist/lib/paths.js.map +1 -0
  121. package/dist/lib/preconditions.d.ts +65 -0
  122. package/dist/lib/preconditions.d.ts.map +1 -0
  123. package/dist/lib/preconditions.js +112 -0
  124. package/dist/lib/preconditions.js.map +1 -0
  125. package/dist/lib/resourceFileName.d.ts +41 -0
  126. package/dist/lib/resourceFileName.d.ts.map +1 -0
  127. package/dist/lib/resourceFileName.js +58 -0
  128. package/dist/lib/resourceFileName.js.map +1 -0
  129. package/dist/lib/revocations.d.ts +49 -0
  130. package/dist/lib/revocations.d.ts.map +1 -0
  131. package/dist/lib/revocations.js +86 -0
  132. package/dist/lib/revocations.js.map +1 -0
  133. package/dist/lib/validateDid.d.ts +19 -0
  134. package/dist/lib/validateDid.d.ts.map +1 -0
  135. package/dist/lib/validateDid.js +35 -0
  136. package/dist/lib/validateDid.js.map +1 -0
  137. package/dist/lib/validateId.d.ts +66 -0
  138. package/dist/lib/validateId.d.ts.map +1 -0
  139. package/dist/lib/validateId.js +126 -0
  140. package/dist/lib/validateId.js.map +1 -0
  141. package/dist/plugin.d.ts +115 -0
  142. package/dist/plugin.d.ts.map +1 -0
  143. package/dist/plugin.js +134 -0
  144. package/dist/plugin.js.map +1 -0
  145. package/dist/policy.d.ts +78 -0
  146. package/dist/policy.d.ts.map +1 -0
  147. package/dist/policy.js +115 -0
  148. package/dist/policy.js.map +1 -0
  149. package/dist/provisioning.d.ts +38 -0
  150. package/dist/provisioning.d.ts.map +1 -0
  151. package/dist/provisioning.js +72 -0
  152. package/dist/provisioning.js.map +1 -0
  153. package/dist/requests/BackendRequest.d.ts +61 -0
  154. package/dist/requests/BackendRequest.d.ts.map +1 -0
  155. package/dist/requests/BackendRequest.js +152 -0
  156. package/dist/requests/BackendRequest.js.map +1 -0
  157. package/dist/requests/CollectionRequest.d.ts +234 -0
  158. package/dist/requests/CollectionRequest.d.ts.map +1 -0
  159. package/dist/requests/CollectionRequest.js +705 -0
  160. package/dist/requests/CollectionRequest.js.map +1 -0
  161. package/dist/requests/KeyRequest.d.ts +115 -0
  162. package/dist/requests/KeyRequest.d.ts.map +1 -0
  163. package/dist/requests/KeyRequest.js +468 -0
  164. package/dist/requests/KeyRequest.js.map +1 -0
  165. package/dist/requests/KeystoreRequest.d.ts +99 -0
  166. package/dist/requests/KeystoreRequest.d.ts.map +1 -0
  167. package/dist/requests/KeystoreRequest.js +247 -0
  168. package/dist/requests/KeystoreRequest.js.map +1 -0
  169. package/dist/requests/PolicyRequest.d.ts +53 -0
  170. package/dist/requests/PolicyRequest.d.ts.map +1 -0
  171. package/dist/requests/PolicyRequest.js +124 -0
  172. package/dist/requests/PolicyRequest.js.map +1 -0
  173. package/dist/requests/ResourceRequest.d.ts +134 -0
  174. package/dist/requests/ResourceRequest.d.ts.map +1 -0
  175. package/dist/requests/ResourceRequest.js +548 -0
  176. package/dist/requests/ResourceRequest.js.map +1 -0
  177. package/dist/requests/RevocationRequest.d.ts +67 -0
  178. package/dist/requests/RevocationRequest.d.ts.map +1 -0
  179. package/dist/requests/RevocationRequest.js +187 -0
  180. package/dist/requests/RevocationRequest.js.map +1 -0
  181. package/dist/requests/SpaceRequest.d.ts +204 -0
  182. package/dist/requests/SpaceRequest.d.ts.map +1 -0
  183. package/dist/requests/SpaceRequest.js +520 -0
  184. package/dist/requests/SpaceRequest.js.map +1 -0
  185. package/dist/requests/SpacesRepositoryRequest.d.ts +50 -0
  186. package/dist/requests/SpacesRepositoryRequest.d.ts.map +1 -0
  187. package/dist/requests/SpacesRepositoryRequest.js +159 -0
  188. package/dist/requests/SpacesRepositoryRequest.js.map +1 -0
  189. package/dist/requests/collectionContext.d.ts +21 -0
  190. package/dist/requests/collectionContext.d.ts.map +1 -0
  191. package/dist/requests/collectionContext.js +30 -0
  192. package/dist/requests/collectionContext.js.map +1 -0
  193. package/dist/requests/controllerConsent.d.ts +58 -0
  194. package/dist/requests/controllerConsent.d.ts.map +1 -0
  195. package/dist/requests/controllerConsent.js +73 -0
  196. package/dist/requests/controllerConsent.js.map +1 -0
  197. package/dist/requests/keystoreContext.d.ts +68 -0
  198. package/dist/requests/keystoreContext.d.ts.map +1 -0
  199. package/dist/requests/keystoreContext.js +87 -0
  200. package/dist/requests/keystoreContext.js.map +1 -0
  201. package/dist/requests/resourceInput.d.ts +19 -0
  202. package/dist/requests/resourceInput.d.ts.map +1 -0
  203. package/dist/requests/resourceInput.js +102 -0
  204. package/dist/requests/resourceInput.js.map +1 -0
  205. package/dist/requests/spaceContext.d.ts +127 -0
  206. package/dist/requests/spaceContext.d.ts.map +1 -0
  207. package/dist/requests/spaceContext.js +201 -0
  208. package/dist/requests/spaceContext.js.map +1 -0
  209. package/dist/routes.d.ts +55 -0
  210. package/dist/routes.d.ts.map +1 -0
  211. package/dist/routes.js +306 -0
  212. package/dist/routes.js.map +1 -0
  213. package/dist/server.d.ts +20 -0
  214. package/dist/server.d.ts.map +1 -0
  215. package/dist/server.js +60 -0
  216. package/dist/server.js.map +1 -0
  217. package/dist/start.d.ts +7 -0
  218. package/dist/start.d.ts.map +1 -0
  219. package/dist/start.js +61 -0
  220. package/dist/start.js.map +1 -0
  221. package/dist/storage.d.ts +29 -0
  222. package/dist/storage.d.ts.map +1 -0
  223. package/dist/storage.js +47 -0
  224. package/dist/storage.js.map +1 -0
  225. package/dist/types.d.ts +915 -0
  226. package/dist/types.d.ts.map +1 -0
  227. package/dist/types.js +2 -0
  228. package/dist/types.js.map +1 -0
  229. package/dist/views/home.hbs +9 -0
  230. package/dist/views/templates/main.hbs +12 -0
  231. package/dist/zcap.d.ts +267 -0
  232. package/dist/zcap.d.ts.map +1 -0
  233. package/dist/zcap.js +478 -0
  234. package/dist/zcap.js.map +1 -0
  235. package/package.json +109 -0
  236. package/src/auth-header-hooks.ts +163 -0
  237. package/src/authorize.ts +117 -0
  238. package/src/backends/filesystem.ts +3626 -0
  239. package/src/backends/postgres.ts +3073 -0
  240. package/src/backends/postgresSchema.ts +231 -0
  241. package/src/config.default.ts +657 -0
  242. package/src/corsProxy.ts +326 -0
  243. package/src/declarations.d.ts +28 -0
  244. package/src/digest.ts +223 -0
  245. package/src/errors.ts +1122 -0
  246. package/src/index.ts +21 -0
  247. package/src/lib/atomicFile.ts +176 -0
  248. package/src/lib/backendRegistry.ts +139 -0
  249. package/src/lib/backendUsage.ts +79 -0
  250. package/src/lib/backends.ts +351 -0
  251. package/src/lib/blindedIndex.ts +466 -0
  252. package/src/lib/collectionDescription.ts +43 -0
  253. package/src/lib/cursor.ts +52 -0
  254. package/src/lib/edvEnvelope.ts +120 -0
  255. package/src/lib/encryption.ts +472 -0
  256. package/src/lib/etag.ts +40 -0
  257. package/src/lib/exportManifest.ts +115 -0
  258. package/src/lib/importTar.ts +381 -0
  259. package/src/lib/isJson.ts +18 -0
  260. package/src/lib/keyEpoch.ts +89 -0
  261. package/src/lib/keyedMutex.ts +45 -0
  262. package/src/lib/kmsModule.ts +451 -0
  263. package/src/lib/kmsRecordCipher.ts +292 -0
  264. package/src/lib/pagination.ts +22 -0
  265. package/src/lib/paths.ts +382 -0
  266. package/src/lib/preconditions.ts +145 -0
  267. package/src/lib/resourceFileName.ts +69 -0
  268. package/src/lib/revocations.ts +116 -0
  269. package/src/lib/validateDid.ts +41 -0
  270. package/src/lib/validateId.ts +148 -0
  271. package/src/plugin.ts +288 -0
  272. package/src/policy.ts +176 -0
  273. package/src/provisioning.ts +98 -0
  274. package/src/requests/BackendRequest.ts +219 -0
  275. package/src/requests/CollectionRequest.ts +899 -0
  276. package/src/requests/KeyRequest.ts +617 -0
  277. package/src/requests/KeystoreRequest.ts +325 -0
  278. package/src/requests/PolicyRequest.ts +169 -0
  279. package/src/requests/ResourceRequest.ts +649 -0
  280. package/src/requests/RevocationRequest.ts +267 -0
  281. package/src/requests/SpaceRequest.ts +686 -0
  282. package/src/requests/SpacesRepositoryRequest.ts +194 -0
  283. package/src/requests/collectionContext.ts +41 -0
  284. package/src/requests/controllerConsent.ts +108 -0
  285. package/src/requests/keystoreContext.ts +124 -0
  286. package/src/requests/resourceInput.ts +118 -0
  287. package/src/requests/spaceContext.ts +311 -0
  288. package/src/routes.ts +420 -0
  289. package/src/server.ts +69 -0
  290. package/src/start.ts +71 -0
  291. package/src/storage.ts +60 -0
  292. package/src/types.ts +1016 -0
  293. package/src/views/home.hbs +9 -0
  294. package/src/views/templates/main.hbs +12 -0
  295. package/src/zcap.ts +657 -0
@@ -0,0 +1,226 @@
1
+ /**
2
+ * At-rest cipher for WebKMS key records (`KMS_RECORD_KEK`, the optional
3
+ * hardening increment). Envelope-encrypts the
4
+ * secret-bearing fields of a stored key so a disk/database dump exposes only
5
+ * ciphertext and a `kekId`, while the wire projection (`KmsKeyDescription`) and
6
+ * the whole authorization model stay byte-for-byte identical.
7
+ *
8
+ * The design mirrors bedrock's `@bedrock/record-cipher`: a deny-by-default field
9
+ * split (an explicit plaintext allowlist; every other `key` field is a secret),
10
+ * a fresh per-record content-encryption key (`A256GCM`) wrapped (`A256KW`) under
11
+ * a config-supplied AES-256 KEK, and a per-record `kekId` so a rotated-in KEK
12
+ * never forces a rewrite. It reuses the same `node:crypto` primitives the KMS
13
+ * module already relies on for AES-KW (`id-aes256-wrap`), so no new crypto
14
+ * dependency is introduced.
15
+ *
16
+ * This module is pure and backend-agnostic: KEK(s) are injected (no env reads
17
+ * here), and it neither touches storage nor knows about Fastify. The
18
+ * orchestration seam (`src/requests/KeyRequest.ts`) applies it around the
19
+ * backend's `insertKey` / `getKey`.
20
+ */
21
+ import { createCipheriv, createDecipheriv, createHash, randomBytes } from 'node:crypto';
22
+ import { IdDecoder } from '@digitalcredentials/bnid';
23
+ /**
24
+ * The plaintext allowlist: the `KmsStoredKey` fields that stay in the clear (and
25
+ * queryable) at rest. EVERY other field of `key` -- `privateKeyMultibase`,
26
+ * `secret`, and any secret-bearing field added later -- is swept into the
27
+ * envelope, so new secrets are protected by default unless explicitly added
28
+ * here. (Bedrock additionally lists `controller`; this server never stores
29
+ * `controller` on the key -- it is read from the live keystore config at
30
+ * description time -- so it is simply absent.)
31
+ */
32
+ export const PLAINTEXT_KEY_FIELDS = new Set([
33
+ '@context',
34
+ 'id',
35
+ 'type',
36
+ 'publicKeyMultibase',
37
+ 'maxCapabilityChainLength',
38
+ 'publicAlias',
39
+ 'publicAliasTemplate'
40
+ ]);
41
+ /**
42
+ * The Multikey header for an AES-256 symmetric key (`0xa2 0x01`, the multicodec
43
+ * varint for `aes-256`), the two bytes a `KMS_RECORD_KEK` multibase value
44
+ * carries before its 32 key bytes -- matching bedrock's KEK encoding.
45
+ */
46
+ const AES_256_MULTIKEY_HEADER = Buffer.from([0xa2, 0x01]);
47
+ /** Content-encryption algorithm: AES-256-GCM (`A256GCM`). */
48
+ const CEK_ALGORITHM = 'aes-256-gcm';
49
+ /** GCM initialization-vector length in bytes (96-bit, per the JWE `A256GCM` profile). */
50
+ const GCM_IV_BYTES = 12;
51
+ /**
52
+ * Key-wrap algorithm: AES Key Wrap (RFC 3394) with a 256-bit KEK (`A256KW`),
53
+ * the same primitive the KMS module uses for its AES-KW key type. Its default
54
+ * IV is the RFC's `0xA6` octet repeated eight times; the wrap is integrity-
55
+ * checked, so a wrong KEK throws on unwrap.
56
+ */
57
+ const KEK_WRAP_ALGORITHM = 'id-aes256-wrap';
58
+ const KEK_WRAP_DEFAULT_IV = Buffer.alloc(8, 0xa6);
59
+ /**
60
+ * Derives a KEK's non-secret, stable id from its raw key bytes: a SHA-256 digest
61
+ * (one-way, so storing it per record leaks nothing about the key). Self-
62
+ * describing and deterministic, so a rotated-in KEK gets a stable id from its
63
+ * material alone -- the convention bedrock follows.
64
+ * @param key {Buffer} the 32-byte AES-256 KEK
65
+ * @returns {string} the derived `urn:kek:sha256:<hex>` id
66
+ */
67
+ export function deriveKekId(key) {
68
+ return `urn:kek:sha256:${createHash('sha256').update(key).digest('hex')}`;
69
+ }
70
+ /**
71
+ * Parses a `secretKeyMultibase` (base58btc Multikey) AES-256 KEK into a
72
+ * `RecordKek` (its raw key plus a derived id). Throws a plain `Error` on a
73
+ * malformed value -- callers are config parsing (fails startup) and tests, not
74
+ * the request path. The error messages name `label` (the offending config
75
+ * variable, e.g. a `KMS_RECORD_KEKS entry N` position) but NEVER echo the secret
76
+ * value itself.
77
+ * @param secretKeyMultibase {string} the multibase (`z...`) KEK value
78
+ * @param [label] {string} the config source named in error messages
79
+ * (defaults to `KMS_RECORD_KEK`)
80
+ * @returns {RecordKek}
81
+ */
82
+ export function parseKekMultibase(secretKeyMultibase, label = 'KMS_RECORD_KEK') {
83
+ const decoder = new IdDecoder({ encoding: 'base58', multibase: true });
84
+ let decoded;
85
+ try {
86
+ decoded = Buffer.from(decoder.decode(secretKeyMultibase));
87
+ }
88
+ catch {
89
+ throw new Error(`${label} is not a valid multibase (base58btc) value.`);
90
+ }
91
+ if (!decoded.subarray(0, 2).equals(AES_256_MULTIKEY_HEADER)) {
92
+ throw new Error(`${label} must carry the AES-256 Multikey header (0xa2 0x01).`);
93
+ }
94
+ const key = decoded.subarray(2);
95
+ if (key.length !== 32) {
96
+ throw new Error(`${label} must be a 256-bit (32-byte) key; got ${key.length} bytes.`);
97
+ }
98
+ return { id: deriveKekId(key), key };
99
+ }
100
+ /**
101
+ * The KEK that wraps NEW records, or `undefined` when encryption is disabled
102
+ * (no registry, or `currentKekId: null`).
103
+ * @param [registry] {KmsRecordKekRegistry}
104
+ * @returns {RecordKek | undefined}
105
+ */
106
+ export function currentRecordKek(registry) {
107
+ if (registry === undefined || registry.currentKekId === null) {
108
+ return undefined;
109
+ }
110
+ return registry.keks.get(registry.currentKekId);
111
+ }
112
+ /**
113
+ * A KEK-lookup function over a registry, resolving a record's stored `kekId` to
114
+ * its `RecordKek` for decryption (`undefined` when the KEK is not registered, or
115
+ * there is no registry at all). The decrypt seam for the pass-through /
116
+ * rotation upgrade paths.
117
+ * @param [registry] {KmsRecordKekRegistry}
118
+ * @returns {(kekId: string) => RecordKek | undefined}
119
+ */
120
+ export function recordKekLoader(registry) {
121
+ return (kekId) => registry?.keks.get(kekId);
122
+ }
123
+ /**
124
+ * Encrypts the secret-bearing fields of a key record under a KEK, returning a
125
+ * record whose `key` carries the allowlisted plaintext fields plus an
126
+ * `encrypted` envelope in place of the secrets. Pure: the KEK is injected, no
127
+ * storage or env access. The record's non-`key` members (`keystoreId`,
128
+ * `localId`, `meta`) are unchanged.
129
+ * @param options {object}
130
+ * @param options.record {KmsKeyRecord} the plaintext (secret-bearing) record
131
+ * @param options.kek {RecordKek} the KEK to wrap the fresh CEK under
132
+ * @returns {KmsKeyRecord} the at-rest record (secrets replaced by `encrypted`)
133
+ */
134
+ export function encryptKeyRecord({ record, kek }) {
135
+ const publicFields = {};
136
+ const secretFields = {};
137
+ for (const [field, value] of Object.entries(record.key)) {
138
+ if (PLAINTEXT_KEY_FIELDS.has(field)) {
139
+ publicFields[field] = value;
140
+ }
141
+ else {
142
+ secretFields[field] = value;
143
+ }
144
+ }
145
+ const plaintext = Buffer.from(JSON.stringify(secretFields), 'utf8');
146
+ // Fresh per-record content-encryption key (CEK), A256GCM. The `protected`
147
+ // header doubles as the GCM additional-authenticated-data (AAD), per JWE.
148
+ const cek = randomBytes(32);
149
+ const iv = randomBytes(GCM_IV_BYTES);
150
+ const protectedHeader = Buffer.from(JSON.stringify({ enc: 'A256GCM' }), 'utf8').toString('base64url');
151
+ const cipher = createCipheriv(CEK_ALGORITHM, cek, iv);
152
+ cipher.setAAD(Buffer.from(protectedHeader, 'ascii'));
153
+ const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
154
+ const tag = cipher.getAuthTag();
155
+ // Wrap the CEK under the KEK (A256KW / RFC 3394).
156
+ const wrap = createCipheriv(KEK_WRAP_ALGORITHM, kek.key, KEK_WRAP_DEFAULT_IV);
157
+ const wrappedCek = Buffer.concat([wrap.update(cek), wrap.final()]);
158
+ const encrypted = {
159
+ kekId: kek.id,
160
+ jwe: {
161
+ protected: protectedHeader,
162
+ recipients: [
163
+ {
164
+ header: { alg: 'A256KW', kid: kek.id },
165
+ encrypted_key: wrappedCek.toString('base64url')
166
+ }
167
+ ],
168
+ iv: iv.toString('base64url'),
169
+ ciphertext: ciphertext.toString('base64url'),
170
+ tag: tag.toString('base64url')
171
+ },
172
+ encoding: 'json'
173
+ };
174
+ return {
175
+ ...record,
176
+ key: { ...publicFields, encrypted }
177
+ };
178
+ }
179
+ /**
180
+ * Decrypts a key record: pass-through when `key.encrypted` is absent (a
181
+ * plaintext record -- the default, and the pass-through upgrade path), else
182
+ * looks up the KEK by the record's stored `kekId`, unwraps the CEK, decrypts the
183
+ * secret subset, and splices the secret fields back onto the allowlisted ones
184
+ * (dropping the envelope). Pure: KEK(s) injected via `kekLoader`, no storage or
185
+ * env access. Throws a plain `Error` when the record's KEK is not registered or
186
+ * the ciphertext fails to authenticate; the request seam wraps that as a 500.
187
+ * @param options {object}
188
+ * @param options.record {KmsKeyRecord} the at-rest (or plaintext) record
189
+ * @param options.kekLoader {(kekId: string) => RecordKek | undefined} KEK lookup
190
+ * @returns {KmsKeyRecord} the decrypted record (secrets restored on `key`)
191
+ */
192
+ export function decryptKeyRecord({ record, kekLoader }) {
193
+ const { encrypted } = record.key;
194
+ if (encrypted === undefined) {
195
+ // Plaintext record: unconditional pass-through (so enabling a KEK on an
196
+ // existing plaintext tree leaves old records readable).
197
+ return record;
198
+ }
199
+ const kek = kekLoader(encrypted.kekId);
200
+ if (kek === undefined) {
201
+ throw new Error(`No KEK registered for kekId "${encrypted.kekId}"; ` +
202
+ 'cannot decrypt WebKMS key record.');
203
+ }
204
+ const { jwe } = encrypted;
205
+ // Unwrap the CEK (A256KW), then decrypt the secret subset (A256GCM). Both
206
+ // steps authenticate: a wrong KEK fails the RFC 3394 integrity check, and a
207
+ // tampered ciphertext fails the GCM tag.
208
+ const wrappedCek = Buffer.from(jwe.recipients[0].encrypted_key, 'base64url');
209
+ const unwrap = createDecipheriv(KEK_WRAP_ALGORITHM, kek.key, KEK_WRAP_DEFAULT_IV);
210
+ const cek = Buffer.concat([unwrap.update(wrappedCek), unwrap.final()]);
211
+ const decipher = createDecipheriv(CEK_ALGORITHM, cek, Buffer.from(jwe.iv, 'base64url'));
212
+ decipher.setAAD(Buffer.from(jwe.protected, 'ascii'));
213
+ decipher.setAuthTag(Buffer.from(jwe.tag, 'base64url'));
214
+ const plaintext = Buffer.concat([
215
+ decipher.update(Buffer.from(jwe.ciphertext, 'base64url')),
216
+ decipher.final()
217
+ ]);
218
+ const secretFields = JSON.parse(plaintext.toString('utf8'));
219
+ // Splice the secrets back onto the public fields, dropping the envelope.
220
+ const { encrypted: _envelope, ...publicFields } = record.key;
221
+ return {
222
+ ...record,
223
+ key: { ...publicFields, ...secretFields }
224
+ };
225
+ }
226
+ //# sourceMappingURL=kmsRecordCipher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kmsRecordCipher.js","sourceRoot":"","sources":["../../src/lib/kmsRecordCipher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Shared page sizing for the List Collection operation's cursor-based
3
+ * pagination and the change feed (spec "Pagination"). Both storage backends
4
+ * clamp through these so an oversized `limit` behaves identically everywhere.
5
+ */
6
+ /**
7
+ * Page sizing: `DEFAULT_PAGE_SIZE` applies when a request omits `limit`;
8
+ * `MAX_PAGE_SIZE` is the server maximum an oversized `limit` is clamped down to
9
+ * (rather than rejected).
10
+ */
11
+ export declare const DEFAULT_PAGE_SIZE = 100;
12
+ export declare const MAX_PAGE_SIZE = 1000;
13
+ /**
14
+ * Clamps a requested `limit` to `[1, MAX_PAGE_SIZE]`.
15
+ * @param limit {number}
16
+ * @returns {number}
17
+ */
18
+ export declare function clampPageSize(limit: number): number;
19
+ //# sourceMappingURL=pagination.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pagination.d.ts","sourceRoot":"","sources":["../../src/lib/pagination.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,MAAM,CAAA;AACpC,eAAO,MAAM,aAAa,OAAO,CAAA;AAEjC;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEnD"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Shared page sizing for the List Collection operation's cursor-based
3
+ * pagination and the change feed (spec "Pagination"). Both storage backends
4
+ * clamp through these so an oversized `limit` behaves identically everywhere.
5
+ */
6
+ /**
7
+ * Page sizing: `DEFAULT_PAGE_SIZE` applies when a request omits `limit`;
8
+ * `MAX_PAGE_SIZE` is the server maximum an oversized `limit` is clamped down to
9
+ * (rather than rejected).
10
+ */
11
+ export const DEFAULT_PAGE_SIZE = 100;
12
+ export const MAX_PAGE_SIZE = 1000;
13
+ /**
14
+ * Clamps a requested `limit` to `[1, MAX_PAGE_SIZE]`.
15
+ * @param limit {number}
16
+ * @returns {number}
17
+ */
18
+ export function clampPageSize(limit) {
19
+ return Math.min(Math.max(Math.trunc(limit), 1), MAX_PAGE_SIZE);
20
+ }
21
+ //# sourceMappingURL=pagination.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pagination.js","sourceRoot":"","sources":["../../src/lib/pagination.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,CAAA;AACpC,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,CAAA;AAEjC;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,aAAa,CAAC,CAAA;AAChE,CAAC"}
@@ -0,0 +1,273 @@
1
+ /**
2
+ * Single source of truth for the server's relative URL path templates. The route
3
+ * shapes registered in `routes.ts` (the `/spaces` repository, `/space/:spaceId`,
4
+ * `/space/:spaceId/:collectionId`, the `policy` / `linkset` auxiliary resources,
5
+ * and the `export` / `import` actions) are mirrored here as builder functions, so
6
+ * handlers, the policy code, and the storage backends construct the same paths
7
+ * from one place rather than re-deriving them inline (which risks drift from the
8
+ * routes).
9
+ *
10
+ * Builders return the canonical, no-trailing-slash member form by default. The
11
+ * spec assigns distinct meaning to a trailing slash -- it addresses the
12
+ * container / "list-or-add-to" view of a member -- so the container builders take
13
+ * an explicit `trailingSlash` option (or, for the always-container `/spaces/` and
14
+ * `.../collections/`, bake the slash in) rather than leaving the slash to drift
15
+ * across call sites. A leaf Resource has no children, so `resourcePath` has no
16
+ * container form.
17
+ */
18
+ /**
19
+ * The SpacesRepository container (`/spaces/`) or one of its members
20
+ * (`/spaces/:spaceId`). The member form is used for the `Location` header of a
21
+ * newly created Space; the container form is the `POST`/`GET` target.
22
+ * @param options {object}
23
+ * @param [options.spaceId] {string} when present, the repository member path;
24
+ * otherwise the (trailing-slash) container path
25
+ * @returns {string}
26
+ */
27
+ export declare function spacesPath({ spaceId }?: {
28
+ spaceId?: string;
29
+ }): string;
30
+ /**
31
+ * `/space/:spaceId` (member) or `/space/:spaceId/` (container -- the
32
+ * "add a Collection" / Space-as-container view) when `trailingSlash` is set.
33
+ * @param options {object}
34
+ * @param options.spaceId {string}
35
+ * @param [options.trailingSlash] {boolean} address the container form
36
+ * @returns {string}
37
+ */
38
+ export declare function spacePath({ spaceId, trailingSlash }: {
39
+ spaceId: string;
40
+ trailingSlash?: boolean;
41
+ }): string;
42
+ /**
43
+ * `/space/:spaceId/collections/` -- the "List Collections" container path.
44
+ * @param options {object}
45
+ * @param options.spaceId {string}
46
+ * @returns {string}
47
+ */
48
+ export declare function collectionsPath({ spaceId }: {
49
+ spaceId: string;
50
+ }): string;
51
+ /**
52
+ * `/space/:spaceId/export` -- the "Export Space" action path.
53
+ * @param options {object}
54
+ * @param options.spaceId {string}
55
+ * @returns {string}
56
+ */
57
+ export declare function exportPath({ spaceId }: {
58
+ spaceId: string;
59
+ }): string;
60
+ /**
61
+ * `/space/:spaceId/import` -- the "Import Space" action path.
62
+ * @param options {object}
63
+ * @param options.spaceId {string}
64
+ * @returns {string}
65
+ */
66
+ export declare function importPath({ spaceId }: {
67
+ spaceId: string;
68
+ }): string;
69
+ /**
70
+ * `/space/:spaceId/:collectionId` (member) or `/space/:spaceId/:collectionId/`
71
+ * (container -- the "add a Resource" / "list items" view) when `trailingSlash`
72
+ * is set.
73
+ * @param options {object}
74
+ * @param options.spaceId {string}
75
+ * @param options.collectionId {string}
76
+ * @param [options.trailingSlash] {boolean} address the container form
77
+ * @returns {string}
78
+ */
79
+ export declare function collectionPath({ spaceId, collectionId, trailingSlash }: {
80
+ spaceId: string;
81
+ collectionId: string;
82
+ trailingSlash?: boolean;
83
+ }): string;
84
+ /**
85
+ * `/space/:spaceId/:collectionId/:resourceId`
86
+ * @param options {object}
87
+ * @param options.spaceId {string}
88
+ * @param options.collectionId {string}
89
+ * @param options.resourceId {string}
90
+ * @returns {string}
91
+ */
92
+ export declare function resourcePath({ spaceId, collectionId, resourceId }: {
93
+ spaceId: string;
94
+ collectionId: string;
95
+ resourceId: string;
96
+ }): string;
97
+ /**
98
+ * The `policy` auxiliary resource path for whichever level the ids address:
99
+ * Space (`spaceId`), Collection (`+ collectionId`), or Resource
100
+ * (`+ collectionId + resourceId`).
101
+ * @param options {object}
102
+ * @param options.spaceId {string}
103
+ * @param [options.collectionId] {string}
104
+ * @param [options.resourceId] {string}
105
+ * @returns {string}
106
+ */
107
+ export declare function policyPath({ spaceId, collectionId, resourceId }: {
108
+ spaceId: string;
109
+ collectionId?: string;
110
+ resourceId?: string;
111
+ }): string;
112
+ /**
113
+ * `/space/:spaceId/backends` -- the "Space Backends Available" list path.
114
+ * @param options {object}
115
+ * @param options.spaceId {string}
116
+ * @returns {string}
117
+ */
118
+ export declare function backendsPath({ spaceId }: {
119
+ spaceId: string;
120
+ }): string;
121
+ /**
122
+ * `/space/:spaceId/backends/:backendId` -- a single registered `external`
123
+ * backend record (the `POST` `Location` target, and the `PUT`/`DELETE` member
124
+ * path). Distinct from {@link backendPath}, which is a Collection's *selected*
125
+ * backend resource.
126
+ * @param options {object}
127
+ * @param options.spaceId {string}
128
+ * @param options.backendId {string}
129
+ * @returns {string}
130
+ */
131
+ export declare function registeredBackendPath({ spaceId, backendId }: {
132
+ spaceId: string;
133
+ backendId: string;
134
+ }): string;
135
+ /**
136
+ * `/space/:spaceId/quotas` -- the Space Quota report path (spec "Quotas").
137
+ * @param options {object}
138
+ * @param options.spaceId {string}
139
+ * @returns {string}
140
+ */
141
+ export declare function quotasPath({ spaceId }: {
142
+ spaceId: string;
143
+ }): string;
144
+ /**
145
+ * `/space/:spaceId/:collectionId/:resourceId/meta` -- the Resource Metadata
146
+ * (reserved `meta` segment) path. Reserved only at the Resource level, so it
147
+ * takes the full id triple.
148
+ * @param options {object}
149
+ * @param options.spaceId {string}
150
+ * @param options.collectionId {string}
151
+ * @param options.resourceId {string}
152
+ * @returns {string}
153
+ */
154
+ export declare function metaPath({ spaceId, collectionId, resourceId }: {
155
+ spaceId: string;
156
+ collectionId: string;
157
+ resourceId: string;
158
+ }): string;
159
+ /**
160
+ * `/space/:spaceId/:collectionId/backend` -- the "Collection Backend Selected"
161
+ * resource path (reserved `backend` segment at the Resource level).
162
+ * @param options {object}
163
+ * @param options.spaceId {string}
164
+ * @param options.collectionId {string}
165
+ * @returns {string}
166
+ */
167
+ export declare function backendPath({ spaceId, collectionId }: {
168
+ spaceId: string;
169
+ collectionId: string;
170
+ }): string;
171
+ /**
172
+ * `/space/:spaceId/:collectionId/quota` -- the per-Collection storage quota
173
+ * report path (reserved `quota` segment at the Resource level; spec "Quotas").
174
+ * @param options {object}
175
+ * @param options.spaceId {string}
176
+ * @param options.collectionId {string}
177
+ * @returns {string}
178
+ */
179
+ export declare function quotaPath({ spaceId, collectionId }: {
180
+ spaceId: string;
181
+ collectionId: string;
182
+ }): string;
183
+ /**
184
+ * `/space/:spaceId/:collectionId/query` -- the reserved `query` endpoint for a
185
+ * Collection (spec "Collection-level reserved endpoints"). The WAS server serves
186
+ * the replication change feed as the `changes` profile of this endpoint.
187
+ * @param options {object}
188
+ * @param options.spaceId {string}
189
+ * @param options.collectionId {string}
190
+ * @returns {string}
191
+ */
192
+ export declare function queryPath({ spaceId, collectionId }: {
193
+ spaceId: string;
194
+ collectionId: string;
195
+ }): string;
196
+ /**
197
+ * The `linkset` discovery resource path for a Space (`spaceId`) or Collection
198
+ * (`+ collectionId`).
199
+ * @param options {object}
200
+ * @param options.spaceId {string}
201
+ * @param [options.collectionId] {string}
202
+ * @returns {string}
203
+ */
204
+ export declare function linksetPath({ spaceId, collectionId }: {
205
+ spaceId: string;
206
+ collectionId?: string;
207
+ }): string;
208
+ /**
209
+ * `/kms/keystores` -- the WebKMS keystores collection (create/list target; the
210
+ * `/kms` facet) or one of its member keystores
211
+ * (`/kms/keystores/:keystoreId`). Unlike the WAS builders there is no
212
+ * trailing-slash container form: the webkms protocol
213
+ * (`@interop/webkms-client`) posts to the bare collection path.
214
+ * @param options {object}
215
+ * @param [options.keystoreId] {string} the keystore's server-generated local
216
+ * id; when present, the member path, otherwise the collection path
217
+ * @returns {string}
218
+ */
219
+ export declare function kmsKeystoresPath({ keystoreId }?: {
220
+ keystoreId?: string;
221
+ }): string;
222
+ /**
223
+ * `/kms/keystores/:keystoreId/keys` -- a keystore's keys collection (the
224
+ * `GenerateKeyOperation` target) or one of its member keys
225
+ * (`/kms/keystores/:keystoreId/keys/:keyId`, the key-operation / description
226
+ * target). Like `kmsKeystoresPath`, no trailing-slash form exists: the webkms
227
+ * protocol's URLs are exact.
228
+ * @param options {object}
229
+ * @param options.keystoreId {string} the keystore's local id
230
+ * @param [options.keyId] {string} the key's server-generated local id; when
231
+ * present, the member path, otherwise the collection path
232
+ * @returns {string}
233
+ */
234
+ export declare function kmsKeysPath({ keystoreId, keyId }: {
235
+ keystoreId: string;
236
+ keyId?: string;
237
+ }): string;
238
+ /**
239
+ * `/kms/keystores/:keystoreId/zcaps/revocations/:revocationId` -- a keystore's
240
+ * zcap revocation submission target (POST; the ezcap-express
241
+ * `/zcaps/revocations/` convention). `revocationId` is the *to-be-revoked
242
+ * capability's id*, URL-encoded into the single path segment the route
243
+ * expects -- the same `encodeURIComponent` framing `@interop/webkms-client`'s
244
+ * `revokeCapability` puts on the wire.
245
+ * @param options {object}
246
+ * @param options.keystoreId {string} the keystore's local id
247
+ * @param options.revocationId {string} the to-be-revoked capability's id
248
+ * (raw, un-encoded)
249
+ * @returns {string}
250
+ */
251
+ export declare function kmsRevocationsPath({ keystoreId, revocationId }: {
252
+ keystoreId: string;
253
+ revocationId: string;
254
+ }): string;
255
+ /**
256
+ * `/space/:spaceId/zcaps/revocations/:revocationId` -- a Space's zcap
257
+ * revocation submission target (POST), the WAS-route sibling of
258
+ * `kmsRevocationsPath` and the same ezcap-express `/zcaps/revocations/`
259
+ * convention. `revocationId` is the *to-be-revoked capability's id*,
260
+ * URL-encoded into the single path segment the route expects. The `zcaps`
261
+ * segment sits four levels under `/space`, deeper than any Collection or
262
+ * Resource route, so it shadows neither and needs no reserved-id entry.
263
+ * @param options {object}
264
+ * @param options.spaceId {string}
265
+ * @param options.revocationId {string} the to-be-revoked capability's id
266
+ * (raw, un-encoded)
267
+ * @returns {string}
268
+ */
269
+ export declare function spaceRevocationsPath({ spaceId, revocationId }: {
270
+ spaceId: string;
271
+ revocationId: string;
272
+ }): string;
273
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/lib/paths.ts"],"names":[],"mappings":"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"}