@bleedingdev/modern-js-create 3.4.0-ultramodern.12 → 3.4.0-ultramodern.14

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 (108) hide show
  1. package/README.md +13 -11
  2. package/dist/cjs/index.cjs +36 -3
  3. package/dist/cjs/locale/en.cjs +10 -0
  4. package/dist/cjs/locale/zh.cjs +10 -0
  5. package/dist/cjs/ultramodern-tooling/commands.cjs +185 -0
  6. package/dist/cjs/ultramodern-tooling/config.cjs +248 -0
  7. package/dist/cjs/ultramodern-workspace/add-vertical.cjs +64 -25
  8. package/dist/cjs/ultramodern-workspace/bridge-config.cjs +327 -0
  9. package/dist/cjs/ultramodern-workspace/codesmith.cjs +1 -0
  10. package/dist/cjs/ultramodern-workspace/contracts.cjs +119 -653
  11. package/dist/cjs/ultramodern-workspace/descriptors.cjs +4 -0
  12. package/dist/cjs/ultramodern-workspace/fs-io.cjs +117 -0
  13. package/dist/cjs/ultramodern-workspace/generation-result.cjs +1 -1
  14. package/dist/cjs/ultramodern-workspace/index.cjs +4 -0
  15. package/dist/cjs/ultramodern-workspace/mf-validation.cjs +572 -0
  16. package/dist/cjs/ultramodern-workspace/module-federation.cjs +14 -0
  17. package/dist/cjs/ultramodern-workspace/package-json.cjs +26 -12
  18. package/dist/cjs/ultramodern-workspace/public-api.cjs +4 -0
  19. package/dist/cjs/ultramodern-workspace/workspace-scripts.cjs +74 -44
  20. package/dist/cjs/ultramodern-workspace/write-workspace.cjs +55 -15
  21. package/dist/esm/index.js +36 -3
  22. package/dist/esm/locale/en.js +10 -0
  23. package/dist/esm/locale/zh.js +10 -0
  24. package/dist/esm/ultramodern-tooling/commands.js +132 -0
  25. package/dist/esm/ultramodern-tooling/config.js +196 -0
  26. package/dist/esm/ultramodern-workspace/add-vertical.js +65 -29
  27. package/dist/esm/ultramodern-workspace/bridge-config.js +270 -0
  28. package/dist/esm/ultramodern-workspace/codesmith.js +1 -0
  29. package/dist/esm/ultramodern-workspace/contracts.js +122 -608
  30. package/dist/esm/ultramodern-workspace/descriptors.js +2 -1
  31. package/dist/esm/ultramodern-workspace/fs-io.js +116 -2
  32. package/dist/esm/ultramodern-workspace/generation-result.js +2 -2
  33. package/dist/esm/ultramodern-workspace/index.js +1 -0
  34. package/dist/esm/ultramodern-workspace/mf-validation.js +517 -0
  35. package/dist/esm/ultramodern-workspace/module-federation.js +14 -0
  36. package/dist/esm/ultramodern-workspace/package-json.js +26 -12
  37. package/dist/esm/ultramodern-workspace/public-api.js +1 -0
  38. package/dist/esm/ultramodern-workspace/workspace-scripts.js +75 -27
  39. package/dist/esm/ultramodern-workspace/write-workspace.js +56 -19
  40. package/dist/esm-node/index.js +36 -3
  41. package/dist/esm-node/locale/en.js +10 -0
  42. package/dist/esm-node/locale/zh.js +10 -0
  43. package/dist/esm-node/ultramodern-tooling/commands.js +133 -0
  44. package/dist/esm-node/ultramodern-tooling/config.js +197 -0
  45. package/dist/esm-node/ultramodern-workspace/add-vertical.js +65 -29
  46. package/dist/esm-node/ultramodern-workspace/bridge-config.js +271 -0
  47. package/dist/esm-node/ultramodern-workspace/codesmith.js +1 -0
  48. package/dist/esm-node/ultramodern-workspace/contracts.js +122 -608
  49. package/dist/esm-node/ultramodern-workspace/descriptors.js +2 -1
  50. package/dist/esm-node/ultramodern-workspace/fs-io.js +116 -2
  51. package/dist/esm-node/ultramodern-workspace/generation-result.js +2 -2
  52. package/dist/esm-node/ultramodern-workspace/index.js +1 -0
  53. package/dist/esm-node/ultramodern-workspace/mf-validation.js +518 -0
  54. package/dist/esm-node/ultramodern-workspace/module-federation.js +14 -0
  55. package/dist/esm-node/ultramodern-workspace/package-json.js +26 -12
  56. package/dist/esm-node/ultramodern-workspace/public-api.js +1 -0
  57. package/dist/esm-node/ultramodern-workspace/workspace-scripts.js +75 -27
  58. package/dist/esm-node/ultramodern-workspace/write-workspace.js +56 -19
  59. package/dist/types/locale/en.d.ts +10 -0
  60. package/dist/types/locale/index.d.ts +20 -0
  61. package/dist/types/locale/zh.d.ts +10 -0
  62. package/dist/types/ultramodern-tooling/commands.d.ts +1 -0
  63. package/dist/types/ultramodern-tooling/config.d.ts +43 -0
  64. package/dist/types/ultramodern-workspace/add-vertical.d.ts +5 -2
  65. package/dist/types/ultramodern-workspace/bridge-config.d.ts +64 -0
  66. package/dist/types/ultramodern-workspace/codesmith.d.ts +1 -0
  67. package/dist/types/ultramodern-workspace/contracts.d.ts +2 -17
  68. package/dist/types/ultramodern-workspace/descriptors.d.ts +1 -0
  69. package/dist/types/ultramodern-workspace/fs-io.d.ts +1 -0
  70. package/dist/types/ultramodern-workspace/index.d.ts +2 -0
  71. package/dist/types/ultramodern-workspace/mf-validation.d.ts +27 -0
  72. package/dist/types/ultramodern-workspace/package-json.d.ts +4 -3
  73. package/dist/types/ultramodern-workspace/public-api.d.ts +2 -0
  74. package/dist/types/ultramodern-workspace/types.d.ts +2 -0
  75. package/dist/types/ultramodern-workspace/workspace-scripts.d.ts +1 -7
  76. package/dist/types/ultramodern-workspace/write-workspace.d.ts +4 -2
  77. package/package.json +5 -3
  78. package/template-workspace/{.agents → .codex}/skills-lock.json +12 -12
  79. package/template-workspace/.gitignore.handlebars +3 -0
  80. package/template-workspace/AGENTS.md.handlebars +11 -5
  81. package/template-workspace/README.md.handlebars +15 -12
  82. package/template-workspace/oxfmt.config.ts +1 -0
  83. package/template-workspace/oxlint.config.ts +1 -0
  84. package/template-workspace/scripts/bootstrap-agent-skills.mjs +77 -67
  85. package/templates/workspace-scripts/assert-mf-types.mjs.handlebars +56 -3
  86. package/templates/workspace-scripts/generate-public-surface-assets.mjs +239 -4
  87. package/templates/workspace-scripts/proof-cloudflare-version.mjs +282 -4
  88. package/templates/workspace-scripts/ultramodern-performance-readiness.mjs +172 -1
  89. package/templates/workspace-scripts/ultramodern-typecheck.mjs +4 -2
  90. package/templates/workspace-scripts/validate-ultramodern-workspace.mjs.handlebars +783 -26
  91. /package/template-workspace/{.agents → .codex}/rstackjs-agent-skills-LICENSE +0 -0
  92. /package/template-workspace/{.agents → .codex}/skills/rsbuild-best-practices/SKILL.md +0 -0
  93. /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/SKILL.md +0 -0
  94. /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/command-map.md +0 -0
  95. /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/common-analysis-patterns.md +0 -0
  96. /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/install-rsdoctor-common.md +0 -0
  97. /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/install-rsdoctor-rspack.md +0 -0
  98. /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/install-rsdoctor-webpack.md +0 -0
  99. /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/install-rsdoctor.md +0 -0
  100. /package/template-workspace/{.agents → .codex}/skills/rsdoctor-analysis/references/rsdoctor-data-types.md +0 -0
  101. /package/template-workspace/{.agents → .codex}/skills/rslib-best-practices/SKILL.md +0 -0
  102. /package/template-workspace/{.agents → .codex}/skills/rslib-modern-package/SKILL.md +0 -0
  103. /package/template-workspace/{.agents → .codex}/skills/rspack-best-practices/SKILL.md +0 -0
  104. /package/template-workspace/{.agents → .codex}/skills/rspack-tracing/SKILL.md +0 -0
  105. /package/template-workspace/{.agents → .codex}/skills/rspack-tracing/references/bottlenecks.md +0 -0
  106. /package/template-workspace/{.agents → .codex}/skills/rspack-tracing/references/tracing-guide.md +0 -0
  107. /package/template-workspace/{.agents → .codex}/skills/rspack-tracing/scripts/analyze_trace.js +0 -0
  108. /package/template-workspace/{.agents → .codex}/skills/rstest-best-practices/SKILL.md +0 -0
@@ -4,18 +4,253 @@ import path from 'node:path';
4
4
  import { fileURLToPath, pathToFileURL } from 'node:url';
5
5
 
6
6
  const workspaceRoot = path.resolve(
7
- path.dirname(fileURLToPath(import.meta.url)),
8
- '..',
7
+ process.env.ULTRAMODERN_WORKSPACE_ROOT ??
8
+ path.join(path.dirname(fileURLToPath(import.meta.url)), '..'),
9
9
  );
10
10
  const contractPath = path.join(
11
11
  workspaceRoot,
12
12
  '.modernjs/ultramodern-generated-contract.json',
13
13
  );
14
+ const compactConfigPath = path.join(workspaceRoot, '.modernjs/ultramodern.json');
14
15
 
15
16
  function readJson(filePath) {
16
17
  return JSON.parse(fs.readFileSync(filePath, 'utf-8'));
17
18
  }
18
19
 
20
+ function toKebabCase(value) {
21
+ return String(value)
22
+ .trim()
23
+ .replace(/([a-z0-9])([A-Z])/gu, '$1-$2')
24
+ .replace(/[^a-zA-Z0-9._-]+/gu, '-')
25
+ .replace(/[._]+/gu, '-')
26
+ .toLowerCase()
27
+ .replace(/-+/gu, '-')
28
+ .replace(/^-+|-+$/gu, '');
29
+ }
30
+
31
+ function toEnvSegment(value) {
32
+ return toKebabCase(value).replace(/-/gu, '_').toUpperCase();
33
+ }
34
+
35
+ function normalizeRelativePath(value) {
36
+ return String(value ?? '').replace(/\\/gu, '/').replace(/^\.\/+/u, '');
37
+ }
38
+
39
+ function appNamespace(app) {
40
+ return app.kind === 'shell' ? 'shell' : (app.domain ?? app.id);
41
+ }
42
+
43
+ function defaultPortEnv(app) {
44
+ return app.kind === 'shell'
45
+ ? 'SHELL_SUPER_APP_PORT'
46
+ : `VERTICAL_${toEnvSegment(app.domain ?? app.id)}_PORT`;
47
+ }
48
+
49
+ function defaultPort(app) {
50
+ return app.kind === 'shell' ? 3020 : 3030;
51
+ }
52
+
53
+ function normalizeCompactApp(rawApp) {
54
+ const id = String(rawApp.id);
55
+ const kind = rawApp.kind === 'vertical' ? 'vertical' : 'shell';
56
+ const appPath =
57
+ typeof rawApp.path === 'string'
58
+ ? normalizeRelativePath(rawApp.path)
59
+ : kind === 'shell'
60
+ ? 'apps/shell-super-app'
61
+ : `verticals/${toKebabCase(id)}`;
62
+ const packageSuffix =
63
+ typeof rawApp.packageSuffix === 'string'
64
+ ? rawApp.packageSuffix
65
+ : appPath.split('/').at(-1) ?? id;
66
+ const domain =
67
+ typeof rawApp.domain === 'string'
68
+ ? rawApp.domain
69
+ : kind === 'vertical'
70
+ ? packageSuffix
71
+ : undefined;
72
+ const moduleFederation =
73
+ rawApp.moduleFederation && typeof rawApp.moduleFederation === 'object'
74
+ ? rawApp.moduleFederation
75
+ : {};
76
+
77
+ return {
78
+ id,
79
+ kind,
80
+ path: appPath,
81
+ packageSuffix,
82
+ domain,
83
+ port:
84
+ typeof rawApp.port === 'number'
85
+ ? rawApp.port
86
+ : defaultPort({ id, kind, domain }),
87
+ portEnv:
88
+ typeof rawApp.portEnv === 'string'
89
+ ? rawApp.portEnv
90
+ : defaultPortEnv({ id, kind, domain }),
91
+ mfName:
92
+ typeof moduleFederation.name === 'string'
93
+ ? moduleFederation.name
94
+ : kind === 'shell'
95
+ ? 'shellSuperApp'
96
+ : `vertical${toKebabCase(domain ?? id)
97
+ .split('-')
98
+ .filter(Boolean)
99
+ .map(part => part.charAt(0).toUpperCase() + part.slice(1))
100
+ .join('')}`,
101
+ exposes: Array.isArray(moduleFederation.exposes)
102
+ ? moduleFederation.exposes.filter(expose => typeof expose === 'string')
103
+ : [],
104
+ verticalRefs: Array.isArray(moduleFederation.verticalRefs)
105
+ ? moduleFederation.verticalRefs.filter(ref => typeof ref === 'string')
106
+ : [],
107
+ marker: {
108
+ appId: id,
109
+ },
110
+ effectApi:
111
+ rawApp.effectApi && typeof rawApp.effectApi === 'object'
112
+ ? {
113
+ stem:
114
+ typeof rawApp.effectApi.stem === 'string'
115
+ ? rawApp.effectApi.stem
116
+ : domain ?? id,
117
+ prefix:
118
+ typeof rawApp.effectApi.prefix === 'string'
119
+ ? rawApp.effectApi.prefix
120
+ : `/${domain ?? id}-api`,
121
+ }
122
+ : undefined,
123
+ };
124
+ }
125
+
126
+ function createRouteOwnedEntries(app) {
127
+ const namespace = appNamespace(app);
128
+ const base = {
129
+ descriptionKey: `${namespace}.seo.description`,
130
+ mfBoundaryId: app.mfName,
131
+ namespace,
132
+ ownerAppId: app.id,
133
+ public: false,
134
+ indexable: false,
135
+ publicSurface: 'private-app-screen',
136
+ };
137
+
138
+ return [
139
+ {
140
+ ...base,
141
+ canonicalPath: '/',
142
+ id: app.kind === 'shell' ? 'shell-home' : `${app.id}-home`,
143
+ localisedPaths: {
144
+ cs: '/',
145
+ en: '/',
146
+ },
147
+ titleKey: app.kind === 'shell' ? 'shell.title' : `${namespace}.title`,
148
+ },
149
+ ];
150
+ }
151
+
152
+ function createPublicRoutes(app) {
153
+ return createRouteOwnedEntries(app)
154
+ .filter(route => route.public && route.indexable)
155
+ .map(route => ({
156
+ canonicalPath: route.canonicalPath,
157
+ id: route.id,
158
+ localisedPaths: route.localisedPaths,
159
+ namespace: route.namespace,
160
+ ownerAppId: route.ownerAppId,
161
+ descriptionKey: route.descriptionKey,
162
+ titleKey: route.titleKey,
163
+ }));
164
+ }
165
+
166
+ function createPublicSurface(app) {
167
+ const publicRoutes = createPublicRoutes(app);
168
+ return {
169
+ authoring: 'colocated-route-meta',
170
+ artifactLifecycle: 'build-and-deploy-output',
171
+ generatedManifest: './src/routes/ultramodern-route-metadata',
172
+ source: 'route-owned-public-routes',
173
+ metadataExport: './src/routes/ultramodern-route-metadata',
174
+ generator: 'scripts/generate-public-surface-assets.mjs',
175
+ outputRoot: 'dist/public',
176
+ cloudflareOutputRoot: '.output/public',
177
+ privateRoutePolicy: 'omit-from-generated-public-surface',
178
+ files:
179
+ publicRoutes.length > 0
180
+ ? ['robots.txt', 'sitemap.xml', 'site.webmanifest']
181
+ : ['robots.txt'],
182
+ omittedByDefault: ['api-catalog.json', 'llms.txt', 'security.txt'],
183
+ languages: ['en', 'cs'],
184
+ contentExpansion: {
185
+ authoring: 'route-owned-esm-provider',
186
+ defaultProviderFile: 'route.sitemap.mjs',
187
+ entryExport: 'default-or-entries',
188
+ paramsSource: 'params-or-localeParams',
189
+ draftPolicy: 'omit-draft-by-default',
190
+ indexablePolicy: 'omit-indexable-false',
191
+ lifecycle: 'executed-during-public-surface-generation',
192
+ },
193
+ contentSources: [],
194
+ publicRoutes,
195
+ routeEntries: [],
196
+ concreteUrlPaths: [],
197
+ };
198
+ }
199
+
200
+ function createCloudflareDeploy(config, app) {
201
+ const packageScope =
202
+ typeof config.workspace?.packageScope === 'string'
203
+ ? config.workspace.packageScope
204
+ : path.basename(workspaceRoot);
205
+ const compatibilityDate =
206
+ typeof config.deploy?.worker?.compatibilityDate === 'string'
207
+ ? config.deploy.worker.compatibilityDate
208
+ : '2026-06-02';
209
+ return {
210
+ workerName: `${toKebabCase(packageScope)}-${app.packageSuffix}`.slice(0, 63),
211
+ publicUrlEnv: `ULTRAMODERN_PUBLIC_URL_${toEnvSegment(app.id)}`,
212
+ compatibilityDate,
213
+ compatibilityFlags: ['nodejs_compat', 'global_fetch_strictly_public'],
214
+ };
215
+ }
216
+
217
+ function synthesizeContractFromCompactConfig(config) {
218
+ const apps = Array.isArray(config.topology?.apps)
219
+ ? config.topology.apps.map(normalizeCompactApp)
220
+ : [];
221
+
222
+ return {
223
+ sourcePath: compactConfigPath,
224
+ apps: apps.map(app => ({
225
+ ...app,
226
+ deploy: {
227
+ cloudflare: createCloudflareDeploy(config, app),
228
+ },
229
+ routes: {
230
+ publicSurface: createPublicSurface(app),
231
+ },
232
+ })),
233
+ };
234
+ }
235
+
236
+ function readGeneratedContractView() {
237
+ if (fs.existsSync(compactConfigPath)) {
238
+ return synthesizeContractFromCompactConfig(readJson(compactConfigPath));
239
+ }
240
+ if (fs.existsSync(contractPath)) {
241
+ return {
242
+ sourcePath: contractPath,
243
+ ...readJson(contractPath),
244
+ };
245
+ }
246
+ throw new Error(
247
+ `Missing UltraModern config. Expected ${path.relative(
248
+ workspaceRoot,
249
+ compactConfigPath,
250
+ )} or ${path.relative(workspaceRoot, contractPath)}.`,
251
+ );
252
+ }
253
+
19
254
  function parseArgs(argv) {
20
255
  const parsed = {
21
256
  appId: undefined,
@@ -517,10 +752,10 @@ try {
517
752
  printHelp();
518
753
  process.exit(0);
519
754
  }
520
- const contract = readJson(contractPath);
755
+ const contract = readGeneratedContractView();
521
756
  const app = contract.apps?.find(candidate => candidate.id === args.appId);
522
757
  if (!app) {
523
- throw new Error(`Unknown app in generated contract: ${args.appId}`);
758
+ throw new Error(`Unknown app in UltraModern config: ${args.appId}`);
524
759
  }
525
760
  await generatePublicSurfaceAssets(app, args.target, args.requirePublicOrigin);
526
761
  } catch (error) {
@@ -1,17 +1,19 @@
1
1
  #!/usr/bin/env node
2
+ import crypto from 'node:crypto';
2
3
  import fs from 'node:fs';
3
4
  import path from 'node:path';
4
5
  import { fileURLToPath } from 'node:url';
5
6
  import { validateApp } from './ultramodern-cloudflare-proof.mjs';
6
7
 
7
8
  const workspaceRoot = path.resolve(
8
- path.dirname(fileURLToPath(import.meta.url)),
9
- '..',
9
+ process.env.ULTRAMODERN_WORKSPACE_ROOT ??
10
+ path.join(path.dirname(fileURLToPath(import.meta.url)), '..'),
10
11
  );
11
12
  const contractPath = path.join(
12
13
  workspaceRoot,
13
14
  '.modernjs/ultramodern-generated-contract.json',
14
15
  );
16
+ const compactConfigPath = path.join(workspaceRoot, '.modernjs/ultramodern.json');
15
17
  const defaultOut = path.join(
16
18
  workspaceRoot,
17
19
  '.codex/reports/cloudflare-version-proof/public-url-proof.json',
@@ -21,6 +23,282 @@ function readJson(filePath) {
21
23
  return JSON.parse(fs.readFileSync(filePath, 'utf8'));
22
24
  }
23
25
 
26
+ function toKebabCase(value) {
27
+ return String(value)
28
+ .trim()
29
+ .replace(/([a-z0-9])([A-Z])/gu, '$1-$2')
30
+ .replace(/[^a-zA-Z0-9._-]+/gu, '-')
31
+ .replace(/[._]+/gu, '-')
32
+ .toLowerCase()
33
+ .replace(/-+/gu, '-')
34
+ .replace(/^-+|-+$/gu, '');
35
+ }
36
+
37
+ function toPascalCase(value) {
38
+ return toKebabCase(value)
39
+ .split('-')
40
+ .filter(Boolean)
41
+ .map(part => part.charAt(0).toUpperCase() + part.slice(1))
42
+ .join('');
43
+ }
44
+
45
+ function toEnvSegment(value) {
46
+ return toKebabCase(value).replace(/-/gu, '_').toUpperCase();
47
+ }
48
+
49
+ function normalizeRelativePath(value) {
50
+ return String(value ?? '').replace(/\\/gu, '/').replace(/^\.\/+/u, '');
51
+ }
52
+
53
+ function appNamespace(app) {
54
+ return app.kind === 'shell' ? 'shell' : (app.domain ?? app.id);
55
+ }
56
+
57
+ function normalizeCompactApp(rawApp) {
58
+ const id = String(rawApp.id);
59
+ const kind = rawApp.kind === 'vertical' ? 'vertical' : 'shell';
60
+ const appPath =
61
+ typeof rawApp.path === 'string'
62
+ ? normalizeRelativePath(rawApp.path)
63
+ : kind === 'shell'
64
+ ? 'apps/shell-super-app'
65
+ : `verticals/${toKebabCase(id)}`;
66
+ const packageSuffix =
67
+ typeof rawApp.packageSuffix === 'string'
68
+ ? rawApp.packageSuffix
69
+ : appPath.split('/').at(-1) ?? id;
70
+ const domain =
71
+ typeof rawApp.domain === 'string'
72
+ ? rawApp.domain
73
+ : kind === 'vertical'
74
+ ? packageSuffix
75
+ : undefined;
76
+ const moduleFederation =
77
+ rawApp.moduleFederation && typeof rawApp.moduleFederation === 'object'
78
+ ? rawApp.moduleFederation
79
+ : {};
80
+ const effectApi =
81
+ rawApp.effectApi && typeof rawApp.effectApi === 'object'
82
+ ? {
83
+ stem:
84
+ typeof rawApp.effectApi.stem === 'string'
85
+ ? rawApp.effectApi.stem
86
+ : domain ?? id,
87
+ prefix:
88
+ typeof rawApp.effectApi.prefix === 'string'
89
+ ? rawApp.effectApi.prefix
90
+ : `/${domain ?? id}-api`,
91
+ }
92
+ : undefined;
93
+
94
+ return {
95
+ id,
96
+ kind,
97
+ path: appPath,
98
+ packageSuffix,
99
+ domain,
100
+ mfName:
101
+ typeof moduleFederation.name === 'string'
102
+ ? moduleFederation.name
103
+ : kind === 'shell'
104
+ ? 'shellSuperApp'
105
+ : `vertical${toPascalCase(domain ?? id)}`,
106
+ effectApi,
107
+ };
108
+ }
109
+
110
+ function createBuildMarker(scope, app) {
111
+ return crypto
112
+ .createHash('sha256')
113
+ .update(`${scope}:${app.packageSuffix}:${app.id}:0.1.0`)
114
+ .digest('hex')
115
+ .slice(0, 16);
116
+ }
117
+
118
+ function createCloudflareSecurity() {
119
+ return {
120
+ enabled: true,
121
+ headers: {
122
+ referrerPolicy: 'strict-origin-when-cross-origin',
123
+ contentTypeOptions: 'nosniff',
124
+ permissionsPolicy:
125
+ 'camera=(), geolocation=(), microphone=(), payment=(), usb=()',
126
+ },
127
+ contentSecurityPolicy: {
128
+ mode: 'report-only',
129
+ directives: {
130
+ 'base-uri': [`'self'`],
131
+ 'connect-src': [`'self'`, 'https:', 'http:', 'wss:', 'ws:'],
132
+ 'default-src': [`'self'`],
133
+ 'font-src': [`'self'`, 'data:', 'https:', 'http:'],
134
+ 'form-action': [`'self'`],
135
+ 'frame-ancestors': [`'self'`],
136
+ 'img-src': [`'self'`, 'data:', 'blob:', 'https:', 'http:'],
137
+ 'manifest-src': [`'self'`, 'https:', 'http:'],
138
+ 'object-src': [`'none'`],
139
+ 'script-src': [
140
+ `'self'`,
141
+ `'unsafe-inline'`,
142
+ `'unsafe-eval'`,
143
+ 'https:',
144
+ 'http:',
145
+ 'blob:',
146
+ ],
147
+ 'style-src': [`'self'`, `'unsafe-inline'`, 'https:', 'http:'],
148
+ 'worker-src': [`'self'`, 'blob:'],
149
+ },
150
+ reason:
151
+ 'Report-only by default so Cloudflare Module Federation SSR can prove remote script, style, and connect compatibility before enforcement.',
152
+ },
153
+ noindex: {
154
+ workersDev: true,
155
+ localhost: true,
156
+ previewHostnames: [],
157
+ },
158
+ };
159
+ }
160
+
161
+ function createQualityGates() {
162
+ return {
163
+ publicRoutes: {
164
+ requireSitemapWhenPresent: true,
165
+ requireRobotsSitemapConsistency: true,
166
+ requireWebManifestWhenPresent: true,
167
+ },
168
+ statusCodes: {
169
+ notFoundRoute: '/__ultramodern-smoke-missing',
170
+ unknownRouteStatus: 404,
171
+ },
172
+ indexing: {
173
+ previewNoindex: true,
174
+ productionPublicRoutesIndexable: true,
175
+ },
176
+ assets: {
177
+ cssPreloadRequired: true,
178
+ cssResponseRequired: true,
179
+ cacheControlRequiredForCss: true,
180
+ sourcemapsPubliclyReferenced: false,
181
+ },
182
+ budgets: {
183
+ ssrHtmlMaxBytes: 250_000,
184
+ mfManifestMaxBytes: 500_000,
185
+ localeJsonMaxBytes: 100_000,
186
+ sitemapXmlMaxBytes: 500_000,
187
+ cssAssetMaxBytes: 750_000,
188
+ },
189
+ csp: {
190
+ finalMode: 'report-only-dogfood',
191
+ decision:
192
+ 'Report-only remains the generated final mode until public smoke proof records MF SSR script/style/connect compatibility for the deployed surface.',
193
+ },
194
+ };
195
+ }
196
+
197
+ function createPublicHead() {
198
+ return {
199
+ alternates: {
200
+ hreflang: ['en', 'cs'],
201
+ xDefault: 'en',
202
+ },
203
+ };
204
+ }
205
+
206
+ function createPublicSurface() {
207
+ return {
208
+ publicRoutes: [],
209
+ routeEntries: [],
210
+ contentSources: [],
211
+ concreteUrlPaths: [],
212
+ };
213
+ }
214
+
215
+ function createCloudflareRoutes(app) {
216
+ return {
217
+ ssr: '/en',
218
+ mfManifest: '/mf-manifest.json',
219
+ locale: `/locales/en/${appNamespace(app)}.json`,
220
+ ...(app.effectApi
221
+ ? {
222
+ effectReadiness: `${app.effectApi.prefix}/effect/${app.effectApi.stem}/readiness`,
223
+ }
224
+ : {}),
225
+ };
226
+ }
227
+
228
+ function createContractApp(config, app) {
229
+ const packageScope =
230
+ typeof config.workspace?.packageScope === 'string'
231
+ ? config.workspace.packageScope
232
+ : path.basename(workspaceRoot);
233
+ const compatibilityDate =
234
+ typeof config.deploy?.worker?.compatibilityDate === 'string'
235
+ ? config.deploy.worker.compatibilityDate
236
+ : '2026-06-02';
237
+
238
+ return {
239
+ id: app.id,
240
+ deploy: {
241
+ cloudflare: {
242
+ workerName: `${toKebabCase(packageScope)}-${app.packageSuffix}`.slice(
243
+ 0,
244
+ 63,
245
+ ),
246
+ publicUrlEnv: `ULTRAMODERN_PUBLIC_URL_${toEnvSegment(app.id)}`,
247
+ compatibilityDate,
248
+ compatibilityFlags: ['nodejs_compat', 'global_fetch_strictly_public'],
249
+ routes: createCloudflareRoutes(app),
250
+ security: createCloudflareSecurity(),
251
+ qualityGates: createQualityGates(),
252
+ },
253
+ },
254
+ i18n: {
255
+ namespace: appNamespace(app),
256
+ },
257
+ marker: {
258
+ appId: app.id,
259
+ build: createBuildMarker(packageScope, app),
260
+ },
261
+ routes: {
262
+ publicHead: createPublicHead(),
263
+ publicSurface: createPublicSurface(),
264
+ },
265
+ styling: {
266
+ federation: {
267
+ rootSelector: `[data-app-id="${app.id}"]`,
268
+ },
269
+ },
270
+ };
271
+ }
272
+
273
+ function synthesizeContractFromCompactConfig(config) {
274
+ const apps = Array.isArray(config.topology?.apps)
275
+ ? config.topology.apps.map(normalizeCompactApp)
276
+ : [];
277
+
278
+ return {
279
+ sourcePath: compactConfigPath,
280
+ apps: apps.map(app => createContractApp(config, app)),
281
+ };
282
+ }
283
+
284
+ function readGeneratedContractView() {
285
+ if (fs.existsSync(compactConfigPath)) {
286
+ return synthesizeContractFromCompactConfig(readJson(compactConfigPath));
287
+ }
288
+ if (fs.existsSync(contractPath)) {
289
+ return {
290
+ sourcePath: contractPath,
291
+ ...readJson(contractPath),
292
+ };
293
+ }
294
+ throw new Error(
295
+ `Missing UltraModern config. Expected ${path.relative(
296
+ workspaceRoot,
297
+ compactConfigPath,
298
+ )} or ${path.relative(workspaceRoot, contractPath)}.`,
299
+ );
300
+ }
301
+
24
302
  function parseArgs(argv) {
25
303
  const parsed = {
26
304
  appId: undefined,
@@ -70,7 +348,7 @@ async function main(argv = process.argv.slice(2)) {
70
348
  return 0;
71
349
  }
72
350
 
73
- const contract = readJson(contractPath);
351
+ const contract = readGeneratedContractView();
74
352
  const apps = args.appId
75
353
  ? contract.apps.filter(app => app.id === args.appId)
76
354
  : contract.apps;
@@ -101,7 +379,7 @@ async function main(argv = process.argv.slice(2)) {
101
379
  schemaVersion: 1,
102
380
  generatedAt: new Date().toISOString(),
103
381
  status: results.length > 0 ? 'pass' : 'skipped',
104
- contractPath,
382
+ contractPath: contract.sourcePath ?? contractPath,
105
383
  results,
106
384
  skipped,
107
385
  };