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/zcap.js ADDED
@@ -0,0 +1,478 @@
1
+ import { securityLoader } from '@interop/security-document-loader';
2
+ import { verifyCapabilityInvocation } from '@interop/http-signature-zcap-verify';
3
+ import jsigs from '@interop/jsonld-signatures';
4
+ import { CapabilityDelegation } from '@interop/zcap';
5
+ import { Ed25519VerificationKey } from '@interop/ed25519-verification-key';
6
+ import { Ed25519Signature2020 } from '@interop/ed25519-signature';
7
+ import * as didKey from '@interop/did-method-key';
8
+ import { AuthVerificationError, InvalidRevocationError, UnauthorizedError } from './errors.js';
9
+ import { capabilitySummaries, revocationChainInspector } from './lib/revocations.js';
10
+ const didKeyDriver = didKey.driver();
11
+ didKeyDriver.use({
12
+ multibaseMultikeyHeader: 'z6Mk',
13
+ fromMultibase: Ed25519VerificationKey.from
14
+ });
15
+ /**
16
+ * The root capability id convention: `urn:zcap:root:` + the url-encoded
17
+ * invocation target (shared by WAS and webkms).
18
+ * @param target {string} the root invocation target (full URL)
19
+ * @returns {string}
20
+ */
21
+ function rootCapabilityId(target) {
22
+ return `urn:zcap:root:${encodeURIComponent(target)}`;
23
+ }
24
+ /**
25
+ * Builds a document loader whose `urn` protocol handler synthesizes
26
+ * `urn:zcap:root:<target>` capabilities on demand, with the controller chosen
27
+ * per target. The zcap library only dereferences a root capability it already
28
+ * expects (per `expectedRootCapability`), so `controllerFor` sees expected
29
+ * targets only -- it may still throw to refuse one outright.
30
+ *
31
+ * @param options {object}
32
+ * @param options.controllerFor {(target: string) => IDID | string[]} maps a
33
+ * decoded root invocation target to the controller(s) of its synthesized
34
+ * root capability
35
+ * @returns {IDocumentLoader}
36
+ */
37
+ function rootCapabilityLoader({ controllerFor }) {
38
+ const loader = securityLoader();
39
+ loader.setProtocolHandler({
40
+ protocol: 'urn',
41
+ handler: {
42
+ get: async ({ id, url }) => {
43
+ const resolvedUrl = url || id;
44
+ const rootZcapTarget = decodeURIComponent(resolvedUrl.split('urn:zcap:root:')[1]);
45
+ return {
46
+ '@context': 'https://w3id.org/zcap/v1',
47
+ id: resolvedUrl,
48
+ invocationTarget: rootZcapTarget,
49
+ controller: controllerFor(rootZcapTarget)
50
+ };
51
+ }
52
+ }
53
+ });
54
+ return loader.build();
55
+ }
56
+ /**
57
+ * Resolves an invocation's keyId to an Ed25519 verifier (the
58
+ * `verifyCapabilityInvocation` HTTP-signature key hook).
59
+ * @param options {object}
60
+ * @param options.keyId {string} the did:key verification method URL
61
+ * @returns {Promise<{ verifier: object, verificationMethod: IVerificationMethod }>}
62
+ */
63
+ async function getVerifier({ keyId }) {
64
+ const verificationMethod = await didKeyDriver.get({ url: keyId });
65
+ const key = await Ed25519VerificationKey.from(verificationMethod);
66
+ const verifier = key.verifier();
67
+ return {
68
+ verifier,
69
+ verificationMethod: verificationMethod
70
+ };
71
+ }
72
+ /**
73
+ * Returns true when a `Capability-Invocation` header value is the bare root
74
+ * form (`zcap id="urn:zcap:root:..."` -- the signer invokes the root capability
75
+ * directly), false when it embeds a delegated capability
76
+ * (`zcap capability="<base64url(gzip(json))>"`). The check is safe on the raw
77
+ * header: a `capability=` substring cannot occur inside the root form's
78
+ * url-encoded `id` (where `=` is percent-encoded).
79
+ *
80
+ * @param options {object}
81
+ * @param options.invocation {string} the raw `Capability-Invocation` header
82
+ * @returns {boolean}
83
+ */
84
+ export function isRootInvocation({ invocation }) {
85
+ return !invocation.includes('capability=');
86
+ }
87
+ /**
88
+ * Verifies the capability-invocation signature on a request against the Space
89
+ * controller's key. Throws AuthVerificationError if verification itself errors,
90
+ * or UnauthorizedError if the capability does not verify.
91
+ *
92
+ * @param options {object}
93
+ * @param options.url {string} request URL (path), resolved against serverUrl
94
+ * @param options.allowedTarget {string} the capability's expected
95
+ * invocationTarget (full URL, including host and port)
96
+ * @param options.allowedAction {string} expected action, e.g. an HTTP verb
97
+ * @param options.method {string} the HTTP method of the request
98
+ * @param options.headers {IncomingHttpHeaders} the request headers (including
99
+ * `authorization`, `capability-invocation`, and `digest`)
100
+ * @param options.serverUrl {string} this server's base URL
101
+ * @param options.spaceController {IDID} the did:key that controls the Space
102
+ * @param [options.requestName] {string} human-readable request name, used in
103
+ * error titles
104
+ * @param [options.logger] {ZcapLogger} logger for verification errors;
105
+ * defaults to `console`
106
+ * @param [options.allowTargetQuery] {boolean} tolerate query parameters that
107
+ * extend `allowedTarget` on the request URL (see `verifyZcap`)
108
+ * @param [options.allowTargetAttenuation] {boolean} accept a request URL
109
+ * that path-extends `allowedTarget` under a capability rooted at
110
+ * `allowedTarget` (see `verifyZcap`)
111
+ * @param [options.attenuatedRootTarget] {string} an ancestor target (e.g.
112
+ * the Space URL) whose root capability is also accepted as the root of a
113
+ * delegated chain that attenuates down to the request URL (see `verifyZcap`)
114
+ * @param options.revocation {object|string} the revocation-store check, run
115
+ * against the dereferenced chain after signature verification. REQUIRED so
116
+ * that skipping revocation is a stated decision, never an omission: pass
117
+ * `{ storage, scope }` -- the scope (keystore or Space) the chain roots
118
+ * in -- or the literal `'no-revocation-scope'` when the verified target has
119
+ * no scope a revocation could be stored under (a create/consent
120
+ * verification for a not-yet-existing resource, or a collection-level root
121
+ * like `/kms/keystores`).
122
+ * @param [options.maxChainLength] {number} max delegation chain length,
123
+ * root included (see `verifyZcap`)
124
+ * @param [options.maxDelegationTtl] {number} max delegated-zcap TTL in
125
+ * milliseconds (see `verifyZcap`)
126
+ * @returns {Promise<VerifyCapabilityInvocationResult>} the successful
127
+ * verification result (callers needing the dereferenced chain, e.g. the
128
+ * per-key `maxCapabilityChainLength` gate, read it from here)
129
+ */
130
+ export async function handleZcapVerify({ url, allowedTarget, allowedAction, method, headers, serverUrl, spaceController, requestName = '', logger = console, allowTargetQuery = false, allowTargetAttenuation = false, attenuatedRootTarget, revocation, maxChainLength, maxDelegationTtl }) {
131
+ const inspectCapabilityChain = revocation === 'no-revocation-scope'
132
+ ? undefined
133
+ : revocationChainInspector(revocation);
134
+ let zcapVerifyResult;
135
+ try {
136
+ zcapVerifyResult = await verifyZcap({
137
+ url,
138
+ allowedTarget,
139
+ allowedAction,
140
+ method,
141
+ headers,
142
+ serverUrl,
143
+ spaceController,
144
+ allowTargetQuery,
145
+ allowTargetAttenuation,
146
+ attenuatedRootTarget,
147
+ inspectCapabilityChain,
148
+ maxChainLength,
149
+ maxDelegationTtl
150
+ });
151
+ }
152
+ catch (err) {
153
+ logger.error({ err }, 'ZCAP verification failed');
154
+ throw new AuthVerificationError({ requestName, cause: err });
155
+ }
156
+ if (!zcapVerifyResult.verified) {
157
+ throw new UnauthorizedError({ requestName });
158
+ }
159
+ return zcapVerifyResult;
160
+ }
161
+ /**
162
+ * Performs the underlying capability-invocation verification: builds a document
163
+ * loader whose `urn` protocol handler synthesizes the root capability on demand
164
+ * (its controller is the Space controller), then calls
165
+ * verifyCapabilityInvocation().
166
+ *
167
+ * @param options {object}
168
+ * @param options.url {string} request URL (path), resolved against serverUrl
169
+ * @param options.allowedTarget {string} expected invocationTarget (full URL)
170
+ * @param options.allowedAction {string} expected action, e.g. an HTTP verb
171
+ * @param options.method {string} the HTTP method of the request
172
+ * @param options.headers {IncomingHttpHeaders} the request headers
173
+ * @param options.serverUrl {string} this server's base URL
174
+ * @param options.spaceController {IDID} the did:key that controls the Space
175
+ * @param [options.allowTargetQuery] {boolean} when set, accept a request URL
176
+ * that adds query parameters to `allowedTarget` (e.g. List Collection's
177
+ * `?limit`/`cursor`) as authorized by a capability for the bare target. The
178
+ * spec requires that pagination parameters select a page within an
179
+ * already-authorized target without changing the target a capability must
180
+ * match. The zcap library otherwise requires the capability's
181
+ * `invocationTarget` to equal the full request URL exactly, so this enables
182
+ * target attenuation (the library treats a `?`-query suffix as a valid RESTful
183
+ * attenuation) and admits both the bare-target root capability (a delegate
184
+ * following `next`) and the query-bearing one (a controller invoking the URL
185
+ * directly). The actual gate -- the bare-target root capability -- is
186
+ * unchanged. (TODO: the `/quotas` endpoint should adopt this too, so its
187
+ * per-Collection breakdown can return to the spec's `?include=collections`
188
+ * opt-in.)
189
+ * @param [options.allowTargetAttenuation] {boolean} when set, accept a
190
+ * request URL that *path*-extends `allowedTarget` (e.g. a WebKMS key
191
+ * operation posted to `<keystoreId>/keys/<keyId>` under a capability rooted
192
+ * at the keystore). The root capability is `allowedTarget`'s alone -- unlike
193
+ * `allowTargetQuery`, the extended URL is never itself an acceptable root --
194
+ * so both a root invocation by the controller and a delegated zcap whose
195
+ * `invocationTarget` narrows down to the request URL verify against the
196
+ * `allowedTarget` root (the webkms authorization model, which roots the
197
+ * invocation target at the keystore id).
198
+ * @param [options.attenuatedRootTarget] {string} when set, an *ancestor*
199
+ * invocation target (the Space URL for the WAS route families) whose root
200
+ * capability is accepted -- in addition to `allowedTarget`'s own -- as the
201
+ * root of the invocation. This is what lets a controller delegate one
202
+ * capability for a whole Space (or a Collection under it, by attenuating
203
+ * the `invocationTarget` down at delegation time) and have the delegate
204
+ * invoke it against any URL underneath: the chain roots at the ancestor's
205
+ * root capability and narrows toward the request URL (RESTful attenuation,
206
+ * the same shape `allowTargetAttenuation` gives the WebKMS keystore).
207
+ * Root invocations of `allowedTarget`'s own root capability verify
208
+ * unchanged, so this only widens what the Space controller can delegate,
209
+ * never who can access.
210
+ * @param [options.inspectCapabilityChain] {InspectCapabilityChain} hook run
211
+ * against the dereferenced chain after signature verification -- the
212
+ * revocation-check extension point (a stored revocation of any capability
213
+ * in the chain fails the verification). Both route families pass one, scoped
214
+ * to the keystore or the Space the request roots in.
215
+ * @param [options.maxChainLength] {number} max delegation chain length,
216
+ * root included (the `/kms` families pass `KMS_MAX_CHAIN_LENGTH`; absent,
217
+ * the zcap library's own default applies)
218
+ * @param [options.maxDelegationTtl] {number} max delegated-zcap TTL in
219
+ * milliseconds, measured `expires` minus the delegation proof's `created`
220
+ * (the `/kms` families pass `KMS_MAX_DELEGATION_TTL`; absent, unbounded)
221
+ * @returns {Promise<VerifyCapabilityInvocationResult>}
222
+ */
223
+ export async function verifyZcap({ url, allowedTarget, allowedAction, method, headers, serverUrl, spaceController, allowTargetQuery = false, allowTargetAttenuation = false, attenuatedRootTarget, inspectCapabilityChain, maxChainLength, maxDelegationTtl }) {
224
+ const fullRequestUrl = new URL(url, serverUrl).toString();
225
+ let expected;
226
+ if (allowTargetQuery || attenuatedRootTarget) {
227
+ // The acceptable roots: the ancestor's root capability (a delegated chain
228
+ // rooted at e.g. the Space URL, narrowing to the request URL), the
229
+ // `allowedTarget`'s own (a root invocation, or a delegated chain for the
230
+ // exact target -- the pre-existing shapes, unchanged), and, under
231
+ // `allowTargetQuery`, the query-bearing request URL's own (a controller
232
+ // invoking the query URL directly).
233
+ const rootTargets = [
234
+ ...(attenuatedRootTarget ? [attenuatedRootTarget] : []),
235
+ allowedTarget,
236
+ ...(allowTargetQuery ? [fullRequestUrl] : [])
237
+ ];
238
+ expected = {
239
+ expectedAction: allowedAction,
240
+ expectedHost: new URL(serverUrl).host,
241
+ expectedRootCapability: [...new Set(rootTargets.map(rootCapabilityId))],
242
+ // The proof's invocationTarget is the invoked URL: `allowedTarget`
243
+ // itself, or (under `allowTargetQuery`) the query-bearing request URL.
244
+ // The array form is narrowed to `string` by the verify fork's option
245
+ // type, but the underlying `@interop/zcap` CapabilityInvocation
246
+ // accepts `string | string[]` -- hence the cast.
247
+ expectedTarget: [
248
+ ...new Set([allowedTarget, fullRequestUrl])
249
+ ],
250
+ allowTargetAttenuation: true
251
+ };
252
+ }
253
+ else if (allowTargetAttenuation) {
254
+ expected = {
255
+ expectedAction: allowedAction,
256
+ expectedHost: new URL(serverUrl).host,
257
+ // The proof's invocationTarget is the invoked URL: `allowedTarget`
258
+ // itself, or a path under it (accepted as a RESTful attenuation).
259
+ // The only acceptable root capability is `allowedTarget`'s. (Same
260
+ // array-form cast as above.)
261
+ expectedRootCapability: rootCapabilityId(allowedTarget),
262
+ expectedTarget: [
263
+ ...new Set([allowedTarget, fullRequestUrl])
264
+ ],
265
+ allowTargetAttenuation: true
266
+ };
267
+ }
268
+ else {
269
+ expected = {
270
+ expectedAction: allowedAction,
271
+ expectedHost: new URL(serverUrl).host,
272
+ rootInvocationTarget: allowedTarget,
273
+ expectedRootCapability: rootCapabilityId(allowedTarget),
274
+ expectedTarget: allowedTarget
275
+ };
276
+ }
277
+ const documentLoader = rootCapabilityLoader({
278
+ controllerFor: () => spaceController
279
+ });
280
+ // Returns the following object:
281
+ // {
282
+ // capability, capabilityAction, controller,
283
+ // dereferencedChain,
284
+ // invoker: controller,
285
+ // verificationMethod,
286
+ // verified: true
287
+ // }
288
+ return await verifyCapabilityInvocation({
289
+ url: fullRequestUrl,
290
+ method,
291
+ headers: headers,
292
+ ...expected,
293
+ documentLoader,
294
+ getVerifier,
295
+ inspectCapabilityChain,
296
+ maxChainLength,
297
+ maxDelegationTtl,
298
+ suite: new Ed25519Signature2020()
299
+ });
300
+ }
301
+ /**
302
+ * Extracts the controller DIDs of one capability (`controller` may be a
303
+ * single value or an array on a synthesized root).
304
+ * @param capability {object} a capability from a dereferenced chain
305
+ * @returns {string[]}
306
+ */
307
+ function capabilityControllers(capability) {
308
+ const { controller } = capability;
309
+ if (controller === undefined) {
310
+ return [];
311
+ }
312
+ return Array.isArray(controller) ? controller : [controller];
313
+ }
314
+ /**
315
+ * Verifies the delegation chain of a capability submitted for revocation
316
+ * (`CapabilityDelegation` proof purpose over the embedded chain), throwing
317
+ * `InvalidRevocationError` (400) when it does not verify. The chain must root
318
+ * in the revocation's scope: its root capability's invocation target must be
319
+ * `rootTarget` -- the keystore URL, or the Space URL for a WAS-route
320
+ * revocation -- or a path under it (enforced where the root is synthesized,
321
+ * so a chain aimed at another keystore or Space -- or another service --
322
+ * cannot be submitted here, per ezcap-express `authorizeZcapRevocation`).
323
+ * Deliberately structural only -- it does NOT consult the revocation store:
324
+ * this runs before the invocation is authorized, and a store-dependent
325
+ * failure here would disclose revocation state to unauthorized callers
326
+ * (400 already-revoked vs the masked 404). The caller checks the returned
327
+ * `capabilities` against the store after authorization.
328
+ *
329
+ * @param options {object}
330
+ * @param options.capability {object} the delegated capability to be revoked
331
+ * (the request body, verbatim)
332
+ * @param options.rootTarget {string} the scope's full URL -- the keystore or
333
+ * the Space -- which the chain is required to root in
334
+ * @param options.rootController {IDID} the scope's controller (controller of
335
+ * the synthesized root capability)
336
+ * @param [options.maxChainLength] {number} max chain length, root included
337
+ * @param [options.maxDelegationTtl] {number} max delegated-zcap TTL (ms)
338
+ * @returns {Promise<{ delegator: string, chainControllers: string[],
339
+ * capabilities: CapabilitySummary[] }>} the capability's delegator (its
340
+ * delegation proof's controller), every controller in its chain (the
341
+ * parties allowed to submit the revocation), and the chain's
342
+ * `(capabilityId, delegator)` pairs for the caller's post-authorization
343
+ * revocation-store check
344
+ */
345
+ export async function verifyRevocationChain({ capability, rootTarget, rootController, maxChainLength, maxDelegationTtl }) {
346
+ const chainControllers = [];
347
+ let capabilities = [];
348
+ const documentLoader = rootCapabilityLoader({
349
+ controllerFor: target => {
350
+ if (target !== rootTarget && !target.startsWith(`${rootTarget}/`)) {
351
+ throw new Error(`The root capability from the revocation's delegation chain must` +
352
+ ` have an invocation target that starts with "${rootTarget}".`);
353
+ }
354
+ return rootController;
355
+ }
356
+ });
357
+ const suite = new Ed25519Signature2020();
358
+ const result = (await jsigs.verify(capability, {
359
+ documentLoader,
360
+ suite,
361
+ purpose: new CapabilityDelegation({
362
+ suite,
363
+ expectedRootCapability: rootCapabilityId(rootTarget),
364
+ // Attenuation is always tolerated when judging revocability: a zcap
365
+ // delegated with attenuation rules an invocation endpoint would refuse
366
+ // can still be revoked (ezcap-express `_verifyDelegation`).
367
+ allowTargetAttenuation: true,
368
+ maxChainLength,
369
+ maxDelegationTtl,
370
+ inspectCapabilityChain: async (details) => {
371
+ // Capture every controller in the dereferenced chain -- these are the
372
+ // parties the dual-root rule lets submit this revocation -- and the
373
+ // chain's lookup pairs for the caller's post-authorization store check.
374
+ for (const chainCapability of details.capabilityChain) {
375
+ chainControllers.push(...capabilityControllers(chainCapability));
376
+ }
377
+ capabilities = capabilitySummaries(details);
378
+ return { valid: true };
379
+ }
380
+ })
381
+ }));
382
+ if (!result.verified) {
383
+ throw new InvalidRevocationError({
384
+ detail: 'The provided capability delegation is invalid.',
385
+ cause: result.error
386
+ });
387
+ }
388
+ const rawDelegator = result.results?.[0]?.purposeResult?.delegator;
389
+ const delegator = typeof rawDelegator === 'string' ? rawDelegator : rawDelegator?.id;
390
+ if (!delegator) {
391
+ throw new InvalidRevocationError({
392
+ detail: 'The capability delegation has no identifiable delegator.'
393
+ });
394
+ }
395
+ return { delegator, chainControllers, capabilities };
396
+ }
397
+ /**
398
+ * Verifies the capability invocation on a revocation submission under the
399
+ * dual-root rule: the invocation may root in the scope -- the keystore or the
400
+ * Space -- (whose controller may revoke anything delegated from it, delegates
401
+ * of a revocation capability included, via target attenuation), or in the
402
+ * revocation URL itself, whose
403
+ * synthesized root capability is controlled by *every controller in the
404
+ * to-be-revoked capability's chain* -- so a delegee can revoke its own zcap
405
+ * without holding a separate capability (ezcap-express
406
+ * `authorizeZcapRevocation`). Throws like `handleZcapVerify`:
407
+ * `AuthVerificationError` (400) when verification errors, the 404-masked
408
+ * `UnauthorizedError` when the invocation does not verify.
409
+ *
410
+ * @param options {object}
411
+ * @param options.url {string} request URL (path), resolved against serverUrl
412
+ * @param options.method {string} the HTTP method of the request
413
+ * @param options.headers {IncomingHttpHeaders} the request headers
414
+ * @param options.serverUrl {string} this server's base URL
415
+ * @param options.rootTarget {string} the scope's full URL (the keystore or
416
+ * the Space)
417
+ * @param options.rootController {IDID} the scope's controller
418
+ * @param options.chainControllers {string[]} every controller in the
419
+ * to-be-revoked capability's (already verified) chain
420
+ * @param options.expectedAction {string} the action the invocation must
421
+ * carry: the webkms `write` on `/kms`, the HTTP verb (`POST`) on the WAS
422
+ * route families, whose capabilities are scoped by HTTP method
423
+ * @param [options.inspectCapabilityChain] {InspectCapabilityChain} the
424
+ * revocation-store hook, run against the *invoking* chain
425
+ * @param [options.maxChainLength] {number} max chain length, root included
426
+ * @param [options.maxDelegationTtl] {number} max delegated-zcap TTL (ms)
427
+ * @param [options.requestName] {string} request name used in error titles
428
+ * @param [options.logger] {ZcapLogger} logger for verification errors
429
+ * @returns {Promise<void>}
430
+ */
431
+ export async function handleRevocationInvocationVerify({ url, method, headers, serverUrl, rootTarget, rootController, chainControllers, expectedAction, inspectCapabilityChain, maxChainLength, maxDelegationTtl, requestName = '', logger = console }) {
432
+ const fullRequestUrl = new URL(url, serverUrl).toString();
433
+ const documentLoader = rootCapabilityLoader({
434
+ controllerFor: target => {
435
+ if (target === rootTarget) {
436
+ return rootController;
437
+ }
438
+ if (target === fullRequestUrl) {
439
+ return chainControllers;
440
+ }
441
+ throw new Error(`Unexpected root capability target "${target}" on a revocation.`);
442
+ }
443
+ });
444
+ let zcapVerifyResult;
445
+ try {
446
+ zcapVerifyResult = await verifyCapabilityInvocation({
447
+ url: fullRequestUrl,
448
+ method,
449
+ headers: headers,
450
+ expectedAction,
451
+ expectedHost: new URL(serverUrl).host,
452
+ expectedRootCapability: [
453
+ rootCapabilityId(rootTarget),
454
+ rootCapabilityId(fullRequestUrl)
455
+ ],
456
+ // The invoked target is the revocation URL, a path under the scope's
457
+ // root; accept either as a delegated zcap's (attenuated) target. The
458
+ // array form is narrowed to `string` by the verify fork's option type
459
+ // (see the same cast in `verifyZcap`'s attenuation branch).
460
+ expectedTarget: [rootTarget, fullRequestUrl],
461
+ allowTargetAttenuation: true,
462
+ documentLoader,
463
+ getVerifier,
464
+ inspectCapabilityChain,
465
+ maxChainLength,
466
+ maxDelegationTtl,
467
+ suite: new Ed25519Signature2020()
468
+ });
469
+ }
470
+ catch (err) {
471
+ logger.error({ err }, 'ZCAP revocation invocation verification failed');
472
+ throw new AuthVerificationError({ requestName, cause: err });
473
+ }
474
+ if (!zcapVerifyResult.verified) {
475
+ throw new UnauthorizedError({ requestName });
476
+ }
477
+ }
478
+ //# sourceMappingURL=zcap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zcap.js","sourceRoot":"","sources":["../src/zcap.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,109 @@
1
+ {
2
+ "name": "was-teaching-server",
3
+ "description": "A basic Wallet Attached Storage server used to demonstrate the WAS specification.",
4
+ "version": "0.9.1",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js"
11
+ },
12
+ "./package.json": "./package.json"
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "common",
17
+ "src",
18
+ "CHANGELOG.md"
19
+ ],
20
+ "scripts": {
21
+ "dev": "tsx watch src/start.js",
22
+ "start": "node dist/start.js | pino-pretty",
23
+ "build": "pnpm run clear && tsc && pnpm run copy-assets",
24
+ "clear": "rimraf dist/*",
25
+ "copy-assets": "node -e \"require('node:fs').cpSync('src/views','dist/views',{recursive:true})\"",
26
+ "rebuild": "pnpm run clear && pnpm run build",
27
+ "lint": "eslint src test conformance",
28
+ "lint:tests": "tsc -p tsconfig.dev.json",
29
+ "fix": "eslint --fix src test conformance && pnpm run format",
30
+ "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\" \"conformance/**/*.ts\" \"*.md\"",
31
+ "test-node": "vitest run",
32
+ "test:pg": "WAS_TEST_DATABASE_URL=postgres://was:was@localhost:5433/was vitest run",
33
+ "test:coverage": "vitest run --coverage",
34
+ "test": "pnpm run fix && pnpm run lint && pnpm run lint:tests && pnpm run build && pnpm run test-node",
35
+ "conformance": "tsx --test conformance/*.test.ts",
36
+ "conformance:local": "tsx scripts/conformance-local.ts",
37
+ "reencrypt-kms-records": "tsx scripts/reencrypt-kms-records.ts"
38
+ },
39
+ "dependencies": {
40
+ "@digitalcredentials/bnid": "^5.0.0",
41
+ "@fastify/cors": "^11.2.0",
42
+ "@fastify/multipart": "^10.0.0",
43
+ "@fastify/static": "^9.1.3",
44
+ "@fastify/view": "^12.0.0",
45
+ "@interop/data-integrity-core": "^8.2.0",
46
+ "@interop/did-method-key": "^7.3.3",
47
+ "@interop/ed25519-signature": "^7.1.3",
48
+ "@interop/ed25519-verification-key": "^8.0.2",
49
+ "@interop/http-digest-header": "^3.0.0",
50
+ "@interop/http-signature-header": "^5.0.2",
51
+ "@interop/http-signature-zcap-verify": "^12.1.1",
52
+ "@interop/jsonld-signatures": "^11.8.2",
53
+ "@interop/lru-memoize": "^4.0.3",
54
+ "@interop/security-document-loader": "^9.4.1",
55
+ "@interop/storage-core": "^0.3.4",
56
+ "@interop/x25519-key-agreement-key": "^5.2.0",
57
+ "@interop/zcap": "^11.0.4",
58
+ "fastify": "^5.8.5",
59
+ "fastify-plugin": "^6.0.0",
60
+ "fs-json-store": "^8.0.1",
61
+ "handlebars": "^4.7.9",
62
+ "mime-types": "^3.0.2",
63
+ "pg": "^8.22.0",
64
+ "pino": "^10.3.1",
65
+ "pino-pretty": "^13.1.3",
66
+ "tar-stream": "^3.2.0",
67
+ "undici": "7.28.0",
68
+ "uuid": "^14.0.0",
69
+ "yaml": "^2.9.0"
70
+ },
71
+ "devDependencies": {
72
+ "@eslint/js": "^10.0.1",
73
+ "@interop/ezcap": "^7.3.2",
74
+ "@interop/http-signature-zcap-invoke": "^6.2.3",
75
+ "@interop/was-client": "^0.14.2",
76
+ "@interop/webkms-client": "^14.7.1",
77
+ "@types/mime-types": "3.0.1",
78
+ "@types/node": "^24.0.0",
79
+ "@types/pg": "^8.20.0",
80
+ "@types/tar-stream": "3.1.4",
81
+ "@vitest/coverage-v8": "^4.1.7",
82
+ "eslint": "^10.4.0",
83
+ "eslint-config-prettier": "^10.1.8",
84
+ "globals": "^17.6.0",
85
+ "prettier": "^3.8.3",
86
+ "rimraf": "^6.1.3",
87
+ "tsx": "^4.20.3",
88
+ "typescript": "^5.9.3",
89
+ "typescript-eslint": "^8.59.4",
90
+ "vitest": "^4.1.7"
91
+ },
92
+ "type": "module",
93
+ "bin": {},
94
+ "packageManager": "pnpm@11.5.0",
95
+ "engines": {
96
+ "node": ">=24.0"
97
+ },
98
+ "author": {
99
+ "name": "Dmitri Zagidulin",
100
+ "url": "https://github.com/dmitrizagidulin/"
101
+ },
102
+ "license": "AGPL-3.0-or-later",
103
+ "repository": {
104
+ "type": "git",
105
+ "url": "https://github.com/interop-alliance/was-teaching-server"
106
+ },
107
+ "homepage": "https://github.com/interop-alliance/was-teaching-server",
108
+ "bugs": "https://github.com/interop-alliance/was-teaching-server/issues"
109
+ }