@seekrit/cli 2.5.1 → 2.7.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 (2) hide show
  1. package/dist/index.js +1892 -1094
  2. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { chmodSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, writeFileSync } from "node:fs";
3
- import { z } from "zod";
3
+ import * as z$1 from "zod";
4
4
  import { Command } from "commander";
5
5
  import { arch, homedir, hostname, platform, tmpdir, userInfo } from "node:os";
6
6
  import { basename, dirname, join, parse, resolve } from "node:path";
@@ -17,48 +17,48 @@ const POLICY_DEFAULT_TTL_SECONDS = 604800;
17
17
  const POLICY_MIN_TTL_SECONDS = 3600;
18
18
  const POLICY_MAX_TTL_SECONDS = 7776e3;
19
19
  /** A bare hostname: no scheme, no port, no path, no wildcard. */
20
- const policyHostSchema = z.string().trim().min(1).max(253).toLowerCase().refine((h) => !/[:/\s*]/.test(h), { message: "host must be a bare hostname (no scheme, port, path, or wildcard)" }).refine((h) => /^[a-z0-9.-]+$/.test(h), { message: "host contains invalid characters" });
21
- const policyMethodSchema = z.string().trim().toUpperCase().regex(/^[A-Z]{3,10}$/, "method must be an HTTP method name");
20
+ const policyHostSchema = z$1.string().trim().min(1).max(253).toLowerCase().refine((h) => !/[:/\s*]/.test(h), { message: "host must be a bare hostname (no scheme, port, path, or wildcard)" }).refine((h) => /^[a-z0-9.-]+$/.test(h), { message: "host contains invalid characters" });
21
+ const policyMethodSchema = z$1.string().trim().toUpperCase().regex(/^[A-Z]{3,10}$/, "method must be an HTTP method name");
22
22
  /**
23
23
  * A path pattern. Must be absolute, because it is matched against a request
24
24
  * path — a relative pattern is a mistake that would silently match nothing.
25
25
  */
26
- const policyPathSchema = z.string().trim().min(1).max(512).startsWith("/", "path pattern must start with /").refine((p) => !p.includes("?"), { message: "path patterns match the path only, not the query" });
27
- const policySecretNameSchema = z.string().trim().regex(/^[A-Za-z0-9_]+$/, "secret names are letters, digits, and underscores");
26
+ const policyPathSchema = z$1.string().trim().min(1).max(512).startsWith("/", "path pattern must start with /").refine((p) => !p.includes("?"), { message: "path patterns match the path only, not the query" });
27
+ const policySecretNameSchema = z$1.string().trim().regex(/^[A-Za-z0-9_]+$/, "secret names are letters, digits, and underscores");
28
28
  /** A TCP port. 0 is refused: it never matches a connection, so a rule naming it is a mistake. */
29
- const policyPortSchema = z.number().int().min(1).max(65535);
30
- const agentPolicyRuleSchema = z.object({
29
+ const policyPortSchema = z$1.number().int().min(1).max(65535);
30
+ const agentPolicyRuleSchema = z$1.object({
31
31
  host: policyHostSchema,
32
- methods: z.array(policyMethodSchema).max(16).default([]),
33
- paths: z.array(policyPathSchema).max(64).default([]),
34
- allow: z.array(policySecretNameSchema).max(64).default([]),
35
- https_ports: z.array(policyPortSchema).max(32).optional(),
36
- http_ports: z.array(policyPortSchema).max(32).optional(),
37
- label: z.string().trim().max(120).optional()
32
+ methods: z$1.array(policyMethodSchema).max(16).default([]),
33
+ paths: z$1.array(policyPathSchema).max(64).default([]),
34
+ allow: z$1.array(policySecretNameSchema).max(64).default([]),
35
+ https_ports: z$1.array(policyPortSchema).max(32).optional(),
36
+ http_ports: z$1.array(policyPortSchema).max(32).optional(),
37
+ label: z$1.string().trim().max(120).optional()
38
38
  });
39
- z.object({
39
+ z$1.object({
40
40
  /** `ap1.<body>.<signature>` — opaque to the server. */
41
- bundle: z.string().min(16).max(262144) });
42
- z.object({
43
- name: z.string().trim().min(1).max(120),
44
- slug: z.string().trim().min(1).max(64).regex(/^[a-z0-9][a-z0-9-]*$/, "slug is lowercase letters, digits, and dashes"),
41
+ bundle: z$1.string().min(16).max(262144) });
42
+ z$1.object({
43
+ name: z$1.string().trim().min(1).max(120),
44
+ slug: z$1.string().trim().min(1).max(64).regex(/^[a-z0-9][a-z0-9-]*$/, "slug is lowercase letters, digits, and dashes"),
45
45
  /** The environment whose secrets this agent's policy may name. Optional. */
46
- environmentId: z.string().trim().min(1).max(64).optional()
46
+ environmentId: z$1.string().trim().min(1).max(64).optional()
47
47
  });
48
- z.object({
49
- name: z.string().trim().min(1).max(120).optional(),
50
- enabled: z.boolean().optional(),
51
- environmentId: z.string().trim().min(1).max(64).nullish()
48
+ z$1.object({
49
+ name: z$1.string().trim().min(1).max(120).optional(),
50
+ enabled: z$1.boolean().optional(),
51
+ environmentId: z$1.string().trim().min(1).max(64).nullish()
52
52
  });
53
- z.object({
53
+ z$1.object({
54
54
  host: policyHostSchema,
55
55
  /** How the agent reaches the host. Omit for a destination the operator fixed. */
56
- transport: z.object({
57
- scheme: z.enum(["https", "http"]),
56
+ transport: z$1.object({
57
+ scheme: z$1.enum(["https", "http"]),
58
58
  port: policyPortSchema
59
59
  }).optional(),
60
60
  method: policyMethodSchema,
61
- path: z.string().trim().min(1).max(2048),
61
+ path: z$1.string().trim().min(1).max(2048),
62
62
  secret: policySecretNameSchema.optional()
63
63
  });
64
64
  /**
@@ -170,7 +170,7 @@ async function policySignerThumbprint(jwk) {
170
170
  y: jwk.y
171
171
  });
172
172
  const digest = await crypto.subtle.digest("SHA-256", utf8(canonical));
173
- return base64url(new Uint8Array(digest));
173
+ return base64url$1(new Uint8Array(digest));
174
174
  }
175
175
  /**
176
176
  * Sign a draft bundle with the publishing admin's key, returning the `ap1.`
@@ -197,8 +197,8 @@ async function signAgentPolicy(privateKey, signerJwk, draft) {
197
197
  }, privateKey, bytes));
198
198
  return [
199
199
  "ap1",
200
- base64url(bytes),
201
- base64url(sig)
200
+ base64url$1(bytes),
201
+ base64url$1(sig)
202
202
  ].join(".");
203
203
  }
204
204
  /** A structurally invalid, unverifiable, or expired bundle. */
@@ -386,7 +386,7 @@ function utf8(text) {
386
386
  function utf8Decode$1(bytes) {
387
387
  return new TextDecoder().decode(bytes);
388
388
  }
389
- function base64url(bytes) {
389
+ function base64url$1(bytes) {
390
390
  let binary = "";
391
391
  for (const b of bytes) binary += String.fromCharCode(b);
392
392
  return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
@@ -399,10 +399,10 @@ function fromBase64url(text) {
399
399
  return out;
400
400
  }
401
401
  /** One aggregated cell: a dimension tuple and how many times it happened. */
402
- const activityEntrySchema = z.object({
402
+ const activityEntrySchema = z$1.object({
403
403
  host: policyHostSchema,
404
404
  method: policyMethodSchema,
405
- decision: z.enum([
405
+ decision: z$1.enum([
406
406
  "allow",
407
407
  "no_rule",
408
408
  "port_not_allowed",
@@ -419,27 +419,27 @@ const activityEntrySchema = z.object({
419
419
  * a review, because "rule 3 refused this" and "nothing covered this" call for
420
420
  * opposite changes.
421
421
  */
422
- ruleIndex: z.number().int().min(0).max(255).nullable(),
423
- count: z.number().int().min(1).max(1e6),
422
+ ruleIndex: z$1.number().int().min(0).max(255).nullable(),
423
+ count: z$1.number().int().min(1).max(1e6),
424
424
  /**
425
425
  * Secret names actually injected, name → count. Only meaningful on `allow`.
426
426
  * This is what lets a review say "rule 2 permits three secrets and the agent
427
427
  * has only ever used one" — the most useful narrowing there is, and impossible
428
428
  * to see from policy alone.
429
429
  */
430
- secrets: z.record(policySecretNameSchema, z.number().int().min(1)).optional()
430
+ secrets: z$1.record(policySecretNameSchema, z$1.number().int().min(1)).optional()
431
431
  });
432
- z.object({
432
+ z$1.object({
433
433
  /** Start of the window these counts cover (ISO 8601). */
434
- windowStart: z.string().trim().min(20).max(40),
434
+ windowStart: z$1.string().trim().min(20).max(40),
435
435
  /** Policy version in force while they were collected, for the ledger. */
436
- policyVersion: z.number().int().min(0).optional(),
436
+ policyVersion: z$1.number().int().min(0).optional(),
437
437
  /**
438
438
  * Capped so one report cannot be unbounded work. A proxy with more distinct
439
439
  * cells than this in a window has a policy far broader than a review can help
440
440
  * with, and truncating loudly beats accepting anything.
441
441
  */
442
- entries: z.array(activityEntrySchema).min(1).max(500)
442
+ entries: z$1.array(activityEntrySchema).min(1).max(500)
443
443
  });
444
444
  // ../../packages/core/src/agent-login.ts
445
445
  /** Where each kind of login is stored unless told otherwise. */
@@ -703,38 +703,38 @@ function countApplicable(proposals) {
703
703
  */
704
704
  const TASK_MAX_TTL_SECONDS = 43200;
705
705
  /** An EC P-256 public JWK, for a sender-constraint proof key. */
706
- const taskProofJwkSchema = z.object({
707
- kty: z.literal("EC"),
708
- crv: z.literal("P-256"),
709
- x: z.string().min(1).max(128),
710
- y: z.string().min(1).max(128)
706
+ const taskProofJwkSchema = z$1.object({
707
+ kty: z$1.literal("EC"),
708
+ crv: z$1.literal("P-256"),
709
+ x: z$1.string().min(1).max(128),
710
+ y: z$1.string().min(1).max(128)
711
711
  });
712
- z.object({
712
+ z$1.object({
713
713
  /**
714
714
  * The public `skd_…` segment of the minted token. Sent because the API never
715
715
  * sees the token at dispatch and still needs a readable handle for the audit
716
716
  * row and for a revoke to name — the id half of a credential, without the
717
717
  * secret half.
718
718
  */
719
- taskRef: z.string().trim().regex(/^skd_[0-9A-Za-z]+$/, "taskRef must be the skd_… segment of the minted token"),
719
+ taskRef: z$1.string().trim().regex(/^skd_[0-9A-Za-z]+$/, "taskRef must be the skd_… segment of the minted token"),
720
720
  /**
721
721
  * SHA-256 (base64url) of the token the dispatcher minted. The token itself
722
722
  * never reaches this API on the dispatch path — only on introspection, where
723
723
  * it is hashed and discarded.
724
724
  */
725
- tokenHash: z.string().trim().min(16).max(128),
725
+ tokenHash: z$1.string().trim().min(16).max(128),
726
726
  /**
727
727
  * Secret names this run may use. Omit for "whatever the agent's policy
728
728
  * allows" — mirroring `Session.scopes: Option<BTreeSet<String>>` in the proxy,
729
729
  * so absent means unnarrowed in both places.
730
730
  */
731
- scopes: z.array(policySecretNameSchema).max(64).optional(),
732
- ttlSeconds: z.number().int().min(60).max(TASK_MAX_TTL_SECONDS).optional(),
731
+ scopes: z$1.array(policySecretNameSchema).max(64).optional(),
732
+ ttlSeconds: z$1.number().int().min(60).max(TASK_MAX_TTL_SECONDS).optional(),
733
733
  /**
734
734
  * What this run is for, for the audit row and the operator's task list. Free
735
735
  * text, and **not** a security input: never put a secret value in it.
736
736
  */
737
- label: z.string().trim().max(200).optional(),
737
+ label: z$1.string().trim().max(200).optional(),
738
738
  /**
739
739
  * Public half of a proof key the presenter holds, recorded as an RFC 7638
740
740
  * thumbprint. See `AgentTaskSession.proofThumbprint` for what this does and —
@@ -742,9 +742,9 @@ z.object({
742
742
  */
743
743
  proofJwk: taskProofJwkSchema.optional()
744
744
  });
745
- z.object({
745
+ z$1.object({
746
746
  /** The presented token. In the body, never a URL — it is a credential. */
747
- token: z.string().trim().min(8).max(512) });
747
+ token: z$1.string().trim().min(8).max(512) });
748
748
  // ../../packages/core/src/archive.ts
749
749
  /**
750
750
  * The **break-glass archive** format: one signed JSON file holding everything
@@ -920,43 +920,43 @@ async function verifySignature(manifest, signature) {
920
920
  const publicKey = await crypto.subtle.importKey("raw", hexToBytes(signature.publicKey), { name: "Ed25519" }, false, ["verify"]);
921
921
  return crypto.subtle.verify({ name: "Ed25519" }, publicKey, hexToBytes(signature.value), signingPayload(manifest));
922
922
  }
923
- const sectionHeaderSchema = z.object({
924
- name: z.enum(ARCHIVE_SECTIONS),
925
- count: z.number().int().min(0),
926
- truncated: z.boolean(),
927
- digest: z.string().regex(/^sha256:[0-9a-f]{64}$/)
923
+ const sectionHeaderSchema = z$1.object({
924
+ name: z$1.enum(ARCHIVE_SECTIONS),
925
+ count: z$1.number().int().min(0),
926
+ truncated: z$1.boolean(),
927
+ digest: z$1.string().regex(/^sha256:[0-9a-f]{64}$/)
928
928
  });
929
- const manifestSchema = z.object({
930
- archiveId: z.string().min(1),
931
- createdAt: z.string().min(1),
932
- org: z.object({
933
- id: z.string(),
934
- slug: z.string(),
935
- name: z.string()
929
+ const manifestSchema = z$1.object({
930
+ archiveId: z$1.string().min(1),
931
+ createdAt: z$1.string().min(1),
932
+ org: z$1.object({
933
+ id: z$1.string(),
934
+ slug: z$1.string(),
935
+ name: z$1.string()
936
936
  }),
937
- producer: z.object({
938
- service: z.string(),
939
- environment: z.string(),
940
- formatVersion: z.string()
937
+ producer: z$1.object({
938
+ service: z$1.string(),
939
+ environment: z$1.string(),
940
+ formatVersion: z$1.string()
941
941
  }),
942
- requestedBy: z.object({
943
- actorType: z.string(),
944
- actorId: z.string(),
945
- label: z.string().nullable()
942
+ requestedBy: z$1.object({
943
+ actorType: z$1.string(),
944
+ actorId: z$1.string(),
945
+ label: z$1.string().nullable()
946
946
  }),
947
- options: z.object({
948
- includeVersions: z.boolean(),
949
- includeAudit: z.boolean(),
950
- auditLimit: z.number().int().min(0)
947
+ options: z$1.object({
948
+ includeVersions: z$1.boolean(),
949
+ includeAudit: z$1.boolean(),
950
+ auditLimit: z$1.number().int().min(0)
951
951
  }),
952
- sections: z.array(sectionHeaderSchema),
953
- digest: z.string().regex(/^sha256:[0-9a-f]{64}$/)
952
+ sections: z$1.array(sectionHeaderSchema),
953
+ digest: z$1.string().regex(/^sha256:[0-9a-f]{64}$/)
954
954
  });
955
- const signatureSchema = z.object({
956
- algorithm: z.literal("ed25519"),
957
- publicKey: z.string().regex(/^[0-9a-f]{64}$/),
958
- keyId: z.string().regex(/^[0-9a-f]{16}$/),
959
- value: z.string().regex(/^[0-9a-f]{128}$/)
955
+ const signatureSchema = z$1.object({
956
+ algorithm: z$1.literal("ed25519"),
957
+ publicKey: z$1.string().regex(/^[0-9a-f]{64}$/),
958
+ keyId: z$1.string().regex(/^[0-9a-f]{16}$/),
959
+ value: z$1.string().regex(/^[0-9a-f]{128}$/)
960
960
  });
961
961
  /**
962
962
  * Envelope schema. `data` is validated only as an object: a v1 verifier must
@@ -965,11 +965,11 @@ const signatureSchema = z.object({
965
965
  * `verifyArchive`'s undeclared/declared cross-check rather than by rejecting
966
966
  * the file outright.
967
967
  */
968
- const archiveSchema = z.object({
969
- format: z.literal(ARCHIVE_FORMAT),
968
+ const archiveSchema = z$1.object({
969
+ format: z$1.literal(ARCHIVE_FORMAT),
970
970
  manifest: manifestSchema,
971
971
  signature: signatureSchema.nullable(),
972
- data: z.record(z.string(), z.unknown())
972
+ data: z$1.record(z$1.string(), z$1.unknown())
973
973
  });
974
974
  /** Parse untrusted JSON text into an archive. Throws with a readable message. */
975
975
  function parseArchive(text) {
@@ -1238,15 +1238,15 @@ function describeChange(kind, name, restoreFrom) {
1238
1238
  }
1239
1239
  // ../../packages/core/src/connect.ts
1240
1240
  /** Workload authentication is separate from secret-decryption principals. */
1241
- const workloadPublicKeySchema = z.object({
1242
- kty: z.literal("EC"),
1243
- crv: z.literal("P-256"),
1244
- x: z.string().regex(/^[A-Za-z0-9_-]{43}$/),
1245
- y: z.string().regex(/^[A-Za-z0-9_-]{43}$/)
1241
+ const workloadPublicKeySchema = z$1.object({
1242
+ kty: z$1.literal("EC"),
1243
+ crv: z$1.literal("P-256"),
1244
+ x: z$1.string().regex(/^[A-Za-z0-9_-]{43}$/),
1245
+ y: z$1.string().regex(/^[A-Za-z0-9_-]{43}$/)
1246
1246
  }).strict();
1247
- const audienceSchema = z.string().min(1).max(256).regex(/^[^\s]+$/);
1247
+ const audienceSchema = z$1.string().min(1).max(256).regex(/^[^\s]+$/);
1248
1248
  /** HTTPS endpoint syntax. Resolved-address safety is enforced by the server runtime. */
1249
- const connectUrlSchema = z.string().max(2048).url().refine((value) => {
1249
+ const connectUrlSchema = z$1.string().max(2048).url().refine((value) => {
1250
1250
  try {
1251
1251
  const u = new URL(value);
1252
1252
  return u.protocol === "https:" && !u.username && !u.password && !u.hash && !u.search && !u.port && u.hostname.length <= 253 && u.hostname.split(".").every((label) => /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/.test(label)) && u.hostname.includes(".") && !/^[0-9.]+$/.test(u.hostname) && !u.hostname.endsWith(".") && !/(^|\.)(localhost|local|localdomain|internal|invalid|home|home\.arpa|onion)$/.test(u.hostname);
@@ -1254,12 +1254,12 @@ const connectUrlSchema = z.string().max(2048).url().refine((value) => {
1254
1254
  return false;
1255
1255
  }
1256
1256
  }, "use a public HTTPS hostname without credentials, query, fragment, or port");
1257
- const federationPolicySchema = z.object({
1257
+ const federationPolicySchema = z$1.object({
1258
1258
  issuer: connectUrlSchema,
1259
1259
  jwksUri: connectUrlSchema,
1260
1260
  audience: audienceSchema,
1261
- subject: z.string().min(1).max(512),
1262
- claims: z.record(z.string().regex(/^[a-zA-Z][a-zA-Z0-9_]{0,63}$/), z.string().min(1).max(512)).refine((claims) => Object.keys(claims).length <= 20 && Object.keys(claims).every((key) => ![
1261
+ subject: z$1.string().min(1).max(512),
1262
+ claims: z$1.record(z$1.string().regex(/^[a-zA-Z][a-zA-Z0-9_]{0,63}$/), z$1.string().min(1).max(512)).refine((claims) => Object.keys(claims).length <= 20 && Object.keys(claims).every((key) => ![
1263
1263
  "iss",
1264
1264
  "aud",
1265
1265
  "sub",
@@ -1268,29 +1268,29 @@ const federationPolicySchema = z.object({
1268
1268
  "nbf"
1269
1269
  ].includes(key))).default({})
1270
1270
  }).strict();
1271
- z.object({
1272
- name: z.string().trim().min(1).max(100),
1273
- environmentId: z.string().min(1).max(128),
1271
+ z$1.object({
1272
+ name: z$1.string().trim().min(1).max(100),
1273
+ environmentId: z$1.string().min(1).max(128),
1274
1274
  publicKey: workloadPublicKeySchema.optional(),
1275
1275
  federation: federationPolicySchema.optional(),
1276
- audiences: z.array(audienceSchema).max(20).default([]),
1277
- maxTtlSeconds: z.number().int().min(60).max(900).default(300)
1276
+ audiences: z$1.array(audienceSchema).max(20).default([]),
1277
+ maxTtlSeconds: z$1.number().int().min(60).max(900).default(300)
1278
1278
  }).strict().refine((v) => !!v.publicKey !== !!v.federation, "choose a public key or a federation policy");
1279
- z.object({
1280
- enabled: z.boolean().optional(),
1279
+ z$1.object({
1280
+ enabled: z$1.boolean().optional(),
1281
1281
  publicKey: workloadPublicKeySchema.optional()
1282
1282
  }).strict().refine((v) => v.enabled !== void 0 || v.publicKey !== void 0);
1283
- const githubPermissionsSchema = z.record(z.string().regex(/^[a-z_]{1,64}$/), z.enum(["read", "write"])).refine((p) => Object.keys(p).length > 0 && Object.keys(p).length <= 40, "specify between 1 and 40 permissions");
1284
- const githubScopeSchema = z.object({
1285
- repositoryIds: z.array(z.number().int().positive().max(Number.MAX_SAFE_INTEGER)).min(1).max(100),
1283
+ const githubPermissionsSchema = z$1.record(z$1.string().regex(/^[a-z_]{1,64}$/), z$1.enum(["read", "write"])).refine((p) => Object.keys(p).length > 0 && Object.keys(p).length <= 40, "specify between 1 and 40 permissions");
1284
+ const githubScopeSchema = z$1.object({
1285
+ repositoryIds: z$1.array(z$1.number().int().positive().max(Number.MAX_SAFE_INTEGER)).min(1).max(100),
1286
1286
  permissions: githubPermissionsSchema
1287
1287
  }).strict();
1288
1288
  /** Exact paths or explicitly allowed descendants, without URL decoding ambiguity. */
1289
- const connectPathSchema = z.string().min(1).max(1024).refine((path) => /^\/[A-Za-z0-9_./~-]*$/.test(path) && !path.includes("//") && !path.split("/").some((part) => part === "." || part === ".."), "use an absolute API path without encoded characters or dot segments");
1290
- const proxyRuleSchema = z.object({
1289
+ const connectPathSchema = z$1.string().min(1).max(1024).refine((path) => /^\/[A-Za-z0-9_./~-]*$/.test(path) && !path.includes("//") && !path.split("/").some((part) => part === "." || part === ".."), "use an absolute API path without encoded characters or dot segments");
1290
+ const proxyRuleSchema = z$1.object({
1291
1291
  path: connectPathSchema,
1292
- descendants: z.boolean().default(false),
1293
- methods: z.array(z.enum([
1292
+ descendants: z$1.boolean().default(false),
1293
+ methods: z$1.array(z$1.enum([
1294
1294
  "GET",
1295
1295
  "POST",
1296
1296
  "PUT",
@@ -1299,18 +1299,18 @@ const proxyRuleSchema = z.object({
1299
1299
  "HEAD"
1300
1300
  ])).min(1).max(6)
1301
1301
  }).strict();
1302
- const staticScopeSchema = z.object({ rules: z.array(proxyRuleSchema).min(1).max(30) }).strict();
1303
- const oauthScopeSchema = z.object({ scopes: z.array(z.string().regex(/^[\x21\x23-\x5b\x5d-\x7e]{1,200}$/)).min(1).max(50).refine((scopes) => new Set(scopes).size === scopes.length, "scopes must be unique") }).strict();
1302
+ const staticScopeSchema = z$1.object({ rules: z$1.array(proxyRuleSchema).min(1).max(30) }).strict();
1303
+ const oauthScopeSchema = z$1.object({ scopes: z$1.array(z$1.string().regex(/^[\x21\x23-\x5b\x5d-\x7e]{1,200}$/)).min(1).max(50).refine((scopes) => new Set(scopes).size === scopes.length, "scopes must be unique") }).strict();
1304
1304
  const oauthConfigSchema = oauthScopeSchema.extend({
1305
- provider: z.literal("oauth"),
1306
- grantType: z.enum(["client_credentials", "authorization_code"]),
1307
- clientId: z.string().min(1).max(512),
1305
+ provider: z$1.literal("oauth"),
1306
+ grantType: z$1.enum(["client_credentials", "authorization_code"]),
1307
+ clientId: z$1.string().min(1).max(512),
1308
1308
  tokenEndpoint: connectUrlSchema,
1309
1309
  authorizationEndpoint: connectUrlSchema.optional(),
1310
- tokenAuthMethod: z.enum(["client_secret_basic", "client_secret_post"]).default("client_secret_basic")
1310
+ tokenAuthMethod: z$1.enum(["client_secret_basic", "client_secret_post"]).default("client_secret_basic")
1311
1311
  });
1312
1312
  const customApiConfigSchema = staticScopeSchema.extend({
1313
- provider: z.literal("custom_api"),
1313
+ provider: z$1.literal("custom_api"),
1314
1314
  origin: connectUrlSchema.refine((value) => {
1315
1315
  try {
1316
1316
  return new URL(value).pathname === "/";
@@ -1318,46 +1318,46 @@ const customApiConfigSchema = staticScopeSchema.extend({
1318
1318
  return false;
1319
1319
  }
1320
1320
  }, "use an origin without a path"),
1321
- headerName: z.string().regex(/^[A-Za-z][A-Za-z0-9-]{0,63}$/).refine((v) => !/^(accept$|user-agent$|host|cookie|content-|proxy-|forwarded|x-forwarded-|cf-|connection|transfer-encoding|upgrade|trailer|te$)/i.test(v)),
1322
- headerPrefix: z.string().max(64).regex(/^[\x20-\x7e]*$/).default("Bearer ")
1321
+ headerName: z$1.string().regex(/^[A-Za-z][A-Za-z0-9-]{0,63}$/).refine((v) => !/^(accept$|user-agent$|host|cookie|content-|proxy-|forwarded|x-forwarded-|cf-|connection|transfer-encoding|upgrade|trailer|te$)/i.test(v)),
1322
+ headerPrefix: z$1.string().max(64).regex(/^[\x20-\x7e]*$/).default("Bearer ")
1323
1323
  });
1324
- const connectConfigSchema = z.discriminatedUnion("provider", [
1324
+ const connectConfigSchema = z$1.discriminatedUnion("provider", [
1325
1325
  customApiConfigSchema,
1326
1326
  oauthConfigSchema,
1327
1327
  githubScopeSchema.extend({
1328
- provider: z.literal("github_app"),
1329
- appId: z.string().regex(/^[A-Za-z0-9_.-]{1,128}$/),
1330
- installationId: z.string().regex(/^[1-9][0-9]{0,19}$/)
1328
+ provider: z$1.literal("github_app"),
1329
+ appId: z$1.string().regex(/^[A-Za-z0-9_.-]{1,128}$/),
1330
+ installationId: z$1.string().regex(/^[1-9][0-9]{0,19}$/)
1331
1331
  }),
1332
1332
  staticScopeSchema.extend({
1333
- provider: z.literal("static_key"),
1334
- service: z.literal("resend"),
1335
- rules: z.array(proxyRuleSchema.refine((rule) => rule.path === "/emails" || rule.path.startsWith("/emails/"), "the Resend connector supports only /emails and its descendants")).min(1).max(30)
1333
+ provider: z$1.literal("static_key"),
1334
+ service: z$1.literal("resend"),
1335
+ rules: z$1.array(proxyRuleSchema.refine((rule) => rule.path === "/emails" || rule.path.startsWith("/emails/"), "the Resend connector supports only /emails and its descendants")).min(1).max(30)
1336
1336
  })
1337
1337
  ]).refine((v) => v.provider !== "oauth" || v.grantType !== "authorization_code" || !!v.authorizationEndpoint, "authorization-code connections require an authorization endpoint");
1338
- const connectGrantPolicySchema = z.discriminatedUnion("provider", [
1339
- staticScopeSchema.extend({ provider: z.literal("custom_api") }),
1340
- oauthScopeSchema.extend({ provider: z.literal("oauth") }),
1341
- githubScopeSchema.extend({ provider: z.literal("github_app") }),
1342
- staticScopeSchema.extend({ provider: z.literal("static_key") })
1338
+ const connectGrantPolicySchema = z$1.discriminatedUnion("provider", [
1339
+ staticScopeSchema.extend({ provider: z$1.literal("custom_api") }),
1340
+ oauthScopeSchema.extend({ provider: z$1.literal("oauth") }),
1341
+ githubScopeSchema.extend({ provider: z$1.literal("github_app") }),
1342
+ staticScopeSchema.extend({ provider: z$1.literal("static_key") })
1343
1343
  ]);
1344
- z.object({
1345
- name: z.string().trim().min(1).max(100),
1344
+ z$1.object({
1345
+ name: z$1.string().trim().min(1).max(100),
1346
1346
  config: connectConfigSchema,
1347
- credentialWrapped: z.string().startsWith("wd1.").max(32e3)
1347
+ credentialWrapped: z$1.string().startsWith("wd1.").max(32e3)
1348
1348
  }).strict();
1349
- z.object({
1350
- enabled: z.boolean().optional(),
1351
- credentialWrapped: z.string().startsWith("wd1.").max(32e3).optional()
1349
+ z$1.object({
1350
+ enabled: z$1.boolean().optional(),
1351
+ credentialWrapped: z$1.string().startsWith("wd1.").max(32e3).optional()
1352
1352
  }).strict().refine((v) => v.enabled !== void 0 || v.credentialWrapped !== void 0);
1353
- z.object({
1354
- workloadId: z.string().min(1).max(128),
1355
- connectionId: z.string().min(1).max(128),
1353
+ z$1.object({
1354
+ workloadId: z$1.string().min(1).max(128),
1355
+ connectionId: z$1.string().min(1).max(128),
1356
1356
  policy: connectGrantPolicySchema
1357
1357
  }).strict();
1358
- z.object({
1358
+ z$1.object({
1359
1359
  path: connectPathSchema,
1360
- method: z.enum([
1360
+ method: z$1.enum([
1361
1361
  "GET",
1362
1362
  "POST",
1363
1363
  "PUT",
@@ -1365,11 +1365,11 @@ z.object({
1365
1365
  "DELETE",
1366
1366
  "HEAD"
1367
1367
  ]).default("GET"),
1368
- query: z.record(z.string().min(1).max(100), z.string().max(2048)).default({}),
1368
+ query: z$1.record(z$1.string().min(1).max(100), z$1.string().max(2048)).default({}),
1369
1369
  /** JSON only; callers cannot inject authorization or forwarding headers. */
1370
- body: z.string().max(65536).optional()
1370
+ body: z$1.string().max(65536).optional()
1371
1371
  }).strict().refine((v) => !["GET", "HEAD"].includes(v.method) || v.body === void 0, "GET and HEAD cannot carry a body");
1372
- z.object({ audience: audienceSchema }).strict();
1372
+ z$1.object({ audience: audienceSchema }).strict();
1373
1373
  // ../../packages/core/src/dotenv.ts
1374
1374
  /**
1375
1375
  * `.env` parsing and serialization — the canonical definition of what a `.env`
@@ -1752,44 +1752,268 @@ function prettyJsonOrRaw(value) {
1752
1752
  const inspection = inspectJsonValue(value);
1753
1753
  return inspection.kind === "json" ? inspection.pretty : value;
1754
1754
  }
1755
- z.enum([
1755
+ // ../../packages/core/src/managed-providers/aws-cache.ts
1756
+ const cacheRegionSchema = z$1.string().regex(/^[a-z]{2}(?:-[a-z]+)+-\d$/);
1757
+ const cacheGroupSchema = z$1.string().min(1).max(128).regex(/^[a-zA-Z][a-zA-Z0-9-]*$/);
1758
+ const cacheAccessSchema = z$1.string().min(1).max(4096).refine((value) => /^on(?:\s|$)/.test(value) && !/(?:^|\s)(?:nopass|resetpass|[>#<])/.test(value), "ACL must enable the user and must not contain password directives");
1759
+ // ../../packages/core/src/managed-providers/common.ts
1760
+ const managedEndpointSchema = z$1.string().url().max(2048).refine((value) => {
1761
+ try {
1762
+ const url = new URL(value);
1763
+ url.port = "";
1764
+ return connectUrlSchema.safeParse(url.toString()).success;
1765
+ } catch {
1766
+ return false;
1767
+ }
1768
+ }, "use a public HTTPS endpoint without embedded credentials, query, or fragment");
1769
+ const managedTtlSchema = z$1.number().int().min(60).max(604800).optional();
1770
+ const nameSchema$1 = z$1.string().min(1).max(128).regex(/^[a-zA-Z_][a-zA-Z0-9_-]*$/);
1771
+ // ../../packages/core/src/managed-providers/memorydb.ts
1772
+ const memorydbTargetConfigSchema = z$1.object({
1773
+ provider: z$1.literal("memorydb"),
1774
+ executor: z$1.literal("in_do"),
1775
+ region: cacheRegionSchema,
1776
+ aclName: cacheGroupSchema,
1777
+ accessString: cacheAccessSchema,
1778
+ maxTtlSeconds: managedTtlSchema
1779
+ }).strict();
1780
+ // ../../packages/core/src/managed-providers/elasticache.ts
1781
+ const elasticacheTargetConfigSchema = z$1.object({
1782
+ provider: z$1.literal("elasticache"),
1783
+ executor: z$1.literal("in_do"),
1784
+ region: cacheRegionSchema,
1785
+ userGroupId: cacheGroupSchema,
1786
+ engine: z$1.enum(["redis", "valkey"]).default("redis"),
1787
+ accessString: cacheAccessSchema,
1788
+ maxTtlSeconds: managedTtlSchema
1789
+ }).strict();
1790
+ // ../../packages/core/src/managed-providers/snowflake.ts
1791
+ const identifier = z$1.string().regex(/^[a-zA-Z_][a-zA-Z0-9_$]{0,254}$/).transform((value) => value.toUpperCase());
1792
+ const snowflakeTargetConfigSchema = z$1.object({
1793
+ provider: z$1.literal("snowflake"),
1794
+ executor: z$1.literal("in_do"),
1795
+ account: z$1.string().min(1).max(200).regex(/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)*$/i),
1796
+ adminRole: identifier.default("USERADMIN"),
1797
+ roles: z$1.array(identifier).min(1).max(50),
1798
+ warehouse: identifier.optional(),
1799
+ networkPolicy: identifier.optional(),
1800
+ maxTtlSeconds: managedTtlSchema
1801
+ }).strict();
1802
+ // ../../packages/core/src/managed-providers/couchbase.ts
1803
+ const resourceName = z$1.string().min(1).max(255);
1804
+ const access = z$1.object({
1805
+ privileges: z$1.array(z$1.enum(["data_reader", "data_writer"])).min(1).max(2),
1806
+ resources: z$1.object({ buckets: z$1.array(z$1.object({
1807
+ name: resourceName,
1808
+ scopes: z$1.array(z$1.object({
1809
+ name: resourceName,
1810
+ collections: z$1.array(resourceName).min(1).max(100).optional()
1811
+ }).strict()).min(1).max(100).optional()
1812
+ }).strict()).min(1).max(100) }).strict()
1813
+ }).strict();
1814
+ const couchbaseTargetConfigSchema = z$1.object({
1815
+ provider: z$1.literal("couchbase"),
1816
+ executor: z$1.literal("in_do"),
1817
+ organizationId: z$1.string().uuid(),
1818
+ projectId: z$1.string().uuid(),
1819
+ clusterId: z$1.string().uuid(),
1820
+ credentialType: z$1.enum(["basic", "advanced"]).default("basic"),
1821
+ access: z$1.array(access).min(1).max(100).optional(),
1822
+ userRoles: z$1.array(resourceName).min(1).max(100).optional(),
1823
+ maxTtlSeconds: managedTtlSchema
1824
+ }).strict().superRefine((value, ctx) => {
1825
+ if (value.credentialType === "basic" ? !value.access || !!value.userRoles : !value.userRoles || !!value.access) ctx.addIssue({
1826
+ code: "custom",
1827
+ message: "basic credentials require access only; advanced credentials require userRoles only"
1828
+ });
1829
+ });
1830
+ // ../../packages/core/src/managed-providers/mongodb-atlas.ts
1831
+ const mongoAtlasTargetConfigSchema = z$1.object({
1832
+ provider: z$1.literal("mongodb-atlas"),
1833
+ executor: z$1.literal("in_do"),
1834
+ projectId: z$1.string().regex(/^[a-f0-9]{24}$/),
1835
+ roles: z$1.array(z$1.object({
1836
+ roleName: z$1.string().min(1).max(128),
1837
+ databaseName: z$1.string().min(1).max(64),
1838
+ collectionName: z$1.string().min(1).max(128).optional()
1839
+ }).strict()).min(1).max(100),
1840
+ clusters: z$1.array(z$1.string().min(1).max(64)).min(1).max(100),
1841
+ maxTtlSeconds: managedTtlSchema
1842
+ }).strict();
1843
+ // ../../packages/core/src/managed-providers/milvus.ts
1844
+ const milvusTargetConfigSchema = z$1.object({
1845
+ provider: z$1.literal("milvus"),
1846
+ executor: z$1.literal("in_do"),
1847
+ endpoint: managedEndpointSchema,
1848
+ roles: z$1.array(z$1.string().regex(/^[a-zA-Z][a-zA-Z0-9_]{0,127}$/)).min(1).max(50),
1849
+ maxTtlSeconds: managedTtlSchema
1850
+ }).strict();
1851
+ // ../../packages/core/src/managed-providers/rabbitmq.ts
1852
+ const rabbitmqTargetConfigSchema = z$1.object({
1853
+ provider: z$1.literal("rabbitmq"),
1854
+ executor: z$1.literal("in_do"),
1855
+ endpoint: managedEndpointSchema,
1856
+ vhost: z$1.string().min(1).max(255),
1857
+ configure: z$1.string().max(2048).default("^$"),
1858
+ write: z$1.string().max(2048).default("^$"),
1859
+ read: z$1.string().max(2048).default("^$"),
1860
+ maxTtlSeconds: managedTtlSchema
1861
+ }).strict();
1862
+ // ../../packages/core/src/managed-providers/clickhouse.ts
1863
+ const clickhouseTargetConfigSchema = z$1.object({
1864
+ provider: z$1.literal("clickhouse"),
1865
+ executor: z$1.literal("in_do"),
1866
+ endpoint: managedEndpointSchema,
1867
+ roles: z$1.array(nameSchema$1).min(1).max(50),
1868
+ database: nameSchema$1.optional(),
1869
+ cluster: nameSchema$1.optional(),
1870
+ maxTtlSeconds: managedTtlSchema
1871
+ }).strict();
1872
+ // ../../packages/core/src/managed-providers/elasticsearch.ts
1873
+ const role = z$1.object({
1874
+ cluster: z$1.array(z$1.string().min(1).max(100)).max(100).default([]),
1875
+ indices: z$1.array(z$1.object({
1876
+ names: z$1.array(z$1.string().min(1).max(256)).min(1).max(100),
1877
+ privileges: z$1.array(z$1.string().min(1).max(100)).min(1).max(100),
1878
+ allow_restricted_indices: z$1.literal(false).optional()
1879
+ }).strict()).max(100).default([])
1880
+ }).strict();
1881
+ const elasticsearchTargetConfigSchema = z$1.object({
1882
+ provider: z$1.literal("elasticsearch"),
1883
+ executor: z$1.literal("in_do"),
1884
+ endpoint: managedEndpointSchema,
1885
+ credentialType: z$1.enum(["user", "api_key"]).default("user"),
1886
+ roles: z$1.array(z$1.string().min(1).max(128)).min(1).max(100).optional(),
1887
+ roleDescriptors: z$1.record(z$1.string().min(1).max(128), role).refine((value) => Object.keys(value).length > 0 && Object.keys(value).length <= 20, "supply explicit key permissions").optional(),
1888
+ maxTtlSeconds: managedTtlSchema
1889
+ }).strict().superRefine((value, ctx) => {
1890
+ if (value.credentialType === "user" && !value.roles?.length) ctx.addIssue({
1891
+ code: "custom",
1892
+ path: ["roles"],
1893
+ message: "select at least one user role"
1894
+ });
1895
+ if (value.credentialType === "api_key" && !value.roleDescriptors) ctx.addIssue({
1896
+ code: "custom",
1897
+ path: ["roleDescriptors"],
1898
+ message: "supply explicit key permissions"
1899
+ });
1900
+ });
1901
+ // ../../packages/core/src/managed-leases.ts
1902
+ /** Providers whose credential is generated by the broker or upstream service. */
1903
+ const MANAGED_LEASE_KINDS = [
1904
+ "openrouter",
1905
+ "tailscale",
1906
+ "elasticsearch",
1907
+ "clickhouse",
1908
+ "rabbitmq",
1909
+ "milvus",
1910
+ "mongodb-atlas",
1911
+ "couchbase",
1912
+ "snowflake",
1913
+ "elasticache",
1914
+ "memorydb"
1915
+ ];
1916
+ const openRouterTargetConfigSchema = z$1.object({
1917
+ provider: z$1.literal("openrouter"),
1918
+ executor: z$1.literal("in_do"),
1919
+ workspaceId: z$1.string().uuid().optional(),
1920
+ creditLimit: z$1.number().finite().nonnegative(),
1921
+ limitReset: z$1.enum([
1922
+ "daily",
1923
+ "weekly",
1924
+ "monthly"
1925
+ ]).optional(),
1926
+ includeByokInLimit: z$1.boolean().optional(),
1927
+ maxTtlSeconds: z$1.number().int().min(60).max(604800).optional()
1928
+ }).strict();
1929
+ const tailscaleTargetConfigSchema = z$1.object({
1930
+ provider: z$1.literal("tailscale"),
1931
+ executor: z$1.literal("in_do"),
1932
+ tailnet: z$1.string().min(1).max(253).regex(/^[a-zA-Z0-9@._-]+$/),
1933
+ credentialType: z$1.enum([
1934
+ "auth",
1935
+ "client",
1936
+ "federated"
1937
+ ]),
1938
+ tags: z$1.array(z$1.string().regex(/^tag:[a-zA-Z0-9_-]+$/)).max(100).default([]),
1939
+ reusable: z$1.boolean().default(false),
1940
+ ephemeral: z$1.boolean().default(true),
1941
+ preauthorized: z$1.boolean().default(false),
1942
+ scopes: z$1.array(z$1.string().min(1).max(128)).max(100).default([]),
1943
+ issuer: z$1.string().url().optional(),
1944
+ audience: z$1.string().min(1).max(2048).optional(),
1945
+ subject: z$1.string().min(1).max(2048).optional(),
1946
+ maxTtlSeconds: z$1.number().int().min(60).max(604800).optional()
1947
+ }).strict().superRefine((value, ctx) => {
1948
+ if (value.credentialType !== "auth" && !value.scopes.length) ctx.addIssue({
1949
+ code: "custom",
1950
+ path: ["scopes"],
1951
+ message: "select at least one scope"
1952
+ });
1953
+ if (value.credentialType === "federated" && (!value.issuer?.startsWith("https://") || !value.audience || !value.subject)) ctx.addIssue({
1954
+ code: "custom",
1955
+ path: ["issuer"],
1956
+ message: "federation requires HTTPS issuer, audience, and subject"
1957
+ });
1958
+ });
1959
+ const managedTargetConfigSchema = z$1.discriminatedUnion("provider", [
1960
+ clickhouseTargetConfigSchema,
1961
+ rabbitmqTargetConfigSchema,
1962
+ milvusTargetConfigSchema,
1963
+ mongoAtlasTargetConfigSchema,
1964
+ couchbaseTargetConfigSchema,
1965
+ snowflakeTargetConfigSchema,
1966
+ elasticacheTargetConfigSchema,
1967
+ memorydbTargetConfigSchema,
1968
+ openRouterTargetConfigSchema,
1969
+ tailscaleTargetConfigSchema,
1970
+ elasticsearchTargetConfigSchema
1971
+ ]);
1972
+ function isManagedLeaseKind(value) {
1973
+ return MANAGED_LEASE_KINDS.includes(value);
1974
+ }
1975
+ function isManagedTarget(value) {
1976
+ return isManagedLeaseKind(value.provider);
1977
+ }
1978
+ z$1.enum([
1756
1979
  "postgres",
1757
1980
  "mysql",
1758
1981
  "ssh",
1759
1982
  "redis",
1760
1983
  "aws",
1761
1984
  "gcp",
1762
- "mongodb"
1985
+ "mongodb",
1986
+ ...MANAGED_LEASE_KINDS
1763
1987
  ]);
1764
- const executorModeSchema = z.enum(["in_do", "remote"]);
1988
+ const executorModeSchema = z$1.enum(["in_do", "remote"]);
1765
1989
  /**
1766
1990
  * A Postgres role name we are willing to create. Deliberately strict — this
1767
1991
  * value is interpolated into a SQL template, so it must be a bare identifier
1768
1992
  * with no way to break out of quoting (no quotes, whitespace, or semicolons).
1769
1993
  */
1770
- const postgresRoleNameSchema = z.string().regex(/^[a-z_][a-z0-9_]{2,62}$/, "must be 3–63 chars, lowercase letters/digits/underscore, starting with a letter or underscore");
1994
+ const postgresRoleNameSchema = z$1.string().regex(/^[a-z_][a-z0-9_]{2,62}$/, "must be 3–63 chars, lowercase letters/digits/underscore, starting with a letter or underscore");
1771
1995
  /**
1772
1996
  * A SCRAM-SHA-256 verifier string as produced by @seekrit/crypto. Validated so
1773
1997
  * it, too, is safe to interpolate into a quoted SQL literal (the alphabet is
1774
1998
  * base64 + the fixed structural characters, none of which is a single quote).
1775
1999
  */
1776
- const scramVerifierSchema = z.string().regex(/^SCRAM-SHA-256\$\d{3,}:[A-Za-z0-9+/=]+\$[A-Za-z0-9+/=]+:[A-Za-z0-9+/=]+$/, "must be a SCRAM-SHA-256 verifier");
2000
+ const scramVerifierSchema = z$1.string().regex(/^SCRAM-SHA-256\$\d{3,}:[A-Za-z0-9+/=]+\$[A-Za-z0-9+/=]+:[A-Za-z0-9+/=]+$/, "must be a SCRAM-SHA-256 verifier");
1777
2001
  /**
1778
2002
  * An SSH login principal (a Unix-style username the certificate authorizes).
1779
2003
  * Bounded and restricted to a safe charset — principals are SSH-wire-encoded,
1780
2004
  * not shell-interpolated, so this is sanity/DoS hardening, not an injection gate.
1781
2005
  */
1782
- const sshPrincipalSchema = z.string().regex(/^[A-Za-z0-9._-]{1,64}$/, "must be 1–64 chars of letters, digits, dot, dash, underscore");
2006
+ const sshPrincipalSchema = z$1.string().regex(/^[A-Za-z0-9._-]{1,64}$/, "must be 1–64 chars of letters, digits, dot, dash, underscore");
1783
2007
  /** An `ssh-ed25519 <base64> [comment]` public key line (deep-validated on sign). */
1784
- const sshPublicKeySchema = z.string().max(2048).regex(/^ssh-ed25519 [A-Za-z0-9+/=]+( .*)?$/, "must be an ssh-ed25519 public key");
2008
+ const sshPublicKeySchema = z$1.string().max(2048).regex(/^ssh-ed25519 [A-Za-z0-9+/=]+( .*)?$/, "must be an ssh-ed25519 public key");
1785
2009
  /** An SSH certificate extension name, e.g. `permit-pty`. */
1786
- const sshExtensionSchema = z.string().regex(/^[a-z0-9-]{1,64}$/);
2010
+ const sshExtensionSchema = z$1.string().regex(/^[a-z0-9-]{1,64}$/);
1787
2011
  /**
1788
2012
  * A MySQL/MariaDB user name we are willing to create. Interpolated into a
1789
2013
  * quoted SQL literal (`'{{name}}'@'%'`), so it is kept strict — plain
1790
2014
  * alphanumerics/underscore, no quotes/whitespace/semicolons to break out.
1791
2015
  */
1792
- const mysqlUserNameSchema = z.string().regex(/^[A-Za-z0-9_]{3,32}$/, "must be 3–32 chars, letters/digits/underscore");
2016
+ const mysqlUserNameSchema = z$1.string().regex(/^[A-Za-z0-9_]{3,32}$/, "must be 3–32 chars, letters/digits/underscore");
1793
2017
  /**
1794
2018
  * A `mysql_native_password` authentication string — `*` followed by 40 upper
1795
2019
  * hex chars (`UPPER(HEX(SHA1(SHA1(password))))`), as produced by
@@ -1797,14 +2021,14 @@ const mysqlUserNameSchema = z.string().regex(/^[A-Za-z0-9_]{3,32}$/, "must be 3
1797
2021
  * `CREATE USER … IDENTIFIED WITH mysql_native_password AS '<str>'`, and its
1798
2022
  * alphabet contains no single quote, so it is safe in a quoted SQL literal.
1799
2023
  */
1800
- const mysqlNativeVerifierSchema = z.string().regex(/^\*[0-9A-F]{40}$/, "must be a mysql_native_password hash (*<40 hex>)");
2024
+ const mysqlNativeVerifierSchema = z$1.string().regex(/^\*[0-9A-F]{40}$/, "must be a mysql_native_password hash (*<40 hex>)");
1801
2025
  /**
1802
2026
  * A Redis ACL user name we are willing to create. Interpolated into a Redis
1803
2027
  * command line as a bare token (`ACL SETUSER <name> …`), so it is kept strict —
1804
2028
  * plain alphanumerics/underscore, no whitespace to split the arg or ACL rule
1805
2029
  * characters (`~ + @ # & %`) that could be read as a permission.
1806
2030
  */
1807
- const redisUserNameSchema = z.string().regex(/^[A-Za-z0-9_]{3,32}$/, "must be 3–32 chars, letters/digits/underscore");
2031
+ const redisUserNameSchema = z$1.string().regex(/^[A-Za-z0-9_]{3,32}$/, "must be 3–32 chars, letters/digits/underscore");
1808
2032
  /**
1809
2033
  * A Redis password verifier — the lowercase-hex SHA-256 of the password, as
1810
2034
  * produced by @seekrit/crypto `redisSha256Verifier`. `ACL SETUSER … on #<hex>`
@@ -1813,22 +2037,22 @@ const redisUserNameSchema = z.string().regex(/^[A-Za-z0-9_]{3,32}$/, "must be 3
1813
2037
  * is preimage-resistant (the password is high-entropy and machine-generated).
1814
2038
  * The alphabet is bare hex, so it is a safe bare command token.
1815
2039
  */
1816
- const redisSha256VerifierSchema = z.string().regex(/^[0-9a-f]{64}$/, "must be a lowercase-hex SHA-256 digest (64 chars)");
2040
+ const redisSha256VerifierSchema = z$1.string().regex(/^[0-9a-f]{64}$/, "must be a lowercase-hex SHA-256 digest (64 chars)");
1817
2041
  /**
1818
2042
  * An IAM role ARN the broker is allowed to assume. Bounded and structurally
1819
2043
  * validated: `arn:<partition>:iam::<account>:role/<path-and-name>`. Partition
1820
2044
  * covers commercial (`aws`), GovCloud (`aws-us-gov`), and China (`aws-cn`).
1821
2045
  */
1822
- const awsRoleArnSchema = z.string().regex(/^arn:aws(?:-us-gov|-cn)?:iam::\d{12}:role\/[\w+=,.@/-]{1,512}$/, "must be an IAM role ARN (arn:aws:iam::<account>:role/<name>)");
2046
+ const awsRoleArnSchema = z$1.string().regex(/^arn:aws(?:-us-gov|-cn)?:iam::\d{12}:role\/[\w+=,.@/-]{1,512}$/, "must be an IAM role ARN (arn:aws:iam::<account>:role/<name>)");
1823
2047
  /** An AWS region id, e.g. `us-east-1`, `eu-west-2`, `us-gov-west-1`. */
1824
- const awsRegionSchema$1 = z.string().regex(/^[a-z]{2}(?:-[a-z]+)+-\d$/, "must be an AWS region id (e.g. us-east-1)");
2048
+ const awsRegionSchema$1 = z$1.string().regex(/^[a-z]{2}(?:-[a-z]+)+-\d$/, "must be an AWS region id (e.g. us-east-1)");
1825
2049
  /**
1826
2050
  * An STS external id — the shared string a role's trust policy can require so a
1827
2051
  * confused-deputy can't assume it. AWS allows a broad charset; we keep to the
1828
2052
  * documented safe set and bound the length.
1829
2053
  */
1830
- const awsExternalIdSchema = z.string().regex(/^[\w+=,.@:/-]{2,1224}$/, "must be a valid STS external id");
1831
- z.string().regex(/^[\w+=,.@-]{2,64}$/, "must be 2–64 chars of [A-Za-z0-9_+=,.@-]");
2054
+ const awsExternalIdSchema = z$1.string().regex(/^[\w+=,.@:/-]{2,1224}$/, "must be a valid STS external id");
2055
+ z$1.string().regex(/^[\w+=,.@-]{2,64}$/, "must be 2–64 chars of [A-Za-z0-9_+=,.@-]");
1832
2056
  /**
1833
2057
  * A GCP service-account email the broker is allowed to impersonate (or that
1834
2058
  * appears in a delegation chain). Structurally validated and bounded: it is
@@ -1837,21 +2061,21 @@ z.string().regex(/^[\w+=,.@-]{2,64}$/, "must be 2–64 chars of [A-Za-z0-9_+=,.@
1837
2061
  * (`name@<project>.iam.gserviceaccount.com`) and Google-managed
1838
2062
  * (`<project-number>-compute@developer.gserviceaccount.com`) forms.
1839
2063
  */
1840
- const gcpServiceAccountEmailSchema = z.string().max(256).regex(/^[a-z0-9-]+@[a-z0-9.-]+\.gserviceaccount\.com$/, "must be a service-account email (…@….gserviceaccount.com)");
2064
+ const gcpServiceAccountEmailSchema = z$1.string().max(256).regex(/^[a-z0-9-]+@[a-z0-9.-]+\.gserviceaccount\.com$/, "must be a service-account email (…@….gserviceaccount.com)");
1841
2065
  /**
1842
2066
  * An OAuth 2.0 scope granted to the minted access token, e.g.
1843
2067
  * `https://www.googleapis.com/auth/cloud-platform`. Bounded and whitespace-free
1844
2068
  * (scopes are space-delimited); passed to the IAM Credentials API in a JSON body
1845
2069
  * array, not a URL, so this is sanity/DoS hardening rather than an injection gate.
1846
2070
  */
1847
- const gcpOauthScopeSchema = z.string().min(1).max(256).regex(/^\S+$/, "must be a single OAuth scope with no whitespace");
2071
+ const gcpOauthScopeSchema = z$1.string().min(1).max(256).regex(/^\S+$/, "must be a single OAuth scope with no whitespace");
1848
2072
  /**
1849
2073
  * The consumer's ephemeral P-256 public key (JWK-serialized) that a tier-2
1850
2074
  * credential is wrapped to before it is returned. Validated structurally here;
1851
2075
  * the executor imports it defensively before wrapping. Bounded so a giant blob
1852
2076
  * can't be pushed through the control plane.
1853
2077
  */
1854
- const p256PublicKeyJwkSchema = z.string().max(2048).refine((s) => {
2078
+ const p256PublicKeyJwkSchema = z$1.string().max(2048).refine((s) => {
1855
2079
  try {
1856
2080
  const jwk = JSON.parse(s);
1857
2081
  return jwk.kty === "EC" && jwk.crv === "P-256" && !!jwk.x && !!jwk.y;
@@ -1859,23 +2083,23 @@ const p256PublicKeyJwkSchema = z.string().max(2048).refine((s) => {
1859
2083
  return false;
1860
2084
  }
1861
2085
  }, "must be a JWK-serialized P-256 public key");
1862
- z.string().regex(/^[A-Za-z0-9_-]{1,64}$/, "must be 1–64 chars of [A-Za-z0-9_-]");
2086
+ z$1.string().regex(/^[A-Za-z0-9_-]{1,64}$/, "must be 1–64 chars of [A-Za-z0-9_-]");
1863
2087
  /**
1864
2088
  * A MongoDB database name — the db a preset role is granted on, or the
1865
2089
  * authentication database a leased user is created in. MongoDB forbids
1866
2090
  * `/\. "$*<>:|?` and the empty string in db names; we keep to a safe subset.
1867
2091
  */
1868
- const mongoDatabaseNameSchema = z.string().regex(/^[A-Za-z0-9_-]{1,63}$/, "must be 1–63 chars of [A-Za-z0-9_-]");
2092
+ const mongoDatabaseNameSchema = z$1.string().regex(/^[A-Za-z0-9_-]{1,63}$/, "must be 1–63 chars of [A-Za-z0-9_-]");
1869
2093
  /**
1870
2094
  * A single MongoDB role grant `{ role, db }` for a `custom` target — e.g.
1871
2095
  * `{ role: "readWrite", db: "app" }` or a user-defined role. Admin-supplied
1872
2096
  * trusted input, set once at registration; still bounded structurally.
1873
2097
  */
1874
- const mongoRoleSchema = z.object({
1875
- role: z.string().regex(/^[A-Za-z0-9_-]{1,64}$/, "must be a role name"),
2098
+ const mongoRoleSchema = z$1.object({
2099
+ role: z$1.string().regex(/^[A-Za-z0-9_-]{1,64}$/, "must be a role name"),
1876
2100
  db: mongoDatabaseNameSchema
1877
2101
  });
1878
- const postgresAccessLevelSchema = z.enum([
2102
+ const postgresAccessLevelSchema = z$1.enum([
1879
2103
  "readonly",
1880
2104
  "readwrite",
1881
2105
  "custom"
@@ -1885,137 +2109,138 @@ const POSTGRES_GROUP_ROLES = {
1885
2109
  readonly: "seekrit_readonly",
1886
2110
  readwrite: "seekrit_readwrite"
1887
2111
  };
1888
- const mysqlAccessLevelSchema = z.enum([
2112
+ const mysqlAccessLevelSchema = z$1.enum([
1889
2113
  "readonly",
1890
2114
  "readwrite",
1891
2115
  "custom"
1892
2116
  ]);
1893
- const redisAccessLevelSchema = z.enum([
2117
+ const redisAccessLevelSchema = z$1.enum([
1894
2118
  "readonly",
1895
2119
  "readwrite",
1896
2120
  "custom"
1897
2121
  ]);
1898
- const mongoAccessLevelSchema = z.enum([
2122
+ const mongoAccessLevelSchema = z$1.enum([
1899
2123
  "readonly",
1900
2124
  "readwrite",
1901
2125
  "custom"
1902
2126
  ]);
1903
- const connectionSchema = z.object({
1904
- host: z.string().min(1),
1905
- port: z.number().int().min(1).max(65535),
1906
- database: z.string().min(1)
2127
+ const connectionSchema = z$1.object({
2128
+ host: z$1.string().min(1),
2129
+ port: z$1.number().int().min(1).max(65535),
2130
+ database: z$1.string().min(1)
1907
2131
  });
1908
2132
  /** A `{{name}}`/`{{verifier}}`/`{{valid_until}}` templated SQL statement. */
1909
- const statementSchema$1 = z.string().min(1).max(4e3);
2133
+ const statementSchema$1 = z$1.string().min(1).max(4e3);
1910
2134
  /** A bare SQL identifier (schema name) — no quotes/whitespace/semicolons. */
1911
- const identifierSchema = z.string().regex(/^[A-Za-z_][A-Za-z0-9_]{0,62}$/, "must be an identifier");
1912
- const postgresTargetConfigSchema = z.object({
1913
- provider: z.literal("postgres"),
2135
+ const identifierSchema = z$1.string().regex(/^[A-Za-z_][A-Za-z0-9_]{0,62}$/, "must be an identifier");
2136
+ const postgresTargetConfigSchema = z$1.object({
2137
+ provider: z$1.literal("postgres"),
1914
2138
  executor: executorModeSchema,
1915
2139
  accessLevel: postgresAccessLevelSchema.optional(),
1916
2140
  schema: identifierSchema.optional(),
1917
2141
  connection: connectionSchema,
1918
- provisionerUrl: z.url().optional(),
1919
- createStatements: z.array(statementSchema$1).max(16).optional(),
1920
- revokeStatements: z.array(statementSchema$1).max(16).optional()
2142
+ provisionerUrl: z$1.url().optional(),
2143
+ createStatements: z$1.array(statementSchema$1).max(16).optional(),
2144
+ revokeStatements: z$1.array(statementSchema$1).max(16).optional()
1921
2145
  });
1922
2146
  /** A MySQL account host part (`'name'@'<host>'`) — no quotes/whitespace. */
1923
- const mysqlHostSchema$1 = z.string().regex(/^[A-Za-z0-9_.%:-]{1,255}$/, "must be a host pattern");
1924
- const mysqlTargetConfigSchema = z.object({
1925
- provider: z.literal("mysql"),
2147
+ const mysqlHostSchema$1 = z$1.string().regex(/^[A-Za-z0-9_.%:-]{1,255}$/, "must be a host pattern");
2148
+ const mysqlTargetConfigSchema = z$1.object({
2149
+ provider: z$1.literal("mysql"),
1926
2150
  executor: executorModeSchema,
1927
2151
  accessLevel: mysqlAccessLevelSchema.optional(),
1928
2152
  connection: connectionSchema,
1929
2153
  userHost: mysqlHostSchema$1.optional(),
1930
- provisionerUrl: z.url().optional(),
1931
- createStatements: z.array(statementSchema$1).max(16).optional(),
1932
- revokeStatements: z.array(statementSchema$1).max(16).optional()
2154
+ provisionerUrl: z$1.url().optional(),
2155
+ createStatements: z$1.array(statementSchema$1).max(16).optional(),
2156
+ revokeStatements: z$1.array(statementSchema$1).max(16).optional()
1933
2157
  });
1934
- const redisConnectionSchema = z.object({
1935
- host: z.string().min(1),
1936
- port: z.number().int().min(1).max(65535),
2158
+ const redisConnectionSchema = z$1.object({
2159
+ host: z$1.string().min(1),
2160
+ port: z$1.number().int().min(1).max(65535),
1937
2161
  /** Redis logical database index (the `/<n>` in a connection URL). */
1938
- db: z.number().int().min(0).max(15).optional()
2162
+ db: z$1.number().int().min(0).max(15).optional()
1939
2163
  });
1940
- const redisTargetConfigSchema = z.object({
1941
- provider: z.literal("redis"),
2164
+ const redisTargetConfigSchema = z$1.object({
2165
+ provider: z$1.literal("redis"),
1942
2166
  executor: executorModeSchema,
1943
2167
  accessLevel: redisAccessLevelSchema.optional(),
1944
2168
  connection: redisConnectionSchema,
1945
- provisionerUrl: z.url().optional(),
1946
- createStatements: z.array(statementSchema$1).max(16).optional(),
1947
- revokeStatements: z.array(statementSchema$1).max(16).optional()
2169
+ provisionerUrl: z$1.url().optional(),
2170
+ createStatements: z$1.array(statementSchema$1).max(16).optional(),
2171
+ revokeStatements: z$1.array(statementSchema$1).max(16).optional()
1948
2172
  });
1949
- const sshTargetConfigSchema = z.object({
1950
- provider: z.literal("ssh"),
1951
- executor: z.literal("in_do"),
2173
+ const sshTargetConfigSchema = z$1.object({
2174
+ provider: z$1.literal("ssh"),
2175
+ executor: z$1.literal("in_do"),
1952
2176
  caPublicKey: sshPublicKeySchema,
1953
- allowedPrincipals: z.array(sshPrincipalSchema).max(64).optional(),
1954
- extensions: z.array(sshExtensionSchema).max(16).optional(),
1955
- maxTtlSeconds: z.number().int().min(60).max(604800).optional(),
1956
- connection: z.object({
1957
- host: z.string().min(1).optional(),
2177
+ allowedPrincipals: z$1.array(sshPrincipalSchema).max(64).optional(),
2178
+ extensions: z$1.array(sshExtensionSchema).max(16).optional(),
2179
+ maxTtlSeconds: z$1.number().int().min(60).max(604800).optional(),
2180
+ connection: z$1.object({
2181
+ host: z$1.string().min(1).optional(),
1958
2182
  user: sshPrincipalSchema.optional()
1959
2183
  }).optional()
1960
2184
  });
1961
2185
  const AWS_MAX_TTL_SECONDS = 43200;
1962
- const awsTargetConfigSchema = z.object({
1963
- provider: z.literal("aws"),
1964
- executor: z.literal("in_do"),
2186
+ const awsTargetConfigSchema = z$1.object({
2187
+ provider: z$1.literal("aws"),
2188
+ executor: z$1.literal("in_do"),
1965
2189
  roleArn: awsRoleArnSchema,
1966
2190
  region: awsRegionSchema$1,
1967
2191
  externalId: awsExternalIdSchema.optional(),
1968
- sessionPolicy: z.string().min(1).max(4e3).optional(),
1969
- maxTtlSeconds: z.number().int().min(900).max(AWS_MAX_TTL_SECONDS).optional()
2192
+ sessionPolicy: z$1.string().min(1).max(4e3).optional(),
2193
+ maxTtlSeconds: z$1.number().int().min(900).max(AWS_MAX_TTL_SECONDS).optional()
1970
2194
  });
1971
2195
  const GCP_MAX_TTL_SECONDS = 43200;
1972
- const gcpTargetConfigSchema = z.object({
1973
- provider: z.literal("gcp"),
1974
- executor: z.literal("in_do"),
2196
+ const gcpTargetConfigSchema = z$1.object({
2197
+ provider: z$1.literal("gcp"),
2198
+ executor: z$1.literal("in_do"),
1975
2199
  serviceAccount: gcpServiceAccountEmailSchema,
1976
- scopes: z.array(gcpOauthScopeSchema).min(1).max(32).optional(),
1977
- delegates: z.array(gcpServiceAccountEmailSchema).max(8).optional(),
1978
- maxTtlSeconds: z.number().int().min(60).max(GCP_MAX_TTL_SECONDS).optional()
2200
+ scopes: z$1.array(gcpOauthScopeSchema).min(1).max(32).optional(),
2201
+ delegates: z$1.array(gcpServiceAccountEmailSchema).max(8).optional(),
2202
+ maxTtlSeconds: z$1.number().int().min(60).max(GCP_MAX_TTL_SECONDS).optional()
1979
2203
  });
1980
- const mongoTargetConfigSchema = z.object({
1981
- provider: z.literal("mongodb"),
1982
- executor: z.literal("in_do"),
2204
+ const mongoTargetConfigSchema = z$1.object({
2205
+ provider: z$1.literal("mongodb"),
2206
+ executor: z$1.literal("in_do"),
1983
2207
  accessLevel: mongoAccessLevelSchema.optional(),
1984
2208
  connection: connectionSchema,
1985
2209
  authSource: mongoDatabaseNameSchema.optional(),
1986
- roles: z.array(mongoRoleSchema).min(1).max(32).optional(),
1987
- tls: z.boolean().optional(),
1988
- maxTtlSeconds: z.number().int().min(60).max(604800).optional()
2210
+ roles: z$1.array(mongoRoleSchema).min(1).max(32).optional(),
2211
+ tls: z$1.boolean().optional(),
2212
+ maxTtlSeconds: z$1.number().int().min(60).max(604800).optional()
1989
2213
  });
1990
- const leaseTargetConfigSchema = z.discriminatedUnion("provider", [
2214
+ const leaseTargetConfigSchema = z$1.discriminatedUnion("provider", [
1991
2215
  postgresTargetConfigSchema,
1992
2216
  mysqlTargetConfigSchema,
1993
2217
  redisTargetConfigSchema,
1994
2218
  sshTargetConfigSchema,
1995
2219
  awsTargetConfigSchema,
1996
2220
  gcpTargetConfigSchema,
1997
- mongoTargetConfigSchema
2221
+ mongoTargetConfigSchema,
2222
+ ...managedTargetConfigSchema.options
1998
2223
  ]);
1999
- z.object({
2000
- name: z.string().trim().min(1).max(128),
2224
+ z$1.object({
2225
+ name: z$1.string().trim().min(1).max(128),
2001
2226
  config: leaseTargetConfigSchema,
2002
2227
  /**
2003
2228
  * The admin/provisioning credential (e.g. a Postgres connection string),
2004
2229
  * encrypted client-side to the broker's public key (a `wd1.` wrap). The
2005
2230
  * control plane stores only this ciphertext — it never sees the plaintext.
2006
2231
  */
2007
- wrappedAdminSecret: z.string().min(1)
2232
+ wrappedAdminSecret: z$1.string().min(1)
2008
2233
  });
2009
2234
  /** Requested lease lifetime, shared by all providers. */
2010
- const ttlSecondsSchema = z.number().int().min(60).max(604800);
2235
+ const ttlSecondsSchema = z$1.number().int().min(60).max(604800);
2011
2236
  /**
2012
2237
  * Client → API: mint a Postgres lease. The client generates the password and
2013
2238
  * its SCRAM verifier locally and sends only the verifier — the plaintext
2014
2239
  * password never leaves the requesting machine.
2015
2240
  */
2016
- const mintPostgresLeaseSchema = z.object({
2017
- provider: z.literal("postgres"),
2018
- targetId: z.string().min(1),
2241
+ const mintPostgresLeaseSchema = z$1.object({
2242
+ provider: z$1.literal("postgres"),
2243
+ targetId: z$1.string().min(1),
2019
2244
  roleName: postgresRoleNameSchema,
2020
2245
  verifier: scramVerifierSchema,
2021
2246
  ttlSeconds: ttlSecondsSchema
@@ -2025,9 +2250,9 @@ const mintPostgresLeaseSchema = z.object({
2025
2250
  * and its `mysql_native_password` hash locally and sends only the hash — the
2026
2251
  * plaintext password never leaves the requesting machine.
2027
2252
  */
2028
- const mintMysqlLeaseSchema = z.object({
2029
- provider: z.literal("mysql"),
2030
- targetId: z.string().min(1),
2253
+ const mintMysqlLeaseSchema = z$1.object({
2254
+ provider: z$1.literal("mysql"),
2255
+ targetId: z$1.string().min(1),
2031
2256
  roleName: mysqlUserNameSchema,
2032
2257
  verifier: mysqlNativeVerifierSchema,
2033
2258
  ttlSeconds: ttlSecondsSchema
@@ -2037,9 +2262,9 @@ const mintMysqlLeaseSchema = z.object({
2037
2262
  * SHA-256 hex digest locally and sends only the digest — the plaintext password
2038
2263
  * never leaves the requesting machine.
2039
2264
  */
2040
- const mintRedisLeaseSchema = z.object({
2041
- provider: z.literal("redis"),
2042
- targetId: z.string().min(1),
2265
+ const mintRedisLeaseSchema = z$1.object({
2266
+ provider: z$1.literal("redis"),
2267
+ targetId: z$1.string().min(1),
2043
2268
  roleName: redisUserNameSchema,
2044
2269
  verifier: redisSha256VerifierSchema,
2045
2270
  ttlSeconds: ttlSecondsSchema
@@ -2049,11 +2274,11 @@ const mintRedisLeaseSchema = z.object({
2049
2274
  * locally and sends only the public key; the signed certificate comes back in
2050
2275
  * the response. The private key never leaves the requesting machine.
2051
2276
  */
2052
- const mintSshLeaseSchema = z.object({
2053
- provider: z.literal("ssh"),
2054
- targetId: z.string().min(1),
2277
+ const mintSshLeaseSchema = z$1.object({
2278
+ provider: z$1.literal("ssh"),
2279
+ targetId: z$1.string().min(1),
2055
2280
  publicKey: sshPublicKeySchema,
2056
- principals: z.array(sshPrincipalSchema).min(1).max(32),
2281
+ principals: z$1.array(sshPrincipalSchema).min(1).max(32),
2057
2282
  ttlSeconds: ttlSecondsSchema
2058
2283
  });
2059
2284
  /**
@@ -2065,11 +2290,11 @@ const mintSshLeaseSchema = z.object({
2065
2290
  * TTL bounds are STS's own `DurationSeconds` limits (15 min – 12 h), not the
2066
2291
  * generic lease bounds — STS rejects anything below 900 seconds.
2067
2292
  */
2068
- const mintAwsLeaseSchema = z.object({
2069
- provider: z.literal("aws"),
2070
- targetId: z.string().min(1),
2293
+ const mintAwsLeaseSchema = z$1.object({
2294
+ provider: z$1.literal("aws"),
2295
+ targetId: z$1.string().min(1),
2071
2296
  recipientPublicKey: p256PublicKeyJwkSchema,
2072
- ttlSeconds: z.number().int().min(900).max(AWS_MAX_TTL_SECONDS)
2297
+ ttlSeconds: z$1.number().int().min(900).max(AWS_MAX_TTL_SECONDS)
2073
2298
  });
2074
2299
  /**
2075
2300
  * Client → API: mint a GCP lease. Like AWS (tier 2): the client generates an
@@ -2081,11 +2306,11 @@ const mintAwsLeaseSchema = z.object({
2081
2306
  * TTL bounds are GCP's `generateAccessToken` limits (1 min – 12 h); tokens over
2082
2307
  * 1 h require the credential-lifetime-extension org policy.
2083
2308
  */
2084
- const mintGcpLeaseSchema = z.object({
2085
- provider: z.literal("gcp"),
2086
- targetId: z.string().min(1),
2309
+ const mintGcpLeaseSchema = z$1.object({
2310
+ provider: z$1.literal("gcp"),
2311
+ targetId: z$1.string().min(1),
2087
2312
  recipientPublicKey: p256PublicKeyJwkSchema,
2088
- ttlSeconds: z.number().int().min(60).max(GCP_MAX_TTL_SECONDS)
2313
+ ttlSeconds: z$1.number().int().min(60).max(GCP_MAX_TTL_SECONDS)
2089
2314
  });
2090
2315
  /**
2091
2316
  * Client → API: mint a MongoDB lease. Like AWS (tier 2), the client generates
@@ -2094,22 +2319,34 @@ const mintGcpLeaseSchema = z.object({
2094
2319
  * to that key. The private key never leaves the requesting machine, so the
2095
2320
  * plaintext credential is only decryptable there.
2096
2321
  */
2097
- const mintMongoLeaseSchema = z.object({
2098
- provider: z.literal("mongodb"),
2099
- targetId: z.string().min(1),
2322
+ const mintMongoLeaseSchema = z$1.object({
2323
+ provider: z$1.literal("mongodb"),
2324
+ targetId: z$1.string().min(1),
2100
2325
  recipientPublicKey: p256PublicKeyJwkSchema,
2101
2326
  ttlSeconds: ttlSecondsSchema
2102
2327
  });
2103
- z.discriminatedUnion("provider", [
2328
+ const mintManagedLeaseSchema = z$1.object({
2329
+ provider: z$1.enum(MANAGED_LEASE_KINDS),
2330
+ targetId: z$1.string().min(1),
2331
+ recipientPublicKey: p256PublicKeyJwkSchema.refine((value) => {
2332
+ try {
2333
+ return !("d" in JSON.parse(value));
2334
+ } catch {
2335
+ return false;
2336
+ }
2337
+ }, "send only a public key"),
2338
+ ttlSeconds: ttlSecondsSchema
2339
+ });
2340
+ z$1.discriminatedUnion("provider", [
2104
2341
  mintPostgresLeaseSchema,
2105
2342
  mintMysqlLeaseSchema,
2106
2343
  mintRedisLeaseSchema,
2107
2344
  mintSshLeaseSchema,
2108
2345
  mintAwsLeaseSchema,
2109
2346
  mintGcpLeaseSchema,
2110
- mintMongoLeaseSchema
2347
+ mintMongoLeaseSchema,
2348
+ mintManagedLeaseSchema
2111
2349
  ]);
2112
- // ../../packages/core/src/providers/aws.ts
2113
2350
  /**
2114
2351
  * The one-time IAM setup an admin performs so seekrit can assume the target
2115
2352
  * role. Analogue of `sshHostSetupInstructions` / `postgresGroupBootstrapSql` —
@@ -2136,7 +2373,6 @@ function awsTrustPolicyInstructions(config) {
2136
2373
  `# on ${config.roleArn}. seekrit only ever calls AssumeRole on this role.`
2137
2374
  ].join("\n");
2138
2375
  }
2139
- // ../../packages/core/src/providers/gcp.ts
2140
2376
  /**
2141
2377
  * The one-time IAM setup an admin performs so seekrit can impersonate the target
2142
2378
  * service account. Analogue of `awsTrustPolicyInstructions` — printed for the
@@ -2158,7 +2394,6 @@ function gcpSetupInstructions(config) {
2158
2394
  "gcloud services enable iamcredentials.googleapis.com"
2159
2395
  ].join("\n");
2160
2396
  }
2161
- // ../../packages/core/src/providers/mongodb.ts
2162
2397
  /**
2163
2398
  * The one-time setup an admin performs so seekrit can provision users: create a
2164
2399
  * dedicated provisioning user with `userAdmin` on the target database (or
@@ -2183,7 +2418,6 @@ function mongoAdminSetupInstructions(config) {
2183
2418
  `// --uri "mongodb://seekrit_provisioner:<pwd>@${config.connection.host}:${config.connection.port}/?authSource=${authSource}"`
2184
2419
  ].join("\n");
2185
2420
  }
2186
- // ../../packages/core/src/providers/postgres.ts
2187
2421
  /**
2188
2422
  * The one-time setup SQL an admin runs to create the shared group role that a
2189
2423
  * read-only / read-write target's leased credentials inherit. Idempotent (safe
@@ -2214,7 +2448,6 @@ function postgresGroupBootstrapSql(config) {
2214
2448
  if (config.accessLevel === "readwrite") lines.push(`GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA "${schema}" TO ${group};`, `ALTER DEFAULT PRIVILEGES IN SCHEMA "${schema}" GRANT USAGE, SELECT ON SEQUENCES TO ${group};`);
2215
2449
  return lines.join("\n");
2216
2450
  }
2217
- // ../../packages/core/src/providers/ssh.ts
2218
2451
  /**
2219
2452
  * The one-time host setup an admin runs so a target's certificates are accepted.
2220
2453
  * Analogue of `postgresGroupBootstrapSql` — displayed for the admin to run, not
@@ -2234,6 +2467,13 @@ function sshHostSetupInstructions(config) {
2234
2467
  "sudo systemctl reload sshd"
2235
2468
  ].join("\n");
2236
2469
  }
2470
+ // ../../packages/core/src/slug.ts
2471
+ /**
2472
+ * The slug rule, with no dependencies — so a caller that cannot afford zod (the
2473
+ * resolve gateway's bundle, see apps/api/src/gateway) validates with the same
2474
+ * pattern `slugSchema` uses rather than a copy of it.
2475
+ */
2476
+ const SLUG_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
2237
2477
  // ../../packages/core/src/types.ts
2238
2478
  const AUDIT_ACTIONS = [
2239
2479
  "workload.created",
@@ -2468,94 +2708,94 @@ const NOTIFICATION_TYPE_META = {
2468
2708
  };
2469
2709
  // ../../packages/core/src/schemas.ts
2470
2710
  /** URL-safe identifier segment: `my-app`, `production`, … */
2471
- const slugSchema = z.string().min(1).max(64).regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, "must be lowercase alphanumeric with hyphens");
2472
- const nameSchema = z.string().trim().min(1).max(128);
2711
+ const slugSchema = z$1.string().min(1).max(64).regex(SLUG_PATTERN, "must be lowercase alphanumeric with hyphens");
2712
+ const nameSchema = z$1.string().trim().min(1).max(128);
2473
2713
  /** An email address, normalized to trimmed lowercase before validation. */
2474
- const emailSchema = z.string().trim().toLowerCase().pipe(z.email().max(320));
2714
+ const emailSchema = z$1.string().trim().toLowerCase().pipe(z$1.email().max(320));
2475
2715
  /** Env-var style secret name: FOO, DATABASE_URL, apiKey2 … */
2476
- const secretNameSchema = z.string().min(1).max(256).regex(/^[A-Za-z_][A-Za-z0-9_]*$/, "must be a valid environment variable name");
2477
- const orgRoleSchema = z.enum([
2716
+ const secretNameSchema = z$1.string().min(1).max(256).regex(/^[A-Za-z_][A-Za-z0-9_]*$/, "must be a valid environment variable name");
2717
+ const orgRoleSchema = z$1.enum([
2478
2718
  "owner",
2479
2719
  "admin",
2480
2720
  "member"
2481
2721
  ]);
2482
2722
  /** Role a person may be invited at — never `owner` (ownership isn't invitable). */
2483
- const inviteRoleSchema = z.enum(["admin", "member"]);
2484
- const principalTypeSchema = z.enum(["user", "service_token"]);
2723
+ const inviteRoleSchema = z$1.enum(["admin", "member"]);
2724
+ const principalTypeSchema = z$1.enum(["user", "service_token"]);
2485
2725
  /** Org-level capability a service token can hold (never `owner`). */
2486
- const serviceTokenRoleSchema = z.enum(["admin", "member"]);
2487
- z.object({
2726
+ const serviceTokenRoleSchema = z$1.enum(["admin", "member"]);
2727
+ z$1.object({
2488
2728
  /** Include the full append-only ciphertext history of every secret. */
2489
- includeVersions: z.boolean().optional(),
2490
- includeAudit: z.boolean().optional(),
2729
+ includeVersions: z$1.boolean().optional(),
2730
+ includeAudit: z$1.boolean().optional(),
2491
2731
  /** Newest audit rows to keep. Exceeding the server cap is a 400, not a silent trim. */
2492
- auditLimit: z.number().int().min(0).optional()
2732
+ auditLimit: z$1.number().int().min(0).optional()
2493
2733
  });
2494
- z.object({
2734
+ z$1.object({
2495
2735
  name: nameSchema,
2496
2736
  slug: slugSchema
2497
2737
  });
2498
- z.object({
2738
+ z$1.object({
2499
2739
  name: nameSchema,
2500
2740
  slug: slugSchema
2501
2741
  });
2502
- z.object({ name: nameSchema });
2503
- z.object({ name: nameSchema });
2504
- z.object({ name: nameSchema });
2505
- z.object({ name: nameSchema });
2506
- z.object({ name: nameSchema });
2507
- z.object({ required: z.boolean() });
2508
- z.object({
2742
+ z$1.object({ name: nameSchema });
2743
+ z$1.object({ name: nameSchema });
2744
+ z$1.object({ name: nameSchema });
2745
+ z$1.object({ name: nameSchema });
2746
+ z$1.object({ name: nameSchema });
2747
+ z$1.object({ required: z$1.boolean() });
2748
+ z$1.object({
2509
2749
  email: emailSchema,
2510
2750
  role: inviteRoleSchema.default("member")
2511
2751
  });
2512
- z.object({
2752
+ z$1.object({
2513
2753
  name: nameSchema,
2514
2754
  slug: slugSchema
2515
2755
  });
2516
2756
  /** Compose a group into an application environment (matched by env slug). */
2517
- const appAccessKeySchema = z.object({
2518
- environmentId: z.string().min(1),
2519
- userId: z.string().min(1),
2520
- wrappedDek: z.string().min(1).max(8192)
2757
+ const appAccessKeySchema = z$1.object({
2758
+ environmentId: z$1.string().min(1),
2759
+ userId: z$1.string().min(1),
2760
+ wrappedDek: z$1.string().min(1).max(8192)
2521
2761
  });
2522
- const appAccessGrantsSchema = z.array(appAccessKeySchema).max(5e3).optional();
2523
- z.object({
2524
- userId: z.string().min(1),
2525
- grants: z.array(appAccessKeySchema).max(5e3)
2762
+ const appAccessGrantsSchema = z$1.array(appAccessKeySchema).max(5e3).optional();
2763
+ z$1.object({
2764
+ userId: z$1.string().min(1),
2765
+ grants: z$1.array(appAccessKeySchema).max(5e3)
2526
2766
  });
2527
- z.object({ role: orgRoleSchema });
2528
- z.object({
2767
+ z$1.object({ role: orgRoleSchema });
2768
+ z$1.object({
2529
2769
  appAccessGrants: appAccessGrantsSchema,
2530
- groupId: z.string().min(1),
2770
+ groupId: z$1.string().min(1),
2531
2771
  /** Precedence among an env's groups (higher wins). Appended if omitted. */
2532
- position: z.number().int().min(0).optional(),
2772
+ position: z$1.number().int().min(0).optional(),
2533
2773
  /** Client-wrapped group DEK for each sync connection newly reading this group. */
2534
- syncGrants: z.array(z.object({
2535
- connectionId: z.string().min(1),
2536
- wrappedDek: z.string().min(1)
2774
+ syncGrants: z$1.array(z$1.object({
2775
+ connectionId: z$1.string().min(1),
2776
+ wrappedDek: z$1.string().min(1)
2537
2777
  })).optional()
2538
2778
  });
2539
- z.object({
2779
+ z$1.object({
2540
2780
  /** Wrap the new DEK to all persistent app recipients. */
2541
- userGrants: z.array(z.object({
2542
- userId: z.string().min(1),
2543
- wrappedDek: z.string().min(1).max(8192)
2781
+ userGrants: z$1.array(z$1.object({
2782
+ userId: z$1.string().min(1),
2783
+ wrappedDek: z$1.string().min(1).max(8192)
2544
2784
  })).max(5e3).optional(),
2545
2785
  name: nameSchema,
2546
2786
  slug: slugSchema,
2547
2787
  /** Environment DEK wrapped to the creator's public key — created client-side. */
2548
- wrappedDek: z.string().min(1),
2788
+ wrappedDek: z$1.string().min(1),
2549
2789
  /**
2550
2790
  * When the org has recovery enabled, the same DEK additionally wrapped to the
2551
2791
  * org recovery public key, so the environment is recovery-protected from
2552
2792
  * creation. Omitted when recovery is off (backfilled later by `recovery sync`).
2553
2793
  */
2554
- recoveryWrappedDek: z.string().min(1).nullish()
2794
+ recoveryWrappedDek: z$1.string().min(1).nullish()
2555
2795
  });
2556
- z.object({
2796
+ z$1.object({
2557
2797
  /** Opaque versioned ciphertext blob from @seekrit/crypto. */
2558
- ciphertext: z.string().min(1).max(65536),
2798
+ ciphertext: z$1.string().min(1).max(65536),
2559
2799
  /**
2560
2800
  * Compare-and-swap: write only if the secret is currently at this version
2561
2801
  * (`0` = only if it does not exist yet), else 412 `precondition_failed`.
@@ -2563,77 +2803,77 @@ z.object({
2563
2803
  * changed, and wrote back — a refreshed agent login, say — find out that
2564
2804
  * someone else wrote in between instead of silently erasing their value.
2565
2805
  */
2566
- expectedVersion: z.number().int().min(0).optional()
2806
+ expectedVersion: z$1.number().int().min(0).optional()
2567
2807
  });
2568
- z.object({ version: z.number().int().positive() });
2569
- z.object({ limit: z.coerce.number().int().min(1).max(200).default(50) });
2570
- z.object({
2571
- requiredApprovals: z.number().int().min(1).max(10).default(1),
2572
- allowSelfApproval: z.boolean().default(false)
2808
+ z$1.object({ version: z$1.number().int().positive() });
2809
+ z$1.object({ limit: z$1.coerce.number().int().min(1).max(200).default(50) });
2810
+ z$1.object({
2811
+ requiredApprovals: z$1.number().int().min(1).max(10).default(1),
2812
+ allowSelfApproval: z$1.boolean().default(false)
2573
2813
  });
2574
- z.object({ comment: z.string().trim().max(1e3).optional() });
2575
- z.string().trim().min(1).max(1e3);
2576
- z.object({
2577
- status: z.enum(CHANGE_REQUEST_STATUSES).optional(),
2578
- envId: z.string().min(1).optional(),
2579
- limit: z.coerce.number().int().min(1).max(200).default(50)
2814
+ z$1.object({ comment: z$1.string().trim().max(1e3).optional() });
2815
+ z$1.string().trim().min(1).max(1e3);
2816
+ z$1.object({
2817
+ status: z$1.enum(CHANGE_REQUEST_STATUSES).optional(),
2818
+ envId: z$1.string().min(1).optional(),
2819
+ limit: z$1.coerce.number().int().min(1).max(200).default(50)
2580
2820
  });
2581
- z.object({
2582
- publicKeyJwk: z.string().min(1),
2821
+ z$1.object({
2822
+ publicKeyJwk: z$1.string().min(1),
2583
2823
  /**
2584
2824
  * Private key encrypted with a passphrase-derived KEK; opaque to the
2585
2825
  * server. Self-contained blob (embeds KDF salt + iterations).
2586
2826
  */
2587
- encryptedPrivateKey: z.string().min(1)
2827
+ encryptedPrivateKey: z$1.string().min(1)
2588
2828
  });
2589
- z.object({
2829
+ z$1.object({
2590
2830
  /** Base64url WebAuthn credential id — what `allowCredentials` is built from. */
2591
- credentialId: z.string().min(1).max(512),
2831
+ credentialId: z$1.string().min(1).max(512),
2592
2832
  /** Human label for the device, e.g. "MacBook Touch ID". Display only. */
2593
- label: z.string().min(1).max(64),
2833
+ label: z$1.string().min(1).max(64),
2594
2834
  /** Base64url PRF evaluation input for this credential; not a secret. */
2595
- prfInput: z.string().min(1).max(256),
2835
+ prfInput: z$1.string().min(1).max(256),
2596
2836
  /** The private key wrapped to this passkey's PRF output. */
2597
- encryptedPrivateKey: z.string().min(1).max(8192).refine((v) => v.startsWith("pk2."), { message: "expected a pk2. passkey wrap" })
2837
+ encryptedPrivateKey: z$1.string().min(1).max(8192).refine((v) => v.startsWith("pk2."), { message: "expected a pk2. passkey wrap" })
2598
2838
  });
2599
- const grantEnvironmentKeySchema = z.object({
2839
+ const grantEnvironmentKeySchema = z$1.object({
2600
2840
  principalType: principalTypeSchema,
2601
- principalId: z.string().min(1),
2602
- wrappedDek: z.string().min(1)
2841
+ principalId: z$1.string().min(1),
2842
+ wrappedDek: z$1.string().min(1)
2603
2843
  });
2604
- z.object({
2844
+ z$1.object({
2605
2845
  slug: slugSchema,
2606
2846
  /** Display name; defaults to the slug. */
2607
2847
  name: nameSchema.optional(),
2608
- ttlSeconds: z.number().int().min(60).max(MAX_BRANCH_TTL_SECONDS).nullish(),
2848
+ ttlSeconds: z$1.number().int().min(60).max(MAX_BRANCH_TTL_SECONDS).nullish(),
2609
2849
  /** The branch's own DEK, wrapped to the creator — generated client-side. */
2610
- wrappedDek: z.string().min(1),
2611
- recoveryWrappedDek: z.string().min(1).nullish(),
2850
+ wrappedDek: z$1.string().min(1),
2851
+ recoveryWrappedDek: z$1.string().min(1).nullish(),
2612
2852
  /** The same DEK wrapped to each of the parent's existing grant-holders. */
2613
- grants: z.array(grantEnvironmentKeySchema).max(500).default([])
2853
+ grants: z$1.array(grantEnvironmentKeySchema).max(500).default([])
2614
2854
  });
2615
2855
  /**
2616
2856
  * Token creation is client-driven so the server never sees the token secret:
2617
2857
  * the client generates the keypair + token string and submits only the hash
2618
2858
  * and public key.
2619
2859
  */
2620
- const environmentGrantBatchSchema = z.array(z.object({
2621
- environmentId: z.string().min(1),
2622
- wrappedDek: z.string().min(1).max(8192)
2860
+ const environmentGrantBatchSchema = z$1.array(z$1.object({
2861
+ environmentId: z$1.string().min(1),
2862
+ wrappedDek: z$1.string().min(1).max(8192)
2623
2863
  })).max(5e3);
2624
- z.object({
2864
+ z$1.object({
2625
2865
  principalType: principalTypeSchema,
2626
- principalId: z.string().min(1),
2866
+ principalId: z$1.string().min(1),
2627
2867
  grants: environmentGrantBatchSchema
2628
2868
  });
2629
- z.object({
2869
+ z$1.object({
2630
2870
  /** Commit the token and all default resolve keys together, when supplied. */
2631
2871
  initialGrants: environmentGrantBatchSchema.optional(),
2632
2872
  name: nameSchema,
2633
- tokenId: z.string().regex(/^skt_[0-9A-Za-z]+$/),
2873
+ tokenId: z$1.string().regex(/^skt_[0-9A-Za-z]+$/),
2634
2874
  /** SHA-256 hash (base64url) of the full token string. */
2635
- tokenHash: z.string().min(1),
2636
- publicKeyJwk: z.string().min(1),
2875
+ tokenHash: z$1.string().min(1),
2876
+ publicKeyJwk: z$1.string().min(1),
2637
2877
  /**
2638
2878
  * Org-level capability. Defaults to `member` (a runtime credential); pass
2639
2879
  * `admin` to mint a headless provisioning token. Only an admin caller may
@@ -2645,35 +2885,35 @@ z.object({
2645
2885
  * Optional so org-admin tokens can exist, but required for runtime tokens
2646
2886
  * that resolve secrets via `GET /v1/resolve`.
2647
2887
  */
2648
- environmentId: z.string().min(1).nullish(),
2649
- expiresAt: z.iso.datetime().nullish()
2888
+ environmentId: z$1.string().min(1).nullish(),
2889
+ expiresAt: z$1.iso.datetime().nullish()
2650
2890
  });
2651
- z.object({
2891
+ z$1.object({
2652
2892
  name: nameSchema,
2653
- tokenId: z.string().regex(/^skt_[0-9A-Za-z]+$/),
2893
+ tokenId: z$1.string().regex(/^skt_[0-9A-Za-z]+$/),
2654
2894
  /** SHA-256 hash (base64url) of the full token string. */
2655
- tokenHash: z.string().min(1),
2895
+ tokenHash: z$1.string().min(1),
2656
2896
  /** Where the decoy was planted, as a reminder for whoever reads the alert. */
2657
- placement: z.string().max(200).nullish()
2897
+ placement: z$1.string().max(200).nullish()
2658
2898
  });
2659
- const kmsKeyPurposeSchema = z.enum(["encrypt", "sign"]);
2660
- const kmsKeySpecSchema = z.enum(["aes-256-gcm", "ecdsa-p256"]);
2899
+ const kmsKeyPurposeSchema = z$1.enum(["encrypt", "sign"]);
2900
+ const kmsKeySpecSchema = z$1.enum(["aes-256-gcm", "ecdsa-p256"]);
2661
2901
  /** A wrapped key grant supplied by the client (server never sees plaintext material). */
2662
- const kmsGrantInputSchema = z.object({
2902
+ const kmsGrantInputSchema = z$1.object({
2663
2903
  principalType: principalTypeSchema,
2664
- principalId: z.string().min(1),
2904
+ principalId: z$1.string().min(1),
2665
2905
  /** Key material wrapped to the principal's public key (`wd1.` blob). */
2666
- wrappedKey: z.string().min(1)
2906
+ wrappedKey: z$1.string().min(1)
2667
2907
  });
2668
- z.object({
2908
+ z$1.object({
2669
2909
  name: nameSchema,
2670
2910
  purpose: kmsKeyPurposeSchema,
2671
2911
  spec: kmsKeySpecSchema,
2672
- applicationId: z.string().min(1).nullish(),
2673
- groupId: z.string().min(1).nullish(),
2912
+ applicationId: z$1.string().min(1).nullish(),
2913
+ groupId: z$1.string().min(1).nullish(),
2674
2914
  /** ECDSA P-256 public key (JWK) for `sign` keys; omit for `encrypt` keys. */
2675
- publicKeyJwk: z.string().min(1).nullish(),
2676
- grants: z.array(kmsGrantInputSchema).min(1)
2915
+ publicKeyJwk: z$1.string().min(1).nullish(),
2916
+ grants: z$1.array(kmsGrantInputSchema).min(1)
2677
2917
  }).refine((v) => !(v.applicationId && v.groupId), {
2678
2918
  message: "a key may be scoped to an application or a group, not both",
2679
2919
  path: ["groupId"]
@@ -2684,15 +2924,15 @@ z.object({
2684
2924
  message: "sign keys require a publicKeyJwk; encrypt keys must omit it",
2685
2925
  path: ["publicKeyJwk"]
2686
2926
  });
2687
- z.object({
2927
+ z$1.object({
2688
2928
  principalType: principalTypeSchema,
2689
- principalId: z.string().min(1),
2929
+ principalId: z$1.string().min(1),
2690
2930
  /** Current-version key material wrapped to the principal's public key. */
2691
- wrappedKey: z.string().min(1)
2931
+ wrappedKey: z$1.string().min(1)
2692
2932
  });
2693
- z.object({
2694
- publicKeyJwk: z.string().min(1).nullish(),
2695
- grants: z.array(kmsGrantInputSchema).min(1)
2933
+ z$1.object({
2934
+ publicKeyJwk: z$1.string().min(1).nullish(),
2935
+ grants: z$1.array(kmsGrantInputSchema).min(1)
2696
2936
  });
2697
2937
  /**
2698
2938
  * One custodian's wrapped Shamir share of the org recovery private key. The
@@ -2700,25 +2940,25 @@ z.object({
2700
2940
  * wraps each share to a custodian's public key — the server stores only the
2701
2941
  * opaque `wrappedShare` and can reconstruct nothing.
2702
2942
  */
2703
- const recoveryShareInputSchema = z.object({
2943
+ const recoveryShareInputSchema = z$1.object({
2704
2944
  principalType: principalTypeSchema,
2705
- principalId: z.string().min(1),
2945
+ principalId: z$1.string().min(1),
2706
2946
  /** Shamir x-coordinate carried by the share (1..255). */
2707
- shareIndex: z.number().int().min(1).max(255),
2947
+ shareIndex: z$1.number().int().min(1).max(255),
2708
2948
  /** The recovery-key share wrapped to the custodian's public key (`wd1.`). */
2709
- wrappedShare: z.string().min(1)
2949
+ wrappedShare: z$1.string().min(1)
2710
2950
  });
2711
2951
  /** An environment DEK additionally wrapped to the org recovery public key. */
2712
- const recoveryEnvGrantSchema = z.object({
2713
- environmentId: z.string().min(1),
2952
+ const recoveryEnvGrantSchema = z$1.object({
2953
+ environmentId: z$1.string().min(1),
2714
2954
  /** The environment's DEK wrapped to the recovery public key (`wd1.`). */
2715
- wrappedDek: z.string().min(1)
2955
+ wrappedDek: z$1.string().min(1)
2716
2956
  });
2717
- z.object({
2718
- recoveryPublicKeyJwk: z.string().min(1),
2719
- threshold: z.number().int().min(1).max(255),
2720
- shares: z.array(recoveryShareInputSchema).min(1).max(255),
2721
- grants: z.array(recoveryEnvGrantSchema).default([])
2957
+ z$1.object({
2958
+ recoveryPublicKeyJwk: z$1.string().min(1),
2959
+ threshold: z$1.number().int().min(1).max(255),
2960
+ shares: z$1.array(recoveryShareInputSchema).min(1).max(255),
2961
+ grants: z$1.array(recoveryEnvGrantSchema).default([])
2722
2962
  }).refine((v) => v.threshold <= v.shares.length, {
2723
2963
  message: "threshold cannot exceed the number of custodians",
2724
2964
  path: ["threshold"]
@@ -2726,104 +2966,104 @@ z.object({
2726
2966
  message: "custodians must be distinct",
2727
2967
  path: ["shares"]
2728
2968
  });
2729
- z.object({ grants: z.array(recoveryEnvGrantSchema).min(1).max(500) });
2730
- z.object({
2731
- targetPublicKeyJwk: z.string().min(1),
2969
+ z$1.object({ grants: z$1.array(recoveryEnvGrantSchema).min(1).max(500) });
2970
+ z$1.object({
2971
+ targetPublicKeyJwk: z$1.string().min(1),
2732
2972
  targetType: principalTypeSchema.nullish(),
2733
- targetId: z.string().min(1).nullish(),
2734
- reason: z.string().max(500).nullish()
2973
+ targetId: z$1.string().min(1).nullish(),
2974
+ reason: z$1.string().max(500).nullish()
2735
2975
  });
2736
- z.object({
2737
- shareIndex: z.number().int().min(1).max(255),
2976
+ z$1.object({
2977
+ shareIndex: z$1.number().int().min(1).max(255),
2738
2978
  /** The custodian's share re-wrapped to the target public key (`wd1.`). */
2739
- contributedShare: z.string().min(1)
2979
+ contributedShare: z$1.string().min(1)
2740
2980
  });
2741
- z.object({
2981
+ z$1.object({
2742
2982
  principalType: principalTypeSchema,
2743
- principalId: z.string().min(1),
2744
- grants: z.array(recoveryEnvGrantSchema).min(1).max(500)
2983
+ principalId: z$1.string().min(1),
2984
+ grants: z$1.array(recoveryEnvGrantSchema).min(1).max(500)
2745
2985
  });
2746
- z.object({ prefs: z.partialRecord(z.enum(NOTIFICATION_TYPES), z.boolean()) });
2747
- z.object({
2748
- endpoint: z.url().max(2048),
2749
- headers: z.record(z.string().min(1).max(256), z.string().max(4096)).optional(),
2750
- enabled: z.boolean().default(true)
2986
+ z$1.object({ prefs: z$1.partialRecord(z$1.enum(NOTIFICATION_TYPES), z$1.boolean()) });
2987
+ z$1.object({
2988
+ endpoint: z$1.url().max(2048),
2989
+ headers: z$1.record(z$1.string().min(1).max(256), z$1.string().max(4096)).optional(),
2990
+ enabled: z$1.boolean().default(true)
2751
2991
  });
2752
- const planFamilySchema = z.enum(PLAN_FAMILY_IDS);
2753
- const subscriptionStatusSchema = z.enum(SUBSCRIPTION_STATUSES);
2754
- z.enum(ENTITLEMENT_KEYS);
2992
+ const planFamilySchema = z$1.enum(PLAN_FAMILY_IDS);
2993
+ const subscriptionStatusSchema = z$1.enum(SUBSCRIPTION_STATUSES);
2994
+ z$1.enum(ENTITLEMENT_KEYS);
2755
2995
  /** An entitlement value: boolean (features), number or null/unlimited (limits, metered). */
2756
- const entitlementValueSchema = z.union([
2757
- z.boolean(),
2758
- z.number(),
2759
- z.null()
2996
+ const entitlementValueSchema = z$1.union([
2997
+ z$1.boolean(),
2998
+ z$1.number(),
2999
+ z$1.null()
2760
3000
  ]);
2761
- z.object({
3001
+ z$1.object({
2762
3002
  family: planFamilySchema,
2763
- version: z.number().int().positive().optional(),
3003
+ version: z$1.number().int().positive().optional(),
2764
3004
  status: subscriptionStatusSchema.default("active")
2765
3005
  });
2766
- z.object({
3006
+ z$1.object({
2767
3007
  value: entitlementValueSchema,
2768
- note: z.string().max(500).nullish(),
2769
- expiresAt: z.iso.datetime().nullish()
3008
+ note: z$1.string().max(500).nullish(),
3009
+ expiresAt: z$1.iso.datetime().nullish()
2770
3010
  });
2771
- z.object({
2772
- code: z.string().min(4).max(40),
3011
+ z$1.object({
3012
+ code: z$1.string().min(4).max(40),
2773
3013
  family: planFamilySchema,
2774
- version: z.number().int().positive().optional(),
2775
- durationDays: z.number().int().positive().max(3650).nullish(),
2776
- maxRedemptions: z.number().int().positive().nullish(),
2777
- startsAt: z.iso.datetime().nullish(),
2778
- endsAt: z.iso.datetime().nullish(),
2779
- note: z.string().max(500).nullish()
3014
+ version: z$1.number().int().positive().optional(),
3015
+ durationDays: z$1.number().int().positive().max(3650).nullish(),
3016
+ maxRedemptions: z$1.number().int().positive().nullish(),
3017
+ startsAt: z$1.iso.datetime().nullish(),
3018
+ endsAt: z$1.iso.datetime().nullish(),
3019
+ note: z$1.string().max(500).nullish()
2780
3020
  });
2781
- z.object({
2782
- maxRedemptions: z.number().int().positive().nullish(),
2783
- startsAt: z.iso.datetime().nullish(),
2784
- endsAt: z.iso.datetime().nullish(),
2785
- note: z.string().max(500).nullish(),
3021
+ z$1.object({
3022
+ maxRedemptions: z$1.number().int().positive().nullish(),
3023
+ startsAt: z$1.iso.datetime().nullish(),
3024
+ endsAt: z$1.iso.datetime().nullish(),
3025
+ note: z$1.string().max(500).nullish(),
2786
3026
  /** Kill switch. Disabling stops new redemptions; live grants are untouched. */
2787
- disabled: z.boolean().optional()
3027
+ disabled: z$1.boolean().optional()
2788
3028
  });
2789
- z.object({ code: z.string().min(1).max(40) });
2790
- z.object({ family: planFamilySchema });
2791
- z.object({
2792
- sessionId: z.string().regex(/^skc_[0-9A-Za-z]+$/),
3029
+ z$1.object({ code: z$1.string().min(1).max(40) });
3030
+ z$1.object({ family: planFamilySchema });
3031
+ z$1.object({
3032
+ sessionId: z$1.string().regex(/^skc_[0-9A-Za-z]+$/),
2793
3033
  /** SHA-256 hash (base64url) of the full session token string. */
2794
- tokenHash: z.string().min(1).max(128),
3034
+ tokenHash: z$1.string().min(1).max(128),
2795
3035
  /** Display-only, e.g. `miles@studio.local`. */
2796
- deviceLabel: z.string().trim().min(1).max(120),
3036
+ deviceLabel: z$1.string().trim().min(1).max(120),
2797
3037
  /** Display-only, e.g. `cli/0.4.2`. */
2798
- client: z.string().trim().max(60).optional()
3038
+ client: z$1.string().trim().max(60).optional()
2799
3039
  });
2800
- z.object({ code: z.string().trim().min(1).max(32) });
2801
- z.object({
2802
- cursor: z.string().optional(),
2803
- limit: z.coerce.number().int().min(1).max(200).default(50),
2804
- action: z.string().optional(),
2805
- resourceType: z.string().optional()
3040
+ z$1.object({ code: z$1.string().trim().min(1).max(32) });
3041
+ z$1.object({
3042
+ cursor: z$1.string().optional(),
3043
+ limit: z$1.coerce.number().int().min(1).max(200).default(50),
3044
+ action: z$1.string().optional(),
3045
+ resourceType: z$1.string().optional()
2806
3046
  });
2807
- z.enum([
3047
+ z$1.enum([
2808
3048
  "generated",
2809
3049
  "postgres",
2810
3050
  "mysql",
2811
3051
  "redis"
2812
3052
  ]);
2813
- z.enum([
3053
+ z$1.enum([
2814
3054
  "active",
2815
3055
  "paused",
2816
3056
  "failed"
2817
3057
  ]);
2818
3058
  /** Statuses an admin may set directly (`failed` is only reached by the sweep). */
2819
- const settableRotationStatusSchema = z.enum(["active", "paused"]);
2820
- const rotationAlphabetSchema = z.enum([
3059
+ const settableRotationStatusSchema = z$1.enum(["active", "paused"]);
3060
+ const rotationAlphabetSchema = z$1.enum([
2821
3061
  "alphanumeric",
2822
3062
  "hex",
2823
3063
  "base64url",
2824
3064
  "printable"
2825
3065
  ]);
2826
- const rotationIntervalSchema = z.number().int().min(300).max(31536e3);
3066
+ const rotationIntervalSchema = z$1.number().int().min(300).max(31536e3);
2827
3067
  /**
2828
3068
  * A database user name we are willing to *re-key*. Deliberately more permissive
2829
3069
  * than the lease providers' name schemas — those name accounts seekrit creates,
@@ -2836,44 +3076,44 @@ const rotationIntervalSchema = z.number().int().min(300).max(31536e3);
2836
3076
  * `;`, so there is no way out of the surrounding quoting, and no whitespace to
2837
3077
  * split one Redis argument into two.
2838
3078
  */
2839
- const rotationUsernameSchema = z.string().regex(/^[A-Za-z0-9_$.-]{1,63}$/, "must be 1–63 chars of letters, digits, underscore, dollar, dot or dash");
3079
+ const rotationUsernameSchema = z$1.string().regex(/^[A-Za-z0-9_$.-]{1,63}$/, "must be 1–63 chars of letters, digits, underscore, dollar, dot or dash");
2840
3080
  /** A `{{name}}`/`{{host}}`/`{{verifier}}` templated statement or command line. */
2841
- const statementSchema = z.string().min(1).max(4e3);
2842
- const passwordLengthSchema = z.number().int().min(16).max(256);
3081
+ const statementSchema = z$1.string().min(1).max(4e3);
3082
+ const passwordLengthSchema = z$1.number().int().min(16).max(256);
2843
3083
  /** A MySQL account host part (`'name'@'<host>'`) — no quotes/whitespace. */
2844
- const mysqlHostSchema = z.string().regex(/^[A-Za-z0-9_.%:-]{1,255}$/, "must be a host pattern");
2845
- const generatedRotationConfigSchema = z.object({
2846
- kind: z.literal("generated"),
3084
+ const mysqlHostSchema = z$1.string().regex(/^[A-Za-z0-9_.%:-]{1,255}$/, "must be a host pattern");
3085
+ const generatedRotationConfigSchema = z$1.object({
3086
+ kind: z$1.literal("generated"),
2847
3087
  length: passwordLengthSchema.optional(),
2848
3088
  alphabet: rotationAlphabetSchema.optional()
2849
3089
  });
2850
- const postgresRotationConfigSchema = z.object({
2851
- kind: z.literal("postgres"),
3090
+ const postgresRotationConfigSchema = z$1.object({
3091
+ kind: z$1.literal("postgres"),
2852
3092
  username: rotationUsernameSchema,
2853
3093
  passwordLength: passwordLengthSchema.optional(),
2854
- statements: z.array(statementSchema).max(16).optional()
3094
+ statements: z$1.array(statementSchema).max(16).optional()
2855
3095
  });
2856
- const mysqlRotationConfigSchema = z.object({
2857
- kind: z.literal("mysql"),
3096
+ const mysqlRotationConfigSchema = z$1.object({
3097
+ kind: z$1.literal("mysql"),
2858
3098
  username: rotationUsernameSchema,
2859
3099
  userHost: mysqlHostSchema.optional(),
2860
3100
  passwordLength: passwordLengthSchema.optional(),
2861
- statements: z.array(statementSchema).max(16).optional()
3101
+ statements: z$1.array(statementSchema).max(16).optional()
2862
3102
  });
2863
- const redisRotationConfigSchema = z.object({
2864
- kind: z.literal("redis"),
3103
+ const redisRotationConfigSchema = z$1.object({
3104
+ kind: z$1.literal("redis"),
2865
3105
  username: rotationUsernameSchema,
2866
3106
  passwordLength: passwordLengthSchema.optional(),
2867
- statements: z.array(statementSchema).max(16).optional()
3107
+ statements: z$1.array(statementSchema).max(16).optional()
2868
3108
  });
2869
- const rotationConfigSchema = z.discriminatedUnion("kind", [
3109
+ const rotationConfigSchema = z$1.discriminatedUnion("kind", [
2870
3110
  generatedRotationConfigSchema,
2871
3111
  postgresRotationConfigSchema,
2872
3112
  mysqlRotationConfigSchema,
2873
3113
  redisRotationConfigSchema
2874
3114
  ]);
2875
- z.object({
2876
- environmentId: z.string().min(1),
3115
+ z$1.object({
3116
+ environmentId: z$1.string().min(1),
2877
3117
  /** The secret whose value rotates. It must already exist. */
2878
3118
  secretName: secretNameSchema,
2879
3119
  config: rotationConfigSchema,
@@ -2882,13 +3122,13 @@ z.object({
2882
3122
  * The registered lease target supplying the connection, executor mode, and
2883
3123
  * wrapped admin credential. Required for every kind but `generated`.
2884
3124
  */
2885
- targetId: z.string().min(1).optional(),
3125
+ targetId: z$1.string().min(1).optional(),
2886
3126
  /** Environment DEK wrapped to the rotator public key (`wd1.` blob). */
2887
- wrappedDek: z.string().min(1).optional(),
3127
+ wrappedDek: z$1.string().min(1).optional(),
2888
3128
  /** Rotate once immediately instead of waiting for the first interval. */
2889
- rotateNow: z.boolean().optional()
3129
+ rotateNow: z$1.boolean().optional()
2890
3130
  });
2891
- z.object({
3131
+ z$1.object({
2892
3132
  intervalSeconds: rotationIntervalSchema.optional(),
2893
3133
  config: rotationConfigSchema.optional(),
2894
3134
  /**
@@ -2948,7 +3188,7 @@ const SYNC_PROVIDER_KINDS = [
2948
3188
  "openai-vault",
2949
3189
  "claude-managed-agents"
2950
3190
  ];
2951
- z.enum(SYNC_PROVIDER_KINDS);
3191
+ z$1.enum(SYNC_PROVIDER_KINDS);
2952
3192
  /**
2953
3193
  * Vercel account scope. The API token itself is never here — it is wrapped to
2954
3194
  * the connection's public key and stored as ciphertext.
@@ -2957,10 +3197,10 @@ z.enum(SYNC_PROVIDER_KINDS);
2957
3197
  * tokens omit it. Vercel rejects team-owned project calls that lack it with a
2958
3198
  * bare 403, so we pass it through as `?teamId=` on every request.
2959
3199
  */
2960
- const vercelConnectionConfigSchema = z.object({
2961
- provider: z.literal("vercel"),
3200
+ const vercelConnectionConfigSchema = z$1.object({
3201
+ provider: z$1.literal("vercel"),
2962
3202
  /** Vercel Team id (`team_…`). Omit for a personal account. */
2963
- teamId: z.string().trim().min(1).max(128).optional()
3203
+ teamId: z$1.string().trim().min(1).max(128).optional()
2964
3204
  });
2965
3205
  /**
2966
3206
  * A Cloudflare account id — 32 lowercase hex characters, found in the sidebar
@@ -2971,7 +3211,7 @@ const vercelConnectionConfigSchema = z.object({
2971
3211
  * hours later inside an alarm, with nobody watching. It does not catch pasting
2972
3212
  * a *zone* id, which has the same shape — only the API can tell those apart.
2973
3213
  */
2974
- const cloudflareAccountIdSchema = z.string().trim().regex(/^[0-9a-f]{32}$/, "must be a 32-character Cloudflare account ID (lowercase hex)");
3214
+ const cloudflareAccountIdSchema = z$1.string().trim().regex(/^[0-9a-f]{32}$/, "must be a 32-character Cloudflare account ID (lowercase hex)");
2975
3215
  /**
2976
3216
  * Cloudflare account scope, shared by all three Cloudflare providers. The API
2977
3217
  * token is never here — it is wrapped to the connection's public key and
@@ -2982,16 +3222,16 @@ const cloudflareAccountIdSchema = z.string().trim().regex(/^[0-9a-f]{32}$/, "mus
2982
3222
  * destinations, and fail in different ways. Splitting them keeps the
2983
3223
  * exhaustiveness guard in `connectorFor` meaningful.
2984
3224
  */
2985
- const cloudflareWorkersConnectionConfigSchema = z.object({
2986
- provider: z.literal("cloudflare-workers"),
3225
+ const cloudflareWorkersConnectionConfigSchema = z$1.object({
3226
+ provider: z$1.literal("cloudflare-workers"),
2987
3227
  accountId: cloudflareAccountIdSchema
2988
3228
  });
2989
- const cloudflarePagesConnectionConfigSchema = z.object({
2990
- provider: z.literal("cloudflare-pages"),
3229
+ const cloudflarePagesConnectionConfigSchema = z$1.object({
3230
+ provider: z$1.literal("cloudflare-pages"),
2991
3231
  accountId: cloudflareAccountIdSchema
2992
3232
  });
2993
- const cloudflareSecretsStoreConnectionConfigSchema = z.object({
2994
- provider: z.literal("cloudflare-secrets-store"),
3233
+ const cloudflareSecretsStoreConnectionConfigSchema = z$1.object({
3234
+ provider: z$1.literal("cloudflare-secrets-store"),
2995
3235
  accountId: cloudflareAccountIdSchema
2996
3236
  });
2997
3237
  /**
@@ -3000,7 +3240,7 @@ const cloudflareSecretsStoreConnectionConfigSchema = z.object({
3000
3240
  * bare GraphQL "Problem processing request" hours later inside an alarm, with
3001
3241
  * nobody watching.
3002
3242
  */
3003
- const railwayIdSchema = z.string().trim().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, "must be a Railway UUID");
3243
+ const railwayIdSchema = z$1.string().trim().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, "must be a Railway UUID");
3004
3244
  /**
3005
3245
  * Which kind of Railway API token the connection holds. This is connection
3006
3246
  * scope rather than a destination detail because it decides the *header* the
@@ -3024,9 +3264,9 @@ const RAILWAY_TOKEN_KINDS = ["account", "project"];
3024
3264
  * a destination names its project outright, so the token plus the destination
3025
3265
  * is the whole address.
3026
3266
  */
3027
- const railwayConnectionConfigSchema = z.object({
3028
- provider: z.literal("railway"),
3029
- tokenKind: z.enum(RAILWAY_TOKEN_KINDS).default("account")
3267
+ const railwayConnectionConfigSchema = z$1.object({
3268
+ provider: z$1.literal("railway"),
3269
+ tokenKind: z$1.enum(RAILWAY_TOKEN_KINDS).default("account")
3030
3270
  });
3031
3271
  /**
3032
3272
  * An AWS region id (`us-east-1`, `eu-central-1`, `us-gov-west-1`).
@@ -3036,7 +3276,7 @@ const railwayConnectionConfigSchema = z.object({
3036
3276
  * would otherwise surface as a DNS failure inside an alarm with nobody
3037
3277
  * watching — which is a much worse place to learn about it than this form.
3038
3278
  */
3039
- const awsRegionSchema = z.string().trim().regex(/^[a-z]{2}(-[a-z]+)+-\d$/, "must be an AWS region ID, e.g. us-east-1");
3279
+ const awsRegionSchema = z$1.string().trim().regex(/^[a-z]{2}(-[a-z]+)+-\d$/, "must be an AWS region ID, e.g. us-east-1");
3040
3280
  /**
3041
3281
  * The IAM access key id seekrit signs with.
3042
3282
  *
@@ -3051,7 +3291,7 @@ const awsRegionSchema = z.string().trim().regex(/^[a-z]{2}(-[a-z]+)+-\d$/, "must
3051
3291
  * Long-lived IAM user keys only. `ASIA…` session credentials from STS expire
3052
3292
  * within hours, and a sync connection has to keep working unattended.
3053
3293
  */
3054
- const awsAccessKeyIdSchema = z.string().trim().regex(/^[A-Z0-9]{16,128}$/, "must be an AWS access key ID, e.g. AKIAIOSFODNN7EXAMPLE");
3294
+ const awsAccessKeyIdSchema = z$1.string().trim().regex(/^[A-Z0-9]{16,128}$/, "must be an AWS access key ID, e.g. AKIAIOSFODNN7EXAMPLE");
3055
3295
  /**
3056
3296
  * AWS account scope, shared by both AWS providers: which region to call and
3057
3297
  * which key to sign with. There is no account id — every endpoint seekrit calls
@@ -3062,13 +3302,13 @@ const awsAccessKeyIdSchema = z.string().trim().regex(/^[A-Z0-9]{16,128}$/, "must
3062
3302
  * the three Cloudflare kinds are separate: different APIs, different
3063
3303
  * destinations, different IAM actions.
3064
3304
  */
3065
- const awsSecretsManagerConnectionConfigSchema = z.object({
3066
- provider: z.literal("aws-secrets-manager"),
3305
+ const awsSecretsManagerConnectionConfigSchema = z$1.object({
3306
+ provider: z$1.literal("aws-secrets-manager"),
3067
3307
  region: awsRegionSchema,
3068
3308
  accessKeyId: awsAccessKeyIdSchema
3069
3309
  });
3070
- const awsParameterStoreConnectionConfigSchema = z.object({
3071
- provider: z.literal("aws-parameter-store"),
3310
+ const awsParameterStoreConnectionConfigSchema = z$1.object({
3311
+ provider: z$1.literal("aws-parameter-store"),
3072
3312
  region: awsRegionSchema,
3073
3313
  accessKeyId: awsAccessKeyIdSchema
3074
3314
  });
@@ -3082,7 +3322,7 @@ const awsParameterStoreConnectionConfigSchema = z.object({
3082
3322
  * nothing is stored. The connection's `name` is what tells an operator which Render
3083
3323
  * workspace it belongs to.
3084
3324
  */
3085
- const renderConnectionConfigSchema = z.object({ provider: z.literal("render") });
3325
+ const renderConnectionConfigSchema = z$1.object({ provider: z$1.literal("render") });
3086
3326
  /**
3087
3327
  * Fly.io account scope — empty, as Render's is.
3088
3328
  *
@@ -3092,7 +3332,7 @@ const renderConnectionConfigSchema = z.object({ provider: z.literal("render") })
3092
3332
  * is — Fly's two token shapes do take different auth schemes, but
3093
3333
  * `flyAuthorization` in the connector reads which one from the token itself.
3094
3334
  */
3095
- const flyConnectionConfigSchema = z.object({ provider: z.literal("fly") });
3335
+ const flyConnectionConfigSchema = z$1.object({ provider: z$1.literal("fly") });
3096
3336
  /**
3097
3337
  * A Northflank id — projects and secret groups are both slugs derived from the
3098
3338
  * name they were created with (`default-project`, `example-secret-group`), and
@@ -3100,7 +3340,7 @@ const flyConnectionConfigSchema = z.object({ provider: z.literal("fly") });
3100
3340
  * so the common slip — pasting the *display name*, spaces and all — fails here
3101
3341
  * rather than as a bare 404 inside an alarm with nobody watching.
3102
3342
  */
3103
- const northflankIdSchema = z.string().trim().min(3).max(100).regex(/^[a-zA-Z0-9]+(-[a-zA-Z0-9]+)*$/, "must be a Northflank ID — the slug in the resource's URL, not its display name");
3343
+ const northflankIdSchema = z$1.string().trim().min(3).max(100).regex(/^[a-zA-Z0-9]+(-[a-zA-Z0-9]+)*$/, "must be a Northflank ID — the slug in the resource's URL, not its display name");
3104
3344
  /**
3105
3345
  * Northflank account scope — deliberately empty.
3106
3346
  *
@@ -3110,7 +3350,7 @@ const northflankIdSchema = z.string().trim().min(3).max(100).regex(/^[a-zA-Z0-9]
3110
3350
  * Cloudflare does: the token plus the destination's project is the whole
3111
3351
  * address. The kind exists so the discriminated union stays uniform.
3112
3352
  */
3113
- const northflankConnectionConfigSchema = z.object({ provider: z.literal("northflank") });
3353
+ const northflankConnectionConfigSchema = z$1.object({ provider: z$1.literal("northflank") });
3114
3354
  /**
3115
3355
  * DigitalOcean account scope — deliberately empty, as Render's and Fly's are.
3116
3356
  *
@@ -3120,7 +3360,7 @@ const northflankConnectionConfigSchema = z.object({ provider: z.literal("northfl
3120
3360
  * disambiguate the way Vercel needs one: the token plus the destination's app
3121
3361
  * id is the whole address.
3122
3362
  */
3123
- const digitalOceanConnectionConfigSchema = z.object({ provider: z.literal("digitalocean") });
3363
+ const digitalOceanConnectionConfigSchema = z$1.object({ provider: z$1.literal("digitalocean") });
3124
3364
  /**
3125
3365
  * Heroku account scope — empty, as Fly's and Render's are.
3126
3366
  *
@@ -3131,7 +3371,7 @@ const digitalOceanConnectionConfigSchema = z.object({ provider: z.literal("digit
3131
3371
  * `/apps/{app_id_or_name}` against everything the token can see, team-owned or
3132
3372
  * not.
3133
3373
  */
3134
- const herokuConnectionConfigSchema = z.object({ provider: z.literal("heroku") });
3374
+ const herokuConnectionConfigSchema = z$1.object({ provider: z$1.literal("heroku") });
3135
3375
  /**
3136
3376
  * Netlify team scope — the one thing a Netlify token cannot tell us itself.
3137
3377
  *
@@ -3146,10 +3386,10 @@ const herokuConnectionConfigSchema = z.object({ provider: z.literal("heroku") })
3146
3386
  * can find without an API call — it is in the dashboard URL
3147
3387
  * (`app.netlify.com/teams/<slug>`) and under Team settings → General.
3148
3388
  */
3149
- const netlifyConnectionConfigSchema = z.object({
3150
- provider: z.literal("netlify"),
3389
+ const netlifyConnectionConfigSchema = z$1.object({
3390
+ provider: z$1.literal("netlify"),
3151
3391
  /** Netlify team slug (`acme`) or account id — `{account_id}` accepts either. */
3152
- accountId: z.string().trim().min(1).max(128).regex(/^[A-Za-z0-9][A-Za-z0-9._-]*$/, "must be a Netlify team slug or account ID — no slashes or spaces")
3392
+ accountId: z$1.string().trim().min(1).max(128).regex(/^[A-Za-z0-9][A-Za-z0-9._-]*$/, "must be a Netlify team slug or account ID — no slashes or spaces")
3153
3393
  });
3154
3394
  /**
3155
3395
  * Bunnyshell account scope — empty, as Fly's, Heroku's, and Northflank's are.
@@ -3163,7 +3403,7 @@ const netlifyConnectionConfigSchema = z.object({
3163
3403
  * id is the whole address. The API offers an `organization` filter, but it
3164
3404
  * narrows a listing — it is not part of an address.
3165
3405
  */
3166
- const bunnyshellConnectionConfigSchema = z.object({ provider: z.literal("bunnyshell") });
3406
+ const bunnyshellConnectionConfigSchema = z$1.object({ provider: z$1.literal("bunnyshell") });
3167
3407
  /**
3168
3408
  * GitHub account scope — empty for github.com, which is the whole point.
3169
3409
  *
@@ -3177,13 +3417,13 @@ const bunnyshellConnectionConfigSchema = z.object({ provider: z.literal("bunnysh
3177
3417
  * with a different plan behind it). Set only for a self-hosted GHES appliance,
3178
3418
  * where the REST API is at `https://<host>/api/v3`.
3179
3419
  */
3180
- const githubActionsConnectionConfigSchema = z.object({
3181
- provider: z.literal("github-actions"),
3420
+ const githubActionsConnectionConfigSchema = z$1.object({
3421
+ provider: z$1.literal("github-actions"),
3182
3422
  /**
3183
3423
  * GitHub Enterprise Server API root, e.g. `https://github.acme.com/api/v3`.
3184
3424
  * Omit for github.com. Must be `https:` — this URL carries the token.
3185
3425
  */
3186
- baseUrl: z.string().trim().max(300).refine((value) => {
3426
+ baseUrl: z$1.string().trim().max(300).refine((value) => {
3187
3427
  let parsed;
3188
3428
  try {
3189
3429
  parsed = new URL(value);
@@ -3203,7 +3443,7 @@ const githubActionsConnectionConfigSchema = z.object({
3203
3443
  * Manager URL is built from this string, and a typo would otherwise surface as
3204
3444
  * a 403 from Google hours later inside an alarm, with nobody watching.
3205
3445
  */
3206
- const gcpProjectSchema = z.string().trim().refine((value) => /^[a-z][a-z0-9-]{4,28}[a-z0-9]$/.test(value) || /^\d{1,20}$/.test(value), "must be a Google Cloud project ID (e.g. acme-prod) or project number");
3446
+ const gcpProjectSchema = z$1.string().trim().refine((value) => /^[a-z][a-z0-9-]{4,28}[a-z0-9]$/.test(value) || /^\d{1,20}$/.test(value), "must be a Google Cloud project ID (e.g. acme-prod) or project number");
3207
3447
  /**
3208
3448
  * Google Cloud project scope — which project's Secret Manager to write.
3209
3449
  *
@@ -3222,8 +3462,8 @@ const gcpProjectSchema = z.string().trim().refine((value) => /^[a-z][a-z0-9-]{4,
3222
3462
  * regional secrets live behind. Data residency is expressed instead through the
3223
3463
  * destination's user-managed replication.
3224
3464
  */
3225
- const gcpSecretManagerConnectionConfigSchema = z.object({
3226
- provider: z.literal("gcp-secret-manager"),
3465
+ const gcpSecretManagerConnectionConfigSchema = z$1.object({
3466
+ provider: z$1.literal("gcp-secret-manager"),
3227
3467
  /** Project ID (`acme-prod`) or project number. */
3228
3468
  projectId: gcpProjectSchema
3229
3469
  });
@@ -3263,16 +3503,16 @@ const LANGGRAPH_PLATFORM_REGIONS = [
3263
3503
  * Vercel's `teamId` sets — so it is passed through as `X-Tenant-Id` whenever
3264
3504
  * it is present.
3265
3505
  */
3266
- const langgraphPlatformConnectionConfigSchema = z.object({
3267
- provider: z.literal("langgraph-platform"),
3506
+ const langgraphPlatformConnectionConfigSchema = z$1.object({
3507
+ provider: z$1.literal("langgraph-platform"),
3268
3508
  /** Control-plane region. Omit for `us`. Mutually exclusive with `baseUrl`. */
3269
- region: z.enum(LANGGRAPH_PLATFORM_REGIONS).optional(),
3509
+ region: z$1.enum(LANGGRAPH_PLATFORM_REGIONS).optional(),
3270
3510
  /**
3271
3511
  * Self-hosted LangSmith control-plane root, e.g.
3272
3512
  * `https://langsmith.acme.com/api-host`. Omit for LangChain's own hosts.
3273
3513
  * Must be `https:` — this URL carries the API key.
3274
3514
  */
3275
- baseUrl: z.string().trim().max(300).refine((value) => {
3515
+ baseUrl: z$1.string().trim().max(300).refine((value) => {
3276
3516
  let parsed;
3277
3517
  try {
3278
3518
  parsed = new URL(value);
@@ -3282,7 +3522,7 @@ const langgraphPlatformConnectionConfigSchema = z.object({
3282
3522
  return parsed.protocol === "https:" && !parsed.username && !parsed.password;
3283
3523
  }, "must be an https:// URL — the self-hosted control-plane root, e.g. https://langsmith.acme.com/api-host").optional(),
3284
3524
  /** LangSmith workspace (tenant) UUID, sent as `X-Tenant-Id`. */
3285
- tenantId: z.string().trim().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, "must be a LangSmith workspace UUID").optional()
3525
+ tenantId: z$1.string().trim().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, "must be a LangSmith workspace UUID").optional()
3286
3526
  }).refine((c) => !(c.baseUrl !== void 0 && c.region !== void 0), {
3287
3527
  message: "set region for a LangChain-hosted account or baseUrl for a self-hosted one, not both",
3288
3528
  path: ["baseUrl"]
@@ -3309,7 +3549,7 @@ const AZURE_CLOUDS = [
3309
3549
  * keeps one rule — a tenant's GUID is on the same admin-center page as the
3310
3550
  * client id it pairs with, so nothing is harder to find.
3311
3551
  */
3312
- const azureGuidSchema = z.string().trim().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, "must be a GUID, as the Entra admin center shows it");
3552
+ const azureGuidSchema = z$1.string().trim().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, "must be a GUID, as the Entra admin center shows it");
3313
3553
  /**
3314
3554
  * Azure account scope: which directory to authenticate against, as which app.
3315
3555
  *
@@ -3326,14 +3566,14 @@ const azureGuidSchema = z.string().trim().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-
3326
3566
  * has nowhere to keep, and Entra caps a client secret at 24 months, which is a
3327
3567
  * rotation the connection's `lastError` will make loud.
3328
3568
  */
3329
- const azureKeyVaultConnectionConfigSchema = z.object({
3330
- provider: z.literal("azure-key-vault"),
3569
+ const azureKeyVaultConnectionConfigSchema = z$1.object({
3570
+ provider: z$1.literal("azure-key-vault"),
3331
3571
  /** Entra directory (tenant) ID. */
3332
3572
  tenantId: azureGuidSchema,
3333
3573
  /** Application (client) ID of the service principal seekrit signs in as. */
3334
3574
  clientId: azureGuidSchema,
3335
3575
  /** Which Azure cloud the tenant and its vaults live in. */
3336
- cloud: z.enum(AZURE_CLOUDS).default("public")
3576
+ cloud: z$1.enum(AZURE_CLOUDS).default("public")
3337
3577
  });
3338
3578
  /**
3339
3579
  * Hugging Face account scope — empty, as Render's and Fly's are.
@@ -3349,9 +3589,9 @@ const azureKeyVaultConnectionConfigSchema = z.object({
3349
3589
  * not something a mirror is expected to accept a write on. Adding the field
3350
3590
  * would invite pointing a connection at a host that silently swallows secrets.
3351
3591
  */
3352
- const huggingfaceSpacesConnectionConfigSchema = z.object({ provider: z.literal("huggingface-spaces") });
3592
+ const huggingfaceSpacesConnectionConfigSchema = z$1.object({ provider: z$1.literal("huggingface-spaces") });
3353
3593
  /** The wrapped credential is an OpenAI project API key with vault read/write access. */
3354
- const openaiVaultConnectionConfigSchema = z.object({ provider: z.literal("openai-vault") });
3594
+ const openaiVaultConnectionConfigSchema = z$1.object({ provider: z$1.literal("openai-vault") });
3355
3595
  /**
3356
3596
  * Claude Managed Agents account scope — empty, for Hugging Face's reason.
3357
3597
  *
@@ -3368,8 +3608,8 @@ const openaiVaultConnectionConfigSchema = z.object({ provider: z.literal("openai
3368
3608
  * credential shape and a different connector (one that would reuse
3369
3609
  * `lib/leases/aws-sigv4.ts`), not a different host for this one.
3370
3610
  */
3371
- const claudeManagedAgentsConnectionConfigSchema = z.object({ provider: z.literal("claude-managed-agents") });
3372
- const syncConnectionConfigSchema = z.discriminatedUnion("provider", [
3611
+ const claudeManagedAgentsConnectionConfigSchema = z$1.object({ provider: z$1.literal("claude-managed-agents") });
3612
+ const syncConnectionConfigSchema = z$1.discriminatedUnion("provider", [
3373
3613
  vercelConnectionConfigSchema,
3374
3614
  cloudflareWorkersConnectionConfigSchema,
3375
3615
  cloudflarePagesConnectionConfigSchema,
@@ -3398,17 +3638,17 @@ const VERCEL_TARGETS = [
3398
3638
  "preview",
3399
3639
  "development"
3400
3640
  ];
3401
- const vercelDestinationSchema = z.object({
3402
- provider: z.literal("vercel"),
3641
+ const vercelDestinationSchema = z$1.object({
3642
+ provider: z$1.literal("vercel"),
3403
3643
  /** Vercel project id (`prj_…`) or project name. */
3404
- projectId: z.string().trim().min(1).max(128),
3644
+ projectId: z$1.string().trim().min(1).max(128),
3405
3645
  /** Which deployment targets receive these values. At least one. */
3406
- targets: z.array(z.enum(VERCEL_TARGETS)).min(1),
3646
+ targets: z$1.array(z$1.enum(VERCEL_TARGETS)).min(1),
3407
3647
  /**
3408
3648
  * Restrict `preview` writes to one git branch. Vercel only honors this when
3409
3649
  * `targets` includes `preview`; ignored otherwise.
3410
3650
  */
3411
- gitBranch: z.string().trim().min(1).max(255).optional()
3651
+ gitBranch: z$1.string().trim().min(1).max(255).optional()
3412
3652
  });
3413
3653
  /**
3414
3654
  * The Worker whose secrets a binding owns. Wrangler *environments* are not a
@@ -3416,19 +3656,19 @@ const vercelDestinationSchema = z.object({
3416
3656
  * `my-api` with `--env staging` creates a Worker literally named
3417
3657
  * `my-api-staging`, so pointing at an environment means naming that script.
3418
3658
  */
3419
- const cloudflareWorkersDestinationSchema = z.object({
3420
- provider: z.literal("cloudflare-workers"),
3659
+ const cloudflareWorkersDestinationSchema = z$1.object({
3660
+ provider: z$1.literal("cloudflare-workers"),
3421
3661
  /** Worker script name, as shown in the dashboard (`my-api`). */
3422
- scriptName: z.string().trim().min(1).max(63).regex(/^[A-Za-z0-9_][A-Za-z0-9_-]*$/, "must be a Worker script name")
3662
+ scriptName: z$1.string().trim().min(1).max(63).regex(/^[A-Za-z0-9_][A-Za-z0-9_-]*$/, "must be a Worker script name")
3423
3663
  });
3424
3664
  /** The two deployment configs a Pages project keeps env vars under. */
3425
3665
  const CLOUDFLARE_PAGES_ENVIRONMENTS = ["production", "preview"];
3426
- const cloudflarePagesDestinationSchema = z.object({
3427
- provider: z.literal("cloudflare-pages"),
3666
+ const cloudflarePagesDestinationSchema = z$1.object({
3667
+ provider: z$1.literal("cloudflare-pages"),
3428
3668
  /** Pages project name (`my-site`) — Pages has no separate project id. */
3429
- projectName: z.string().trim().min(1).max(58).regex(/^[A-Za-z0-9][A-Za-z0-9-]*$/, "must be a Pages project name"),
3669
+ projectName: z$1.string().trim().min(1).max(58).regex(/^[A-Za-z0-9][A-Za-z0-9-]*$/, "must be a Pages project name"),
3430
3670
  /** Which deployment configs receive these values. At least one. */
3431
- environments: z.array(z.enum(CLOUDFLARE_PAGES_ENVIRONMENTS)).min(1)
3671
+ environments: z$1.array(z$1.enum(CLOUDFLARE_PAGES_ENVIRONMENTS)).min(1)
3432
3672
  });
3433
3673
  /**
3434
3674
  * Scopes a Secrets Store secret may be used by. Cloudflare requires at least
@@ -3442,12 +3682,12 @@ const CLOUDFLARE_SECRETS_STORE_SCOPES = [
3442
3682
  "containers",
3443
3683
  "websearch"
3444
3684
  ];
3445
- const cloudflareSecretsStoreDestinationSchema = z.object({
3446
- provider: z.literal("cloudflare-secrets-store"),
3685
+ const cloudflareSecretsStoreDestinationSchema = z$1.object({
3686
+ provider: z$1.literal("cloudflare-secrets-store"),
3447
3687
  /** Store id (32 hex). An account has exactly one store today. */
3448
- storeId: z.string().trim().regex(/^[0-9a-f]{32}$/, "must be a 32-character Secrets Store ID (lowercase hex)"),
3688
+ storeId: z$1.string().trim().regex(/^[0-9a-f]{32}$/, "must be a 32-character Secrets Store ID (lowercase hex)"),
3449
3689
  /** Scopes applied to secrets this binding creates. At least one. */
3450
- scopes: z.array(z.enum(CLOUDFLARE_SECRETS_STORE_SCOPES)).min(1)
3690
+ scopes: z$1.array(z$1.enum(CLOUDFLARE_SECRETS_STORE_SCOPES)).min(1)
3451
3691
  });
3452
3692
  /**
3453
3693
  * Where inside Railway a binding writes.
@@ -3462,8 +3702,8 @@ const cloudflareSecretsStoreDestinationSchema = z.object({
3462
3702
  * genuinely different destination from any one service's variables, so it is an
3463
3703
  * absent field rather than a sentinel.
3464
3704
  */
3465
- const railwayDestinationSchema = z.object({
3466
- provider: z.literal("railway"),
3705
+ const railwayDestinationSchema = z$1.object({
3706
+ provider: z$1.literal("railway"),
3467
3707
  /** Railway project id (a UUID, from the project's Settings page or URL). */
3468
3708
  projectId: railwayIdSchema,
3469
3709
  /** Railway environment id (a UUID) — the deployment environment to write. */
@@ -3479,7 +3719,7 @@ const railwayDestinationSchema = z.object({
3479
3719
  * gated behind a release process and a secrets push must not start one; the
3480
3720
  * values then sit staged until the next deploy.
3481
3721
  */
3482
- skipDeploys: z.boolean().optional()
3722
+ skipDeploys: z$1.boolean().optional()
3483
3723
  });
3484
3724
  /**
3485
3725
  * A customer-managed KMS key to encrypt with, as a key id, ARN, or alias
@@ -3490,7 +3730,7 @@ const railwayDestinationSchema = z.object({
3490
3730
  * cross-account ARNs, and rejecting a valid one here would be worse than
3491
3731
  * letting KMS give its own (very clear) error.
3492
3732
  */
3493
- const awsKmsKeyIdSchema = z.string().trim().min(1).max(2048);
3733
+ const awsKmsKeyIdSchema = z$1.string().trim().min(1).max(2048);
3494
3734
  /**
3495
3735
  * How a binding lays its secrets out in Secrets Manager.
3496
3736
  *
@@ -3510,18 +3750,18 @@ const AWS_SECRETS_MANAGER_LAYOUTS = ["secret-per-name", "json-bundle"];
3510
3750
  * *variable name* (`[A-Za-z0-9_]`, no slashes), while this produces a
3511
3751
  * *namespace* — `prod/storefront/` — and slashes are the whole point of it.
3512
3752
  */
3513
- const awsSecretsManagerDestinationSchema = z.object({
3514
- provider: z.literal("aws-secrets-manager"),
3515
- layout: z.enum(AWS_SECRETS_MANAGER_LAYOUTS).default("secret-per-name"),
3753
+ const awsSecretsManagerDestinationSchema = z$1.object({
3754
+ provider: z$1.literal("aws-secrets-manager"),
3755
+ layout: z$1.enum(AWS_SECRETS_MANAGER_LAYOUTS).default("secret-per-name"),
3516
3756
  /**
3517
3757
  * `secret-per-name` only: prepended to every secret's name, e.g.
3518
3758
  * `prod/storefront/`. Optional, but strongly advised in an account that
3519
3759
  * holds anything else — without it a binding writes at the root of a
3520
3760
  * namespace it does not own.
3521
3761
  */
3522
- pathPrefix: z.string().trim().max(400).regex(/^[A-Za-z0-9/_+=.@-]*$/, "may contain letters, digits, and / _ + = . @ -").optional(),
3762
+ pathPrefix: z$1.string().trim().max(400).regex(/^[A-Za-z0-9/_+=.@-]*$/, "may contain letters, digits, and / _ + = . @ -").optional(),
3523
3763
  /** `json-bundle` only: the one secret that holds every value, e.g. `prod/storefront/env`. */
3524
- secretName: z.string().trim().min(1).max(512).regex(/^[A-Za-z0-9/_+=.@-]+$/, "may contain letters, digits, and / _ + = . @ -").optional(),
3764
+ secretName: z$1.string().trim().min(1).max(512).regex(/^[A-Za-z0-9/_+=.@-]+$/, "may contain letters, digits, and / _ + = . @ -").optional(),
3525
3765
  kmsKeyId: awsKmsKeyIdSchema.optional()
3526
3766
  }).refine((d) => d.layout !== "json-bundle" || d.secretName !== void 0, {
3527
3767
  message: "a json-bundle destination needs the name of the secret to write",
@@ -3544,17 +3784,17 @@ const AWS_PARAMETER_TIERS = [
3544
3784
  * and trailing slashes are required so the binding's names concatenate
3545
3785
  * unambiguously — `/prod/storefront/` + `DB_URL`.
3546
3786
  */
3547
- const awsParameterStoreDestinationSchema = z.object({
3548
- provider: z.literal("aws-parameter-store"),
3787
+ const awsParameterStoreDestinationSchema = z$1.object({
3788
+ provider: z$1.literal("aws-parameter-store"),
3549
3789
  /** Must start and end with `/`. `aws`/`ssm` are reserved by AWS as the first segment. */
3550
- path: z.string().trim().max(1011).regex(/^\/([A-Za-z0-9_.-]+\/)*$/, "must be a parameter path like /prod/storefront/"),
3551
- type: z.enum(AWS_PARAMETER_TYPES).default("SecureString"),
3790
+ path: z$1.string().trim().max(1011).regex(/^\/([A-Za-z0-9_.-]+\/)*$/, "must be a parameter path like /prod/storefront/"),
3791
+ type: z$1.enum(AWS_PARAMETER_TYPES).default("SecureString"),
3552
3792
  /**
3553
3793
  * Standard caps a value at 4KB and costs nothing; Advanced raises that to 8KB
3554
3794
  * and is billed per parameter per month. `Intelligent-Tiering` lets AWS pick,
3555
3795
  * upgrading only the parameters that need it.
3556
3796
  */
3557
- tier: z.enum(AWS_PARAMETER_TIERS).default("Standard"),
3797
+ tier: z$1.enum(AWS_PARAMETER_TIERS).default("Standard"),
3558
3798
  kmsKeyId: awsKmsKeyIdSchema.optional()
3559
3799
  });
3560
3800
  /**
@@ -3569,12 +3809,12 @@ const awsParameterStoreDestinationSchema = z.object({
3569
3809
  * the day Render introduces a new resource prefix, which is not our call to
3570
3810
  * make.
3571
3811
  */
3572
- const renderServiceIdSchema = z.string().trim().regex(/^(?!evg-)[A-Za-z0-9_-]{1,64}$/, "must be a Render service ID (`srv-…` or `crn-…`), not an environment group");
3573
- const renderEnvGroupIdSchema = z.string().trim().regex(/^(?!srv-|crn-)[A-Za-z0-9_-]{1,64}$/, "must be a Render environment group ID (`evg-…`), not a service");
3812
+ const renderServiceIdSchema = z$1.string().trim().regex(/^(?!evg-)[A-Za-z0-9_-]{1,64}$/, "must be a Render service ID (`srv-…` or `crn-…`), not an environment group");
3813
+ const renderEnvGroupIdSchema = z$1.string().trim().regex(/^(?!srv-|crn-)[A-Za-z0-9_-]{1,64}$/, "must be a Render environment group ID (`evg-…`), not a service");
3574
3814
  /** Environment variables set directly on one service. */
3575
- const renderServiceDestinationSchema = z.object({
3576
- provider: z.literal("render"),
3577
- kind: z.literal("service"),
3815
+ const renderServiceDestinationSchema = z$1.object({
3816
+ provider: z$1.literal("render"),
3817
+ kind: z$1.literal("service"),
3578
3818
  /** Service id (`srv-…`, or `crn-…` for a cron job), from its dashboard URL. */
3579
3819
  serviceId: renderServiceIdSchema
3580
3820
  });
@@ -3584,13 +3824,13 @@ const renderServiceDestinationSchema = z.object({
3584
3824
  * worth thinking about twice: its blast radius is the link list, not one
3585
3825
  * service.
3586
3826
  */
3587
- const renderEnvGroupDestinationSchema = z.object({
3588
- provider: z.literal("render"),
3589
- kind: z.literal("env-group"),
3827
+ const renderEnvGroupDestinationSchema = z$1.object({
3828
+ provider: z$1.literal("render"),
3829
+ kind: z$1.literal("env-group"),
3590
3830
  /** Environment group id (`evg-…`), from its dashboard URL. */
3591
3831
  envGroupId: renderEnvGroupIdSchema
3592
3832
  });
3593
- const renderDestinationSchema = z.discriminatedUnion("kind", [renderServiceDestinationSchema, renderEnvGroupDestinationSchema]);
3833
+ const renderDestinationSchema = z$1.discriminatedUnion("kind", [renderServiceDestinationSchema, renderEnvGroupDestinationSchema]);
3594
3834
  /**
3595
3835
  * The Fly app whose secret set a binding owns.
3596
3836
  *
@@ -3607,10 +3847,10 @@ const renderDestinationSchema = z.discriminatedUnion("kind", [renderServiceDesti
3607
3847
  * after the push get them straight away. The connector deliberately restarts
3608
3848
  * nothing — see the note in `apps/api/src/lib/sync/connectors/fly.ts`.
3609
3849
  */
3610
- const flyDestinationSchema = z.object({
3611
- provider: z.literal("fly"),
3850
+ const flyDestinationSchema = z$1.object({
3851
+ provider: z$1.literal("fly"),
3612
3852
  /** Fly app name, as `fly apps list` prints it. */
3613
- appName: z.string().trim().min(1).max(63).regex(/^[a-z0-9][a-z0-9-]*$/, "must be a Fly app name (lowercase letters, numbers, and dashes)")
3853
+ appName: z$1.string().trim().min(1).max(63).regex(/^[a-z0-9][a-z0-9-]*$/, "must be a Fly app name (lowercase letters, numbers, and dashes)")
3614
3854
  });
3615
3855
  /**
3616
3856
  * Where inside Northflank a binding writes: one **secret group** in one
@@ -3627,8 +3867,8 @@ const flyDestinationSchema = z.object({
3627
3867
  * separate environments are separate projects (or separate groups restricted to
3628
3868
  * a stage), so the binding's seekrit environment maps to a group, one to one.
3629
3869
  */
3630
- const northflankDestinationSchema = z.object({
3631
- provider: z.literal("northflank"),
3870
+ const northflankDestinationSchema = z$1.object({
3871
+ provider: z$1.literal("northflank"),
3632
3872
  /** Project id — the slug in the project URL (`default-project`). */
3633
3873
  projectId: northflankIdSchema,
3634
3874
  /** Secret group id — the slug in the group's URL (`example-secret-group`). */
@@ -3660,13 +3900,13 @@ const DIGITALOCEAN_ENV_SCOPES = [
3660
3900
  * from a typo: pasting the app's *name* (`storefront`), which `GET /v2/apps/{id}`
3661
3901
  * answers with a flat 404 hours later inside an alarm, with nobody watching.
3662
3902
  */
3663
- const digitalOceanAppIdSchema = z.string().trim().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, "must be a DigitalOcean app ID (the UUID in the app's URL), not its name");
3903
+ const digitalOceanAppIdSchema = z$1.string().trim().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, "must be a DigitalOcean app ID (the UUID in the app's URL), not its name");
3664
3904
  /**
3665
3905
  * A component name, matching App Platform's own pattern for one. Names are
3666
3906
  * unique within an app, which is what makes a name — rather than an index into
3667
3907
  * `services` — the stable way to address a component's variables.
3668
3908
  */
3669
- const digitalOceanComponentNameSchema = z.string().trim().regex(/^[a-z][a-z0-9-]{0,30}[a-z0-9]$/, "must be an App Platform component name (lowercase letters, numbers, and dashes)");
3909
+ const digitalOceanComponentNameSchema = z$1.string().trim().regex(/^[a-z][a-z0-9-]{0,30}[a-z0-9]$/, "must be an App Platform component name (lowercase letters, numbers, and dashes)");
3670
3910
  /**
3671
3911
  * Where inside a DigitalOcean app a binding writes.
3672
3912
  *
@@ -3693,27 +3933,27 @@ const digitalOceanComponentNameSchema = z.string().trim().regex(/^[a-z][a-z0-9-]
3693
3933
  * about to write is already there — see
3694
3934
  * `apps/api/src/lib/sync/connectors/digitalocean.ts`.
3695
3935
  */
3696
- const digitalOceanAppDestinationSchema = z.object({
3697
- provider: z.literal("digitalocean"),
3698
- kind: z.literal("app"),
3936
+ const digitalOceanAppDestinationSchema = z$1.object({
3937
+ provider: z$1.literal("digitalocean"),
3938
+ kind: z$1.literal("app"),
3699
3939
  /** App id — the UUID in `cloud.digitalocean.com/apps/<id>`. */
3700
3940
  appId: digitalOceanAppIdSchema,
3701
- scope: z.enum(DIGITALOCEAN_ENV_SCOPES).default("RUN_TIME")
3941
+ scope: z$1.enum(DIGITALOCEAN_ENV_SCOPES).default("RUN_TIME")
3702
3942
  });
3703
3943
  /**
3704
3944
  * One component's own environment variables. Narrower than the app-level list:
3705
3945
  * only this service, worker, job, static site, or function sees them, and a key
3706
3946
  * here wins over the same key at app level.
3707
3947
  */
3708
- const digitalOceanComponentDestinationSchema = z.object({
3709
- provider: z.literal("digitalocean"),
3710
- kind: z.literal("component"),
3948
+ const digitalOceanComponentDestinationSchema = z$1.object({
3949
+ provider: z$1.literal("digitalocean"),
3950
+ kind: z$1.literal("component"),
3711
3951
  appId: digitalOceanAppIdSchema,
3712
3952
  /** Component name, as it appears in the app spec — not its type. */
3713
3953
  componentName: digitalOceanComponentNameSchema,
3714
- scope: z.enum(DIGITALOCEAN_ENV_SCOPES).default("RUN_TIME")
3954
+ scope: z$1.enum(DIGITALOCEAN_ENV_SCOPES).default("RUN_TIME")
3715
3955
  });
3716
- const digitalOceanDestinationSchema = z.discriminatedUnion("kind", [digitalOceanAppDestinationSchema, digitalOceanComponentDestinationSchema]);
3956
+ const digitalOceanDestinationSchema = z$1.discriminatedUnion("kind", [digitalOceanAppDestinationSchema, digitalOceanComponentDestinationSchema]);
3717
3957
  /**
3718
3958
  * A Heroku app, named the way `/apps/{app_id_or_name}` names one: either the
3719
3959
  * app name or its UUID id. Both are accepted because both work, and the id is
@@ -3726,7 +3966,7 @@ const digitalOceanDestinationSchema = z.discriminatedUnion("kind", [digitalOcean
3726
3966
  * capitals — into a message at the form rather than a bare 404 from an alarm
3727
3967
  * with nobody watching.
3728
3968
  */
3729
- const herokuAppSchema = z.string().trim().refine((value) => /^[a-z][a-z0-9-]{1,28}[a-z0-9]$/.test(value) || /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value), "must be a Heroku app name (lowercase letters, numbers, and dashes) or its UUID");
3969
+ const herokuAppSchema = z$1.string().trim().refine((value) => /^[a-z][a-z0-9-]{1,28}[a-z0-9]$/.test(value) || /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value), "must be a Heroku app name (lowercase letters, numbers, and dashes) or its UUID");
3730
3970
  /**
3731
3971
  * The Heroku app whose config vars a binding owns.
3732
3972
  *
@@ -3740,8 +3980,8 @@ const herokuAppSchema = z.string().trim().refine((value) => /^[a-z][a-z0-9-]{1,2
3740
3980
  * release and restarts the app's dynos, which is why a run sends exactly one
3741
3981
  * request — see the note in `apps/api/src/lib/sync/connectors/heroku.ts`.
3742
3982
  */
3743
- const herokuDestinationSchema = z.object({
3744
- provider: z.literal("heroku"),
3983
+ const herokuDestinationSchema = z$1.object({
3984
+ provider: z$1.literal("heroku"),
3745
3985
  /** App name as `heroku apps` prints it, or the app's UUID. */
3746
3986
  app: herokuAppSchema
3747
3987
  });
@@ -3779,7 +4019,7 @@ const NETLIFY_CONTEXTS = [
3779
4019
  * by every site in it. Refusing anything but the UUID keeps a slip from turning
3780
4020
  * into a much wider blast radius than the operator asked for.
3781
4021
  */
3782
- const netlifySiteIdSchema = z.string().trim().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, "must be the site's API ID (a UUID), not its name or URL");
4022
+ const netlifySiteIdSchema = z$1.string().trim().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, "must be the site's API ID (a UUID), not its name or URL");
3783
4023
  /**
3784
4024
  * The Netlify site, and which of its deploy contexts a binding owns.
3785
4025
  *
@@ -3801,16 +4041,16 @@ const netlifySiteIdSchema = z.string().trim().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0
3801
4041
  * existing variable, or removed from one ever — and it needs a plan that
3802
4042
  * includes Secrets Controller.
3803
4043
  */
3804
- const netlifyDestinationSchema = z.object({
3805
- provider: z.literal("netlify"),
4044
+ const netlifyDestinationSchema = z$1.object({
4045
+ provider: z$1.literal("netlify"),
3806
4046
  /** Site API ID (a UUID), from Project configuration → General. */
3807
4047
  siteId: netlifySiteIdSchema,
3808
4048
  /** Which deploy contexts receive these values. At least one. */
3809
- contexts: z.array(z.enum(NETLIFY_CONTEXTS)).min(1),
4049
+ contexts: z$1.array(z$1.enum(NETLIFY_CONTEXTS)).min(1),
3810
4050
  /** Branch name, required when `contexts` includes `branch`; ignored otherwise. */
3811
- branch: z.string().trim().min(1).max(255).optional(),
4051
+ branch: z$1.string().trim().min(1).max(255).optional(),
3812
4052
  /** Create variables as Netlify secrets (default true). */
3813
- secret: z.boolean().optional()
4053
+ secret: z$1.boolean().optional()
3814
4054
  }).refine((d) => !d.contexts.includes("branch") || d.branch !== void 0, {
3815
4055
  message: "a branch context needs the branch name it applies to",
3816
4056
  path: ["branch"]
@@ -3832,7 +4072,7 @@ const netlifyDestinationSchema = z.object({
3832
4072
  * before it touches it, so a filter that failed to bite cannot turn into an
3833
4073
  * edit of a neighbouring environment's variables.
3834
4074
  */
3835
- const bunnyshellIdSchema = z.string().trim().min(1).max(64).regex(/^[A-Za-z0-9][A-Za-z0-9._-]*$/, "must be a Bunnyshell ID — no slashes or spaces");
4075
+ const bunnyshellIdSchema = z$1.string().trim().min(1).max(64).regex(/^[A-Za-z0-9][A-Za-z0-9._-]*$/, "must be a Bunnyshell ID — no slashes or spaces");
3836
4076
  /**
3837
4077
  * Variables on one Bunnyshell **environment** — the set every component in it
3838
4078
  * inherits, and the closest match to a seekrit environment.
@@ -3840,13 +4080,13 @@ const bunnyshellIdSchema = z.string().trim().min(1).max(64).regex(/^[A-Za-z0-9][
3840
4080
  * This is the destination for an environment that already exists and stays
3841
4081
  * around: a primary environment, or a long-lived ephemeral one.
3842
4082
  */
3843
- const bunnyshellEnvironmentDestinationSchema = z.object({
3844
- provider: z.literal("bunnyshell"),
3845
- kind: z.literal("environment"),
4083
+ const bunnyshellEnvironmentDestinationSchema = z$1.object({
4084
+ provider: z$1.literal("bunnyshell"),
4085
+ kind: z$1.literal("environment"),
3846
4086
  /** Environment ID, as `bns environments list` prints it. */
3847
4087
  environmentId: bunnyshellIdSchema,
3848
4088
  /** Mark what seekrit creates as a Bunnyshell secret (default true). */
3849
- secret: z.boolean().optional()
4089
+ secret: z$1.boolean().optional()
3850
4090
  });
3851
4091
  /**
3852
4092
  * Variables on a Bunnyshell **project** — inherited by every environment
@@ -3863,13 +4103,13 @@ const bunnyshellEnvironmentDestinationSchema = z.object({
3863
4103
  * overridden at its own scope — so a project binding does not fight an
3864
4104
  * environment binding pointed at the same name, it loses to it.
3865
4105
  */
3866
- const bunnyshellProjectDestinationSchema = z.object({
3867
- provider: z.literal("bunnyshell"),
3868
- kind: z.literal("project"),
4106
+ const bunnyshellProjectDestinationSchema = z$1.object({
4107
+ provider: z$1.literal("bunnyshell"),
4108
+ kind: z$1.literal("project"),
3869
4109
  /** Project ID, as `bns projects list` prints it. */
3870
4110
  projectId: bunnyshellIdSchema,
3871
4111
  /** Mark what seekrit creates as a Bunnyshell secret (default true). */
3872
- secret: z.boolean().optional()
4112
+ secret: z$1.boolean().optional()
3873
4113
  });
3874
4114
  /**
3875
4115
  * Where in Bunnyshell a binding writes.
@@ -3889,7 +4129,7 @@ const bunnyshellProjectDestinationSchema = z.object({
3889
4129
  * variables seekrit **creates**: an update never sends the flag, so a variable
3890
4130
  * an operator deliberately un-secreted stays that way.
3891
4131
  */
3892
- const bunnyshellDestinationSchema = z.discriminatedUnion("kind", [bunnyshellEnvironmentDestinationSchema, bunnyshellProjectDestinationSchema]);
4132
+ const bunnyshellDestinationSchema = z$1.discriminatedUnion("kind", [bunnyshellEnvironmentDestinationSchema, bunnyshellProjectDestinationSchema]);
3893
4133
  /**
3894
4134
  * Which repositories in an organization can read an org-level secret.
3895
4135
  *
@@ -3912,14 +4152,14 @@ const GITHUB_ACTIONS_VISIBILITIES = [
3912
4152
  * owner field — fails at the form rather than as a 404 from an alarm with nobody
3913
4153
  * watching.
3914
4154
  */
3915
- const githubOwnerSchema = z.string().trim().min(1).max(39).regex(/^[A-Za-z0-9](?:-?[A-Za-z0-9])*$/, "must be a GitHub user or organization login — not a URL or an owner/repo pair");
4155
+ const githubOwnerSchema = z$1.string().trim().min(1).max(39).regex(/^[A-Za-z0-9](?:-?[A-Za-z0-9])*$/, "must be a GitHub user or organization login — not a URL or an owner/repo pair");
3916
4156
  /**
3917
4157
  * A repository name. GitHub's rules are looser than an owner's: letters,
3918
4158
  * numbers, hyphens, underscores, and periods, up to 100 characters. `.` and `..`
3919
4159
  * are refused outright — they would traverse the API path rather than name a
3920
4160
  * repository.
3921
4161
  */
3922
- const githubRepoSchema = z.string().trim().min(1).max(100).regex(/^[A-Za-z0-9._-]+$/, "must be a repository name alone (`api`), not `owner/repo` or a URL").refine((value) => value !== "." && value !== "..", "is not a repository name");
4162
+ const githubRepoSchema = z$1.string().trim().min(1).max(100).regex(/^[A-Za-z0-9._-]+$/, "must be a repository name alone (`api`), not `owner/repo` or a URL").refine((value) => value !== "." && value !== "..", "is not a repository name");
3923
4163
  /**
3924
4164
  * A deployment environment name.
3925
4165
  *
@@ -3928,7 +4168,7 @@ const githubRepoSchema = z.string().trim().min(1).max(100).regex(/^[A-Za-z0-9._-
3928
4168
  * break the request are refused — an empty name, and the path separators that
3929
4169
  * would let a name escape its URL segment. Everything else is GitHub's to reject.
3930
4170
  */
3931
- const githubEnvironmentSchema = z.string().trim().min(1).max(255).refine((value) => !value.includes("/") && !value.includes("\\"), "cannot contain a slash — that is a path separator, not part of an environment name");
4171
+ const githubEnvironmentSchema = z$1.string().trim().min(1).max(255).refine((value) => !value.includes("/") && !value.includes("\\"), "cannot contain a slash — that is a path separator, not part of an environment name");
3932
4172
  /**
3933
4173
  * One repository's Actions secrets.
3934
4174
  *
@@ -3937,9 +4177,9 @@ const githubEnvironmentSchema = z.string().trim().min(1).max(255).refine((value)
3937
4177
  * choice this connector makes — but it is the reason `environment` exists below,
3938
4178
  * and the reason to prefer it for anything that touches production.
3939
4179
  */
3940
- const githubActionsRepoDestinationSchema = z.object({
3941
- provider: z.literal("github-actions"),
3942
- kind: z.literal("repo"),
4180
+ const githubActionsRepoDestinationSchema = z$1.object({
4181
+ provider: z$1.literal("github-actions"),
4182
+ kind: z$1.literal("repo"),
3943
4183
  /** Repository owner — a user or organization login. */
3944
4184
  owner: githubOwnerSchema,
3945
4185
  /** Repository name, without the owner. */
@@ -3959,9 +4199,9 @@ const githubActionsRepoDestinationSchema = z.object({
3959
4199
  * because a name was misspelled would quietly remove the protection the operator
3960
4200
  * was relying on.
3961
4201
  */
3962
- const githubActionsEnvironmentDestinationSchema = z.object({
3963
- provider: z.literal("github-actions"),
3964
- kind: z.literal("environment"),
4202
+ const githubActionsEnvironmentDestinationSchema = z$1.object({
4203
+ provider: z$1.literal("github-actions"),
4204
+ kind: z$1.literal("environment"),
3965
4205
  owner: githubOwnerSchema,
3966
4206
  repo: githubRepoSchema,
3967
4207
  /** Environment name, exactly as the repository's Settings → Environments shows it. */
@@ -3981,15 +4221,15 @@ const githubActionsEnvironmentDestinationSchema = z.object({
3981
4221
  * resolution would mean this connector picking which repository an ambiguous
3982
4222
  * name meant, and getting that wrong widens a secret's reach silently.
3983
4223
  */
3984
- const githubActionsOrgDestinationSchema = z.object({
3985
- provider: z.literal("github-actions"),
3986
- kind: z.literal("org"),
4224
+ const githubActionsOrgDestinationSchema = z$1.object({
4225
+ provider: z$1.literal("github-actions"),
4226
+ kind: z$1.literal("org"),
3987
4227
  /** Organization login. */
3988
4228
  org: githubOwnerSchema,
3989
4229
  /** Which repositories may read these secrets. Stated, never defaulted. */
3990
- visibility: z.enum(GITHUB_ACTIONS_VISIBILITIES),
4230
+ visibility: z$1.enum(GITHUB_ACTIONS_VISIBILITIES),
3991
4231
  /** Numeric repository ids, required when `visibility` is `selected`. */
3992
- selectedRepositoryIds: z.array(z.number().int().positive()).max(500).optional()
4232
+ selectedRepositoryIds: z$1.array(z$1.number().int().positive()).max(500).optional()
3993
4233
  }).refine((dest) => dest.visibility !== "selected" || dest.selectedRepositoryIds !== void 0 && dest.selectedRepositoryIds.length > 0, {
3994
4234
  message: "selected visibility needs at least one repository id",
3995
4235
  path: ["selectedRepositoryIds"]
@@ -3997,7 +4237,7 @@ const githubActionsOrgDestinationSchema = z.object({
3997
4237
  message: "repository ids only apply to selected visibility — remove them, or select it",
3998
4238
  path: ["selectedRepositoryIds"]
3999
4239
  });
4000
- const githubActionsDestinationSchema = z.discriminatedUnion("kind", [
4240
+ const githubActionsDestinationSchema = z$1.discriminatedUnion("kind", [
4001
4241
  githubActionsRepoDestinationSchema,
4002
4242
  githubActionsEnvironmentDestinationSchema,
4003
4243
  githubActionsOrgDestinationSchema
@@ -4036,14 +4276,14 @@ const GCP_REPLICATION_POLICIES = ["automatic", "user-managed"];
4036
4276
  * Manager namespace is spelled `prod-storefront-DB_URL`, not
4037
4277
  * `prod/storefront/DB_URL`.
4038
4278
  */
4039
- const gcpSecretIdSchema = z.string().trim().min(1).max(255).regex(/^[A-Za-z0-9_-]+$/, "may contain letters, digits, hyphens, and underscores");
4279
+ const gcpSecretIdSchema = z$1.string().trim().min(1).max(255).regex(/^[A-Za-z0-9_-]+$/, "may contain letters, digits, hyphens, and underscores");
4040
4280
  /**
4041
4281
  * A GCP region for a user-managed replica (`us-east1`, `europe-west4`,
4042
4282
  * `northamerica-northeast1`). Validated by shape rather than against a list,
4043
4283
  * because Google adds regions faster than we ship — a name Secret Manager does
4044
4284
  * not know is refused by Google with a clear message at creation.
4045
4285
  */
4046
- const gcpLocationSchema = z.string().trim().regex(/^[a-z]+-[a-z]+\d+$/, "must be a GCP region ID, e.g. us-east1");
4286
+ const gcpLocationSchema = z$1.string().trim().regex(/^[a-z]+-[a-z]+\d+$/, "must be a GCP region ID, e.g. us-east1");
4047
4287
  /**
4048
4288
  * A Cloud KMS key, as its full resource name — the only form the API accepts:
4049
4289
  * `projects/p/locations/l/keyRings/r/cryptoKeys/k`.
@@ -4053,7 +4293,7 @@ const gcpLocationSchema = z.string().trim().regex(/^[a-z]+-[a-z]+\d+$/, "must be
4053
4293
  * rejected at creation: an automatic-replication secret needs a `global` key,
4054
4294
  * and a user-managed replica needs one in its own region.
4055
4295
  */
4056
- const gcpKmsKeyNameSchema = z.string().trim().max(1024).regex(/^projects\/[^/]+\/locations\/[^/]+\/keyRings\/[^/]+\/cryptoKeys\/[^/]+$/, "must be a full Cloud KMS key name (projects/…/locations/…/keyRings/…/cryptoKeys/…)");
4296
+ const gcpKmsKeyNameSchema = z$1.string().trim().max(1024).regex(/^projects\/[^/]+\/locations\/[^/]+\/keyRings\/[^/]+\/cryptoKeys\/[^/]+$/, "must be a full Cloud KMS key name (projects/…/locations/…/keyRings/…/cryptoKeys/…)");
4057
4297
  /**
4058
4298
  * Where inside a project's Secret Manager a binding writes.
4059
4299
  *
@@ -4072,25 +4312,25 @@ const gcpKmsKeyNameSchema = z.string().trim().max(1024).regex(/^projects\/[^/]+\
4072
4312
  * on, the version a push supersedes is destroyed as soon as the new one lands,
4073
4313
  * so a secret keeps exactly one active version.
4074
4314
  */
4075
- const gcpSecretManagerDestinationSchema = z.object({
4076
- provider: z.literal("gcp-secret-manager"),
4077
- layout: z.enum(GCP_SECRET_MANAGER_LAYOUTS).default("secret-per-name"),
4315
+ const gcpSecretManagerDestinationSchema = z$1.object({
4316
+ provider: z$1.literal("gcp-secret-manager"),
4317
+ layout: z$1.enum(GCP_SECRET_MANAGER_LAYOUTS).default("secret-per-name"),
4078
4318
  /**
4079
4319
  * `secret-per-name` only: prepended to every secret ID, e.g.
4080
4320
  * `prod-storefront-`. Optional, but strongly advised in a project that holds
4081
4321
  * anything else — without it a binding writes at the root of a namespace it
4082
4322
  * does not own, and Secret Manager has no folders to hide behind.
4083
4323
  */
4084
- idPrefix: z.string().trim().max(200).regex(/^[A-Za-z0-9_-]*$/, "may contain letters, digits, hyphens, and underscores").optional(),
4324
+ idPrefix: z$1.string().trim().max(200).regex(/^[A-Za-z0-9_-]*$/, "may contain letters, digits, hyphens, and underscores").optional(),
4085
4325
  /** `json-bundle` only: the one secret that holds every value, e.g. `prod-storefront-env`. */
4086
4326
  secretId: gcpSecretIdSchema.optional(),
4087
- replication: z.enum(GCP_REPLICATION_POLICIES).default("automatic"),
4327
+ replication: z$1.enum(GCP_REPLICATION_POLICIES).default("automatic"),
4088
4328
  /** `user-managed` only: the regions to replicate to. At least one. */
4089
- locations: z.array(gcpLocationSchema).min(1).max(16).optional(),
4329
+ locations: z$1.array(gcpLocationSchema).min(1).max(16).optional(),
4090
4330
  /** Customer-managed encryption key. Omitted means Google-managed keys. */
4091
4331
  kmsKeyName: gcpKmsKeyNameSchema.optional(),
4092
4332
  /** Destroy the version each push supersedes, keeping one active version. */
4093
- pruneVersions: z.boolean().optional()
4333
+ pruneVersions: z$1.boolean().optional()
4094
4334
  }).refine((d) => d.layout !== "json-bundle" || d.secretId !== void 0, {
4095
4335
  message: "a json-bundle destination needs the ID of the secret to write",
4096
4336
  path: ["secretId"]
@@ -4117,10 +4357,10 @@ const gcpSecretManagerDestinationSchema = z.object({
4117
4357
  * the `id` from `GET /v2/deployments`, and the UUID in the deployment's
4118
4358
  * dashboard URL.
4119
4359
  */
4120
- const langgraphPlatformDestinationSchema = z.object({
4121
- provider: z.literal("langgraph-platform"),
4360
+ const langgraphPlatformDestinationSchema = z$1.object({
4361
+ provider: z$1.literal("langgraph-platform"),
4122
4362
  /** Deployment UUID, from the dashboard URL or `GET /v2/deployments`. */
4123
- deploymentId: z.string().trim().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, "must be a LangGraph Platform deployment UUID")
4363
+ deploymentId: z$1.string().trim().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, "must be a LangGraph Platform deployment UUID")
4124
4364
  });
4125
4365
  /**
4126
4366
  * A Key Vault's name — the leftmost label of its DNS name, so the vault
@@ -4136,7 +4376,7 @@ const langgraphPlatformDestinationSchema = z.object({
4136
4376
  * any host, and the whole address seekrit needs is this label plus the cloud
4137
4377
  * already named on the connection.
4138
4378
  */
4139
- const azureVaultNameSchema = z.string().trim().regex(/^[A-Za-z](?!.*--)[A-Za-z0-9-]{1,22}[A-Za-z0-9]$/, "must be a Key Vault name: 3–24 letters, digits, and single hyphens, starting with a letter");
4379
+ const azureVaultNameSchema = z$1.string().trim().regex(/^[A-Za-z](?!.*--)[A-Za-z0-9-]{1,22}[A-Za-z0-9]$/, "must be a Key Vault name: 3–24 letters, digits, and single hyphens, starting with a letter");
4140
4380
  /**
4141
4381
  * What to do with a name Key Vault cannot store.
4142
4382
  *
@@ -4167,8 +4407,8 @@ const AZURE_KEY_VAULT_NAME_MODES = ["dash", "reject"];
4167
4407
  * charges per *operation*, so fifty names cost the same stored fifty ways. One
4168
4408
  * secret per name is simply correct here.
4169
4409
  */
4170
- const azureKeyVaultDestinationSchema = z.object({
4171
- provider: z.literal("azure-key-vault"),
4410
+ const azureKeyVaultDestinationSchema = z$1.object({
4411
+ provider: z$1.literal("azure-key-vault"),
4172
4412
  /** Vault name, e.g. `acme-prod` for `acme-prod.vault.azure.net`. */
4173
4413
  vault: azureVaultNameSchema,
4174
4414
  /**
@@ -4177,9 +4417,9 @@ const azureKeyVaultDestinationSchema = z.object({
4177
4417
  * accepts — so unlike Parameter Store's `path` this is a naming convention
4178
4418
  * and nothing more. Worth setting in a vault that holds anything else.
4179
4419
  */
4180
- prefix: z.string().trim().max(64).regex(/^[A-Za-z0-9-]*$/, "may contain letters, digits, and hyphens").optional(),
4420
+ prefix: z$1.string().trim().max(64).regex(/^[A-Za-z0-9-]*$/, "may contain letters, digits, and hyphens").optional(),
4181
4421
  /** What to do with a name Key Vault cannot store — see {@link AZURE_KEY_VAULT_NAME_MODES}. */
4182
- nameMode: z.enum(AZURE_KEY_VAULT_NAME_MODES).default("dash")
4422
+ nameMode: z$1.enum(AZURE_KEY_VAULT_NAME_MODES).default("dash")
4183
4423
  });
4184
4424
  /**
4185
4425
  * The Space whose secrets a binding owns, addressed the way the Hub addresses
@@ -4198,7 +4438,7 @@ const azureKeyVaultDestinationSchema = z.object({
4198
4438
  * leading character is held to alphanumeric, which is also what rejects the
4199
4439
  * `.` and `..` that no repository may be called.
4200
4440
  */
4201
- const huggingfaceRepoIdSchema = z.string().trim().regex(/^[A-Za-z0-9][A-Za-z0-9._-]{0,95}\/[A-Za-z0-9][A-Za-z0-9._-]{0,95}$/, "must be a Space ID as owner/name, e.g. acme/support-demo — not a URL");
4441
+ const huggingfaceRepoIdSchema = z$1.string().trim().regex(/^[A-Za-z0-9][A-Za-z0-9._-]{0,95}\/[A-Za-z0-9][A-Za-z0-9._-]{0,95}$/, "must be a Space ID as owner/name, e.g. acme/support-demo — not a URL");
4202
4442
  /**
4203
4443
  * One Hugging Face **Space**, whose secrets arrive in the app's container as
4204
4444
  * environment variables.
@@ -4210,16 +4450,16 @@ const huggingfaceRepoIdSchema = z.string().trim().regex(/^[A-Za-z0-9][A-Za-z0-9.
4210
4450
  * it, so this connector has no variables mode — a binding that wants one is
4211
4451
  * asking for the wrong thing.
4212
4452
  */
4213
- const huggingfaceSpacesDestinationSchema = z.object({
4214
- provider: z.literal("huggingface-spaces"),
4453
+ const huggingfaceSpacesDestinationSchema = z$1.object({
4454
+ provider: z$1.literal("huggingface-spaces"),
4215
4455
  /** Space ID as `owner/name`, e.g. `acme/support-demo`. */
4216
4456
  repoId: huggingfaceRepoIdSchema
4217
4457
  });
4218
4458
  /** One existing OpenAI vault; every credential in this binding gets the same host boundary. */
4219
- const openaiVaultDestinationSchema = z.object({
4220
- provider: z.literal("openai-vault"),
4221
- vaultId: z.string().trim().regex(/^vault_[A-Za-z0-9_-]+$/, "must be an OpenAI vault ID"),
4222
- allowedHosts: z.array(z.string().trim().toLowerCase().max(253).regex(/^(?=.{1,253}$)[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)+$/, "must be an exact hostname without scheme, port, path, or wildcard")).min(1).max(100).refine((hosts) => new Set(hosts).size === hosts.length, "hostnames must be unique")
4459
+ const openaiVaultDestinationSchema = z$1.object({
4460
+ provider: z$1.literal("openai-vault"),
4461
+ vaultId: z$1.string().trim().regex(/^vault_[A-Za-z0-9_-]+$/, "must be an OpenAI vault ID"),
4462
+ allowedHosts: z$1.array(z$1.string().trim().toLowerCase().max(253).regex(/^(?=.{1,253}$)[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)+$/, "must be an exact hostname without scheme, port, path, or wildcard")).min(1).max(100).refine((hosts) => new Set(hosts).size === hosts.length, "hostnames must be unique")
4223
4463
  });
4224
4464
  /**
4225
4465
  * A vault ID as the Claude Console and API show it: `vlt_` and an opaque
@@ -4227,7 +4467,7 @@ const openaiVaultDestinationSchema = z.object({
4227
4467
  * vault's display name — is a 404 from inside an alarm, which says nothing
4228
4468
  * about which half of the address was wrong.
4229
4469
  */
4230
- const claudeVaultIdSchema = z.string().trim().regex(/^vlt_[A-Za-z0-9]{1,128}$/, "must be a vault ID, e.g. vlt_01ABC… — not its display name");
4470
+ const claudeVaultIdSchema = z$1.string().trim().regex(/^vlt_[A-Za-z0-9]{1,128}$/, "must be a vault ID, e.g. vlt_01ABC… — not its display name");
4231
4471
  /** Ceiling on per-name host rules; a vault itself holds at most 20 credentials. */
4232
4472
  const CLAUDE_VAULT_MAX_HOST_RULES = 100;
4233
4473
  /** A hostname of two or more labels whose last label starts with a letter. */
@@ -4244,14 +4484,14 @@ const CLAUDE_VAULT_IPV4 = /^(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2
4244
4484
  * `stripe.com` **but not `stripe.com` itself**, so a service reached at its apex
4245
4485
  * needs both entries. A bare TLD wildcard (`*.com`) is refused by shape.
4246
4486
  */
4247
- const claudeVaultHostSchema = z.string().trim().toLowerCase().max(253).refine((host) => CLAUDE_VAULT_HOSTNAME.test(host) || CLAUDE_VAULT_IPV4.test(host), "must be a bare hostname (api.example.com), a *.example.com wildcard, or an IPv4 address — not a URL");
4487
+ const claudeVaultHostSchema = z$1.string().trim().toLowerCase().max(253).refine((host) => CLAUDE_VAULT_HOSTNAME.test(host) || CLAUDE_VAULT_IPV4.test(host), "must be a bare hostname (api.example.com), a *.example.com wildcard, or an IPv4 address — not a URL");
4248
4488
  /**
4249
4489
  * Where one secret's value may be substituted: a list of hosts, or the literal
4250
4490
  * `"unrestricted"`, which lets it reach any host the agent's *environment*
4251
4491
  * permits. The literal is spelled out rather than implied by an empty list, so
4252
4492
  * the widest setting is never something a binding arrives at by omission.
4253
4493
  */
4254
- const claudeVaultHostRuleSchema = z.union([z.literal("unrestricted"), z.array(claudeVaultHostSchema).min(1).max(16)]);
4494
+ const claudeVaultHostRuleSchema = z$1.union([z$1.literal("unrestricted"), z$1.array(claudeVaultHostSchema).min(1).max(16)]);
4255
4495
  /**
4256
4496
  * Which parts of an outbound request a secret's placeholder is swapped in. The
4257
4497
  * API's own default when the field is omitted is both; seekrit's is `header`,
@@ -4284,15 +4524,15 @@ const CLAUDE_VAULT_INJECTION_LOCATIONS = [
4284
4524
  * flow. Both levels apply beside the agent environment's own network policy,
4285
4525
  * which must also let the host through; this shape cannot see that policy.
4286
4526
  */
4287
- const claudeManagedAgentsDestinationSchema = z.object({
4288
- provider: z.literal("claude-managed-agents"),
4527
+ const claudeManagedAgentsDestinationSchema = z$1.object({
4528
+ provider: z$1.literal("claude-managed-agents"),
4289
4529
  /** The vault's ID, e.g. `vlt_01ABC…`. */
4290
4530
  vaultId: claudeVaultIdSchema,
4291
4531
  /** Hosts for every name without its own entry in `allowedHostsByName`. */
4292
4532
  allowedHosts: claudeVaultHostRuleSchema.optional(),
4293
4533
  /** Destination name → the hosts that one value may be substituted on. */
4294
- allowedHostsByName: z.record(secretNameSchema, claudeVaultHostRuleSchema).optional(),
4295
- injectionLocation: z.enum(CLAUDE_VAULT_INJECTION_LOCATIONS).default("header")
4534
+ allowedHostsByName: z$1.record(secretNameSchema, claudeVaultHostRuleSchema).optional(),
4535
+ injectionLocation: z$1.enum(CLAUDE_VAULT_INJECTION_LOCATIONS).default("header")
4296
4536
  }).refine((d) => d.allowedHosts !== void 0 || Object.keys(d.allowedHostsByName ?? {}).length > 0, {
4297
4537
  message: "name the hosts each secret may be used on — allowedHosts for all of them, allowedHostsByName per name, or \"unrestricted\"",
4298
4538
  path: ["allowedHosts"]
@@ -4300,7 +4540,7 @@ const claudeManagedAgentsDestinationSchema = z.object({
4300
4540
  message: `at most ${CLAUDE_VAULT_MAX_HOST_RULES} per-name host rules`,
4301
4541
  path: ["allowedHostsByName"]
4302
4542
  });
4303
- const syncDestinationSchema = z.discriminatedUnion("provider", [
4543
+ const syncDestinationSchema = z$1.discriminatedUnion("provider", [
4304
4544
  vercelDestinationSchema,
4305
4545
  cloudflareWorkersDestinationSchema,
4306
4546
  cloudflarePagesDestinationSchema,
@@ -4327,59 +4567,59 @@ const syncDestinationSchema = z.discriminatedUnion("provider", [
4327
4567
  * How seekrit secret names become destination key names. Applied in order:
4328
4568
  * explicit `rename` (wins outright), then `prefix`/`suffix`, then `case`.
4329
4569
  */
4330
- const nameTransformSchema = z.object({
4331
- prefix: z.string().max(64).regex(/^[A-Za-z0-9_]*$/, "must be alphanumeric or underscore").optional(),
4332
- suffix: z.string().max(64).regex(/^[A-Za-z0-9_]*$/, "must be alphanumeric or underscore").optional(),
4333
- case: z.enum([
4570
+ const nameTransformSchema = z$1.object({
4571
+ prefix: z$1.string().max(64).regex(/^[A-Za-z0-9_]*$/, "must be alphanumeric or underscore").optional(),
4572
+ suffix: z$1.string().max(64).regex(/^[A-Za-z0-9_]*$/, "must be alphanumeric or underscore").optional(),
4573
+ case: z$1.enum([
4334
4574
  "preserve",
4335
4575
  "upper",
4336
4576
  "lower"
4337
4577
  ]).optional(),
4338
4578
  /** Exact per-secret overrides, seekrit name → destination name. */
4339
- rename: z.record(secretNameSchema, secretNameSchema).optional()
4579
+ rename: z$1.record(secretNameSchema, secretNameSchema).optional()
4340
4580
  });
4341
- z.object({
4581
+ z$1.object({
4342
4582
  /**
4343
4583
  * The id the client already fetched a public key for. Connections are a
4344
4584
  * two-step dance — mint the key, wrap the credential to it, then create the
4345
4585
  * row — so the id has to be chosen before the row exists. Omit it and the
4346
4586
  * server generates one (only useful when there is no credential to wrap yet).
4347
4587
  */
4348
- id: z.string().regex(/^syc_[A-Za-z0-9]{24}$/, "must be a connection id from the public-key call").optional(),
4349
- name: z.string().trim().min(1).max(128),
4588
+ id: z$1.string().regex(/^syc_[A-Za-z0-9]{24}$/, "must be a connection id from the public-key call").optional(),
4589
+ name: z$1.string().trim().min(1).max(128),
4350
4590
  config: syncConnectionConfigSchema,
4351
4591
  /**
4352
4592
  * The destination's API credential (a Vercel token), encrypted client-side to
4353
4593
  * the connection's public key (a `wd1.` wrap). The control plane stores only
4354
4594
  * this ciphertext; it is unwrapped transiently inside the sync engine DO.
4355
4595
  */
4356
- wrappedCredential: z.string().min(1)
4596
+ wrappedCredential: z$1.string().min(1)
4357
4597
  });
4358
- z.object({ destination: syncDestinationSchema });
4359
- const globListSchema = z.array(z.string().trim().min(1).max(256)).max(100);
4360
- z.object({
4361
- connectionId: z.string().min(1),
4362
- environmentId: z.string().min(1),
4598
+ z$1.object({ destination: syncDestinationSchema });
4599
+ const globListSchema = z$1.array(z$1.string().trim().min(1).max(256)).max(100);
4600
+ z$1.object({
4601
+ connectionId: z$1.string().min(1),
4602
+ environmentId: z$1.string().min(1),
4363
4603
  destination: syncDestinationSchema,
4364
4604
  nameTransform: nameTransformSchema.optional(),
4365
4605
  include: globListSchema.optional(),
4366
4606
  exclude: globListSchema.optional(),
4367
- onDelete: z.enum(["delete", "retain"]).default("delete"),
4368
- mode: z.enum(["auto", "manual"]).default("auto"),
4369
- wrappedDeks: z.array(z.object({
4370
- environmentId: z.string().min(1),
4371
- wrappedDek: z.string().min(1)
4607
+ onDelete: z$1.enum(["delete", "retain"]).default("delete"),
4608
+ mode: z$1.enum(["auto", "manual"]).default("auto"),
4609
+ wrappedDeks: z$1.array(z$1.object({
4610
+ environmentId: z$1.string().min(1),
4611
+ wrappedDek: z$1.string().min(1)
4372
4612
  })).min(1),
4373
- acknowledgedDecryption: z.literal(true)
4613
+ acknowledgedDecryption: z$1.literal(true)
4374
4614
  });
4375
- z.object({
4615
+ z$1.object({
4376
4616
  destination: syncDestinationSchema.optional(),
4377
4617
  nameTransform: nameTransformSchema.nullable().optional(),
4378
4618
  include: globListSchema.nullable().optional(),
4379
4619
  exclude: globListSchema.nullable().optional(),
4380
- onDelete: z.enum(["delete", "retain"]).optional(),
4381
- mode: z.enum(["auto", "manual"]).optional(),
4382
- enabled: z.boolean().optional()
4620
+ onDelete: z$1.enum(["delete", "retain"]).optional(),
4621
+ mode: z$1.enum(["auto", "manual"]).optional(),
4622
+ enabled: z$1.boolean().optional()
4383
4623
  });
4384
4624
  // ../../packages/core/src/vault.ts
4385
4625
  /** One encrypted credential within a connection. */
@@ -4411,73 +4651,73 @@ const VAULT_WEBHOOK_EVENTS = [
4411
4651
  "connection.reauth_required",
4412
4652
  "connection.revoked"
4413
4653
  ];
4414
- const base64urlMember = z.string().regex(/^[A-Za-z0-9_-]{43}$/, "not a P-256 coordinate");
4415
- const vaultPublicJwkSchema = z.object({
4416
- kty: z.literal("EC"),
4417
- crv: z.literal("P-256"),
4654
+ const base64urlMember = z$1.string().regex(/^[A-Za-z0-9_-]{43}$/, "not a P-256 coordinate");
4655
+ const vaultPublicJwkSchema = z$1.object({
4656
+ kty: z$1.literal("EC"),
4657
+ crv: z$1.literal("P-256"),
4418
4658
  x: base64urlMember,
4419
4659
  y: base64urlMember
4420
4660
  });
4421
- const isoInstant = z.iso.datetime({ offset: true });
4422
- z.object({
4423
- v: z.literal(1),
4424
- accessToken: z.string().min(1).max(16384),
4425
- tokenType: z.literal("Bearer"),
4661
+ const isoInstant = z$1.iso.datetime({ offset: true });
4662
+ z$1.object({
4663
+ v: z$1.literal(1),
4664
+ accessToken: z$1.string().min(1).max(16384),
4665
+ tokenType: z$1.literal("Bearer"),
4426
4666
  accessTokenExpiresAt: isoInstant.optional(),
4427
- refreshToken: z.string().min(1).max(16384).optional(),
4667
+ refreshToken: z$1.string().min(1).max(16384).optional(),
4428
4668
  refreshTokenExpiresAt: isoInstant.optional(),
4429
- scope: z.array(z.string().max(512)).max(128),
4669
+ scope: z$1.array(z$1.string().max(512)).max(128),
4430
4670
  obtainedAt: isoInstant
4431
4671
  });
4432
- z.object({
4433
- v: z.literal(1),
4434
- key: z.string().min(1).max(8192)
4672
+ z$1.object({
4673
+ v: z$1.literal(1),
4674
+ key: z$1.string().min(1).max(8192)
4435
4675
  });
4436
4676
  /** RFC 6238 parameters, as an authenticator app would hold them. */
4437
- const vaultTotpSchema = z.object({
4677
+ const vaultTotpSchema = z$1.object({
4438
4678
  /** Base32 (RFC 4648), upper case, no padding, no separators. */
4439
- secret: z.string().regex(/^[A-Z2-7]{16,128}$/, "TOTP secret must be base32"),
4440
- digits: z.union([z.literal(6), z.literal(8)]),
4441
- period: z.number().int().min(15).max(120),
4442
- algorithm: z.enum([
4679
+ secret: z$1.string().regex(/^[A-Z2-7]{16,128}$/, "TOTP secret must be base32"),
4680
+ digits: z$1.union([z$1.literal(6), z$1.literal(8)]),
4681
+ period: z$1.number().int().min(15).max(120),
4682
+ algorithm: z$1.enum([
4443
4683
  "SHA1",
4444
4684
  "SHA256",
4445
4685
  "SHA512"
4446
4686
  ])
4447
4687
  });
4448
- z.object({
4449
- v: z.literal(1),
4450
- username: z.string().min(1).max(512),
4451
- password: z.string().min(1).max(4096),
4688
+ z$1.object({
4689
+ v: z$1.literal(1),
4690
+ username: z$1.string().min(1).max(512),
4691
+ password: z$1.string().min(1).max(4096),
4452
4692
  totp: vaultTotpSchema.optional()
4453
4693
  });
4454
- const vaultSessionCookieSchema = z.object({
4455
- name: z.string().min(1).max(4096),
4456
- value: z.string().max(16384),
4694
+ const vaultSessionCookieSchema = z$1.object({
4695
+ name: z$1.string().min(1).max(4096),
4696
+ value: z$1.string().max(16384),
4457
4697
  /** Kept exactly as captured — parent-domain cookies restore to their parent. */
4458
- domain: z.string().min(1).max(253),
4459
- path: z.string().min(1).max(4096),
4698
+ domain: z$1.string().min(1).max(253),
4699
+ path: z$1.string().min(1).max(4096),
4460
4700
  /** Unix seconds; -1 ⇒ a session cookie. */
4461
- expires: z.number(),
4462
- httpOnly: z.boolean(),
4463
- secure: z.boolean(),
4464
- sameSite: z.enum([
4701
+ expires: z$1.number(),
4702
+ httpOnly: z$1.boolean(),
4703
+ secure: z$1.boolean(),
4704
+ sameSite: z$1.enum([
4465
4705
  "Strict",
4466
4706
  "Lax",
4467
4707
  "None"
4468
4708
  ]).optional(),
4469
- partitionKey: z.unknown().optional()
4709
+ partitionKey: z$1.unknown().optional()
4470
4710
  });
4471
- z.object({
4472
- v: z.literal(1),
4473
- siteId: z.string().min(1).max(64),
4711
+ z$1.object({
4712
+ v: z$1.literal(1),
4713
+ siteId: z$1.string().min(1).max(64),
4474
4714
  capturedAt: isoInstant,
4475
- userAgent: z.string().max(1024),
4476
- cookies: z.array(vaultSessionCookieSchema).max(4096),
4715
+ userAgent: z$1.string().max(1024),
4716
+ cookies: z$1.array(vaultSessionCookieSchema).max(4096),
4477
4717
  /** origin → key → value. */
4478
- localStorage: z.record(z.string(), z.record(z.string(), z.string()))
4718
+ localStorage: z$1.record(z$1.string(), z$1.record(z$1.string(), z$1.string()))
4479
4719
  });
4480
- const vaultProviderIdSchema = z.string().trim().min(1).max(64).regex(/^[a-z0-9][a-z0-9._-]*$/, "provider ids are lowercase letters, digits, dots and dashes");
4720
+ const vaultProviderIdSchema = z$1.string().trim().min(1).max(64).regex(/^[a-z0-9][a-z0-9._-]*$/, "provider ids are lowercase letters, digits, dots and dashes");
4481
4721
  /**
4482
4722
  * What the dashboard, Connect and the SDK may know about a provider: its name,
4483
4723
  * its method, and — for the consent screen — a plain sentence about what the
@@ -4485,90 +4725,90 @@ const vaultProviderIdSchema = z.string().trim().min(1).max(64).regex(/^[a-z0-9][
4485
4725
  * those are compiled into the executor and the API must not be able to serve a
4486
4726
  * different version of them.
4487
4727
  */
4488
- const vaultCatalogProviderSchema = z.object({
4728
+ const vaultCatalogProviderSchema = z$1.object({
4489
4729
  id: vaultProviderIdSchema,
4490
- displayName: z.string().trim().min(1).max(80),
4491
- method: z.enum(["oauth2", "api_key"]),
4730
+ displayName: z$1.string().trim().min(1).max(80),
4731
+ method: z$1.enum(["oauth2", "api_key"]),
4492
4732
  /** The one sentence Connect shows: "read and send email as you". */
4493
- consentSummary: z.string().trim().min(1).max(240),
4733
+ consentSummary: z$1.string().trim().min(1).max(240),
4494
4734
  /** Hosts the executor will forward to, for display. */
4495
- hosts: z.array(z.string().trim().min(1).max(253)).max(64).default([]),
4735
+ hosts: z$1.array(z$1.string().trim().min(1).max(253)).max(64).default([]),
4496
4736
  /** Where the end user finds the key (api_key providers). */
4497
- helpUrl: z.url().max(2048).optional(),
4737
+ helpUrl: z$1.url().max(2048).optional(),
4498
4738
  /** Label for the key field (api_key providers), e.g. "API key". */
4499
- keyLabel: z.string().trim().min(1).max(60).optional(),
4739
+ keyLabel: z$1.string().trim().min(1).max(60).optional(),
4500
4740
  /** OAuth scopes the provider will be asked for (oauth2 providers), for display. */
4501
- scopes: z.array(z.string().trim().min(1).max(512)).max(64).optional()
4741
+ scopes: z$1.array(z$1.string().trim().min(1).max(512)).max(64).optional()
4502
4742
  });
4503
- const vaultCatalogSiteSchema = z.object({
4743
+ const vaultCatalogSiteSchema = z$1.object({
4504
4744
  id: vaultProviderIdSchema,
4505
- displayName: z.string().trim().min(1).max(80),
4506
- consentSummary: z.string().trim().min(1).max(240),
4745
+ displayName: z$1.string().trim().min(1).max(80),
4746
+ consentSummary: z$1.string().trim().min(1).max(240),
4507
4747
  /** Origins the login form must live on (shown so the person can check). */
4508
- loginOrigins: z.array(z.url().max(2048)).max(16).default([]),
4748
+ loginOrigins: z$1.array(z$1.url().max(2048)).max(16).default([]),
4509
4749
  /** Where a restored session lands, for display. */
4510
- startUrl: z.url().max(2048).optional()
4750
+ startUrl: z$1.url().max(2048).optional()
4511
4751
  });
4512
- const vaultCatalogSchema = z.object({
4513
- v: z.literal(1),
4514
- providers: z.array(vaultCatalogProviderSchema).max(200).default([]),
4515
- sites: z.array(vaultCatalogSiteSchema).max(200).default([])
4752
+ const vaultCatalogSchema = z$1.object({
4753
+ v: z$1.literal(1),
4754
+ providers: z$1.array(vaultCatalogProviderSchema).max(200).default([]),
4755
+ sites: z$1.array(vaultCatalogSiteSchema).max(200).default([])
4516
4756
  });
4517
- const vaultDisplaySchema = z.object({
4757
+ const vaultDisplaySchema = z$1.object({
4518
4758
  /** The platform's name as its users know it: "Instinct", not "instinct-prod". */
4519
- name: z.string().trim().min(1).max(80),
4520
- logoUrl: z.url().max(2048).startsWith("https://").optional(),
4759
+ name: z$1.string().trim().min(1).max(80),
4760
+ logoUrl: z$1.url().max(2048).startsWith("https://").optional(),
4521
4761
  /** `#rrggbb`. */
4522
- accent: z.string().regex(/^#[0-9a-fA-F]{6}$/, "accent must be a #rrggbb colour").optional(),
4762
+ accent: z$1.string().regex(/^#[0-9a-fA-F]{6}$/, "accent must be a #rrggbb colour").optional(),
4523
4763
  /** Origins a `returnUrl` may point at. Exact-match, scheme + host (+ port). */
4524
- returnOrigins: z.array(z.url().max(2048)).max(16).default([])
4764
+ returnOrigins: z$1.array(z$1.url().max(2048)).max(16).default([])
4525
4765
  });
4526
- z.object({
4766
+ z$1.object({
4527
4767
  name: nameSchema,
4528
4768
  display: vaultDisplaySchema.optional()
4529
4769
  });
4530
- z.object({
4770
+ z$1.object({
4531
4771
  name: nameSchema.optional(),
4532
4772
  display: vaultDisplaySchema.optional(),
4533
- status: z.enum(["active", "disabled"]).optional()
4773
+ status: z$1.enum(["active", "disabled"]).optional()
4534
4774
  });
4535
- z.object({ name: nameSchema });
4775
+ z$1.object({ name: nameSchema });
4536
4776
  /**
4537
4777
  * The platform's opaque identifier for its end user. Stored as given and
4538
4778
  * returned as given. It must not be an email address or anything else that
4539
4779
  * identifies the person outside the platform: the person has no seekrit
4540
4780
  * account, and this is the one field about them Vault holds in the clear.
4541
4781
  */
4542
- const vaultUserRefSchema = z.string().trim().min(1).max(200).refine((v) => !/\s/.test(v), { message: "userRef must not contain whitespace" }).refine((v) => !/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(v), { message: "userRef must be an opaque identifier, not an email address" });
4543
- z.object({
4782
+ const vaultUserRefSchema = z$1.string().trim().min(1).max(200).refine((v) => !/\s/.test(v), { message: "userRef must not contain whitespace" }).refine((v) => !/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(v), { message: "userRef must be an opaque identifier, not an email address" });
4783
+ z$1.object({
4544
4784
  userRef: vaultUserRefSchema,
4545
4785
  providerId: vaultProviderIdSchema,
4546
- purpose: z.enum(["connect", "reconnect"]).default("connect"),
4786
+ purpose: z$1.enum(["connect", "reconnect"]).default("connect"),
4547
4787
  /** Required for `reconnect`: the connection being repaired. */
4548
- connectionId: z.string().trim().min(1).max(64).optional(),
4788
+ connectionId: z$1.string().trim().min(1).max(64).optional(),
4549
4789
  /** Where the done screen may send the person. Must match a registered origin. */
4550
- returnUrl: z.url().max(2048).optional(),
4551
- expiresInSeconds: z.number().int().min(60).max(VAULT_CONNECT_SESSION_MAX_TTL_SECONDS).optional()
4790
+ returnUrl: z$1.url().max(2048).optional(),
4791
+ expiresInSeconds: z$1.number().int().min(60).max(VAULT_CONNECT_SESSION_MAX_TTL_SECONDS).optional()
4552
4792
  });
4553
- z.object({
4793
+ z$1.object({
4554
4794
  userRef: vaultUserRefSchema,
4555
- returnUrl: z.url().max(2048).optional(),
4556
- expiresInSeconds: z.number().int().min(60).max(VAULT_CONNECT_SESSION_MAX_TTL_SECONDS).optional()
4795
+ returnUrl: z$1.url().max(2048).optional(),
4796
+ expiresInSeconds: z$1.number().int().min(60).max(VAULT_CONNECT_SESSION_MAX_TTL_SECONDS).optional()
4557
4797
  });
4558
- z.object({
4559
- url: z.url().max(2048).refine((u) => u.startsWith("https://"), "webhook URLs must be https"),
4798
+ z$1.object({
4799
+ url: z$1.url().max(2048).refine((u) => u.startsWith("https://"), "webhook URLs must be https"),
4560
4800
  /** Defaults to every event. */
4561
- events: z.array(z.enum(VAULT_WEBHOOK_EVENTS)).min(1).max(VAULT_WEBHOOK_EVENTS.length).optional(),
4562
- description: z.string().trim().max(200).optional()
4801
+ events: z$1.array(z$1.enum(VAULT_WEBHOOK_EVENTS)).min(1).max(VAULT_WEBHOOK_EVENTS.length).optional(),
4802
+ description: z$1.string().trim().max(200).optional()
4563
4803
  });
4564
- z.object({
4804
+ z$1.object({
4565
4805
  userRef: vaultUserRefSchema.optional(),
4566
- status: z.enum(VAULT_CONNECTION_STATUSES).optional(),
4567
- cursor: z.string().max(200).optional(),
4568
- limit: z.coerce.number().int().min(1).max(200).default(50)
4806
+ status: z$1.enum(VAULT_CONNECTION_STATUSES).optional(),
4807
+ cursor: z$1.string().max(200).optional(),
4808
+ limit: z$1.coerce.number().int().min(1).max(200).default(50)
4569
4809
  });
4570
4810
  /** An `https://host[:port]` origin with nothing after it; `http://localhost` in dev. */
4571
- const vaultOriginSchema = z.string().trim().max(2048).refine((v) => {
4811
+ const vaultOriginSchema = z$1.string().trim().max(2048).refine((v) => {
4572
4812
  let url;
4573
4813
  try {
4574
4814
  url = new URL(v);
@@ -4583,85 +4823,85 @@ const vaultOriginSchema = z.string().trim().max(2048).refine((v) => {
4583
4823
  "[::1]"
4584
4824
  ].includes(url.hostname);
4585
4825
  }, { message: "must be an https origin (scheme + host, nothing else)" });
4586
- const vaultWrappingKeySchema = z.object({
4826
+ const vaultWrappingKeySchema = z$1.object({
4587
4827
  jwk: vaultPublicJwkSchema,
4588
- thumbprint: z.string().regex(/^[A-Za-z0-9_-]{43}$/)
4828
+ thumbprint: z$1.string().regex(/^[A-Za-z0-9_-]{43}$/)
4589
4829
  });
4590
- z.object({
4591
- code: z.string().trim().min(16).max(200),
4830
+ z$1.object({
4831
+ code: z$1.string().trim().min(16).max(200),
4592
4832
  origin: vaultOriginSchema,
4593
4833
  wrappingKey: vaultWrappingKeySchema,
4594
4834
  catalog: vaultCatalogSchema,
4595
- sdkVersion: z.string().trim().min(1).max(40)
4835
+ sdkVersion: z$1.string().trim().min(1).max(40)
4596
4836
  });
4597
- z.object({
4837
+ z$1.object({
4598
4838
  catalog: vaultCatalogSchema,
4599
- sdkVersion: z.string().trim().min(1).max(40)
4839
+ sdkVersion: z$1.string().trim().min(1).max(40)
4600
4840
  });
4601
- z.object({ wrappingKey: vaultWrappingKeySchema });
4841
+ z$1.object({ wrappingKey: vaultWrappingKeySchema });
4602
4842
  /** One encrypted slot, as produced by Connect or the executor. */
4603
- const vaultEncryptedSlotSchema = z.object({
4604
- slot: z.enum(VAULT_SLOTS),
4605
- revision: z.number().int().min(1),
4606
- ciphertext: z.string().startsWith("sc1.").max(VAULT_CIPHERTEXT_MAX_CHARS),
4607
- wrappedDek: z.string().startsWith("wd1.").max(2048),
4608
- keyThumbprint: z.string().regex(/^[A-Za-z0-9_-]{43}$/)
4843
+ const vaultEncryptedSlotSchema = z$1.object({
4844
+ slot: z$1.enum(VAULT_SLOTS),
4845
+ revision: z$1.number().int().min(1),
4846
+ ciphertext: z$1.string().startsWith("sc1.").max(VAULT_CIPHERTEXT_MAX_CHARS),
4847
+ wrappedDek: z$1.string().startsWith("wd1.").max(2048),
4848
+ keyThumbprint: z$1.string().regex(/^[A-Za-z0-9_-]{43}$/)
4609
4849
  });
4610
- z.object({
4611
- slots: z.array(vaultEncryptedSlotSchema).min(1).max(2),
4850
+ z$1.object({
4851
+ slots: z$1.array(vaultEncryptedSlotSchema).min(1).max(2),
4612
4852
  /** "ava@example.com" / "@ava" — shown to the platform and the org, never used for auth. */
4613
- accountLabel: z.string().trim().min(1).max(200).optional()
4853
+ accountLabel: z$1.string().trim().min(1).max(200).optional()
4614
4854
  });
4615
- z.object({
4855
+ z$1.object({
4616
4856
  /** The revision the writer read; the write lands as `expectedRevision + 1`. */
4617
- expectedRevision: z.number().int().min(0),
4618
- ciphertext: z.string().startsWith("sc1.").max(VAULT_CIPHERTEXT_MAX_CHARS),
4619
- wrappedDek: z.string().startsWith("wd1.").max(2048),
4620
- keyThumbprint: z.string().regex(/^[A-Za-z0-9_-]{43}$/)
4857
+ expectedRevision: z$1.number().int().min(0),
4858
+ ciphertext: z$1.string().startsWith("sc1.").max(VAULT_CIPHERTEXT_MAX_CHARS),
4859
+ wrappedDek: z$1.string().startsWith("wd1.").max(2048),
4860
+ keyThumbprint: z$1.string().regex(/^[A-Za-z0-9_-]{43}$/)
4621
4861
  });
4622
- z.discriminatedUnion("status", [z.object({
4623
- status: z.literal("reauth_required"),
4624
- reason: z.string().trim().min(1).max(120)
4625
- }), z.object({ status: z.literal("active") })]);
4626
- z.object({ claimToken: z.string().min(16).max(200) });
4627
- z.object({ token: z.string().min(16).max(200) });
4628
- z.object({ consentVersion: z.literal(1) });
4629
- z.object({ connectionId: z.string().trim().min(1).max(64) });
4630
- z.object({
4862
+ z$1.discriminatedUnion("status", [z$1.object({
4863
+ status: z$1.literal("reauth_required"),
4864
+ reason: z$1.string().trim().min(1).max(120)
4865
+ }), z$1.object({ status: z$1.literal("active") })]);
4866
+ z$1.object({ claimToken: z$1.string().min(16).max(200) });
4867
+ z$1.object({ token: z$1.string().min(16).max(200) });
4868
+ z$1.object({ consentVersion: z$1.literal(1) });
4869
+ z$1.object({ connectionId: z$1.string().trim().min(1).max(64) });
4870
+ z$1.object({
4631
4871
  login: vaultEncryptedSlotSchema.refine((slot) => slot.slot === "login", "must be the login slot").optional(),
4632
- accountLabel: z.string().trim().min(1).max(200).optional()
4872
+ accountLabel: z$1.string().trim().min(1).max(200).optional()
4633
4873
  });
4634
- z.object({
4874
+ z$1.object({
4635
4875
  userRef: vaultUserRefSchema,
4636
- connectionId: z.string().trim().min(1).max(64),
4637
- request: z.object({
4638
- method: z.string().trim().toUpperCase().regex(/^[A-Z]{3,10}$/),
4639
- url: z.url().max(8192),
4640
- headers: z.record(z.string().max(256), z.string().max(16384)).optional(),
4876
+ connectionId: z$1.string().trim().min(1).max(64),
4877
+ request: z$1.object({
4878
+ method: z$1.string().trim().toUpperCase().regex(/^[A-Z]{3,10}$/),
4879
+ url: z$1.url().max(8192),
4880
+ headers: z$1.record(z$1.string().max(256), z$1.string().max(16384)).optional(),
4641
4881
  /** UTF-8 text. Binary bodies are out of scope for V1. */
4642
- body: z.string().max(4194304).optional()
4882
+ body: z$1.string().max(4194304).optional()
4643
4883
  })
4644
4884
  });
4645
- const connectionIdSchema = z.string().trim().min(1).max(64);
4646
- const leaseIdSchema = z.string().trim().min(1).max(64);
4647
- z.object({
4885
+ const connectionIdSchema = z$1.string().trim().min(1).max(64);
4886
+ const leaseIdSchema = z$1.string().trim().min(1).max(64);
4887
+ z$1.object({
4648
4888
  userRef: vaultUserRefSchema,
4649
4889
  connectionId: connectionIdSchema,
4650
4890
  /** How long the agent may hold the browser. Clamped to the site's ceiling. */
4651
- keepAliveMs: z.number().int().min(VAULT_LEASE_MIN_MS).max(VAULT_LEASE_MAX_MS).optional()
4891
+ keepAliveMs: z$1.number().int().min(VAULT_LEASE_MIN_MS).max(VAULT_LEASE_MAX_MS).optional()
4652
4892
  });
4653
- z.object({
4893
+ z$1.object({
4654
4894
  userRef: vaultUserRefSchema,
4655
4895
  leaseId: leaseIdSchema,
4656
- field: z.enum(VAULT_FILL_FIELDS)
4896
+ field: z$1.enum(VAULT_FILL_FIELDS)
4657
4897
  });
4658
- z.object({
4898
+ z$1.object({
4659
4899
  userRef: vaultUserRefSchema,
4660
4900
  leaseId: leaseIdSchema,
4661
4901
  /** Write the rotated session back (default). `false` drops the browser without saving. */
4662
- save: z.boolean().default(true)
4902
+ save: z$1.boolean().default(true)
4663
4903
  });
4664
- z.object({
4904
+ z$1.object({
4665
4905
  userRef: vaultUserRefSchema,
4666
4906
  leaseId: leaseIdSchema
4667
4907
  });
@@ -5045,6 +5285,19 @@ async function decryptDataKey(material, wrapped) {
5045
5285
  throw new SeekritCryptoError("DECRYPT_FAILED", "data key unwrap failed: wrong key or tampered blob");
5046
5286
  }
5047
5287
  }
5288
+ // ../../packages/crypto/src/managed-credential.ts
5289
+ const generateCredentialRecipientKeyPair = generateKeyPair;
5290
+ /** Only called on the consumer; the API receives the wrapped bytes. */
5291
+ async function unwrapManagedCredential(wrapped, privateKeyJwk) {
5292
+ const bytes = await unwrapDek(wrapped, await importPrivateKey(privateKeyJwk));
5293
+ try {
5294
+ const result = JSON.parse(new TextDecoder().decode(bytes));
5295
+ if (!result || typeof result !== "object" || Array.isArray(result) || !Object.values(result).every((value) => typeof value === "string")) throw new Error();
5296
+ return result;
5297
+ } catch {
5298
+ throw new SeekritCryptoError("DECRYPT_FAILED", "invalid managed credential");
5299
+ }
5300
+ }
5048
5301
  // ../../packages/crypto/src/random.ts
5049
5302
  const ALPHABETS = {
5050
5303
  alphanumeric: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
@@ -5887,7 +6140,7 @@ async function createAgentTaskToken() {
5887
6140
  };
5888
6141
  }
5889
6142
  // package.json
5890
- var version = "2.5.1";
6143
+ var version = "2.7.0";
5891
6144
  // ../../packages/api-client/src/index.ts
5892
6145
  /**
5893
6146
  * The proposer's note travels as a header, not a body field: an unprotected
@@ -7052,13 +7305,13 @@ const CLI_CLIENT = `cli/${version}`;
7052
7305
  * bearer of nothing: a 401 where the honest answer is "you have no
7053
7306
  * credentials", pointing at the API instead of at the missing variable.
7054
7307
  */
7055
- function present(value) {
7308
+ function present$1(value) {
7056
7309
  const trimmed = value?.trim();
7057
7310
  return trimmed ? trimmed : void 0;
7058
7311
  }
7059
7312
  function tryBuildContext(dotenvVars = {}) {
7060
7313
  const config = readGlobalConfig();
7061
- const fromEnv = (key) => present(process.env[key]) ?? present(dotenvVars[key]);
7314
+ const fromEnv = (key) => present$1(process.env[key]) ?? present$1(dotenvVars[key]);
7062
7315
  const apiUrl = fromEnv("SEEKRIT_API_URL") ?? config.apiUrl ?? "https://api.seekrit.dev";
7063
7316
  const token = fromEnv("SEEKRIT_TOKEN") ?? config.token ?? config.sessionToken;
7064
7317
  const devUser = fromEnv("SEEKRIT_DEV_USER") ?? config.devUser;
@@ -7103,7 +7356,7 @@ function describeError(err) {
7103
7356
  if (!(err instanceof Error)) return String(err);
7104
7357
  if (err.message !== "fetch failed") return err.message;
7105
7358
  const config = readGlobalConfig();
7106
- const apiUrl = present(process.env.SEEKRIT_API_URL) ?? config.apiUrl ?? "https://api.seekrit.dev";
7359
+ const apiUrl = present$1(process.env.SEEKRIT_API_URL) ?? config.apiUrl ?? "https://api.seekrit.dev";
7107
7360
  const cause = err.cause;
7108
7361
  const reason = cause instanceof Error ? cause.code ?? cause.message : void 0;
7109
7362
  return `cannot reach the seekrit API at ${apiUrl}${reason ? ` (${reason})` : ""} — check SEEKRIT_API_URL, your network, and that the API is up`;
@@ -7658,7 +7911,7 @@ function defaultIsAlive(pid) {
7658
7911
  }
7659
7912
  }
7660
7913
  /** Write a file so a reader sees the old bytes or the new ones, never half of each. */
7661
- function writeAtomic(path, content) {
7914
+ function writeAtomic$1(path, content) {
7662
7915
  mkdirSync(dirname(path), {
7663
7916
  recursive: true,
7664
7917
  mode: 448
@@ -7725,7 +7978,7 @@ var AgentLoginSession = class {
7725
7978
  await this.recoverLeftover();
7726
7979
  await this.acquire();
7727
7980
  this.registerHolder();
7728
- writeAtomic(this.o.path, this.synced);
7981
+ writeAtomic$1(this.o.path, this.synced);
7729
7982
  this.placed = true;
7730
7983
  this.lastRemotePoll = this.o.now();
7731
7984
  this.timer = setInterval(() => void this.tick(), this.o.localPollMs);
@@ -7899,7 +8152,7 @@ var AgentLoginSession = class {
7899
8152
  this.version = snapshot.version;
7900
8153
  continue;
7901
8154
  }
7902
- writeAtomic(this.o.path, remote.content);
8155
+ writeAtomic$1(this.o.path, remote.content);
7903
8156
  this.adopt(snapshot, remote);
7904
8157
  this.o.log(`another sandbox refreshed the ${this.o.adapter.label} login at the same moment; switched to its copy. If ${this.o.adapter.label} reports a sign-in error, run \`seekrit agent-login ${this.o.adapter.id}\` again.`);
7905
8158
  return;
@@ -7925,7 +8178,7 @@ var AgentLoginSession = class {
7925
8178
  const local = readIfExists(this.o.path);
7926
8179
  if (local !== null && local !== this.synced) return;
7927
8180
  if (remote.content !== this.synced && !this.fresher(this.synced, remote.content)) {
7928
- writeAtomic(this.o.path, remote.content);
8181
+ writeAtomic$1(this.o.path, remote.content);
7929
8182
  this.o.log(`picked up a ${this.o.adapter.label} login another sandbox refreshed`);
7930
8183
  }
7931
8184
  if (remote.claim?.holder !== this.o.holder) this.claimUntil = null;
@@ -7976,7 +8229,7 @@ var AgentLoginSession = class {
7976
8229
  secret: this.o.secretName,
7977
8230
  holders
7978
8231
  };
7979
- writeAtomic(this.markerPath, `${JSON.stringify(marker, null, 2)}\n`);
8232
+ writeAtomic$1(this.markerPath, `${JSON.stringify(marker, null, 2)}\n`);
7980
8233
  }
7981
8234
  /** Several runs on one machine can share a home; the last one out cleans up. */
7982
8235
  registerHolder() {
@@ -9560,7 +9813,7 @@ async function syncGrantsForGroupLink(ctx, orgId, envId, envSlug, groupId) {
9560
9813
  }
9561
9814
  // src/kms.ts
9562
9815
  /** Collect a repeatable option into a list. */
9563
- function collect$9(value, acc = []) {
9816
+ function collect$10(value, acc = []) {
9564
9817
  acc.push(value);
9565
9818
  return acc;
9566
9819
  }
@@ -9628,7 +9881,7 @@ async function kmsRecoverMaterial(ctx, orgId, keyId, version) {
9628
9881
  }
9629
9882
  function registerKmsCommands(program) {
9630
9883
  const kms = program.command("kms").description("managed keys for application-layer encryption & signing (client-side)");
9631
- kms.command("create").description("create a managed key (material is generated locally and wrapped, never sent)").requiredOption("--name <name>", "org-unique key name").requiredOption("--purpose <purpose>", "encrypt | sign").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--app <slug>", "scope the key to an application").option("--group <slug>", "scope the key to a group").option("--grant-user <email>", "also grant an org member (repeatable)", collect$9, []).option("--grant-token <tokenId>", "also grant a service token (repeatable)", collect$9, []).action(async (options) => {
9884
+ kms.command("create").description("create a managed key (material is generated locally and wrapped, never sent)").requiredOption("--name <name>", "org-unique key name").requiredOption("--purpose <purpose>", "encrypt | sign").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--app <slug>", "scope the key to an application").option("--group <slug>", "scope the key to a group").option("--grant-user <email>", "also grant an org member (repeatable)", collect$10, []).option("--grant-token <tokenId>", "also grant a service token (repeatable)", collect$10, []).action(async (options) => {
9632
9885
  if (options.purpose !== "encrypt" && options.purpose !== "sign") fail("--purpose must be encrypt or sign");
9633
9886
  if (options.app && options.group) fail("pass at most one of --app or --group");
9634
9887
  const ctx = buildContext();
@@ -9849,7 +10102,7 @@ function registerKmsCommands(program) {
9849
10102
  }
9850
10103
  // src/recovery.ts
9851
10104
  /** Collect a repeatable option into a list. */
9852
- function collect$8(value, acc = []) {
10105
+ function collect$9(value, acc = []) {
9853
10106
  acc.push(value);
9854
10107
  return acc;
9855
10108
  }
@@ -9946,7 +10199,7 @@ function registerRecoveryCommands(program) {
9946
10199
  for (const cst of status.custodians) console.log(` - ${cst.label ?? cst.principalId} (${cst.principalType}, share #${cst.shareIndex})`);
9947
10200
  if (status.coverage.unprotectedEnvIds.length > 0) console.log(`${status.coverage.unprotectedEnvIds.length} environment(s) not yet protected — run \`seekrit recovery sync\``);
9948
10201
  });
9949
- recovery.command("setup").description("enable recovery: split a fresh recovery key across custodians").requiredOption("--threshold <M>", "custodians required to recover (M in M-of-N)").option("--custodian <email|skt_id>", "a recovery custodian (repeatable)", collect$8, []).option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (options) => {
10202
+ recovery.command("setup").description("enable recovery: split a fresh recovery key across custodians").requiredOption("--threshold <M>", "custodians required to recover (M in M-of-N)").option("--custodian <email|skt_id>", "a recovery custodian (repeatable)", collect$9, []).option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (options) => {
9950
10203
  const ctx = buildContext();
9951
10204
  const org = await resolveOrg(ctx, options.org);
9952
10205
  const config = await buildRecoveryConfig(ctx, org.id, options.threshold, options.custodian);
@@ -9964,7 +10217,7 @@ function registerRecoveryCommands(program) {
9964
10217
  const { wrapped, skipped } = await syncRecoveryGrants(ctx, (await resolveOrg(ctx, options.org)).id);
9965
10218
  console.error(`recovery-protected ${wrapped} environment(s); skipped ${skipped} you cannot decrypt`);
9966
10219
  });
9967
- recovery.command("rotate").description("rotate the recovery key (new keypair, custodians, and env re-wraps)").requiredOption("--threshold <M>", "custodians required to recover (M in M-of-N)").option("--custodian <email|skt_id>", "a recovery custodian (repeatable)", collect$8, []).option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (options) => {
10220
+ recovery.command("rotate").description("rotate the recovery key (new keypair, custodians, and env re-wraps)").requiredOption("--threshold <M>", "custodians required to recover (M in M-of-N)").option("--custodian <email|skt_id>", "a recovery custodian (repeatable)", collect$9, []).option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (options) => {
9968
10221
  const ctx = buildContext();
9969
10222
  const org = await resolveOrg(ctx, options.org);
9970
10223
  const config = await buildRecoveryConfig(ctx, org.id, options.threshold, options.custodian);
@@ -11103,7 +11356,7 @@ function formatSecrets(values, format) {
11103
11356
  * `buildContext()` in any of them silently breaks the promise the feature makes.
11104
11357
  */
11105
11358
  /** Collect a repeatable option into a list. */
11106
- function collect$7(value, acc = []) {
11359
+ function collect$8(value, acc = []) {
11107
11360
  acc.push(value);
11108
11361
  return acc;
11109
11362
  }
@@ -11380,7 +11633,7 @@ function registerArchiveCommands(program) {
11380
11633
  } catch {}
11381
11634
  fail("none of the recovery shares in this archive unwrap with that key");
11382
11635
  });
11383
- archive.command("decrypt <file>").description("decrypt an archive's secrets with your own key (offline)").option("-o, --out <dir>", "write one file per environment into this directory").option("--stdout", "print plaintext to stdout instead of writing files").option("--env <label>", "only this environment (app/env, group@env, slug, or id)").option("--format <format>", "dotenv | json | shell", "dotenv").option("--token <skt_…>", "decrypt as a service token instead of a passphrase").option("--key-file <path>", "decrypt with a private key JWK file").option("--share <file>", "custodian share for an offline quorum (repeatable)", collect$7).option("-y, --yes", "skip the confirmation when printing plaintext to stdout").action(async (file, options) => {
11636
+ archive.command("decrypt <file>").description("decrypt an archive's secrets with your own key (offline)").option("-o, --out <dir>", "write one file per environment into this directory").option("--stdout", "print plaintext to stdout instead of writing files").option("--env <label>", "only this environment (app/env, group@env, slug, or id)").option("--format <format>", "dotenv | json | shell", "dotenv").option("--token <skt_…>", "decrypt as a service token instead of a passphrase").option("--key-file <path>", "decrypt with a private key JWK file").option("--share <file>", "custodian share for an offline quorum (repeatable)", collect$8).option("-y, --yes", "skip the confirmation when printing plaintext to stdout").action(async (file, options) => {
11384
11637
  if (!options.out && !options.stdout) fail("choose a destination: --out <dir> to write files, or --stdout to print plaintext");
11385
11638
  if (![
11386
11639
  "dotenv",
@@ -12612,6 +12865,81 @@ function registerDoctorCommand(program) {
12612
12865
  if (checks.some((c) => c.status === "fail")) process.exitCode = 1;
12613
12866
  });
12614
12867
  }
12868
+ // src/dynamic.ts
12869
+ function dynamicTtl(value) {
12870
+ const match = /^(\d+)([smhd]?)$/.exec(value);
12871
+ if (!match) throw new Error("invalid TTL (use 15m, 1h, or 1d)");
12872
+ const seconds = Number(match[1]) * ({
12873
+ s: 1,
12874
+ m: 60,
12875
+ h: 3600,
12876
+ d: 86400
12877
+ }[match[2] || "s"] ?? 1);
12878
+ if (!Number.isSafeInteger(seconds) || seconds < 60 || seconds > 604800) throw new Error("TTL must be 1 minute–7 days");
12879
+ return seconds;
12880
+ }
12881
+ function registerDynamicCommands(program) {
12882
+ const dynamic = program.command("dynamic").description("manage provider-issued temporary credentials");
12883
+ const targets = dynamic.command("target").description("manage dynamic credential targets");
12884
+ targets.command("add").requiredOption("--name <name>", "target name").requiredOption("--config <file>", "non-secret provider configuration JSON").option("--org <slug>", "organization").description("register a target; read its admin credential from stdin and encrypt it locally").action(async (options) => {
12885
+ const config = managedTargetConfigSchema.parse(JSON.parse(readFileSync(options.config, "utf8")));
12886
+ if (process.stdin.isTTY) fail("pipe the admin credential on stdin");
12887
+ const secret = (await readStdin()).trim();
12888
+ if (!secret) fail("admin credential is empty");
12889
+ const ctx = buildContext();
12890
+ const org = await resolveOrg(ctx, options.org);
12891
+ const { publicKeyJwk } = await ctx.client.getLeaseBrokerKey(org.id);
12892
+ const wrappedAdminSecret = await wrapDek(new TextEncoder().encode(secret), publicKeyJwk);
12893
+ const { target } = await ctx.client.registerLeaseTarget(org.id, {
12894
+ name: options.name,
12895
+ config,
12896
+ wrappedAdminSecret
12897
+ });
12898
+ console.log(JSON.stringify(target));
12899
+ });
12900
+ targets.command("list").option("--org <slug>", "organization").action(async (options) => {
12901
+ const ctx = buildContext();
12902
+ const org = await resolveOrg(ctx, options.org);
12903
+ const { targets } = await ctx.client.listLeaseTargets(org.id);
12904
+ console.log(JSON.stringify(targets.filter((target) => isManagedTarget(target))));
12905
+ });
12906
+ dynamic.command("lease <target>").option("--ttl <duration>", "credential lifetime", "1h").option("--org <slug>", "organization").description("mint and decrypt a credential locally; outputs JSON once").action(async (reference, options) => {
12907
+ const ttlSeconds = dynamicTtl(options.ttl);
12908
+ const ctx = buildContext();
12909
+ const org = await resolveOrg(ctx, options.org);
12910
+ const { targets } = await ctx.client.listLeaseTargets(org.id);
12911
+ const matches = targets.filter((target) => target.id === reference || target.name === reference);
12912
+ if (matches.length !== 1) fail("target must identify exactly one registered target");
12913
+ const target = matches[0];
12914
+ if (!target) fail("target not found");
12915
+ const config = managedTargetConfigSchema.parse(target.config);
12916
+ const recipient = await generateCredentialRecipientKeyPair();
12917
+ const result = await ctx.client.mintLease(org.id, {
12918
+ provider: config.provider,
12919
+ targetId: target.id,
12920
+ recipientPublicKey: recipient.publicKeyJwk,
12921
+ ttlSeconds
12922
+ });
12923
+ try {
12924
+ const credential = await unwrapManagedCredential(result.credential.wrappedCredential, recipient.privateKeyJwk);
12925
+ console.log(JSON.stringify({
12926
+ leaseId: result.lease.id,
12927
+ expiresAt: result.credential.expiresAt,
12928
+ credential
12929
+ }));
12930
+ } catch (error) {
12931
+ await ctx.client.revokeLease(org.id, result.lease.id);
12932
+ throw error;
12933
+ }
12934
+ });
12935
+ dynamic.command("revoke <leaseId>").option("--org <slug>", "organization").option("-y, --yes", "skip the confirmation prompt").description("revoke a temporary credential now").action(async (leaseId, options) => {
12936
+ await confirmDestructive(options.yes, `Revoke temporary credential ${leaseId}?`);
12937
+ const ctx = buildContext();
12938
+ const org = await resolveOrg(ctx, options.org);
12939
+ await ctx.client.revokeLease(org.id, leaseId);
12940
+ console.log(JSON.stringify({ revoked: leaseId }));
12941
+ });
12942
+ }
12615
12943
  // src/gcp.ts
12616
12944
  /**
12617
12945
  * `seekrit gcp` — temporary GCP credentials via IAM Credentials
@@ -13123,134 +13451,772 @@ function registerHoneyTokenCommands(program) {
13123
13451
  console.error(`${honeyTokenId} deleted`);
13124
13452
  });
13125
13453
  }
13126
- // src/m2m.ts
13127
- /**
13128
- * Resolve M2M client credentials from (in order) the process environment, a
13129
- * `.env` overlay (for `seekrit run`), then saved config. Both halves must come
13130
- * through for the credential to be usable.
13131
- */
13132
- function readM2mCreds(dotenvVars = {}) {
13133
- const config = readGlobalConfig();
13134
- const fromEnv = (key) => process.env[key] ?? dotenvVars[key];
13135
- const clientId = fromEnv("SEEKRIT_CLIENT_ID") ?? config.clientId;
13136
- const clientSecret = fromEnv("SEEKRIT_CLIENT_SECRET") ?? config.clientSecret;
13137
- if (!clientId || !clientSecret) return null;
13138
- return {
13139
- clientId,
13140
- clientSecret
13454
+ // src/run-command.ts
13455
+ /** Keep signal handlers installed from provisioning through asynchronous cleanup. */
13456
+ async function runCommand(cmd, args, prepare, cleanup) {
13457
+ let child;
13458
+ let forwarded;
13459
+ let result = { code: 1 };
13460
+ const stragglers = /* @__PURE__ */ new Set();
13461
+ const collect = () => {
13462
+ if (process.platform === "win32" || !child?.pid) return;
13463
+ for (const pid of teardownTargets(child.pid)) stragglers.add(pid);
13141
13464
  };
13142
- }
13143
- /**
13144
- * True when a service/session/dev credential is already configured explicitly.
13145
- * A browser-authorized session counts: a human who ran `seekrit login` must not
13146
- * be silently swapped onto a machine identity.
13147
- */
13148
- function hasExplicitCredential(dotenvVars) {
13149
- const fromEnv = (key) => process.env[key] ?? dotenvVars[key];
13150
- if (fromEnv("SEEKRIT_TOKEN") || fromEnv("SEEKRIT_DEV_USER")) return true;
13151
- const config = readGlobalConfig();
13152
- return Boolean(config.token || config.sessionToken || config.devUser);
13153
- }
13154
- /** Mint a fresh org-scoped admin token using M2M credentials (keyless). */
13155
- async function mintAdminToken(apiUrl, creds) {
13156
- const client = new SeekritClient({
13157
- baseUrl: apiUrl,
13158
- auth: {
13159
- type: "m2m",
13160
- clientId: creds.clientId,
13161
- clientSecret: creds.clientSecret
13162
- },
13163
- client: `cli/${version}`
13164
- });
13165
- const { orgs } = await client.listOrgs();
13166
- const org = orgs[0];
13167
- if (!org) throw new Error("machine client has no organization — sign up first (POST /signup)");
13168
- const created = await createServiceToken();
13169
- await client.createToken(org.id, {
13170
- name: "agent-admin (auto)",
13171
- tokenId: created.tokenId,
13172
- tokenHash: created.tokenHash,
13173
- publicKeyJwk: created.publicKeyJwk,
13174
- role: "admin",
13175
- environmentId: null
13176
- });
13177
- return created.token;
13178
- }
13179
- /**
13180
- * If M2M credentials are configured (and no explicit token/dev-user is), ensure
13181
- * an admin token exists for them — minting and caching one on first use — and
13182
- * expose it as `SEEKRIT_TOKEN` so the normal credential resolution
13183
- * ({@link tryBuildContext}) picks it up. A no-op (returns null) when there is
13184
- * nothing to bootstrap. Throws only when credentials ARE present but minting
13185
- * fails, so the reason surfaces instead of a later opaque "no credentials".
13186
- */
13187
- async function ensureM2mAdminToken(dotenvVars = {}) {
13188
- if (hasExplicitCredential(dotenvVars)) return null;
13189
- const creds = readM2mCreds(dotenvVars);
13190
- if (!creds) return null;
13191
- const cached = readCachedM2mToken(creds.clientId);
13192
- if (cached) {
13193
- let usable = false;
13194
- try {
13195
- serviceTokenAuth(cached);
13196
- usable = true;
13465
+ const forward = (signal) => {
13466
+ forwarded ??= signal;
13467
+ if (!child || child.exitCode !== null || child.signalCode !== null) return;
13468
+ collect();
13469
+ child.kill(signal);
13470
+ for (const pid of stragglers) try {
13471
+ process.kill(pid, signal);
13197
13472
  } catch {}
13198
- if (usable) {
13199
- process.env.SEEKRIT_TOKEN = cached;
13200
- return cached;
13473
+ };
13474
+ const signals = [
13475
+ "SIGINT",
13476
+ "SIGTERM",
13477
+ "SIGHUP",
13478
+ "SIGQUIT"
13479
+ ];
13480
+ for (const signal of signals) process.on(signal, forward);
13481
+ try {
13482
+ const env = await prepare(() => forwarded !== void 0);
13483
+ if (!forwarded) {
13484
+ const running = spawn(cmd, args, {
13485
+ stdio: "inherit",
13486
+ env
13487
+ });
13488
+ child = running;
13489
+ result = await new Promise((resolve, reject) => {
13490
+ running.once("exit", (code, signal) => resolve({
13491
+ code: code ?? 1,
13492
+ signal: signal ?? void 0
13493
+ }));
13494
+ running.once("error", (err) => reject(/* @__PURE__ */ new Error(`failed to start ${cmd}: ${err.message}`)));
13495
+ });
13201
13496
  }
13202
- }
13203
- const token = await mintAdminToken(process.env.SEEKRIT_API_URL ?? dotenvVars.SEEKRIT_API_URL ?? readGlobalConfig().apiUrl ?? "https://api.seekrit.dev", creds);
13204
- cacheM2mToken(creds.clientId, token);
13205
- process.env.SEEKRIT_TOKEN = token;
13206
- return token;
13207
- }
13208
- /** Lowercase, hyphenated, at most 40 characters — what `slugSchema` accepts. */
13209
- function slugify(name) {
13210
- return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40).replace(/-+$/g, "") || "workspace";
13211
- }
13212
- /** `acme-storefront` → `Acme Storefront`: a slug-ish name as a human reads it. */
13213
- function titleCase(name) {
13214
- return name.split(/[^A-Za-z0-9]+/).filter(Boolean).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
13215
- }
13216
- /**
13217
- * The project's name, from whichever manifest the directory carries — the
13218
- * package name without its npm scope, the Python or Rust package name, the last
13219
- * segment of a Go module path — falling back to the directory's own name. The
13220
- * manifests are read leniently (a regex, not a parser) because a malformed one
13221
- * should cost the default, not the command.
13222
- */
13223
- function detectProjectName(dir = process.cwd()) {
13224
- const read = (file) => {
13225
- const path = join(dir, file);
13226
- if (!existsSync(path)) return null;
13497
+ } finally {
13227
13498
  try {
13228
- return readFileSync(path, "utf8");
13229
- } catch {
13230
- return null;
13499
+ if (forwarded) {
13500
+ collect();
13501
+ await reapStragglers(stragglers, forwarded);
13502
+ }
13503
+ } finally {
13504
+ try {
13505
+ if (!await cleanup() && result.code === 0) result.code = 1;
13506
+ } finally {
13507
+ for (const signal of signals) process.off(signal, forward);
13508
+ }
13231
13509
  }
13232
- };
13233
- const pkg = read("package.json");
13234
- if (pkg) try {
13235
- const name = JSON.parse(pkg).name;
13236
- if (typeof name === "string" && name.trim()) return name.replace(/^@[^/]+\//, "");
13237
- } catch {}
13238
- const pyName = read("pyproject.toml")?.match(/^\[project\][^[]*?^name\s*=\s*"([^"]+)"/ms)?.[1];
13239
- if (pyName) return pyName;
13240
- const cargoName = read("Cargo.toml")?.match(/^\[package\][^[]*?^name\s*=\s*"([^"]+)"/ms)?.[1];
13241
- if (cargoName) return cargoName;
13242
- const goModule = read("go.mod")?.match(/^module\s+(\S+)/m)?.[1];
13243
- if (goModule) return goModule.split("/").pop() ?? goModule;
13244
- return basename(dir);
13510
+ }
13511
+ if (!child && forwarded) result.signal = forwarded;
13512
+ return result;
13245
13513
  }
13246
13514
  /**
13247
- * What `init` would sign up as, from the flags and the directory. Pure, so the
13248
- * naming rules are testable without a terminal or an API.
13249
- */
13250
- function planWorkspace(options, project) {
13251
- const orgName = options.orgName?.trim() || titleCase(project);
13252
- const orgSlug = options.org ?? slugify(options.orgName?.trim() || project);
13253
- if (!slugSchema.safeParse(orgSlug).success) fail(`"${orgSlug}" is not a valid org slug (lowercase letters, numbers, and hyphens) — pass --org <slug>`);
13515
+ * Every live process `seekrit run` is responsible for tearing down, from a
13516
+ * single `ps(1)` snapshot: each descendant of `root`, plus — when we lead our
13517
+ * own process group — every other member of that group.
13518
+ *
13519
+ * Two mechanisms, because each covers the other's blind spot:
13520
+ *
13521
+ * - The parent-chain walk reaches a process that left our group via
13522
+ * setsid(2)/setpgid(2), which no group-wide kill and no tty-generated signal
13523
+ * can touch. But it loses anything whose chain up to `root` has already
13524
+ * broken — teardown kills the middle layers first, and an orphan reparents to
13525
+ * init, out of reach of any walk down from `root`.
13526
+ * - Group membership survives exactly that: a pgid outlives the parent that
13527
+ * passed it down. But it misses the ones that left the group.
13528
+ *
13529
+ * The group half applies only when our pid *is* our pgid, which is the shell-job
13530
+ * case: the shell put this command in a new group, so every other member of it
13531
+ * descends from us. Nested inside a shell script or a CI runner we are not the
13532
+ * leader and the group holds processes we did not start, so there we use the
13533
+ * walk alone.
13534
+ *
13535
+ * Zombies are skipped: they are already dead and waiting to be reaped, so
13536
+ * counting them would stall teardown for the full grace period and then report
13537
+ * a kill that did nothing. Returns nothing if `ps` is unavailable; callers fall
13538
+ * back to signalling the immediate child.
13539
+ */
13540
+ function teardownTargets(root) {
13541
+ const ps = spawnSync("ps", [
13542
+ "-A",
13543
+ "-o",
13544
+ "pid=,ppid=,pgid=,stat="
13545
+ ], { encoding: "utf8" });
13546
+ if (ps.status !== 0 || typeof ps.stdout !== "string") return [];
13547
+ const childrenOf = /* @__PURE__ */ new Map();
13548
+ const groupOf = /* @__PURE__ */ new Map();
13549
+ const isId = (value) => value !== void 0 && Number.isInteger(value);
13550
+ for (const line of ps.stdout.split("\n")) {
13551
+ const [pid, ppid, pgid, stat] = line.trim().split(/\s+/, 4);
13552
+ const [id, parent, group] = [
13553
+ pid,
13554
+ ppid,
13555
+ pgid
13556
+ ].map(Number);
13557
+ if (!isId(id) || !isId(parent) || !isId(group)) continue;
13558
+ if (stat?.startsWith("Z")) continue;
13559
+ const siblings = childrenOf.get(parent);
13560
+ if (siblings) siblings.push(id);
13561
+ else childrenOf.set(parent, [id]);
13562
+ groupOf.set(id, group);
13563
+ }
13564
+ const found = /* @__PURE__ */ new Set();
13565
+ const queue = [root];
13566
+ const seen = new Set(queue);
13567
+ for (let pid = queue.shift(); pid !== void 0; pid = queue.shift()) for (const kid of childrenOf.get(pid) ?? []) {
13568
+ if (seen.has(kid)) continue;
13569
+ seen.add(kid);
13570
+ found.add(kid);
13571
+ queue.push(kid);
13572
+ }
13573
+ if (groupOf.get(process.pid) === process.pid) {
13574
+ for (const [pid, group] of groupOf) if (group === process.pid) found.add(pid);
13575
+ }
13576
+ found.delete(process.pid);
13577
+ found.delete(root);
13578
+ return [...found];
13579
+ }
13580
+ /** Whether `pid` still exists — signal 0 tests reachability, delivers nothing. */
13581
+ function isAlive(pid) {
13582
+ try {
13583
+ process.kill(pid, 0);
13584
+ return true;
13585
+ } catch {
13586
+ return false;
13587
+ }
13588
+ }
13589
+ /** How long a straggler gets to finish shutting down before SIGKILL. */
13590
+ const STRAGGLER_GRACE_MS = 2e3;
13591
+ /**
13592
+ * Once the command has exited, make sure nothing it started outlives us.
13593
+ *
13594
+ * Anything still alive here has ignored the signal we forwarded *and* lost the
13595
+ * parent that launched it, and we are the last process that knows its pid:
13596
+ * the tty won't hang it up (it is no longer in the foreground group, and the
13597
+ * shell has moved on), so it survives until the machine reboots. That is how
13598
+ * `tsx` and the server under it stacked up for days.
13599
+ *
13600
+ * So escalate rather than trust. SIGTERM first — it costs no extra time and is
13601
+ * a rung the SIGINT-only handlers common in dev servers don't catch — then
13602
+ * SIGKILL whatever is left after the grace period. Nothing is killed unless it
13603
+ * was asked to stop first and declined, and this runs only when we forwarded a
13604
+ * termination signal: a command that exits on its own having deliberately left a
13605
+ * daemon behind keeps working.
13606
+ */
13607
+ async function reapStragglers(pids, signal) {
13608
+ let live = [...pids].filter(isAlive);
13609
+ if (live.length === 0) return;
13610
+ for (const pid of live) try {
13611
+ process.kill(pid, "SIGTERM");
13612
+ } catch {}
13613
+ const deadline = Date.now() + STRAGGLER_GRACE_MS;
13614
+ while (live.length > 0 && Date.now() < deadline) {
13615
+ await new Promise((resolve) => setTimeout(resolve, 50));
13616
+ live = live.filter(isAlive);
13617
+ }
13618
+ if (live.length === 0) return;
13619
+ console.error(`seekrit: force-killed ${live.length} leftover process(es) that ignored ${signal} and SIGTERM (${live.join(", ")})`);
13620
+ for (const pid of live) try {
13621
+ process.kill(pid, "SIGKILL");
13622
+ } catch {}
13623
+ }
13624
+ // src/identity.ts
13625
+ /**
13626
+ * `seekrit identity` — keyless access to AWS, Google Cloud, OpenAI and Anthropic
13627
+ * from a seekrit workload identity, the way a hosting platform's OIDC
13628
+ * integration works.
13629
+ *
13630
+ * The workload authenticates to seekrit (an enrolled P-256 key, or a platform
13631
+ * JWT it already has), asks for a short-lived identity token addressed to each
13632
+ * provider, and writes it to the token file that provider's own SDK already
13633
+ * knows how to read. The provider verifies the token against the org's issuer
13634
+ * (`https://oidc.seekrit.dev/<orgId>`) and its own trust policy, and mints its own short-lived
13635
+ * credential. No provider key is stored anywhere — not here, not in seekrit.
13636
+ *
13637
+ * Identity, not secrets: nothing on this path decrypts anything, and the API
13638
+ * signs these tokens with its own issuer key, so the zero-knowledge invariant is
13639
+ * untouched.
13640
+ */
13641
+ const DEFAULT_ISSUER = "https://api.seekrit.dev";
13642
+ const CLIENT_ASSERTION_TYPE = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer";
13643
+ const TOKEN_EXCHANGE_GRANT = "urn:ietf:params:oauth:grant-type:token-exchange";
13644
+ const JWT_TOKEN_TYPE = "urn:ietf:params:oauth:token-type:jwt";
13645
+ function present(value) {
13646
+ return value?.trim() ? value.trim() : void 0;
13647
+ }
13648
+ function httpsOrigin(value, what) {
13649
+ let url;
13650
+ try {
13651
+ url = new URL(value);
13652
+ } catch {
13653
+ throw new Error(`${what} must be an HTTPS origin, got "${value}"`);
13654
+ }
13655
+ if (url.protocol !== "https:" || url.username || url.password || url.search || url.hash) throw new Error(`${what} must be an HTTPS origin, got "${value}"`);
13656
+ return url.origin;
13657
+ }
13658
+ /**
13659
+ * Where the workload's credential comes from: the file the dashboard downloads
13660
+ * at enrollment (`SEEKRIT_WORKLOAD_FILE`), or — for a platform-federated
13661
+ * workload — its id plus the platform token's path.
13662
+ */
13663
+ function loadWorkloadCredentials(opts, env = process.env) {
13664
+ const file = present(opts.workloadFile) ?? present(env.SEEKRIT_WORKLOAD_FILE);
13665
+ let fromFile = {};
13666
+ if (file) {
13667
+ let parsed;
13668
+ try {
13669
+ parsed = JSON.parse(readFileSync(file, "utf8"));
13670
+ } catch (err) {
13671
+ throw new Error(`cannot read workload credentials from ${file}: ${err instanceof Error ? err.message : String(err)}`);
13672
+ }
13673
+ if (!parsed || typeof parsed !== "object") throw new Error(`${file} is not a workload credential file`);
13674
+ fromFile = parsed;
13675
+ }
13676
+ const workloadId = present(opts.workloadId) ?? present(fromFile.workloadId) ?? present(env.SEEKRIT_WORKLOAD_ID);
13677
+ if (!workloadId) throw new Error("no workload identity: set SEEKRIT_WORKLOAD_FILE (or --workload-file) to the credentials downloaded at enrollment, or --workload-id with --platform-token-file");
13678
+ if (!/^wli_[A-Za-z0-9_-]{1,128}$/.test(workloadId)) throw new Error(`"${workloadId}" is not a workload id (expected wli_…)`);
13679
+ const issuer = httpsOrigin(present(opts.issuer) ?? present(fromFile.issuer) ?? present(env.SEEKRIT_ISSUER) ?? DEFAULT_ISSUER, "the seekrit issuer");
13680
+ const platformTokenFile = present(opts.platformTokenFile) ?? present(fromFile.platformTokenFile) ?? present(env.SEEKRIT_PLATFORM_TOKEN_FILE);
13681
+ const signingKey = fromFile.signingKey;
13682
+ if (!!signingKey === !!platformTokenFile) throw new Error(signingKey ? "the workload file holds an enrollment key; do not also pass a platform token" : "this workload needs an enrollment key (in its credential file) or --platform-token-file");
13683
+ if (signingKey && (signingKey.kty !== "EC" || signingKey.crv !== "P-256" || !signingKey.d || !signingKey.x)) throw new Error("the workload file's signingKey is not a private P-256 key");
13684
+ return {
13685
+ workloadId,
13686
+ issuer,
13687
+ signingKey,
13688
+ platformTokenFile
13689
+ };
13690
+ }
13691
+ function base64url(bytes) {
13692
+ return Buffer.from(bytes).toString("base64url");
13693
+ }
13694
+ /** A one-use, 60-second ES256 client assertion, the shape `/oauth/token` verifies. */
13695
+ async function signClientAssertion(creds, key, nowSeconds) {
13696
+ const unsigned = `${base64url(new TextEncoder().encode(JSON.stringify({
13697
+ alg: "ES256",
13698
+ typ: "JWT"
13699
+ })))}.${base64url(new TextEncoder().encode(JSON.stringify({
13700
+ iss: creds.workloadId,
13701
+ sub: creds.workloadId,
13702
+ aud: `${creds.issuer}/oauth/token`,
13703
+ iat: nowSeconds,
13704
+ exp: nowSeconds + 60,
13705
+ jti: crypto.randomUUID()
13706
+ })))}`;
13707
+ const signature = await crypto.subtle.sign({
13708
+ name: "ECDSA",
13709
+ hash: "SHA-256"
13710
+ }, key, new TextEncoder().encode(unsigned));
13711
+ return `${unsigned}.${base64url(new Uint8Array(signature))}`;
13712
+ }
13713
+ async function errorText(response) {
13714
+ try {
13715
+ const body = await response.json();
13716
+ if (body.error_description) return body.error_description;
13717
+ if (typeof body.error === "object" && body.error?.message) return body.error.message;
13718
+ if (typeof body.error === "string") return body.error;
13719
+ } catch {}
13720
+ return `HTTP ${response.status}`;
13721
+ }
13722
+ /** Session exchange + identity-token requests against one seekrit deployment. */
13723
+ var WorkloadClient = class {
13724
+ creds;
13725
+ fetcher;
13726
+ now;
13727
+ session;
13728
+ key;
13729
+ constructor(creds, fetcher = (input, init) => fetch(input, init), now = Date.now) {
13730
+ this.creds = creds;
13731
+ this.fetcher = fetcher;
13732
+ this.now = now;
13733
+ }
13734
+ signingKey() {
13735
+ this.key ??= crypto.subtle.importKey("jwk", this.creds.signingKey, {
13736
+ name: "ECDSA",
13737
+ namedCurve: "P-256"
13738
+ }, false, ["sign"]);
13739
+ return this.key;
13740
+ }
13741
+ async exchange() {
13742
+ const form = new URLSearchParams({
13743
+ client_id: this.creds.workloadId,
13744
+ scope: "connect"
13745
+ });
13746
+ if (this.creds.platformTokenFile) {
13747
+ const platformToken = readFileSync(this.creds.platformTokenFile, "utf8").trim();
13748
+ form.set("grant_type", TOKEN_EXCHANGE_GRANT);
13749
+ form.set("subject_token_type", JWT_TOKEN_TYPE);
13750
+ form.set("subject_token", platformToken);
13751
+ } else {
13752
+ form.set("grant_type", "client_credentials");
13753
+ form.set("client_assertion_type", CLIENT_ASSERTION_TYPE);
13754
+ form.set("client_assertion", await signClientAssertion(this.creds, await this.signingKey(), Math.floor(this.now() / 1e3)));
13755
+ }
13756
+ const response = await this.fetcher(`${this.creds.issuer}/oauth/token`, {
13757
+ method: "POST",
13758
+ headers: { "content-type": "application/x-www-form-urlencoded" },
13759
+ body: form
13760
+ });
13761
+ if (!response.ok) throw new Error(`workload sign-in failed: ${await errorText(response)}`);
13762
+ const body = await response.json();
13763
+ this.session = {
13764
+ token: body.access_token,
13765
+ expiresAt: this.now() + body.expires_in * 1e3
13766
+ };
13767
+ return body.access_token;
13768
+ }
13769
+ async accessToken() {
13770
+ if (this.session && this.session.expiresAt - 3e4 > this.now()) return this.session.token;
13771
+ return this.exchange();
13772
+ }
13773
+ /** An identity token for one enrolled audience. */
13774
+ async identityToken(audience) {
13775
+ for (let attempt = 0;; attempt++) {
13776
+ const response = await this.fetcher(`${this.creds.issuer}/v1/connect/identity-token`, {
13777
+ method: "POST",
13778
+ headers: {
13779
+ authorization: `Bearer ${await this.accessToken()}`,
13780
+ "content-type": "application/json"
13781
+ },
13782
+ body: JSON.stringify({ audience })
13783
+ });
13784
+ if (response.status === 401 && attempt === 0) {
13785
+ this.session = void 0;
13786
+ continue;
13787
+ }
13788
+ if (!response.ok) throw new Error(`identity token for "${audience}" refused: ${await errorText(response)}`);
13789
+ return await response.json();
13790
+ }
13791
+ }
13792
+ };
13793
+ /** The audience each provider's own docs use; any enrolled audience can override it. */
13794
+ const DEFAULT_AUDIENCES = {
13795
+ aws: "sts.amazonaws.com",
13796
+ openai: "https://api.openai.com/v1",
13797
+ anthropic: "https://api.anthropic.com"
13798
+ };
13799
+ /**
13800
+ * Credentials that outrank web identity in each provider's default chain. An
13801
+ * explicit `--aws`/`--anthropic`/… means "use the federated identity", so a
13802
+ * long-lived key left in the shell must not quietly win — the same rule as
13803
+ * `seekrit run --lease`.
13804
+ */
13805
+ const SHADOWING = {
13806
+ aws: [
13807
+ "AWS_ACCESS_KEY_ID",
13808
+ "AWS_SECRET_ACCESS_KEY",
13809
+ "AWS_SESSION_TOKEN",
13810
+ "AWS_PROFILE"
13811
+ ],
13812
+ gcp: [],
13813
+ openai: ["OPENAI_API_KEY"],
13814
+ anthropic: [
13815
+ "ANTHROPIC_API_KEY",
13816
+ "ANTHROPIC_AUTH_TOKEN",
13817
+ "ANTHROPIC_PROFILE",
13818
+ "ANTHROPIC_IDENTITY_TOKEN"
13819
+ ]
13820
+ };
13821
+ /** `projects/N/locations/global/workloadIdentityPools/P/providers/R`, from any of its spellings. */
13822
+ function normalizeGcpProvider(input) {
13823
+ const resource = input.trim().replace(/^https:\/\/iam\.googleapis\.com\//, "").replace(/^\/\/iam\.googleapis\.com\//, "");
13824
+ if (!/^projects\/\d+\/locations\/global\/workloadIdentityPools\/[a-z0-9-]{4,32}\/providers\/[a-z0-9-]{4,32}$/.test(resource)) throw new Error(`--gcp must name a workload identity pool provider by project number: projects/<number>/locations/global/workloadIdentityPools/<pool>/providers/<provider> (got "${input}")`);
13825
+ return resource;
13826
+ }
13827
+ function parseAudienceOverrides(values = []) {
13828
+ const out = {};
13829
+ for (const value of values) {
13830
+ const at = value.indexOf("=");
13831
+ const id = value.slice(0, at);
13832
+ const audience = value.slice(at + 1).trim();
13833
+ if (at < 1 || ![
13834
+ "aws",
13835
+ "gcp",
13836
+ "openai",
13837
+ "anthropic"
13838
+ ].includes(id) || !audience) throw new Error(`--audience takes provider=audience, e.g. anthropic=api.anthropic.com`);
13839
+ if (out[id]) throw new Error(`--audience given twice for ${id}`);
13840
+ out[id] = audience;
13841
+ }
13842
+ return out;
13843
+ }
13844
+ /**
13845
+ * What to write and export for each requested provider. Pure: paths are inside
13846
+ * `dir`, which the caller creates (mode 0700) and removes.
13847
+ */
13848
+ function planProviders(opts, dir, workloadId, env = process.env) {
13849
+ const audiences = parseAudienceOverrides(opts.audience);
13850
+ const plans = [];
13851
+ if (opts.aws !== void 0) {
13852
+ if (!/^arn:aws[a-z-]*:iam::\d{12}:role\/[\w+=,.@/-]+$/.test(opts.aws.trim())) throw new Error(`--aws must be an IAM role ARN, got "${opts.aws}"`);
13853
+ const tokenFile = join(dir, "aws-token");
13854
+ plans.push({
13855
+ id: "aws",
13856
+ audience: audiences.aws ?? DEFAULT_AUDIENCES.aws,
13857
+ tokenFile,
13858
+ env: {
13859
+ AWS_ROLE_ARN: opts.aws.trim(),
13860
+ AWS_WEB_IDENTITY_TOKEN_FILE: tokenFile,
13861
+ AWS_ROLE_SESSION_NAME: present(env.AWS_ROLE_SESSION_NAME) ?? `seekrit-${workloadId}`.slice(0, 64)
13862
+ },
13863
+ unset: SHADOWING.aws,
13864
+ files: []
13865
+ });
13866
+ }
13867
+ if (opts.gcp !== void 0) {
13868
+ const resource = normalizeGcpProvider(opts.gcp);
13869
+ const tokenFile = join(dir, "gcp-token");
13870
+ const configFile = join(dir, "gcp-credentials.json");
13871
+ const sa = present(opts.gcpServiceAccount);
13872
+ if (sa && !/^[a-z0-9-]+@[a-z0-9.-]+\.gserviceaccount\.com$/.test(sa)) throw new Error(`--gcp-service-account must be a service account email, got "${sa}"`);
13873
+ const config = {
13874
+ type: "external_account",
13875
+ audience: `//iam.googleapis.com/${resource}`,
13876
+ subject_token_type: JWT_TOKEN_TYPE,
13877
+ token_url: "https://sts.googleapis.com/v1/token",
13878
+ credential_source: {
13879
+ file: tokenFile,
13880
+ format: { type: "text" }
13881
+ },
13882
+ ...sa ? { service_account_impersonation_url: `https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/${sa}:generateAccessToken` } : {}
13883
+ };
13884
+ plans.push({
13885
+ id: "gcp",
13886
+ audience: audiences.gcp ?? `https://iam.googleapis.com/${resource}`,
13887
+ tokenFile,
13888
+ env: {
13889
+ GOOGLE_APPLICATION_CREDENTIALS: configFile,
13890
+ CLOUDSDK_AUTH_CREDENTIAL_FILE_OVERRIDE: configFile
13891
+ },
13892
+ unset: SHADOWING.gcp,
13893
+ files: [{
13894
+ path: configFile,
13895
+ content: `${JSON.stringify(config, null, 2)}\n`
13896
+ }]
13897
+ });
13898
+ } else if (opts.gcpServiceAccount) throw new Error("--gcp-service-account needs --gcp");
13899
+ if (opts.openai) {
13900
+ const tokenFile = join(dir, "openai-token");
13901
+ plans.push({
13902
+ id: "openai",
13903
+ audience: audiences.openai ?? DEFAULT_AUDIENCES.openai,
13904
+ tokenFile,
13905
+ env: { OPENAI_IDENTITY_TOKEN_FILE: tokenFile },
13906
+ unset: SHADOWING.openai,
13907
+ files: []
13908
+ });
13909
+ }
13910
+ if (opts.anthropic) {
13911
+ const tokenFile = join(dir, "anthropic-token");
13912
+ plans.push({
13913
+ id: "anthropic",
13914
+ audience: audiences.anthropic ?? DEFAULT_AUDIENCES.anthropic,
13915
+ tokenFile,
13916
+ env: { ANTHROPIC_IDENTITY_TOKEN_FILE: tokenFile },
13917
+ unset: SHADOWING.anthropic,
13918
+ files: []
13919
+ });
13920
+ }
13921
+ for (const id of Object.keys(audiences)) if (!plans.some((p) => p.id === id)) throw new Error(`--audience ${id}=… without --${id}`);
13922
+ if (plans.length === 0) throw new Error("name at least one provider: --aws <role-arn>, --gcp <provider>, --openai, --anthropic");
13923
+ return plans;
13924
+ }
13925
+ /**
13926
+ * The child's environment: shadowing credentials removed, provider variables
13927
+ * set. Returns the names it removed (never values) so the caller can say so.
13928
+ */
13929
+ function childEnvironment(base, plans) {
13930
+ const env = { ...base };
13931
+ const removed = [];
13932
+ for (const plan of plans) for (const name of plan.unset) if (env[name] !== void 0) {
13933
+ delete env[name];
13934
+ removed.push(name);
13935
+ }
13936
+ for (const plan of plans) Object.assign(env, plan.env);
13937
+ return {
13938
+ env,
13939
+ removed
13940
+ };
13941
+ }
13942
+ /** Variables a provider SDK needs from the operator before it will federate at all. */
13943
+ function missingProviderSettings(plans, env) {
13944
+ const missing = [];
13945
+ if (plans.some((p) => p.id === "anthropic")) {
13946
+ for (const name of ["ANTHROPIC_FEDERATION_RULE_ID", "ANTHROPIC_ORGANIZATION_ID"]) if (!present(env[name])) missing.push(name);
13947
+ }
13948
+ return missing;
13949
+ }
13950
+ /** Write-then-rename, so a reader never sees half a token. */
13951
+ function writeAtomic(path, content) {
13952
+ const tmp = `${path}.${crypto.randomUUID()}.tmp`;
13953
+ writeFileSync(tmp, content, { mode: 384 });
13954
+ renameSync(tmp, path);
13955
+ }
13956
+ /**
13957
+ * Keeps each provider's token file current. Refreshes at half the token's
13958
+ * lifetime, so a provider SDK rereading the file always finds a token with
13959
+ * plenty of life left — and, for Anthropic, which accepts each token's `jti`
13960
+ * only once, a fresh one by the time it next exchanges.
13961
+ */
13962
+ var TokenFileRefresher = class {
13963
+ client;
13964
+ plans;
13965
+ timers = /* @__PURE__ */ new Map();
13966
+ expiries = /* @__PURE__ */ new Map();
13967
+ stopped = false;
13968
+ log;
13969
+ minIntervalMs;
13970
+ setTimer;
13971
+ clearTimer;
13972
+ now;
13973
+ constructor(client, plans, opts = {}) {
13974
+ this.client = client;
13975
+ this.plans = plans;
13976
+ this.log = opts.log ?? ((m) => console.error(m));
13977
+ this.minIntervalMs = opts.minIntervalMs ?? 3e4;
13978
+ this.setTimer = opts.setTimer ?? ((fn, ms) => setTimeout(fn, ms));
13979
+ this.clearTimer = opts.clearTimer ?? ((t) => clearTimeout(t));
13980
+ this.now = opts.now ?? Date.now;
13981
+ }
13982
+ /** Fetch every token once. Throws if any provider's first token cannot be had. */
13983
+ async start() {
13984
+ for (const plan of this.plans) for (const file of plan.files) writeAtomic(file.path, file.content);
13985
+ await Promise.all(this.plans.map((plan) => this.refresh(plan, true)));
13986
+ }
13987
+ async refresh(plan, first = false) {
13988
+ if (this.stopped) return;
13989
+ try {
13990
+ const issued = await this.client.identityToken(plan.audience);
13991
+ if (this.stopped) return;
13992
+ writeAtomic(plan.tokenFile, issued.token);
13993
+ this.expiries.set(plan.id, this.now() + issued.expiresIn * 1e3);
13994
+ this.schedule(plan, Math.max(this.minIntervalMs, issued.expiresIn * 1e3 / 2));
13995
+ } catch (err) {
13996
+ if (first) throw err;
13997
+ const left = (this.expiries.get(plan.id) ?? 0) - this.now();
13998
+ this.log(`seekrit: could not refresh the ${plan.id} identity token (${err instanceof Error ? err.message : String(err)}); ${left > 0 ? `the current one is valid for ${Math.round(left / 1e3)}s more, retrying` : "the current one has expired, retrying"}`);
13999
+ this.schedule(plan, Math.min(this.minIntervalMs, Math.max(1e3, left / 4)));
14000
+ }
14001
+ }
14002
+ schedule(plan, ms) {
14003
+ if (this.stopped) return;
14004
+ const timer = this.setTimer(() => void this.refresh(plan), ms);
14005
+ timer.unref?.();
14006
+ this.timers.set(plan.id, timer);
14007
+ }
14008
+ stop() {
14009
+ this.stopped = true;
14010
+ for (const timer of this.timers.values()) this.clearTimer(timer);
14011
+ this.timers.clear();
14012
+ }
14013
+ };
14014
+ /**
14015
+ * Run `cmd` with provider token files kept fresh for as long as it lives. The
14016
+ * token directory is private (0700, files 0600) and removed afterwards.
14017
+ */
14018
+ async function runWithIdentity(cmd, args, client, opts) {
14019
+ const log = opts.log ?? ((m) => console.error(m));
14020
+ const dir = mkdtempSync(join(tmpdir(), "seekrit-identity-"));
14021
+ let refresher;
14022
+ try {
14023
+ const plans = planProviders(opts, dir, opts.workloadId);
14024
+ for (const name of missingProviderSettings(plans, process.env)) log(`seekrit: ${name} is not set; the provider SDK will not use the federated token without it`);
14025
+ return await runCommand(cmd, args, async () => {
14026
+ refresher = new TokenFileRefresher(client, plans, { log });
14027
+ await refresher.start();
14028
+ const { env, removed } = childEnvironment(process.env, plans);
14029
+ if (removed.length > 0) log(`seekrit: unset ${removed.join(", ")} for the command so the federated identity is used`);
14030
+ return env;
14031
+ }, async () => {
14032
+ refresher?.stop();
14033
+ rmSync(dir, {
14034
+ recursive: true,
14035
+ force: true
14036
+ });
14037
+ return true;
14038
+ });
14039
+ } catch (err) {
14040
+ rmSync(dir, {
14041
+ recursive: true,
14042
+ force: true
14043
+ });
14044
+ throw err;
14045
+ }
14046
+ }
14047
+ function collect$7(value, previous = []) {
14048
+ return [...previous, value];
14049
+ }
14050
+ function clientFrom(options) {
14051
+ try {
14052
+ const creds = loadWorkloadCredentials(options);
14053
+ return {
14054
+ client: new WorkloadClient(creds),
14055
+ workloadId: creds.workloadId
14056
+ };
14057
+ } catch (err) {
14058
+ fail(err instanceof Error ? err.message : String(err));
14059
+ }
14060
+ }
14061
+ function credentialFlags(command) {
14062
+ return command.option("--workload-file <path>", "credentials downloaded at enrollment (default: $SEEKRIT_WORKLOAD_FILE)").option("--workload-id <id>", "workload id, for a platform-federated workload").option("--platform-token-file <path>", "platform JWT to exchange, reread on every sign-in (default: $SEEKRIT_PLATFORM_TOKEN_FILE)").option("--issuer <origin>", `seekrit API origin (default: the credential file's, or ${DEFAULT_ISSUER})`);
14063
+ }
14064
+ function registerIdentityCommands(program) {
14065
+ const identity = program.command("identity").description("keyless AWS, Google Cloud, OpenAI and Anthropic access from a seekrit workload identity");
14066
+ credentialFlags(identity.command("token").description("print a signed identity token for one enrolled audience").requiredOption("--audience <aud>", "an audience enrolled on the workload").option("--json", "print {token, expiresIn, issuer, subject} instead of the bare token")).action(async (options) => {
14067
+ const { client } = clientFrom(options);
14068
+ try {
14069
+ const issued = await client.identityToken(options.audience);
14070
+ console.log(options.json ? JSON.stringify(issued, null, 2) : issued.token);
14071
+ } catch (err) {
14072
+ fail(err instanceof Error ? err.message : String(err));
14073
+ }
14074
+ });
14075
+ credentialFlags(identity.command("run").description("run a command with provider identity-token files kept fresh and the provider SDK variables set").passThroughOptions().option("--aws <role-arn>", "assume this IAM role via web identity").option("--gcp <provider>", "workload identity pool provider: projects/<number>/locations/global/workloadIdentityPools/<pool>/providers/<id>").option("--gcp-service-account <email>", "impersonate this service account after federating").option("--openai", "write OPENAI_IDENTITY_TOKEN_FILE").option("--anthropic", "write ANTHROPIC_IDENTITY_TOKEN_FILE").option("--audience <provider=aud>", "override a provider's default audience (repeatable)", collect$7).argument("<command...>", "command to run (prefix with -- to pass flags)")).action(async (commandParts, options) => {
14076
+ const [cmd, ...args] = commandParts;
14077
+ if (!cmd) fail("no command given");
14078
+ const { client, workloadId } = clientFrom(options);
14079
+ let result;
14080
+ try {
14081
+ result = await runWithIdentity(cmd, args, client, {
14082
+ ...options,
14083
+ workloadId
14084
+ });
14085
+ } catch (err) {
14086
+ fail(err instanceof Error ? err.message : String(err));
14087
+ }
14088
+ if (result.signal) process.kill(process.pid, result.signal);
14089
+ else process.exit(result.code);
14090
+ });
14091
+ }
14092
+ // src/m2m.ts
14093
+ /**
14094
+ * Resolve M2M client credentials from (in order) the process environment, a
14095
+ * `.env` overlay (for `seekrit run`), then saved config. Both halves must come
14096
+ * through for the credential to be usable.
14097
+ */
14098
+ function readM2mCreds(dotenvVars = {}) {
14099
+ const config = readGlobalConfig();
14100
+ const fromEnv = (key) => process.env[key] ?? dotenvVars[key];
14101
+ const clientId = fromEnv("SEEKRIT_CLIENT_ID") ?? config.clientId;
14102
+ const clientSecret = fromEnv("SEEKRIT_CLIENT_SECRET") ?? config.clientSecret;
14103
+ if (!clientId || !clientSecret) return null;
14104
+ return {
14105
+ clientId,
14106
+ clientSecret
14107
+ };
14108
+ }
14109
+ /**
14110
+ * True when a service/session/dev credential is already configured explicitly.
14111
+ * A browser-authorized session counts: a human who ran `seekrit login` must not
14112
+ * be silently swapped onto a machine identity.
14113
+ */
14114
+ function hasExplicitCredential(dotenvVars) {
14115
+ const fromEnv = (key) => process.env[key] ?? dotenvVars[key];
14116
+ if (fromEnv("SEEKRIT_TOKEN") || fromEnv("SEEKRIT_DEV_USER")) return true;
14117
+ const config = readGlobalConfig();
14118
+ return Boolean(config.token || config.sessionToken || config.devUser);
14119
+ }
14120
+ /** Mint a fresh org-scoped admin token using M2M credentials (keyless). */
14121
+ async function mintAdminToken(apiUrl, creds) {
14122
+ const client = new SeekritClient({
14123
+ baseUrl: apiUrl,
14124
+ auth: {
14125
+ type: "m2m",
14126
+ clientId: creds.clientId,
14127
+ clientSecret: creds.clientSecret
14128
+ },
14129
+ client: `cli/${version}`
14130
+ });
14131
+ const { orgs } = await client.listOrgs();
14132
+ const org = orgs[0];
14133
+ if (!org) throw new Error("machine client has no organization — sign up first (POST /signup)");
14134
+ const created = await createServiceToken();
14135
+ await client.createToken(org.id, {
14136
+ name: "agent-admin (auto)",
14137
+ tokenId: created.tokenId,
14138
+ tokenHash: created.tokenHash,
14139
+ publicKeyJwk: created.publicKeyJwk,
14140
+ role: "admin",
14141
+ environmentId: null
14142
+ });
14143
+ return created.token;
14144
+ }
14145
+ /**
14146
+ * If M2M credentials are configured (and no explicit token/dev-user is), ensure
14147
+ * an admin token exists for them — minting and caching one on first use — and
14148
+ * expose it as `SEEKRIT_TOKEN` so the normal credential resolution
14149
+ * ({@link tryBuildContext}) picks it up. A no-op (returns null) when there is
14150
+ * nothing to bootstrap. Throws only when credentials ARE present but minting
14151
+ * fails, so the reason surfaces instead of a later opaque "no credentials".
14152
+ */
14153
+ async function ensureM2mAdminToken(dotenvVars = {}) {
14154
+ if (hasExplicitCredential(dotenvVars)) return null;
14155
+ const creds = readM2mCreds(dotenvVars);
14156
+ if (!creds) return null;
14157
+ const cached = readCachedM2mToken(creds.clientId);
14158
+ if (cached) {
14159
+ let usable = false;
14160
+ try {
14161
+ serviceTokenAuth(cached);
14162
+ usable = true;
14163
+ } catch {}
14164
+ if (usable) {
14165
+ process.env.SEEKRIT_TOKEN = cached;
14166
+ return cached;
14167
+ }
14168
+ }
14169
+ const token = await mintAdminToken(process.env.SEEKRIT_API_URL ?? dotenvVars.SEEKRIT_API_URL ?? readGlobalConfig().apiUrl ?? "https://api.seekrit.dev", creds);
14170
+ cacheM2mToken(creds.clientId, token);
14171
+ process.env.SEEKRIT_TOKEN = token;
14172
+ return token;
14173
+ }
14174
+ /** Lowercase, hyphenated, at most 40 characters — what `slugSchema` accepts. */
14175
+ function slugify(name) {
14176
+ return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40).replace(/-+$/g, "") || "workspace";
14177
+ }
14178
+ /** `acme-storefront` → `Acme Storefront`: a slug-ish name as a human reads it. */
14179
+ function titleCase(name) {
14180
+ return name.split(/[^A-Za-z0-9]+/).filter(Boolean).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
14181
+ }
14182
+ /**
14183
+ * The project's name, from whichever manifest the directory carries — the
14184
+ * package name without its npm scope, the Python or Rust package name, the last
14185
+ * segment of a Go module path — falling back to the directory's own name. The
14186
+ * manifests are read leniently (a regex, not a parser) because a malformed one
14187
+ * should cost the default, not the command.
14188
+ */
14189
+ function detectProjectName(dir = process.cwd()) {
14190
+ const read = (file) => {
14191
+ const path = join(dir, file);
14192
+ if (!existsSync(path)) return null;
14193
+ try {
14194
+ return readFileSync(path, "utf8");
14195
+ } catch {
14196
+ return null;
14197
+ }
14198
+ };
14199
+ const pkg = read("package.json");
14200
+ if (pkg) try {
14201
+ const name = JSON.parse(pkg).name;
14202
+ if (typeof name === "string" && name.trim()) return name.replace(/^@[^/]+\//, "");
14203
+ } catch {}
14204
+ const pyName = read("pyproject.toml")?.match(/^\[project\][^[]*?^name\s*=\s*"([^"]+)"/ms)?.[1];
14205
+ if (pyName) return pyName;
14206
+ const cargoName = read("Cargo.toml")?.match(/^\[package\][^[]*?^name\s*=\s*"([^"]+)"/ms)?.[1];
14207
+ if (cargoName) return cargoName;
14208
+ const goModule = read("go.mod")?.match(/^module\s+(\S+)/m)?.[1];
14209
+ if (goModule) return goModule.split("/").pop() ?? goModule;
14210
+ return basename(dir);
14211
+ }
14212
+ /**
14213
+ * What `init` would sign up as, from the flags and the directory. Pure, so the
14214
+ * naming rules are testable without a terminal or an API.
14215
+ */
14216
+ function planWorkspace(options, project) {
14217
+ const orgName = options.orgName?.trim() || titleCase(project);
14218
+ const orgSlug = options.org ?? slugify(options.orgName?.trim() || project);
14219
+ if (!slugSchema.safeParse(orgSlug).success) fail(`"${orgSlug}" is not a valid org slug (lowercase letters, numbers, and hyphens) — pass --org <slug>`);
13254
14220
  return {
13255
14221
  orgName,
13256
14222
  orgSlug
@@ -16171,176 +17137,6 @@ function registerRotationCommands(program) {
16171
17137
  console.error(`disabled rotation of ${r.secretName}${rotatorRevoked ? " — rotator key access revoked for this environment" : ""}`);
16172
17138
  });
16173
17139
  }
16174
- // src/run-command.ts
16175
- /** Keep signal handlers installed from provisioning through asynchronous cleanup. */
16176
- async function runCommand(cmd, args, prepare, cleanup) {
16177
- let child;
16178
- let forwarded;
16179
- let result = { code: 1 };
16180
- const stragglers = /* @__PURE__ */ new Set();
16181
- const collect = () => {
16182
- if (process.platform === "win32" || !child?.pid) return;
16183
- for (const pid of teardownTargets(child.pid)) stragglers.add(pid);
16184
- };
16185
- const forward = (signal) => {
16186
- forwarded ??= signal;
16187
- if (!child || child.exitCode !== null || child.signalCode !== null) return;
16188
- collect();
16189
- child.kill(signal);
16190
- for (const pid of stragglers) try {
16191
- process.kill(pid, signal);
16192
- } catch {}
16193
- };
16194
- const signals = [
16195
- "SIGINT",
16196
- "SIGTERM",
16197
- "SIGHUP",
16198
- "SIGQUIT"
16199
- ];
16200
- for (const signal of signals) process.on(signal, forward);
16201
- try {
16202
- const env = await prepare(() => forwarded !== void 0);
16203
- if (!forwarded) {
16204
- const running = spawn(cmd, args, {
16205
- stdio: "inherit",
16206
- env
16207
- });
16208
- child = running;
16209
- result = await new Promise((resolve, reject) => {
16210
- running.once("exit", (code, signal) => resolve({
16211
- code: code ?? 1,
16212
- signal: signal ?? void 0
16213
- }));
16214
- running.once("error", (err) => reject(/* @__PURE__ */ new Error(`failed to start ${cmd}: ${err.message}`)));
16215
- });
16216
- }
16217
- } finally {
16218
- try {
16219
- if (forwarded) {
16220
- collect();
16221
- await reapStragglers(stragglers, forwarded);
16222
- }
16223
- } finally {
16224
- try {
16225
- if (!await cleanup() && result.code === 0) result.code = 1;
16226
- } finally {
16227
- for (const signal of signals) process.off(signal, forward);
16228
- }
16229
- }
16230
- }
16231
- if (!child && forwarded) result.signal = forwarded;
16232
- return result;
16233
- }
16234
- /**
16235
- * Every live process `seekrit run` is responsible for tearing down, from a
16236
- * single `ps(1)` snapshot: each descendant of `root`, plus — when we lead our
16237
- * own process group — every other member of that group.
16238
- *
16239
- * Two mechanisms, because each covers the other's blind spot:
16240
- *
16241
- * - The parent-chain walk reaches a process that left our group via
16242
- * setsid(2)/setpgid(2), which no group-wide kill and no tty-generated signal
16243
- * can touch. But it loses anything whose chain up to `root` has already
16244
- * broken — teardown kills the middle layers first, and an orphan reparents to
16245
- * init, out of reach of any walk down from `root`.
16246
- * - Group membership survives exactly that: a pgid outlives the parent that
16247
- * passed it down. But it misses the ones that left the group.
16248
- *
16249
- * The group half applies only when our pid *is* our pgid, which is the shell-job
16250
- * case: the shell put this command in a new group, so every other member of it
16251
- * descends from us. Nested inside a shell script or a CI runner we are not the
16252
- * leader and the group holds processes we did not start, so there we use the
16253
- * walk alone.
16254
- *
16255
- * Zombies are skipped: they are already dead and waiting to be reaped, so
16256
- * counting them would stall teardown for the full grace period and then report
16257
- * a kill that did nothing. Returns nothing if `ps` is unavailable; callers fall
16258
- * back to signalling the immediate child.
16259
- */
16260
- function teardownTargets(root) {
16261
- const ps = spawnSync("ps", [
16262
- "-A",
16263
- "-o",
16264
- "pid=,ppid=,pgid=,stat="
16265
- ], { encoding: "utf8" });
16266
- if (ps.status !== 0 || typeof ps.stdout !== "string") return [];
16267
- const childrenOf = /* @__PURE__ */ new Map();
16268
- const groupOf = /* @__PURE__ */ new Map();
16269
- const isId = (value) => value !== void 0 && Number.isInteger(value);
16270
- for (const line of ps.stdout.split("\n")) {
16271
- const [pid, ppid, pgid, stat] = line.trim().split(/\s+/, 4);
16272
- const [id, parent, group] = [
16273
- pid,
16274
- ppid,
16275
- pgid
16276
- ].map(Number);
16277
- if (!isId(id) || !isId(parent) || !isId(group)) continue;
16278
- if (stat?.startsWith("Z")) continue;
16279
- const siblings = childrenOf.get(parent);
16280
- if (siblings) siblings.push(id);
16281
- else childrenOf.set(parent, [id]);
16282
- groupOf.set(id, group);
16283
- }
16284
- const found = /* @__PURE__ */ new Set();
16285
- const queue = [root];
16286
- const seen = new Set(queue);
16287
- for (let pid = queue.shift(); pid !== void 0; pid = queue.shift()) for (const kid of childrenOf.get(pid) ?? []) {
16288
- if (seen.has(kid)) continue;
16289
- seen.add(kid);
16290
- found.add(kid);
16291
- queue.push(kid);
16292
- }
16293
- if (groupOf.get(process.pid) === process.pid) {
16294
- for (const [pid, group] of groupOf) if (group === process.pid) found.add(pid);
16295
- }
16296
- found.delete(process.pid);
16297
- found.delete(root);
16298
- return [...found];
16299
- }
16300
- /** Whether `pid` still exists — signal 0 tests reachability, delivers nothing. */
16301
- function isAlive(pid) {
16302
- try {
16303
- process.kill(pid, 0);
16304
- return true;
16305
- } catch {
16306
- return false;
16307
- }
16308
- }
16309
- /** How long a straggler gets to finish shutting down before SIGKILL. */
16310
- const STRAGGLER_GRACE_MS = 2e3;
16311
- /**
16312
- * Once the command has exited, make sure nothing it started outlives us.
16313
- *
16314
- * Anything still alive here has ignored the signal we forwarded *and* lost the
16315
- * parent that launched it, and we are the last process that knows its pid:
16316
- * the tty won't hang it up (it is no longer in the foreground group, and the
16317
- * shell has moved on), so it survives until the machine reboots. That is how
16318
- * `tsx` and the server under it stacked up for days.
16319
- *
16320
- * So escalate rather than trust. SIGTERM first — it costs no extra time and is
16321
- * a rung the SIGINT-only handlers common in dev servers don't catch — then
16322
- * SIGKILL whatever is left after the grace period. Nothing is killed unless it
16323
- * was asked to stop first and declined, and this runs only when we forwarded a
16324
- * termination signal: a command that exits on its own having deliberately left a
16325
- * daemon behind keeps working.
16326
- */
16327
- async function reapStragglers(pids, signal) {
16328
- let live = [...pids].filter(isAlive);
16329
- if (live.length === 0) return;
16330
- for (const pid of live) try {
16331
- process.kill(pid, "SIGTERM");
16332
- } catch {}
16333
- const deadline = Date.now() + STRAGGLER_GRACE_MS;
16334
- while (live.length > 0 && Date.now() < deadline) {
16335
- await new Promise((resolve) => setTimeout(resolve, 50));
16336
- live = live.filter(isAlive);
16337
- }
16338
- if (live.length === 0) return;
16339
- console.error(`seekrit: force-killed ${live.length} leftover process(es) that ignored ${signal} and SIGTERM (${live.join(", ")})`);
16340
- for (const pid of live) try {
16341
- process.kill(pid, "SIGKILL");
16342
- } catch {}
16343
- }
16344
17140
  // src/run-leases.ts
16345
17141
  /** Validate all flags before contacting the API or creating any database roles. */
16346
17142
  function parseRunLeaseOptions(bindings = [], ttl) {
@@ -18000,6 +18796,8 @@ registerHermesCommands(program);
18000
18796
  registerSshCommands(program);
18001
18797
  registerAwsCommands(program);
18002
18798
  registerGcpCommands(program);
18799
+ registerDynamicCommands(program);
18800
+ registerIdentityCommands(program);
18003
18801
  registerMongoCommands(program);
18004
18802
  registerKmsCommands(program);
18005
18803
  registerRotationCommands(program);