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