@bleedingdev/modern-js-ultramodern-create 3.9.0-ultramodern.11 → 3.9.0-ultramodern.13

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 (251) hide show
  1. package/README.md +32 -36
  2. package/dist/cjs/ultramodern-release-cohort.cjs +6 -21
  3. package/dist/cjs/ultramodern-tooling/commands/cloudflare-output-verify.cjs +29 -53
  4. package/dist/cjs/ultramodern-tooling/commands/context.cjs +1 -27
  5. package/dist/cjs/ultramodern-tooling/commands/routes-generate-app.cjs +60 -0
  6. package/dist/cjs/ultramodern-tooling/commands/routes-generate.cjs +12 -48
  7. package/dist/cjs/ultramodern-tooling/commands/validate.cjs +5 -58
  8. package/dist/cjs/ultramodern-tooling/commands.cjs +13 -3
  9. package/dist/cjs/ultramodern-tooling/config/index.cjs +11 -4
  10. package/dist/cjs/ultramodern-tooling/config/load.cjs +4 -17
  11. package/dist/cjs/ultramodern-tooling/config/metadata.cjs +41 -2
  12. package/dist/cjs/ultramodern-tooling/config/normalize.cjs +121 -198
  13. package/dist/cjs/ultramodern-workspace/add-shell.cjs +103 -147
  14. package/dist/cjs/ultramodern-workspace/add-vertical/execute.cjs +61 -94
  15. package/dist/cjs/ultramodern-workspace/add-vertical/plan.cjs +14 -160
  16. package/dist/cjs/ultramodern-workspace/add-vertical/preflight.cjs +8 -13
  17. package/dist/cjs/ultramodern-workspace/add-vertical/preview.cjs +78 -0
  18. package/dist/cjs/ultramodern-workspace/add-vertical/topology.cjs +0 -32
  19. package/dist/cjs/ultramodern-workspace/add-vertical/transaction.cjs +2 -2
  20. package/dist/cjs/ultramodern-workspace/add-vertical/workspace-state.cjs +19 -42
  21. package/dist/cjs/ultramodern-workspace/add-vertical.cjs +0 -9
  22. package/dist/cjs/ultramodern-workspace/api/contracts.cjs +2 -2
  23. package/dist/cjs/ultramodern-workspace/api/rpc.cjs +16 -14
  24. package/dist/cjs/ultramodern-workspace/api/service.cjs +4 -8
  25. package/dist/cjs/ultramodern-workspace/api/shared.cjs +1 -1
  26. package/dist/cjs/ultramodern-workspace/backend-federation.cjs +3 -3
  27. package/dist/cjs/ultramodern-workspace/contracts.cjs +14 -183
  28. package/dist/cjs/ultramodern-workspace/delivery-unit-stamp.cjs +10 -5
  29. package/dist/cjs/ultramodern-workspace/delivery-unit-sync.cjs +27 -17
  30. package/dist/cjs/ultramodern-workspace/delivery-unit.cjs +11 -6
  31. package/dist/cjs/ultramodern-workspace/demo-components.cjs +62 -115
  32. package/dist/cjs/ultramodern-workspace/descriptors.cjs +0 -4
  33. package/dist/cjs/ultramodern-workspace/generation-result.cjs +1 -1
  34. package/dist/cjs/ultramodern-workspace/index.cjs +2 -5
  35. package/dist/cjs/ultramodern-workspace/mf-validation/constants.cjs +0 -6
  36. package/dist/cjs/ultramodern-workspace/mf-validation/discovery.cjs +6 -6
  37. package/dist/cjs/ultramodern-workspace/mf-validation/path-utils.cjs +37 -38
  38. package/dist/cjs/ultramodern-workspace/module-federation/config.cjs +9 -16
  39. package/dist/cjs/ultramodern-workspace/module-federation/remote-refs.cjs +1 -43
  40. package/dist/cjs/ultramodern-workspace/package-json.cjs +47 -54
  41. package/dist/cjs/ultramodern-workspace/patch-inventory.cjs +122 -0
  42. package/dist/cjs/ultramodern-workspace/policy.cjs +6 -380
  43. package/dist/cjs/ultramodern-workspace/public-surface.cjs +2 -2
  44. package/dist/cjs/ultramodern-workspace/routes.cjs +11 -7
  45. package/dist/cjs/ultramodern-workspace/shared-patches.cjs +12 -2
  46. package/dist/cjs/ultramodern-workspace/shells.cjs +0 -70
  47. package/dist/cjs/ultramodern-workspace/tooling-command-catalog.cjs +6 -43
  48. package/dist/cjs/ultramodern-workspace/tsconfigs.cjs +3 -1
  49. package/dist/cjs/ultramodern-workspace/validation/architecture.cjs +397 -0
  50. package/dist/cjs/ultramodern-workspace/validation/assertions.cjs +140 -0
  51. package/dist/cjs/ultramodern-workspace/validation/types.cjs +18 -0
  52. package/dist/cjs/ultramodern-workspace/validation/workspace.cjs +343 -0
  53. package/dist/cjs/ultramodern-workspace/versions.cjs +25 -41
  54. package/dist/cjs/ultramodern-workspace/workspace-artifact-ownership.cjs +71 -31
  55. package/dist/cjs/ultramodern-workspace/workspace-script-plan.cjs +7 -7
  56. package/dist/cjs/ultramodern-workspace/workspace-scripts.cjs +17 -143
  57. package/dist/cjs/ultramodern-workspace/workspace-validation-contract.cjs +62 -371
  58. package/dist/cjs/ultramodern-workspace/write-app.cjs +5 -4
  59. package/dist/cjs/ultramodern-workspace/write-workspace.cjs +10 -50
  60. package/dist/esm/ultramodern-release-cohort.js +5 -14
  61. package/dist/esm/ultramodern-tooling/commands/cloudflare-output-verify.js +29 -53
  62. package/dist/esm/ultramodern-tooling/commands/context.js +3 -24
  63. package/dist/esm/ultramodern-tooling/commands/routes-generate-app.js +28 -0
  64. package/dist/esm/ultramodern-tooling/commands/routes-generate.js +13 -49
  65. package/dist/esm/ultramodern-tooling/commands/validate.js +6 -49
  66. package/dist/esm/ultramodern-tooling/commands.js +12 -3
  67. package/dist/esm/ultramodern-tooling/config/index.js +1 -0
  68. package/dist/esm/ultramodern-tooling/config/load.js +5 -17
  69. package/dist/esm/ultramodern-tooling/config/metadata.js +36 -1
  70. package/dist/esm/ultramodern-tooling/config/normalize.js +125 -191
  71. package/dist/esm/ultramodern-workspace/add-shell.js +110 -153
  72. package/dist/esm/ultramodern-workspace/add-vertical/execute.js +61 -98
  73. package/dist/esm/ultramodern-workspace/add-vertical/plan.js +16 -150
  74. package/dist/esm/ultramodern-workspace/add-vertical/preflight.js +6 -11
  75. package/dist/esm/ultramodern-workspace/add-vertical/preview.js +40 -0
  76. package/dist/esm/ultramodern-workspace/add-vertical/topology.js +1 -30
  77. package/dist/esm/ultramodern-workspace/add-vertical/transaction.js +2 -2
  78. package/dist/esm/ultramodern-workspace/add-vertical/workspace-state.js +15 -32
  79. package/dist/esm/ultramodern-workspace/add-vertical.js +1 -1
  80. package/dist/esm/ultramodern-workspace/api/contracts.js +2 -2
  81. package/dist/esm/ultramodern-workspace/api/rpc.js +16 -14
  82. package/dist/esm/ultramodern-workspace/api/service.js +4 -8
  83. package/dist/esm/ultramodern-workspace/api/shared.js +1 -1
  84. package/dist/esm/ultramodern-workspace/backend-federation.js +3 -3
  85. package/dist/esm/ultramodern-workspace/contracts.js +14 -180
  86. package/dist/esm/ultramodern-workspace/delivery-unit-stamp.js +10 -5
  87. package/dist/esm/ultramodern-workspace/delivery-unit-sync.js +28 -18
  88. package/dist/esm/ultramodern-workspace/delivery-unit.js +11 -6
  89. package/dist/esm/ultramodern-workspace/demo-components.js +62 -115
  90. package/dist/esm/ultramodern-workspace/descriptors.js +1 -2
  91. package/dist/esm/ultramodern-workspace/generation-result.js +2 -2
  92. package/dist/esm/ultramodern-workspace/index.js +1 -1
  93. package/dist/esm/ultramodern-workspace/mf-validation/constants.js +1 -4
  94. package/dist/esm/ultramodern-workspace/mf-validation/discovery.js +7 -7
  95. package/dist/esm/ultramodern-workspace/mf-validation/path-utils.js +36 -34
  96. package/dist/esm/ultramodern-workspace/module-federation/config.js +10 -17
  97. package/dist/esm/ultramodern-workspace/module-federation/remote-refs.js +1 -43
  98. package/dist/esm/ultramodern-workspace/package-json.js +48 -55
  99. package/dist/esm/ultramodern-workspace/patch-inventory.js +84 -0
  100. package/dist/esm/ultramodern-workspace/policy.js +6 -371
  101. package/dist/esm/ultramodern-workspace/public-surface.js +2 -2
  102. package/dist/esm/ultramodern-workspace/routes.js +11 -7
  103. package/dist/esm/ultramodern-workspace/shared-patches.js +2 -2
  104. package/dist/esm/ultramodern-workspace/shells.js +3 -67
  105. package/dist/esm/ultramodern-workspace/tooling-command-catalog.js +7 -41
  106. package/dist/esm/ultramodern-workspace/tsconfigs.js +4 -2
  107. package/dist/esm/ultramodern-workspace/validation/architecture.js +348 -0
  108. package/dist/esm/ultramodern-workspace/validation/assertions.js +65 -0
  109. package/dist/esm/ultramodern-workspace/validation/types.js +0 -0
  110. package/dist/esm/ultramodern-workspace/validation/workspace.js +285 -0
  111. package/dist/esm/ultramodern-workspace/versions.js +24 -28
  112. package/dist/esm/ultramodern-workspace/workspace-artifact-ownership.js +64 -30
  113. package/dist/esm/ultramodern-workspace/workspace-script-plan.js +7 -7
  114. package/dist/esm/ultramodern-workspace/workspace-scripts.js +19 -136
  115. package/dist/esm/ultramodern-workspace/workspace-validation-contract.js +64 -373
  116. package/dist/esm/ultramodern-workspace/write-app.js +4 -3
  117. package/dist/esm/ultramodern-workspace/write-workspace.js +16 -53
  118. package/dist/esm-node/ultramodern-release-cohort.js +5 -14
  119. package/dist/esm-node/ultramodern-tooling/commands/cloudflare-output-verify.js +29 -53
  120. package/dist/esm-node/ultramodern-tooling/commands/context.js +3 -24
  121. package/dist/esm-node/ultramodern-tooling/commands/routes-generate-app.js +29 -0
  122. package/dist/esm-node/ultramodern-tooling/commands/routes-generate.js +13 -49
  123. package/dist/esm-node/ultramodern-tooling/commands/validate.js +6 -49
  124. package/dist/esm-node/ultramodern-tooling/commands.js +12 -3
  125. package/dist/esm-node/ultramodern-tooling/config/index.js +1 -0
  126. package/dist/esm-node/ultramodern-tooling/config/load.js +5 -17
  127. package/dist/esm-node/ultramodern-tooling/config/metadata.js +36 -1
  128. package/dist/esm-node/ultramodern-tooling/config/normalize.js +125 -191
  129. package/dist/esm-node/ultramodern-workspace/add-shell.js +110 -153
  130. package/dist/esm-node/ultramodern-workspace/add-vertical/execute.js +61 -98
  131. package/dist/esm-node/ultramodern-workspace/add-vertical/plan.js +16 -150
  132. package/dist/esm-node/ultramodern-workspace/add-vertical/preflight.js +6 -11
  133. package/dist/esm-node/ultramodern-workspace/add-vertical/preview.js +41 -0
  134. package/dist/esm-node/ultramodern-workspace/add-vertical/topology.js +1 -30
  135. package/dist/esm-node/ultramodern-workspace/add-vertical/transaction.js +2 -2
  136. package/dist/esm-node/ultramodern-workspace/add-vertical/workspace-state.js +15 -32
  137. package/dist/esm-node/ultramodern-workspace/add-vertical.js +1 -1
  138. package/dist/esm-node/ultramodern-workspace/api/contracts.js +2 -2
  139. package/dist/esm-node/ultramodern-workspace/api/rpc.js +16 -14
  140. package/dist/esm-node/ultramodern-workspace/api/service.js +4 -8
  141. package/dist/esm-node/ultramodern-workspace/api/shared.js +1 -1
  142. package/dist/esm-node/ultramodern-workspace/backend-federation.js +3 -3
  143. package/dist/esm-node/ultramodern-workspace/contracts.js +14 -180
  144. package/dist/esm-node/ultramodern-workspace/delivery-unit-stamp.js +10 -5
  145. package/dist/esm-node/ultramodern-workspace/delivery-unit-sync.js +28 -18
  146. package/dist/esm-node/ultramodern-workspace/delivery-unit.js +11 -6
  147. package/dist/esm-node/ultramodern-workspace/demo-components.js +62 -115
  148. package/dist/esm-node/ultramodern-workspace/descriptors.js +1 -2
  149. package/dist/esm-node/ultramodern-workspace/generation-result.js +2 -2
  150. package/dist/esm-node/ultramodern-workspace/index.js +1 -1
  151. package/dist/esm-node/ultramodern-workspace/mf-validation/constants.js +1 -4
  152. package/dist/esm-node/ultramodern-workspace/mf-validation/discovery.js +7 -7
  153. package/dist/esm-node/ultramodern-workspace/mf-validation/path-utils.js +36 -34
  154. package/dist/esm-node/ultramodern-workspace/module-federation/config.js +10 -17
  155. package/dist/esm-node/ultramodern-workspace/module-federation/remote-refs.js +1 -43
  156. package/dist/esm-node/ultramodern-workspace/package-json.js +48 -55
  157. package/dist/esm-node/ultramodern-workspace/patch-inventory.js +85 -0
  158. package/dist/esm-node/ultramodern-workspace/policy.js +6 -371
  159. package/dist/esm-node/ultramodern-workspace/public-surface.js +2 -2
  160. package/dist/esm-node/ultramodern-workspace/routes.js +11 -7
  161. package/dist/esm-node/ultramodern-workspace/shared-patches.js +2 -2
  162. package/dist/esm-node/ultramodern-workspace/shells.js +3 -67
  163. package/dist/esm-node/ultramodern-workspace/tooling-command-catalog.js +7 -41
  164. package/dist/esm-node/ultramodern-workspace/tsconfigs.js +4 -2
  165. package/dist/esm-node/ultramodern-workspace/validation/architecture.js +349 -0
  166. package/dist/esm-node/ultramodern-workspace/validation/assertions.js +66 -0
  167. package/dist/esm-node/ultramodern-workspace/validation/types.js +1 -0
  168. package/dist/esm-node/ultramodern-workspace/validation/workspace.js +286 -0
  169. package/dist/esm-node/ultramodern-workspace/versions.js +24 -28
  170. package/dist/esm-node/ultramodern-workspace/workspace-artifact-ownership.js +64 -30
  171. package/dist/esm-node/ultramodern-workspace/workspace-script-plan.js +7 -7
  172. package/dist/esm-node/ultramodern-workspace/workspace-scripts.js +19 -136
  173. package/dist/esm-node/ultramodern-workspace/workspace-validation-contract.js +64 -373
  174. package/dist/esm-node/ultramodern-workspace/write-app.js +4 -3
  175. package/dist/esm-node/ultramodern-workspace/write-workspace.js +16 -53
  176. package/dist/types/ultramodern-release-cohort.d.ts +1 -3
  177. package/dist/types/ultramodern-tooling/commands/cloudflare-output-verify.d.ts +2 -2
  178. package/dist/types/ultramodern-tooling/commands/context.d.ts +0 -1
  179. package/dist/types/ultramodern-tooling/commands/routes-generate-app.d.ts +1 -0
  180. package/dist/types/ultramodern-tooling/commands/routes-generate.d.ts +1 -1
  181. package/dist/types/ultramodern-tooling/commands/validate.d.ts +1 -1
  182. package/dist/types/ultramodern-tooling/config/index.d.ts +1 -0
  183. package/dist/types/ultramodern-tooling/config/load.d.ts +6 -58
  184. package/dist/types/ultramodern-tooling/config/metadata.d.ts +3 -0
  185. package/dist/types/ultramodern-tooling/config/normalize.d.ts +9 -88
  186. package/dist/types/ultramodern-tooling/config/types.d.ts +1 -9
  187. package/dist/types/ultramodern-workspace/add-shell.d.ts +1 -1
  188. package/dist/types/ultramodern-workspace/add-vertical/execute.d.ts +1 -0
  189. package/dist/types/ultramodern-workspace/add-vertical/preflight.d.ts +4 -3
  190. package/dist/types/ultramodern-workspace/add-vertical/preview.d.ts +4 -0
  191. package/dist/types/ultramodern-workspace/add-vertical/topology.d.ts +0 -1
  192. package/dist/types/ultramodern-workspace/add-vertical/transaction.d.ts +4 -1
  193. package/dist/types/ultramodern-workspace/add-vertical/workspace-state.d.ts +8 -5
  194. package/dist/types/ultramodern-workspace/add-vertical.d.ts +1 -1
  195. package/dist/types/ultramodern-workspace/api/rpc.d.ts +1 -1
  196. package/dist/types/ultramodern-workspace/contracts.d.ts +1 -3
  197. package/dist/types/ultramodern-workspace/delivery-unit-stamp.d.ts +2 -2
  198. package/dist/types/ultramodern-workspace/delivery-unit.d.ts +2 -2
  199. package/dist/types/ultramodern-workspace/descriptors.d.ts +0 -1
  200. package/dist/types/ultramodern-workspace/index.d.ts +1 -1
  201. package/dist/types/ultramodern-workspace/mf-validation/constants.d.ts +0 -1
  202. package/dist/types/ultramodern-workspace/mf-validation/path-utils.d.ts +2 -3
  203. package/dist/types/ultramodern-workspace/module-federation/config.d.ts +1 -1
  204. package/dist/types/ultramodern-workspace/patch-inventory.d.ts +10 -0
  205. package/dist/types/ultramodern-workspace/policy.d.ts +60 -182
  206. package/dist/types/ultramodern-workspace/shells.d.ts +1 -14
  207. package/dist/types/ultramodern-workspace/tooling-command-catalog.d.ts +1 -6
  208. package/dist/types/ultramodern-workspace/validation/architecture.d.ts +2 -0
  209. package/dist/types/ultramodern-workspace/validation/assertions.d.ts +14 -0
  210. package/dist/types/ultramodern-workspace/validation/types.d.ts +9 -0
  211. package/dist/types/ultramodern-workspace/validation/workspace.d.ts +6 -0
  212. package/dist/types/ultramodern-workspace/versions.d.ts +23 -27
  213. package/dist/types/ultramodern-workspace/workspace-artifact-ownership.d.ts +5 -0
  214. package/dist/types/ultramodern-workspace/workspace-script-plan.d.ts +1 -1
  215. package/dist/types/ultramodern-workspace/workspace-scripts.d.ts +7 -19
  216. package/dist/types/ultramodern-workspace/workspace-validation-contract.d.ts +22 -188
  217. package/dist/types/ultramodern-workspace/write-workspace.d.ts +1 -3
  218. package/package.json +17 -16
  219. package/{template-workspace/.modernjs/release-cohort.json → release-cohort.json} +48 -48
  220. package/template-workspace/README.md.handlebars +9 -16
  221. package/template-workspace/pnpm-workspace.yaml.handlebars +0 -24
  222. package/templates/workspace/apps/modern.config.ts.handlebars +6 -6
  223. package/templates/workspace/apps/shared/src/routes/ultramodern-route-metadata.ts.handlebars +8 -21
  224. package/templates/workspace/apps/shell-super-app/src/routes/[lang]/page.tsx.handlebars +20 -20
  225. package/templates/workspace/apps/shell-super-app/src/routes/vertical-components.helpers.tsx.handlebars +1 -1
  226. package/templates/workspace/apps/shell-super-app/src/routes/vertical-components.tsx.handlebars +11 -11
  227. package/templates/workspace/apps/shell-super-app/src/routes/vertical-components.worker.helpers.tsx.handlebars +1 -1
  228. package/templates/workspace-scripts/generate-node-backend-federation.mjs +39 -49
  229. package/templates/workspace-scripts/generate-public-surface-assets.mjs +142 -206
  230. package/templates/workspace-scripts/materialize-zerops-runtime.mjs +3 -11
  231. package/templates/workspace-scripts/proof-cloudflare-version.mjs +53 -444
  232. package/templates/workspace-scripts/proof-node-backend-federation.mjs +193 -39
  233. package/templates/workspace-scripts/proof-workerd-ssr.mjs +126 -66
  234. package/templates/workspace-scripts/ultramodern-performance-readiness.mjs +45 -147
  235. package/dist/cjs/ultramodern-workspace/cohort-parity.cjs +0 -129
  236. package/dist/cjs/ultramodern-workspace/patch-parity.cjs +0 -163
  237. package/dist/esm/ultramodern-workspace/cohort-parity.js +0 -74
  238. package/dist/esm/ultramodern-workspace/patch-parity.js +0 -99
  239. package/dist/esm-node/ultramodern-workspace/cohort-parity.js +0 -75
  240. package/dist/esm-node/ultramodern-workspace/patch-parity.js +0 -100
  241. package/dist/types/ultramodern-workspace/cohort-parity.d.ts +0 -31
  242. package/dist/types/ultramodern-workspace/patch-parity.d.ts +0 -39
  243. package/template-workspace/patches/@module-federation__bridge-react@2.9.0.patch +0 -47
  244. package/template-workspace/patches/@module-federation__dts-plugin@2.9.0.patch +0 -100
  245. package/template-workspace/patches/@module-federation__modern-js-v3@2.9.0.patch +0 -268
  246. package/template-workspace/patches/@module-federation__runtime-core@2.9.0.patch +0 -13
  247. package/template-workspace/patches/drizzle-orm-ts7-strict-declarations.patch +0 -471
  248. package/template-workspace/patches/msgpackr@2.1.0.patch +0 -30
  249. package/template-workspace/patches/zod@4.5.4.patch +0 -56
  250. package/templates/packages/effect-bff-runtime.ts +0 -2
  251. package/templates/workspace-scripts/validate-ultramodern-workspace.mjs.handlebars +0 -4046
@@ -9,7 +9,8 @@ import { fileURLToPath, pathToFileURL } from 'node:url';
9
9
 
10
10
  const workspaceRoot = path.resolve(process.env.ULTRAMODERN_WORKSPACE_ROOT ?? process.cwd());
11
11
  const workspaceRequire = createRequire(path.join(workspaceRoot, 'package.json'));
12
- const compactConfigPath = path.join(workspaceRoot, '.modernjs/ultramodern.json');
12
+ const topologyPath = path.join(workspaceRoot, 'topology/reference-topology.json');
13
+ const localOverlayPath = path.join(workspaceRoot, 'topology/local-overlays/development.json');
13
14
  const defaultOut = path.join(
14
15
  workspaceRoot,
15
16
  '.codex/reports/node-backend-federation-proof/proof.json',
@@ -70,7 +71,6 @@ export async function importBackendFederationRuntime() {
70
71
  `${effectPath} does not export createEffectBffTestHandler`,
71
72
  );
72
73
  }
73
-
74
74
  return {
75
75
  loadBackendFederatedEffectApiFromManifest:
76
76
  runtime.loadBackendFederatedEffectApiFromManifest,
@@ -96,7 +96,6 @@ function createBackendName(app) {
96
96
  return (
97
97
  app.backendFederation?.name ??
98
98
  app.backendFederation?.executionSurfaces?.node?.remoteName ??
99
- app.serverExecution?.node?.remoteName ??
100
99
  (typeof app.moduleFederation?.name === 'string'
101
100
  ? `${app.moduleFederation.name}Backend`
102
101
  : `vertical${toPascalCase(app.id)}Backend`)
@@ -105,7 +104,6 @@ function createBackendName(app) {
105
104
 
106
105
  function createBackendManifestUrl(app) {
107
106
  return (
108
- app.backendFederation?.executionSurfaces?.node?.manifestUrl ??
109
107
  app.serverExecution?.node?.manifestUrl ??
110
108
  `http://localhost:${app.port}/backend-mf-manifest.json`
111
109
  );
@@ -113,7 +111,6 @@ function createBackendManifestUrl(app) {
113
111
 
114
112
  function createBackendContainerEntry(app) {
115
113
  return (
116
- app.backendFederation?.executionSurfaces?.node?.containerEntry ??
117
114
  app.serverExecution?.node?.containerEntry ??
118
115
  `http://localhost:${app.port}/backendRemoteEntry.cjs`
119
116
  );
@@ -121,8 +118,8 @@ function createBackendContainerEntry(app) {
121
118
 
122
119
  function resolveRemoteType(app) {
123
120
  return (
124
- app.backendFederation?.executionSurfaces?.node?.remoteType ??
125
121
  app.serverExecution?.node?.remoteType ??
122
+ app.backendFederation?.executionSurfaces?.node?.remoteType ??
126
123
  'commonjs-module'
127
124
  );
128
125
  }
@@ -140,8 +137,8 @@ function collectJsonSmokeChecks(apps, targetApp) {
140
137
 
141
138
  const configuredChecks = apps
142
139
  .flatMap((app) =>
143
- Array.isArray(app?.deploy?.cloudflare?.jsonSmokeChecks)
144
- ? app.deploy.cloudflare.jsonSmokeChecks
140
+ Array.isArray(app?.cloudflare?.jsonSmokeChecks)
141
+ ? app.cloudflare.jsonSmokeChecks
145
142
  : [],
146
143
  )
147
144
  .filter((check) => {
@@ -178,27 +175,70 @@ function collectJsonSmokeChecks(apps, targetApp) {
178
175
  ];
179
176
  }
180
177
 
181
- function compactApps(config, appFilter) {
182
- const apps = Array.isArray(config.topology?.apps) ? config.topology.apps : [];
178
+ export function topologyApps(topology, localOverlay, appFilter, env = process.env) {
179
+ if (!Array.isArray(topology?.verticals) || !localOverlay?.ports || !localOverlay?.serverExecution) {
180
+ throw new Error('Node proof requires declared reference topology and development overlay.');
181
+ }
182
+ const apps = topology.verticals;
183
183
  const filteredApps = apps
184
184
  .filter((app) => app?.kind === 'vertical' && app.api)
185
185
  .filter((app) => !appFilter || app.id === appFilter)
186
- .map((app) => ({
186
+ .map((app) => {
187
+ const overlayPort = localOverlay.ports[app.id];
188
+ const domain = app.domain ?? app.id;
189
+ const portEnv = app.portEnv ??
190
+ `VERTICAL_${String(domain).replace(/[^a-zA-Z0-9]/gu, '_').toUpperCase()}_PORT`;
191
+ const configuredPort = env[portEnv];
192
+ const port = configuredPort === undefined ? overlayPort : Number(configuredPort);
193
+ const serverExecution = localOverlay.serverExecution[app.id];
194
+ if (!app.path || !Number.isInteger(overlayPort) || !Number.isInteger(port) || port < 1 || port > 65535 || !serverExecution?.node) {
195
+ throw new Error(`${app.id} is missing its declared path, port or Node server execution.`);
196
+ }
197
+ const appManifest = readJson(path.join(workspaceRoot, app.path, 'package.json'));
198
+ if (app.package !== appManifest.name || typeof appManifest.version !== 'string') {
199
+ throw new Error(`${app.id} topology package identity must match package.json`);
200
+ }
201
+ const api = { ...app.api, prefix: app.api.bff?.prefix };
202
+ const declared = { ...app, api, serverExecution };
203
+ const publicUrlEnv = app.cloudflare?.publicUrlEnv;
204
+ const configuredPublicUrl = publicUrlEnv ? env[publicUrlEnv] : undefined;
205
+ const publicOrigin = configuredPublicUrl
206
+ ? new URL(configuredPublicUrl).origin
207
+ : `http://localhost:${port}`;
208
+ if (!/^https?:\/\//u.test(publicOrigin)) {
209
+ throw new Error(`${app.id} has an invalid declared public URL.`);
210
+ }
211
+ const nodeUrl = (declaredUrl) => {
212
+ const url = new URL(declaredUrl);
213
+ return url.origin === new URL(`http://localhost:${overlayPort}`).origin &&
214
+ url.username === '' &&
215
+ url.password === ''
216
+ ? `${publicOrigin}${url.pathname}${url.search}${url.hash}`
217
+ : declaredUrl;
218
+ };
219
+ return {
187
220
  id: app.id,
188
- directory:
189
- typeof app.path === 'string' ? normalizeRelativePath(app.path) : `verticals/${app.id}`,
190
- backendName: createBackendName(app),
191
- manifestUrl: createBackendManifestUrl(app),
192
- containerEntry: createBackendContainerEntry(app),
193
- port: app.port,
194
- portEnv: app.portEnv,
195
- remoteType: resolveRemoteType(app),
196
- smokeChecks: collectJsonSmokeChecks(apps, app),
197
- compactDeliveryUnit:
221
+ directory: normalizeRelativePath(app.path),
222
+ backendName: createBackendName(declared),
223
+ manifestUrl: nodeUrl(createBackendManifestUrl(declared)),
224
+ containerEntry: nodeUrl(createBackendContainerEntry(declared)),
225
+ port,
226
+ portEnv,
227
+ remoteType: resolveRemoteType(declared),
228
+ apiProtocol: app.api.protocol ?? 'rest',
229
+ apiPrefix: app.api.bff?.prefix,
230
+ rpcPath: app.api.rpcPath,
231
+ rpcSerialization: app.api.rpcSerialization,
232
+ apiOnly: app.surfaceProfile === 'api-only',
233
+ smokeChecks: collectJsonSmokeChecks(apps, declared),
234
+ topologyDeliveryUnit:
198
235
  app.deliveryUnit && typeof app.deliveryUnit === 'object'
199
236
  ? app.deliveryUnit
200
237
  : undefined,
201
- }));
238
+ packageName: appManifest.name,
239
+ version: appManifest.version,
240
+ };
241
+ });
202
242
 
203
243
  if (appFilter && filteredApps.length === 0) {
204
244
  throw new Error(`No vertical API app matched --app ${appFilter}`);
@@ -440,7 +480,7 @@ function sha256(bytes) {
440
480
  return createHash('sha256').update(bytes).digest('hex');
441
481
  }
442
482
 
443
- function readBoundReleaseEnvelope(app, target) {
483
+ export function readBoundReleaseEnvelope(app, target) {
444
484
  const targetDirectory = path.join(workspaceRoot, app.directory, target);
445
485
  const envelopePath = path.join(targetDirectory, releaseEnvelopePath);
446
486
  assertFile(envelopePath, app.id, 'Node release envelope');
@@ -451,6 +491,18 @@ function readBoundReleaseEnvelope(app, target) {
451
491
  `${app.id} release-envelope schema`,
452
492
  );
453
493
  assertEqual(envelope.target, 'node', `${app.id} release-envelope target`);
494
+ assertEqual(
495
+ envelope.kind,
496
+ 'ultramodern-target-microvertical-release-envelope',
497
+ `${app.id} release-envelope kind`,
498
+ );
499
+ if (app.apiOnly) {
500
+ if (envelope.surfaces?.uiClient?.length !== 0 || envelope.surfaces?.ssr?.length !== 0) {
501
+ throw new Error(`${app.id} API-only release envelope must declare empty UI/client and SSR surfaces`);
502
+ }
503
+ } else if (!envelope.surfaces?.uiClient?.length || !envelope.surfaces?.ssr?.length) {
504
+ throw new Error(`${app.id} full-stack release envelope must bind UI/client and SSR surfaces`);
505
+ }
454
506
 
455
507
  const manifestLogicalPath = envelope.surfaces?.backendFederation?.manifest;
456
508
  const containerLogicalPath = envelope.surfaces?.backendFederation?.container;
@@ -696,6 +748,98 @@ async function proveLiveApi(app, manifest, releaseBinding) {
696
748
  };
697
749
  }
698
750
 
751
+ export async function proveLiveRpcApi(app, loaded, manifest, releaseBinding) {
752
+ const contract = loaded.contract;
753
+ if (contract?.protocol !== 'rpc' || typeof contract.group !== 'string' ||
754
+ typeof contract.path !== 'string' || contract.serialization !== 'json') {
755
+ throw new Error(`${app.id} backend expose missing native RPC contract`);
756
+ }
757
+ assertEqual(contract.path, app.rpcPath, `${app.id} RPC contract/topology path`);
758
+ assertEqual(contract.path, manifest.backendFederation?.rpcPath, `${app.id} RPC contract/manifest path`);
759
+ assertEqual(contract.serialization, app.rpcSerialization, `${app.id} RPC contract/topology serialization`);
760
+ assertEqual(contract.serialization, manifest.backendFederation?.rpcSerialization, `${app.id} RPC contract/manifest serialization`);
761
+ const check = app.smokeChecks.find((entry) => entry?.body?.method === 'list' && entry.route === contract.path);
762
+ if (!check || !Number.isInteger(check.body?.params?.limit) || check.body.params.limit < 1) {
763
+ throw new Error(`${app.id} has no declared RPC list smoke check`);
764
+ }
765
+ const route = normalizeRoutePath(contract.path);
766
+ const url = new URL(route, app.manifestUrl).href;
767
+ const clientModule = createRequire(
768
+ path.join(workspaceRoot, app.directory, 'package.json'),
769
+ )(`${app.packageName}/api/rpc-client`);
770
+ const clientName = toPascalCase(contract.group);
771
+ const localContract = clientModule[`${clientName}RpcContract`];
772
+ if (localContract?.path !== contract.path ||
773
+ localContract?.group !== contract.group ||
774
+ localContract?.serialization !== contract.serialization ||
775
+ localContract?.protocol !== contract.protocol) {
776
+ throw new Error(`${app.id} public RPC client contract does not match the verified backend expose`);
777
+ }
778
+ const makeClient = clientModule[`make${clientName}RpcClient`];
779
+ if (typeof makeClient !== 'function' ||
780
+ typeof clientModule.Effect?.runPromise !== 'function') {
781
+ throw new Error(`${app.id} has no native public RPC client`);
782
+ }
783
+ const client = await clientModule.Effect.runPromise(makeClient({ url }));
784
+ try {
785
+ const listed = await clientModule.Effect.runPromise(client.list({ limit: check.body.params.limit }));
786
+ const item = listed?.items?.[0];
787
+ if (typeof item?.id !== 'string' || item.id.length === 0) {
788
+ throw new Error(`${app.id} native RPC list returned no item id`);
789
+ }
790
+ for (const expectation of normalizeJsonExpectations(check)) {
791
+ if (expectation.path === 'id') {
792
+ assertJsonEqual(check.body.id, expectation.value, `${app.id} declared RPC request id`);
793
+ } else if (expectation.path.startsWith('result.')) {
794
+ assertJsonEqual(
795
+ jsonPathValue(listed, expectation.path.slice('result.'.length)),
796
+ expectation.value,
797
+ `${app.id} native RPC ${expectation.path}`,
798
+ );
799
+ } else {
800
+ throw new Error(`${app.id} RPC smoke check has unsupported expectation ${expectation.path}`);
801
+ }
802
+ }
803
+ const fetched = await clientModule.Effect.runPromise(client.get({ id: item.id }));
804
+ assertEqual(fetched?.id, item.id, `${app.id} native RPC get item id`);
805
+ const missingId = `__ultramodern-proof-missing-${item.id}__`;
806
+ const missing = await clientModule.Effect.runPromise(
807
+ clientModule.Effect.match(client.get({ id: missingId }), {
808
+ onFailure: (error) => ({ error }),
809
+ onSuccess: (value) => ({ value }),
810
+ }),
811
+ );
812
+ const expectedErrorTag = `${toPascalCase(contract.group)}NotFoundRpc`;
813
+ if (missing?.error?._tag !== expectedErrorTag ||
814
+ missing.error?.id !== missingId) {
815
+ throw new Error(`${app.id} native RPC get did not return ${expectedErrorTag} for a missing item`);
816
+ }
817
+ return {
818
+ method: 'RPC',
819
+ route,
820
+ url,
821
+ protocol: contract.protocol,
822
+ serialization: contract.serialization,
823
+ group: contract.group,
824
+ operations: [
825
+ { method: 'list', itemId: item.id, status: 'pass' },
826
+ { method: 'get', itemId: fetched.id, status: 'pass' },
827
+ { method: 'get', errorTag: missing.error._tag, missingId, status: 'pass' },
828
+ ],
829
+ envelopeDigest: releaseBinding.envelope.envelopeDigest,
830
+ apiBackendArtifacts: releaseBinding.apiBackendArtifacts.map((artifact) => ({
831
+ logicalPath: artifact.logicalPath,
832
+ runtime: artifact.runtime,
833
+ byteLength: artifact.byteLength,
834
+ sha256: artifact.sha256,
835
+ })),
836
+ status: 'pass',
837
+ };
838
+ } finally {
839
+ await client.dispose();
840
+ }
841
+ }
842
+
699
843
  function jsonPathValue(value, path) {
700
844
  const segments = String(path ?? '')
701
845
  .split('.')
@@ -748,12 +892,17 @@ async function runSmokeChecks(app, loaded, createEffectBffTestHandler) {
748
892
  throw new Error(`${app.id} backend runtime cannot create Effect test handler`);
749
893
  }
750
894
 
751
- const servicePrefix = loaded.contract?.servicePrefix ?? loaded.contract?.apiPrefix;
895
+ const servicePrefix = loaded.contract?.protocol === 'rpc'
896
+ ? app.apiPrefix
897
+ : loaded.contract?.servicePrefix ?? loaded.contract?.apiPrefix;
752
898
  if (typeof servicePrefix !== 'string' || servicePrefix.length === 0) {
753
899
  throw new Error(
754
- `${app.id} backend expose missing contract.servicePrefix/apiPrefix`,
900
+ `${app.id} backend expose missing declared API prefix`,
755
901
  );
756
902
  }
903
+ if (loaded.contract?.protocol === 'rpc') {
904
+ assertEqual(loaded.contract.path, app.rpcPath, `${app.id} RPC smoke route`);
905
+ }
757
906
 
758
907
  const edge = await createEffectBffTestHandler({
759
908
  module: loaded.runtime,
@@ -962,10 +1111,10 @@ function validateManifest(app, manifest, buildIdentity) {
962
1111
  }
963
1112
  }
964
1113
 
965
- function assertCompactStableIdentityMatchesBuild(app, buildIdentity) {
966
- const compactDeliveryUnit = app.compactDeliveryUnit;
967
- if (!compactDeliveryUnit) {
968
- return;
1114
+ function assertTopologyStableIdentityMatchesBuild(app, buildIdentity) {
1115
+ const topologyDeliveryUnit = app.topologyDeliveryUnit;
1116
+ if (!topologyDeliveryUnit) {
1117
+ throw new Error(`${app.id} is missing its declared topology delivery-unit identity`);
969
1118
  }
970
1119
 
971
1120
  const mismatches = [];
@@ -974,20 +1123,22 @@ function assertCompactStableIdentityMatchesBuild(app, buildIdentity) {
974
1123
  mismatches.push(`${label}: deliveryUnit=${a} vs ultramodern-build=${b}`);
975
1124
  }
976
1125
  };
977
- compare('unitId', compactDeliveryUnit.unitId, buildIdentity.unitId);
1126
+ compare('unitId', topologyDeliveryUnit.unitId, buildIdentity.unitId);
978
1127
  compare(
979
1128
  'packageName',
980
- compactDeliveryUnit.packageName,
1129
+ topologyDeliveryUnit.packageName,
981
1130
  buildIdentity.packageName,
982
1131
  );
983
- compare('version', compactDeliveryUnit.version, buildIdentity.version);
1132
+ compare('version', topologyDeliveryUnit.version, buildIdentity.version);
1133
+ compare('packageName', app.packageName, buildIdentity.packageName);
1134
+ compare('version', app.version, buildIdentity.version);
984
1135
 
985
1136
  if (mismatches.length > 0) {
986
1137
  throw new Error(
987
1138
  `${app.id} delivery-unit identity drift between ${path.relative(
988
1139
  workspaceRoot,
989
- compactConfigPath,
990
- )} (generation metadata) and ${path.relative(
1140
+ topologyPath,
1141
+ )} (reference topology) and ${path.relative(
991
1142
  workspaceRoot,
992
1143
  buildIdentity.artifactPath,
993
1144
  )} (stamped target identity): ${mismatches.join('; ')}`,
@@ -1006,7 +1157,7 @@ async function proveBackend(app, backendRuntime, target) {
1006
1157
  assertFile(entryPath, app.id, 'backend remote entry');
1007
1158
 
1008
1159
  const buildIdentity = readBuildIdentity(app, target);
1009
- assertCompactStableIdentityMatchesBuild(app, buildIdentity);
1160
+ assertTopologyStableIdentityMatchesBuild(app, buildIdentity);
1010
1161
  const manifest = readJson(manifestPath);
1011
1162
  validateManifest(app, manifest, buildIdentity);
1012
1163
  const releaseBinding = readBoundReleaseEnvelope(app, target);
@@ -1108,7 +1259,9 @@ async function proveBackend(app, backendRuntime, target) {
1108
1259
  }
1109
1260
 
1110
1261
  const smokeChecks = await runSmokeChecks(app, loaded, createEffectBffTestHandler);
1111
- const liveApi = await proveLiveApi(app, manifest, releaseBinding);
1262
+ const liveApi = loaded.contract?.protocol === 'rpc'
1263
+ ? await proveLiveRpcApi(app, loaded, manifest, releaseBinding)
1264
+ : await proveLiveApi(app, manifest, releaseBinding);
1112
1265
 
1113
1266
  return {
1114
1267
  appId: app.id,
@@ -1185,9 +1338,10 @@ async function main(argv = process.argv.slice(2)) {
1185
1338
  return 0;
1186
1339
  }
1187
1340
 
1188
- const config = readJson(compactConfigPath);
1189
- const runtimeApps = compactApps(config);
1190
- const apps = args.app ? compactApps(config, args.app) : runtimeApps;
1341
+ const topology = readJson(topologyPath);
1342
+ const localOverlay = readJson(localOverlayPath);
1343
+ const runtimeApps = topologyApps(topology, localOverlay);
1344
+ const apps = args.app ? topologyApps(topology, localOverlay, args.app) : runtimeApps;
1191
1345
  const results = [];
1192
1346
  const backendRuntime =
1193
1347
  apps.length > 0 ? await importBackendFederationRuntime() : undefined;