@the-ai-company/cbio-node-runtime 0.31.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 (70) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +46 -0
  3. package/dist/agent/agent.d.ts +234 -0
  4. package/dist/agent/agent.js +565 -0
  5. package/dist/agent/agent.js.map +1 -0
  6. package/dist/audit/ActivityLog.d.ts +25 -0
  7. package/dist/audit/ActivityLog.js +66 -0
  8. package/dist/audit/ActivityLog.js.map +1 -0
  9. package/dist/errors.d.ts +28 -0
  10. package/dist/errors.js +37 -0
  11. package/dist/errors.js.map +1 -0
  12. package/dist/http/authClient.d.ts +26 -0
  13. package/dist/http/authClient.js +132 -0
  14. package/dist/http/authClient.js.map +1 -0
  15. package/dist/http/localAuthProxy.d.ts +33 -0
  16. package/dist/http/localAuthProxy.js +93 -0
  17. package/dist/http/localAuthProxy.js.map +1 -0
  18. package/dist/http/secretAcquisition.d.ts +54 -0
  19. package/dist/http/secretAcquisition.js +177 -0
  20. package/dist/http/secretAcquisition.js.map +1 -0
  21. package/dist/protocol/childSecretNaming.d.ts +7 -0
  22. package/dist/protocol/childSecretNaming.js +12 -0
  23. package/dist/protocol/childSecretNaming.js.map +1 -0
  24. package/dist/protocol/crypto.d.ts +23 -0
  25. package/dist/protocol/crypto.js +37 -0
  26. package/dist/protocol/crypto.js.map +1 -0
  27. package/dist/protocol/identity.d.ts +8 -0
  28. package/dist/protocol/identity.js +16 -0
  29. package/dist/protocol/identity.js.map +1 -0
  30. package/dist/runtime/index.d.ts +14 -0
  31. package/dist/runtime/index.js +11 -0
  32. package/dist/runtime/index.js.map +1 -0
  33. package/dist/sealed/index.d.ts +6 -0
  34. package/dist/sealed/index.js +6 -0
  35. package/dist/sealed/index.js.map +1 -0
  36. package/dist/sealed/seal.d.ts +19 -0
  37. package/dist/sealed/seal.js +56 -0
  38. package/dist/sealed/seal.js.map +1 -0
  39. package/dist/storage/fs.d.ts +16 -0
  40. package/dist/storage/fs.js +68 -0
  41. package/dist/storage/fs.js.map +1 -0
  42. package/dist/storage/memory.d.ts +11 -0
  43. package/dist/storage/memory.js +19 -0
  44. package/dist/storage/memory.js.map +1 -0
  45. package/dist/storage/provider.d.ts +12 -0
  46. package/dist/storage/provider.js +6 -0
  47. package/dist/storage/provider.js.map +1 -0
  48. package/dist/vault/secretPolicy.d.ts +3 -0
  49. package/dist/vault/secretPolicy.js +14 -0
  50. package/dist/vault/secretPolicy.js.map +1 -0
  51. package/dist/vault/vault.d.ts +91 -0
  52. package/dist/vault/vault.js +534 -0
  53. package/dist/vault/vault.js.map +1 -0
  54. package/docs/ARCHITECTURE.md +100 -0
  55. package/docs/REFERENCE.md +184 -0
  56. package/docs/TODO-multi-vault.md +29 -0
  57. package/docs/WORKS_WITH_CUSTOM_FETCH.md +196 -0
  58. package/docs/es/README.md +27 -0
  59. package/docs/fr/README.md +27 -0
  60. package/docs/ja/README.md +27 -0
  61. package/docs/ko/README.md +27 -0
  62. package/docs/pt/README.md +27 -0
  63. package/docs/spec/runtime/README.md +27 -0
  64. package/docs/spec/runtime/activity-log.md +67 -0
  65. package/docs/spec/runtime/managed-agent-record.md +52 -0
  66. package/docs/spec/runtime/merge-rules.md +52 -0
  67. package/docs/spec/runtime/secret-origin-policy.md +46 -0
  68. package/docs/zh/README.md +27 -0
  69. package/examples/minimal.ts +13 -0
  70. package/package.json +57 -0
@@ -0,0 +1,66 @@
1
+ /**
2
+ * ActivityLog
3
+ *
4
+ * Audit log for fetchWithAuth/fetchJsonAndAddSecret/fetchJsonAndUpdateSecret. Separate from vault.
5
+ * No sensitive data. For dashboard/UI display. Optional, can be disabled.
6
+ * First line is metadata (_meta) for consumer identification.
7
+ */
8
+ const NEWLINE = '\n';
9
+ export async function appendActivityLog(storage, key, entry, metadata) {
10
+ let existing = await storage.read(key);
11
+ if ((!existing || existing.length === 0) && metadata) {
12
+ const metaLine = JSON.stringify({ _meta: metadata }) + NEWLINE;
13
+ existing = Buffer.from(metaLine, 'utf8');
14
+ }
15
+ const line = JSON.stringify(entry) + NEWLINE;
16
+ const next = existing ? Buffer.concat([existing, Buffer.from(line, 'utf8')]) : Buffer.from(line, 'utf8');
17
+ await storage.write(key, next);
18
+ }
19
+ export async function readActivityLog(storage, key) {
20
+ const buf = await storage.read(key);
21
+ if (!buf || buf.length === 0)
22
+ return [];
23
+ const text = buf.toString('utf8');
24
+ const lines = text.split(NEWLINE).filter(Boolean);
25
+ return lines
26
+ .map((l) => {
27
+ const raw = JSON.parse(l);
28
+ if (raw._meta)
29
+ return null;
30
+ const secretName = raw.secretName ?? raw.alias;
31
+ if (typeof raw.ts !== 'number')
32
+ return null;
33
+ if (raw.action !== 'fetchWithAuth' && raw.action !== 'fetchJsonAndAddSecret' && raw.action !== 'fetchJsonAndUpdateSecret')
34
+ return null;
35
+ if (typeof secretName !== 'string')
36
+ return null;
37
+ if (typeof raw.url !== 'string')
38
+ return null;
39
+ if (typeof raw.method !== 'string')
40
+ return null;
41
+ if (typeof raw.success !== 'boolean')
42
+ return null;
43
+ return {
44
+ ts: raw.ts,
45
+ action: raw.action,
46
+ secretName,
47
+ url: raw.url,
48
+ method: raw.method,
49
+ success: raw.success,
50
+ ...(typeof raw.error === 'string' ? { error: raw.error } : {}),
51
+ };
52
+ })
53
+ .filter((e) => e !== null);
54
+ }
55
+ export async function readActivityLogMetadata(storage, key) {
56
+ const buf = await storage.read(key);
57
+ if (!buf || buf.length === 0)
58
+ return null;
59
+ const firstLine = buf.toString('utf8').split(NEWLINE)[0];
60
+ if (!firstLine)
61
+ return null;
62
+ const raw = JSON.parse(firstLine);
63
+ const meta = raw._meta;
64
+ return meta && typeof meta.agentId === 'string' && typeof meta.storageKey === 'string' ? meta : null;
65
+ }
66
+ //# sourceMappingURL=ActivityLog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ActivityLog.js","sourceRoot":"","sources":["../../src/audit/ActivityLog.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Structured error hierarchy for local vault and identity operations.
3
+ */
4
+ export declare enum IdentityErrorCode {
5
+ VAULT_PERSISTENCE_FAILED = "VAULT_PERSISTENCE_FAILED",
6
+ SECRET_NOT_FOUND = "SECRET_NOT_FOUND",
7
+ ISSUED_IDENTITY_INVALID = "ISSUED_IDENTITY_INVALID",
8
+ VAULT_WRITE_INTEGRITY_FAILED = "VAULT_WRITE_INTEGRITY_FAILED",
9
+ INVALID_KDK = "INVALID_KDK",
10
+ VAULT_CORRUPTED = "VAULT_CORRUPTED",
11
+ VAULT_DECRYPT_FAILED = "VAULT_DECRYPT_FAILED",
12
+ MERGE_IDENTITY_MISMATCH = "MERGE_IDENTITY_MISMATCH",
13
+ SIGNER_REQUIRES_PUBLIC_KEY = "SIGNER_REQUIRES_PUBLIC_KEY",
14
+ SIGNER_REQUIRES_PRIVATE_KEY = "SIGNER_REQUIRES_PRIVATE_KEY",
15
+ EXPORT_REQUIRES_LOCAL_SIGNER = "EXPORT_REQUIRES_LOCAL_SIGNER",
16
+ CHILD_IDENTITY_REQUIRES_PRIVATE_KEY = "CHILD_IDENTITY_REQUIRES_PRIVATE_KEY",
17
+ SECRET_ALREADY_EXISTS = "SECRET_ALREADY_EXISTS",
18
+ VAULT_FILE_NOT_FOUND = "VAULT_FILE_NOT_FOUND",
19
+ SECRET_POLICY_REQUIRED = "SECRET_POLICY_REQUIRED",
20
+ SECRET_SOURCE_ORIGIN_MISMATCH = "SECRET_SOURCE_ORIGIN_MISMATCH",
21
+ UNSUPPORTED_SIGNED_BODY = "UNSUPPORTED_SIGNED_BODY",
22
+ PERMISSION_DENIED = "PERMISSION_DENIED"
23
+ }
24
+ export declare class IdentityError extends Error {
25
+ readonly code: IdentityErrorCode;
26
+ constructor(code: IdentityErrorCode, message: string, options?: ErrorOptions);
27
+ static isIdentityError(e: unknown): e is IdentityError;
28
+ }
package/dist/errors.js ADDED
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Structured error hierarchy for local vault and identity operations.
3
+ */
4
+ export var IdentityErrorCode;
5
+ (function (IdentityErrorCode) {
6
+ IdentityErrorCode["VAULT_PERSISTENCE_FAILED"] = "VAULT_PERSISTENCE_FAILED";
7
+ IdentityErrorCode["SECRET_NOT_FOUND"] = "SECRET_NOT_FOUND";
8
+ IdentityErrorCode["ISSUED_IDENTITY_INVALID"] = "ISSUED_IDENTITY_INVALID";
9
+ IdentityErrorCode["VAULT_WRITE_INTEGRITY_FAILED"] = "VAULT_WRITE_INTEGRITY_FAILED";
10
+ IdentityErrorCode["INVALID_KDK"] = "INVALID_KDK";
11
+ IdentityErrorCode["VAULT_CORRUPTED"] = "VAULT_CORRUPTED";
12
+ IdentityErrorCode["VAULT_DECRYPT_FAILED"] = "VAULT_DECRYPT_FAILED";
13
+ IdentityErrorCode["MERGE_IDENTITY_MISMATCH"] = "MERGE_IDENTITY_MISMATCH";
14
+ IdentityErrorCode["SIGNER_REQUIRES_PUBLIC_KEY"] = "SIGNER_REQUIRES_PUBLIC_KEY";
15
+ IdentityErrorCode["SIGNER_REQUIRES_PRIVATE_KEY"] = "SIGNER_REQUIRES_PRIVATE_KEY";
16
+ IdentityErrorCode["EXPORT_REQUIRES_LOCAL_SIGNER"] = "EXPORT_REQUIRES_LOCAL_SIGNER";
17
+ IdentityErrorCode["CHILD_IDENTITY_REQUIRES_PRIVATE_KEY"] = "CHILD_IDENTITY_REQUIRES_PRIVATE_KEY";
18
+ IdentityErrorCode["SECRET_ALREADY_EXISTS"] = "SECRET_ALREADY_EXISTS";
19
+ IdentityErrorCode["VAULT_FILE_NOT_FOUND"] = "VAULT_FILE_NOT_FOUND";
20
+ IdentityErrorCode["SECRET_POLICY_REQUIRED"] = "SECRET_POLICY_REQUIRED";
21
+ IdentityErrorCode["SECRET_SOURCE_ORIGIN_MISMATCH"] = "SECRET_SOURCE_ORIGIN_MISMATCH";
22
+ IdentityErrorCode["UNSUPPORTED_SIGNED_BODY"] = "UNSUPPORTED_SIGNED_BODY";
23
+ IdentityErrorCode["PERMISSION_DENIED"] = "PERMISSION_DENIED";
24
+ })(IdentityErrorCode || (IdentityErrorCode = {}));
25
+ export class IdentityError extends Error {
26
+ code;
27
+ constructor(code, message, options) {
28
+ super(message, options);
29
+ this.name = "IdentityError";
30
+ this.code = code;
31
+ Object.setPrototypeOf(this, IdentityError.prototype);
32
+ }
33
+ static isIdentityError(e) {
34
+ return e instanceof IdentityError;
35
+ }
36
+ }
37
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,CAAN,IAAY,iBAmBX;AAnBD,WAAY,iBAAiB;IACzB,0EAAqD,CAAA;IACrD,0DAAqC,CAAA;IACrC,wEAAmD,CAAA;IACnD,kFAA6D,CAAA;IAC7D,gDAA2B,CAAA;IAC3B,wDAAmC,CAAA;IACnC,kEAA6C,CAAA;IAC7C,wEAAmD,CAAA;IACnD,8EAAyD,CAAA;IACzD,gFAA2D,CAAA;IAC3D,kFAA6D,CAAA;IAC7D,gGAA2E,CAAA;IAC3E,oEAA+C,CAAA;IAC/C,kEAA6C,CAAA;IAC7C,sEAAiD,CAAA;IACjD,oFAA+D,CAAA;IAC/D,wEAAmD,CAAA;IACnD,4DAAuC,CAAA;AAC3C,CAAC,EAnBW,iBAAiB,KAAjB,iBAAiB,QAmB5B;AAED,MAAM,OAAO,aAAc,SAAQ,KAAK;IAC3B,IAAI,CAAoB;IAEjC,YAAY,IAAuB,EAAE,OAAe,EAAE,OAAsB;QACxE,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;QAC5B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;IACzD,CAAC;IAED,MAAM,CAAC,eAAe,CAAC,CAAU;QAC7B,OAAO,CAAC,YAAY,aAAa,CAAC;IACtC,CAAC;CACJ"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * AuthClient
3
+ *
4
+ * Runtime HTTP client that uses vault-stored secrets for Authorization.
5
+ * Handles fetchWithAuth and createFetchWithAuth. Vault only does storage.
6
+ */
7
+ import { Signer } from '../protocol/crypto.js';
8
+ import type { CbioVault } from '../vault/vault.js';
9
+ import type { ActivityLogEntry } from '../audit/ActivityLog.js';
10
+ export interface FetchWithAuthOptions extends RequestInit {
11
+ authPrefix?: string;
12
+ authHeaderName?: string;
13
+ withSignature?: boolean;
14
+ }
15
+ /**
16
+ * AuthClient uses vault's secrets for authenticated HTTP requests.
17
+ * Secret values never leave the vault; AuthClient reads via vault.getSecret.
18
+ */
19
+ export declare class AuthClient {
20
+ private readonly _vault;
21
+ private readonly _signer;
22
+ private readonly _appendActivityLog;
23
+ constructor(_vault: CbioVault, _signer: Signer | null, _appendActivityLog: (entry: ActivityLogEntry) => Promise<void>);
24
+ fetchWithAuth(secretName: string, url: string, options?: FetchWithAuthOptions): Promise<Response>;
25
+ createFetchWithAuth(secretName: string): (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
26
+ }
@@ -0,0 +1,132 @@
1
+ /**
2
+ * AuthClient
3
+ *
4
+ * Runtime HTTP client that uses vault-stored secrets for Authorization.
5
+ * Handles fetchWithAuth and createFetchWithAuth. Vault only does storage.
6
+ */
7
+ import { createHash } from 'node:crypto';
8
+ import { IdentityError, IdentityErrorCode } from '../errors.js';
9
+ async function hashRequestBody(body) {
10
+ if (body == null)
11
+ return '';
12
+ if (typeof body === 'string') {
13
+ return createHash('sha256').update(body).digest('hex');
14
+ }
15
+ if (body instanceof URLSearchParams) {
16
+ return createHash('sha256').update(body.toString()).digest('hex');
17
+ }
18
+ if (body instanceof ArrayBuffer) {
19
+ return createHash('sha256').update(Buffer.from(body)).digest('hex');
20
+ }
21
+ if (ArrayBuffer.isView(body)) {
22
+ return createHash('sha256')
23
+ .update(Buffer.from(body.buffer, body.byteOffset, body.byteLength))
24
+ .digest('hex');
25
+ }
26
+ if (typeof Blob !== 'undefined' && body instanceof Blob) {
27
+ const bytes = Buffer.from(await body.arrayBuffer());
28
+ return createHash('sha256').update(bytes).digest('hex');
29
+ }
30
+ throw new IdentityError(IdentityErrorCode.UNSUPPORTED_SIGNED_BODY, 'withSignature only supports string, URLSearchParams, Blob, ArrayBuffer, and typed array request bodies.');
31
+ }
32
+ /**
33
+ * AuthClient uses vault's secrets for authenticated HTTP requests.
34
+ * Secret values never leave the vault; AuthClient reads via vault.getSecret.
35
+ */
36
+ export class AuthClient {
37
+ _vault;
38
+ _signer;
39
+ _appendActivityLog;
40
+ constructor(_vault, _signer, _appendActivityLog) {
41
+ this._vault = _vault;
42
+ this._signer = _signer;
43
+ this._appendActivityLog = _appendActivityLog;
44
+ }
45
+ async fetchWithAuth(secretName, url, options = {}) {
46
+ const method = options.method ?? 'GET';
47
+ const appendFailure = async (error) => {
48
+ await this._appendActivityLog({
49
+ ts: Date.now(),
50
+ action: 'fetchWithAuth',
51
+ secretName,
52
+ url,
53
+ method,
54
+ success: false,
55
+ error,
56
+ });
57
+ };
58
+ const secretValue = this._vault.getSecret(secretName);
59
+ if (!secretValue) {
60
+ try {
61
+ await appendFailure(`Secret name '${secretName}' not found in vault.`);
62
+ }
63
+ catch (appendErr) {
64
+ throw new IdentityError(IdentityErrorCode.SECRET_NOT_FOUND, `Secret name '${secretName}' not found in vault.`, { cause: appendErr });
65
+ }
66
+ throw new IdentityError(IdentityErrorCode.SECRET_NOT_FOUND, `Secret name '${secretName}' not found in vault.`);
67
+ }
68
+ const { authPrefix = 'Bearer ', authHeaderName = 'Authorization', withSignature = false, ...fetchOptions } = options;
69
+ const headers = new Headers(fetchOptions.headers || {});
70
+ headers.set(authHeaderName, `${authPrefix}${secretValue}`);
71
+ if (withSignature && this._signer) {
72
+ const timestamp = Date.now().toString();
73
+ const methodUpper = (fetchOptions.method ?? 'GET').toUpperCase();
74
+ const bodyHash = await hashRequestBody(fetchOptions.body);
75
+ const message = `${methodUpper}:${url}:${timestamp}:${bodyHash}`;
76
+ const signature = await this._signer.sign(message);
77
+ headers.set('X-CBIO-Signature', signature);
78
+ headers.set('X-CBIO-Timestamp', timestamp);
79
+ }
80
+ try {
81
+ const response = await fetch(url, {
82
+ ...fetchOptions,
83
+ headers
84
+ });
85
+ await this._appendActivityLog({
86
+ ts: Date.now(),
87
+ action: 'fetchWithAuth',
88
+ secretName,
89
+ url,
90
+ method,
91
+ success: true,
92
+ });
93
+ return response;
94
+ }
95
+ catch (e) {
96
+ try {
97
+ await appendFailure(e.message ?? String(e));
98
+ }
99
+ catch (appendErr) {
100
+ const msg = e.message ?? String(e);
101
+ if (IdentityError.isIdentityError(e)) {
102
+ throw new IdentityError(e.code, msg, { cause: appendErr });
103
+ }
104
+ throw new Error(msg, { cause: appendErr });
105
+ }
106
+ throw e;
107
+ }
108
+ }
109
+ createFetchWithAuth(secretName) {
110
+ const self = this;
111
+ return async function (input, init) {
112
+ let url;
113
+ let options = {};
114
+ if (typeof input === 'string') {
115
+ url = input;
116
+ }
117
+ else if (input instanceof URL) {
118
+ url = input.toString();
119
+ }
120
+ else {
121
+ const req = input.clone();
122
+ url = req.url;
123
+ options = { method: req.method, headers: req.headers, body: req.body };
124
+ }
125
+ if (init) {
126
+ options = { ...options, ...init };
127
+ }
128
+ return self.fetchWithAuth(secretName, url, options);
129
+ };
130
+ }
131
+ }
132
+ //# sourceMappingURL=authClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authClient.js","sourceRoot":"","sources":["../../src/http/authClient.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAUhE,KAAK,UAAU,eAAe,CAAC,IAAiC;IAC5D,IAAI,IAAI,IAAI,IAAI;QAAE,OAAO,EAAE,CAAC;IAC5B,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC3B,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC3D,CAAC;IACD,IAAI,IAAI,YAAY,eAAe,EAAE,CAAC;QAClC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACtE,CAAC;IACD,IAAI,IAAI,YAAY,WAAW,EAAE,CAAC;QAC9B,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACxE,CAAC;IACD,IAAI,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,OAAO,UAAU,CAAC,QAAQ,CAAC;aACtB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;aAClE,MAAM,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;IACD,IAAI,OAAO,IAAI,KAAK,WAAW,IAAI,IAAI,YAAY,IAAI,EAAE,CAAC;QACtD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;QACpD,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC5D,CAAC;IAED,MAAM,IAAI,aAAa,CACnB,iBAAiB,CAAC,uBAAuB,EACzC,yGAAyG,CAC5G,CAAC;AACN,CAAC;AAED;;;GAGG;AACH,MAAM,OAAO,UAAU;IAEE;IACA;IACA;IAHrB,YACqB,MAAiB,EACjB,OAAsB,EACtB,kBAA8D;QAF9D,WAAM,GAAN,MAAM,CAAW;QACjB,YAAO,GAAP,OAAO,CAAe;QACtB,uBAAkB,GAAlB,kBAAkB,CAA4C;IAChF,CAAC;IAEJ,KAAK,CAAC,aAAa,CAAC,UAAkB,EAAE,GAAW,EAAE,UAAgC,EAAE;QACnF,MAAM,MAAM,GAAI,OAAO,CAAC,MAAiB,IAAI,KAAK,CAAC;QACnD,MAAM,aAAa,GAAG,KAAK,EAAE,KAAa,EAAiB,EAAE;YACzD,MAAM,IAAI,CAAC,kBAAkB,CAAC;gBAC1B,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;gBACd,MAAM,EAAE,eAAe;gBACvB,UAAU;gBACV,GAAG;gBACH,MAAM;gBACN,OAAO,EAAE,KAAK;gBACd,KAAK;aACR,CAAC,CAAC;QACP,CAAC,CAAC;QAEF,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QACtD,IAAI,CAAC,WAAW,EAAE,CAAC;YACf,IAAI,CAAC;gBACD,MAAM,aAAa,CAAC,gBAAgB,UAAU,uBAAuB,CAAC,CAAC;YAC3E,CAAC;YAAC,OAAO,SAAS,EAAE,CAAC;gBACjB,MAAM,IAAI,aAAa,CACnB,iBAAiB,CAAC,gBAAgB,EAClC,gBAAgB,UAAU,uBAAuB,EACjD,EAAE,KAAK,EAAE,SAAS,EAAE,CACvB,CAAC;YACN,CAAC;YACD,MAAM,IAAI,aAAa,CAAC,iBAAiB,CAAC,gBAAgB,EAAE,gBAAgB,UAAU,uBAAuB,CAAC,CAAC;QACnH,CAAC;QAED,MAAM,EAAE,UAAU,GAAG,SAAS,EAAE,cAAc,GAAG,eAAe,EAAE,aAAa,GAAG,KAAK,EAAE,GAAG,YAAY,EAAE,GAAG,OAAO,CAAC;QACrH,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,YAAY,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;QACxD,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,GAAG,UAAU,GAAG,WAAW,EAAE,CAAC,CAAC;QAE3D,IAAI,aAAa,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAChC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC;YACxC,MAAM,WAAW,GAAG,CAAC,YAAY,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;YACjE,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;YAE1D,MAAM,OAAO,GAAG,GAAG,WAAW,IAAI,GAAG,IAAI,SAAS,IAAI,QAAQ,EAAE,CAAC;YACjE,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACnD,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,SAAS,CAAC,CAAC;YAC3C,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,SAAS,CAAC,CAAC;QAC/C,CAAC;QAED,IAAI,CAAC;YACD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAC9B,GAAG,YAAY;gBACf,OAAO;aACV,CAAC,CAAC;YACH,MAAM,IAAI,CAAC,kBAAkB,CAAC;gBAC1B,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;gBACd,MAAM,EAAE,eAAe;gBACvB,UAAU;gBACV,GAAG;gBACH,MAAM;gBACN,OAAO,EAAE,IAAI;aAChB,CAAC,CAAC;YACH,OAAO,QAAQ,CAAC;QACpB,CAAC;QAAC,OAAO,CAAM,EAAE,CAAC;YACd,IAAI,CAAC;gBACD,MAAM,aAAa,CAAC,CAAC,CAAC,OAAO,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;YAChD,CAAC;YAAC,OAAO,SAAS,EAAE,CAAC;gBACjB,MAAM,GAAG,GAAG,CAAC,CAAC,OAAO,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;gBACnC,IAAI,aAAa,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;oBACnC,MAAM,IAAI,aAAa,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;gBAC/D,CAAC;gBACD,MAAM,IAAI,KAAK,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;YAC/C,CAAC;YACD,MAAM,CAAC,CAAC;QACZ,CAAC;IACL,CAAC;IAED,mBAAmB,CAAC,UAAkB;QAClC,MAAM,IAAI,GAAG,IAAI,CAAC;QAClB,OAAO,KAAK,WAAW,KAAwB,EAAE,IAAkB;YAC/D,IAAI,GAAW,CAAC;YAChB,IAAI,OAAO,GAAgB,EAAE,CAAC;YAC9B,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;gBAC5B,GAAG,GAAG,KAAK,CAAC;YAChB,CAAC;iBAAM,IAAI,KAAK,YAAY,GAAG,EAAE,CAAC;gBAC9B,GAAG,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;YAC3B,CAAC;iBAAM,CAAC;gBACJ,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC;gBAC1B,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC;gBACd,OAAO,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC;YAC3E,CAAC;YACD,IAAI,IAAI,EAAE,CAAC;gBACP,OAAO,GAAG,EAAE,GAAG,OAAO,EAAE,GAAG,IAAI,EAAE,CAAC;YACtC,CAAC;YACD,OAAO,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;QACxD,CAAC,CAAC;IACN,CAAC;CACJ"}
@@ -0,0 +1,33 @@
1
+ import type { FetchWithAuthOptions } from "./authClient.js";
2
+ export interface FetchWithAuthLike {
3
+ fetchWithAuth(secretName: string, url: string, options?: FetchWithAuthOptions): Promise<Response>;
4
+ }
5
+ /**
6
+ * Configuration for a local proxy that forwards requests to one upstream API
7
+ * while injecting a vault-backed secret into each outbound request.
8
+ */
9
+ export interface LocalAuthProxyOptions {
10
+ /** Trusted handle used to send authenticated requests upstream. */
11
+ authHandle: FetchWithAuthLike;
12
+ /** Vault secret name to inject into the outbound auth header. */
13
+ secretName: string;
14
+ /** Upstream API base URL, such as `https://api.openai.com`. */
15
+ upstreamBaseUrl: string;
16
+ /** HTTP header name for auth. Defaults to `Authorization`. */
17
+ authHeaderName?: string;
18
+ /** Prefix prepended before the secret value. Defaults to `Bearer `. */
19
+ authPrefix?: string;
20
+ /** Local bind host for the proxy server. Defaults to `127.0.0.1`. */
21
+ host?: string;
22
+ /** Local bind port. Defaults to `0` for an ephemeral port. */
23
+ port?: number;
24
+ }
25
+ export interface LocalAuthProxyHandle {
26
+ readonly secretName: string;
27
+ readonly upstreamBaseUrl: string;
28
+ readonly host: string;
29
+ readonly port: number;
30
+ readonly baseUrl: string;
31
+ close(): Promise<void>;
32
+ }
33
+ export declare function startLocalAuthProxy(options: LocalAuthProxyOptions): Promise<LocalAuthProxyHandle>;
@@ -0,0 +1,93 @@
1
+ import * as http from "node:http";
2
+ function normalizeProxyRequestHeaders(headers) {
3
+ const next = new Headers();
4
+ for (const [key, value] of Object.entries(headers)) {
5
+ if (value == null)
6
+ continue;
7
+ const lower = key.toLowerCase();
8
+ if (lower === "host" || lower === "content-length" || lower === "connection" || lower === "authorization") {
9
+ continue;
10
+ }
11
+ if (Array.isArray(value)) {
12
+ next.set(key, value.join(", "));
13
+ }
14
+ else {
15
+ next.set(key, value);
16
+ }
17
+ }
18
+ next.set("x-cbio-local-proxy", "1");
19
+ return next;
20
+ }
21
+ async function readRequestBody(req) {
22
+ const chunks = [];
23
+ for await (const chunk of req) {
24
+ chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
25
+ }
26
+ if (chunks.length === 0)
27
+ return undefined;
28
+ return Buffer.concat(chunks);
29
+ }
30
+ export async function startLocalAuthProxy(options) {
31
+ const { authHandle, secretName, upstreamBaseUrl, authHeaderName = "Authorization", authPrefix = "Bearer ", host = "127.0.0.1", port = 0, } = options;
32
+ const upstream = new URL(upstreamBaseUrl);
33
+ const server = http.createServer(async (req, res) => {
34
+ try {
35
+ const method = req.method ?? "GET";
36
+ const targetUrl = new URL(req.url ?? "/", upstream);
37
+ const headers = normalizeProxyRequestHeaders(req.headers);
38
+ const body = await readRequestBody(req);
39
+ const upstreamResponse = await authHandle.fetchWithAuth(secretName, targetUrl.toString(), {
40
+ method,
41
+ headers,
42
+ body: body ? new Uint8Array(body) : undefined,
43
+ authHeaderName,
44
+ authPrefix,
45
+ });
46
+ res.statusCode = upstreamResponse.status;
47
+ upstreamResponse.headers.forEach((value, key) => {
48
+ const lower = key.toLowerCase();
49
+ if (lower === "content-length" || lower === "transfer-encoding" || lower === "connection") {
50
+ return;
51
+ }
52
+ res.setHeader(key, value);
53
+ });
54
+ const responseBuffer = Buffer.from(await upstreamResponse.arrayBuffer());
55
+ res.end(responseBuffer);
56
+ }
57
+ catch (e) {
58
+ const message = e instanceof Error ? e.message : String(e);
59
+ res.statusCode = 502;
60
+ res.setHeader("Content-Type", "application/json");
61
+ res.end(JSON.stringify({
62
+ error: "CBIO_LOCAL_PROXY_UPSTREAM_FAILED",
63
+ message,
64
+ }));
65
+ }
66
+ });
67
+ await new Promise((resolve, reject) => {
68
+ server.once("error", reject);
69
+ server.listen(port, host, () => {
70
+ server.off("error", reject);
71
+ resolve();
72
+ });
73
+ });
74
+ const address = server.address();
75
+ if (!address || typeof address === "string") {
76
+ throw new Error("Failed to determine local proxy address.");
77
+ }
78
+ const resolvedAddress = address;
79
+ const baseUrl = `http://${host}:${resolvedAddress.port}`;
80
+ return {
81
+ secretName,
82
+ upstreamBaseUrl,
83
+ host,
84
+ port: resolvedAddress.port,
85
+ baseUrl,
86
+ close() {
87
+ return new Promise((resolve, reject) => {
88
+ server.close((err) => (err ? reject(err) : resolve()));
89
+ });
90
+ },
91
+ };
92
+ }
93
+ //# sourceMappingURL=localAuthProxy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"localAuthProxy.js","sourceRoot":"","sources":["../../src/http/localAuthProxy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * SecretAcquisition
3
+ *
4
+ * Fetches secrets from remote JSON endpoints and stores them in vault.
5
+ * Secret never leaves this module; fetch + extract + store is atomic.
6
+ */
7
+ import type { CbioVault } from '../vault/vault.js';
8
+ import type { ActivityLogEntry } from '../audit/ActivityLog.js';
9
+ interface FetchResultBase {
10
+ /** True when the operation succeeded/failed but activity log write failed. Caller gets FetchResult; audit trail may be incomplete. */
11
+ activityLogWriteFailed?: boolean;
12
+ }
13
+ export interface FetchSuccess<TData = unknown> extends FetchResultBase {
14
+ success: true;
15
+ data: TData;
16
+ secretName: string;
17
+ }
18
+ export interface FetchFailure extends FetchResultBase {
19
+ success: false;
20
+ error: string;
21
+ code?: string;
22
+ }
23
+ export type FetchResult<TData = unknown> = FetchSuccess<TData> | FetchFailure;
24
+ export interface FetchJsonAndAddSecretOptions<TResponse = unknown, TBody = unknown> {
25
+ secretName: string;
26
+ url: string;
27
+ method?: string;
28
+ headers?: Record<string, string>;
29
+ /** JSON-serializable request body. */
30
+ body?: TBody;
31
+ /** Extract the secret from a parsed JSON response body. */
32
+ extractKey: (response: TResponse) => string;
33
+ allowedOrigins?: string[];
34
+ }
35
+ export interface FetchJsonAndUpdateSecretOptions<TResponse = unknown, TBody = unknown> {
36
+ secretName: string;
37
+ url: string;
38
+ method?: string;
39
+ headers?: Record<string, string>;
40
+ /** JSON-serializable request body. */
41
+ body?: TBody;
42
+ /** Extract the rotated secret from a parsed JSON response body. */
43
+ extractKey: (response: TResponse) => string;
44
+ }
45
+ export declare class SecretAcquisition {
46
+ private readonly _vault;
47
+ private readonly _appendActivityLog;
48
+ constructor(_vault: CbioVault, _appendActivityLog: (entry: ActivityLogEntry) => Promise<void>);
49
+ hasSecret(secretName: string): boolean;
50
+ listSecretNames(): string[];
51
+ fetchJsonAndAddSecret<TResponse = unknown, TBody = unknown>(options: FetchJsonAndAddSecretOptions<TResponse, TBody>): Promise<FetchResult<TResponse>>;
52
+ fetchJsonAndUpdateSecret<TResponse = unknown, TBody = unknown>(options: FetchJsonAndUpdateSecretOptions<TResponse, TBody>): Promise<FetchResult<TResponse>>;
53
+ }
54
+ export {};