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,270 @@
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 function spacesPath({ spaceId } = {}) {
28
+ return spaceId !== undefined ? `/spaces/${spaceId}` : `/spaces/`;
29
+ }
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 function spacePath({ spaceId, trailingSlash = false }) {
39
+ return `/space/${spaceId}${trailingSlash ? '/' : ''}`;
40
+ }
41
+ /**
42
+ * `/space/:spaceId/collections/` -- the "List Collections" container path.
43
+ * @param options {object}
44
+ * @param options.spaceId {string}
45
+ * @returns {string}
46
+ */
47
+ export function collectionsPath({ spaceId }) {
48
+ return `${spacePath({ spaceId })}/collections/`;
49
+ }
50
+ /**
51
+ * `/space/:spaceId/export` -- the "Export Space" action path.
52
+ * @param options {object}
53
+ * @param options.spaceId {string}
54
+ * @returns {string}
55
+ */
56
+ export function exportPath({ spaceId }) {
57
+ return `${spacePath({ spaceId })}/export`;
58
+ }
59
+ /**
60
+ * `/space/:spaceId/import` -- the "Import Space" action path.
61
+ * @param options {object}
62
+ * @param options.spaceId {string}
63
+ * @returns {string}
64
+ */
65
+ export function importPath({ spaceId }) {
66
+ return `${spacePath({ spaceId })}/import`;
67
+ }
68
+ /**
69
+ * `/space/:spaceId/:collectionId` (member) or `/space/:spaceId/:collectionId/`
70
+ * (container -- the "add a Resource" / "list items" view) when `trailingSlash`
71
+ * is set.
72
+ * @param options {object}
73
+ * @param options.spaceId {string}
74
+ * @param options.collectionId {string}
75
+ * @param [options.trailingSlash] {boolean} address the container form
76
+ * @returns {string}
77
+ */
78
+ export function collectionPath({ spaceId, collectionId, trailingSlash = false }) {
79
+ return `/space/${spaceId}/${collectionId}${trailingSlash ? '/' : ''}`;
80
+ }
81
+ /**
82
+ * `/space/:spaceId/:collectionId/:resourceId`
83
+ * @param options {object}
84
+ * @param options.spaceId {string}
85
+ * @param options.collectionId {string}
86
+ * @param options.resourceId {string}
87
+ * @returns {string}
88
+ */
89
+ export function resourcePath({ spaceId, collectionId, resourceId }) {
90
+ return `/space/${spaceId}/${collectionId}/${resourceId}`;
91
+ }
92
+ /**
93
+ * The `policy` auxiliary resource path for whichever level the ids address:
94
+ * Space (`spaceId`), Collection (`+ collectionId`), or Resource
95
+ * (`+ collectionId + resourceId`).
96
+ * @param options {object}
97
+ * @param options.spaceId {string}
98
+ * @param [options.collectionId] {string}
99
+ * @param [options.resourceId] {string}
100
+ * @returns {string}
101
+ */
102
+ export function policyPath({ spaceId, collectionId, resourceId }) {
103
+ if (collectionId !== undefined && resourceId !== undefined) {
104
+ return `${resourcePath({ spaceId, collectionId, resourceId })}/policy`;
105
+ }
106
+ if (collectionId !== undefined) {
107
+ return `${collectionPath({ spaceId, collectionId })}/policy`;
108
+ }
109
+ return `${spacePath({ spaceId })}/policy`;
110
+ }
111
+ /**
112
+ * `/space/:spaceId/backends` -- the "Space Backends Available" list path.
113
+ * @param options {object}
114
+ * @param options.spaceId {string}
115
+ * @returns {string}
116
+ */
117
+ export function backendsPath({ spaceId }) {
118
+ return `${spacePath({ spaceId })}/backends`;
119
+ }
120
+ /**
121
+ * `/space/:spaceId/backends/:backendId` -- a single registered `external`
122
+ * backend record (the `POST` `Location` target, and the `PUT`/`DELETE` member
123
+ * path). Distinct from {@link backendPath}, which is a Collection's *selected*
124
+ * backend resource.
125
+ * @param options {object}
126
+ * @param options.spaceId {string}
127
+ * @param options.backendId {string}
128
+ * @returns {string}
129
+ */
130
+ export function registeredBackendPath({ spaceId, backendId }) {
131
+ return `${backendsPath({ spaceId })}/${backendId}`;
132
+ }
133
+ /**
134
+ * `/space/:spaceId/quotas` -- the Space Quota report path (spec "Quotas").
135
+ * @param options {object}
136
+ * @param options.spaceId {string}
137
+ * @returns {string}
138
+ */
139
+ export function quotasPath({ spaceId }) {
140
+ return `${spacePath({ spaceId })}/quotas`;
141
+ }
142
+ /**
143
+ * `/space/:spaceId/:collectionId/:resourceId/meta` -- the Resource Metadata
144
+ * (reserved `meta` segment) path. Reserved only at the Resource level, so it
145
+ * takes the full id triple.
146
+ * @param options {object}
147
+ * @param options.spaceId {string}
148
+ * @param options.collectionId {string}
149
+ * @param options.resourceId {string}
150
+ * @returns {string}
151
+ */
152
+ export function metaPath({ spaceId, collectionId, resourceId }) {
153
+ return `${resourcePath({ spaceId, collectionId, resourceId })}/meta`;
154
+ }
155
+ /**
156
+ * `/space/:spaceId/:collectionId/backend` -- the "Collection Backend Selected"
157
+ * resource path (reserved `backend` segment at the Resource level).
158
+ * @param options {object}
159
+ * @param options.spaceId {string}
160
+ * @param options.collectionId {string}
161
+ * @returns {string}
162
+ */
163
+ export function backendPath({ spaceId, collectionId }) {
164
+ return `${collectionPath({ spaceId, collectionId })}/backend`;
165
+ }
166
+ /**
167
+ * `/space/:spaceId/:collectionId/quota` -- the per-Collection storage quota
168
+ * report path (reserved `quota` segment at the Resource level; spec "Quotas").
169
+ * @param options {object}
170
+ * @param options.spaceId {string}
171
+ * @param options.collectionId {string}
172
+ * @returns {string}
173
+ */
174
+ export function quotaPath({ spaceId, collectionId }) {
175
+ return `${collectionPath({ spaceId, collectionId })}/quota`;
176
+ }
177
+ /**
178
+ * `/space/:spaceId/:collectionId/query` -- the reserved `query` endpoint for a
179
+ * Collection (spec "Collection-level reserved endpoints"). The WAS server serves
180
+ * the replication change feed as the `changes` profile of this endpoint.
181
+ * @param options {object}
182
+ * @param options.spaceId {string}
183
+ * @param options.collectionId {string}
184
+ * @returns {string}
185
+ */
186
+ export function queryPath({ spaceId, collectionId }) {
187
+ return `${collectionPath({ spaceId, collectionId })}/query`;
188
+ }
189
+ /**
190
+ * The `linkset` discovery resource path for a Space (`spaceId`) or Collection
191
+ * (`+ collectionId`).
192
+ * @param options {object}
193
+ * @param options.spaceId {string}
194
+ * @param [options.collectionId] {string}
195
+ * @returns {string}
196
+ */
197
+ export function linksetPath({ spaceId, collectionId }) {
198
+ const anchor = collectionId !== undefined
199
+ ? collectionPath({ spaceId, collectionId })
200
+ : spacePath({ spaceId });
201
+ return `${anchor}/linkset`;
202
+ }
203
+ /**
204
+ * `/kms/keystores` -- the WebKMS keystores collection (create/list target; the
205
+ * `/kms` facet) or one of its member keystores
206
+ * (`/kms/keystores/:keystoreId`). Unlike the WAS builders there is no
207
+ * trailing-slash container form: the webkms protocol
208
+ * (`@interop/webkms-client`) posts to the bare collection path.
209
+ * @param options {object}
210
+ * @param [options.keystoreId] {string} the keystore's server-generated local
211
+ * id; when present, the member path, otherwise the collection path
212
+ * @returns {string}
213
+ */
214
+ export function kmsKeystoresPath({ keystoreId } = {}) {
215
+ return keystoreId !== undefined
216
+ ? `/kms/keystores/${keystoreId}`
217
+ : '/kms/keystores';
218
+ }
219
+ /**
220
+ * `/kms/keystores/:keystoreId/keys` -- a keystore's keys collection (the
221
+ * `GenerateKeyOperation` target) or one of its member keys
222
+ * (`/kms/keystores/:keystoreId/keys/:keyId`, the key-operation / description
223
+ * target). Like `kmsKeystoresPath`, no trailing-slash form exists: the webkms
224
+ * protocol's URLs are exact.
225
+ * @param options {object}
226
+ * @param options.keystoreId {string} the keystore's local id
227
+ * @param [options.keyId] {string} the key's server-generated local id; when
228
+ * present, the member path, otherwise the collection path
229
+ * @returns {string}
230
+ */
231
+ export function kmsKeysPath({ keystoreId, keyId }) {
232
+ const keysPath = `${kmsKeystoresPath({ keystoreId })}/keys`;
233
+ return keyId !== undefined ? `${keysPath}/${keyId}` : keysPath;
234
+ }
235
+ /**
236
+ * `/kms/keystores/:keystoreId/zcaps/revocations/:revocationId` -- a keystore's
237
+ * zcap revocation submission target (POST; the ezcap-express
238
+ * `/zcaps/revocations/` convention). `revocationId` is the *to-be-revoked
239
+ * capability's id*, URL-encoded into the single path segment the route
240
+ * expects -- the same `encodeURIComponent` framing `@interop/webkms-client`'s
241
+ * `revokeCapability` puts on the wire.
242
+ * @param options {object}
243
+ * @param options.keystoreId {string} the keystore's local id
244
+ * @param options.revocationId {string} the to-be-revoked capability's id
245
+ * (raw, un-encoded)
246
+ * @returns {string}
247
+ */
248
+ export function kmsRevocationsPath({ keystoreId, revocationId }) {
249
+ return (`${kmsKeystoresPath({ keystoreId })}/zcaps/revocations/` +
250
+ encodeURIComponent(revocationId));
251
+ }
252
+ /**
253
+ * `/space/:spaceId/zcaps/revocations/:revocationId` -- a Space's zcap
254
+ * revocation submission target (POST), the WAS-route sibling of
255
+ * `kmsRevocationsPath` and the same ezcap-express `/zcaps/revocations/`
256
+ * convention. `revocationId` is the *to-be-revoked capability's id*,
257
+ * URL-encoded into the single path segment the route expects. The `zcaps`
258
+ * segment sits four levels under `/space`, deeper than any Collection or
259
+ * Resource route, so it shadows neither and needs no reserved-id entry.
260
+ * @param options {object}
261
+ * @param options.spaceId {string}
262
+ * @param options.revocationId {string} the to-be-revoked capability's id
263
+ * (raw, un-encoded)
264
+ * @returns {string}
265
+ */
266
+ export function spaceRevocationsPath({ spaceId, revocationId }) {
267
+ return (`${spacePath({ spaceId })}/zcaps/revocations/` +
268
+ encodeURIComponent(revocationId));
269
+ }
270
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/lib/paths.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Evaluates a content-write (or delete) precondition against a Resource's
3
+ * current state. Throws `PreconditionFailedError` (412) when it is not met.
4
+ * `ifNoneMatch` (`If-None-Match: *`, create-if-absent) takes precedence over
5
+ * `ifMatch` when both are present (RFC9110): the write proceeds only if the
6
+ * Resource is absent. `ifMatch` (update-if-unchanged) requires the Resource to
7
+ * exist with a current ETag equal to the supplied validator.
8
+ * @param options {object}
9
+ * @param options.resourceId {string} for the error detail
10
+ * @param options.exists {boolean} whether the Resource currently exists (a
11
+ * tombstone counts as "does not exist")
12
+ * @param options.currentVersion {number} the Resource's current content
13
+ * `version` (0 for a legacy Resource without one)
14
+ * @param [options.ifMatch] {string} a quoted ETag (`If-Match`)
15
+ * @param [options.ifNoneMatch] {boolean} `If-None-Match: *` (create-if-absent)
16
+ * @returns {void}
17
+ */
18
+ export declare function assertWritePrecondition({ resourceId, exists, currentVersion, ifMatch, ifNoneMatch }: {
19
+ resourceId: string;
20
+ exists: boolean;
21
+ currentVersion: number;
22
+ ifMatch?: string;
23
+ ifNoneMatch?: boolean;
24
+ }): void;
25
+ /**
26
+ * Evaluates a Collection Description write precondition against the Collection's
27
+ * current description `version` (the `key-epochs` / conditional-Collection-write
28
+ * feature). Throws `PreconditionFailedError` (412) when the supplied `If-Match`
29
+ * validator does not equal the current description ETag. Only `If-Match`
30
+ * (update-if-unchanged) is supported for Collections; a create through an
31
+ * unconditional PUT is unaffected. MUST be called atomically with the write
32
+ * (under the filesystem backend's per-Collection lock, or inside the Postgres
33
+ * backend's row-locking transaction).
34
+ * @param options {object}
35
+ * @param options.collectionId {string} for the error detail
36
+ * @param options.currentVersion {number} the Collection's current description
37
+ * `version` (0 for a legacy Collection without one, or before its first write)
38
+ * @param [options.ifMatch] {string} a quoted ETag (`If-Match`)
39
+ * @returns {void}
40
+ */
41
+ export declare function assertCollectionWritePrecondition({ collectionId, currentVersion, ifMatch }: {
42
+ collectionId: string;
43
+ currentVersion: number;
44
+ ifMatch?: string;
45
+ }): void;
46
+ /**
47
+ * Evaluates a metadata-write (`/meta`) precondition against a Resource's
48
+ * current `metaVersion`. Throws `PreconditionFailedError` (412) when it is not
49
+ * met. `If-None-Match: *` means "only if no metadata has been written yet"
50
+ * (`metaVersion` unset); `If-Match` pins the current `metaVersion` ETag.
51
+ * @param options {object}
52
+ * @param options.resourceId {string} for the error detail
53
+ * @param [options.metaVersion] {number} the current `metaVersion`
54
+ * (`undefined` until the first metadata write)
55
+ * @param [options.ifMatch] {string} a quoted ETag (`If-Match`)
56
+ * @param [options.ifNoneMatch] {boolean} `If-None-Match: *`
57
+ * @returns {void}
58
+ */
59
+ export declare function assertMetaWritePrecondition({ resourceId, metaVersion, ifMatch, ifNoneMatch }: {
60
+ resourceId: string;
61
+ metaVersion?: number;
62
+ ifMatch?: string;
63
+ ifNoneMatch?: boolean;
64
+ }): void;
65
+ //# sourceMappingURL=preconditions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preconditions.d.ts","sourceRoot":"","sources":["../../src/lib/preconditions.ts"],"names":[],"mappings":"AAYA;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,uBAAuB,CAAC,EACtC,UAAU,EACV,MAAM,EACN,cAAc,EACd,OAAO,EACP,WAAW,EACZ,EAAE;IACD,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,OAAO,CAAA;IACf,cAAc,EAAE,MAAM,CAAA;IACtB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB,GAAG,IAAI,CA2BP;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iCAAiC,CAAC,EAChD,YAAY,EACZ,cAAc,EACd,OAAO,EACR,EAAE;IACD,YAAY,EAAE,MAAM,CAAA;IACpB,cAAc,EAAE,MAAM,CAAA;IACtB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,GAAG,IAAI,CAUP;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,2BAA2B,CAAC,EAC1C,UAAU,EACV,WAAW,EACX,OAAO,EACP,WAAW,EACZ,EAAE;IACD,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB,GAAG,IAAI,CAeP"}
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Backend-agnostic conditional-write precondition evaluation (the
3
+ * `conditional-writes` feature). Both storage backends evaluate `If-Match` /
4
+ * `If-None-Match` against a Resource's current state through these two
5
+ * helpers, so the 412 semantics cannot drift between them. Callers MUST invoke
6
+ * them atomically with the write that follows (under the filesystem backend's
7
+ * per-Resource lock, or inside the Postgres backend's row-locking
8
+ * transaction).
9
+ */
10
+ import { PreconditionFailedError } from '../errors.js';
11
+ import { formatEtag } from './etag.js';
12
+ /**
13
+ * Evaluates a content-write (or delete) precondition against a Resource's
14
+ * current state. Throws `PreconditionFailedError` (412) when it is not met.
15
+ * `ifNoneMatch` (`If-None-Match: *`, create-if-absent) takes precedence over
16
+ * `ifMatch` when both are present (RFC9110): the write proceeds only if the
17
+ * Resource is absent. `ifMatch` (update-if-unchanged) requires the Resource to
18
+ * exist with a current ETag equal to the supplied validator.
19
+ * @param options {object}
20
+ * @param options.resourceId {string} for the error detail
21
+ * @param options.exists {boolean} whether the Resource currently exists (a
22
+ * tombstone counts as "does not exist")
23
+ * @param options.currentVersion {number} the Resource's current content
24
+ * `version` (0 for a legacy Resource without one)
25
+ * @param [options.ifMatch] {string} a quoted ETag (`If-Match`)
26
+ * @param [options.ifNoneMatch] {boolean} `If-None-Match: *` (create-if-absent)
27
+ * @returns {void}
28
+ */
29
+ export function assertWritePrecondition({ resourceId, exists, currentVersion, ifMatch, ifNoneMatch }) {
30
+ if (ifNoneMatch) {
31
+ if (exists) {
32
+ throw new PreconditionFailedError({
33
+ detail: `Resource '${resourceId}' already exists (If-None-Match: *).`
34
+ });
35
+ }
36
+ return;
37
+ }
38
+ if (ifMatch === undefined) {
39
+ return;
40
+ }
41
+ // `If-Match` (update-if-unchanged): the Resource must exist and its current
42
+ // ETag must equal the supplied validator.
43
+ if (!exists) {
44
+ throw new PreconditionFailedError({
45
+ detail: `Resource '${resourceId}' does not exist; If-Match cannot be satisfied.`
46
+ });
47
+ }
48
+ const currentEtag = formatEtag(currentVersion);
49
+ if (currentEtag !== ifMatch) {
50
+ throw new PreconditionFailedError({
51
+ detail: `Resource '${resourceId}' ETag ${currentEtag} does not match If-Match ${ifMatch}.`
52
+ });
53
+ }
54
+ }
55
+ /**
56
+ * Evaluates a Collection Description write precondition against the Collection's
57
+ * current description `version` (the `key-epochs` / conditional-Collection-write
58
+ * feature). Throws `PreconditionFailedError` (412) when the supplied `If-Match`
59
+ * validator does not equal the current description ETag. Only `If-Match`
60
+ * (update-if-unchanged) is supported for Collections; a create through an
61
+ * unconditional PUT is unaffected. MUST be called atomically with the write
62
+ * (under the filesystem backend's per-Collection lock, or inside the Postgres
63
+ * backend's row-locking transaction).
64
+ * @param options {object}
65
+ * @param options.collectionId {string} for the error detail
66
+ * @param options.currentVersion {number} the Collection's current description
67
+ * `version` (0 for a legacy Collection without one, or before its first write)
68
+ * @param [options.ifMatch] {string} a quoted ETag (`If-Match`)
69
+ * @returns {void}
70
+ */
71
+ export function assertCollectionWritePrecondition({ collectionId, currentVersion, ifMatch }) {
72
+ if (ifMatch === undefined) {
73
+ return;
74
+ }
75
+ const currentEtag = formatEtag(currentVersion);
76
+ if (currentEtag !== ifMatch) {
77
+ throw new PreconditionFailedError({
78
+ detail: `Collection '${collectionId}' ETag ${currentEtag} does not match If-Match ${ifMatch}.`
79
+ });
80
+ }
81
+ }
82
+ /**
83
+ * Evaluates a metadata-write (`/meta`) precondition against a Resource's
84
+ * current `metaVersion`. Throws `PreconditionFailedError` (412) when it is not
85
+ * met. `If-None-Match: *` means "only if no metadata has been written yet"
86
+ * (`metaVersion` unset); `If-Match` pins the current `metaVersion` ETag.
87
+ * @param options {object}
88
+ * @param options.resourceId {string} for the error detail
89
+ * @param [options.metaVersion] {number} the current `metaVersion`
90
+ * (`undefined` until the first metadata write)
91
+ * @param [options.ifMatch] {string} a quoted ETag (`If-Match`)
92
+ * @param [options.ifNoneMatch] {boolean} `If-None-Match: *`
93
+ * @returns {void}
94
+ */
95
+ export function assertMetaWritePrecondition({ resourceId, metaVersion, ifMatch, ifNoneMatch }) {
96
+ if (ifNoneMatch) {
97
+ if (metaVersion !== undefined) {
98
+ throw new PreconditionFailedError({
99
+ detail: `Resource '${resourceId}' metadata already exists (If-None-Match: *).`
100
+ });
101
+ }
102
+ }
103
+ else if (ifMatch !== undefined) {
104
+ const currentEtag = formatEtag(metaVersion ?? 0);
105
+ if (currentEtag !== ifMatch) {
106
+ throw new PreconditionFailedError({
107
+ detail: `Resource '${resourceId}' metadata ETag ${currentEtag} does not match If-Match ${ifMatch}.`
108
+ });
109
+ }
110
+ }
111
+ }
112
+ //# sourceMappingURL=preconditions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preconditions.js","sourceRoot":"","sources":["../../src/lib/preconditions.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAA;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAEtC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,uBAAuB,CAAC,EACtC,UAAU,EACV,MAAM,EACN,cAAc,EACd,OAAO,EACP,WAAW,EAOZ;IACC,IAAI,WAAW,EAAE,CAAC;QAChB,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,IAAI,uBAAuB,CAAC;gBAChC,MAAM,EAAE,aAAa,UAAU,sCAAsC;aACtE,CAAC,CAAA;QACJ,CAAC;QACD,OAAM;IACR,CAAC;IAED,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAM;IACR,CAAC;IAED,4EAA4E;IAC5E,0CAA0C;IAC1C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,uBAAuB,CAAC;YAChC,MAAM,EAAE,aAAa,UAAU,iDAAiD;SACjF,CAAC,CAAA;IACJ,CAAC;IACD,MAAM,WAAW,GAAG,UAAU,CAAC,cAAc,CAAC,CAAA;IAC9C,IAAI,WAAW,KAAK,OAAO,EAAE,CAAC;QAC5B,MAAM,IAAI,uBAAuB,CAAC;YAChC,MAAM,EAAE,aAAa,UAAU,UAAU,WAAW,4BAA4B,OAAO,GAAG;SAC3F,CAAC,CAAA;IACJ,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,iCAAiC,CAAC,EAChD,YAAY,EACZ,cAAc,EACd,OAAO,EAKR;IACC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAM;IACR,CAAC;IACD,MAAM,WAAW,GAAG,UAAU,CAAC,cAAc,CAAC,CAAA;IAC9C,IAAI,WAAW,KAAK,OAAO,EAAE,CAAC;QAC5B,MAAM,IAAI,uBAAuB,CAAC;YAChC,MAAM,EAAE,eAAe,YAAY,UAAU,WAAW,4BAA4B,OAAO,GAAG;SAC/F,CAAC,CAAA;IACJ,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,2BAA2B,CAAC,EAC1C,UAAU,EACV,WAAW,EACX,OAAO,EACP,WAAW,EAMZ;IACC,IAAI,WAAW,EAAE,CAAC;QAChB,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YAC9B,MAAM,IAAI,uBAAuB,CAAC;gBAChC,MAAM,EAAE,aAAa,UAAU,+CAA+C;aAC/E,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;SAAM,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QACjC,MAAM,WAAW,GAAG,UAAU,CAAC,WAAW,IAAI,CAAC,CAAC,CAAA;QAChD,IAAI,WAAW,KAAK,OAAO,EAAE,CAAC;YAC5B,MAAM,IAAI,uBAAuB,CAAC;gBAChC,MAAM,EAAE,aAAa,UAAU,mBAAmB,WAAW,4BAA4B,OAAO,GAAG;aACpG,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Percent-encodes a filename segment so it carries no literal `.`, the
3
+ * structural delimiter of `r.<resourceId>.<encodedContentType>.<ext>`.
4
+ * `encodeURIComponent` leaves `.` unescaped, so escape it explicitly to `%2E`;
5
+ * `decodeURIComponent` reverses both. This keeps resource ids and content-types
6
+ * that legitimately contain dots (e.g. `index.html`, `application/vnd.api+json`)
7
+ * unambiguously parseable -- without it, a dotted id mis-splits and is read back
8
+ * under the wrong id and content-type. For dot-free segments (the common case)
9
+ * the result is byte-identical to the previous `encodeURIComponent`-only scheme.
10
+ * @param segment {string}
11
+ * @returns {string}
12
+ */
13
+ export declare function encodeFilenameSegment(segment: string): string;
14
+ /**
15
+ * Builds the on-disk filename for a resource representation:
16
+ * `r.<resourceId>.<encodedContentType>.<ext>`. Both the `resourceId` and
17
+ * content-type segments are dot-escaped (see {@link encodeFilenameSegment}) so
18
+ * the three `.` separators are the only literal dots.
19
+ * @param options {object}
20
+ * @param options.resourceId {string}
21
+ * @param options.contentType {string}
22
+ * @returns {string}
23
+ */
24
+ export declare function fileNameFor({ resourceId, contentType }: {
25
+ resourceId: string;
26
+ contentType: string;
27
+ }): string;
28
+ /**
29
+ * Parses an on-disk resource filename (`r.<resourceId>.<encodedContentType>.<ext>`)
30
+ * back into its components, reversing the dot-escaping {@link fileNameFor}
31
+ * applies. Returns the exact stored content-type (decoded from the filename
32
+ * segment, more reliable than `mime.lookup` on the extension), falling back to
33
+ * the spec default `application/octet-stream` if unparseable.
34
+ * @param fileName {string} the basename of the resource file
35
+ * @returns {{ resourceId: string, contentType: string }}
36
+ */
37
+ export declare function parseResourceFileName(fileName: string): {
38
+ resourceId: string;
39
+ contentType: string;
40
+ };
41
+ //# sourceMappingURL=resourceFileName.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resourceFileName.d.ts","sourceRoot":"","sources":["../../src/lib/resourceFileName.ts"],"names":[],"mappings":"AASA;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,EAC1B,UAAU,EACV,WAAW,EACZ,EAAE;IACD,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;CACpB,GAAG,MAAM,CAKT;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG;IACvD,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;CACpB,CAQA"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * On-disk resource-filename codec: the single shared home for encoding a
3
+ * Resource's representation file name (`r.<resourceId>.<encodedContentType>.<ext>`)
4
+ * and decoding it back. Kept low-level (no imports from `src/backends/` or
5
+ * `importTar.ts`) so both the filesystem backend and the tar importer can depend
6
+ * on it without an import cycle.
7
+ */
8
+ import * as mime from 'mime-types';
9
+ /**
10
+ * Percent-encodes a filename segment so it carries no literal `.`, the
11
+ * structural delimiter of `r.<resourceId>.<encodedContentType>.<ext>`.
12
+ * `encodeURIComponent` leaves `.` unescaped, so escape it explicitly to `%2E`;
13
+ * `decodeURIComponent` reverses both. This keeps resource ids and content-types
14
+ * that legitimately contain dots (e.g. `index.html`, `application/vnd.api+json`)
15
+ * unambiguously parseable -- without it, a dotted id mis-splits and is read back
16
+ * under the wrong id and content-type. For dot-free segments (the common case)
17
+ * the result is byte-identical to the previous `encodeURIComponent`-only scheme.
18
+ * @param segment {string}
19
+ * @returns {string}
20
+ */
21
+ export function encodeFilenameSegment(segment) {
22
+ return encodeURIComponent(segment).replace(/\./g, '%2E');
23
+ }
24
+ /**
25
+ * Builds the on-disk filename for a resource representation:
26
+ * `r.<resourceId>.<encodedContentType>.<ext>`. Both the `resourceId` and
27
+ * content-type segments are dot-escaped (see {@link encodeFilenameSegment}) so
28
+ * the three `.` separators are the only literal dots.
29
+ * @param options {object}
30
+ * @param options.resourceId {string}
31
+ * @param options.contentType {string}
32
+ * @returns {string}
33
+ */
34
+ export function fileNameFor({ resourceId, contentType }) {
35
+ const encodedId = encodeFilenameSegment(resourceId);
36
+ const encodedType = encodeFilenameSegment(contentType);
37
+ const extension = mime.extension(contentType) || 'blob';
38
+ return `r.${encodedId}.${encodedType}.${extension}`;
39
+ }
40
+ /**
41
+ * Parses an on-disk resource filename (`r.<resourceId>.<encodedContentType>.<ext>`)
42
+ * back into its components, reversing the dot-escaping {@link fileNameFor}
43
+ * applies. Returns the exact stored content-type (decoded from the filename
44
+ * segment, more reliable than `mime.lookup` on the extension), falling back to
45
+ * the spec default `application/octet-stream` if unparseable.
46
+ * @param fileName {string} the basename of the resource file
47
+ * @returns {{ resourceId: string, contentType: string }}
48
+ */
49
+ export function parseResourceFileName(fileName) {
50
+ const [, encodedId, encodedType] = fileName.split('.');
51
+ return {
52
+ resourceId: encodedId ? decodeURIComponent(encodedId) : '',
53
+ contentType: encodedType
54
+ ? decodeURIComponent(encodedType)
55
+ : 'application/octet-stream'
56
+ };
57
+ }
58
+ //# sourceMappingURL=resourceFileName.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resourceFileName.js","sourceRoot":"","sources":["../../src/lib/resourceFileName.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,IAAI,MAAM,YAAY,CAAA;AAElC;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAAe;IACnD,OAAO,kBAAkB,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;AAC1D,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,WAAW,CAAC,EAC1B,UAAU,EACV,WAAW,EAIZ;IACC,MAAM,SAAS,GAAG,qBAAqB,CAAC,UAAU,CAAC,CAAA;IACnD,MAAM,WAAW,GAAG,qBAAqB,CAAC,WAAW,CAAC,CAAA;IACtD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,MAAM,CAAA;IACvD,OAAO,KAAK,SAAS,IAAI,WAAW,IAAI,SAAS,EAAE,CAAA;AACrD,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,qBAAqB,CAAC,QAAgB;IAIpD,MAAM,CAAC,EAAE,SAAS,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IACtD,OAAO;QACL,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE;QAC1D,WAAW,EAAE,WAAW;YACtB,CAAC,CAAC,kBAAkB,CAAC,WAAW,CAAC;YACjC,CAAC,CAAC,0BAA0B;KAC/B,CAAA;AACH,CAAC"}
@@ -0,0 +1,49 @@
1
+ import type { CapabilityChainDetails, InspectCapabilityChain } from '@interop/zcap';
2
+ import type { CapabilitySummary, RevocationScope, StorageBackend } from '../types.js';
3
+ /**
4
+ * The file name a revocation record is stored (and archived) under:
5
+ * the `(delegator, capabilityId)` unique key folded into a SHA-256 digest,
6
+ * plus `.json`. Both parts are arbitrary-length URIs, so hashing (rather than
7
+ * encoding) keeps the name fixed-width and filesystem-safe. Shared by the
8
+ * filesystem store and both backends' `exportSpace`, so the same record
9
+ * always lands under the same name.
10
+ * @param options {object}
11
+ * @param options.delegator {string} the revoked capability's delegator
12
+ * @param options.capabilityId {string} the revoked capability's id
13
+ * @returns {string}
14
+ */
15
+ export declare function revocationFileName({ delegator, capabilityId }: {
16
+ delegator: string;
17
+ capabilityId: string;
18
+ }): string;
19
+ /**
20
+ * Extracts the `(capabilityId, delegator)` lookup pairs from a verified,
21
+ * dereferenced capability chain. The root capability is skipped -- root zcaps
22
+ * cannot be revoked -- and so is any link whose verify result carries no
23
+ * delegator (nothing to key a revocation record on).
24
+ *
25
+ * @param options {object}
26
+ * @param options.capabilityChain {object[]} the dereferenced chain (root to
27
+ * tail)
28
+ * @param options.capabilityChainMeta {object[]} the per-capability verify
29
+ * results (the root's entry has a `null` `verifyResult`)
30
+ * @returns {CapabilitySummary[]}
31
+ */
32
+ export declare function capabilitySummaries({ capabilityChain, capabilityChainMeta }: CapabilityChainDetails): CapabilitySummary[];
33
+ /**
34
+ * Builds the `inspectCapabilityChain` hook for one scope: valid when no
35
+ * delegated capability in the chain has a stored revocation under that
36
+ * keystore or Space (a chain of just the root has nothing to check, so a bare
37
+ * root invocation never reaches the store).
38
+ *
39
+ * @param options {object}
40
+ * @param options.storage {StorageBackend} supplies the revocation store
41
+ * @param options.scope {RevocationScope} the keystore or Space the lookup is
42
+ * keyed on
43
+ * @returns {InspectCapabilityChain}
44
+ */
45
+ export declare function revocationChainInspector({ storage, scope }: {
46
+ storage: StorageBackend;
47
+ scope: RevocationScope;
48
+ }): InspectCapabilityChain;
49
+ //# sourceMappingURL=revocations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"revocations.d.ts","sourceRoot":"","sources":["../../src/lib/revocations.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EACV,sBAAsB,EACtB,sBAAsB,EACvB,MAAM,eAAe,CAAA;AACtB,OAAO,KAAK,EACV,iBAAiB,EACjB,eAAe,EACf,cAAc,EACf,MAAM,aAAa,CAAA;AAEpB;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,SAAS,EACT,YAAY,EACb,EAAE;IACD,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY,EAAE,MAAM,CAAA;CACrB,GAAG,MAAM,CAKT;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,eAAe,EACf,mBAAmB,EACpB,EAAE,sBAAsB,GAAG,iBAAiB,EAAE,CAgB9C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CAAC,EACvC,OAAO,EACP,KAAK,EACN,EAAE;IACD,OAAO,EAAE,cAAc,CAAA;IACvB,KAAK,EAAE,eAAe,CAAA;CACvB,GAAG,sBAAsB,CAiBzB"}