@dragonmastery/tamer 0.34.0 → 0.35.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 (63) hide show
  1. package/dist/{apply-BsVQ9cbK.mjs → apply-B2wMY64Q.mjs} +10 -10
  2. package/dist/{apply-BsVQ9cbK.mjs.map → apply-B2wMY64Q.mjs.map} +1 -1
  3. package/dist/{applyTarget-BJlVrED9.mjs → applyTarget-KBomh7SL.mjs} +2 -2
  4. package/dist/{applyTarget-BJlVrED9.mjs.map → applyTarget-KBomh7SL.mjs.map} +1 -1
  5. package/dist/{bootstrap-CV6OT-c9.mjs → bootstrap-C7CZYHzb.mjs} +7 -7
  6. package/dist/bootstrap-C7CZYHzb.mjs.map +1 -0
  7. package/dist/{cloudflareSnapshot-CMbPQIsN.mjs → cloudflareSnapshot-BVlpH5K6.mjs} +3 -3
  8. package/dist/{cloudflareSnapshot-CMbPQIsN.mjs.map → cloudflareSnapshot-BVlpH5K6.mjs.map} +1 -1
  9. package/dist/{deploy-dNygCucr.mjs → deploy-C4Mi_qwz.mjs} +7 -7
  10. package/dist/{deploy-dNygCucr.mjs.map → deploy-C4Mi_qwz.mjs.map} +1 -1
  11. package/dist/{destroy-C0cKkpWe.mjs → destroy-DDVWxl7U.mjs} +18 -12
  12. package/dist/destroy-DDVWxl7U.mjs.map +1 -0
  13. package/dist/{destroy-tenant-hyEb1gEz.mjs → destroy-tenant-DL99EoRZ.mjs} +2 -2
  14. package/dist/{destroy-tenant-hyEb1gEz.mjs.map → destroy-tenant-DL99EoRZ.mjs.map} +1 -1
  15. package/dist/{dev-Bug5l5OZ.mjs → dev-BiPXBOKk.mjs} +6 -6
  16. package/dist/{dev-Bug5l5OZ.mjs.map → dev-BiPXBOKk.mjs.map} +1 -1
  17. package/dist/{doctor-BwuEPYM6.mjs → doctor-DDwsA2V6.mjs} +2 -2
  18. package/dist/{doctor-BwuEPYM6.mjs.map → doctor-DDwsA2V6.mjs.map} +1 -1
  19. package/dist/{drift-DENAf1Oe.mjs → drift-DqMtlwkg.mjs} +4 -4
  20. package/dist/{drift-B5y9LF5X.mjs → drift-RpShXwG7.mjs} +5 -5
  21. package/dist/{drift-B5y9LF5X.mjs.map → drift-RpShXwG7.mjs.map} +1 -1
  22. package/dist/{emit-DTpaIMkn.mjs → emit-BUPlQH-r.mjs} +2 -2
  23. package/dist/{emit-DTpaIMkn.mjs.map → emit-BUPlQH-r.mjs.map} +1 -1
  24. package/dist/{events-B7Lencm8.mjs → events-D9kQWwH8.mjs} +2 -2
  25. package/dist/{events-B7Lencm8.mjs.map → events-D9kQWwH8.mjs.map} +1 -1
  26. package/dist/{generator-ZTEeHlft.mjs → generator-BCcu_eoO.mjs} +2 -2
  27. package/dist/{generator-ZTEeHlft.mjs.map → generator-BCcu_eoO.mjs.map} +1 -1
  28. package/dist/{import-Ciq9MN3v.mjs → import-DHmLtue3.mjs} +3 -3
  29. package/dist/{import-Ciq9MN3v.mjs.map → import-DHmLtue3.mjs.map} +1 -1
  30. package/dist/{migrate-DWyUVN1I.mjs → migrate-36WDEaFz.mjs} +4 -4
  31. package/dist/{migrate-DWyUVN1I.mjs.map → migrate-36WDEaFz.mjs.map} +1 -1
  32. package/dist/{plan-Blxn-yKr.mjs → plan-k0jLGYyw.mjs} +8 -8
  33. package/dist/{plan-Blxn-yKr.mjs.map → plan-k0jLGYyw.mjs.map} +1 -1
  34. package/dist/{provision-tenant-BHDWTC2U.mjs → provision-tenant-BjFpVm-y.mjs} +6 -5
  35. package/dist/provision-tenant-BjFpVm-y.mjs.map +1 -0
  36. package/dist/{registry-BlHEOKlN.mjs → registry-DyToEush.mjs} +2 -2
  37. package/dist/{registry-BlHEOKlN.mjs.map → registry-DyToEush.mjs.map} +1 -1
  38. package/dist/{status-PlMHsDzT.mjs → status-DaaOPBEf.mjs} +3 -3
  39. package/dist/{status-PlMHsDzT.mjs.map → status-DaaOPBEf.mjs.map} +1 -1
  40. package/dist/{sync-YKZ5HD8v.mjs → sync-DEudPgQc.mjs} +4 -4
  41. package/dist/{sync-YKZ5HD8v.mjs.map → sync-DEudPgQc.mjs.map} +1 -1
  42. package/dist/tamer.mjs +135 -85
  43. package/dist/tamer.mjs.map +1 -1
  44. package/dist/tamerArtifactsR2-7qUbhOLD.mjs +51 -0
  45. package/dist/tamerArtifactsR2-7qUbhOLD.mjs.map +1 -0
  46. package/dist/{types-CADr4Kck.mjs → types-BQajHdJb.mjs} +4 -4
  47. package/dist/{types-CADr4Kck.mjs.map → types-BQajHdJb.mjs.map} +1 -1
  48. package/dist/{verifyPlanFile-BBAwWzUo.mjs → verifyPlanFile-CpxwOxrV.mjs} +2 -2
  49. package/dist/{verifyPlanFile-BBAwWzUo.mjs.map → verifyPlanFile-CpxwOxrV.mjs.map} +1 -1
  50. package/dist/{wfp-delete-CQc9tveU.mjs → wfp-delete-DsfqSBxt.mjs} +2 -2
  51. package/dist/{wfp-delete-CQc9tveU.mjs.map → wfp-delete-DsfqSBxt.mjs.map} +1 -1
  52. package/dist/{wfp-put-CVw8cloM.mjs → wfp-put-DX_bH-s7.mjs} +2 -2
  53. package/dist/{wfp-put-CVw8cloM.mjs.map → wfp-put-DX_bH-s7.mjs.map} +1 -1
  54. package/dist/{worker-route-CqBDvjgo.mjs → worker-route-CUQBu9xe.mjs} +2 -2
  55. package/dist/{worker-route-CqBDvjgo.mjs.map → worker-route-CUQBu9xe.mjs.map} +1 -1
  56. package/dist/{workers-y9RTOzbC.mjs → workers-BjDCuyVv.mjs} +2 -2
  57. package/dist/{workers-y9RTOzbC.mjs.map → workers-BjDCuyVv.mjs.map} +1 -1
  58. package/package.json +6 -2
  59. package/dist/bootstrap-CV6OT-c9.mjs.map +0 -1
  60. package/dist/destroy-C0cKkpWe.mjs.map +0 -1
  61. package/dist/provision-tenant-BHDWTC2U.mjs.map +0 -1
  62. package/dist/tamerArtifactsR2-Ba29OVp9.mjs +0 -52
  63. package/dist/tamerArtifactsR2-Ba29OVp9.mjs.map +0 -1
package/dist/tamer.mjs CHANGED
@@ -5495,12 +5495,19 @@ var CFApiClient = class {
5495
5495
  //#region src/core/secrets/secretsDb.ts
5496
5496
  /** Max audit rows retained per secret name (oldest dropped on insert). */
5497
5497
  const SECRET_HISTORY_CAP = 50;
5498
- /** Cloudflare D1 database for encrypted secrets (`tamer-secrets-dev`, …). */
5499
- function tamerSecretsDatabaseName(env) {
5500
- return `tamer-secrets-${env}`;
5498
+ /**
5499
+ * Account-scoped D1 database for encrypted secrets (`tamer-secrets`).
5500
+ * Each env's secrets are isolated by row key: `{env}:{secretName}`.
5501
+ */
5502
+ function tamerSecretsDatabaseName() {
5503
+ return "tamer-secrets";
5501
5504
  }
5502
- async function findTamerSecretsDatabaseUuid(api, env) {
5503
- const name = tamerSecretsDatabaseName(env);
5505
+ /** Row key for a secret in the shared D1: `{env}:{secretName}`. */
5506
+ function secretRowKey(env, secretName) {
5507
+ return `${env}:${secretName}`;
5508
+ }
5509
+ async function findTamerSecretsDatabaseUuid(api) {
5510
+ const name = tamerSecretsDatabaseName();
5504
5511
  return (await api.d1ListAll()).find((d) => d.name === name)?.uuid;
5505
5512
  }
5506
5513
  const SECRETS_TABLE_DDL = `CREATE TABLE IF NOT EXISTS secrets (
@@ -5520,16 +5527,28 @@ const SECRET_HISTORY_TABLE_DDL = `CREATE TABLE IF NOT EXISTS secret_history (
5520
5527
  updated_by TEXT
5521
5528
  )`;
5522
5529
  /**
5523
- * Create `tamer-secrets-{env}` if missing and ensure `secrets` / `secret_history`
5524
- * tables. Idempotent — safe to call on every bootstrap or first vault touch.
5530
+ * Create `tamer-secrets` (account-scoped) if missing and ensure `secrets` /
5531
+ * `secret_history` tables. Idempotent — safe to call on every bootstrap or
5532
+ * first vault touch.
5525
5533
  */
5526
- async function ensureTamerSecretsDatabase(api, env) {
5527
- let uuid$1 = await findTamerSecretsDatabaseUuid(api, env);
5528
- if (!uuid$1) uuid$1 = (await api.d1Create(tamerSecretsDatabaseName(env))).uuid;
5534
+ async function ensureTamerSecretsDatabase(api) {
5535
+ let uuid$1 = await findTamerSecretsDatabaseUuid(api);
5536
+ if (!uuid$1) uuid$1 = (await api.d1Create(tamerSecretsDatabaseName())).uuid;
5529
5537
  await api.d1Query(uuid$1, SECRETS_TABLE_DDL);
5530
5538
  await api.d1Query(uuid$1, SECRET_HISTORY_TABLE_DDL);
5531
5539
  return uuid$1;
5532
5540
  }
5541
+ /**
5542
+ * Delete all secret rows for a specific env from the shared account-scoped D1.
5543
+ * Used by `tamer destroy --wipe-metadata`.
5544
+ */
5545
+ async function deleteEnvSecretRows(api, env) {
5546
+ const uuid$1 = await findTamerSecretsDatabaseUuid(api);
5547
+ if (!uuid$1) return false;
5548
+ await api.d1Query(uuid$1, `DELETE FROM secrets WHERE name LIKE ?`, [`${env}:%`]);
5549
+ await api.d1Query(uuid$1, `DELETE FROM secret_history WHERE name LIKE ?`, [`${env}:%`]);
5550
+ return true;
5551
+ }
5533
5552
 
5534
5553
  //#endregion
5535
5554
  //#region src/core/secrets/masterKey.ts
@@ -6147,7 +6166,7 @@ function resolveCrossResourceReferences(merged, ctx) {
6147
6166
  return next;
6148
6167
  }
6149
6168
  function stripTamerFields(config$1) {
6150
- const { path, config: configPath, resources, local, env, scriptName: _scriptName, wranglerOutFile: _out, dispatchNamespace: _dispatchNs, tamerRoutes: _tamerRoutes, tamerStaleRouteSweepZones: _tamerStaleRouteSweepZones, ...rest$1 } = config$1;
6169
+ const { path, config: configPath, resources, local, env, scriptName: _scriptName, wranglerOutFile: _out, dispatchNamespace: _dispatchNs, tamerRoutes: _tamerRoutes, tamerStaleRouteSweepZones: _tamerStaleRouteSweepZones, build: _build, secrets: _secrets, alias: _alias, ...rest$1 } = config$1;
6151
6170
  return rest$1;
6152
6171
  }
6153
6172
  /**
@@ -6556,9 +6575,21 @@ function stackNameForConfig(config$1) {
6556
6575
  * 5: + `secret` state entries (fingerprints only; additive resource rows).
6557
6576
  */
6558
6577
  const STATE_SCHEMA_VERSION = 5;
6559
- /** Cloudflare D1 database that holds JSON state for an env (`tamer-state-dev`, …). */
6560
- function tamerStateDatabaseName(env) {
6561
- return `tamer-state-${env}`;
6578
+ /**
6579
+ * Account-scoped D1 database that holds JSON state for **all** envs
6580
+ * (`tamer-state`). Each env's state is isolated by row key:
6581
+ * `cfi_state:{env}:{stackName}`.
6582
+ */
6583
+ function tamerStateDatabaseName() {
6584
+ return "tamer-state";
6585
+ }
6586
+ /**
6587
+ * D1 `tamer_kv.k` value for a given env + stack's state row.
6588
+ * Format: `cfi_state:{env}:{stackName}` — env namespacing ensures
6589
+ * cross-env isolation within the shared account-scoped D1.
6590
+ */
6591
+ function stateRowKey(env, stackName) {
6592
+ return `cfi_state:${env}:${stackName}`;
6562
6593
  }
6563
6594
  function createEmptyCfiState(tenantId, env) {
6564
6595
  return {
@@ -6587,24 +6618,24 @@ function migrateRawCfiStateInPlace(raw) {
6587
6618
  if (raw.schemaVersion === 3) raw.schemaVersion = 4;
6588
6619
  if (raw.schemaVersion === 4) raw.schemaVersion = STATE_SCHEMA_VERSION;
6589
6620
  }
6590
- async function findTamerStateDatabaseUuid(api, env) {
6591
- const name = tamerStateDatabaseName(env);
6621
+ async function findTamerStateDatabaseUuid(api) {
6622
+ const name = tamerStateDatabaseName();
6592
6623
  return (await api.d1ListAll()).find((d) => d.name === name)?.uuid;
6593
6624
  }
6594
6625
  /**
6595
- * Create `tamer-state-{env}` if missing, ensure `tamer_kv` table, and seed an
6596
- * initial empty `cfi_state:{stackName}` row when this stack has no row yet.
6597
- * Idempotent — re-running for the same stack is a no-op; re-running for a
6598
- * different stack against the same env D1 just adds another row.
6626
+ * Create `tamer-state` (account-scoped) if missing, ensure `tamer_kv` table,
6627
+ * and seed an initial empty `cfi_state:{env}:{stackName}` row when this stack
6628
+ * has no row yet. Idempotent — re-running for the same env+stack is a no-op;
6629
+ * re-running for a different env or stack just adds another row.
6599
6630
  */
6600
6631
  async function ensureTamerStateDatabase(api, tenantId, env, stackName = DEFAULT_STACK_NAME) {
6601
- let uuid$1 = await findTamerStateDatabaseUuid(api, env);
6602
- if (!uuid$1) uuid$1 = (await api.d1Create(tamerStateDatabaseName(env))).uuid;
6632
+ let uuid$1 = await findTamerStateDatabaseUuid(api);
6633
+ if (!uuid$1) uuid$1 = (await api.d1Create(tamerStateDatabaseName())).uuid;
6603
6634
  await api.d1Query(uuid$1, `CREATE TABLE IF NOT EXISTS tamer_kv (
6604
6635
  k TEXT PRIMARY KEY,
6605
6636
  v TEXT NOT NULL
6606
6637
  )`);
6607
- const rowKey = `cfi_state:${stackName}`;
6638
+ const rowKey = stateRowKey(env, stackName);
6608
6639
  const { rows } = await api.d1Query(uuid$1, `SELECT v FROM tamer_kv WHERE k = ?`, [rowKey]);
6609
6640
  if (rows.length === 0) {
6610
6641
  const initial = createEmptyCfiState(tenantId, env);
@@ -6619,10 +6650,19 @@ function parseCfiStateJson(json) {
6619
6650
  if (!result.success) throw new Error(`Invalid tamer state JSON: ${result.error.message}`);
6620
6651
  return result.data;
6621
6652
  }
6622
- async function destroyTamerStateDatabase(api, env) {
6623
- const uuid$1 = await findTamerStateDatabaseUuid(api, env);
6653
+ /**
6654
+ * Delete all state rows for a specific env from the shared account-scoped D1.
6655
+ * Used by `tamer destroy --wipe-metadata` to clean up an env's state without
6656
+ * affecting other envs that share the same `tamer-state` database.
6657
+ *
6658
+ * Note: this does NOT delete the D1 database itself — the shared `tamer-state`
6659
+ * database persists for other envs. To remove Tamer entirely from an account,
6660
+ * delete the D1/R2 resources manually via the Cloudflare dashboard.
6661
+ */
6662
+ async function deleteEnvStateRows(api, env) {
6663
+ const uuid$1 = await findTamerStateDatabaseUuid(api);
6624
6664
  if (!uuid$1) return false;
6625
- await api.d1Delete(uuid$1);
6665
+ await api.d1Query(uuid$1, `DELETE FROM tamer_kv WHERE k LIKE ?`, [`cfi_state:${env}:%`]);
6626
6666
  return true;
6627
6667
  }
6628
6668
 
@@ -6705,15 +6745,13 @@ var StateConflictError = class extends Error {
6705
6745
 
6706
6746
  //#endregion
6707
6747
  //#region src/core/state/StateManager.ts
6708
- /** D1 `tamer_kv.k` value for a given stack's state row. */
6709
- function stateRowKey(stackName) {
6710
- return `cfi_state:${stackName}`;
6711
- }
6712
6748
  const OPERATION_HISTORY_CAP = 50;
6713
6749
  /**
6714
6750
  * Authoritative deployment state for an env.
6715
6751
  *
6716
- * - **Non-local:** stored as JSON in Cloudflare D1 (`tamer-state-{env}`).
6752
+ * - **Non-local:** stored as JSON in Cloudflare D1 (`tamer-state`,
6753
+ * account-scoped). Each env's state is isolated by row key:
6754
+ * `cfi_state:{env}:{stackName}`.
6717
6755
  * Call {@link hydrate} before {@link load}, then {@link persist} after mutations.
6718
6756
  * - **local:** in-memory only (no persistence).
6719
6757
  */
@@ -6730,14 +6768,13 @@ var StateManager = class {
6730
6768
  /**
6731
6769
  * @param tenantId `config.tenant.id` — recorded on the state row for
6732
6770
  * diagnostics; not part of the row key.
6733
- * @param env Cloudflare environment name; selects the
6734
- * `tamer-state-{env}` D1 database.
6771
+ * @param env Cloudflare environment name; included in the D1 row key
6772
+ * (`cfi_state:{env}:{stackName}`) for isolation within the
6773
+ * shared account-scoped `tamer-state` database.
6735
6774
  * @param stackName Stack identity (`config.stack.name ?? tenant.slug`).
6736
- * The state row in D1 is keyed `cfi_state:{stackName}`,
6737
- * so multiple stacks coexist in one env D1 without
6738
- * clobbering each other. Defaults to `"default"` —
6739
- * unit tests that synthesize a StateManager without
6740
- * a config get a stable key without extra plumbing.
6775
+ * Combined with env to form the D1 row key, so multiple
6776
+ * stacks and multiple envs coexist in one D1 without
6777
+ * clobbering each other. Defaults to `"default"`.
6741
6778
  */
6742
6779
  constructor(tenantId, env, stackName = DEFAULT_STACK_NAME) {
6743
6780
  this.tenantId = tenantId;
@@ -6755,11 +6792,10 @@ var StateManager = class {
6755
6792
  this.baselineRevision = this.state.revision ?? 0;
6756
6793
  return;
6757
6794
  }
6758
- const name = tamerStateDatabaseName(this.env);
6759
- const uuid$1 = await findTamerStateDatabaseUuid(api, this.env);
6760
- if (!uuid$1) throw new Error(`Tamer state database "${name}" not found. Run: tamer bootstrap --env ${this.env}`);
6795
+ const uuid$1 = await findTamerStateDatabaseUuid(api);
6796
+ if (!uuid$1) throw new Error(`Tamer state database "tamer-state" not found. Run: tamer bootstrap --env ${this.env}`);
6761
6797
  this.tamerStateDbUuid = uuid$1;
6762
- const rowKey = stateRowKey(this.stackName);
6798
+ const rowKey = stateRowKey(this.env, this.stackName);
6763
6799
  const { rows } = await api.d1Query(uuid$1, `SELECT v FROM tamer_kv WHERE k = ?`, [rowKey]);
6764
6800
  if (rows.length === 0) {
6765
6801
  this.state = createEmptyCfiState(this.tenantId, this.env);
@@ -6951,7 +6987,7 @@ var StateManager = class {
6951
6987
  return;
6952
6988
  }
6953
6989
  if (!this.dirty || !this.state || !this.tamerStateDbUuid) return;
6954
- const rowKey = stateRowKey(this.stackName);
6990
+ const rowKey = stateRowKey(this.env, this.stackName);
6955
6991
  const { rows } = await api.d1Query(this.tamerStateDbUuid, `SELECT v FROM tamer_kv WHERE k = ?`, [rowKey]);
6956
6992
  let remoteRev = 0;
6957
6993
  if (rows.length > 0) {
@@ -7333,7 +7369,8 @@ function namingFromConfig(config$1) {
7333
7369
  //#endregion
7334
7370
  //#region src/core/secrets/SecretsVault.ts
7335
7371
  /**
7336
- * Encrypted secrets vault backed by `tamer-secrets-{env}` D1.
7372
+ * Encrypted secrets vault backed by account-scoped `tamer-secrets` D1.
7373
+ * Each env's secrets are isolated by row key: `{env}:{secretName}`.
7337
7374
  * Stores ciphertext only — never plaintext.
7338
7375
  */
7339
7376
  var SecretsVault = class {
@@ -7343,10 +7380,19 @@ var SecretsVault = class {
7343
7380
  this.env = env;
7344
7381
  this.databaseId = databaseId;
7345
7382
  }
7383
+ /** Convert a logical secret name to its D1 row key: `{env}:{name}`. */
7384
+ key(name) {
7385
+ return secretRowKey(this.env, name);
7386
+ }
7387
+ /** Reverse: strip the `{env}:` prefix from a D1 row key. */
7388
+ unkey(rowKey) {
7389
+ const prefix = `${this.env}:`;
7390
+ return rowKey.startsWith(prefix) ? rowKey.slice(prefix.length) : rowKey;
7391
+ }
7346
7392
  async dbId() {
7347
7393
  if (this.databaseId) return this.databaseId;
7348
- const uuid$1 = await findTamerSecretsDatabaseUuid(this.api, this.env);
7349
- if (!uuid$1) throw new Error(`secrets vault not provisioned for env "${this.env}" (expected D1 ${tamerSecretsDatabaseName(this.env)}); run tamer bootstrap`);
7394
+ const uuid$1 = await findTamerSecretsDatabaseUuid(this.api);
7395
+ if (!uuid$1) throw new Error(`secrets vault not provisioned (expected D1 "tamer-secrets"); run tamer bootstrap`);
7350
7396
  this.databaseId = uuid$1;
7351
7397
  return uuid$1;
7352
7398
  }
@@ -7354,6 +7400,7 @@ var SecretsVault = class {
7354
7400
  const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
7355
7401
  const updatedBy = options?.updatedBy;
7356
7402
  const db = await this.dbId();
7403
+ const key = this.key(name);
7357
7404
  await this.api.d1Query(db, `INSERT INTO secrets (
7358
7405
  name, ciphertext, iv, wrapped_dek, dek_iv, value_hash, updated_at, updated_by
7359
7406
  ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
@@ -7365,7 +7412,7 @@ var SecretsVault = class {
7365
7412
  value_hash = excluded.value_hash,
7366
7413
  updated_at = excluded.updated_at,
7367
7414
  updated_by = excluded.updated_by`, [
7368
- name,
7415
+ key,
7369
7416
  blobParam(encrypted.ciphertext),
7370
7417
  blobParam(encrypted.iv),
7371
7418
  blobParam(encrypted.wrappedDek),
@@ -7376,7 +7423,7 @@ var SecretsVault = class {
7376
7423
  ]);
7377
7424
  await this.api.d1Query(db, `INSERT INTO secret_history (name, value_hash, updated_at, updated_by)
7378
7425
  VALUES (?, ?, ?, ?)`, [
7379
- name,
7426
+ key,
7380
7427
  valueHash,
7381
7428
  updatedAt,
7382
7429
  updatedBy ?? null
@@ -7391,24 +7438,24 @@ var SecretsVault = class {
7391
7438
  LIMIT -1 OFFSET ?
7392
7439
  )
7393
7440
  )`, [
7394
- name,
7395
- name,
7441
+ key,
7442
+ key,
7396
7443
  SECRET_HISTORY_CAP
7397
7444
  ]);
7398
7445
  }
7399
7446
  async get(name) {
7400
7447
  const db = await this.dbId();
7401
7448
  const { rows } = await this.api.d1Query(db, `SELECT name, ciphertext, iv, wrapped_dek, dek_iv, value_hash, updated_at, updated_by
7402
- FROM secrets WHERE name = ?`, [name]);
7449
+ FROM secrets WHERE name = ?`, [this.key(name)]);
7403
7450
  if (rows.length === 0) return void 0;
7404
- return rowToVaultSecret(rows[0]);
7451
+ return rowToVaultSecret(rows[0], this.env);
7405
7452
  }
7406
7453
  async list() {
7407
7454
  const db = await this.dbId();
7408
7455
  const { rows } = await this.api.d1Query(db, `SELECT name, value_hash, updated_at, updated_by
7409
- FROM secrets ORDER BY name`);
7456
+ FROM secrets WHERE name LIKE ? ORDER BY name`, [`${this.env}:%`]);
7410
7457
  return rows.map((row) => ({
7411
- name: String(row.name),
7458
+ name: this.unkey(String(row.name)),
7412
7459
  valueHash: row.value_hash,
7413
7460
  updatedAt: String(row.updated_at),
7414
7461
  updatedBy: row.updated_by != null ? String(row.updated_by) : void 0
@@ -7416,7 +7463,7 @@ var SecretsVault = class {
7416
7463
  }
7417
7464
  async delete(name) {
7418
7465
  const db = await this.dbId();
7419
- const { rows } = await this.api.d1Query(db, `DELETE FROM secrets WHERE name = ? RETURNING name`, [name]);
7466
+ const { rows } = await this.api.d1Query(db, `DELETE FROM secrets WHERE name = ? RETURNING name`, [this.key(name)]);
7420
7467
  return rows.length > 0;
7421
7468
  }
7422
7469
  /** Append an audit row (e.g. after `secrets get`) without changing the secret. */
@@ -7426,9 +7473,10 @@ var SecretsVault = class {
7426
7473
  const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
7427
7474
  const updatedBy = options?.updatedBy;
7428
7475
  const db = await this.dbId();
7476
+ const key = this.key(name);
7429
7477
  await this.api.d1Query(db, `INSERT INTO secret_history (name, value_hash, updated_at, updated_by)
7430
7478
  VALUES (?, ?, ?, ?)`, [
7431
- name,
7479
+ key,
7432
7480
  record$1.valueHash,
7433
7481
  updatedAt,
7434
7482
  updatedBy ?? null
@@ -7443,8 +7491,8 @@ var SecretsVault = class {
7443
7491
  LIMIT -1 OFFSET ?
7444
7492
  )
7445
7493
  )`, [
7446
- name,
7447
- name,
7494
+ key,
7495
+ key,
7448
7496
  SECRET_HISTORY_CAP
7449
7497
  ]);
7450
7498
  }
@@ -7453,18 +7501,20 @@ var SecretsVault = class {
7453
7501
  const { rows } = await this.api.d1Query(db, `SELECT name, value_hash, updated_at, updated_by
7454
7502
  FROM secret_history
7455
7503
  WHERE name = ?
7456
- ORDER BY updated_at DESC`, [name]);
7504
+ ORDER BY updated_at DESC`, [this.key(name)]);
7457
7505
  return rows.map((row) => ({
7458
- name: String(row.name),
7506
+ name: this.unkey(String(row.name)),
7459
7507
  valueHash: row.value_hash,
7460
7508
  updatedAt: String(row.updated_at),
7461
7509
  updatedBy: row.updated_by != null ? String(row.updated_by) : void 0
7462
7510
  }));
7463
7511
  }
7464
7512
  };
7465
- function rowToVaultSecret(row) {
7513
+ function rowToVaultSecret(row, env) {
7514
+ const rawName = String(row.name);
7515
+ const prefix = `${env}:`;
7466
7516
  return {
7467
- name: String(row.name),
7517
+ name: rawName.startsWith(prefix) ? rawName.slice(prefix.length) : rawName,
7468
7518
  ciphertext: blobFromRow(row.ciphertext),
7469
7519
  iv: blobFromRow(row.iv),
7470
7520
  wrappedDek: blobFromRow(row.wrapped_dek),
@@ -7512,7 +7562,7 @@ async function createSecretsContext(options) {
7512
7562
  const accountId = config$1.account_id ?? cloudflareAccountIdFromEnv();
7513
7563
  if (!accountId) throw new Error("account_id required in config or CLOUDFLARE_ACCOUNT_ID env var");
7514
7564
  const api = new CFApiClient(accountId);
7515
- const vault = new SecretsVault(api, env, await ensureTamerSecretsDatabase(api, env));
7565
+ const vault = new SecretsVault(api, env, await ensureTamerSecretsDatabase(api));
7516
7566
  const state = new StateManager(config$1.tenant.id, env, stackNameForConfig(config$1));
7517
7567
  await state.hydrate(api);
7518
7568
  const masterKey = readMasterKeyFromEnv(env);
@@ -7593,7 +7643,7 @@ function displayPathFromCwd(absOrRel) {
7593
7643
  async function createDeploySecretsResources(api, env) {
7594
7644
  const resolvedEnv = resolveSecretsEnv(env);
7595
7645
  return {
7596
- vault: new SecretsVault(api, resolvedEnv, await ensureTamerSecretsDatabase(api, resolvedEnv)),
7646
+ vault: new SecretsVault(api, resolvedEnv, await ensureTamerSecretsDatabase(api)),
7597
7647
  masterKey: readMasterKeyFromEnv(resolvedEnv)
7598
7648
  };
7599
7649
  }
@@ -7606,8 +7656,8 @@ async function runSecretsInit(options) {
7606
7656
  if (!accountId) throw new Error("account_id required in config or CLOUDFLARE_ACCOUNT_ID env var");
7607
7657
  const masterKey = generateMasterKey();
7608
7658
  const varName = masterKeyEnvVarName(env);
7609
- const uuid$1 = await ensureTamerSecretsDatabase(new CFApiClient(accountId), env);
7610
- console.log(`Secrets vault ready: D1 uuid=${uuid$1} name=${tamerSecretsDatabaseName(env)}`);
7659
+ const uuid$1 = await ensureTamerSecretsDatabase(new CFApiClient(accountId));
7660
+ console.log(`Secrets vault ready: D1 uuid=${uuid$1} name=${tamerSecretsDatabaseName()}`);
7611
7661
  console.log("");
7612
7662
  console.log(`Generated master key for env "${env}" (store in two durable places — CI + password manager):`);
7613
7663
  console.log("");
@@ -8654,14 +8704,14 @@ async function main() {
8654
8704
  try {
8655
8705
  switch (command) {
8656
8706
  case "bootstrap":
8657
- await import("./bootstrap-CV6OT-c9.mjs").then((m) => m.runBootstrap(parseBootstrapArgs(rest)));
8707
+ await import("./bootstrap-C7CZYHzb.mjs").then((m) => m.runBootstrap(parseBootstrapArgs(rest)));
8658
8708
  break;
8659
8709
  case "sync":
8660
- await import("./sync-YKZ5HD8v.mjs").then((m) => m.runSync(parseSyncArgs(rest)));
8710
+ await import("./sync-DEudPgQc.mjs").then((m) => m.runSync(parseSyncArgs(rest)));
8661
8711
  break;
8662
8712
  case "apply": {
8663
8713
  const a = parseApplyArgs(rest);
8664
- await import("./apply-BsVQ9cbK.mjs").then((m) => m.runApply({
8714
+ await import("./apply-B2wMY64Q.mjs").then((m) => m.runApply({
8665
8715
  env: a.env,
8666
8716
  addShard: a.addShard,
8667
8717
  configPath: a.configPath,
@@ -8673,11 +8723,11 @@ async function main() {
8673
8723
  break;
8674
8724
  }
8675
8725
  case "dev":
8676
- await import("./dev-Bug5l5OZ.mjs").then((m) => m.runDev(parseDevArgs(rest)));
8726
+ await import("./dev-BiPXBOKk.mjs").then((m) => m.runDev(parseDevArgs(rest)));
8677
8727
  break;
8678
8728
  case "deploy": {
8679
8729
  const d = parseDeployArgs(rest);
8680
- await import("./deploy-dNygCucr.mjs").then((m) => m.runDeploy({
8730
+ await import("./deploy-C4Mi_qwz.mjs").then((m) => m.runDeploy({
8681
8731
  worker: d.worker,
8682
8732
  env: d.env,
8683
8733
  configPath: d.configPath,
@@ -8686,23 +8736,23 @@ async function main() {
8686
8736
  break;
8687
8737
  }
8688
8738
  case "migrate":
8689
- await import("./migrate-DWyUVN1I.mjs").then((m) => m.runMigrate(parseMigrateArgs(rest)));
8739
+ await import("./migrate-36WDEaFz.mjs").then((m) => m.runMigrate(parseMigrateArgs(rest)));
8690
8740
  break;
8691
8741
  case "types":
8692
- await import("./types-CADr4Kck.mjs").then((m) => m.runTypes(parseTypesArgs(rest)));
8742
+ await import("./types-BQajHdJb.mjs").then((m) => m.runTypes(parseTypesArgs(rest)));
8693
8743
  break;
8694
8744
  case "status":
8695
- await import("./status-PlMHsDzT.mjs").then((m) => m.runStatus(parseStatusArgs(rest)));
8745
+ await import("./status-DaaOPBEf.mjs").then((m) => m.runStatus(parseStatusArgs(rest)));
8696
8746
  break;
8697
8747
  case "events":
8698
- await import("./events-B7Lencm8.mjs").then((m) => m.runEvents(parseEventsArgs(rest)));
8748
+ await import("./events-D9kQWwH8.mjs").then((m) => m.runEvents(parseEventsArgs(rest)));
8699
8749
  break;
8700
8750
  case "drift":
8701
- exitStatus = await import("./drift-DENAf1Oe.mjs").then((m) => m.runDrift(parseDriftArgs(rest)));
8751
+ exitStatus = await import("./drift-DqMtlwkg.mjs").then((m) => m.runDrift(parseDriftArgs(rest)));
8702
8752
  break;
8703
8753
  case "plan": {
8704
8754
  const p = parsePlanArgs(rest);
8705
- exitStatus = await import("./plan-Blxn-yKr.mjs").then((m) => m.runPlan({
8755
+ exitStatus = await import("./plan-k0jLGYyw.mjs").then((m) => m.runPlan({
8706
8756
  env: p.env,
8707
8757
  configPath: p.configPath,
8708
8758
  json: p.json,
@@ -8714,14 +8764,14 @@ async function main() {
8714
8764
  break;
8715
8765
  }
8716
8766
  case "import":
8717
- await import("./import-Ciq9MN3v.mjs").then((m) => m.runImport(parseImportArgs(rest)));
8767
+ await import("./import-DHmLtue3.mjs").then((m) => m.runImport(parseImportArgs(rest)));
8718
8768
  break;
8719
8769
  case "doctor":
8720
- exitStatus = await import("./doctor-BwuEPYM6.mjs").then((m) => m.runDoctor(parseDoctorArgs(rest)));
8770
+ exitStatus = await import("./doctor-DDwsA2V6.mjs").then((m) => m.runDoctor(parseDoctorArgs(rest)));
8721
8771
  break;
8722
8772
  case "provision-tenant": {
8723
8773
  const p = parseProvisionTenantArgs(rest);
8724
- await import("./provision-tenant-BHDWTC2U.mjs").then((m) => m.runProvisionTenant({
8774
+ await import("./provision-tenant-BjFpVm-y.mjs").then((m) => m.runProvisionTenant({
8725
8775
  env: p.env,
8726
8776
  product: p.product,
8727
8777
  workspace: p.workspace,
@@ -8738,7 +8788,7 @@ async function main() {
8738
8788
  }
8739
8789
  case "destroy-tenant": {
8740
8790
  const t = parseDestroyTenantArgs(rest);
8741
- await import("./destroy-tenant-hyEb1gEz.mjs").then((m) => m.runDestroyTenant({
8791
+ await import("./destroy-tenant-DL99EoRZ.mjs").then((m) => m.runDestroyTenant({
8742
8792
  env: t.env,
8743
8793
  product: t.product,
8744
8794
  workspace: t.workspace,
@@ -8751,7 +8801,7 @@ async function main() {
8751
8801
  }
8752
8802
  case "destroy": {
8753
8803
  const d = parseDestroyArgs(rest);
8754
- await import("./destroy-C0cKkpWe.mjs").then((m) => m.runDestroy({
8804
+ await import("./destroy-DDVWxl7U.mjs").then((m) => m.runDestroy({
8755
8805
  env: d.env,
8756
8806
  force: d.force,
8757
8807
  skipWorkers: d.skipWorkers,
@@ -8766,12 +8816,12 @@ async function main() {
8766
8816
  case "wfp": {
8767
8817
  const [sub, ...wfpRest] = rest;
8768
8818
  if (sub === "put") {
8769
- const { parseWfpPutArgs, runWfpPut } = await import("./wfp-put-CVw8cloM.mjs");
8819
+ const { parseWfpPutArgs, runWfpPut } = await import("./wfp-put-DX_bH-s7.mjs");
8770
8820
  await runWfpPut(parseWfpPutArgs(wfpRest));
8771
8821
  break;
8772
8822
  }
8773
8823
  if (sub === "delete") {
8774
- const { parseWfpDeleteArgs, runWfpDelete } = await import("./wfp-delete-CQc9tveU.mjs");
8824
+ const { parseWfpDeleteArgs, runWfpDelete } = await import("./wfp-delete-DsfqSBxt.mjs");
8775
8825
  await runWfpDelete(parseWfpDeleteArgs(wfpRest));
8776
8826
  break;
8777
8827
  }
@@ -8871,5 +8921,5 @@ Environment variables (same as Wrangler):
8871
8921
  main();
8872
8922
 
8873
8923
  //#endregion
8874
- export { rewriteIntraStackServiceTargets as A, getWorkers as B, tamerStateDatabaseName as C, mergedWorkerConfigForEnv as D, mergeWorkerConfigForResourcePick as E, ensureTamerSecretsDatabase as F, tamerSecretsDatabaseName as I, CFApiClient as L, wranglerConfigCliArgs as M, effectiveDispatchNamespaceName as N, resolveDeployedWorkerName as O, isEphemeralEnv as P, cloudflareAccountIdFromEnv as R, ensureTamerStateDatabase as S, buildIntraStackScriptNameMap as T, loadConfig as V, tenantDispatchScriptName as _, reconcileSecrets as a, createEmptyCfiState as b, vaultReaderFromMap as c, requiredSecretsForWorker as d, fetchStackImports as f, parseTenantShardRoles as g, StateManager as h, pushSecretsForDeploy as i, resolveReferencesInString as j, resolveWorkerConfig as k, createDeploySecretsResources as l, scanConfigForImports as m, parseSecretsArgs as n, secretsDrift as o, importedStackNames as p, runSecrets as r, secretsPlanItems as s, SECRETS_USAGE as t, namingFromConfig as u, tenantShardDatabaseName as v, stackNameForConfig as w, destroyTamerStateDatabase as x, tenantStateKey as y, cloudflareApiTokenFromEnv as z };
8924
+ export { rewriteIntraStackServiceTargets as A, cloudflareApiTokenFromEnv as B, tamerStateDatabaseName as C, mergedWorkerConfigForEnv as D, mergeWorkerConfigForResourcePick as E, deleteEnvSecretRows as F, loadConfig as H, ensureTamerSecretsDatabase as I, tamerSecretsDatabaseName as L, wranglerConfigCliArgs as M, effectiveDispatchNamespaceName as N, resolveDeployedWorkerName as O, isEphemeralEnv as P, CFApiClient as R, ensureTamerStateDatabase as S, buildIntraStackScriptNameMap as T, getWorkers as V, tenantDispatchScriptName as _, reconcileSecrets as a, createEmptyCfiState as b, vaultReaderFromMap as c, requiredSecretsForWorker as d, fetchStackImports as f, parseTenantShardRoles as g, StateManager as h, pushSecretsForDeploy as i, resolveReferencesInString as j, resolveWorkerConfig as k, createDeploySecretsResources as l, scanConfigForImports as m, parseSecretsArgs as n, secretsDrift as o, importedStackNames as p, runSecrets as r, secretsPlanItems as s, SECRETS_USAGE as t, namingFromConfig as u, tenantShardDatabaseName as v, stackNameForConfig as w, deleteEnvStateRows as x, tenantStateKey as y, cloudflareAccountIdFromEnv as z };
8875
8925
  //# sourceMappingURL=tamer.mjs.map