@caelo-cms/provisioning 0.10.53 → 0.10.57

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 (244) hide show
  1. package/dist/agent-db.js +272 -128
  2. package/dist/audit-job-setup.d.ts +69 -0
  3. package/dist/audit-job-setup.d.ts.map +1 -0
  4. package/dist/audit-job-setup.js +317 -0
  5. package/dist/audit-job-setup.js.map +1 -0
  6. package/dist/caddy.d.ts +9 -0
  7. package/dist/caddy.d.ts.map +1 -1
  8. package/dist/caddy.js +38 -0
  9. package/dist/caddy.js.map +1 -1
  10. package/dist/cli-routing.js +1 -1
  11. package/dist/cli-routing.js.map +1 -1
  12. package/dist/cli.js +36 -9
  13. package/dist/cli.js.map +1 -1
  14. package/dist/compose.js +5 -0
  15. package/dist/compose.js.map +1 -1
  16. package/dist/converge-checkpoint.d.ts +66 -0
  17. package/dist/converge-checkpoint.d.ts.map +1 -0
  18. package/dist/converge-checkpoint.js +61 -0
  19. package/dist/converge-checkpoint.js.map +1 -0
  20. package/dist/converge-job-gcp.d.ts +46 -0
  21. package/dist/converge-job-gcp.d.ts.map +1 -0
  22. package/dist/converge-job-gcp.js +368 -0
  23. package/dist/converge-job-gcp.js.map +1 -0
  24. package/dist/converge-job-setup.d.ts +62 -0
  25. package/dist/converge-job-setup.d.ts.map +1 -0
  26. package/dist/converge-job-setup.js +228 -0
  27. package/dist/converge-job-setup.js.map +1 -0
  28. package/dist/converge-job.d.ts +141 -0
  29. package/dist/converge-job.d.ts.map +1 -0
  30. package/dist/converge-job.js +325 -0
  31. package/dist/converge-job.js.map +1 -0
  32. package/dist/gcp-names.d.ts +25 -1
  33. package/dist/gcp-names.d.ts.map +1 -1
  34. package/dist/gcp-names.js +36 -0
  35. package/dist/gcp-names.js.map +1 -1
  36. package/dist/index.d.ts +2 -0
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +2 -0
  39. package/dist/index.js.map +1 -1
  40. package/dist/infra-contract.d.ts +1 -1
  41. package/dist/infra-contract.d.ts.map +1 -1
  42. package/dist/infra-contract.js +28 -1
  43. package/dist/infra-contract.js.map +1 -1
  44. package/dist/install-job.d.ts +11 -3
  45. package/dist/install-job.d.ts.map +1 -1
  46. package/dist/install-job.js +22 -12
  47. package/dist/install-job.js.map +1 -1
  48. package/dist/lifecycle.d.ts +13 -1
  49. package/dist/lifecycle.d.ts.map +1 -1
  50. package/dist/lifecycle.js +115 -58
  51. package/dist/lifecycle.js.map +1 -1
  52. package/dist/operator-access.d.ts.map +1 -1
  53. package/dist/operator-access.js +13 -3
  54. package/dist/operator-access.js.map +1 -1
  55. package/dist/private-file.d.ts +26 -0
  56. package/dist/private-file.d.ts.map +1 -0
  57. package/dist/private-file.js +49 -0
  58. package/dist/private-file.js.map +1 -0
  59. package/dist/release-contract.d.ts +3 -2
  60. package/dist/release-contract.d.ts.map +1 -1
  61. package/dist/release-contract.js +8 -2
  62. package/dist/release-contract.js.map +1 -1
  63. package/dist/release-manifest.d.ts +2 -0
  64. package/dist/release-manifest.d.ts.map +1 -1
  65. package/dist/release-manifest.js.map +1 -1
  66. package/dist/remote-mcp-edge.d.ts +114 -0
  67. package/dist/remote-mcp-edge.d.ts.map +1 -0
  68. package/dist/remote-mcp-edge.js +116 -0
  69. package/dist/remote-mcp-edge.js.map +1 -0
  70. package/dist/remote-mcp.d.ts +117 -0
  71. package/dist/remote-mcp.d.ts.map +1 -0
  72. package/dist/remote-mcp.js +379 -0
  73. package/dist/remote-mcp.js.map +1 -0
  74. package/dist/runtime-secrets.d.ts +12 -0
  75. package/dist/runtime-secrets.d.ts.map +1 -1
  76. package/dist/runtime-secrets.js +32 -4
  77. package/dist/runtime-secrets.js.map +1 -1
  78. package/dist/seal-key-rotation.d.ts +38 -0
  79. package/dist/seal-key-rotation.d.ts.map +1 -0
  80. package/dist/seal-key-rotation.js +206 -0
  81. package/dist/seal-key-rotation.js.map +1 -0
  82. package/dist/stack-contract.d.ts +175 -3
  83. package/dist/stack-contract.d.ts.map +1 -1
  84. package/dist/stack-contract.js +183 -3
  85. package/dist/stack-contract.js.map +1 -1
  86. package/dist/stack-converge.d.ts +38 -1
  87. package/dist/stack-converge.d.ts.map +1 -1
  88. package/dist/stack-converge.js +74 -4
  89. package/dist/stack-converge.js.map +1 -1
  90. package/dist/state-lock-lease.d.ts +142 -0
  91. package/dist/state-lock-lease.d.ts.map +1 -0
  92. package/dist/state-lock-lease.js +347 -0
  93. package/dist/state-lock-lease.js.map +1 -0
  94. package/dist/state-store.d.ts +66 -9
  95. package/dist/state-store.d.ts.map +1 -1
  96. package/dist/state-store.js +249 -30
  97. package/dist/state-store.js.map +1 -1
  98. package/dist/tar-entries.d.ts.map +1 -1
  99. package/dist/tar-entries.js +84 -9
  100. package/dist/tar-entries.js.map +1 -1
  101. package/dist/upgrade/app-roll.d.ts +36 -7
  102. package/dist/upgrade/app-roll.d.ts.map +1 -1
  103. package/dist/upgrade/app-roll.js +88 -19
  104. package/dist/upgrade/app-roll.js.map +1 -1
  105. package/dist/upgrade/audit-job-roll.d.ts +38 -0
  106. package/dist/upgrade/audit-job-roll.d.ts.map +1 -0
  107. package/dist/upgrade/audit-job-roll.js +43 -0
  108. package/dist/upgrade/audit-job-roll.js.map +1 -0
  109. package/dist/upgrade/converge.d.ts.map +1 -1
  110. package/dist/upgrade/converge.js +141 -8
  111. package/dist/upgrade/converge.js.map +1 -1
  112. package/dist/upgrade/gcp-lookup.d.ts +27 -10
  113. package/dist/upgrade/gcp-lookup.d.ts.map +1 -1
  114. package/dist/upgrade/gcp-lookup.js +46 -7
  115. package/dist/upgrade/gcp-lookup.js.map +1 -1
  116. package/dist/upgrade/record-rolled.d.ts +40 -0
  117. package/dist/upgrade/record-rolled.d.ts.map +1 -0
  118. package/dist/upgrade/record-rolled.js +46 -0
  119. package/dist/upgrade/record-rolled.js.map +1 -0
  120. package/dist/upgrade/upgrade.d.ts +45 -1
  121. package/dist/upgrade/upgrade.d.ts.map +1 -1
  122. package/dist/upgrade/upgrade.js +60 -17
  123. package/dist/upgrade/upgrade.js.map +1 -1
  124. package/dist/upgrader-assess.d.ts +15 -1
  125. package/dist/upgrader-assess.d.ts.map +1 -1
  126. package/dist/upgrader-assess.js +36 -6
  127. package/dist/upgrader-assess.js.map +1 -1
  128. package/dist/upgrader-gcp.d.ts +15 -0
  129. package/dist/upgrader-gcp.d.ts.map +1 -1
  130. package/dist/upgrader-gcp.js +42 -7
  131. package/dist/upgrader-gcp.js.map +1 -1
  132. package/dist/upgrader-iam-preflight.d.ts +123 -0
  133. package/dist/upgrader-iam-preflight.d.ts.map +1 -0
  134. package/dist/upgrader-iam-preflight.js +414 -0
  135. package/dist/upgrader-iam-preflight.js.map +1 -0
  136. package/dist/upgrader-job.d.ts +33 -9
  137. package/dist/upgrader-job.d.ts.map +1 -1
  138. package/dist/upgrader-job.js +169 -27
  139. package/dist/upgrader-job.js.map +1 -1
  140. package/dist/upgrader-records.d.ts +58 -0
  141. package/dist/upgrader-records.d.ts.map +1 -0
  142. package/dist/upgrader-records.js +87 -0
  143. package/dist/upgrader-records.js.map +1 -0
  144. package/dist/upgrader-reporter.d.ts +3 -2
  145. package/dist/upgrader-reporter.d.ts.map +1 -1
  146. package/dist/upgrader-reporter.js +10 -2
  147. package/dist/upgrader-reporter.js.map +1 -1
  148. package/dist/upgrader-setup.d.ts +25 -3
  149. package/dist/upgrader-setup.d.ts.map +1 -1
  150. package/dist/upgrader-setup.js +132 -14
  151. package/dist/upgrader-setup.js.map +1 -1
  152. package/dist/wizards/gcp-cost.d.ts.map +1 -1
  153. package/dist/wizards/gcp-cost.js +14 -6
  154. package/dist/wizards/gcp-cost.js.map +1 -1
  155. package/dist/wizards/gcp-pulumi.d.ts +6 -0
  156. package/dist/wizards/gcp-pulumi.d.ts.map +1 -1
  157. package/dist/wizards/gcp-pulumi.js +7 -0
  158. package/dist/wizards/gcp-pulumi.js.map +1 -1
  159. package/dist/wizards/gcp.d.ts.map +1 -1
  160. package/dist/wizards/gcp.js +130 -4
  161. package/dist/wizards/gcp.js.map +1 -1
  162. package/package.json +4 -4
  163. package/src/agent/run.test.ts +15 -1
  164. package/src/audit-job-setup.test.ts +234 -0
  165. package/src/audit-job-setup.ts +360 -0
  166. package/src/caddy-redirects.docker.test.ts +19 -6
  167. package/src/caddy.test.ts +30 -0
  168. package/src/caddy.ts +43 -0
  169. package/src/cli-init-validation.test.ts +44 -0
  170. package/src/cli-routing.ts +1 -1
  171. package/src/cli.ts +40 -8
  172. package/src/compose.ts +5 -0
  173. package/src/converge-checkpoint.ts +75 -0
  174. package/src/converge-entrypoint.test.ts +213 -0
  175. package/src/converge-job-gcp.test.ts +222 -0
  176. package/src/converge-job-gcp.ts +443 -0
  177. package/src/converge-job-setup.test.ts +152 -0
  178. package/src/converge-job-setup.ts +268 -0
  179. package/src/converge-job.test.ts +486 -0
  180. package/src/converge-job.ts +542 -0
  181. package/src/gateway-env-isolation.test.ts +8 -1
  182. package/src/gcp-names.ts +43 -1
  183. package/src/gcp-url-map.test.ts +9 -1
  184. package/src/index.ts +8 -0
  185. package/src/infra-contract.test.ts +7 -4
  186. package/src/infra-contract.ts +28 -1
  187. package/src/install-job.test.ts +3 -1
  188. package/src/install-job.ts +31 -14
  189. package/src/lifecycle.ts +137 -71
  190. package/src/operator-access.test.ts +14 -0
  191. package/src/operator-access.ts +13 -3
  192. package/src/private-file.test.ts +80 -0
  193. package/src/private-file.ts +50 -0
  194. package/src/release-contract.ts +8 -2
  195. package/src/release-manifest.test.ts +42 -0
  196. package/src/release-manifest.ts +2 -0
  197. package/src/remote-mcp-edge.ts +137 -0
  198. package/src/remote-mcp.test.ts +517 -0
  199. package/src/remote-mcp.ts +460 -0
  200. package/src/runtime-secrets.test.ts +31 -6
  201. package/src/runtime-secrets.ts +41 -3
  202. package/src/seal-key-rotation.test.ts +131 -0
  203. package/src/seal-key-rotation.ts +258 -0
  204. package/src/stack-contract-parity.test.ts +20 -3
  205. package/src/stack-contract.test.ts +34 -2
  206. package/src/stack-contract.ts +305 -3
  207. package/src/stack-converge-secrets.test.ts +3 -0
  208. package/src/stack-converge.test.ts +21 -5
  209. package/src/stack-converge.ts +101 -7
  210. package/src/state-attach.test.ts +7 -1
  211. package/src/state-lock-lease.test.ts +302 -0
  212. package/src/state-lock-lease.ts +423 -0
  213. package/src/state-lock.test.ts +568 -0
  214. package/src/state-store.ts +347 -27
  215. package/src/tar-entries.test.ts +149 -7
  216. package/src/tar-entries.ts +90 -9
  217. package/src/upgrade/app-roll.ts +135 -21
  218. package/src/upgrade/audit-job-roll.ts +68 -0
  219. package/src/upgrade/converge.ts +170 -7
  220. package/src/upgrade/gcp-lookup.test.ts +80 -0
  221. package/src/upgrade/gcp-lookup.ts +65 -8
  222. package/src/upgrade/record-rolled.test.ts +105 -0
  223. package/src/upgrade/record-rolled.ts +91 -0
  224. package/src/upgrade/upgrade.test.ts +279 -5
  225. package/src/upgrade/upgrade.ts +120 -24
  226. package/src/upgrader-assess.test.ts +93 -3
  227. package/src/upgrader-assess.ts +58 -9
  228. package/src/upgrader-gcp.ts +47 -8
  229. package/src/upgrader-iam-preflight.test.ts +393 -0
  230. package/src/upgrader-iam-preflight.ts +510 -0
  231. package/src/upgrader-job.test.ts +587 -15
  232. package/src/upgrader-job.ts +237 -53
  233. package/src/upgrader-records.ts +151 -0
  234. package/src/upgrader-reporter.test.ts +6 -0
  235. package/src/upgrader-reporter.ts +7 -2
  236. package/src/upgrader-setup.test.ts +4 -3
  237. package/src/upgrader-setup.ts +137 -13
  238. package/src/wizards/gcp-cost.ts +15 -6
  239. package/src/wizards/gcp-pulumi.ts +7 -0
  240. package/src/wizards/gcp.ts +162 -4
  241. package/stacks/aws/index.ts +18 -0
  242. package/stacks/azure/index.ts +18 -0
  243. package/stacks/gcp/index.ts +59 -7
  244. package/stacks/gcp-firebase/index.ts +50 -6
@@ -31,6 +31,7 @@ import {
31
31
  staticPublisherServiceAccountId,
32
32
  } from "../../dist/gcp-names.js";
33
33
  import { createSiteUrlMap } from "../../dist/gcp-url-map.js";
34
+ import { mcpArmorRuleArgs } from "../../dist/remote-mcp-edge.js";
34
35
  import {
35
36
  ADMIN_MEMORY_DEFAULT,
36
37
  adminEnvContract,
@@ -40,10 +41,12 @@ import {
40
41
  type CloudRunSlug,
41
42
  databaseUrls,
42
43
  defaultStagingHost,
44
+ GATEWAY_TIMEOUT_SECONDS,
43
45
  gatewayEnvContract,
44
46
  type RuntimeSecret,
45
47
  runtimeSecretBindings,
46
48
  STATIC_CDN_POLICY,
49
+ secretFileVolumesTemplate,
47
50
  } from "../../dist/stack-contract.js";
48
51
 
49
52
  const cfg = new pulumi.Config();
@@ -251,6 +254,10 @@ const runtimeSecretIds: Record<RuntimeSecret, pulumi.Input<string>> = {
251
254
  "tool-approval-secret": gcpSecretId(env, "tool-approval-secret"),
252
255
  "staging-gate-secret": gcpSecretId(env, "staging-gate-secret"),
253
256
  "public-role-password": gcpSecretId(env, "public-role-password"),
257
+ // #806 — remote MCP: the Owner-set Google OAuth client (a placeholder
258
+ // until then) and the broker's seal key, both CLI-generated.
259
+ "mcp-oauth-client": gcpSecretId(env, "mcp-oauth-client"),
260
+ "mcp-oauth-seal-key": gcpSecretId(env, "mcp-oauth-seal-key"),
254
261
  };
255
262
 
256
263
  // #613 — public_role's own password (CLI-generated, stack-contract.ts
@@ -472,6 +479,20 @@ for (const binding of runtimeSecretBindings()) {
472
479
  );
473
480
  }
474
481
 
482
+ // #806 — the Owner's remote-MCP setup (Settings → MCP → Remote) stores the
483
+ // Google OAuth client in this one secret. Add-version only: the admin can
484
+ // replace the client the gateway reads, never read it back or touch any
485
+ // other secret (stack-contract.ts GCP_COMMON says why).
486
+ new gcp.secretmanager.SecretIamMember(
487
+ `${namePrefix}-admin-mcp-oauth-client-version-adder`,
488
+ {
489
+ secretId: runtimeSecretIds["mcp-oauth-client"],
490
+ role: "roles/secretmanager.secretVersionAdder",
491
+ member: pulumi.interpolate`serviceAccount:${runSa.email}`,
492
+ },
493
+ opts,
494
+ );
495
+
475
496
  new gcp.storage.BucketIAMMember(
476
497
  `${namePrefix}-media-rw`,
477
498
  {
@@ -627,8 +648,8 @@ interface CloudRunArgs {
627
648
  * Per-request timeout. Cloud Run's default is 300s (5min), which is too
628
649
  * short for the admin's SSE chat-stream — a multi-tool compose-page session
629
650
  * regularly runs 5–15 min. Pass an explicit "<n>s" Pulumi-style duration
630
- * string. Gateway stays on the default; visitor-facing endpoints don't
631
- * legitimately need longer.
651
+ * string. The gateway gets the same (#806): it proxies remote-MCP chat
652
+ * streams to the admin.
632
653
  */
633
654
  readonly timeout?: string;
634
655
  /**
@@ -689,16 +710,23 @@ function cloudRunService(args: CloudRunArgs): gcp.cloudrunv2.Service {
689
710
  },
690
711
  timeout: args.timeout,
691
712
  ...(args.mediaVolume
692
- ? {
693
- executionEnvironment: args.mediaVolume.executionEnvironment,
694
- volumes: [...args.mediaVolume.volumes],
695
- }
713
+ ? { executionEnvironment: args.mediaVolume.executionEnvironment }
696
714
  : {}),
715
+ // The admin's media bucket, plus each service's secret files (#806:
716
+ // the gateway's remote-MCP OAuth client) — both from the contract
717
+ // upgrade applies to existing installs.
718
+ volumes: [
719
+ ...(args.mediaVolume?.volumes ?? []),
720
+ ...secretFileVolumesTemplate(args.serviceName, env).volumes,
721
+ ],
697
722
  containers: [
698
723
  {
699
724
  image: imageTag(args.serviceName),
700
725
  envs: [...args.contractEnv],
701
- ...(args.mediaVolume ? { volumeMounts: [...args.mediaVolume.volumeMounts] } : {}),
726
+ volumeMounts: [
727
+ ...(args.mediaVolume?.volumeMounts ?? []),
728
+ ...secretFileVolumesTemplate(args.serviceName, env).volumeMounts,
729
+ ],
702
730
  resources: { limits: { cpu: "1", memory: args.memory } },
703
731
  },
704
732
  ],
@@ -749,6 +777,11 @@ const gatewaySvc = cloudRunService({
749
777
  minInstances: gatewayMinInstances,
750
778
  maxInstances: 100,
751
779
  memory: "512Mi",
780
+ // #806 — remote MCP: chat turns stream through the gateway for minutes,
781
+ // so it gets the admin's 3600 s instead of Cloud Run's 300 s default
782
+ // (stack-contract.ts GATEWAY_TIMEOUT_SECONDS). The LB in front imposes no
783
+ // shorter limit on serverless NEG backends.
784
+ timeout: `${GATEWAY_TIMEOUT_SECONDS}s`,
752
785
  // public_role on cms_public only: no cms_admin login of any role
753
786
  // (#613, #635, CLAUDE.md §2).
754
787
  contractEnv: gatewayEnvContract(envContractInputs),
@@ -784,6 +817,12 @@ const wafPolicy = new gcp.compute.SecurityPolicy(
784
817
  {
785
818
  description: `Caelo ${env} Cloud Armor — rate limit + OWASP`,
786
819
  rules: [
820
+ // #806 — remote MCP (/api/mcp/*): a per-IP throttle sized for agent
821
+ // traffic behind shared connector IPs, evaluated first; below it the
822
+ // rule allows, so the OWASP packs (MCP bodies carry HTML) and the
823
+ // general ban below do not apply there. src/remote-mcp-edge.ts says
824
+ // why; `cms-provision upgrade` adds the same rule to existing installs.
825
+ mcpArmorRuleArgs(),
787
826
  // Rate limit per source IP — 100 req / min sliding window.
788
827
  {
789
828
  action: "rate_based_ban",
@@ -984,6 +1023,19 @@ new gcp.iap.WebBackendServiceIamMember(
984
1023
  opts,
985
1024
  );
986
1025
 
1026
+ // =========================================================================
1027
+ // Quality-audit job — deliberately NOT here
1028
+ // =========================================================================
1029
+ //
1030
+ // #875 — every Stage audit's Lighthouse runs execute in parallel in a Cloud
1031
+ // Run job, one task per run, under its own service account (results bucket
1032
+ // create-only, staged build read-only, no secrets, no VPC). The CLI owns the
1033
+ // job, its account, the results bucket and the grants
1034
+ // (packages/provisioning/src/audit-job-setup.ts, run by the wizard after
1035
+ // `pulumi up` and by `upgrade`), because `upgrade` never runs Pulumi: a
1036
+ // bucket or job both this program and `upgrade` created would collide on
1037
+ // the next wizard run. The app-roll moves the job's image with the admin's.
1038
+
987
1039
  // =========================================================================
988
1040
  // Operator access — deliberately NOT here
989
1041
  // =========================================================================
@@ -46,9 +46,11 @@ import {
46
46
  type CloudRunSlug,
47
47
  databaseUrls,
48
48
  defaultStagingHost,
49
+ GATEWAY_TIMEOUT_SECONDS,
49
50
  gatewayEnvContract,
50
51
  type RuntimeSecret,
51
52
  runtimeSecretBindings,
53
+ secretFileVolumesTemplate,
52
54
  } from "../../dist/stack-contract.js";
53
55
 
54
56
  const cfg = new pulumi.Config();
@@ -224,6 +226,10 @@ const runtimeSecretIds: Record<RuntimeSecret, pulumi.Input<string>> = {
224
226
  "tool-approval-secret": gcpSecretId(env, "tool-approval-secret"),
225
227
  "staging-gate-secret": gcpSecretId(env, "staging-gate-secret"),
226
228
  "public-role-password": gcpSecretId(env, "public-role-password"),
229
+ // #806 — remote MCP: the Owner-set Google OAuth client (a placeholder
230
+ // until then) and the broker's seal key, both CLI-generated.
231
+ "mcp-oauth-client": gcpSecretId(env, "mcp-oauth-client"),
232
+ "mcp-oauth-seal-key": gcpSecretId(env, "mcp-oauth-seal-key"),
227
233
  };
228
234
 
229
235
  // #613 — public_role's own password (CLI-generated, stack-contract.ts
@@ -376,6 +382,20 @@ for (const binding of runtimeSecretBindings()) {
376
382
  );
377
383
  }
378
384
 
385
+ // #806 — the Owner's remote-MCP setup (Settings → MCP → Remote) stores the
386
+ // Google OAuth client in this one secret. Add-version only: the admin can
387
+ // replace the client the gateway reads, never read it back or touch any
388
+ // other secret (stack-contract.ts GCP_COMMON says why).
389
+ new gcp.secretmanager.SecretIamMember(
390
+ `${namePrefix}-admin-mcp-oauth-client-version-adder`,
391
+ {
392
+ secretId: runtimeSecretIds["mcp-oauth-client"],
393
+ role: "roles/secretmanager.secretVersionAdder",
394
+ member: pulumi.interpolate`serviceAccount:${runSa.email}`,
395
+ },
396
+ opts,
397
+ );
398
+
379
399
  new gcp.storage.BucketIAMMember(
380
400
  `${namePrefix}-media-rw`,
381
401
  {
@@ -551,16 +571,23 @@ function cloudRunService(args: CloudRunArgs): gcp.cloudrunv2.Service {
551
571
  },
552
572
  timeout: args.timeout,
553
573
  ...(args.mediaVolume
554
- ? {
555
- executionEnvironment: args.mediaVolume.executionEnvironment,
556
- volumes: [...args.mediaVolume.volumes],
557
- }
574
+ ? { executionEnvironment: args.mediaVolume.executionEnvironment }
558
575
  : {}),
576
+ // The admin's media bucket, plus each service's secret files (#806:
577
+ // the gateway's remote-MCP OAuth client) — both from the contract
578
+ // upgrade applies to existing installs.
579
+ volumes: [
580
+ ...(args.mediaVolume?.volumes ?? []),
581
+ ...secretFileVolumesTemplate(args.serviceName, env).volumes,
582
+ ],
559
583
  containers: [
560
584
  {
561
585
  image: imageRef(args.serviceName),
562
586
  envs: [...args.contractEnv],
563
- ...(args.mediaVolume ? { volumeMounts: [...args.mediaVolume.volumeMounts] } : {}),
587
+ volumeMounts: [
588
+ ...(args.mediaVolume?.volumeMounts ?? []),
589
+ ...secretFileVolumesTemplate(args.serviceName, env).volumeMounts,
590
+ ],
564
591
  resources: { limits: { cpu: "1", memory: args.memory } },
565
592
  },
566
593
  ],
@@ -613,7 +640,11 @@ const gatewaySvc = cloudRunService({
613
640
  minInstances: gatewayMinInstances,
614
641
  maxInstances: 100,
615
642
  memory: "512Mi",
616
- timeout: "60s",
643
+ // #806 — remote MCP: chat turns stream through the gateway for minutes
644
+ // (stack-contract.ts GATEWAY_TIMEOUT_SECONDS). The Firebase Hosting
645
+ // rewrite keeps its own 60 s cut; MCP clients use the gateway's Cloud Run
646
+ // URL directly.
647
+ timeout: `${GATEWAY_TIMEOUT_SECONDS}s`,
617
648
  // #650 — all traffic: the gateway also serves staging.<domain> through
618
649
  // a Cloud Run domain mapping (`cms-provision staging-domain enable`),
619
650
  // and Cloud Run refuses domain-mapped requests under an internal-only
@@ -900,6 +931,19 @@ new gcp.iap.WebCloudRunServiceIamMember(
900
931
  opts,
901
932
  );
902
933
 
934
+ // =========================================================================
935
+ // Quality-audit job — deliberately NOT here
936
+ // =========================================================================
937
+ //
938
+ // #875 — every Stage audit's Lighthouse runs execute in parallel in a Cloud
939
+ // Run job, one task per run, under its own service account (results bucket
940
+ // create-only, staged build read-only, no secrets, no VPC). The CLI owns the
941
+ // job, its account, the results bucket and the grants
942
+ // (packages/provisioning/src/audit-job-setup.ts, run by the wizard after
943
+ // `pulumi up` and by `upgrade`), because `upgrade` never runs Pulumi: a
944
+ // bucket or job both this program and `upgrade` created would collide on
945
+ // the next wizard run. The app-roll moves the job's image with the admin's.
946
+
903
947
  // =========================================================================
904
948
  // Operator access — deliberately NOT here
905
949
  // =========================================================================