create-svc 0.1.70 → 0.1.72

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-svc",
3
- "version": "0.1.70",
3
+ "version": "0.1.72",
4
4
  "description": "Local microservice bootstrap CLI for Cloud Run and Workers services with Neon-backed data.",
5
5
  "module": "index.ts",
6
6
  "type": "module",
@@ -17,6 +17,7 @@ import {
17
17
  formatError,
18
18
  gcloud,
19
19
  ensureProductionDomainMapping,
20
+ readVaultField,
20
21
  requireCommand,
21
22
  requireGcloudAuth,
22
23
  resolveDeploymentTarget,
@@ -347,6 +348,7 @@ async function runSdk(args: string[]) {
347
348
  const [subcommand] = args;
348
349
  if (subcommand === "publish") {
349
350
  requireCommand("buf");
351
+ ensureBufAuth();
350
352
  run("buf", ["push"]);
351
353
  const published = resolvePublishedSdk();
352
354
  await writeSdkMode("remote", published);
@@ -371,6 +373,7 @@ async function runSdk(args: string[]) {
371
373
 
372
374
  if (subcommand === "use-remote") {
373
375
  requireCommand("buf");
376
+ ensureBufAuth();
374
377
  const published = resolvePublishedSdk();
375
378
  await writeSdkMode("remote", published);
376
379
  return `Remote Buf SDK recorded for consumers: ${bufModule()}@${published.commit}`;
@@ -447,7 +450,17 @@ async function writeSdkMode(mode: "local" | "remote", published?: PublishedSdk)
447
450
  }
448
451
 
449
452
  function bufModule() {
450
- return `buf.build/anmho/${config.serviceName}`;
453
+ return config.buf.module || `buf.build/anmho/${config.serviceName}`;
454
+ }
455
+
456
+ function ensureBufAuth() {
457
+ const token =
458
+ process.env.BUF_TOKEN?.trim() ||
459
+ readVaultField(config.buf.vaultMount, config.buf.vaultPath, ["BUF_TOKEN", "buf.api_token", "buf_token", "api_token", "token"]);
460
+ if (!token) {
461
+ return;
462
+ }
463
+ run("buf", ["registry", "login", "buf.build", "--token-stdin"], { input: `${token}\n` });
451
464
  }
452
465
 
453
466
  async function resolveLocalSdkPath() {
@@ -46,6 +46,11 @@ export const config = {
46
46
  vaultMount: vault.mount || "secret",
47
47
  vaultPath: vault.temporal_path || "prod/providers/temporal",
48
48
  },
49
+ buf: {
50
+ module: serviceConfig.buf?.module || `buf.build/anmho/${serviceConfig.service_id}`,
51
+ vaultMount: vault.mount || "secret",
52
+ vaultPath: vault.buf_path || "prod/providers/buf",
53
+ },
49
54
  neon: {
50
55
  projectId: neon.project_id,
51
56
  baseBranchId: neon.base_branch_id,
@@ -589,7 +589,7 @@ function renderTemporalMtlsEnv(temporal: ReturnType<typeof resolveTemporalRuntim
589
589
  .join("\n");
590
590
  }
591
591
 
592
- function readVaultField(mount: string, path: string, fields: string[]) {
592
+ export function readVaultField(mount: string, path: string, fields: string[]) {
593
593
  const vault = Bun.which("vault");
594
594
  if (!vault || !path) {
595
595
  return "";
@@ -37,6 +37,7 @@ test("service sdk publish pushes the named Buf module and selects remote SDK mod
37
37
  const generatedRoot = join(root, "sdk-proof");
38
38
  const fakeBin = join(root, "bin");
39
39
  const bufLog = join(root, "buf.log");
40
+ const tokenLog = join(root, "buf-token.log");
40
41
 
41
42
  await scaffoldProject(baseConfig(generatedRoot));
42
43
  await mkdir(join(generatedRoot, "node_modules"));
@@ -46,10 +47,19 @@ test("service sdk publish pushes the named Buf module and selects remote SDK mod
46
47
  [
47
48
  "#!/bin/sh",
48
49
  `echo "$@" >> "${bufLog}"`,
50
+ 'if [ "$1 $2 $3 $4" = "registry login buf.build --token-stdin" ]; then',
51
+ ` cat > "${tokenLog}"`,
52
+ " exit 0",
53
+ "fi",
49
54
  'if [ "$1 $2 $3 $4" = "registry module commit list" ]; then',
50
55
  ' printf \'{"commits":[{"name":"buf.build/anmho/sdk-proof:commit-123","digest":"b5:abc123","create_time":"2026-05-25T12:00:00Z"}]}\'',
56
+ " exit 0",
51
57
  "fi",
52
- "exit 0",
58
+ 'if [ "$1" = "push" ]; then',
59
+ " exit 0",
60
+ "fi",
61
+ "echo unexpected buf command: $@ >&2",
62
+ "exit 1",
53
63
  "",
54
64
  ].join("\n")
55
65
  );
@@ -57,16 +67,19 @@ test("service sdk publish pushes the named Buf module and selects remote SDK mod
57
67
 
58
68
  const result = Bun.spawnSync(["bun", join(import.meta.dir, "..", "..", "..", "index.ts"), "sdk", "publish"], {
59
69
  cwd: generatedRoot,
60
- env: { ...process.env, PATH: `${fakeBin}:${process.env.PATH ?? ""}` },
70
+ env: { ...process.env, BUF_TOKEN: "test-token", PATH: `${fakeBin}:${process.env.PATH ?? ""}` },
61
71
  stdout: "pipe",
62
72
  stderr: "pipe",
63
73
  });
64
74
 
65
75
  expect(result.success, [result.stdout.toString(), result.stderr.toString()].join("\n")).toBeTrue();
66
76
  expect(result.stdout.toString()).toContain("recorded for consumers");
77
+ expect(result.stdout.toString()).not.toContain("test-token");
78
+ expect(result.stderr.toString()).not.toContain("test-token");
67
79
  expect((await readFile(bufLog, "utf8")).trim()).toBe(
68
- ["push", "registry module commit list buf.build/anmho/sdk-proof --format json --page-size 1"].join("\n")
80
+ ["registry login buf.build --token-stdin", "push", "registry module commit list buf.build/anmho/sdk-proof --format json --page-size 1"].join("\n")
69
81
  );
82
+ expect((await readFile(tokenLog, "utf8")).trim()).toBe("test-token");
70
83
  const sdkState = JSON.parse(await Bun.file(join(generatedRoot, ".service", "sdk.json")).text());
71
84
  expect(sdkState).toMatchObject({
72
85
  mode: "remote",
@@ -62,6 +62,28 @@ test("resolveTemporalRuntimeConfigValues reads self-hosted mTLS config from Vaul
62
62
  });
63
63
  });
64
64
 
65
+ test("resolveTemporalRuntimeConfigValues renders configured mTLS secret names without raw credentials", () => {
66
+ const resolved = resolveTemporalRuntimeConfigValues(
67
+ { ...baseConfig, address: "temporal-grpc.anmho.com:7233" },
68
+ {},
69
+ () => ({
70
+ namespace: "default",
71
+ })
72
+ );
73
+
74
+ expect(resolved).toMatchObject({
75
+ enabled: true,
76
+ address: "temporal-grpc.anmho.com:7233",
77
+ namespace: "default",
78
+ tlsCaCertSecretName: "orders-temporal-ca-cert",
79
+ tlsCertSecretName: "orders-temporal-client-cert",
80
+ tlsKeySecretName: "orders-temporal-client-key",
81
+ tlsCaCert: "",
82
+ tlsCert: "",
83
+ tlsKey: "",
84
+ });
85
+ });
86
+
65
87
  test("resolveTemporalRuntimeConfigValues prefers explicit environment overrides", () => {
66
88
  const resolved = resolveTemporalRuntimeConfigValues(
67
89
  baseConfig,
@@ -75,6 +75,13 @@ export function resolveTemporalRuntimeConfigValues(
75
75
  env.TEMPORAL_TLS_CERT_SECRET?.trim() || (tlsCert ? config.tlsCertSecretName || `${config.taskQueue}-temporal-client-cert` : "");
76
76
  const tlsKeySecretName =
77
77
  env.TEMPORAL_TLS_KEY_SECRET?.trim() || (tlsKey ? config.tlsKeySecretName || `${config.taskQueue}-temporal-client-key` : "");
78
+ const configuredTLSSecretNames = Boolean(config.tlsCaCertSecretName && config.tlsCertSecretName && config.tlsKeySecretName);
79
+ const shouldRenderTLSSecretNames = Boolean(tlsCaCert || (!apiKey && configuredTLSSecretNames));
80
+ const resolvedTLSSecretNames = {
81
+ ca: shouldRenderTLSSecretNames ? tlsCaCertSecretName || config.tlsCaCertSecretName || "" : "",
82
+ cert: shouldRenderTLSSecretNames ? tlsCertSecretName || config.tlsCertSecretName || "" : "",
83
+ key: shouldRenderTLSSecretNames ? tlsKeySecretName || config.tlsKeySecretName || "" : "",
84
+ };
78
85
 
79
86
  if (isLocalTemporalAddress(address)) {
80
87
  throw new Error(
@@ -95,7 +102,7 @@ export function resolveTemporalRuntimeConfigValues(
95
102
  `Temporal mTLS is partially configured; set TEMPORAL_TLS_CA_CERT, TEMPORAL_TLS_CERT, and TEMPORAL_TLS_KEY together in env or Vault at ${config.vaultMount}/${config.vaultPath}`
96
103
  );
97
104
  }
98
- if (!apiKey && !tlsCaCert) {
105
+ if (!apiKey && !apiKeySecretName && !tlsCaCert && !configuredTLSSecretNames) {
99
106
  throw new Error(
100
107
  `Temporal is enabled but no credentials were found; set TEMPORAL_API_KEY or TEMPORAL_TLS_CA_CERT/TEMPORAL_TLS_CERT/TEMPORAL_TLS_KEY in env or Vault at ${config.vaultMount}/${config.vaultPath}`
101
108
  );
@@ -108,9 +115,9 @@ export function resolveTemporalRuntimeConfigValues(
108
115
  taskQueue,
109
116
  apiKeySecretName,
110
117
  apiKey,
111
- tlsCaCertSecretName,
112
- tlsCertSecretName,
113
- tlsKeySecretName,
118
+ tlsCaCertSecretName: resolvedTLSSecretNames.ca,
119
+ tlsCertSecretName: resolvedTLSSecretNames.cert,
120
+ tlsKeySecretName: resolvedTLSSecretNames.key,
114
121
  tlsCaCert,
115
122
  tlsCert,
116
123
  tlsKey,
@@ -70,7 +70,8 @@
70
70
  "cloudflare_path": "prod/providers/cloudflare",
71
71
  "grafana_path": "prod/providers/grafana",
72
72
  "clerk_m2m_path": "prod/providers/clerk-m2m",
73
- "temporal_path": "prod/providers/temporal"
73
+ "temporal_path": "prod/providers/temporal",
74
+ "buf_path": "prod/providers/buf"
74
75
  }
75
76
  },
76
77