usertrust 1.0.0 → 1.0.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/dist/cli/init.d.ts +2 -0
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +231 -37
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/main.d.ts +1 -1
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +18 -3
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/pricing.d.ts +5 -0
- package/dist/cli/pricing.d.ts.map +1 -0
- package/dist/cli/pricing.js +61 -0
- package/dist/cli/pricing.js.map +1 -0
- package/dist/cli/validate-key.d.ts +17 -0
- package/dist/cli/validate-key.d.ts.map +1 -0
- package/dist/cli/validate-key.js +58 -0
- package/dist/cli/validate-key.js.map +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +31 -0
- package/dist/config.js.map +1 -1
- package/dist/govern.d.ts +3 -1
- package/dist/govern.d.ts.map +1 -1
- package/dist/govern.js +415 -47
- package/dist/govern.js.map +1 -1
- package/dist/headless.d.ts +77 -0
- package/dist/headless.d.ts.map +1 -0
- package/dist/headless.js +566 -0
- package/dist/headless.js.map +1 -0
- package/dist/index.d.ts +12 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -1
- package/dist/index.js.map +1 -1
- package/dist/ledger/pricing.d.ts +6 -2
- package/dist/ledger/pricing.d.ts.map +1 -1
- package/dist/ledger/pricing.js +31 -3
- package/dist/ledger/pricing.js.map +1 -1
- package/dist/policy/canary.d.ts +17 -0
- package/dist/policy/canary.d.ts.map +1 -0
- package/dist/policy/canary.js +44 -0
- package/dist/policy/canary.js.map +1 -0
- package/dist/policy/injection.d.ts +24 -0
- package/dist/policy/injection.d.ts.map +1 -0
- package/dist/policy/injection.js +178 -0
- package/dist/policy/injection.js.map +1 -0
- package/dist/policy/pii.d.ts +13 -1
- package/dist/policy/pii.d.ts.map +1 -1
- package/dist/policy/pii.js +88 -0
- package/dist/policy/pii.js.map +1 -1
- package/dist/shared/errors.d.ts +20 -0
- package/dist/shared/errors.d.ts.map +1 -1
- package/dist/shared/errors.js +46 -0
- package/dist/shared/errors.js.map +1 -1
- package/dist/shared/types.d.ts +264 -0
- package/dist/shared/types.d.ts.map +1 -1
- package/dist/shared/types.js +67 -0
- package/dist/shared/types.js.map +1 -1
- package/dist/supply-chain/manifest.d.ts +22 -0
- package/dist/supply-chain/manifest.d.ts.map +1 -0
- package/dist/supply-chain/manifest.js +46 -0
- package/dist/supply-chain/manifest.js.map +1 -0
- package/dist/supply-chain/permissions.d.ts +12 -0
- package/dist/supply-chain/permissions.d.ts.map +1 -0
- package/dist/supply-chain/permissions.js +89 -0
- package/dist/supply-chain/permissions.js.map +1 -0
- package/dist/supply-chain/sign.d.ts +17 -0
- package/dist/supply-chain/sign.d.ts.map +1 -0
- package/dist/supply-chain/sign.js +95 -0
- package/dist/supply-chain/sign.js.map +1 -0
- package/dist/vault/derive.d.ts +13 -0
- package/dist/vault/derive.d.ts.map +1 -0
- package/dist/vault/derive.js +32 -0
- package/dist/vault/derive.js.map +1 -0
- package/dist/vault/scope.d.ts +20 -0
- package/dist/vault/scope.d.ts.map +1 -0
- package/dist/vault/scope.js +35 -0
- package/dist/vault/scope.js.map +1 -0
- package/dist/vault/store.d.ts +31 -0
- package/dist/vault/store.d.ts.map +1 -0
- package/dist/vault/store.js +204 -0
- package/dist/vault/store.js.map +1 -0
- package/package.json +13 -2
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright 2026 Usertools, Inc.
|
|
3
|
+
import { createHash } from "node:crypto";
|
|
4
|
+
import { canonicalize } from "../audit/canonical.js";
|
|
5
|
+
import { SkillVerificationError } from "../shared/errors.js";
|
|
6
|
+
import { SkillManifestSchema } from "../shared/types.js";
|
|
7
|
+
import { verifySignature } from "./sign.js";
|
|
8
|
+
/**
|
|
9
|
+
* Computes a SHA-256 hash of the full manifest for audit inclusion.
|
|
10
|
+
*/
|
|
11
|
+
function computeManifestHash(manifest) {
|
|
12
|
+
const canonical = canonicalize(manifest);
|
|
13
|
+
return createHash("sha256").update(canonical).digest("hex");
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Checks whether a manifest's permissions are allowed by the config policy.
|
|
17
|
+
* Trusted publishers bypass permission restrictions.
|
|
18
|
+
*/
|
|
19
|
+
export function checkPermissions(manifest, config) {
|
|
20
|
+
const sc = config.supplyChain;
|
|
21
|
+
const manifestHash = computeManifestHash(manifest);
|
|
22
|
+
// Trusted publishers get all permissions
|
|
23
|
+
if (sc.trustedPublishers.includes(manifest.publisher)) {
|
|
24
|
+
return {
|
|
25
|
+
valid: true,
|
|
26
|
+
permissionsAllowed: true,
|
|
27
|
+
deniedPermissions: [],
|
|
28
|
+
manifestHash,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
const allowed = new Set(sc.allowedPermissions);
|
|
32
|
+
const denied = manifest.permissions.filter((p) => !allowed.has(p));
|
|
33
|
+
return {
|
|
34
|
+
valid: true,
|
|
35
|
+
permissionsAllowed: denied.length === 0,
|
|
36
|
+
deniedPermissions: denied,
|
|
37
|
+
manifestHash,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Full verification pipeline: validate schema, verify signature, check permissions, check trusted publishers.
|
|
42
|
+
* Returns a SkillVerification result. Throws SkillVerificationError on hard failures.
|
|
43
|
+
*/
|
|
44
|
+
export function enforceSkillLoad(manifest, config) {
|
|
45
|
+
const sc = config.supplyChain;
|
|
46
|
+
// Guard: if supply chain is disabled, allow everything
|
|
47
|
+
if (!sc.enabled) {
|
|
48
|
+
return {
|
|
49
|
+
valid: true,
|
|
50
|
+
permissionsAllowed: true,
|
|
51
|
+
deniedPermissions: [],
|
|
52
|
+
manifestHash: computeManifestHash(manifest),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
// Step 1: Validate schema
|
|
56
|
+
const parseResult = SkillManifestSchema.safeParse(manifest);
|
|
57
|
+
if (!parseResult.success) {
|
|
58
|
+
const reason = parseResult.error.issues.map((i) => i.message).join("; ");
|
|
59
|
+
throw new SkillVerificationError(manifest.id ?? "unknown", `Schema validation failed: ${reason}`);
|
|
60
|
+
}
|
|
61
|
+
// Step 2: Verify signature
|
|
62
|
+
// Always verify signature for trusted publishers (prevent publisher forgery)
|
|
63
|
+
// Also verify if requireSignature is true
|
|
64
|
+
const isTrusted = sc.trustedPublishers.includes(manifest.publisher);
|
|
65
|
+
if (sc.requireSignature || isTrusted) {
|
|
66
|
+
const sigValid = verifySignature(manifest);
|
|
67
|
+
if (!sigValid) {
|
|
68
|
+
const manifestHash = computeManifestHash(manifest);
|
|
69
|
+
return {
|
|
70
|
+
valid: false,
|
|
71
|
+
permissionsAllowed: false,
|
|
72
|
+
deniedPermissions: manifest.permissions,
|
|
73
|
+
manifestHash,
|
|
74
|
+
error: "Invalid manifest signature",
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// Step 3: Check permissions and trusted publishers
|
|
79
|
+
const result = checkPermissions(manifest, config);
|
|
80
|
+
if (!result.permissionsAllowed) {
|
|
81
|
+
return {
|
|
82
|
+
...result,
|
|
83
|
+
valid: false,
|
|
84
|
+
error: `Denied permissions: ${result.deniedPermissions.join(", ")}`,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
return result;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=permissions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissions.js","sourceRoot":"","sources":["../../src/supply-chain/permissions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { SkillManifest } from "../shared/types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Generates an Ed25519 keypair. Returns hex-encoded public and private keys.
|
|
4
|
+
*/
|
|
5
|
+
export declare function generateKeyPair(): {
|
|
6
|
+
publicKey: string;
|
|
7
|
+
privateKey: string;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Signs an unsigned manifest with the given private key. Returns a fully signed SkillManifest.
|
|
11
|
+
*/
|
|
12
|
+
export declare function signManifest(manifest: Omit<SkillManifest, "signature" | "publicKey" | "signedAt">, privateKeyHex: string): SkillManifest;
|
|
13
|
+
/**
|
|
14
|
+
* Verifies the Ed25519 signature on a signed manifest.
|
|
15
|
+
*/
|
|
16
|
+
export declare function verifySignature(manifest: SkillManifest): boolean;
|
|
17
|
+
//# sourceMappingURL=sign.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sign.d.ts","sourceRoot":"","sources":["../../src/supply-chain/sign.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD;;GAEG;AACH,wBAAgB,eAAe,IAAI;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAU3E;AAuBD;;GAEG;AACH,wBAAgB,YAAY,CAC3B,QAAQ,EAAE,IAAI,CAAC,aAAa,EAAE,WAAW,GAAG,WAAW,GAAG,UAAU,CAAC,EACrE,aAAa,EAAE,MAAM,GACnB,aAAa,CA+Bf;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CA+BhE"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright 2026 Usertools, Inc.
|
|
3
|
+
import { createPrivateKey, createPublicKey, generateKeyPairSync, sign, verify } from "node:crypto";
|
|
4
|
+
import { canonicalize } from "../audit/canonical.js";
|
|
5
|
+
/**
|
|
6
|
+
* Generates an Ed25519 keypair. Returns hex-encoded public and private keys.
|
|
7
|
+
*/
|
|
8
|
+
export function generateKeyPair() {
|
|
9
|
+
const { publicKey, privateKey } = generateKeyPairSync("ed25519", {
|
|
10
|
+
publicKeyEncoding: { type: "spki", format: "der" },
|
|
11
|
+
privateKeyEncoding: { type: "pkcs8", format: "der" },
|
|
12
|
+
});
|
|
13
|
+
// Ed25519 SPKI DER is 44 bytes: 12-byte prefix + 32-byte raw key
|
|
14
|
+
const rawPublic = publicKey.subarray(12).toString("hex");
|
|
15
|
+
// Return full DER for private key (needed for signing)
|
|
16
|
+
const rawPrivate = privateKey.toString("hex");
|
|
17
|
+
return { publicKey: rawPublic, privateKey: rawPrivate };
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Computes the canonical hash of manifest fields for signing (excluding signature and publicKey and signedAt).
|
|
21
|
+
*/
|
|
22
|
+
function computeSigningPayload(manifest, signedAt, publicKey) {
|
|
23
|
+
const hashable = {
|
|
24
|
+
version: manifest.version,
|
|
25
|
+
id: manifest.id,
|
|
26
|
+
name: manifest.name,
|
|
27
|
+
publisher: manifest.publisher,
|
|
28
|
+
permissions: manifest.permissions,
|
|
29
|
+
entryHash: manifest.entryHash,
|
|
30
|
+
signedAt,
|
|
31
|
+
publicKey,
|
|
32
|
+
};
|
|
33
|
+
return canonicalize(hashable);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Signs an unsigned manifest with the given private key. Returns a fully signed SkillManifest.
|
|
37
|
+
*/
|
|
38
|
+
export function signManifest(manifest, privateKeyHex) {
|
|
39
|
+
const privateKeyDer = Buffer.from(privateKeyHex, "hex");
|
|
40
|
+
const privateKey = {
|
|
41
|
+
key: privateKeyDer,
|
|
42
|
+
format: "der",
|
|
43
|
+
type: "pkcs8",
|
|
44
|
+
};
|
|
45
|
+
// Derive public key from the private key
|
|
46
|
+
const privKeyObj = createPrivateKey({
|
|
47
|
+
key: privateKeyDer,
|
|
48
|
+
format: "der",
|
|
49
|
+
type: "pkcs8",
|
|
50
|
+
});
|
|
51
|
+
const pubKeyObj = createPublicKey(privKeyObj);
|
|
52
|
+
const pubKeyDerActual = pubKeyObj.export({ type: "spki", format: "der" });
|
|
53
|
+
const publicKeyHex = pubKeyDerActual.subarray(12).toString("hex");
|
|
54
|
+
const signedAt = new Date().toISOString();
|
|
55
|
+
const payload = computeSigningPayload(manifest, signedAt, publicKeyHex);
|
|
56
|
+
const payloadBytes = Buffer.from(payload, "utf-8");
|
|
57
|
+
const signature = sign(null, payloadBytes, privateKey);
|
|
58
|
+
const signatureHex = signature.toString("hex");
|
|
59
|
+
return {
|
|
60
|
+
...manifest,
|
|
61
|
+
signedAt,
|
|
62
|
+
publicKey: publicKeyHex,
|
|
63
|
+
signature: signatureHex,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Verifies the Ed25519 signature on a signed manifest.
|
|
68
|
+
*/
|
|
69
|
+
export function verifySignature(manifest) {
|
|
70
|
+
try {
|
|
71
|
+
const payload = computeSigningPayload({
|
|
72
|
+
version: manifest.version,
|
|
73
|
+
id: manifest.id,
|
|
74
|
+
name: manifest.name,
|
|
75
|
+
publisher: manifest.publisher,
|
|
76
|
+
permissions: manifest.permissions,
|
|
77
|
+
entryHash: manifest.entryHash,
|
|
78
|
+
}, manifest.signedAt, manifest.publicKey);
|
|
79
|
+
const payloadBytes = Buffer.from(payload, "utf-8");
|
|
80
|
+
// Reconstruct DER-encoded SPKI public key from raw 32-byte key
|
|
81
|
+
const rawPubKey = Buffer.from(manifest.publicKey, "hex");
|
|
82
|
+
const spkiPrefix = Buffer.from("302a300506032b6570032100", "hex");
|
|
83
|
+
const spkiDer = Buffer.concat([spkiPrefix, rawPubKey]);
|
|
84
|
+
const publicKey = {
|
|
85
|
+
key: spkiDer,
|
|
86
|
+
format: "der",
|
|
87
|
+
type: "spki",
|
|
88
|
+
};
|
|
89
|
+
return verify(null, payloadBytes, publicKey, Buffer.from(manifest.signature, "hex"));
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=sign.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sign.js","sourceRoot":"","sources":["../../src/supply-chain/sign.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Derive a 32-byte AES-256 key from a passphrase using scrypt.
|
|
3
|
+
*
|
|
4
|
+
* @param passphrase - The master passphrase (from env var).
|
|
5
|
+
* @param salt - A 16-byte salt (from generateSalt or stored alongside ciphertext).
|
|
6
|
+
* @returns A 32-byte Buffer suitable for AES-256-GCM.
|
|
7
|
+
*/
|
|
8
|
+
export declare function deriveKey(passphrase: string, salt: Buffer): Buffer;
|
|
9
|
+
/**
|
|
10
|
+
* Generate a cryptographically random 16-byte salt.
|
|
11
|
+
*/
|
|
12
|
+
export declare function generateSalt(): Buffer;
|
|
13
|
+
//# sourceMappingURL=derive.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"derive.d.ts","sourceRoot":"","sources":["../../src/vault/derive.ts"],"names":[],"mappings":"AAYA;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAQlE;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright 2026 Usertools, Inc.
|
|
3
|
+
/**
|
|
4
|
+
* Key Derivation — scrypt-based AES-256 key from passphrase + salt.
|
|
5
|
+
*
|
|
6
|
+
* Uses node:crypto scryptSync with N=2^17, r=8, p=1 to derive a 32-byte
|
|
7
|
+
* key suitable for AES-256-GCM encryption of the credential vault.
|
|
8
|
+
*/
|
|
9
|
+
import { randomBytes, scryptSync } from "node:crypto";
|
|
10
|
+
/**
|
|
11
|
+
* Derive a 32-byte AES-256 key from a passphrase using scrypt.
|
|
12
|
+
*
|
|
13
|
+
* @param passphrase - The master passphrase (from env var).
|
|
14
|
+
* @param salt - A 16-byte salt (from generateSalt or stored alongside ciphertext).
|
|
15
|
+
* @returns A 32-byte Buffer suitable for AES-256-GCM.
|
|
16
|
+
*/
|
|
17
|
+
export function deriveKey(passphrase, salt) {
|
|
18
|
+
// maxmem must cover 128 * N * r = 128 MiB for N=2^17, r=8.
|
|
19
|
+
return scryptSync(passphrase, salt, 32, {
|
|
20
|
+
N: 2 ** 17,
|
|
21
|
+
r: 8,
|
|
22
|
+
p: 1,
|
|
23
|
+
maxmem: 256 * 1024 * 1024,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Generate a cryptographically random 16-byte salt.
|
|
28
|
+
*/
|
|
29
|
+
export function generateSalt() {
|
|
30
|
+
return randomBytes(16);
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=derive.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"derive.js","sourceRoot":"","sources":["../../src/vault/derive.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,iCAAiC;AAEjC;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEtD;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,UAAkB,EAAE,IAAY;IACzD,2DAA2D;IAC3D,OAAO,UAAU,CAAC,UAAU,EAAE,IAAI,EAAE,EAAE,EAAE;QACvC,CAAC,EAAE,CAAC,IAAI,EAAE;QACV,CAAC,EAAE,CAAC;QACJ,CAAC,EAAE,CAAC;QACJ,MAAM,EAAE,GAAG,GAAG,IAAI,GAAG,IAAI;KACzB,CAAW,CAAC;AACd,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY;IAC3B,OAAO,WAAW,CAAC,EAAE,CAAC,CAAC;AACxB,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scope Checking — validates credential access against agent, action, and expiry constraints.
|
|
3
|
+
*/
|
|
4
|
+
import type { ActionKind, CredentialScope } from "../shared/types.js";
|
|
5
|
+
/**
|
|
6
|
+
* Check whether an accessor is allowed to use a credential given its scope.
|
|
7
|
+
*
|
|
8
|
+
* Rules:
|
|
9
|
+
* - Agent scope: empty agents array = all agents allowed; otherwise accessor.agent must be in list.
|
|
10
|
+
* - Action scope: empty actions array = all actions allowed; otherwise accessor.action must be in list.
|
|
11
|
+
* - Expiry: if expiresAt is non-null and in the past, deny with "Credential expired".
|
|
12
|
+
*/
|
|
13
|
+
export declare function checkScope(scope: CredentialScope, accessor: {
|
|
14
|
+
agent: string;
|
|
15
|
+
action: ActionKind;
|
|
16
|
+
}): {
|
|
17
|
+
allowed: boolean;
|
|
18
|
+
reason?: string;
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=scope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../../src/vault/scope.ts"],"names":[],"mappings":"AAGA;;GAEG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAEtE;;;;;;;GAOG;AACH,wBAAgB,UAAU,CACzB,KAAK,EAAE,eAAe,EACtB,QAAQ,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,UAAU,CAAA;CAAE,GAC7C;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CA0BvC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright 2026 Usertools, Inc.
|
|
3
|
+
/**
|
|
4
|
+
* Check whether an accessor is allowed to use a credential given its scope.
|
|
5
|
+
*
|
|
6
|
+
* Rules:
|
|
7
|
+
* - Agent scope: empty agents array = all agents allowed; otherwise accessor.agent must be in list.
|
|
8
|
+
* - Action scope: empty actions array = all actions allowed; otherwise accessor.action must be in list.
|
|
9
|
+
* - Expiry: if expiresAt is non-null and in the past, deny with "Credential expired".
|
|
10
|
+
*/
|
|
11
|
+
export function checkScope(scope, accessor) {
|
|
12
|
+
// Check agent scope
|
|
13
|
+
if (scope.agents.length > 0 && !scope.agents.includes(accessor.agent)) {
|
|
14
|
+
return {
|
|
15
|
+
allowed: false,
|
|
16
|
+
reason: `Agent "${accessor.agent}" is not in the allowed agents list`,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
// Check action scope
|
|
20
|
+
if (scope.actions.length > 0 && !scope.actions.includes(accessor.action)) {
|
|
21
|
+
return {
|
|
22
|
+
allowed: false,
|
|
23
|
+
reason: `Action "${accessor.action}" is not in the allowed actions list`,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
// Check expiry
|
|
27
|
+
if (scope.expiresAt !== null) {
|
|
28
|
+
const expiresAt = new Date(scope.expiresAt).getTime();
|
|
29
|
+
if (expiresAt <= Date.now()) {
|
|
30
|
+
return { allowed: false, reason: "Credential expired" };
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return { allowed: true };
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=scope.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope.js","sourceRoot":"","sources":["../../src/vault/scope.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,iCAAiC;AAQjC;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU,CACzB,KAAsB,EACtB,QAA+C;IAE/C,oBAAoB;IACpB,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACvE,OAAO;YACN,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,UAAU,QAAQ,CAAC,KAAK,qCAAqC;SACrE,CAAC;IACH,CAAC;IAED,qBAAqB;IACrB,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1E,OAAO;YACN,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,WAAW,QAAQ,CAAC,MAAM,sCAAsC;SACxE,CAAC;IACH,CAAC;IAED,eAAe;IACf,IAAI,KAAK,CAAC,SAAS,KAAK,IAAI,EAAE,CAAC;QAC9B,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC;QACtD,IAAI,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;YAC7B,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,oBAAoB,EAAE,CAAC;QACzD,CAAC;IACF,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { AuditWriter } from "../audit/chain.js";
|
|
2
|
+
import type { ActionKind, CredentialAccessResult, CredentialScope, TrustConfig } from "../shared/types.js";
|
|
3
|
+
export interface VaultStore {
|
|
4
|
+
add(name: string, value: string, scope?: Partial<CredentialScope>): Promise<void>;
|
|
5
|
+
remove(name: string): Promise<void>;
|
|
6
|
+
get(name: string, accessor: {
|
|
7
|
+
agent: string;
|
|
8
|
+
action: ActionKind;
|
|
9
|
+
}): Promise<CredentialAccessResult>;
|
|
10
|
+
list(): Promise<Array<{
|
|
11
|
+
name: string;
|
|
12
|
+
scope: CredentialScope;
|
|
13
|
+
createdAt: string;
|
|
14
|
+
rotatedAt: string;
|
|
15
|
+
}>>;
|
|
16
|
+
rotate(name: string, newValue: string): Promise<void>;
|
|
17
|
+
destroy(): void;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Create an encrypted vault store.
|
|
21
|
+
*
|
|
22
|
+
* Reads the master key from the env var specified in config.vault.masterKeyEnv
|
|
23
|
+
* (default: USERTRUST_VAULT_KEY). Throws VaultNotInitializedError if the key
|
|
24
|
+
* is not set.
|
|
25
|
+
*/
|
|
26
|
+
export declare function createVaultStore(opts: {
|
|
27
|
+
vaultBase: string;
|
|
28
|
+
config: TrustConfig;
|
|
29
|
+
audit?: AuditWriter;
|
|
30
|
+
}): Promise<VaultStore>;
|
|
31
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/vault/store.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrD,OAAO,KAAK,EACX,UAAU,EACV,sBAAsB,EAEtB,eAAe,EACf,WAAW,EACX,MAAM,oBAAoB,CAAC;AAe5B,MAAM,WAAW,UAAU;IAC1B,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClF,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,GAAG,CACF,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,UAAU,CAAA;KAAE,GAC7C,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACnC,IAAI,IAAI,OAAO,CACd,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,eAAe,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CACrF,CAAC;IACF,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtD,OAAO,IAAI,IAAI,CAAC;CAChB;AAiCD;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,WAAW,CAAC;IACpB,KAAK,CAAC,EAAE,WAAW,CAAC;CACpB,GAAG,OAAO,CAAC,UAAU,CAAC,CAiLtB"}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright 2026 Usertools, Inc.
|
|
3
|
+
/**
|
|
4
|
+
* Encrypted Credential Store — AES-256-GCM vault for agent secrets.
|
|
5
|
+
*
|
|
6
|
+
* Stores credentials in `<vaultBase>/.usertrust/credentials.enc` as a JSON
|
|
7
|
+
* envelope `{ salt, iv, tag, ciphertext }` wrapping an encrypted array of
|
|
8
|
+
* CredentialEntry objects. Scoped access (agent/action/time-window) is enforced
|
|
9
|
+
* on every `get()` call, with audit events emitted for all operations.
|
|
10
|
+
*
|
|
11
|
+
* Atomic writes: data is written to a .tmp file then renamed, matching the
|
|
12
|
+
* spend-ledger pattern in govern.ts.
|
|
13
|
+
*/
|
|
14
|
+
import { createCipheriv, createDecipheriv, randomBytes } from "node:crypto";
|
|
15
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
16
|
+
import { join } from "node:path";
|
|
17
|
+
import { VAULT_DIR } from "../shared/constants.js";
|
|
18
|
+
import { VaultKeyMissingError } from "../shared/errors.js";
|
|
19
|
+
import { deriveKey, generateSalt } from "./derive.js";
|
|
20
|
+
import { checkScope } from "./scope.js";
|
|
21
|
+
// ── Encryption helpers ──
|
|
22
|
+
function encrypt(data, passphrase) {
|
|
23
|
+
const salt = generateSalt();
|
|
24
|
+
const key = deriveKey(passphrase, salt);
|
|
25
|
+
const iv = randomBytes(12); // 12-byte IV for AES-256-GCM
|
|
26
|
+
const cipher = createCipheriv("aes-256-gcm", key, iv);
|
|
27
|
+
const encrypted = Buffer.concat([cipher.update(data, "utf-8"), cipher.final()]);
|
|
28
|
+
const tag = cipher.getAuthTag(); // 16-byte auth tag
|
|
29
|
+
return {
|
|
30
|
+
salt: salt.toString("hex"),
|
|
31
|
+
iv: iv.toString("hex"),
|
|
32
|
+
tag: tag.toString("hex"),
|
|
33
|
+
ciphertext: encrypted.toString("hex"),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function decrypt(envelope, passphrase) {
|
|
37
|
+
const salt = Buffer.from(envelope.salt, "hex");
|
|
38
|
+
const key = deriveKey(passphrase, salt);
|
|
39
|
+
const iv = Buffer.from(envelope.iv, "hex");
|
|
40
|
+
const tag = Buffer.from(envelope.tag, "hex");
|
|
41
|
+
const ciphertext = Buffer.from(envelope.ciphertext, "hex");
|
|
42
|
+
const decipher = createDecipheriv("aes-256-gcm", key, iv);
|
|
43
|
+
decipher.setAuthTag(tag);
|
|
44
|
+
const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
|
|
45
|
+
return decrypted.toString("utf-8");
|
|
46
|
+
}
|
|
47
|
+
// ── Factory ──
|
|
48
|
+
/**
|
|
49
|
+
* Create an encrypted vault store.
|
|
50
|
+
*
|
|
51
|
+
* Reads the master key from the env var specified in config.vault.masterKeyEnv
|
|
52
|
+
* (default: USERTRUST_VAULT_KEY). Throws VaultNotInitializedError if the key
|
|
53
|
+
* is not set.
|
|
54
|
+
*/
|
|
55
|
+
export async function createVaultStore(opts) {
|
|
56
|
+
const { vaultBase, config, audit } = opts;
|
|
57
|
+
const masterKeyEnv = config.vault?.masterKeyEnv ?? "USERTRUST_VAULT_KEY";
|
|
58
|
+
const envValue = process.env[masterKeyEnv];
|
|
59
|
+
if (!envValue) {
|
|
60
|
+
throw new VaultKeyMissingError(masterKeyEnv);
|
|
61
|
+
}
|
|
62
|
+
const passphrase = envValue;
|
|
63
|
+
const auditAccess = config.vault?.auditAccess ?? true;
|
|
64
|
+
const defaultScope = {
|
|
65
|
+
agents: config.vault?.defaultScope?.agents ?? [],
|
|
66
|
+
actions: (config.vault?.defaultScope?.actions ?? []),
|
|
67
|
+
expiresAt: config.vault?.defaultScope?.expiresAt ?? null,
|
|
68
|
+
};
|
|
69
|
+
const vaultDir = join(vaultBase, VAULT_DIR);
|
|
70
|
+
const credPath = join(vaultDir, "credentials.enc");
|
|
71
|
+
const tmpPath = join(vaultDir, "credentials.enc.tmp");
|
|
72
|
+
// Ensure vault directory exists
|
|
73
|
+
if (!existsSync(vaultDir)) {
|
|
74
|
+
mkdirSync(vaultDir, { recursive: true, mode: 0o700 });
|
|
75
|
+
}
|
|
76
|
+
// ── In-memory credential state ──
|
|
77
|
+
let entries = [];
|
|
78
|
+
let destroyed = false;
|
|
79
|
+
// Load existing credentials from disk
|
|
80
|
+
if (existsSync(credPath)) {
|
|
81
|
+
const raw = readFileSync(credPath, "utf-8");
|
|
82
|
+
const envelope = JSON.parse(raw);
|
|
83
|
+
const plaintext = decrypt(envelope, passphrase);
|
|
84
|
+
entries = JSON.parse(plaintext);
|
|
85
|
+
}
|
|
86
|
+
// ── Persistence ──
|
|
87
|
+
function persist() {
|
|
88
|
+
const plaintext = JSON.stringify(entries);
|
|
89
|
+
const envelope = encrypt(plaintext, passphrase);
|
|
90
|
+
// Atomic write: write to .tmp then rename
|
|
91
|
+
writeFileSync(tmpPath, JSON.stringify(envelope), { encoding: "utf-8", mode: 0o600 });
|
|
92
|
+
renameSync(tmpPath, credPath);
|
|
93
|
+
}
|
|
94
|
+
// ── Audit helper ──
|
|
95
|
+
async function emitAudit(kind, data) {
|
|
96
|
+
if (auditAccess && audit) {
|
|
97
|
+
await audit.appendEvent({ kind, actor: "vault", data });
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// ── VaultStore implementation ──
|
|
101
|
+
async function add(name, value, scope) {
|
|
102
|
+
if (destroyed)
|
|
103
|
+
throw new Error("VaultStore has been destroyed");
|
|
104
|
+
const now = new Date().toISOString();
|
|
105
|
+
const mergedScope = {
|
|
106
|
+
agents: scope?.agents ?? defaultScope.agents,
|
|
107
|
+
actions: scope?.actions ?? defaultScope.actions,
|
|
108
|
+
expiresAt: scope?.expiresAt !== undefined ? scope.expiresAt : defaultScope.expiresAt,
|
|
109
|
+
};
|
|
110
|
+
// Overwrite if already exists
|
|
111
|
+
const existing = entries.findIndex((e) => e.name === name);
|
|
112
|
+
const entry = {
|
|
113
|
+
name,
|
|
114
|
+
value,
|
|
115
|
+
scope: mergedScope,
|
|
116
|
+
createdAt: now,
|
|
117
|
+
rotatedAt: now,
|
|
118
|
+
};
|
|
119
|
+
if (existing >= 0) {
|
|
120
|
+
entries[existing] = entry;
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
entries.push(entry);
|
|
124
|
+
}
|
|
125
|
+
persist();
|
|
126
|
+
await emitAudit("credential_added", { name });
|
|
127
|
+
}
|
|
128
|
+
async function remove(name) {
|
|
129
|
+
if (destroyed)
|
|
130
|
+
throw new Error("VaultStore has been destroyed");
|
|
131
|
+
entries = entries.filter((e) => e.name !== name);
|
|
132
|
+
persist();
|
|
133
|
+
await emitAudit("credential_removed", { name });
|
|
134
|
+
}
|
|
135
|
+
async function get(name, accessor) {
|
|
136
|
+
if (destroyed)
|
|
137
|
+
throw new Error("VaultStore has been destroyed");
|
|
138
|
+
const entry = entries.find((e) => e.name === name);
|
|
139
|
+
if (!entry) {
|
|
140
|
+
return { granted: false, reason: `Credential "${name}" not found` };
|
|
141
|
+
}
|
|
142
|
+
const scopeResult = checkScope(entry.scope, accessor);
|
|
143
|
+
if (!scopeResult.allowed) {
|
|
144
|
+
const reason = scopeResult.reason ?? "Access denied";
|
|
145
|
+
await emitAudit("credential_denied", {
|
|
146
|
+
name,
|
|
147
|
+
agent: accessor.agent,
|
|
148
|
+
action: accessor.action,
|
|
149
|
+
granted: false,
|
|
150
|
+
reason,
|
|
151
|
+
});
|
|
152
|
+
return { granted: false, reason };
|
|
153
|
+
}
|
|
154
|
+
await emitAudit("credential_access", {
|
|
155
|
+
name,
|
|
156
|
+
agent: accessor.agent,
|
|
157
|
+
action: accessor.action,
|
|
158
|
+
granted: true,
|
|
159
|
+
});
|
|
160
|
+
return { granted: true, value: entry.value };
|
|
161
|
+
}
|
|
162
|
+
async function list() {
|
|
163
|
+
if (destroyed)
|
|
164
|
+
throw new Error("VaultStore has been destroyed");
|
|
165
|
+
return entries.map((e) => ({
|
|
166
|
+
name: e.name,
|
|
167
|
+
scope: e.scope,
|
|
168
|
+
createdAt: e.createdAt,
|
|
169
|
+
rotatedAt: e.rotatedAt,
|
|
170
|
+
}));
|
|
171
|
+
}
|
|
172
|
+
async function rotate(name, newValue) {
|
|
173
|
+
if (destroyed)
|
|
174
|
+
throw new Error("VaultStore has been destroyed");
|
|
175
|
+
const entry = entries.find((e) => e.name === name);
|
|
176
|
+
if (!entry) {
|
|
177
|
+
throw new Error(`Credential "${name}" not found`);
|
|
178
|
+
}
|
|
179
|
+
entry.value = newValue;
|
|
180
|
+
entry.rotatedAt = new Date().toISOString();
|
|
181
|
+
persist();
|
|
182
|
+
await emitAudit("credential_rotated", { name });
|
|
183
|
+
}
|
|
184
|
+
function destroyStore() {
|
|
185
|
+
// Note: JavaScript strings are immutable in V8 — assigning "" removes the
|
|
186
|
+
// reference but the original string remains in the heap until GC. True
|
|
187
|
+
// memory-safe secret clearing requires Buffer-based storage, which is a
|
|
188
|
+
// future enhancement. This destroy() provides reference cleanup only.
|
|
189
|
+
for (const entry of entries) {
|
|
190
|
+
entry.value = "";
|
|
191
|
+
}
|
|
192
|
+
entries = [];
|
|
193
|
+
destroyed = true;
|
|
194
|
+
}
|
|
195
|
+
return {
|
|
196
|
+
add,
|
|
197
|
+
remove,
|
|
198
|
+
get,
|
|
199
|
+
list,
|
|
200
|
+
rotate,
|
|
201
|
+
destroy: destroyStore,
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/vault/store.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "usertrust",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "Financial governance for AI agents. Every LLM call becomes an immutable, auditable transaction.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Usertools, Inc. <hello@usertools.ai> (https://usertrust.ai)",
|
|
@@ -35,9 +35,18 @@
|
|
|
35
35
|
".": {
|
|
36
36
|
"import": "./dist/index.js",
|
|
37
37
|
"types": "./dist/index.d.ts"
|
|
38
|
+
},
|
|
39
|
+
"./headless": {
|
|
40
|
+
"import": "./dist/headless.js",
|
|
41
|
+
"types": "./dist/headless.d.ts"
|
|
42
|
+
},
|
|
43
|
+
"./pricing": {
|
|
44
|
+
"import": "./dist/ledger/pricing.js",
|
|
45
|
+
"types": "./dist/ledger/pricing.d.ts"
|
|
38
46
|
}
|
|
39
47
|
},
|
|
40
48
|
"dependencies": {
|
|
49
|
+
"@clack/prompts": "^1.1.0",
|
|
41
50
|
"minimatch": "^10.2.4",
|
|
42
51
|
"picocolors": "^1.1.1",
|
|
43
52
|
"tigerbeetle-node": "^0.16.0",
|
|
@@ -48,7 +57,9 @@
|
|
|
48
57
|
"build": "tsc",
|
|
49
58
|
"prepublishOnly": "tsc"
|
|
50
59
|
},
|
|
51
|
-
"files": [
|
|
60
|
+
"files": [
|
|
61
|
+
"dist"
|
|
62
|
+
],
|
|
52
63
|
"peerDependencies": {
|
|
53
64
|
"@anthropic-ai/sdk": ">=0.30.0",
|
|
54
65
|
"openai": ">=4.70.0"
|