@seekrit/cli 1.6.2 → 1.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -12,10 +12,10 @@ import { connect } from "node:net";
12
12
  import { fileURLToPath } from "node:url";
13
13
  import { request } from "node:http";
14
14
  /** Default lifetime of a published bundle (7 days), in seconds. */
15
- const POLICY_DEFAULT_TTL_SECONDS = 10080 * 60;
15
+ const POLICY_DEFAULT_TTL_SECONDS = 604800;
16
16
  /** Bounds on a bundle's lifetime: an hour at the short end, 90 days at the long. */
17
17
  const POLICY_MIN_TTL_SECONDS = 3600;
18
- const POLICY_MAX_TTL_SECONDS = 2160 * 60 * 60;
18
+ const POLICY_MAX_TTL_SECONDS = 7776e3;
19
19
  /** A bare hostname: no scheme, no port, no path, no wildcard. */
20
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
21
  const policyMethodSchema = z.string().trim().toUpperCase().regex(/^[A-Z]{3,10}$/, "method must be an HTTP method name");
@@ -34,7 +34,7 @@ const agentPolicyRuleSchema = z.object({
34
34
  });
35
35
  z.object({
36
36
  /** `ap1.<body>.<signature>` — opaque to the server. */
37
- bundle: z.string().min(16).max(256 * 1024) });
37
+ bundle: z.string().min(16).max(262144) });
38
38
  z.object({
39
39
  name: z.string().trim().min(1).max(120),
40
40
  slug: z.string().trim().min(1).max(64).regex(/^[a-z0-9][a-z0-9-]*$/, "slug is lowercase letters, digits, and dashes"),
@@ -521,7 +521,7 @@ function countApplicable(proposals) {
521
521
  * to bound one run; something that needs longer wants a policy change, not a
522
522
  * longer ticket.
523
523
  */
524
- const TASK_MAX_TTL_SECONDS = 720 * 60;
524
+ const TASK_MAX_TTL_SECONDS = 43200;
525
525
  /** An EC P-256 public JWK, for a sender-constraint proof key. */
526
526
  const taskProofJwkSchema = z.object({
527
527
  kty: z.literal("EC"),
@@ -707,14 +707,16 @@ async function verifyArchive(archive, options = {}) {
707
707
  if (options.skipSignature) {
708
708
  signature = "unverifiable";
709
709
  signatureNote = "signature checking was skipped";
710
- } else if (archive.signature) if (options.expectKeyId && options.expectKeyId !== archive.signature.keyId) {
711
- signature = "invalid";
712
- signatureNote = `signed by key ${archive.signature.keyId}, expected ${options.expectKeyId}`;
713
- } else try {
714
- signature = await verifySignature(archive.manifest, archive.signature) ? "valid" : "invalid";
715
- } catch (err) {
716
- signature = "unverifiable";
717
- signatureNote = err instanceof Error ? err.message : String(err);
710
+ } else if (archive.signature) {
711
+ if (options.expectKeyId && options.expectKeyId !== archive.signature.keyId) {
712
+ signature = "invalid";
713
+ signatureNote = `signed by key ${archive.signature.keyId}, expected ${options.expectKeyId}`;
714
+ } else try {
715
+ signature = await verifySignature(archive.manifest, archive.signature) ? "valid" : "invalid";
716
+ } catch (err) {
717
+ signature = "unverifiable";
718
+ signatureNote = err instanceof Error ? err.message : String(err);
719
+ }
718
720
  }
719
721
  return {
720
722
  ok: badSections.length === 0 && missingSections.length === 0 && undeclaredSections.length === 0 && manifestDigestOk && signature === "valid",
@@ -1001,7 +1003,7 @@ const SUBSCRIPTION_STATUSES = [
1001
1003
  * composition (matched by slug) and have no single parent to overlay.
1002
1004
  */
1003
1005
  /** Longest life a branch may be given. Bounds sprawl even if nobody cleans up. */
1004
- const MAX_BRANCH_TTL_SECONDS = 720 * 60 * 60;
1006
+ const MAX_BRANCH_TTL_SECONDS = 2592e3;
1005
1007
  /**
1006
1008
  * Parse a human TTL — `30m`, `12h`, `7d`, `2w`, or bare seconds — into seconds.
1007
1009
  * Returns null for anything unparseable, so callers can report the input back.
@@ -1610,13 +1612,13 @@ const sshTargetConfigSchema = z.object({
1610
1612
  caPublicKey: sshPublicKeySchema,
1611
1613
  allowedPrincipals: z.array(sshPrincipalSchema).max(64).optional(),
1612
1614
  extensions: z.array(sshExtensionSchema).max(16).optional(),
1613
- maxTtlSeconds: z.number().int().min(60).max(3600 * 24 * 7).optional(),
1615
+ maxTtlSeconds: z.number().int().min(60).max(604800).optional(),
1614
1616
  connection: z.object({
1615
1617
  host: z.string().min(1).optional(),
1616
1618
  user: sshPrincipalSchema.optional()
1617
1619
  }).optional()
1618
1620
  });
1619
- const AWS_MAX_TTL_SECONDS = 3600 * 12;
1621
+ const AWS_MAX_TTL_SECONDS = 43200;
1620
1622
  const awsTargetConfigSchema = z.object({
1621
1623
  provider: z.literal("aws"),
1622
1624
  executor: z.literal("in_do"),
@@ -1626,7 +1628,7 @@ const awsTargetConfigSchema = z.object({
1626
1628
  sessionPolicy: z.string().min(1).max(4e3).optional(),
1627
1629
  maxTtlSeconds: z.number().int().min(900).max(AWS_MAX_TTL_SECONDS).optional()
1628
1630
  });
1629
- const GCP_MAX_TTL_SECONDS = 3600 * 12;
1631
+ const GCP_MAX_TTL_SECONDS = 43200;
1630
1632
  const gcpTargetConfigSchema = z.object({
1631
1633
  provider: z.literal("gcp"),
1632
1634
  executor: z.literal("in_do"),
@@ -1643,7 +1645,7 @@ const mongoTargetConfigSchema = z.object({
1643
1645
  authSource: mongoDatabaseNameSchema.optional(),
1644
1646
  roles: z.array(mongoRoleSchema).min(1).max(32).optional(),
1645
1647
  tls: z.boolean().optional(),
1646
- maxTtlSeconds: z.number().int().min(60).max(3600 * 24 * 7).optional()
1648
+ maxTtlSeconds: z.number().int().min(60).max(604800).optional()
1647
1649
  });
1648
1650
  const leaseTargetConfigSchema = z.discriminatedUnion("provider", [
1649
1651
  postgresTargetConfigSchema,
@@ -1665,7 +1667,7 @@ z.object({
1665
1667
  wrappedAdminSecret: z.string().min(1)
1666
1668
  });
1667
1669
  /** Requested lease lifetime, shared by all providers. */
1668
- const ttlSecondsSchema = z.number().int().min(60).max(3600 * 24 * 7);
1670
+ const ttlSecondsSchema = z.number().int().min(60).max(604800);
1669
1671
  /**
1670
1672
  * Client → API: mint a Postgres lease. The client generates the password and
1671
1673
  * its SCRAM verifier locally and sends only the verifier — the plaintext
@@ -2376,7 +2378,7 @@ const rotationAlphabetSchema = z.enum([
2376
2378
  "base64url",
2377
2379
  "printable"
2378
2380
  ]);
2379
- const rotationIntervalSchema = z.number().int().min(300).max(3600 * 24 * 365);
2381
+ const rotationIntervalSchema = z.number().int().min(300).max(31536e3);
2380
2382
  /**
2381
2383
  * A database user name we are willing to *re-key*. Deliberately more permissive
2382
2384
  * than the lease providers' name schemas — those name accounts seekrit creates,
@@ -5053,7 +5055,7 @@ async function createAgentTaskToken() {
5053
5055
  }
5054
5056
  //#endregion
5055
5057
  //#region package.json
5056
- var version = "1.6.2";
5058
+ var version = "1.6.4";
5057
5059
  //#endregion
5058
5060
  //#region ../../packages/api-client/src/index.ts
5059
5061
  var SeekritApiError = class extends Error {
@@ -7063,7 +7065,7 @@ function registerPolicyCommands(policy) {
7063
7065
  const KEY_DOMAIN = "seekrit-lkg-cache-v1";
7064
7066
  const TOKEN_DOMAIN = "seekrit-token-fp-v1";
7065
7067
  /** 24h: long enough to ride out an outage, short enough to bound the tail. */
7066
- const DEFAULT_MAX_AGE_MS = 1440 * 60 * 1e3;
7068
+ const DEFAULT_MAX_AGE_MS = 864e5;
7067
7069
  /**
7068
7070
  * Derive the key for one resolve request. Overrides are sorted, so flag order
7069
7071
  * never splits the cache. Byte-for-byte identical to `CacheKey::new` in
@@ -9126,8 +9128,12 @@ function envLabel(archive, env) {
9126
9128
  }
9127
9129
  /** Filesystem path for an environment's output file, mirroring its label. */
9128
9130
  function envPath(archive, env, extension) {
9129
- if (env.groupId) return join("groups", archive.data.groups.find((g) => g.id === env.groupId)?.slug ?? env.groupId, `${env.slug}.${extension}`);
9130
- return join("apps", archive.data.applications.find((a) => a.id === env.applicationId)?.slug ?? env.applicationId ?? "unknown", `${env.slug}.${extension}`);
9131
+ if (env.groupId) {
9132
+ const group = archive.data.groups.find((g) => g.id === env.groupId);
9133
+ return join("groups", group?.slug ?? env.groupId, `${env.slug}.${extension}`);
9134
+ }
9135
+ const app = archive.data.applications.find((a) => a.id === env.applicationId);
9136
+ return join("apps", app?.slug ?? env.applicationId ?? "unknown", `${env.slug}.${extension}`);
9131
9137
  }
9132
9138
  /**
9133
9139
  * Recover a private key to open the archive with, from (in order) a service
@@ -9545,7 +9551,7 @@ function registerAwsCommands(program) {
9545
9551
  const cfg = t.config;
9546
9552
  if (cfg.provider !== "aws") fail(`"${t.name}" is not an aws target (see \`seekrit pg\`)`);
9547
9553
  const ttlSeconds = parseTtlSeconds$6(options.ttl);
9548
- if (ttlSeconds < 900) fail(`--ttl must be at least ${900 / 60}m (STS minimum)`);
9554
+ if (ttlSeconds < 900) fail(`--ttl must be at least 15m (STS minimum)`);
9549
9555
  const recipient = await generateAwsRecipientKeyPair();
9550
9556
  const { aws: leased } = await ctx.client.mintLease(org.id, {
9551
9557
  provider: "aws",
@@ -11951,11 +11957,12 @@ function checkPlugin(pluginDir, opts = {}) {
11951
11957
  detail: fingerprintOk ? String(fingerprintBody?.version ?? "") : (fingerprint.stderr || fingerprint.stdout || "no output").trim()
11952
11958
  });
11953
11959
  if (!fingerprintOk) return steps;
11954
- const fetch = spawnSync(bin, [...opts.config ? [
11960
+ const argv = opts.config ? [
11955
11961
  "--config",
11956
11962
  opts.config,
11957
11963
  "fetch"
11958
- ] : ["fetch"], opts.path ?? ""], {
11964
+ ] : ["fetch"];
11965
+ const fetch = spawnSync(bin, [...argv, opts.path ?? ""], {
11959
11966
  encoding: "utf8",
11960
11967
  timeout: 6e4,
11961
11968
  env: {
@@ -15525,7 +15532,7 @@ registerKmsCommands(program);
15525
15532
  registerRotationCommands(program);
15526
15533
  registerRecoveryCommands(program);
15527
15534
  program.command("mcp").description("run an MCP server over stdio so AI agents can drive seekrit").action(async () => {
15528
- const { runMcpServer } = await import("./mcp-CjHg4P-V.js");
15535
+ const { runMcpServer } = await import("./mcp-BvXwiGRv.js");
15529
15536
  await runMcpServer();
15530
15537
  });
15531
15538
  registerAuditCommands(program);
@@ -438,7 +438,8 @@ async function runMcpServer(options = {}) {
438
438
  const k = await kmsResolveKey(ctx, orgRef.id, key);
439
439
  if (k.purpose !== "sign") throw new Error(`${k.name} is a ${k.purpose} key`);
440
440
  const { material, currentVersion } = await kmsRecoverMaterial(ctx, orgRef.id, k.id);
441
- return { signature: await signMessage(await importSigningKey(material), {
441
+ const privateKey = await importSigningKey(material);
442
+ return { signature: await signMessage(privateKey, {
442
443
  keyId: k.id,
443
444
  version: currentVersion
444
445
  }, message) };
@@ -527,7 +528,8 @@ async function runMcpServer(options = {}) {
527
528
  const { apps } = await ctx.client.listApps(orgRef.id);
528
529
  const appRow = apps.find((a) => a.slug === app || a.id === app);
529
530
  if (!appRow) throw new Error(`no app "${app}" in ${orgRef.slug}`);
530
- const wrappedDek = await wrapDek(generateDek(), await principalPublicKeyJwk(ctx));
531
+ const dek = generateDek();
532
+ const wrappedDek = await wrapDek(dek, await principalPublicKeyJwk(ctx));
531
533
  return (await ctx.client.createEnv(orgRef.id, appRow.id, {
532
534
  name,
533
535
  slug,
@@ -594,7 +596,8 @@ async function runMcpServer(options = {}) {
594
596
  org,
595
597
  group
596
598
  });
597
- const wrappedDek = await wrapDek(generateDek(), await principalPublicKeyJwk(ctx));
599
+ const dek = generateDek();
600
+ const wrappedDek = await wrapDek(dek, await principalPublicKeyJwk(ctx));
598
601
  return (await ctx.client.createGroupEnv(g.orgId, g.id, {
599
602
  name,
600
603
  slug,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seekrit/cli",
3
- "version": "1.6.2",
3
+ "version": "1.6.4",
4
4
  "description": "End-to-end encrypted secrets manager CLI — inject decrypted secrets into any command.",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -27,8 +27,8 @@
27
27
  "zod": "^4.6.2"
28
28
  },
29
29
  "devDependencies": {
30
- "@types/node": "^26.1.0",
31
- "tsdown": "^0.22.3",
30
+ "@types/node": "^26.5.1",
31
+ "tsdown": "^0.23.0",
32
32
  "vitest": "^4.1.11",
33
33
  "@seekrit/api-client": "0.0.1",
34
34
  "@seekrit/core": "0.0.1",