@coffre/vault 0.1.15 → 0.1.17
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/dist/cloudflare.js +1 -1
- package/dist/node.js +1 -1
- package/dist/{vault-BmEa1SIQ.js → vault-BexBMpZL.js} +16 -4
- package/package.json +3 -3
- package/src/vault.ts +13 -3
package/dist/cloudflare.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as verifyCheckpoint, i as checkpointMessage, n as KekUnavailableError, o as derivedSigningKey, r as awsKms, s as resolveVaultConfig, t as KekBadClaimError } from "./src-1yVV2L0_.js";
|
|
2
|
-
import { n as prepareVault, t as openVault } from "./vault-
|
|
2
|
+
import { n as prepareVault, t as openVault } from "./vault-BexBMpZL.js";
|
|
3
3
|
import { createDatabase } from "@coffre/db";
|
|
4
4
|
import { HyperdrivePool, postgres } from "@coffre/db/hyperdrive";
|
|
5
5
|
import { WorkerEntrypoint } from "cloudflare:workers";
|
package/dist/node.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as verifyCheckpoint, i as checkpointMessage, n as KekUnavailableError, o as derivedSigningKey, r as awsKms, s as resolveVaultConfig, t as KekBadClaimError } from "./src-1yVV2L0_.js";
|
|
2
|
-
import { n as prepareVault, t as openVault } from "./vault-
|
|
2
|
+
import { n as prepareVault, t as openVault } from "./vault-BexBMpZL.js";
|
|
3
3
|
import { chmodSync, existsSync, lstatSync, rmSync } from "node:fs";
|
|
4
4
|
import { Agent, createServer, request } from "node:http";
|
|
5
5
|
import { openDatabase } from "@coffre/db/connect";
|
|
@@ -914,6 +914,10 @@ const MESSAGES = {
|
|
|
914
914
|
wrong_kek: "this vault's key does not open the data it holds",
|
|
915
915
|
tampered: "this member's record failed the vault's integrity check"
|
|
916
916
|
};
|
|
917
|
+
/** The credential a CI run's request came in on, as its entries record it: copied, never decided on. */
|
|
918
|
+
function traced(correlation) {
|
|
919
|
+
return correlation.credentialId == null ? {} : { credentialId: correlation.credentialId };
|
|
920
|
+
}
|
|
917
921
|
/**
|
|
918
922
|
* The one implementation of `Vault`. Every decision is one transaction on
|
|
919
923
|
* the shared database: it locks the rows of the members it is about, reads
|
|
@@ -1335,7 +1339,8 @@ var VaultService = class {
|
|
|
1335
1339
|
requestId: input.requestId,
|
|
1336
1340
|
metadata: JSON.stringify({
|
|
1337
1341
|
...detail,
|
|
1338
|
-
secretVersionId: id
|
|
1342
|
+
secretVersionId: id,
|
|
1343
|
+
...traced(input)
|
|
1339
1344
|
})
|
|
1340
1345
|
};
|
|
1341
1346
|
return {
|
|
@@ -1424,6 +1429,7 @@ var VaultService = class {
|
|
|
1424
1429
|
operation: action,
|
|
1425
1430
|
expiresAt: at + this.#prepared.options.keyBudgetMs + 2 * LOCK_TIMEOUT_MS,
|
|
1426
1431
|
...call.input.purpose === void 0 ? {} : { purpose: call.input.purpose },
|
|
1432
|
+
...traced(call.input),
|
|
1427
1433
|
keys: secrets.map((secret, item) => ({
|
|
1428
1434
|
item,
|
|
1429
1435
|
subject: secret.path,
|
|
@@ -2392,6 +2398,7 @@ const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
|
2392
2398
|
function validateCorrelation(input) {
|
|
2393
2399
|
if (input.requestId != null) validateText(input.requestId);
|
|
2394
2400
|
if (input.operationId != null && (typeof input.operationId !== "string" || !UUID.test(input.operationId))) throw new Error(`operationId must be a lowercase UUID, got: ${String(input.operationId)}`);
|
|
2401
|
+
if (input.credentialId != null && (typeof input.credentialId !== "string" || !UUID.test(input.credentialId))) throw new Error(`credentialId must be a lowercase UUID, got: ${String(input.credentialId)}`);
|
|
2395
2402
|
}
|
|
2396
2403
|
/** Validate the entire batch before any provider sees a key. */
|
|
2397
2404
|
function validateItems(items, field) {
|
|
@@ -2452,7 +2459,8 @@ function keyEntry(action, principal, secret, decision, code, correlation, detail
|
|
|
2452
2459
|
subject: secret.path,
|
|
2453
2460
|
...action === "key.wrap" ? { secretId: secret.secretId } : {},
|
|
2454
2461
|
version: secret.version,
|
|
2455
|
-
...detail
|
|
2462
|
+
...detail,
|
|
2463
|
+
...traced(correlation)
|
|
2456
2464
|
})
|
|
2457
2465
|
};
|
|
2458
2466
|
}
|
|
@@ -2470,9 +2478,13 @@ function accessEntry(actor, action, principal, decision, correlation, detail, co
|
|
|
2470
2478
|
subjectPrincipal: PRINCIPAL.test(principal) ? principal : null,
|
|
2471
2479
|
operationId: correlation.operationId ?? null,
|
|
2472
2480
|
requestId: correlation.requestId ?? null,
|
|
2473
|
-
metadata: JSON.stringify(PRINCIPAL.test(principal) ?
|
|
2481
|
+
metadata: JSON.stringify(PRINCIPAL.test(principal) ? {
|
|
2482
|
+
...detail,
|
|
2483
|
+
...traced(correlation)
|
|
2484
|
+
} : {
|
|
2474
2485
|
subject: principal,
|
|
2475
|
-
...detail
|
|
2486
|
+
...detail,
|
|
2487
|
+
...traced(correlation)
|
|
2476
2488
|
})
|
|
2477
2489
|
};
|
|
2478
2490
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coffre/vault",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.17",
|
|
4
4
|
"description": "coffre's vault: keys, grants and members, in the database the app uses, as a Cloudflare Worker or on Node.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -36,8 +36,8 @@
|
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"drizzle-orm": "0.45.2",
|
|
39
|
-
"@coffre/core": "0.1.
|
|
40
|
-
"@coffre/db": "0.1.
|
|
39
|
+
"@coffre/core": "0.1.17",
|
|
40
|
+
"@coffre/db": "0.1.17"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@types/node": "26.1.1",
|
package/src/vault.ts
CHANGED
|
@@ -265,7 +265,12 @@ type Decision = {
|
|
|
265
265
|
type KeyAction = 'secret.read' | 'key.wrap' | 'key.rewrap';
|
|
266
266
|
|
|
267
267
|
/** What ties an entry to the app's request, and to the one action it is part of. */
|
|
268
|
-
type Correlation = { requestId?: string | null; operationId?: string | null };
|
|
268
|
+
type Correlation = { requestId?: string | null; operationId?: string | null; credentialId?: string | null };
|
|
269
|
+
|
|
270
|
+
/** The credential a CI run's request came in on, as its entries record it: copied, never decided on. */
|
|
271
|
+
function traced(correlation: Correlation): { credentialId?: string } {
|
|
272
|
+
return correlation.credentialId == null ? {} : { credentialId: correlation.credentialId };
|
|
273
|
+
}
|
|
269
274
|
|
|
270
275
|
/** Why a member's row is not the one the vault last wrote; rows.ts. */
|
|
271
276
|
type Fault = 'mac' | 'stale';
|
|
@@ -714,7 +719,7 @@ class VaultService implements Vault {
|
|
|
714
719
|
if (version === undefined) return {
|
|
715
720
|
actor: input.principal, action, decision: 'deny', code: 'bad_claim',
|
|
716
721
|
operationId: input.operationId, requestId: input.requestId,
|
|
717
|
-
metadata: JSON.stringify({ ...detail, secretVersionId: id }),
|
|
722
|
+
metadata: JSON.stringify({ ...detail, secretVersionId: id, ...traced(input) }),
|
|
718
723
|
};
|
|
719
724
|
return { ...keyEntry(action, input.principal, version.secret, 'deny', 'bad_claim', input, detail), secretVersionId: id };
|
|
720
725
|
}));
|
|
@@ -824,6 +829,7 @@ class VaultService implements Vault {
|
|
|
824
829
|
// Member and outcome locks can each wait before accounting is overdue.
|
|
825
830
|
expiresAt: at + this.#prepared.options.keyBudgetMs + 2 * LOCK_TIMEOUT_MS,
|
|
826
831
|
...(call.input.purpose === undefined ? {} : { purpose: call.input.purpose }),
|
|
832
|
+
...traced(call.input),
|
|
827
833
|
keys: secrets.map((secret, item) => ({ item, subject: secret.path, secretId: secret.secretId, version: secret.version })),
|
|
828
834
|
}),
|
|
829
835
|
}]);
|
|
@@ -1712,6 +1718,9 @@ function validateCorrelation(input: Correlation): void {
|
|
|
1712
1718
|
if (input.operationId != null && (typeof input.operationId !== 'string' || !UUID.test(input.operationId))) {
|
|
1713
1719
|
throw new Error(`operationId must be a lowercase UUID, got: ${String(input.operationId)}`);
|
|
1714
1720
|
}
|
|
1721
|
+
if (input.credentialId != null && (typeof input.credentialId !== 'string' || !UUID.test(input.credentialId))) {
|
|
1722
|
+
throw new Error(`credentialId must be a lowercase UUID, got: ${String(input.credentialId)}`);
|
|
1723
|
+
}
|
|
1715
1724
|
}
|
|
1716
1725
|
|
|
1717
1726
|
/** Validate the entire batch before any provider sees a key. */
|
|
@@ -1780,6 +1789,7 @@ function keyEntry(
|
|
|
1780
1789
|
...(action === 'key.wrap' ? { secretId: secret.secretId } : {}),
|
|
1781
1790
|
version: secret.version,
|
|
1782
1791
|
...detail,
|
|
1792
|
+
...traced(correlation),
|
|
1783
1793
|
}),
|
|
1784
1794
|
};
|
|
1785
1795
|
}
|
|
@@ -1813,7 +1823,7 @@ function accessEntry(
|
|
|
1813
1823
|
subjectPrincipal: PRINCIPAL.test(principal) ? principal : null,
|
|
1814
1824
|
operationId: correlation.operationId ?? null,
|
|
1815
1825
|
requestId: correlation.requestId ?? null,
|
|
1816
|
-
metadata: JSON.stringify(PRINCIPAL.test(principal) ? detail : { subject: principal, ...detail }),
|
|
1826
|
+
metadata: JSON.stringify(PRINCIPAL.test(principal) ? { ...detail, ...traced(correlation) } : { subject: principal, ...detail, ...traced(correlation) }),
|
|
1817
1827
|
};
|
|
1818
1828
|
}
|
|
1819
1829
|
|