@aexhq/sdk 0.13.6

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 (112) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +160 -0
  3. package/dist/_contracts/connection-ticket.d.ts +21 -0
  4. package/dist/_contracts/connection-ticket.js +49 -0
  5. package/dist/_contracts/event-envelope.d.ts +276 -0
  6. package/dist/_contracts/event-envelope.js +324 -0
  7. package/dist/_contracts/event-stream-client.d.ts +47 -0
  8. package/dist/_contracts/event-stream-client.js +141 -0
  9. package/dist/_contracts/http.d.ts +35 -0
  10. package/dist/_contracts/http.js +114 -0
  11. package/dist/_contracts/index.d.ts +28 -0
  12. package/dist/_contracts/index.js +29 -0
  13. package/dist/_contracts/managed-key.d.ts +74 -0
  14. package/dist/_contracts/managed-key.js +110 -0
  15. package/dist/_contracts/operations.d.ts +237 -0
  16. package/dist/_contracts/operations.js +632 -0
  17. package/dist/_contracts/provider-support.d.ts +220 -0
  18. package/dist/_contracts/provider-support.js +90 -0
  19. package/dist/_contracts/proxy-protocol.d.ts +257 -0
  20. package/dist/_contracts/proxy-protocol.js +234 -0
  21. package/dist/_contracts/proxy-validation.d.ts +19 -0
  22. package/dist/_contracts/proxy-validation.js +51 -0
  23. package/dist/_contracts/run-artifacts.d.ts +47 -0
  24. package/dist/_contracts/run-artifacts.js +101 -0
  25. package/dist/_contracts/run-config.d.ts +304 -0
  26. package/dist/_contracts/run-config.js +659 -0
  27. package/dist/_contracts/run-cost.d.ts +125 -0
  28. package/dist/_contracts/run-cost.js +616 -0
  29. package/dist/_contracts/run-custody.d.ts +226 -0
  30. package/dist/_contracts/run-custody.js +465 -0
  31. package/dist/_contracts/run-record.d.ts +127 -0
  32. package/dist/_contracts/run-record.js +177 -0
  33. package/dist/_contracts/run-retention.d.ts +213 -0
  34. package/dist/_contracts/run-retention.js +484 -0
  35. package/dist/_contracts/run-unit.d.ts +194 -0
  36. package/dist/_contracts/run-unit.js +215 -0
  37. package/dist/_contracts/runner-event.d.ts +114 -0
  38. package/dist/_contracts/runner-event.js +187 -0
  39. package/dist/_contracts/runtime-manifest.d.ts +106 -0
  40. package/dist/_contracts/runtime-manifest.js +98 -0
  41. package/dist/_contracts/runtime-security-profile.d.ts +27 -0
  42. package/dist/_contracts/runtime-security-profile.js +82 -0
  43. package/dist/_contracts/runtime-sizes.d.ts +144 -0
  44. package/dist/_contracts/runtime-sizes.js +136 -0
  45. package/dist/_contracts/runtime-types.d.ts +212 -0
  46. package/dist/_contracts/runtime-types.js +2 -0
  47. package/dist/_contracts/sdk-errors.d.ts +34 -0
  48. package/dist/_contracts/sdk-errors.js +52 -0
  49. package/dist/_contracts/sdk-secrets.d.ts +31 -0
  50. package/dist/_contracts/sdk-secrets.js +220 -0
  51. package/dist/_contracts/side-effect-audit.d.ts +129 -0
  52. package/dist/_contracts/side-effect-audit.js +494 -0
  53. package/dist/_contracts/sse.d.ts +74 -0
  54. package/dist/_contracts/sse.js +0 -0
  55. package/dist/_contracts/stable.d.ts +26 -0
  56. package/dist/_contracts/stable.js +44 -0
  57. package/dist/_contracts/status.d.ts +19 -0
  58. package/dist/_contracts/status.js +61 -0
  59. package/dist/_contracts/submission.d.ts +383 -0
  60. package/dist/_contracts/submission.js +1380 -0
  61. package/dist/agents-md.d.ts +46 -0
  62. package/dist/agents-md.js +83 -0
  63. package/dist/agents-md.js.map +1 -0
  64. package/dist/asset-upload.d.ts +66 -0
  65. package/dist/asset-upload.js +168 -0
  66. package/dist/asset-upload.js.map +1 -0
  67. package/dist/bundle.d.ts +33 -0
  68. package/dist/bundle.js +89 -0
  69. package/dist/bundle.js.map +1 -0
  70. package/dist/cli.mjs +4140 -0
  71. package/dist/cli.mjs.sha256 +1 -0
  72. package/dist/client.d.ts +460 -0
  73. package/dist/client.js +857 -0
  74. package/dist/client.js.map +1 -0
  75. package/dist/fetch-archive.d.ts +16 -0
  76. package/dist/fetch-archive.js +170 -0
  77. package/dist/fetch-archive.js.map +1 -0
  78. package/dist/file.d.ts +57 -0
  79. package/dist/file.js +153 -0
  80. package/dist/file.js.map +1 -0
  81. package/dist/index.d.ts +30 -0
  82. package/dist/index.js +34 -0
  83. package/dist/index.js.map +1 -0
  84. package/dist/mcp-server.d.ts +84 -0
  85. package/dist/mcp-server.js +114 -0
  86. package/dist/mcp-server.js.map +1 -0
  87. package/dist/node-fs.d.ts +12 -0
  88. package/dist/node-fs.js +44 -0
  89. package/dist/node-fs.js.map +1 -0
  90. package/dist/proxy-endpoint.d.ts +131 -0
  91. package/dist/proxy-endpoint.js +147 -0
  92. package/dist/proxy-endpoint.js.map +1 -0
  93. package/dist/skill.d.ts +117 -0
  94. package/dist/skill.js +169 -0
  95. package/dist/skill.js.map +1 -0
  96. package/dist/version.d.ts +9 -0
  97. package/dist/version.js +10 -0
  98. package/dist/version.js.map +1 -0
  99. package/docs/cleanup.md +38 -0
  100. package/docs/credentials.md +153 -0
  101. package/docs/events.md +76 -0
  102. package/docs/mcp.md +47 -0
  103. package/docs/outputs.md +157 -0
  104. package/docs/product-boundaries.md +57 -0
  105. package/docs/provider-runtime-capabilities.md +103 -0
  106. package/docs/quickstart.md +110 -0
  107. package/docs/release.md +99 -0
  108. package/docs/run-config.md +53 -0
  109. package/docs/run-record.md +39 -0
  110. package/docs/skills.md +139 -0
  111. package/docs/testing.md +29 -0
  112. package/package.json +47 -0
@@ -0,0 +1,226 @@
1
+ import type { CredentialMode } from "./managed-key.js";
2
+ import type { RunStatus } from "./status.js";
3
+ import type { RunProvider, RuntimeKind } from "./submission.js";
4
+ export declare const CUSTODY_MANIFEST_SCHEMA_VERSION = 1;
5
+ export declare const CUSTODY_TOMBSTONE_SCHEMA_VERSION = 1;
6
+ export declare const CUSTODY_REDACTION_SCANNER_VERSION = 1;
7
+ export declare const CUSTODY_MANIFEST_KIND = "aex.custody_manifest.v1";
8
+ export declare const CUSTODY_TOMBSTONE_KIND = "aex.custody_tombstone.v1";
9
+ export declare const CUSTODY_MANIFEST_CONTENT_TYPE = "application/json; charset=utf-8";
10
+ export declare const CUSTODY_MANIFEST_RUN_REL_PATH = "metadata/custody.json";
11
+ export declare const CUSTODY_SECRET_CLASSES: readonly ["provider_api_key", "mcp_credential", "proxy_endpoint_auth", "runner_bearer", "managed_system_credential"];
12
+ export type CustodySecretClass = (typeof CUSTODY_SECRET_CLASSES)[number];
13
+ export declare const CUSTODY_RESOURCE_CLASSES: readonly ["runtime_machine", "native_provider_session", "native_provider_resource", "provider_asset", "proxy_token", "execution_secret", "event_archive", "run_output", "run_log", "run_asset"];
14
+ export type CustodyResourceClass = (typeof CUSTODY_RESOURCE_CLASSES)[number];
15
+ export declare const CUSTODY_EXPOSURE_SURFACES: readonly ["aex_vault", "aex_kv", "fly_machine_env", "fly_machine_file", "provider_vault", "provider_session", "dashboard_proxy", "api_provider_proxy", "api_mcp_proxy", "run_artifact_store", "coordinator_event_archive"];
16
+ export type CustodyExposureSurface = (typeof CUSTODY_EXPOSURE_SURFACES)[number];
17
+ export declare const CUSTODY_EXPOSURE_ACCESS_KINDS: readonly ["stored", "injected", "proxied", "replicated", "observed", "unknown"];
18
+ export type CustodyExposureAccessKind = (typeof CUSTODY_EXPOSURE_ACCESS_KINDS)[number];
19
+ export declare const CUSTODY_EXPOSURE_STATUSES: readonly ["exposed", "revoked", "retained", "failed", "not_applicable"];
20
+ export type CustodyExposureStatus = (typeof CUSTODY_EXPOSURE_STATUSES)[number];
21
+ export declare const CUSTODY_DISPOSITION_STATUSES: readonly ["destroyed", "revoked", "not_found", "provider_delete_confirmed", "retained_by_policy", "cleanup_failed", "parked_for_operator", "pending", "not_applicable"];
22
+ export type CustodyDispositionStatus = (typeof CUSTODY_DISPOSITION_STATUSES)[number];
23
+ export declare const CUSTODY_CLEANUP_STATUSES: readonly ["succeeded", "partial", "failed", "retained", "pending"];
24
+ export type CustodyCleanupStatus = (typeof CUSTODY_CLEANUP_STATUSES)[number];
25
+ export declare const CUSTODY_EVIDENCE_SOURCES: readonly ["run_row", "runtime_manifest", "terminal_event", "cleanup_step", "output_capture", "proxy_audit", "provider_cleanup_summary"];
26
+ export type CustodyEvidenceSource = (typeof CUSTODY_EVIDENCE_SOURCES)[number];
27
+ export declare const CUSTODY_MANIFEST_EXCLUDED_VALUE_CLASSES: readonly ["raw_secret_values", "bearer_hashes", "provider_response_bodies", "signed_urls", "r2_object_keys", "vault_ids", "private_resource_handles"];
28
+ export type CustodyManifestExcludedValueClass = (typeof CUSTODY_MANIFEST_EXCLUDED_VALUE_CLASSES)[number];
29
+ export declare const CUSTODY_TOMBSTONE_MANIFEST_STATUSES: readonly ["written", "not_written", "write_failed", "purged"];
30
+ export type CustodyTombstoneManifestStatus = (typeof CUSTODY_TOMBSTONE_MANIFEST_STATUSES)[number];
31
+ export declare const CUSTODY_TOMBSTONE_DELETION_STATUSES: readonly ["not_deleted", "pending_delete", "deleted"];
32
+ export type CustodyTombstoneDeletionStatus = (typeof CUSTODY_TOMBSTONE_DELETION_STATUSES)[number];
33
+ export interface CustodyManifestRunV1 {
34
+ readonly runId: string;
35
+ readonly workspaceId: string;
36
+ readonly provider: RunProvider | string;
37
+ readonly runtime: RuntimeKind | string;
38
+ readonly terminalStatus: RunStatus | string;
39
+ readonly credentialMode?: CredentialMode;
40
+ readonly createdAt?: string;
41
+ readonly terminalAt?: string;
42
+ }
43
+ export interface CustodyManifestExposureV1 {
44
+ readonly surface: CustodyExposureSurface | string;
45
+ readonly access: CustodyExposureAccessKind;
46
+ readonly status?: CustodyExposureStatus;
47
+ readonly count?: number;
48
+ readonly firstExposedAt?: string;
49
+ readonly lastExposedAt?: string;
50
+ readonly revokedAt?: string;
51
+ }
52
+ export interface CustodyManifestDispositionV1 {
53
+ readonly status: CustodyDispositionStatus;
54
+ readonly reason?: string;
55
+ readonly decidedAt?: string;
56
+ readonly errorClass?: string;
57
+ readonly followUpRequired?: boolean;
58
+ }
59
+ export interface CustodyManifestEvidenceSummaryV1 {
60
+ readonly source: CustodyEvidenceSource | string;
61
+ readonly status?: string;
62
+ readonly observedAt?: string;
63
+ readonly count?: number;
64
+ readonly errorClass?: string;
65
+ }
66
+ export interface CustodyManifestSecretClassV1 {
67
+ readonly class: CustodySecretClass | string;
68
+ readonly present: boolean;
69
+ readonly count: number;
70
+ readonly exposures: readonly CustodyManifestExposureV1[];
71
+ readonly disposition: CustodyManifestDispositionV1;
72
+ readonly evidence?: readonly CustodyManifestEvidenceSummaryV1[];
73
+ }
74
+ export interface CustodyManifestResourceClassV1 {
75
+ readonly class: CustodyResourceClass | string;
76
+ readonly count: number;
77
+ readonly exposures: readonly CustodyManifestExposureV1[];
78
+ readonly disposition: CustodyManifestDispositionV1;
79
+ readonly evidence?: readonly CustodyManifestEvidenceSummaryV1[];
80
+ }
81
+ export interface CustodyManifestCleanupV1 {
82
+ readonly status: CustodyCleanupStatus;
83
+ readonly startedAt?: string;
84
+ readonly finishedAt?: string;
85
+ readonly errorClass?: string;
86
+ readonly followUpRequiredCount?: number;
87
+ }
88
+ export interface CustodyManifestSummaryV1 {
89
+ readonly secretClassCount: number;
90
+ readonly secretInstanceCount: number;
91
+ readonly resourceClassCount: number;
92
+ readonly resourceInstanceCount: number;
93
+ readonly exposureCount: number;
94
+ readonly revokedExposureCount: number;
95
+ readonly retainedCount: number;
96
+ readonly cleanupFailedCount: number;
97
+ readonly parkedForOperatorCount: number;
98
+ readonly pendingCount: number;
99
+ readonly followUpRequiredCount: number;
100
+ readonly dispositionCounts: Readonly<Partial<Record<CustodyDispositionStatus, number>>>;
101
+ }
102
+ export interface CustodyManifestRedactionV1 {
103
+ readonly policy: "metadata_only";
104
+ readonly scannerVersion: typeof CUSTODY_REDACTION_SCANNER_VERSION;
105
+ readonly excludes: readonly CustodyManifestExcludedValueClass[];
106
+ }
107
+ export interface CustodyManifestV1 {
108
+ readonly schemaVersion: typeof CUSTODY_MANIFEST_SCHEMA_VERSION;
109
+ readonly kind: typeof CUSTODY_MANIFEST_KIND;
110
+ readonly generatedAt: string;
111
+ readonly finalizedAt?: string;
112
+ readonly run: CustodyManifestRunV1;
113
+ readonly secrets: readonly CustodyManifestSecretClassV1[];
114
+ readonly resources: readonly CustodyManifestResourceClassV1[];
115
+ readonly cleanup: CustodyManifestCleanupV1;
116
+ readonly summary: CustodyManifestSummaryV1;
117
+ readonly redaction: CustodyManifestRedactionV1;
118
+ }
119
+ export type CustodyManifestRunInput = CustodyManifestRunV1;
120
+ export type CustodyManifestExposureInput = CustodyManifestExposureV1;
121
+ export type CustodyManifestDispositionInput = CustodyManifestDispositionV1;
122
+ export type CustodyManifestEvidenceSummaryInput = CustodyManifestEvidenceSummaryV1;
123
+ export type CustodyManifestCleanupInput = CustodyManifestCleanupV1;
124
+ export interface CustodyManifestSecretClassInput extends Omit<CustodyManifestSecretClassV1, "count" | "exposures"> {
125
+ readonly count?: number;
126
+ readonly exposures?: readonly CustodyManifestExposureInput[];
127
+ }
128
+ export interface CustodyManifestResourceClassInput extends Omit<CustodyManifestResourceClassV1, "count" | "exposures"> {
129
+ readonly count?: number;
130
+ readonly exposures?: readonly CustodyManifestExposureInput[];
131
+ }
132
+ export interface CustodyManifestInput {
133
+ readonly generatedAt: string;
134
+ readonly finalizedAt?: string;
135
+ readonly run: CustodyManifestRunInput;
136
+ readonly secrets?: readonly CustodyManifestSecretClassInput[];
137
+ readonly resources?: readonly CustodyManifestResourceClassInput[];
138
+ readonly cleanup?: CustodyManifestCleanupInput;
139
+ }
140
+ export interface CustodyTombstoneRunV1 {
141
+ readonly runId: string;
142
+ readonly workspaceId: string;
143
+ readonly terminalStatus: RunStatus | string;
144
+ readonly terminalAt?: string;
145
+ }
146
+ export interface CustodyTombstoneManifestV1 {
147
+ readonly schemaVersion: typeof CUSTODY_MANIFEST_SCHEMA_VERSION;
148
+ readonly status: CustodyTombstoneManifestStatus;
149
+ readonly generatedAt?: string;
150
+ readonly finalizedAt?: string;
151
+ readonly tombstonedAt: string;
152
+ }
153
+ export interface CustodyTombstoneDeletionV1 {
154
+ readonly status: CustodyTombstoneDeletionStatus;
155
+ readonly pendingAt?: string;
156
+ readonly deletedAt?: string;
157
+ }
158
+ export interface CustodyTombstoneRetentionV1 {
159
+ readonly defaultPolicy: "retain_indefinitely";
160
+ readonly userAction: "purge_or_anonymize_later";
161
+ }
162
+ export interface CustodyTombstoneV1 {
163
+ readonly schemaVersion: typeof CUSTODY_TOMBSTONE_SCHEMA_VERSION;
164
+ readonly kind: typeof CUSTODY_TOMBSTONE_KIND;
165
+ readonly run: CustodyTombstoneRunV1;
166
+ readonly manifest: CustodyTombstoneManifestV1;
167
+ readonly summary: CustodyManifestSummaryV1;
168
+ readonly deletion: CustodyTombstoneDeletionV1;
169
+ readonly retention: CustodyTombstoneRetentionV1;
170
+ }
171
+ export interface CustodyTombstoneInput {
172
+ readonly run: CustodyTombstoneRunV1;
173
+ readonly manifest: Omit<CustodyTombstoneManifestV1, "schemaVersion">;
174
+ readonly summary: CustodyManifestSummaryV1;
175
+ readonly deletion?: CustodyTombstoneDeletionV1;
176
+ }
177
+ export interface CustodyTombstoneFromManifestInput {
178
+ readonly manifestStatus?: CustodyTombstoneManifestStatus;
179
+ readonly tombstonedAt: string;
180
+ readonly deletion?: CustodyTombstoneDeletionV1;
181
+ }
182
+ export interface CustodyManifestWriteObject {
183
+ readonly key: string;
184
+ readonly contentType: typeof CUSTODY_MANIFEST_CONTENT_TYPE;
185
+ readonly manifest: CustodyManifestV1;
186
+ }
187
+ export interface CustodyManifestObjectStore {
188
+ putCustodyManifestObject(object: CustodyManifestWriteObject): Promise<void>;
189
+ }
190
+ export interface CustodyManifestWriteResult {
191
+ readonly status: "written";
192
+ readonly schemaVersion: typeof CUSTODY_MANIFEST_SCHEMA_VERSION;
193
+ readonly runId: string;
194
+ readonly workspaceId: string;
195
+ readonly key: string;
196
+ readonly writtenAt: string;
197
+ }
198
+ export interface CustodyManifestWriter {
199
+ writeCustodyManifest(input: CustodyManifestInput): Promise<CustodyManifestWriteResult>;
200
+ }
201
+ export type CustodyRedactionReason = "forbidden_field_name" | "bearer_token" | "provider_key" | "signed_url" | "r2_object_key" | "vault_id" | "private_resource_handle" | "high_entropy_token";
202
+ export interface CustodyRedactionFinding {
203
+ readonly path: string;
204
+ readonly reason: CustodyRedactionReason;
205
+ readonly valueLength?: number;
206
+ }
207
+ export declare class CustodyManifestRedactionError extends Error {
208
+ readonly code = "custody_manifest_not_public_safe";
209
+ readonly findings: readonly CustodyRedactionFinding[];
210
+ constructor(findings: readonly CustodyRedactionFinding[]);
211
+ }
212
+ export declare class FakeCustodyManifestObjectStore implements CustodyManifestObjectStore {
213
+ #private;
214
+ putCustodyManifestObject(object: CustodyManifestWriteObject): Promise<void>;
215
+ getByRunId(runId: string): CustodyManifestV1 | undefined;
216
+ get(key: string): CustodyManifestV1 | undefined;
217
+ listKeys(): readonly string[];
218
+ }
219
+ export declare function custodyManifestObjectKey(runId: string): string;
220
+ export declare function createCustodyManifestWriter(store: CustodyManifestObjectStore): CustodyManifestWriter;
221
+ export declare function writeCustodyManifest(store: CustodyManifestObjectStore, input: CustodyManifestInput): Promise<CustodyManifestWriteResult>;
222
+ export declare function buildCustodyManifest(input: CustodyManifestInput): CustodyManifestV1;
223
+ export declare function buildCustodyTombstone(input: CustodyTombstoneInput): CustodyTombstoneV1;
224
+ export declare function buildCustodyTombstoneFromManifest(manifest: CustodyManifestV1, input: CustodyTombstoneFromManifestInput): CustodyTombstoneV1;
225
+ export declare function scanCustodyPayloadForSensitiveValues(input: unknown): readonly CustodyRedactionFinding[];
226
+ export declare function assertPublicSafeCustodyPayload(input: unknown): void;
@@ -0,0 +1,465 @@
1
+ export const CUSTODY_MANIFEST_SCHEMA_VERSION = 1;
2
+ export const CUSTODY_TOMBSTONE_SCHEMA_VERSION = 1;
3
+ export const CUSTODY_REDACTION_SCANNER_VERSION = 1;
4
+ export const CUSTODY_MANIFEST_KIND = "aex.custody_manifest.v1";
5
+ export const CUSTODY_TOMBSTONE_KIND = "aex.custody_tombstone.v1";
6
+ export const CUSTODY_MANIFEST_CONTENT_TYPE = "application/json; charset=utf-8";
7
+ export const CUSTODY_MANIFEST_RUN_REL_PATH = "metadata/custody.json";
8
+ export const CUSTODY_SECRET_CLASSES = [
9
+ "provider_api_key",
10
+ "mcp_credential",
11
+ "proxy_endpoint_auth",
12
+ "runner_bearer",
13
+ "managed_system_credential"
14
+ ];
15
+ export const CUSTODY_RESOURCE_CLASSES = [
16
+ "runtime_machine",
17
+ "native_provider_session",
18
+ "native_provider_resource",
19
+ "provider_asset",
20
+ "proxy_token",
21
+ "execution_secret",
22
+ "event_archive",
23
+ "run_output",
24
+ "run_log",
25
+ "run_asset"
26
+ ];
27
+ export const CUSTODY_EXPOSURE_SURFACES = [
28
+ "aex_vault",
29
+ "aex_kv",
30
+ "fly_machine_env",
31
+ "fly_machine_file",
32
+ "provider_vault",
33
+ "provider_session",
34
+ "dashboard_proxy",
35
+ "api_provider_proxy",
36
+ "api_mcp_proxy",
37
+ "run_artifact_store",
38
+ "coordinator_event_archive"
39
+ ];
40
+ export const CUSTODY_EXPOSURE_ACCESS_KINDS = [
41
+ "stored",
42
+ "injected",
43
+ "proxied",
44
+ "replicated",
45
+ "observed",
46
+ "unknown"
47
+ ];
48
+ export const CUSTODY_EXPOSURE_STATUSES = [
49
+ "exposed",
50
+ "revoked",
51
+ "retained",
52
+ "failed",
53
+ "not_applicable"
54
+ ];
55
+ export const CUSTODY_DISPOSITION_STATUSES = [
56
+ "destroyed",
57
+ "revoked",
58
+ "not_found",
59
+ "provider_delete_confirmed",
60
+ "retained_by_policy",
61
+ "cleanup_failed",
62
+ "parked_for_operator",
63
+ "pending",
64
+ "not_applicable"
65
+ ];
66
+ export const CUSTODY_CLEANUP_STATUSES = [
67
+ "succeeded",
68
+ "partial",
69
+ "failed",
70
+ "retained",
71
+ "pending"
72
+ ];
73
+ export const CUSTODY_EVIDENCE_SOURCES = [
74
+ "run_row",
75
+ "runtime_manifest",
76
+ "terminal_event",
77
+ "cleanup_step",
78
+ "output_capture",
79
+ "proxy_audit",
80
+ "provider_cleanup_summary"
81
+ ];
82
+ export const CUSTODY_MANIFEST_EXCLUDED_VALUE_CLASSES = [
83
+ "raw_secret_values",
84
+ "bearer_hashes",
85
+ "provider_response_bodies",
86
+ "signed_urls",
87
+ "r2_object_keys",
88
+ "vault_ids",
89
+ "private_resource_handles"
90
+ ];
91
+ export const CUSTODY_TOMBSTONE_MANIFEST_STATUSES = [
92
+ "written",
93
+ "not_written",
94
+ "write_failed",
95
+ "purged"
96
+ ];
97
+ export const CUSTODY_TOMBSTONE_DELETION_STATUSES = [
98
+ "not_deleted",
99
+ "pending_delete",
100
+ "deleted"
101
+ ];
102
+ export class CustodyManifestRedactionError extends Error {
103
+ code = "custody_manifest_not_public_safe";
104
+ findings;
105
+ constructor(findings) {
106
+ super(`custody manifest contains non-public custody data at ${formatFindingPaths(findings)}`);
107
+ this.name = "CustodyManifestRedactionError";
108
+ this.findings = Object.freeze([...findings]);
109
+ }
110
+ }
111
+ export class FakeCustodyManifestObjectStore {
112
+ #objects = new Map();
113
+ async putCustodyManifestObject(object) {
114
+ assertPublicSafeCustodyPayload(object.manifest);
115
+ this.#objects.set(object.key, cloneJson(object.manifest));
116
+ }
117
+ getByRunId(runId) {
118
+ return this.get(custodyManifestObjectKey(runId));
119
+ }
120
+ get(key) {
121
+ const object = this.#objects.get(key);
122
+ return object ? cloneJson(object) : undefined;
123
+ }
124
+ listKeys() {
125
+ return Object.freeze([...this.#objects.keys()].sort());
126
+ }
127
+ }
128
+ export function custodyManifestObjectKey(runId) {
129
+ assertSafeIdentifier(runId, "runId");
130
+ return `runs/${runId}/${CUSTODY_MANIFEST_RUN_REL_PATH}`;
131
+ }
132
+ export function createCustodyManifestWriter(store) {
133
+ return {
134
+ async writeCustodyManifest(input) {
135
+ return writeCustodyManifest(store, input);
136
+ }
137
+ };
138
+ }
139
+ export async function writeCustodyManifest(store, input) {
140
+ const manifest = buildCustodyManifest(input);
141
+ const key = custodyManifestObjectKey(manifest.run.runId);
142
+ await store.putCustodyManifestObject({
143
+ key,
144
+ contentType: CUSTODY_MANIFEST_CONTENT_TYPE,
145
+ manifest
146
+ });
147
+ return Object.freeze({
148
+ status: "written",
149
+ schemaVersion: CUSTODY_MANIFEST_SCHEMA_VERSION,
150
+ runId: manifest.run.runId,
151
+ workspaceId: manifest.run.workspaceId,
152
+ key,
153
+ writtenAt: manifest.finalizedAt ?? manifest.generatedAt
154
+ });
155
+ }
156
+ export function buildCustodyManifest(input) {
157
+ const secrets = Object.freeze((input.secrets ?? []).map(normalizeSecretClass));
158
+ const resources = Object.freeze((input.resources ?? []).map(normalizeResourceClass));
159
+ const cleanup = normalizeCleanup(input.cleanup);
160
+ const manifest = Object.freeze({
161
+ schemaVersion: CUSTODY_MANIFEST_SCHEMA_VERSION,
162
+ kind: CUSTODY_MANIFEST_KIND,
163
+ generatedAt: assertTimestamp(input.generatedAt, "generatedAt"),
164
+ ...(input.finalizedAt ? { finalizedAt: assertTimestamp(input.finalizedAt, "finalizedAt") } : {}),
165
+ run: normalizeRun(input.run),
166
+ secrets,
167
+ resources,
168
+ cleanup,
169
+ summary: buildCustodySummary(secrets, resources, cleanup),
170
+ redaction: Object.freeze({
171
+ policy: "metadata_only",
172
+ scannerVersion: CUSTODY_REDACTION_SCANNER_VERSION,
173
+ excludes: Object.freeze([...CUSTODY_MANIFEST_EXCLUDED_VALUE_CLASSES])
174
+ })
175
+ });
176
+ assertPublicSafeCustodyPayload(manifest);
177
+ return manifest;
178
+ }
179
+ export function buildCustodyTombstone(input) {
180
+ const tombstone = Object.freeze({
181
+ schemaVersion: CUSTODY_TOMBSTONE_SCHEMA_VERSION,
182
+ kind: CUSTODY_TOMBSTONE_KIND,
183
+ run: normalizeTombstoneRun(input.run),
184
+ manifest: normalizeTombstoneManifest(input.manifest),
185
+ summary: normalizeSummary(input.summary),
186
+ deletion: normalizeTombstoneDeletion(input.deletion ?? { status: "not_deleted" }),
187
+ retention: Object.freeze({
188
+ defaultPolicy: "retain_indefinitely",
189
+ userAction: "purge_or_anonymize_later"
190
+ })
191
+ });
192
+ assertPublicSafeCustodyPayload(tombstone);
193
+ return tombstone;
194
+ }
195
+ export function buildCustodyTombstoneFromManifest(manifest, input) {
196
+ return buildCustodyTombstone({
197
+ run: {
198
+ runId: manifest.run.runId,
199
+ workspaceId: manifest.run.workspaceId,
200
+ terminalStatus: manifest.run.terminalStatus,
201
+ ...(manifest.run.terminalAt ? { terminalAt: manifest.run.terminalAt } : {})
202
+ },
203
+ manifest: {
204
+ status: input.manifestStatus ?? "written",
205
+ generatedAt: manifest.generatedAt,
206
+ ...(manifest.finalizedAt ? { finalizedAt: manifest.finalizedAt } : {}),
207
+ tombstonedAt: input.tombstonedAt
208
+ },
209
+ summary: manifest.summary,
210
+ ...(input.deletion ? { deletion: input.deletion } : {})
211
+ });
212
+ }
213
+ export function scanCustodyPayloadForSensitiveValues(input) {
214
+ const findings = [];
215
+ visitCustodyValue(input, "$", findings);
216
+ return Object.freeze(findings);
217
+ }
218
+ export function assertPublicSafeCustodyPayload(input) {
219
+ const findings = scanCustodyPayloadForSensitiveValues(input);
220
+ if (findings.length > 0) {
221
+ throw new CustodyManifestRedactionError(findings);
222
+ }
223
+ }
224
+ function normalizeRun(input) {
225
+ return Object.freeze({
226
+ runId: assertSafeIdentifier(input.runId, "run.runId"),
227
+ workspaceId: assertSafeIdentifier(input.workspaceId, "run.workspaceId"),
228
+ provider: assertSafeMetadataString(input.provider, "run.provider"),
229
+ runtime: assertSafeMetadataString(input.runtime, "run.runtime"),
230
+ terminalStatus: assertSafeMetadataString(input.terminalStatus, "run.terminalStatus"),
231
+ ...(input.credentialMode ? { credentialMode: input.credentialMode } : {}),
232
+ ...(input.createdAt ? { createdAt: assertTimestamp(input.createdAt, "run.createdAt") } : {}),
233
+ ...(input.terminalAt ? { terminalAt: assertTimestamp(input.terminalAt, "run.terminalAt") } : {})
234
+ });
235
+ }
236
+ function normalizeSecretClass(input) {
237
+ const count = nonNegativeInteger(input.count ?? (input.present ? 1 : 0), "secret.count");
238
+ return Object.freeze({
239
+ class: assertSafeMetadataString(input.class, "secret.class"),
240
+ present: input.present,
241
+ count,
242
+ exposures: Object.freeze((input.exposures ?? []).map(normalizeExposure)),
243
+ disposition: normalizeDisposition(input.disposition),
244
+ ...(input.evidence ? { evidence: Object.freeze(input.evidence.map(normalizeEvidence)) } : {})
245
+ });
246
+ }
247
+ function normalizeResourceClass(input) {
248
+ const count = nonNegativeInteger(input.count ?? 1, "resource.count");
249
+ return Object.freeze({
250
+ class: assertSafeMetadataString(input.class, "resource.class"),
251
+ count,
252
+ exposures: Object.freeze((input.exposures ?? []).map(normalizeExposure)),
253
+ disposition: normalizeDisposition(input.disposition),
254
+ ...(input.evidence ? { evidence: Object.freeze(input.evidence.map(normalizeEvidence)) } : {})
255
+ });
256
+ }
257
+ function normalizeExposure(input) {
258
+ return Object.freeze({
259
+ surface: assertSafeMetadataString(input.surface, "exposure.surface"),
260
+ access: input.access,
261
+ ...(input.status ? { status: input.status } : {}),
262
+ ...(input.count !== undefined ? { count: nonNegativeInteger(input.count, "exposure.count") } : {}),
263
+ ...(input.firstExposedAt
264
+ ? { firstExposedAt: assertTimestamp(input.firstExposedAt, "exposure.firstExposedAt") }
265
+ : {}),
266
+ ...(input.lastExposedAt
267
+ ? { lastExposedAt: assertTimestamp(input.lastExposedAt, "exposure.lastExposedAt") }
268
+ : {}),
269
+ ...(input.revokedAt ? { revokedAt: assertTimestamp(input.revokedAt, "exposure.revokedAt") } : {})
270
+ });
271
+ }
272
+ function normalizeDisposition(input) {
273
+ return Object.freeze({
274
+ status: input.status,
275
+ ...(input.reason ? { reason: assertSafeMetadataString(input.reason, "disposition.reason") } : {}),
276
+ ...(input.decidedAt ? { decidedAt: assertTimestamp(input.decidedAt, "disposition.decidedAt") } : {}),
277
+ ...(input.errorClass ? { errorClass: assertSafeMetadataString(input.errorClass, "disposition.errorClass") } : {}),
278
+ ...(input.followUpRequired !== undefined ? { followUpRequired: input.followUpRequired } : {})
279
+ });
280
+ }
281
+ function normalizeEvidence(input) {
282
+ return Object.freeze({
283
+ source: assertSafeMetadataString(input.source, "evidence.source"),
284
+ ...(input.status ? { status: assertSafeMetadataString(input.status, "evidence.status") } : {}),
285
+ ...(input.observedAt ? { observedAt: assertTimestamp(input.observedAt, "evidence.observedAt") } : {}),
286
+ ...(input.count !== undefined ? { count: nonNegativeInteger(input.count, "evidence.count") } : {}),
287
+ ...(input.errorClass ? { errorClass: assertSafeMetadataString(input.errorClass, "evidence.errorClass") } : {})
288
+ });
289
+ }
290
+ function normalizeCleanup(input) {
291
+ if (!input) {
292
+ return Object.freeze({ status: "pending" });
293
+ }
294
+ return Object.freeze({
295
+ status: input.status,
296
+ ...(input.startedAt ? { startedAt: assertTimestamp(input.startedAt, "cleanup.startedAt") } : {}),
297
+ ...(input.finishedAt ? { finishedAt: assertTimestamp(input.finishedAt, "cleanup.finishedAt") } : {}),
298
+ ...(input.errorClass ? { errorClass: assertSafeMetadataString(input.errorClass, "cleanup.errorClass") } : {}),
299
+ ...(input.followUpRequiredCount !== undefined
300
+ ? {
301
+ followUpRequiredCount: nonNegativeInteger(input.followUpRequiredCount, "cleanup.followUpRequiredCount")
302
+ }
303
+ : {})
304
+ });
305
+ }
306
+ function buildCustodySummary(secrets, resources, cleanup) {
307
+ const records = [...secrets, ...resources];
308
+ const dispositionCounts = {};
309
+ let exposureCount = 0;
310
+ let revokedExposureCount = 0;
311
+ let followUpRequiredCount = cleanup.followUpRequiredCount ?? 0;
312
+ for (const record of records) {
313
+ dispositionCounts[record.disposition.status] = (dispositionCounts[record.disposition.status] ?? 0) + 1;
314
+ exposureCount += record.exposures.length;
315
+ revokedExposureCount += record.exposures.filter((exposure) => exposure.status === "revoked").length;
316
+ if (record.disposition.followUpRequired) {
317
+ followUpRequiredCount++;
318
+ }
319
+ }
320
+ return Object.freeze({
321
+ secretClassCount: secrets.length,
322
+ secretInstanceCount: secrets.reduce((sum, record) => sum + record.count, 0),
323
+ resourceClassCount: resources.length,
324
+ resourceInstanceCount: resources.reduce((sum, record) => sum + record.count, 0),
325
+ exposureCount,
326
+ revokedExposureCount,
327
+ retainedCount: dispositionCounts.retained_by_policy ?? 0,
328
+ cleanupFailedCount: dispositionCounts.cleanup_failed ?? 0,
329
+ parkedForOperatorCount: dispositionCounts.parked_for_operator ?? 0,
330
+ pendingCount: dispositionCounts.pending ?? 0,
331
+ followUpRequiredCount,
332
+ dispositionCounts: Object.freeze({ ...dispositionCounts })
333
+ });
334
+ }
335
+ function normalizeSummary(input) {
336
+ return Object.freeze({
337
+ secretClassCount: nonNegativeInteger(input.secretClassCount, "summary.secretClassCount"),
338
+ secretInstanceCount: nonNegativeInteger(input.secretInstanceCount, "summary.secretInstanceCount"),
339
+ resourceClassCount: nonNegativeInteger(input.resourceClassCount, "summary.resourceClassCount"),
340
+ resourceInstanceCount: nonNegativeInteger(input.resourceInstanceCount, "summary.resourceInstanceCount"),
341
+ exposureCount: nonNegativeInteger(input.exposureCount, "summary.exposureCount"),
342
+ revokedExposureCount: nonNegativeInteger(input.revokedExposureCount, "summary.revokedExposureCount"),
343
+ retainedCount: nonNegativeInteger(input.retainedCount, "summary.retainedCount"),
344
+ cleanupFailedCount: nonNegativeInteger(input.cleanupFailedCount, "summary.cleanupFailedCount"),
345
+ parkedForOperatorCount: nonNegativeInteger(input.parkedForOperatorCount, "summary.parkedForOperatorCount"),
346
+ pendingCount: nonNegativeInteger(input.pendingCount, "summary.pendingCount"),
347
+ followUpRequiredCount: nonNegativeInteger(input.followUpRequiredCount, "summary.followUpRequiredCount"),
348
+ dispositionCounts: Object.freeze(Object.fromEntries(Object.entries(input.dispositionCounts).map(([key, value]) => [
349
+ key,
350
+ nonNegativeInteger(value, `summary.dispositionCounts.${key}`)
351
+ ])))
352
+ });
353
+ }
354
+ function normalizeTombstoneRun(input) {
355
+ return Object.freeze({
356
+ runId: assertSafeIdentifier(input.runId, "tombstone.run.runId"),
357
+ workspaceId: assertSafeIdentifier(input.workspaceId, "tombstone.run.workspaceId"),
358
+ terminalStatus: assertSafeMetadataString(input.terminalStatus, "tombstone.run.terminalStatus"),
359
+ ...(input.terminalAt ? { terminalAt: assertTimestamp(input.terminalAt, "tombstone.run.terminalAt") } : {})
360
+ });
361
+ }
362
+ function normalizeTombstoneManifest(input) {
363
+ return Object.freeze({
364
+ schemaVersion: CUSTODY_MANIFEST_SCHEMA_VERSION,
365
+ status: input.status,
366
+ ...(input.generatedAt ? { generatedAt: assertTimestamp(input.generatedAt, "tombstone.manifest.generatedAt") } : {}),
367
+ ...(input.finalizedAt ? { finalizedAt: assertTimestamp(input.finalizedAt, "tombstone.manifest.finalizedAt") } : {}),
368
+ tombstonedAt: assertTimestamp(input.tombstonedAt, "tombstone.manifest.tombstonedAt")
369
+ });
370
+ }
371
+ function normalizeTombstoneDeletion(input) {
372
+ return Object.freeze({
373
+ status: input.status,
374
+ ...(input.pendingAt ? { pendingAt: assertTimestamp(input.pendingAt, "tombstone.deletion.pendingAt") } : {}),
375
+ ...(input.deletedAt ? { deletedAt: assertTimestamp(input.deletedAt, "tombstone.deletion.deletedAt") } : {})
376
+ });
377
+ }
378
+ function visitCustodyValue(input, path, findings) {
379
+ if (typeof input === "string") {
380
+ scanStringValue(input, path, findings);
381
+ return;
382
+ }
383
+ if (Array.isArray(input)) {
384
+ input.forEach((value, index) => visitCustodyValue(value, `${path}[${index}]`, findings));
385
+ return;
386
+ }
387
+ if (!input || typeof input !== "object") {
388
+ return;
389
+ }
390
+ for (const [key, value] of Object.entries(input)) {
391
+ const childPath = `${path}.${key}`;
392
+ if (isForbiddenCustodyFieldName(key)) {
393
+ findings.push(Object.freeze({ path: childPath, reason: "forbidden_field_name" }));
394
+ }
395
+ visitCustodyValue(value, childPath, findings);
396
+ }
397
+ }
398
+ function scanStringValue(value, path, findings) {
399
+ for (const pattern of forbiddenStringPatterns) {
400
+ if (pattern.regex.test(value)) {
401
+ findings.push(Object.freeze({
402
+ path,
403
+ reason: pattern.reason,
404
+ valueLength: value.length
405
+ }));
406
+ }
407
+ }
408
+ }
409
+ const forbiddenStringPatterns = Object.freeze([
410
+ { reason: "bearer_token", regex: /\bBearer\s+[A-Za-z0-9._~+/=-]{8,}/i },
411
+ {
412
+ reason: "provider_key",
413
+ regex: /\b(?:sk-(?:ant|proj|live|test|deepseek|openai)|xox[baprs]-|AIza)[A-Za-z0-9_-]{8,}/i
414
+ },
415
+ { reason: "signed_url", regex: /[?&](?:X-Amz-Signature|X-Amz-Credential|X-Amz-Algorithm|AWSAccessKeyId)=/i },
416
+ { reason: "r2_object_key", regex: /(^|[\s"'`])(?:runs|assets)\/[^?<#\s"'`]+/i },
417
+ { reason: "vault_id", regex: /\b(?:vault|vlt|secret)[_:-][A-Za-z0-9][A-Za-z0-9_-]{7,}\b/i },
418
+ {
419
+ reason: "private_resource_handle",
420
+ regex: /\b(?:machine|session|agent|file|skill|env|resource|handle|token_hash|bearer_hash)[_:-][A-Za-z0-9][A-Za-z0-9_-]{7,}\b/i
421
+ },
422
+ { reason: "high_entropy_token", regex: /\b(?=[A-Za-z0-9_-]{40,}\b)(?=.*[A-Za-z])(?=.*\d)[A-Za-z0-9_-]{40,}\b/ }
423
+ ]);
424
+ function isForbiddenCustodyFieldName(key) {
425
+ return /^(apiKey|secretValue|bearerHash|signedUrl|r2Key|objectKey|vaultId|providerResponseBody|responseBody|privateResourceHandle|resourceHandle|rawBody)$/i.test(key);
426
+ }
427
+ function assertSafeIdentifier(value, field) {
428
+ assertNonEmptyString(value, field);
429
+ if (!/^[A-Za-z0-9._:-]+$/.test(value)) {
430
+ throw new Error(`custody manifest ${field} must be an opaque identifier without path separators`);
431
+ }
432
+ assertPublicSafeCustodyPayload(value);
433
+ return value;
434
+ }
435
+ function assertSafeMetadataString(value, field) {
436
+ assertNonEmptyString(value, field);
437
+ assertPublicSafeCustodyPayload(value);
438
+ return value;
439
+ }
440
+ function assertNonEmptyString(value, field) {
441
+ if (typeof value !== "string" || value.trim().length === 0) {
442
+ throw new Error(`custody manifest ${field} must be a non-empty string`);
443
+ }
444
+ }
445
+ function assertTimestamp(value, field) {
446
+ assertSafeMetadataString(value, field);
447
+ const ms = Date.parse(value);
448
+ if (!Number.isFinite(ms)) {
449
+ throw new Error(`custody manifest ${field} must be an ISO timestamp string`);
450
+ }
451
+ return value;
452
+ }
453
+ function nonNegativeInteger(value, field) {
454
+ if (!Number.isSafeInteger(value) || value < 0) {
455
+ throw new Error(`custody manifest ${field} must be a non-negative safe integer`);
456
+ }
457
+ return value;
458
+ }
459
+ function formatFindingPaths(findings) {
460
+ return findings.map((finding) => `${finding.path} (${finding.reason})`).join(", ");
461
+ }
462
+ function cloneJson(value) {
463
+ return JSON.parse(JSON.stringify(value));
464
+ }
465
+ //# sourceMappingURL=run-custody.js.map