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
package/dist/routes.js ADDED
@@ -0,0 +1,306 @@
1
+ import { SpacesRepositoryRequest } from './requests/SpacesRepositoryRequest.js';
2
+ import { SpaceRequest } from './requests/SpaceRequest.js';
3
+ import { handleError } from './errors.js';
4
+ import { ResourceRequest } from './requests/ResourceRequest.js';
5
+ import { CollectionRequest } from './requests/CollectionRequest.js';
6
+ import { PolicyRequest } from './requests/PolicyRequest.js';
7
+ import { BackendRequest } from './requests/BackendRequest.js';
8
+ import { KeystoreRequest } from './requests/KeystoreRequest.js';
9
+ import { KeyRequest } from './requests/KeyRequest.js';
10
+ import { RevocationRequest } from './requests/RevocationRequest.js';
11
+ import { parseAuthHeaders, requireAuthHeaders, requireAuthHeadersOrPublicRead } from './auth-header-hooks.js';
12
+ import { captureRawBody, verifyBodyDigest } from './digest.js';
13
+ import { provisioningGate } from './provisioning.js';
14
+ /**
15
+ * Toggles the trailing slash on the request's actual path (preserving any query
16
+ * string), returning the canonical target for a slash/no-slash redirect. Built
17
+ * from `request.url` rather than the route template so the `Location` carries
18
+ * the concrete ids (`/space/abc123`), not the literal `/space/:spaceId` -- which
19
+ * a client cannot follow.
20
+ * @param url {string} the request URL (path plus optional query string)
21
+ * @param addSlash {boolean} append (true) or strip (false) the trailing slash
22
+ * @returns {string}
23
+ */
24
+ function toggleTrailingSlash(url, addSlash) {
25
+ const queryIndex = url.indexOf('?');
26
+ const pathPart = queryIndex === -1 ? url : url.slice(0, queryIndex);
27
+ const query = queryIndex === -1 ? '' : url.slice(queryIndex);
28
+ const canonical = addSlash
29
+ ? pathPart.endsWith('/')
30
+ ? pathPart
31
+ : `${pathPart}/`
32
+ : pathPart.endsWith('/')
33
+ ? pathPart.slice(0, -1)
34
+ : pathPart;
35
+ return `${canonical}${query}`;
36
+ }
37
+ /**
38
+ * Redirects to the trailing-slash canonical form of the request URL with a
39
+ * `308` (Permanent Redirect), which -- unlike the default `302` -- requires the
40
+ * client to replay the same method and body, so a redirected POST/PUT is not
41
+ * silently downgraded to GET.
42
+ * @param request {import('fastify').FastifyRequest}
43
+ * @param reply {import('fastify').FastifyReply}
44
+ * @returns {FastifyReply}
45
+ */
46
+ function redirectAddSlash(request, reply) {
47
+ return reply.redirect(toggleTrailingSlash(request.url, true), 308);
48
+ }
49
+ /**
50
+ * Redirects to the no-trailing-slash canonical form of the request URL (see
51
+ * {@link redirectAddSlash} for the `308` rationale).
52
+ * @param request {import('fastify').FastifyRequest}
53
+ * @param reply {import('fastify').FastifyReply}
54
+ * @returns {FastifyReply}
55
+ */
56
+ function redirectStripSlash(request, reply) {
57
+ return reply.redirect(toggleTrailingSlash(request.url, false), 308);
58
+ }
59
+ /**
60
+ * Registers SpacesRepository routes (POST/GET /spaces). Installs the
61
+ * `requireAuthHeadersOrPublicRead` then `parseAuthHeaders` onRequest hooks and
62
+ * the `handleError` error handler.
63
+ * @param app {import('fastify').FastifyInstance}
64
+ * @param options {object} Fastify plugin options
65
+ * @returns {Promise<void>}
66
+ */
67
+ export async function initSpacesRepositoryRoutes(app, _options) {
68
+ app.setErrorHandler(handleError);
69
+ // Gate provisioning (Create Space): the configured policy may grant/deny, or
70
+ // (the default) allow -- in which case the normal zcap path below runs.
71
+ app.addHook('onRequest', provisioningGate);
72
+ // Create Space (POST) requires auth-related headers (401 otherwise); a List
73
+ // Spaces read may proceed unauthenticated -- an anonymous list is the spec's
74
+ // empty-items 200, never an error (the exception to 404 masking).
75
+ app.addHook('onRequest', requireAuthHeadersOrPublicRead);
76
+ // Parse the relevant request headers, set the request.zcap parameter
77
+ app.addHook('onRequest', parseAuthHeaders);
78
+ // Capture raw body bytes (JSON/text) so the digest can be recomputed against
79
+ // exactly what the client signed (spec "Request Body Integrity").
80
+ app.addHook('preParsing', captureRawBody);
81
+ // Enforce the Digest header binding: require it covered by the signature and,
82
+ // when the raw body is available, recompute and compare it.
83
+ app.addHook('preValidation', verifyBodyDigest);
84
+ // Add a Space to a SpacesRepository (Create Space)
85
+ app.post('/spaces', redirectAddSlash);
86
+ app.post('/spaces/', SpacesRepositoryRequest.post);
87
+ // List Spaces
88
+ app.get('/spaces', redirectAddSlash);
89
+ app.get('/spaces/', SpacesRepositoryRequest.get);
90
+ }
91
+ /**
92
+ * Registers Space routes (get/update/delete a Space, add/list Collections,
93
+ * export/import). Installs the auth hooks and the `handleError` error handler.
94
+ * @param app {import('fastify').FastifyInstance}
95
+ * @param options {object} Fastify plugin options
96
+ * @returns {Promise<void>}
97
+ */
98
+ export async function initSpaceRoutes(app, _options) {
99
+ app.setErrorHandler(handleError);
100
+ // Writes require auth; reads (GET/HEAD) may proceed unauthenticated so the
101
+ // handler can fall back to an access-control policy (e.g. a public Space).
102
+ app.addHook('onRequest', requireAuthHeadersOrPublicRead);
103
+ // Parse the relevant request headers, set the request.zcap parameter
104
+ app.addHook('onRequest', parseAuthHeaders);
105
+ // Capture raw body bytes (JSON/text) so the digest can be recomputed against
106
+ // exactly what the client signed (spec "Request Body Integrity").
107
+ app.addHook('preParsing', captureRawBody);
108
+ // Enforce the Digest header binding: require it covered by the signature and,
109
+ // when the raw body is available, recompute and compare it.
110
+ app.addHook('preValidation', verifyBodyDigest);
111
+ // Get Space description object
112
+ app.get('/space/:spaceId', SpaceRequest.get);
113
+ // Update or Create Space by Id (only "no trailing slash" is valid)
114
+ app.put('/space/:spaceId/', redirectStripSlash);
115
+ app.put('/space/:spaceId', SpaceRequest.put);
116
+ // Delete Space
117
+ app.delete('/space/:spaceId', SpaceRequest.delete);
118
+ // List Collections for a space (the canonical form has a trailing slash;
119
+ // registered as GET so `GET /space/:spaceId/collections` redirects there
120
+ // rather than falling through to the Collection GET route).
121
+ app.get('/space/:spaceId/collections', redirectAddSlash);
122
+ app.get('/space/:spaceId/collections/', SpaceRequest.listCollections);
123
+ // Space access-control policy (reserved segment; Fastify routes static
124
+ // segments ahead of the `:collectionId` parameter, so this never collides).
125
+ app.get('/space/:spaceId/policy', PolicyRequest.get);
126
+ app.put('/space/:spaceId/policy', PolicyRequest.put);
127
+ app.delete('/space/:spaceId/policy', PolicyRequest.delete);
128
+ // Space linkset (RFC9264 policy discovery)
129
+ app.get('/space/:spaceId/linkset', SpaceRequest.linkset);
130
+ // Space Backends Available (reserved segment; static-beats-parametric routing
131
+ // keeps this ahead of the `:collectionId` parameter in the Collection routes).
132
+ app.get('/space/:spaceId/backends', SpaceRequest.listBackends);
133
+ // Register / replace / deregister an `external` backend record. Static
134
+ // `backends` beats the parametric `:collectionId` / `:resourceId` of the
135
+ // Collection/Resource route groups, so these resolve correctly (the same
136
+ // mechanism that keeps the GET above and the singular `/backend` working).
137
+ app.post('/space/:spaceId/backends', BackendRequest.post);
138
+ app.put('/space/:spaceId/backends/:backendId', BackendRequest.put);
139
+ app.delete('/space/:spaceId/backends/:backendId', BackendRequest.delete);
140
+ // Space Quota report (reserved segment; static-beats-parametric routing keeps
141
+ // this ahead of the `:collectionId` parameter). The per-Collection breakdown
142
+ // (spec's `?include=collections`) is opt-in via that query string -- see the
143
+ // handler note on the ZCap query-string limitation.
144
+ app.get('/space/:spaceId/quotas', SpaceRequest.quotas);
145
+ // Revoke a zcap delegated from this Space (`:revocationId` = the URL-encoded
146
+ // id of the capability being revoked, which is also the request body). Four
147
+ // segments deep, so it shadows no Collection or Resource route.
148
+ app.post('/space/:spaceId/zcaps/revocations/:revocationId', RevocationRequest.postSpace);
149
+ // Add Collection to a Space
150
+ app.post('/space/:spaceId', redirectAddSlash);
151
+ app.post('/space/:spaceId/', SpaceRequest.post);
152
+ // POST /space/12345/export
153
+ app.post('/space/:spaceId/export', SpaceRequest.export);
154
+ // POST /space/12345/import
155
+ app.addContentTypeParser('application/x-tar', (_req, body, done) => {
156
+ done(null, body);
157
+ });
158
+ app.post('/space/:spaceId/import', SpaceRequest.import);
159
+ }
160
+ /**
161
+ * Registers Collection routes (get/update/delete a Collection, list its items,
162
+ * add a Resource). Installs the auth hooks and the `handleError` error handler.
163
+ * @param app {import('fastify').FastifyInstance}
164
+ * @param options {object} Fastify plugin options
165
+ * @returns {Promise<void>}
166
+ */
167
+ export async function initCollectionRoutes(app, _options) {
168
+ app.setErrorHandler(handleError);
169
+ // Writes require auth; reads (GET/HEAD) may proceed unauthenticated so the
170
+ // handler can fall back to an access-control policy (e.g. a public Collection).
171
+ app.addHook('onRequest', requireAuthHeadersOrPublicRead);
172
+ // Parse the relevant request headers, set the request.zcap parameter
173
+ app.addHook('onRequest', parseAuthHeaders);
174
+ // Capture raw body bytes (JSON/text) so the digest can be recomputed against
175
+ // exactly what the client signed (spec "Request Body Integrity").
176
+ app.addHook('preParsing', captureRawBody);
177
+ // Enforce the Digest header binding: require it covered by the signature and,
178
+ // when the raw body is available, recompute and compare it.
179
+ app.addHook('preValidation', verifyBodyDigest);
180
+ // Get Collection description
181
+ app.get('/space/:spaceId/:collectionId', CollectionRequest.get);
182
+ // List Collection items
183
+ app.get('/space/:spaceId/:collectionId/', CollectionRequest.list);
184
+ // Collection access-control policy (reserved segment; static-beats-parametric
185
+ // routing keeps this ahead of the `:resourceId` parameter).
186
+ app.get('/space/:spaceId/:collectionId/policy', PolicyRequest.get);
187
+ app.put('/space/:spaceId/:collectionId/policy', PolicyRequest.put);
188
+ app.delete('/space/:spaceId/:collectionId/policy', PolicyRequest.delete);
189
+ // Collection linkset (RFC9264 policy discovery)
190
+ app.get('/space/:spaceId/:collectionId/linkset', CollectionRequest.linkset);
191
+ // Collection Backend Selected (reserved segment; static-beats-parametric
192
+ // routing keeps this ahead of the `:resourceId` parameter in Resource routes).
193
+ app.get('/space/:spaceId/:collectionId/backend', CollectionRequest.getBackend);
194
+ // Per-Collection Quota report (reserved segment; static-beats-parametric
195
+ // routing keeps this ahead of the `:resourceId` parameter in Resource routes).
196
+ app.get('/space/:spaceId/:collectionId/quota', CollectionRequest.getQuota);
197
+ // Collection query (reserved segment; spec "Collection-level reserved
198
+ // endpoints"). The WAS server serves the replication change feed as the
199
+ // `changes` profile; params ride the signed
200
+ // POST body. Static-beats-parametric routing keeps this ahead of the
201
+ // `:resourceId` parameter in Resource routes.
202
+ app.post('/space/:spaceId/:collectionId/query', CollectionRequest.query);
203
+ // Add Resource to a Collection
204
+ app.post('/space/:spaceId/:collectionId', redirectAddSlash);
205
+ app.post('/space/:spaceId/:collectionId/', CollectionRequest.post);
206
+ // Create a Collection by Id
207
+ app.put('/space/:spaceId/:collectionId/', // no trailing slash allowed
208
+ redirectStripSlash);
209
+ app.put('/space/:spaceId/:collectionId', CollectionRequest.put);
210
+ // Delete Collection by Id
211
+ app.delete('/space/:spaceId/:collectionId/', // no trailing slash allowed
212
+ redirectStripSlash);
213
+ app.delete('/space/:spaceId/:collectionId', CollectionRequest.delete);
214
+ }
215
+ /**
216
+ * Registers Resource routes (create-by-id, get, delete a Resource). Installs the
217
+ * auth hooks and the `handleError` error handler.
218
+ * @param app {import('fastify').FastifyInstance}
219
+ * @param options {object} Fastify plugin options
220
+ * @returns {Promise<void>}
221
+ */
222
+ export async function initResourceRoutes(app, _options) {
223
+ app.setErrorHandler(handleError);
224
+ // Writes require auth; reads (GET/HEAD) may proceed unauthenticated so the
225
+ // handler can fall back to an access-control policy (e.g. a public Resource).
226
+ app.addHook('onRequest', requireAuthHeadersOrPublicRead);
227
+ // Parse the relevant request headers, set the request.zcap parameter
228
+ app.addHook('onRequest', parseAuthHeaders);
229
+ // Capture raw body bytes (JSON/text) so the digest can be recomputed against
230
+ // exactly what the client signed (spec "Request Body Integrity").
231
+ app.addHook('preParsing', captureRawBody);
232
+ // Enforce the Digest header binding: require it covered by the signature and,
233
+ // when the raw body is available, recompute and compare it.
234
+ app.addHook('preValidation', verifyBodyDigest);
235
+ // Create a Resource by Id
236
+ app.put('/space/:spaceId/:collectionId/:resourceId/', // no trailing slash allowed
237
+ redirectStripSlash);
238
+ app.put('/space/:spaceId/:collectionId/:resourceId', ResourceRequest.put);
239
+ // Head Resource. Declared before the GET route so it overrides Fastify's
240
+ // auto-exposed HEAD (which would share the GET handler and stream the body
241
+ // without a Content-Length); this handler reads only the Metadata and sets
242
+ // Content-Type/Content-Length from it (spec "Content Types and Representations").
243
+ app.head('/space/:spaceId/:collectionId/:resourceId', ResourceRequest.head);
244
+ // Get Resource
245
+ app.get('/space/:spaceId/:collectionId/:resourceId', ResourceRequest.get);
246
+ // Delete Resource
247
+ app.delete('/space/:spaceId/:collectionId/:resourceId', ResourceRequest.delete);
248
+ // Resource access-control policy (reserved segment)
249
+ app.get('/space/:spaceId/:collectionId/:resourceId/policy', PolicyRequest.get);
250
+ app.put('/space/:spaceId/:collectionId/:resourceId/policy', PolicyRequest.put);
251
+ app.delete('/space/:spaceId/:collectionId/:resourceId/policy', PolicyRequest.delete);
252
+ // Resource metadata (reserved segment; spec "Resource Metadata Data Model")
253
+ app.get('/space/:spaceId/:collectionId/:resourceId/meta', ResourceRequest.getMeta);
254
+ // Update Resource Metadata (full replacement of the user-writable `custom`).
255
+ app.put('/space/:spaceId/:collectionId/:resourceId/meta', ResourceRequest.putMeta);
256
+ }
257
+ /**
258
+ * Registers the WebKMS keystore and key routes (the `/kms` facet).
259
+ * Installs the same hook chain as the WAS groups
260
+ * except that the auth requirement is the strict `requireAuthHeaders`: every
261
+ * webkms route, GETs included, is zcap-invoked -- the protocol has no public
262
+ * reads. No slash-redirect variants either; the protocol's URLs are exact --
263
+ * only these shapes are registered.
264
+ * @param app {import('fastify').FastifyInstance}
265
+ * @param options {object} Fastify plugin options
266
+ * @returns {Promise<void>}
267
+ */
268
+ export async function initKmsRoutes(app, _options) {
269
+ app.setErrorHandler(handleError);
270
+ // Gate provisioning (Create Keystore): the configured policy may grant/deny,
271
+ // or (the default) allow -- in which case the normal zcap path below runs.
272
+ app.addHook('onRequest', provisioningGate);
273
+ // Every operation is privileged: 401 when auth headers are absent.
274
+ app.addHook('onRequest', requireAuthHeaders);
275
+ // Parse the relevant request headers, set the request.zcap parameter
276
+ app.addHook('onRequest', parseAuthHeaders);
277
+ // Capture raw body bytes (JSON/text) so the digest can be recomputed against
278
+ // exactly what the client signed (spec "Request Body Integrity").
279
+ app.addHook('preParsing', captureRawBody);
280
+ // Enforce the Digest header binding: require it covered by the signature and,
281
+ // when the raw body is available, recompute and compare it.
282
+ app.addHook('preValidation', verifyBodyDigest);
283
+ // Create Keystore
284
+ app.post('/kms/keystores', KeystoreRequest.post);
285
+ // List Keystores by controller (`?controller=<did>`)
286
+ app.get('/kms/keystores', KeystoreRequest.list);
287
+ // Get Keystore config
288
+ app.get('/kms/keystores/:keystoreId', KeystoreRequest.get);
289
+ // Update Keystore config
290
+ app.post('/kms/keystores/:keystoreId', KeystoreRequest.update);
291
+ // Generate Key (GenerateKeyOperation)
292
+ app.post('/kms/keystores/:keystoreId/keys', KeyRequest.generate);
293
+ // List Keys (fork extension: enumerate the keystore's public key
294
+ // descriptions). Static `/keys` beats the parametric `/keys/:keyId` below,
295
+ // so this never collides with the key-description GET.
296
+ app.get('/kms/keystores/:keystoreId/keys', KeyRequest.list);
297
+ // Key operation dispatch by envelope type (Sign / Verify / DeriveSecret /
298
+ // WrapKey / UnwrapKey)
299
+ app.post('/kms/keystores/:keystoreId/keys/:keyId', KeyRequest.operation);
300
+ // Public key description
301
+ app.get('/kms/keystores/:keystoreId/keys/:keyId', KeyRequest.get);
302
+ // Revoke a delegated zcap (`:revocationId` = the URL-encoded id of the
303
+ // capability being revoked, which is also the request body)
304
+ app.post('/kms/keystores/:keystoreId/zcaps/revocations/:revocationId', RevocationRequest.post);
305
+ }
306
+ //# sourceMappingURL=routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.js","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * App factory: createApp() is the community-edition composition. It builds the
3
+ * Fastify instance, registers the `fastifyWas` plugin (the whole WAS protocol
4
+ * surface -- see plugin.ts), and adds the teaching-server extras around it:
5
+ * static assets, the Handlebars-rendered welcome page, the `/health` probe,
6
+ * and the CORS proxy.
7
+ */
8
+ import { type FastifyInstance } from 'fastify';
9
+ import { type FastifyWasOptions } from './plugin.js';
10
+ /**
11
+ * Builds the Fastify instance: registers the `fastifyWas` protocol plugin
12
+ * (which carries the storage/config decorations and all WAS + WebKMS routes;
13
+ * options are passed through -- see {@link FastifyWasOptions}), then the
14
+ * teaching-server extras (static files, welcome page, health probe, CORS
15
+ * proxy).
16
+ * @param options {FastifyWasOptions}
17
+ * @returns {import('fastify').FastifyInstance}
18
+ */
19
+ export declare function createApp(options?: FastifyWasOptions): FastifyInstance;
20
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAgB,EAAE,KAAK,eAAe,EAAE,MAAM,SAAS,CAAA;AAMvD,OAAO,EAAc,KAAK,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAMhE;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,OAAO,GAAE,iBAAsB,GAAG,eAAe,CAwC1E"}
package/dist/server.js ADDED
@@ -0,0 +1,60 @@
1
+ /**
2
+ * App factory: createApp() is the community-edition composition. It builds the
3
+ * Fastify instance, registers the `fastifyWas` plugin (the whole WAS protocol
4
+ * surface -- see plugin.ts), and adds the teaching-server extras around it:
5
+ * static assets, the Handlebars-rendered welcome page, the `/health` probe,
6
+ * and the CORS proxy.
7
+ */
8
+ import Fastify, {} from 'fastify';
9
+ import fastifyView from '@fastify/view';
10
+ import fastifyStatic from '@fastify/static';
11
+ import handlebars from 'handlebars';
12
+ import path from 'node:path';
13
+ import { fastifyWas } from './plugin.js';
14
+ import { initCorsProxyRoutes as initApiCorsProxyRoutes } from './corsProxy.js';
15
+ import { SPEC_URL, SERVER_VERSION } from './config.default.js';
16
+ // TODO: https://github.com/fastify/fastify-helmet
17
+ /**
18
+ * Builds the Fastify instance: registers the `fastifyWas` protocol plugin
19
+ * (which carries the storage/config decorations and all WAS + WebKMS routes;
20
+ * options are passed through -- see {@link FastifyWasOptions}), then the
21
+ * teaching-server extras (static files, welcome page, health probe, CORS
22
+ * proxy).
23
+ * @param options {FastifyWasOptions}
24
+ * @returns {import('fastify').FastifyInstance}
25
+ */
26
+ export function createApp(options = {}) {
27
+ // By default uses 'pino' logger
28
+ const fastify = Fastify({ logger: true });
29
+ // The WAS protocol surface (decorations, parsers, WAS + WebKMS route groups)
30
+ fastify.register(fastifyWas, options);
31
+ // Serve static files from the /common folder
32
+ fastify.register(fastifyStatic, {
33
+ root: path.join(import.meta.dirname, '..', 'common'),
34
+ prefix: '/common/'
35
+ });
36
+ // Use Handlebars as the rendering engine
37
+ fastify.register(fastifyView, {
38
+ engine: { handlebars },
39
+ root: path.join(import.meta.dirname, './views'),
40
+ layout: '/templates/main', // ./views/templates/main.hbs
41
+ viewExt: 'hbs'
42
+ });
43
+ // Add a human-readable 'Welcome' page
44
+ fastify.get('/', async (request, reply) => {
45
+ return reply.view('home', { title: 'Welcome', SPEC_URL, SERVER_VERSION });
46
+ });
47
+ // Operational liveness probe (not a WAS protocol feature). Public,
48
+ // unauthenticated, and side-effect-free so load balancers, uptime monitors,
49
+ // and orchestrators can poll it cheaply. Body follows the
50
+ // `application/health+json` shape from the IETF `draft-inadarei-api-health-check`
51
+ // draft; Fastify's implicit HEAD route serves bodyless probes for free.
52
+ fastify.get('/health', async (request, reply) => {
53
+ return reply
54
+ .type('application/health+json')
55
+ .send({ status: 'pass', version: SERVER_VERSION });
56
+ });
57
+ fastify.register(initApiCorsProxyRoutes);
58
+ return fastify;
59
+ }
60
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,OAAO,EAAE,EAAwB,MAAM,SAAS,CAAA;AACvD,OAAO,WAAW,MAAM,eAAe,CAAA;AACvC,OAAO,aAAa,MAAM,iBAAiB,CAAA;AAC3C,OAAO,UAAU,MAAM,YAAY,CAAA;AACnC,OAAO,IAAI,MAAM,WAAW,CAAA;AAE5B,OAAO,EAAE,UAAU,EAA0B,MAAM,aAAa,CAAA;AAChE,OAAO,EAAE,mBAAmB,IAAI,sBAAsB,EAAE,MAAM,gBAAgB,CAAA;AAC9E,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAE9D,kDAAkD;AAElD;;;;;;;;GAQG;AACH,MAAM,UAAU,SAAS,CAAC,UAA6B,EAAE;IACvD,gCAAgC;IAChC,MAAM,OAAO,GAAG,OAAO,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAA;IAEzC,6EAA6E;IAC7E,OAAO,CAAC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAA;IAErC,6CAA6C;IAC7C,OAAO,CAAC,QAAQ,CAAC,aAAa,EAAE;QAC9B,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,QAAQ,CAAC;QACpD,MAAM,EAAE,UAAU;KACnB,CAAC,CAAA;IAEF,yCAAyC;IACzC,OAAO,CAAC,QAAQ,CAAC,WAAW,EAAE;QAC5B,MAAM,EAAE,EAAE,UAAU,EAAE;QACtB,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC;QAC/C,MAAM,EAAE,iBAAiB,EAAE,6BAA6B;QACxD,OAAO,EAAE,KAAK;KACf,CAAC,CAAA;IAEF,sCAAsC;IACtC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACxC,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,EAAE,CAAC,CAAA;IAC3E,CAAC,CAAC,CAAA;IAEF,mEAAmE;IACnE,4EAA4E;IAC5E,0DAA0D;IAC1D,kFAAkF;IAClF,wEAAwE;IACxE,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QAC9C,OAAO,KAAK;aACT,IAAI,CAAC,yBAAyB,CAAC;aAC/B,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,CAAA;IACtD,CAAC,CAAC,CAAA;IAEF,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAC,CAAA;IAExC,OAAO,OAAO,CAAA;AAChB,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Loads the validated env config, builds the app via createApp(), and starts
3
+ * listening. Exits the process with code 1 on startup failure.
4
+ * @returns {Promise<void>}
5
+ */
6
+ export declare function startServer(): Promise<void>;
7
+ //# sourceMappingURL=start.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../src/start.ts"],"names":[],"mappings":"AAUA;;;;GAIG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAqDjD"}
package/dist/start.js ADDED
@@ -0,0 +1,61 @@
1
+ import { createApp } from './server.js';
2
+ import { PostgresBackend } from './backends/postgres.js';
3
+ import { loadConfigFromEnv } from './config.default.js';
4
+ /**
5
+ * Loads the validated env config, builds the app via createApp(), and starts
6
+ * listening. Exits the process with code 1 on startup failure.
7
+ * @returns {Promise<void>}
8
+ */
9
+ export async function startServer() {
10
+ let fastify;
11
+ try {
12
+ const config = loadConfigFromEnv();
13
+ // Backend selection: presence of DATABASE_URL selects the Postgres
14
+ // backend; otherwise createApp falls back to the default filesystem
15
+ // backend (rooted at data/). An injected backend carries its own quota
16
+ // configuration, so the per-Space/per-upload limits are passed to it
17
+ // directly rather than through the createApp options.
18
+ const backend = config.databaseUrl
19
+ ? new PostgresBackend({
20
+ connectionString: config.databaseUrl,
21
+ capacityBytes: config.storageLimitPerSpace,
22
+ maxUploadBytes: config.maxUploadBytes,
23
+ maxSpacesPerController: config.maxSpacesPerController,
24
+ maxCollectionsPerSpace: config.maxCollectionsPerSpace,
25
+ maxResourcesPerSpace: config.maxResourcesPerSpace
26
+ })
27
+ : undefined;
28
+ fastify = createApp({
29
+ serverUrl: config.serverUrl,
30
+ ...(backend && { backend }),
31
+ storageLimitPerSpace: config.storageLimitPerSpace,
32
+ maxUploadBytes: config.maxUploadBytes,
33
+ maxSpacesPerController: config.maxSpacesPerController,
34
+ maxCollectionsPerSpace: config.maxCollectionsPerSpace,
35
+ maxResourcesPerSpace: config.maxResourcesPerSpace,
36
+ enabledBackendProviders: config.enabledBackendProviders,
37
+ kmsRecordKek: config.kmsRecordKek,
38
+ onboardingToken: config.onboardingToken
39
+ });
40
+ // Warn (once, at startup, where the Fastify logger now exists) about limits
41
+ // left implicitly unbounded. These warnings live only here so library and
42
+ // test compositions of createApp() stay silent; an explicit `unlimited`
43
+ // (Infinity) or a finite value is a deliberate choice and warns nothing.
44
+ if (config.storageLimitPerSpace === undefined) {
45
+ fastify.log.warn('No per-Space storage quota configured; Spaces may grow without ' +
46
+ 'bound. Set STORAGE_LIMIT_PER_SPACE (bytes), or ' +
47
+ 'STORAGE_LIMIT_PER_SPACE=unlimited to acknowledge.');
48
+ }
49
+ if (config.maxUploadBytes === Infinity) {
50
+ fastify.log.warn('Per-upload size cap disabled (MAX_UPLOAD_BYTES=unlimited); a single ' +
51
+ 'upload may consume unbounded memory on buffered write paths.');
52
+ }
53
+ await fastify.listen({ port: config.port, host: '0.0.0.0' });
54
+ }
55
+ catch (err) {
56
+ console.error('Server startup failed:', err);
57
+ process.exit(1);
58
+ }
59
+ }
60
+ startServer();
61
+ //# sourceMappingURL=start.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start.js","sourceRoot":"","sources":["../src/start.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAEvD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,IAAI,OAAwB,CAAA;IAC5B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,iBAAiB,EAAE,CAAA;QAClC,mEAAmE;QACnE,oEAAoE;QACpE,uEAAuE;QACvE,qEAAqE;QACrE,sDAAsD;QACtD,MAAM,OAAO,GAAG,MAAM,CAAC,WAAW;YAChC,CAAC,CAAC,IAAI,eAAe,CAAC;gBAClB,gBAAgB,EAAE,MAAM,CAAC,WAAW;gBACpC,aAAa,EAAE,MAAM,CAAC,oBAAoB;gBAC1C,cAAc,EAAE,MAAM,CAAC,cAAc;gBACrC,sBAAsB,EAAE,MAAM,CAAC,sBAAsB;gBACrD,sBAAsB,EAAE,MAAM,CAAC,sBAAsB;gBACrD,oBAAoB,EAAE,MAAM,CAAC,oBAAoB;aAClD,CAAC;YACJ,CAAC,CAAC,SAAS,CAAA;QACb,OAAO,GAAG,SAAS,CAAC;YAClB,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,GAAG,CAAC,OAAO,IAAI,EAAE,OAAO,EAAE,CAAC;YAC3B,oBAAoB,EAAE,MAAM,CAAC,oBAAoB;YACjD,cAAc,EAAE,MAAM,CAAC,cAAc;YACrC,sBAAsB,EAAE,MAAM,CAAC,sBAAsB;YACrD,sBAAsB,EAAE,MAAM,CAAC,sBAAsB;YACrD,oBAAoB,EAAE,MAAM,CAAC,oBAAoB;YACjD,uBAAuB,EAAE,MAAM,CAAC,uBAAuB;YACvD,YAAY,EAAE,MAAM,CAAC,YAAY;YACjC,eAAe,EAAE,MAAM,CAAC,eAAe;SACxC,CAAC,CAAA;QACF,4EAA4E;QAC5E,0EAA0E;QAC1E,wEAAwE;QACxE,yEAAyE;QACzE,IAAI,MAAM,CAAC,oBAAoB,KAAK,SAAS,EAAE,CAAC;YAC9C,OAAO,CAAC,GAAG,CAAC,IAAI,CACd,iEAAiE;gBAC/D,iDAAiD;gBACjD,mDAAmD,CACtD,CAAA;QACH,CAAC;QACD,IAAI,MAAM,CAAC,cAAc,KAAK,QAAQ,EAAE,CAAC;YACvC,OAAO,CAAC,GAAG,CAAC,IAAI,CACd,sEAAsE;gBACpE,8DAA8D,CACjE,CAAA;QACH,CAAC;QACD,MAAM,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAA;IAC9D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,wBAAwB,EAAE,GAAG,CAAC,CAAA;QAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;AACH,CAAC;AAED,WAAW,EAAE,CAAA"}
@@ -0,0 +1,29 @@
1
+ import type { StorageBackend } from './types.js';
2
+ /**
3
+ * Builds the default filesystem-backed storage, rooted at the project `data/`
4
+ * directory. Used by `createApp()` when no backend is injected (production).
5
+ * @param options {object}
6
+ * @param [options.capacityBytes] {number} per-Space storage limit in bytes
7
+ * (spec "Quotas"); `undefined` (or `Infinity`) means each Space is unlimited.
8
+ * @param [options.maxUploadBytes] {number} per-upload size cap in bytes (spec
9
+ * "Quotas", `maxUploadBytes`); `undefined` applies the backend's default-on
10
+ * cap, `Infinity` means no per-upload cap.
11
+ * @param [options.maxSpacesPerController] {number} max Spaces per controller
12
+ * (spec "Quotas"); `undefined` applies the backend's default-on limit,
13
+ * `Infinity` means no cap.
14
+ * @param [options.maxCollectionsPerSpace] {number} max Collections per Space
15
+ * (spec "Quotas"); `undefined` applies the backend's default-on limit,
16
+ * `Infinity` means no cap.
17
+ * @param [options.maxResourcesPerSpace] {number} max live Resources per Space
18
+ * (spec "Quotas"); `undefined` applies the backend's default-on limit,
19
+ * `Infinity` means no cap.
20
+ * @returns {StorageBackend}
21
+ */
22
+ export declare function defaultBackend({ capacityBytes, maxUploadBytes, maxSpacesPerController, maxCollectionsPerSpace, maxResourcesPerSpace }?: {
23
+ capacityBytes?: number;
24
+ maxUploadBytes?: number;
25
+ maxSpacesPerController?: number;
26
+ maxCollectionsPerSpace?: number;
27
+ maxResourcesPerSpace?: number;
28
+ }): StorageBackend;
29
+ //# sourceMappingURL=storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAEhD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,cAAc,CAAC,EAC7B,aAAa,EACb,cAAc,EACd,sBAAsB,EACtB,sBAAsB,EACtB,oBAAoB,EACrB,GAAE;IACD,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,sBAAsB,CAAC,EAAE,MAAM,CAAA;IAC/B,sBAAsB,CAAC,EAAE,MAAM,CAAA;IAC/B,oBAAoB,CAAC,EAAE,MAAM,CAAA;CACzB,GAAG,cAAc,CAStB"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Storage composition helper: builds the default StorageBackend used by the
3
+ * server when no backend is injected.
4
+ *
5
+ * This module only supplies the default backend for production / `start.ts`,
6
+ * where `createApp()` is called without an explicit backend.
7
+ * The active backend is injected into the Fastify instance via
8
+ * `createApp({ backend })` (see plugin.ts) and read in handlers as
9
+ * `request.server.storage`.
10
+ *
11
+ * The StorageBackend contract — including its invariants (getters resolve falsy
12
+ * for not-found, writes are upserts, deletes are idempotent) — is documented on
13
+ * the interface in src/types.ts.
14
+ */
15
+ import path from 'node:path';
16
+ import { FileSystemBackend } from './backends/filesystem.js';
17
+ /**
18
+ * Builds the default filesystem-backed storage, rooted at the project `data/`
19
+ * directory. Used by `createApp()` when no backend is injected (production).
20
+ * @param options {object}
21
+ * @param [options.capacityBytes] {number} per-Space storage limit in bytes
22
+ * (spec "Quotas"); `undefined` (or `Infinity`) means each Space is unlimited.
23
+ * @param [options.maxUploadBytes] {number} per-upload size cap in bytes (spec
24
+ * "Quotas", `maxUploadBytes`); `undefined` applies the backend's default-on
25
+ * cap, `Infinity` means no per-upload cap.
26
+ * @param [options.maxSpacesPerController] {number} max Spaces per controller
27
+ * (spec "Quotas"); `undefined` applies the backend's default-on limit,
28
+ * `Infinity` means no cap.
29
+ * @param [options.maxCollectionsPerSpace] {number} max Collections per Space
30
+ * (spec "Quotas"); `undefined` applies the backend's default-on limit,
31
+ * `Infinity` means no cap.
32
+ * @param [options.maxResourcesPerSpace] {number} max live Resources per Space
33
+ * (spec "Quotas"); `undefined` applies the backend's default-on limit,
34
+ * `Infinity` means no cap.
35
+ * @returns {StorageBackend}
36
+ */
37
+ export function defaultBackend({ capacityBytes, maxUploadBytes, maxSpacesPerController, maxCollectionsPerSpace, maxResourcesPerSpace } = {}) {
38
+ return new FileSystemBackend({
39
+ dataDir: path.join(import.meta.dirname, '..', 'data'),
40
+ capacityBytes,
41
+ maxUploadBytes,
42
+ maxSpacesPerController,
43
+ maxCollectionsPerSpace,
44
+ maxResourcesPerSpace
45
+ });
46
+ }
47
+ //# sourceMappingURL=storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.js","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAG5D;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,cAAc,CAAC,EAC7B,aAAa,EACb,cAAc,EACd,sBAAsB,EACtB,sBAAsB,EACtB,oBAAoB,KAOlB,EAAE;IACJ,OAAO,IAAI,iBAAiB,CAAC;QAC3B,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC;QACrD,aAAa;QACb,cAAc;QACd,sBAAsB;QACtB,sBAAsB;QACtB,oBAAoB;KACrB,CAAC,CAAA;AACJ,CAAC"}