@jami-studio/orchestra 0.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.
package/src/index.mjs ADDED
@@ -0,0 +1,897 @@
1
+ import { createCipheriv, createDecipheriv, createHash, randomBytes } from "node:crypto";
2
+ import { ORCHESTRA_DRIZZLE_SCHEMA, libsqlOrchestraSchema, pgOrchestraSchema } from "./drizzle.mjs";
3
+ import { ORCHESTRA_SCHEMA_VERSION, ORCHESTRA_TABLE_NAMES, ORCHESTRA_TABLES } from "./schema.mjs";
4
+
5
+ export { ORCHESTRA_DRIZZLE_SCHEMA, libsqlOrchestraSchema, pgOrchestraSchema } from "./drizzle.mjs";
6
+ export { ORCHESTRA_SCHEMA_VERSION, ORCHESTRA_TABLE_NAMES, ORCHESTRA_TABLES } from "./schema.mjs";
7
+ export {
8
+ JOSE_SOURCE_LOCK,
9
+ OAuthTokenSecurityError,
10
+ assertSecretContextIsolation,
11
+ createOAuthTokenAuthority,
12
+ resolveSecretRefsForRun,
13
+ signLinkToken,
14
+ verifyLinkToken,
15
+ } from "./oauth.mjs";
16
+
17
+ import { createOAuthTokenAuthority } from "./oauth.mjs";
18
+
19
+ export const ORCHESTRA_PACKAGE = {
20
+ name: "@jami-studio/orchestra",
21
+ version: "0.1.0",
22
+ schemaVersion: ORCHESTRA_SCHEMA_VERSION,
23
+ };
24
+
25
+ export const DISPATCH_SOURCE_ATTRIBUTION = {
26
+ upstreamPackage: "@agent-native/dispatch",
27
+ upstreamVersion: "0.11.5",
28
+ upstreamRepository: "https://github.com/BuilderIO/agent-native/tree/main/packages/dispatch",
29
+ upstreamLicense: "MIT",
30
+ verifiedAt: "2026-06-22",
31
+ npmTarball: "https://registry.npmjs.org/@agent-native/dispatch/-/dispatch-0.11.5.tgz",
32
+ adoptionBoundary: "Control-plane dispatch concepts were reimplemented behind Jami-owned schema, vault, approval, grant, and audit contracts; no upstream source files are vendored.",
33
+ };
34
+
35
+ export const ORCHESTRA_MIGRATION_FIXTURES = [
36
+ {
37
+ fixtureId: "orchestra_vault_schema_2026_06_22_initial",
38
+ fromSchemaVersion: null,
39
+ toSchemaVersion: ORCHESTRA_SCHEMA_VERSION,
40
+ affectedTables: ["orchestra_secrets", "orchestra_secret_key_versions", "orchestra_audit_logs"],
41
+ verifies: ["sealed_payload_has_no_plaintext", "active_key_version_exists", "audit_records_secret_mutations_without_values"],
42
+ },
43
+ {
44
+ fixtureId: "orchestra_vault_key_rotation_2026_06_22",
45
+ fromSchemaVersion: ORCHESTRA_SCHEMA_VERSION,
46
+ toSchemaVersion: ORCHESTRA_SCHEMA_VERSION,
47
+ affectedTables: ["orchestra_secrets", "orchestra_secret_key_versions"],
48
+ verifies: ["old_key_version_retired", "secret_resealed_with_active_key", "plaintext_round_trips_after_rotation"],
49
+ },
50
+ {
51
+ fixtureId: "orchestra_oauth_token_binding_2026_06_23",
52
+ fromSchemaVersion: ORCHESTRA_SCHEMA_VERSION,
53
+ toSchemaVersion: ORCHESTRA_SCHEMA_VERSION,
54
+ affectedTables: ["orchestra_secrets", "orchestra_grants", "orchestra_audit_logs"],
55
+ verifies: [
56
+ "oauth_token_sealed_with_owner_org_audience_aad",
57
+ "cross_owner_or_org_read_denied",
58
+ "audience_binding_required_for_read",
59
+ "scope_change_revokes_active_tokens",
60
+ ],
61
+ },
62
+ ];
63
+
64
+ const STATUS = new Set(["todo", "queued", "running", "waiting_approval", "completed", "failed", "cancelled", "blocked"]);
65
+ const APPROVAL_STATUS = new Set(["requested", "approved", "denied", "expired"]);
66
+ const RISK = new Set(["read", "write", "destructive", "external", "secret_adjacent", "unknown"]);
67
+ const REDACTED = "[redacted]";
68
+ const SECURITY_FORMAT_CHARS = /[\u200B-\u200F\u202A-\u202E\u2060-\u206F\uFEFF]/g;
69
+ const STRUCTURED_REDACTION_LIMIT = 65_536;
70
+ const SENSITIVE_FIELD_PATTERN = /secret|apiKey|api_key|credential|password|plaintext|plain_text|tokenValue|token_value|clientSecret|client_secret|authorization|cookie|session|^value$/i;
71
+ const SENSITIVE_TOKEN_FIELD_PATTERN = /^token$|^token(value|secret|credential|key|payload|plaintext)$|[a-z0-9_-]*token$/i;
72
+ const SECRET_REF_SCHEMA_FIELDS = new Set(["schemaVersion", "secretId", "provider", "scope", "redactionClass", "createdAt", "expiresAt", "rotationRef", "description"]);
73
+
74
+ export class OrchestraControlPlaneError extends Error {
75
+ constructor(code, message) {
76
+ super(message);
77
+ this.name = "OrchestraControlPlaneError";
78
+ this.code = code;
79
+ }
80
+ }
81
+
82
+ export function createInMemoryOrchestraControlPlane(options = {}) {
83
+ const now = options.now ?? (() => new Date());
84
+ const vault = options.vault ?? createSealedSecretVault({ now });
85
+ const oauth = createOAuthTokenAuthority({
86
+ now,
87
+ vault,
88
+ auditSink: { write: (event) => audit(adaptOAuthAuditEvent(event)) },
89
+ });
90
+ const state = {
91
+ orgDirectory: new Map(),
92
+ agents: new Map(),
93
+ dreams: new Map(),
94
+ tasks: new Map(),
95
+ runs: new Map(),
96
+ runEvents: new Map(),
97
+ toolCalls: new Map(),
98
+ artifacts: new Map(),
99
+ grants: new Map(),
100
+ approvals: new Map(),
101
+ secrets: new Map(),
102
+ secretKeyVersions: new Map(vault.keyVersionRecords().map((record) => [record.keyVersionId, record])),
103
+ auditLogs: new Map(),
104
+ };
105
+
106
+ function audit(input) {
107
+ const auditId = input.auditId ?? makeId("aud", input.actorId, input.eventType, state.auditLogs.size);
108
+ const record = {
109
+ schemaVersion: ORCHESTRA_SCHEMA_VERSION,
110
+ auditId,
111
+ actorId: normalizeId(input.actorId, "actor"),
112
+ eventType: input.eventType,
113
+ resourceRef: input.resourceRef ?? "resource_unknown",
114
+ outcome: input.outcome ?? "recorded",
115
+ summary: redactSummary(input.summary ?? input.eventType),
116
+ recordedAt: input.recordedAt ?? now().toISOString(),
117
+ metadata: redactObject(input.metadata ?? {}),
118
+ };
119
+ state.auditLogs.set(auditId, record);
120
+ return record;
121
+ }
122
+
123
+ function upsertDirectoryActor(input) {
124
+ const actorId = normalizeId(input.actorId, "actor");
125
+ const record = {
126
+ schemaVersion: ORCHESTRA_SCHEMA_VERSION,
127
+ actorId,
128
+ actorType: input.actorType ?? "agent",
129
+ displayName: input.displayName ?? actorId,
130
+ status: input.status ?? "active",
131
+ metadata: redactObject(input.metadata ?? {}),
132
+ createdAt: input.createdAt ?? now().toISOString(),
133
+ updatedAt: input.updatedAt ?? now().toISOString(),
134
+ };
135
+ state.orgDirectory.set(actorId, record);
136
+ audit({ actorId, eventType: "org_directory.upserted", resourceRef: actorId, outcome: "allow", summary: "directory actor upserted" });
137
+ return record;
138
+ }
139
+
140
+ function registerAgent(input) {
141
+ const agentId = normalizeId(input.agentId, "agent");
142
+ const directoryActorId = normalizeId(input.directoryActorId ?? `actor_${agentId.replace(/^agent_/, "")}`, "actor");
143
+ if (!state.orgDirectory.has(directoryActorId)) {
144
+ upsertDirectoryActor({ actorId: directoryActorId, actorType: "agent", displayName: input.displayName ?? agentId });
145
+ }
146
+ const record = {
147
+ schemaVersion: ORCHESTRA_SCHEMA_VERSION,
148
+ agentId,
149
+ directoryActorId,
150
+ modelFamily: input.modelFamily ?? "unknown",
151
+ capabilities: redactObject(input.capabilities ?? {}),
152
+ status: input.status ?? "active",
153
+ createdAt: input.createdAt ?? now().toISOString(),
154
+ updatedAt: input.updatedAt ?? now().toISOString(),
155
+ };
156
+ state.agents.set(agentId, record);
157
+ audit({ actorId: directoryActorId, eventType: "agent.registered", resourceRef: agentId, outcome: "allow", summary: "agent registered" });
158
+ return record;
159
+ }
160
+
161
+ function createDream(input) {
162
+ const dreamId = normalizeId(input.dreamId, "dream");
163
+ const record = {
164
+ schemaVersion: ORCHESTRA_SCHEMA_VERSION,
165
+ dreamId,
166
+ title: requireString(input.title, "title"),
167
+ status: input.status ?? "todo",
168
+ ownerActorId: normalizeId(input.ownerActorId, "actor"),
169
+ priority: Number.isInteger(input.priority) ? input.priority : 0,
170
+ metadata: redactObject(input.metadata ?? {}),
171
+ createdAt: input.createdAt ?? now().toISOString(),
172
+ updatedAt: input.updatedAt ?? now().toISOString(),
173
+ };
174
+ state.dreams.set(dreamId, record);
175
+ audit({ actorId: record.ownerActorId, eventType: "dream.created", resourceRef: dreamId, outcome: "allow", summary: "dream created" });
176
+ return record;
177
+ }
178
+
179
+ function createTask(input) {
180
+ const taskId = normalizeId(input.taskId, "task");
181
+ const assigneeAgentId = normalizeId(input.assigneeAgentId, "agent");
182
+ if (!state.agents.has(assigneeAgentId)) {
183
+ throw new OrchestraControlPlaneError("unknown_agent", `agent ${assigneeAgentId} is not registered`);
184
+ }
185
+ if (input.dreamId && !state.dreams.has(input.dreamId)) {
186
+ throw new OrchestraControlPlaneError("unknown_dream", `dream ${input.dreamId} does not exist`);
187
+ }
188
+ const record = {
189
+ schemaVersion: ORCHESTRA_SCHEMA_VERSION,
190
+ taskId,
191
+ dreamId: input.dreamId,
192
+ assigneeAgentId,
193
+ status: normalizeStatus(input.status ?? "queued"),
194
+ input: redactObject(input.input ?? {}),
195
+ requiredScopes: [...new Set(asArray(input.requiredScopes))].sort(),
196
+ createdAt: input.createdAt ?? now().toISOString(),
197
+ updatedAt: input.updatedAt ?? now().toISOString(),
198
+ };
199
+ state.tasks.set(taskId, record);
200
+ audit({ actorId: assigneeAgentId, eventType: "task.created", resourceRef: taskId, outcome: "allow", summary: "task created" });
201
+ return record;
202
+ }
203
+
204
+ function createRun(input) {
205
+ const runId = normalizeId(input.runId, "run");
206
+ const task = state.tasks.get(input.taskId);
207
+ if (!task) throw new OrchestraControlPlaneError("unknown_task", `task ${input.taskId} does not exist`);
208
+ const record = {
209
+ schemaVersion: ORCHESTRA_SCHEMA_VERSION,
210
+ runId,
211
+ taskId: task.taskId,
212
+ agentId: normalizeId(input.agentId ?? task.assigneeAgentId, "agent"),
213
+ status: normalizeStatus(input.status ?? "running"),
214
+ attempt: Number.isInteger(input.attempt) ? input.attempt : nextAttempt(task.taskId),
215
+ startedAt: input.startedAt ?? now().toISOString(),
216
+ completedAt: input.completedAt,
217
+ metadata: redactObject(input.metadata ?? {}),
218
+ };
219
+ state.runs.set(runId, record);
220
+ audit({ actorId: record.agentId, eventType: "run.created", resourceRef: runId, outcome: "allow", summary: "run created" });
221
+ return record;
222
+ }
223
+
224
+ function recordRunEvent(input) {
225
+ const run = state.runs.get(input.runId);
226
+ if (!run) throw new OrchestraControlPlaneError("unknown_run", `run ${input.runId} does not exist`);
227
+ const sequence = Number.isInteger(input.sequence) ? input.sequence : [...state.runEvents.values()].filter((event) => event.runId === run.runId).length;
228
+ const eventId = normalizeId(input.eventId ?? makeId("evt", run.runId, sequence), "evt");
229
+ const record = {
230
+ schemaVersion: ORCHESTRA_SCHEMA_VERSION,
231
+ eventId,
232
+ runId: run.runId,
233
+ eventType: requireString(input.eventType, "eventType"),
234
+ sequence,
235
+ payload: redactObject(input.payload ?? {}),
236
+ recordedAt: input.recordedAt ?? now().toISOString(),
237
+ };
238
+ state.runEvents.set(eventId, record);
239
+ audit({ actorId: run.agentId, eventType: "run.event_recorded", resourceRef: eventId, outcome: "allow", summary: record.eventType });
240
+ return record;
241
+ }
242
+
243
+ function recordToolCall(input) {
244
+ const run = state.runs.get(input.runId);
245
+ if (!run) throw new OrchestraControlPlaneError("unknown_run", `run ${input.runId} does not exist`);
246
+ const toolCallId = normalizeId(input.toolCallId, "tool");
247
+ const record = {
248
+ schemaVersion: ORCHESTRA_SCHEMA_VERSION,
249
+ toolCallId,
250
+ runId: run.runId,
251
+ toolName: requireString(input.toolName, "toolName"),
252
+ risk: RISK.has(input.risk) ? input.risk : "unknown",
253
+ status: input.status ?? "requested",
254
+ inputRef: normalizeResourceRef(input.inputRef ?? `artifact://${toolCallId}/input`),
255
+ outputRef: input.outputRef ? normalizeResourceRef(input.outputRef) : undefined,
256
+ createdAt: input.createdAt ?? now().toISOString(),
257
+ };
258
+ state.toolCalls.set(toolCallId, record);
259
+ audit({ actorId: run.agentId, eventType: "tool_call.recorded", resourceRef: toolCallId, outcome: "allow", summary: "tool call recorded" });
260
+ return record;
261
+ }
262
+
263
+ function writeArtifact(input) {
264
+ const run = state.runs.get(input.runId);
265
+ if (!run) throw new OrchestraControlPlaneError("unknown_run", `run ${input.runId} does not exist`);
266
+ const artifactId = normalizeId(input.artifactId, "art");
267
+ const record = {
268
+ schemaVersion: ORCHESTRA_SCHEMA_VERSION,
269
+ artifactId,
270
+ runId: run.runId,
271
+ kind: input.kind ?? "evidence",
272
+ uri: normalizeResourceRef(input.uri ?? `memory://${artifactId}`),
273
+ provenance: redactObject(input.provenance ?? {}),
274
+ createdAt: input.createdAt ?? now().toISOString(),
275
+ };
276
+ state.artifacts.set(artifactId, record);
277
+ audit({ actorId: run.agentId, eventType: "artifact.written", resourceRef: artifactId, outcome: "allow", summary: "artifact written" });
278
+ return record;
279
+ }
280
+
281
+ function grantScope(input) {
282
+ const grantId = normalizeId(input.grantId, "grant");
283
+ const record = {
284
+ schemaVersion: ORCHESTRA_SCHEMA_VERSION,
285
+ grantId,
286
+ subjectActorId: normalizeId(input.subjectActorId, "actor"),
287
+ scope: requireString(input.scope, "scope"),
288
+ resourceRef: normalizeResourceRef(input.resourceRef ?? "*"),
289
+ status: input.status ?? "active",
290
+ expiresAt: input.expiresAt,
291
+ createdAt: input.createdAt ?? now().toISOString(),
292
+ };
293
+ state.grants.set(grantId, record);
294
+ audit({ actorId: record.subjectActorId, eventType: "grant.created", resourceRef: grantId, outcome: "allow", summary: "grant created" });
295
+ return record;
296
+ }
297
+
298
+ function requestApproval(input) {
299
+ const approvalId = normalizeId(input.approvalId, "approval");
300
+ const record = {
301
+ schemaVersion: ORCHESTRA_SCHEMA_VERSION,
302
+ approvalId,
303
+ runId: normalizeId(input.runId, "run"),
304
+ actionId: normalizeId(input.actionId, "act"),
305
+ requestedBy: normalizeId(input.requestedBy, "actor"),
306
+ decidedBy: undefined,
307
+ status: "requested",
308
+ requiredScopes: [...new Set(asArray(input.requiredScopes))].sort(),
309
+ requestedAt: input.requestedAt ?? now().toISOString(),
310
+ decidedAt: undefined,
311
+ expiresAt: input.expiresAt,
312
+ };
313
+ state.approvals.set(approvalId, record);
314
+ audit({ actorId: record.requestedBy, eventType: "approval.requested", resourceRef: approvalId, outcome: "needs_approval", summary: "approval requested" });
315
+ return record;
316
+ }
317
+
318
+ function decideApproval(input) {
319
+ const approval = state.approvals.get(input.approvalId);
320
+ if (!approval) throw new OrchestraControlPlaneError("unknown_approval", `approval ${input.approvalId} does not exist`);
321
+ const status = input.status ?? "approved";
322
+ if (!APPROVAL_STATUS.has(status) || status === "requested") {
323
+ throw new OrchestraControlPlaneError("invalid_approval_status", `unsupported approval decision ${status}`);
324
+ }
325
+ const record = {
326
+ ...approval,
327
+ status,
328
+ decidedBy: normalizeId(input.decidedBy, "actor"),
329
+ decidedAt: input.decidedAt ?? now().toISOString(),
330
+ };
331
+ state.approvals.set(record.approvalId, record);
332
+ audit({ actorId: record.decidedBy, eventType: "approval.decided", resourceRef: record.approvalId, outcome: status, summary: `approval ${status}` });
333
+ return record;
334
+ }
335
+
336
+ function writeSecret(input) {
337
+ const secretId = normalizeId(input.secretId, "secret");
338
+ const sealed = vault.seal(requireString(input.value, "value"), {
339
+ secretId,
340
+ aad: input.name ?? secretId,
341
+ });
342
+ const record = {
343
+ schemaVersion: ORCHESTRA_SCHEMA_VERSION,
344
+ secretId,
345
+ name: input.name ?? secretId,
346
+ keyVersionId: sealed.keyVersionId,
347
+ sealedPayload: sealed,
348
+ metadata: redactObject(input.metadata ?? {}),
349
+ createdAt: input.createdAt ?? now().toISOString(),
350
+ rotatedAt: undefined,
351
+ };
352
+ state.secrets.set(secretId, record);
353
+ syncKeyVersions();
354
+ audit({ actorId: normalizeId(input.actorId, "actor"), eventType: "secret.sealed", resourceRef: secretId, outcome: "allow", summary: "secret sealed at rest" });
355
+ return publicSecretRecord(record);
356
+ }
357
+
358
+ function readSecret(input) {
359
+ const secretId = normalizeId(input.secretId, "secret");
360
+ const actorId = normalizeId(input.actorId, "actor");
361
+ const secret = state.secrets.get(secretId);
362
+ if (!secret) throw new OrchestraControlPlaneError("unknown_secret", `secret ${secretId} does not exist`);
363
+ if (!hasGrant(actorId, `secret:read:${secretId}`, `secret://${secretId}`)) {
364
+ audit({ actorId, eventType: "secret.read_denied", resourceRef: secretId, outcome: "deny", summary: "secret read denied" });
365
+ throw new OrchestraControlPlaneError("missing_secret_grant", `actor ${actorId} lacks secret read grant`);
366
+ }
367
+ const value = vault.open(secret.sealedPayload, { aad: secret.name });
368
+ audit({ actorId, eventType: "secret.read", resourceRef: secretId, outcome: "allow", summary: "secret read allowed; value omitted" });
369
+ return { secretId, name: secret.name, value };
370
+ }
371
+
372
+ function rotateVaultKey(input = {}) {
373
+ const rotation = vault.rotateKey({ retiredAt: input.retiredAt ?? now().toISOString() });
374
+ syncKeyVersions();
375
+ for (const secret of state.secrets.values()) {
376
+ const plaintext = vault.open(secret.sealedPayload, { aad: secret.name });
377
+ const sealedPayload = vault.seal(plaintext, { secretId: secret.secretId, aad: secret.name });
378
+ state.secrets.set(secret.secretId, {
379
+ ...secret,
380
+ keyVersionId: sealedPayload.keyVersionId,
381
+ sealedPayload,
382
+ rotatedAt: input.rotatedAt ?? now().toISOString(),
383
+ });
384
+ }
385
+ syncKeyVersions();
386
+ audit({ actorId: normalizeId(input.actorId ?? "actor_system", "actor"), eventType: "vault.rotated", resourceRef: rotation.activeKeyVersionId, outcome: "allow", summary: "vault key rotated and secrets resealed" });
387
+ return rotation;
388
+ }
389
+
390
+ function snapshot() {
391
+ return {
392
+ ...Object.fromEntries(Object.entries(state).map(([key, map]) => [key, [...map.values()].map((record) => (key === "secrets" ? publicSecretRecord(record) : structuredClone(record)))])),
393
+ oauthTokens: oauth.listTokenRecords(),
394
+ };
395
+ }
396
+
397
+ function inspect() {
398
+ return {
399
+ package: ORCHESTRA_PACKAGE,
400
+ attribution: DISPATCH_SOURCE_ATTRIBUTION,
401
+ schema: {
402
+ version: ORCHESTRA_SCHEMA_VERSION,
403
+ tableCount: ORCHESTRA_TABLE_NAMES.length,
404
+ tables: ORCHESTRA_TABLE_NAMES,
405
+ drizzleDialects: Object.keys(ORCHESTRA_DRIZZLE_SCHEMA.dialects),
406
+ },
407
+ capabilities: {
408
+ controlPlane: true,
409
+ dispatchState: true,
410
+ postgresSchema: true,
411
+ libsqlSchema: true,
412
+ sealedSecretsAtRest: true,
413
+ keyRotation: true,
414
+ approvals: true,
415
+ grants: true,
416
+ auditLogs: true,
417
+ oauthScopedRead: true,
418
+ oauthTokensEncryptedAtRest: true,
419
+ oauthAudienceBinding: true,
420
+ oauthRotationAndRevocation: true,
421
+ linkTokenJoseVerification: true,
422
+ secretContextIsolation: true,
423
+ hostedRuntime: false,
424
+ },
425
+ migrationFixtures: ORCHESTRA_MIGRATION_FIXTURES,
426
+ };
427
+ }
428
+
429
+ function syncKeyVersions() {
430
+ for (const record of vault.keyVersionRecords()) {
431
+ state.secretKeyVersions.set(record.keyVersionId, record);
432
+ }
433
+ }
434
+
435
+ function hasGrant(actorId, scope, resourceRef) {
436
+ const currentTime = now().getTime();
437
+ return [...state.grants.values()].some((grant) => {
438
+ if (grant.subjectActorId !== actorId || grant.status !== "active") return false;
439
+ if (grant.expiresAt && Date.parse(grant.expiresAt) <= currentTime) return false;
440
+ const scopeMatches = grant.scope === scope || grant.scope === "secret:read:*" || grant.scope === "*";
441
+ const resourceMatches = grant.resourceRef === resourceRef || grant.resourceRef === "*" || grant.resourceRef === `secret://${resourceRef.replace(/^secret:\/\//, "")}`;
442
+ return scopeMatches && resourceMatches;
443
+ });
444
+ }
445
+
446
+ function nextAttempt(taskId) {
447
+ return [...state.runs.values()].filter((run) => run.taskId === taskId).length + 1;
448
+ }
449
+
450
+ return {
451
+ inspect,
452
+ snapshot,
453
+ upsertDirectoryActor,
454
+ registerAgent,
455
+ createDream,
456
+ createTask,
457
+ createRun,
458
+ recordRunEvent,
459
+ recordToolCall,
460
+ writeArtifact,
461
+ grantScope,
462
+ requestApproval,
463
+ decideApproval,
464
+ writeSecret,
465
+ readSecret,
466
+ rotateVaultKey,
467
+ oauth,
468
+ audit,
469
+ };
470
+ }
471
+
472
+ export function createSealedSecretVault(options = {}) {
473
+ const now = options.now ?? (() => new Date());
474
+ const keys = new Map();
475
+ let activeKeyVersionId = options.activeKeyVersionId ?? "key_2026_06_22_0001";
476
+ keys.set(activeKeyVersionId, {
477
+ keyVersionId: activeKeyVersionId,
478
+ key: normalizeKey(options.key),
479
+ status: "active",
480
+ algorithm: "AES-256-GCM",
481
+ createdAt: now().toISOString(),
482
+ retiredAt: undefined,
483
+ rotationPolicy: options.rotationPolicy ?? { maxAgeDays: 90, rotateBeforePublish: true },
484
+ });
485
+
486
+ function seal(value, input = {}) {
487
+ const keyRecord = keys.get(activeKeyVersionId);
488
+ const iv = randomBytes(12);
489
+ const cipher = createCipheriv("aes-256-gcm", keyRecord.key, iv);
490
+ const aad = Buffer.from(input.aad ?? input.secretId ?? "secret", "utf8");
491
+ cipher.setAAD(aad);
492
+ const ciphertext = Buffer.concat([cipher.update(String(value), "utf8"), cipher.final()]);
493
+ const tag = cipher.getAuthTag();
494
+ return {
495
+ schemaVersion: "2026-06-22.sealed-secret-envelope",
496
+ algorithm: keyRecord.algorithm,
497
+ keyVersionId: keyRecord.keyVersionId,
498
+ iv: iv.toString("base64url"),
499
+ ciphertext: ciphertext.toString("base64url"),
500
+ tag: tag.toString("base64url"),
501
+ aadHash: sha256(aad),
502
+ };
503
+ }
504
+
505
+ function open(envelope, input = {}) {
506
+ const keyRecord = keys.get(envelope?.keyVersionId);
507
+ if (!keyRecord) throw new OrchestraControlPlaneError("unknown_key_version", `key version ${envelope?.keyVersionId} is not available`);
508
+ const decipher = createDecipheriv("aes-256-gcm", keyRecord.key, Buffer.from(envelope.iv, "base64url"));
509
+ const aad = Buffer.from(input.aad ?? "secret", "utf8");
510
+ if (sha256(aad) !== envelope.aadHash) {
511
+ throw new OrchestraControlPlaneError("secret_aad_mismatch", "sealed secret associated data does not match");
512
+ }
513
+ decipher.setAAD(aad);
514
+ decipher.setAuthTag(Buffer.from(envelope.tag, "base64url"));
515
+ return Buffer.concat([decipher.update(Buffer.from(envelope.ciphertext, "base64url")), decipher.final()]).toString("utf8");
516
+ }
517
+
518
+ function rotateKey(input = {}) {
519
+ const previousKeyVersionId = activeKeyVersionId;
520
+ const previous = keys.get(previousKeyVersionId);
521
+ keys.set(previousKeyVersionId, {
522
+ ...previous,
523
+ status: "retired",
524
+ retiredAt: input.retiredAt ?? now().toISOString(),
525
+ });
526
+ activeKeyVersionId = input.keyVersionId ?? makeId("key", now().toISOString(), keys.size + 1);
527
+ keys.set(activeKeyVersionId, {
528
+ keyVersionId: activeKeyVersionId,
529
+ key: normalizeKey(input.key),
530
+ status: "active",
531
+ algorithm: "AES-256-GCM",
532
+ createdAt: now().toISOString(),
533
+ retiredAt: undefined,
534
+ rotationPolicy: input.rotationPolicy ?? previous.rotationPolicy,
535
+ });
536
+ return { previousKeyVersionId, activeKeyVersionId };
537
+ }
538
+
539
+ function keyVersionRecords() {
540
+ return [...keys.values()].map(({ key, ...record }) => structuredClone(record));
541
+ }
542
+
543
+ return {
544
+ seal,
545
+ open,
546
+ rotateKey,
547
+ keyVersionRecords,
548
+ get activeKeyVersionId() {
549
+ return activeKeyVersionId;
550
+ },
551
+ };
552
+ }
553
+
554
+ function publicSecretRecord(record) {
555
+ return {
556
+ ...structuredClone(record),
557
+ sealedPayload: {
558
+ ...record.sealedPayload,
559
+ ciphertext: record.sealedPayload.ciphertext,
560
+ },
561
+ };
562
+ }
563
+
564
+ function normalizeKey(value) {
565
+ if (Buffer.isBuffer(value) && value.length === 32) return value;
566
+ if (typeof value === "string" && Buffer.byteLength(value) >= 32) {
567
+ return createHash("sha256").update(value).digest();
568
+ }
569
+ return randomBytes(32);
570
+ }
571
+
572
+ function normalizeIdBody(value) {
573
+ const source = String(value).toLowerCase();
574
+ let out = "";
575
+ let prevUnderscore = false;
576
+ for (let index = 0; index < source.length; index += 1) {
577
+ const char = source[index];
578
+ const code = source.charCodeAt(index);
579
+ const isLowerAlpha = code >= 97 && code <= 122;
580
+ const isDigit = code >= 48 && code <= 57;
581
+ const isSafe = isLowerAlpha || isDigit || char === "_" || char === "-";
582
+ if (isSafe) {
583
+ out += char;
584
+ prevUnderscore = false;
585
+ continue;
586
+ }
587
+ if (!prevUnderscore) {
588
+ out += "_";
589
+ prevUnderscore = true;
590
+ }
591
+ }
592
+
593
+ let start = 0;
594
+ while (start < out.length && out[start] === "_") {
595
+ start += 1;
596
+ }
597
+ let end = out.length;
598
+ while (end > start && out[end - 1] === "_") {
599
+ end -= 1;
600
+ }
601
+ return out.slice(start, end);
602
+ }
603
+
604
+ function stripLeadingAlphaPrefix(value) {
605
+ const text = String(value);
606
+ let index = 0;
607
+ while (index < text.length) {
608
+ const code = text.charCodeAt(index);
609
+ if (code < 97 || code > 122) break;
610
+ index += 1;
611
+ }
612
+ if (index > 0 && text[index] === "_") {
613
+ return text.slice(index + 1);
614
+ }
615
+ return text;
616
+ }
617
+
618
+ function normalizeId(value, prefix) {
619
+ const normalized = normalizeIdBody(value ?? `${prefix}_unknown`);
620
+ const withPrefix = normalized.startsWith(`${prefix}_`) ? normalized : `${prefix}_${stripLeadingAlphaPrefix(normalized)}`;
621
+ if (!isHarnessIdentifier(withPrefix)) {
622
+ throw new OrchestraControlPlaneError("invalid_identifier", `${prefix} identifier is invalid`);
623
+ }
624
+ return withPrefix.slice(0, 96);
625
+ }
626
+
627
+ function normalizeStatus(value) {
628
+ if (STATUS.has(value)) return value;
629
+ throw new OrchestraControlPlaneError("invalid_status", `unsupported status ${value}`);
630
+ }
631
+
632
+ function normalizeResourceRef(value) {
633
+ const resource = String(value ?? "");
634
+ if (resource === "*" || isSupportedUri(resource)) return resource;
635
+ if (isHarnessIdentifier(resource)) return resource;
636
+ throw new OrchestraControlPlaneError("invalid_resource_ref", "resource ref must be a URI, wildcard, or harness id");
637
+ }
638
+
639
+ function isHarnessIdentifier(value) {
640
+ if (typeof value !== "string" || value.length < 3) return false;
641
+ const separatorIndex = value.indexOf("_");
642
+ if (separatorIndex <= 0 || separatorIndex === value.length - 1) return false;
643
+ if (!isLowerAlpha(value[0])) return false;
644
+ if (!isLowerAlpha(value[separatorIndex + 1]) && !isDigit(value[separatorIndex + 1])) return false;
645
+ for (let index = 0; index < value.length; index += 1) {
646
+ const character = value[index];
647
+ if (index === separatorIndex) continue;
648
+ if (isLowerAlpha(character) || isDigit(character)) continue;
649
+ if (index > separatorIndex && (character === "_" || character === "-")) continue;
650
+ return false;
651
+ }
652
+ return true;
653
+ }
654
+
655
+ function isSupportedUri(value) {
656
+ if (value.length > 2048) return false;
657
+ try {
658
+ const url = new URL(value);
659
+ return isUriScheme(url.protocol.slice(0, -1));
660
+ } catch {
661
+ return false;
662
+ }
663
+ }
664
+
665
+ function isUriScheme(value) {
666
+ if (value.length === 0 || !isLowerAlpha(value[0])) return false;
667
+ for (let index = 1; index < value.length; index += 1) {
668
+ const character = value[index];
669
+ if (isLowerAlpha(character) || isDigit(character) || character === "+" || character === "." || character === "-") continue;
670
+ return false;
671
+ }
672
+ return true;
673
+ }
674
+
675
+ function isLowerAlpha(character) {
676
+ return character >= "a" && character <= "z";
677
+ }
678
+
679
+ function isDigit(character) {
680
+ return character >= "0" && character <= "9";
681
+ }
682
+
683
+ function requireString(value, field) {
684
+ if (typeof value !== "string" || value.length === 0) {
685
+ throw new OrchestraControlPlaneError("invalid_input", `${field} is required`);
686
+ }
687
+ return value;
688
+ }
689
+
690
+ function asArray(value) {
691
+ return Array.isArray(value) ? value : [];
692
+ }
693
+
694
+ function redactObject(value) {
695
+ if (Array.isArray(value)) return value.map(redactObject);
696
+ if (value === null || typeof value !== "object") {
697
+ return typeof value === "string" ? redactSummary(value) : value;
698
+ }
699
+ const secretRefRecord = isSecretRefRecord(value);
700
+ return Object.fromEntries(Object.entries(value).map(([key, child], index) => {
701
+ const outputKey = containsSensitiveString(key) ? `[redacted-key-${index}]` : key;
702
+ return [
703
+ outputKey,
704
+ isSecretRefField(key) || (secretRefRecord && SECRET_REF_SCHEMA_FIELDS.has(key))
705
+ ? redactObject(child)
706
+ : isSensitiveField(key) ? REDACTED : redactObject(child),
707
+ ];
708
+ }));
709
+ }
710
+
711
+ function redactSummary(value) {
712
+ const normalized = normalizeSecurityText(String(value));
713
+ const structured = redactStructuredText(normalized);
714
+ return structured
715
+ .replace(/\b(Bearer)\s+[A-Za-z0-9._~+/=-]+/g, `$1 ${REDACTED}`)
716
+ .replace(/(["']?\b(api[_-]?key|tokenValue|token|password|credential|clientSecret|plaintext)\b["']?)(\s*[:=]\s*)("[^"]*"|'[^']*'|[^,\s;}]+)/gi, (_match, key, _name, separator) => {
717
+ const assignment = separator.includes(":") ? separator : "=";
718
+ return `${key}${assignment}${assignment.includes(":") ? JSON.stringify(REDACTED) : REDACTED}`;
719
+ })
720
+ .replace(/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/gi, "[redacted-email]")
721
+ .replace(/\b\d{3}-\d{2}-\d{4}\b/g, "[redacted-ssn]")
722
+ .replace(/(?<!\d)(?:\+?1[-.\s]?)?\(?\d{3}\)?[-.\s]\d{3}[-.\s]\d{4}\b/g, "[redacted-phone]");
723
+ }
724
+
725
+ function redactStructuredText(value) {
726
+ const decoded = decodeSensitiveString(value);
727
+ if (decoded && containsSensitiveString(decoded)) return REDACTED;
728
+
729
+ const exact = parseJsonAst(value);
730
+ if (exact !== undefined) return stringifyRedactedAst(value, exact);
731
+
732
+ return redactEmbeddedJsonAsts(value);
733
+ }
734
+
735
+ function stringifyRedactedAst(source, ast) {
736
+ const redacted = redactObject(ast);
737
+ const before = JSON.stringify(ast);
738
+ const after = JSON.stringify(redacted);
739
+ return before === after ? source : after;
740
+ }
741
+
742
+ function redactEmbeddedJsonAsts(value) {
743
+ if (value.length > STRUCTURED_REDACTION_LIMIT) return value;
744
+ let output = "";
745
+ let cursor = 0;
746
+ for (let index = 0; index < value.length; index += 1) {
747
+ const open = value[index];
748
+ if (open !== "{" && open !== "[") continue;
749
+ const close = open === "{" ? "}" : "]";
750
+ let depth = 0;
751
+ let inString = false;
752
+ let escaped = false;
753
+ for (let end = index; end < value.length; end += 1) {
754
+ const char = value[end];
755
+ if (inString) {
756
+ if (escaped) {
757
+ escaped = false;
758
+ } else if (char === "\\") {
759
+ escaped = true;
760
+ } else if (char === "\"") {
761
+ inString = false;
762
+ }
763
+ continue;
764
+ }
765
+ if (char === "\"") {
766
+ inString = true;
767
+ continue;
768
+ }
769
+ if (char === open) depth += 1;
770
+ if (char === close) depth -= 1;
771
+ if (depth !== 0) continue;
772
+ const fragment = value.slice(index, end + 1);
773
+ const ast = parseJsonAst(fragment);
774
+ if (ast !== undefined) {
775
+ output += value.slice(cursor, index) + stringifyRedactedAst(fragment, ast);
776
+ cursor = end + 1;
777
+ index = end;
778
+ }
779
+ break;
780
+ }
781
+ }
782
+ return cursor === 0 ? value : output + value.slice(cursor);
783
+ }
784
+
785
+ function parseJsonAst(value) {
786
+ const trimmed = value.trim();
787
+ if (trimmed.length === 0 || trimmed.length > STRUCTURED_REDACTION_LIMIT) return undefined;
788
+ if (!trimmed.startsWith("{") && !trimmed.startsWith("[")) return undefined;
789
+ try {
790
+ return JSON.parse(trimmed);
791
+ } catch {
792
+ return undefined;
793
+ }
794
+ }
795
+
796
+ function decodeSensitiveString(value) {
797
+ const compact = value.trim();
798
+ if (compact.length < 16 || compact.length > 8192 || compact.length % 4 !== 0 || !/^[A-Za-z0-9+/]+={0,2}$/.test(compact)) return undefined;
799
+ try {
800
+ const decoded = Buffer.from(compact, "base64").toString("utf8");
801
+ if (!decoded || /[\u0000-\u0008\u000E-\u001F]/.test(decoded)) return undefined;
802
+ return decoded;
803
+ } catch {
804
+ return undefined;
805
+ }
806
+ }
807
+
808
+ function containsSensitiveString(value) {
809
+ const normalized = normalizeSecurityText(value);
810
+ return /["']?\b(api[_-]?key|tokenValue|token|password|credential|clientSecret|plaintext|authorization|cookie|session)\b["']?\s*[:=]/i.test(normalized)
811
+ || /[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/i.test(normalized)
812
+ || /\b\d{3}-\d{2}-\d{4}\b/.test(normalized)
813
+ || /(?<!\d)(?:\+?1[-.\s]?)?\(?\d{3}\)?[-.\s]\d{3}[-.\s]\d{4}\b/.test(normalized)
814
+ || containsSensitiveJson(normalized);
815
+ }
816
+
817
+ function containsSensitiveJson(value) {
818
+ const ast = parseJsonAst(value);
819
+ return ast !== undefined && hasSensitiveJsonKey(ast);
820
+ }
821
+
822
+ function hasSensitiveJsonKey(value) {
823
+ if (Array.isArray(value)) return value.some(hasSensitiveJsonKey);
824
+ if (value === null || typeof value !== "object") return false;
825
+ return Object.entries(value).some(([key, child]) => isSensitiveField(key) || hasSensitiveJsonKey(child));
826
+ }
827
+
828
+ function isSensitiveField(key) {
829
+ const normalized = normalizeFieldKey(key);
830
+ return SENSITIVE_FIELD_PATTERN.test(key)
831
+ || SENSITIVE_TOKEN_FIELD_PATTERN.test(key)
832
+ || SENSITIVE_FIELD_PATTERN.test(normalized)
833
+ || SENSITIVE_TOKEN_FIELD_PATTERN.test(normalized);
834
+ }
835
+
836
+ function isSecretRefField(key) {
837
+ const normalized = normalizeFieldKey(key);
838
+ return normalized === "secretref" || normalized === "secretrefs";
839
+ }
840
+
841
+ function isSecretRefRecord(value) {
842
+ return value
843
+ && typeof value === "object"
844
+ && !Array.isArray(value)
845
+ && value.schemaVersion === "2026-06-09"
846
+ && typeof value.secretId === "string"
847
+ && /^sec_[a-z0-9][a-z0-9_-]*$/.test(value.secretId)
848
+ && typeof value.provider === "string"
849
+ && typeof value.scope === "string"
850
+ && typeof value.redactionClass === "string"
851
+ && typeof value.createdAt === "string";
852
+ }
853
+
854
+ function normalizeFieldKey(key) {
855
+ return String(key).toLowerCase().replace(/[^a-z0-9]/g, "");
856
+ }
857
+
858
+ function normalizeSecurityText(value) {
859
+ return String(value).normalize("NFKC").replace(SECURITY_FORMAT_CHARS, "");
860
+ }
861
+
862
+ function adaptOAuthAuditEvent(event = {}) {
863
+ const actorId = event.ownerId ?? event.requesterOwnerId ?? "actor_system";
864
+ const summaryParts = [event.eventType];
865
+ if (event.audience) summaryParts.push(`audience=${event.audience}`);
866
+ if (event.resource) summaryParts.push(`resource=${event.resource}`);
867
+ if (event.reason) summaryParts.push(`reason=${event.reason}`);
868
+ return {
869
+ actorId,
870
+ eventType: event.eventType ?? "oauth.token.event",
871
+ resourceRef: event.tokenId ?? "resource_unknown",
872
+ outcome: event.outcome ?? "recorded",
873
+ summary: summaryParts.filter(Boolean).join(" "),
874
+ metadata: {
875
+ ownerId: event.ownerId,
876
+ orgId: event.orgId,
877
+ requesterOwnerId: event.requesterOwnerId,
878
+ requesterOrgId: event.requesterOrgId,
879
+ },
880
+ };
881
+ }
882
+
883
+ function makeId(prefix, ...parts) {
884
+ const body = parts
885
+ .filter((part) => part !== undefined && part !== null)
886
+ .join("_")
887
+ .toLowerCase()
888
+ .replace(/^(run|task|agent|actor|dream|evt|tool|art|grant|approval|secret|aud|key|act)_/g, "")
889
+ .replace(/[^a-z0-9_]+/g, "_")
890
+ .replace(/^_+|_+$/g, "")
891
+ .slice(0, 72);
892
+ return `${prefix}_${body || "record"}`;
893
+ }
894
+
895
+ function sha256(value) {
896
+ return `sha256:${createHash("sha256").update(value).digest("hex")}`;
897
+ }