usertrust 1.0.0 → 1.1.0

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 (80) hide show
  1. package/dist/cli/init.d.ts +2 -0
  2. package/dist/cli/init.d.ts.map +1 -1
  3. package/dist/cli/init.js +231 -37
  4. package/dist/cli/init.js.map +1 -1
  5. package/dist/cli/main.d.ts +1 -1
  6. package/dist/cli/main.d.ts.map +1 -1
  7. package/dist/cli/main.js +18 -3
  8. package/dist/cli/main.js.map +1 -1
  9. package/dist/cli/pricing.d.ts +5 -0
  10. package/dist/cli/pricing.d.ts.map +1 -0
  11. package/dist/cli/pricing.js +61 -0
  12. package/dist/cli/pricing.js.map +1 -0
  13. package/dist/cli/validate-key.d.ts +17 -0
  14. package/dist/cli/validate-key.d.ts.map +1 -0
  15. package/dist/cli/validate-key.js +58 -0
  16. package/dist/cli/validate-key.js.map +1 -0
  17. package/dist/config.d.ts.map +1 -1
  18. package/dist/config.js +31 -0
  19. package/dist/config.js.map +1 -1
  20. package/dist/govern.d.ts +3 -1
  21. package/dist/govern.d.ts.map +1 -1
  22. package/dist/govern.js +415 -47
  23. package/dist/govern.js.map +1 -1
  24. package/dist/headless.d.ts +77 -0
  25. package/dist/headless.d.ts.map +1 -0
  26. package/dist/headless.js +566 -0
  27. package/dist/headless.js.map +1 -0
  28. package/dist/index.d.ts +12 -2
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +13 -1
  31. package/dist/index.js.map +1 -1
  32. package/dist/ledger/pricing.d.ts +6 -2
  33. package/dist/ledger/pricing.d.ts.map +1 -1
  34. package/dist/ledger/pricing.js +31 -3
  35. package/dist/ledger/pricing.js.map +1 -1
  36. package/dist/policy/canary.d.ts +17 -0
  37. package/dist/policy/canary.d.ts.map +1 -0
  38. package/dist/policy/canary.js +44 -0
  39. package/dist/policy/canary.js.map +1 -0
  40. package/dist/policy/injection.d.ts +24 -0
  41. package/dist/policy/injection.d.ts.map +1 -0
  42. package/dist/policy/injection.js +178 -0
  43. package/dist/policy/injection.js.map +1 -0
  44. package/dist/policy/pii.d.ts +13 -1
  45. package/dist/policy/pii.d.ts.map +1 -1
  46. package/dist/policy/pii.js +88 -0
  47. package/dist/policy/pii.js.map +1 -1
  48. package/dist/shared/errors.d.ts +20 -0
  49. package/dist/shared/errors.d.ts.map +1 -1
  50. package/dist/shared/errors.js +46 -0
  51. package/dist/shared/errors.js.map +1 -1
  52. package/dist/shared/types.d.ts +264 -0
  53. package/dist/shared/types.d.ts.map +1 -1
  54. package/dist/shared/types.js +67 -0
  55. package/dist/shared/types.js.map +1 -1
  56. package/dist/supply-chain/manifest.d.ts +22 -0
  57. package/dist/supply-chain/manifest.d.ts.map +1 -0
  58. package/dist/supply-chain/manifest.js +46 -0
  59. package/dist/supply-chain/manifest.js.map +1 -0
  60. package/dist/supply-chain/permissions.d.ts +12 -0
  61. package/dist/supply-chain/permissions.d.ts.map +1 -0
  62. package/dist/supply-chain/permissions.js +89 -0
  63. package/dist/supply-chain/permissions.js.map +1 -0
  64. package/dist/supply-chain/sign.d.ts +17 -0
  65. package/dist/supply-chain/sign.d.ts.map +1 -0
  66. package/dist/supply-chain/sign.js +95 -0
  67. package/dist/supply-chain/sign.js.map +1 -0
  68. package/dist/vault/derive.d.ts +13 -0
  69. package/dist/vault/derive.d.ts.map +1 -0
  70. package/dist/vault/derive.js +32 -0
  71. package/dist/vault/derive.js.map +1 -0
  72. package/dist/vault/scope.d.ts +20 -0
  73. package/dist/vault/scope.d.ts.map +1 -0
  74. package/dist/vault/scope.js +35 -0
  75. package/dist/vault/scope.js.map +1 -0
  76. package/dist/vault/store.d.ts +31 -0
  77. package/dist/vault/store.d.ts.map +1 -0
  78. package/dist/vault/store.js +204 -0
  79. package/dist/vault/store.js.map +1 -0
  80. 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":"AAAA,sCAAsC;AACtC,iCAAiC;AAEjC,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,mBAAmB,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACnG,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAGrD;;GAEG;AACH,MAAM,UAAU,eAAe;IAC9B,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,mBAAmB,CAAC,SAAS,EAAE;QAChE,iBAAiB,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE;QAClD,kBAAkB,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE;KACpD,CAAC,CAAC;IACH,iEAAiE;IACjE,MAAM,SAAS,GAAI,SAAoB,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACrE,uDAAuD;IACvD,MAAM,UAAU,GAAI,UAAqB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC1D,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC;AACzD,CAAC;AAED;;GAEG;AACH,SAAS,qBAAqB,CAC7B,QAAqE,EACrE,QAAgB,EAChB,SAAiB;IAEjB,MAAM,QAAQ,GAAG;QAChB,OAAO,EAAE,QAAQ,CAAC,OAAO;QACzB,EAAE,EAAE,QAAQ,CAAC,EAAE;QACf,IAAI,EAAE,QAAQ,CAAC,IAAI;QACnB,SAAS,EAAE,QAAQ,CAAC,SAAS;QAC7B,WAAW,EAAE,QAAQ,CAAC,WAAW;QACjC,SAAS,EAAE,QAAQ,CAAC,SAAS;QAC7B,QAAQ;QACR,SAAS;KACT,CAAC;IACF,OAAO,YAAY,CAAC,QAAQ,CAAC,CAAC;AAC/B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAC3B,QAAqE,EACrE,aAAqB;IAErB,MAAM,aAAa,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;IACxD,MAAM,UAAU,GAAG;QAClB,GAAG,EAAE,aAAa;QAClB,MAAM,EAAE,KAAc;QACtB,IAAI,EAAE,OAAgB;KACtB,CAAC;IAEF,yCAAyC;IACzC,MAAM,UAAU,GAAG,gBAAgB,CAAC;QACnC,GAAG,EAAE,aAAa;QAClB,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,OAAO;KACb,CAAC,CAAC;IACH,MAAM,SAAS,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;IAC9C,MAAM,eAAe,GAAG,SAAS,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IAC1E,MAAM,YAAY,GAAI,eAA0B,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE9E,MAAM,QAAQ,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC1C,MAAM,OAAO,GAAG,qBAAqB,CAAC,QAAQ,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC;IACxE,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAEnD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC;IACvD,MAAM,YAAY,GAAI,SAAoB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE3D,OAAO;QACN,GAAG,QAAQ;QACX,QAAQ;QACR,SAAS,EAAE,YAAY;QACvB,SAAS,EAAE,YAAY;KACvB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,QAAuB;IACtD,IAAI,CAAC;QACJ,MAAM,OAAO,GAAG,qBAAqB,CACpC;YACC,OAAO,EAAE,QAAQ,CAAC,OAAO;YACzB,EAAE,EAAE,QAAQ,CAAC,EAAE;YACf,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,SAAS,EAAE,QAAQ,CAAC,SAAS;YAC7B,WAAW,EAAE,QAAQ,CAAC,WAAW;YACjC,SAAS,EAAE,QAAQ,CAAC,SAAS;SAC7B,EACD,QAAQ,CAAC,QAAQ,EACjB,QAAQ,CAAC,SAAS,CAClB,CAAC;QACF,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAEnD,+DAA+D;QAC/D,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QACzD,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,0BAA0B,EAAE,KAAK,CAAC,CAAC;QAClE,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC;QAEvD,MAAM,SAAS,GAAG;YACjB,GAAG,EAAE,OAAO;YACZ,MAAM,EAAE,KAAc;YACtB,IAAI,EAAE,MAAe;SACrB,CAAC;QAEF,OAAO,MAAM,CAAC,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC;IACtF,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,KAAK,CAAC;IACd,CAAC;AACF,CAAC"}
@@ -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.0",
3
+ "version": "1.1.0",
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": ["dist"],
60
+ "files": [
61
+ "dist"
62
+ ],
52
63
  "peerDependencies": {
53
64
  "@anthropic-ai/sdk": ">=0.30.0",
54
65
  "openai": ">=4.70.0"