@tdk-landscape/tdk-cli-core 1.3.15 → 1.3.26

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 (274) hide show
  1. package/Tiltfile +144 -0
  2. package/discovery/AGENTS.md +362 -0
  3. package/discovery/TILT_DISCOVERY.star +424 -0
  4. package/discovery/Tiltfile +58 -0
  5. package/discovery/config.star +258 -0
  6. package/discovery/constants.star +127 -0
  7. package/discovery/deterministic.star +211 -0
  8. package/discovery/discovery_daemon.star +191 -0
  9. package/discovery/discovery_orchestrator.star +460 -0
  10. package/discovery/filtering.star +5 -0
  11. package/discovery/identity-management-backend/service.yaml +26 -0
  12. package/discovery/identity-management-frontend/service.yaml +29 -0
  13. package/discovery/identity-sdk/service.yaml +9 -0
  14. package/discovery/incremental_discovery.star +213 -0
  15. package/discovery/indexing.star +7 -0
  16. package/discovery/json_manifest_scanner.star +51 -0
  17. package/discovery/libraries.star +46 -0
  18. package/discovery/loading.star +23 -0
  19. package/discovery/manifest/constants.star +104 -0
  20. package/discovery/manifest/loading.star +386 -0
  21. package/discovery/manifest/normalize.star +281 -0
  22. package/discovery/manifest/validation.star +108 -0
  23. package/discovery/normalization.star +11 -0
  24. package/discovery/registry.star +544 -0
  25. package/discovery/resource_snapshot.py +382 -0
  26. package/discovery/resource_snapshot.star +143 -0
  27. package/discovery/schemas.star +1 -0
  28. package/discovery/services/platform/cdc/debezium/nats-connector/service.yaml +9 -0
  29. package/discovery/services/platform/cdc/nats-http-bridge/service.yaml +9 -0
  30. package/discovery/services/platform/orchestrator/orchestrator-glue-backend/service.yaml +26 -0
  31. package/discovery/services/platform/synthetic-monitor/service.yaml +9 -0
  32. package/discovery/test_resource_snapshot.py +251 -0
  33. package/discovery/validation.star +78 -0
  34. package/discovery/versioning.star +1 -0
  35. package/dist/commands/config.d.ts.map +1 -1
  36. package/dist/commands/config.js +11 -0
  37. package/dist/commands/config.js.map +1 -1
  38. package/dist/commands/doctor.d.ts.map +1 -1
  39. package/dist/commands/doctor.js +1 -2
  40. package/dist/commands/doctor.js.map +1 -1
  41. package/dist/commands/project.d.ts.map +1 -1
  42. package/dist/commands/project.js +36 -41
  43. package/dist/commands/project.js.map +1 -1
  44. package/dist/commands/resource.d.ts.map +1 -1
  45. package/dist/commands/resource.js +51 -55
  46. package/dist/commands/resource.js.map +1 -1
  47. package/dist/commands/stack.d.ts.map +1 -1
  48. package/dist/commands/stack.js +22 -24
  49. package/dist/commands/stack.js.map +1 -1
  50. package/dist/commands/ui.d.ts.map +1 -1
  51. package/dist/commands/ui.js +1 -2
  52. package/dist/commands/ui.js.map +1 -1
  53. package/dist/commands/up.d.ts.map +1 -1
  54. package/dist/commands/up.js +1 -2
  55. package/dist/commands/up.js.map +1 -1
  56. package/dist/commands/upgrade.d.ts +8 -0
  57. package/dist/commands/upgrade.d.ts.map +1 -1
  58. package/dist/commands/upgrade.js +59 -18
  59. package/dist/commands/upgrade.js.map +1 -1
  60. package/dist/generator/extension-fetch.d.ts +19 -0
  61. package/dist/generator/extension-fetch.d.ts.map +1 -1
  62. package/dist/generator/extension-fetch.js +71 -5
  63. package/dist/generator/extension-fetch.js.map +1 -1
  64. package/dist/generator/template-engine.d.ts +1 -0
  65. package/dist/generator/template-engine.d.ts.map +1 -1
  66. package/dist/generator/template-engine.js +50 -6
  67. package/dist/generator/template-engine.js.map +1 -1
  68. package/dist/utils/command-helpers.d.ts.map +1 -1
  69. package/dist/utils/command-helpers.js +7 -9
  70. package/dist/utils/command-helpers.js.map +1 -1
  71. package/dist/utils/constants.d.ts +1 -0
  72. package/dist/utils/constants.d.ts.map +1 -1
  73. package/dist/utils/constants.js +1 -0
  74. package/dist/utils/constants.js.map +1 -1
  75. package/dist/utils/errors.d.ts +2 -0
  76. package/dist/utils/errors.d.ts.map +1 -1
  77. package/dist/utils/errors.js +6 -1
  78. package/dist/utils/errors.js.map +1 -1
  79. package/dist/utils/project-features.d.ts.map +1 -1
  80. package/dist/utils/project-features.js +1 -1
  81. package/dist/utils/project-features.js.map +1 -1
  82. package/dist/utils/resource-features.d.ts.map +1 -1
  83. package/dist/utils/resource-features.js +2 -2
  84. package/dist/utils/resource-features.js.map +1 -1
  85. package/dist/utils/tar.js +4 -4
  86. package/dist/utils/tar.js.map +1 -1
  87. package/dist/utils/validation.d.ts +7 -0
  88. package/dist/utils/validation.d.ts.map +1 -1
  89. package/dist/utils/validation.js +9 -0
  90. package/dist/utils/validation.js.map +1 -1
  91. package/engine/AGENTS.md +705 -0
  92. package/engine/README.md +29 -0
  93. package/engine/REFACTORING_MANIFEST_SYSTEM.md +974 -0
  94. package/engine/Tiltfile +80 -0
  95. package/engine/assets/docker/golden-layers.Dockerfile +221 -0
  96. package/engine/assets/scripts/cleanup-completed-migrator-images.sh +37 -0
  97. package/engine/assets/scripts/cleanup-tilt-images.sh +120 -0
  98. package/engine/assets/scripts/mac-m1-resource-monitor.sh +121 -0
  99. package/engine/config.star +3 -0
  100. package/engine/docs/AUTODISCOVERY_TEST.md +182 -0
  101. package/engine/docs/C4-ARCHITECTURE-operations.md +396 -0
  102. package/engine/docs/C4-ARCHITECTURE-overview.md +284 -0
  103. package/engine/docs/C4-ARCHITECTURE.md +17 -0
  104. package/engine/docs/GOLDEN_IMAGE_INTEGRATION.md +349 -0
  105. package/engine/docs/MANIFEST_DRIVEN_ARCHITECTURE.md +357 -0
  106. package/engine/docs/README.md +284 -0
  107. package/engine/entrypoint.star +97 -0
  108. package/engine/lifecycle/orchestrator.star +260 -0
  109. package/engine/paths.star +717 -0
  110. package/engine/schemas/manifest-schema.json +301 -0
  111. package/engine/schemas/service-schema.json +301 -0
  112. package/engine/scripts/README.md +89 -0
  113. package/engine/scripts/build-and-publish-lib.sh +205 -0
  114. package/engine/scripts/check-lib-publish.sh +85 -0
  115. package/engine/scripts/debug-container.sh +258 -0
  116. package/engine/scripts/generate-manifest.sh +197 -0
  117. package/engine/spec.master +702 -0
  118. package/engine/spec.master.example +341 -0
  119. package/engine/topologies/README.md +34 -0
  120. package/engine/topologies/platform/docker/AGENTS.md +59 -0
  121. package/engine/topologies/platform/docker/auth/auth.star +167 -0
  122. package/engine/topologies/platform/docker/build/golden_image.star +37 -0
  123. package/engine/topologies/platform/docker/build/golden_image_build.star +82 -0
  124. package/engine/topologies/platform/docker/build/golden_image_constants.star +93 -0
  125. package/engine/topologies/platform/docker/build/golden_image_dockerfile.star +291 -0
  126. package/engine/topologies/platform/docker/compose/compose.star +636 -0
  127. package/engine/topologies/platform/docker/compose/compose_helpers.star +52 -0
  128. package/engine/topologies/platform/docker/compose/traefik_standalone.star +53 -0
  129. package/engine/topologies/platform/docker/config/bunignore.star +142 -0
  130. package/engine/topologies/platform/docker/config/dockerignore.star +150 -0
  131. package/engine/topologies/platform/docker/constants.star +170 -0
  132. package/engine/topologies/platform/docker/dockerfile/dockerfile.star +54 -0
  133. package/engine/topologies/platform/docker/generators/golden_docker_generator_v2.star +73 -0
  134. package/engine/topologies/platform/docker/index.star +27 -0
  135. package/engine/topologies/platform/docker/layers/bun_helpers.star +23 -0
  136. package/engine/topologies/platform/docker/layers/infisical/index.star +40 -0
  137. package/engine/topologies/platform/docker/layers/infisical/infisical_docker.star +262 -0
  138. package/engine/topologies/platform/docker/layers/l1_base_layers.star +87 -0
  139. package/engine/topologies/platform/docker/layers/l2_dependency_layers.star +125 -0
  140. package/engine/topologies/platform/docker/layers/l3_builder_layers.star +209 -0
  141. package/engine/topologies/platform/docker/layers/l4_runtime_layers.star +214 -0
  142. package/engine/topologies/platform/docker/layers/prisma/constants.star +135 -0
  143. package/engine/topologies/platform/docker/layers/prisma/db_readiness.star +96 -0
  144. package/engine/topologies/platform/docker/layers/prisma/filesystem_setup.star +109 -0
  145. package/engine/topologies/platform/docker/layers/prisma/migrate_script.star +98 -0
  146. package/engine/topologies/platform/docker/layers/prisma/prisma_build.star +126 -0
  147. package/engine/topologies/platform/docker/layers/prisma/prisma_runtime.star +161 -0
  148. package/engine/topologies/platform/docker/layers/prisma/secret_resolution.star +119 -0
  149. package/engine/topologies/platform/docker/networking/api_path_constants.star +230 -0
  150. package/engine/topologies/platform/docker/networking/sablier_container_cycle.star +27 -0
  151. package/engine/topologies/platform/docker/networking/traefik.star +232 -0
  152. package/engine/topologies/platform/docker/networking/traefik_constants.star +146 -0
  153. package/engine/topologies/platform/docker/networking/traefik_helpers.star +160 -0
  154. package/engine/topologies/platform/docker/secrets/infisical.star +135 -0
  155. package/engine/topologies/platform/net/proxy.star +4 -0
  156. package/engine/topologies/platform/registries/local.star +4 -0
  157. package/engine/topologies/platform/security/secrets.star +239 -0
  158. package/engine/topologies/platform/state/relational.star +4 -0
  159. package/engine/topologies/tilt/common/AGENTS.md +59 -0
  160. package/engine/topologies/tilt/common/utils.star +364 -0
  161. package/engine/topologies/tilt/common/utils_debug.star +69 -0
  162. package/engine/topologies/tilt/common/utils_deterministic.star +168 -0
  163. package/engine/topologies/tilt/common/utils_docker_networks.star +46 -0
  164. package/engine/topologies/tilt/common/utils_env.star +43 -0
  165. package/engine/topologies/tilt/common/utils_output.star +97 -0
  166. package/engine/topologies/tilt/config/AGENTS.md +68 -0
  167. package/engine/topologies/tilt/config/defaults.star +3 -0
  168. package/engine/topologies/tilt/config/feature_flags.star +10 -0
  169. package/engine/topologies/tilt/config/global.star +55 -0
  170. package/engine/topologies/tilt/config/profiles.star +382 -0
  171. package/engine/topologies/tilt/generators/agents_md.star +62 -0
  172. package/engine/topologies/tilt/generators/api_gateway.star +145 -0
  173. package/engine/topologies/tilt/generators/index.star +124 -0
  174. package/engine/topologies/tilt/generators/infisical/README.md +424 -0
  175. package/engine/topologies/tilt/generators/infisical/examples.star +312 -0
  176. package/engine/topologies/tilt/generators/infisical/index.star +57 -0
  177. package/engine/topologies/tilt/generators/infisical/machine_identity.star +420 -0
  178. package/engine/topologies/tilt/generators/infisical/organization.star +534 -0
  179. package/engine/topologies/tilt/generators/infisical/path_manager.star +476 -0
  180. package/engine/topologies/tilt/generators/infisical/secrets_generator.star +420 -0
  181. package/engine/topologies/tilt/generators/nginx_conf.star +143 -0
  182. package/engine/topologies/tilt/generators/npmrc.star +111 -0
  183. package/engine/topologies/tilt/generators/tsconfig.star +23 -0
  184. package/engine/topologies/tilt/generators/typescript/backend_library_tsconfig.star +71 -0
  185. package/engine/topologies/tilt/generators/typescript/backend_tsconfig.star +124 -0
  186. package/engine/topologies/tilt/generators/typescript/common.star +7 -0
  187. package/engine/topologies/tilt/generators/typescript/frontend_library_tsconfig.star +76 -0
  188. package/engine/topologies/tilt/generators/typescript/frontend_tsconfig.star +110 -0
  189. package/engine/topologies/tilt/generators/typescript/include.star +23 -0
  190. package/engine/topologies/tilt/generators/typescript/playwright_config.star +40 -0
  191. package/engine/topologies/tilt/generators/typescript/prisma_config.star +49 -0
  192. package/engine/topologies/tilt/generators/validators.star +853 -0
  193. package/engine/topologies/tilt/generators/vite/backend.star +78 -0
  194. package/engine/topologies/tilt/generators/vite/frontend.star +98 -0
  195. package/engine/topologies/tilt/generators/vite/generators.star +43 -0
  196. package/engine/topologies/tilt/generators/vite/helpers.star +244 -0
  197. package/engine/topologies/tilt/generators/vite/library.star +65 -0
  198. package/engine/topologies/tilt/generators/vite/sdk.star +73 -0
  199. package/engine/topologies/tilt/generators/vite/templates.star +737 -0
  200. package/engine/topologies/tilt/generators/vite_config.star +22 -0
  201. package/engine/topologies/tilt/manifest/AGENTS.md +61 -0
  202. package/engine/topologies/tilt/manifest/README.md +693 -0
  203. package/engine/topologies/tilt/manifest/__init__.star +218 -0
  204. package/engine/topologies/tilt/manifest/constants.star +252 -0
  205. package/engine/topologies/tilt/manifest/errors.star +266 -0
  206. package/engine/topologies/tilt/manifest/integration.star +339 -0
  207. package/engine/topologies/tilt/manifest/json_to_yaml.py +54 -0
  208. package/engine/topologies/tilt/manifest/loader.star +214 -0
  209. package/engine/topologies/tilt/manifest/mapper.star +227 -0
  210. package/engine/topologies/tilt/manifest/parser.star +400 -0
  211. package/engine/topologies/tilt/manifest/schema.star +462 -0
  212. package/engine/topologies/tilt/manifest/tests/test_integration.star +276 -0
  213. package/engine/topologies/tilt/manifest/tests/test_loader_parser.star +397 -0
  214. package/engine/topologies/tilt/manifest/tests/test_manifest.star +316 -0
  215. package/engine/topologies/tilt/manifest/tests/test_validator.star +470 -0
  216. package/engine/topologies/tilt/manifest/validator.star +717 -0
  217. package/engine/topologies/tilt/manifest/yaml_to_json.py +18 -0
  218. package/engine/topologies/tilt/resources/AGENTS.md +71 -0
  219. package/engine/topologies/tilt/resources/conditions.star +3 -0
  220. package/engine/topologies/tilt/resources/databases.star +244 -0
  221. package/engine/topologies/tilt/resources/declaration.star +3 -0
  222. package/engine/topologies/tilt/resources/deps.star +3 -0
  223. package/engine/topologies/tilt/resources/infra-loader.star +437 -0
  224. package/engine/topologies/tilt/resources/libs.star +30 -0
  225. package/engine/topologies/tilt/resources/libs_discovery.star +102 -0
  226. package/engine/topologies/tilt/resources/libs_paths.star +79 -0
  227. package/engine/topologies/tilt/resources/libs_resource_definition.star +151 -0
  228. package/engine/topologies/tilt/resources/libs_setup.star +164 -0
  229. package/engine/topologies/tilt/resources/libs_tsconfig.star +37 -0
  230. package/engine/topologies/tilt/resources/orchestrator/apply.star +77 -0
  231. package/engine/topologies/tilt/resources/orchestrator/apply_compose_resource_registration.star +431 -0
  232. package/engine/topologies/tilt/resources/orchestrator/apply_manifest_orchestration.star +81 -0
  233. package/engine/topologies/tilt/resources/orchestrator/apply_migrator_orchestration.star +148 -0
  234. package/engine/topologies/tilt/resources/orchestrator/apply_resource_validation.star +36 -0
  235. package/engine/topologies/tilt/resources/orchestrator/apply_runtime_flags.star +44 -0
  236. package/engine/topologies/tilt/resources/orchestrator/builders/typescript.star +164 -0
  237. package/engine/topologies/tilt/resources/orchestrator/generators/dependencies/AGENTS.md +75 -0
  238. package/engine/topologies/tilt/resources/orchestrator/generators/dependencies/index.star +21 -0
  239. package/engine/topologies/tilt/resources/orchestrator/generators/dependencies/resolver.star +134 -0
  240. package/engine/topologies/tilt/resources/orchestrator/generators/env.star +258 -0
  241. package/engine/topologies/tilt/resources/orchestrator/generators/frontend.star +169 -0
  242. package/engine/topologies/tilt/resources/orchestrator/generators/manifest_resource.star +524 -0
  243. package/engine/topologies/tilt/resources/orchestrator/helpers.star +33 -0
  244. package/engine/topologies/tilt/resources/orchestrator.star +54 -0
  245. package/engine/topologies/tilt/resources/ordering.star +3 -0
  246. package/engine/topologies/tilt/resources/triggers.star +3 -0
  247. package/engine/topologies/tilt/resources/watchers.star +299 -0
  248. package/engine/where-things-live.star +717 -0
  249. package/ext/Tiltfile +66 -0
  250. package/ext/ide-components/README.md +219 -0
  251. package/ext/ide-components/code_executor/server.py +268 -0
  252. package/ext/ide-components/code_viewer/server.py +206 -0
  253. package/ext/ide-components/config_inspector/server.py +1050 -0
  254. package/ext/ide-components/file_browser/server.py +285 -0
  255. package/ext/ide-components/shared/config_service.py +469 -0
  256. package/ext/ide-components/shared/file_utils.py +298 -0
  257. package/ext/ide-components/shared/http_utils.py +232 -0
  258. package/ext/ide-components/shared/static/styles.css +1334 -0
  259. package/ext/ide-components/shared/syntax_highlighter.py +140 -0
  260. package/ext/ide-components/shared/template_engine.py +123 -0
  261. package/ext/ide-components/shared/templates/base.html +121 -0
  262. package/ext/ide-components/shared/test_config_service.py +326 -0
  263. package/ext/ide-components/shared/tilt_integration.py +158 -0
  264. package/ext/ui-enhancements/cron-status-server.sh +49 -0
  265. package/ext/ui-enhancements/cron-status-tracker.sh +146 -0
  266. package/ext/ui-enhancements/extension.yaml +36 -0
  267. package/ext/ui-enhancements/tiltfile.py +99 -0
  268. package/ext/ui-enhancements/ui/cron-jobs-tab.css +396 -0
  269. package/ext/ui-enhancements/ui/help-panel.css +279 -0
  270. package/ext/ui-enhancements/ui/icons.css +125 -0
  271. package/ext/ui-enhancements/ui/tooltips.css +114 -0
  272. package/package.json +13 -9
  273. package/specs/specs/TILT_SERVICE_DEFAULTS.star +205 -0
  274. package/specs/specs/TILT_TECH_STACK.star +159 -0
@@ -0,0 +1,853 @@
1
+ # =============================================================================
2
+ # 🛡️ VALIDATORS - Pre-Flight Validation Generators
3
+ # =============================================================================
4
+ # These generators run BEFORE services start to catch issues early
5
+ # They prevent vibe-coding failures by enforcing constraints at build time
6
+ # =============================================================================
7
+
8
+ # === INLINED CONSTANTS for pure extension loading ===
9
+ BASE_PORT_FRONTEND = 3000
10
+ # === END INLINED CONSTANTS ===
11
+
12
+
13
+ """
14
+ Validators Architecture:
15
+ 1. docker_path_validator - Ensures path aliases work in Docker context
16
+ 2. dependency_validator - Ensures all declared dependencies exist
17
+ 3. db_readiness_validator - Validates database credentials before startup
18
+ 4. package_publish_validator - Ensures shared packages are published
19
+ 5. env_var_validator - Validates all required environment variables
20
+ 6. resource_health_validator - Pre-flight health checks
21
+ 7. shared_package_copier - Copies shared packages to Docker context
22
+ """
23
+
24
+ load("../common/utils.star", "Utils")
25
+ load("../../platform/docker/constants.star", "PlatformDockerConstants")
26
+ load("../manifest/constants.star", "GENERATED_CONFIG_FILENAMES")
27
+
28
+ load("../common/utils.star", "LIBRARY_ROOTS")
29
+
30
+ # =============================================================================
31
+ # 1. Docker Path Alias Validator
32
+ # =============================================================================
33
+
34
+ def validate_docker_path_aliases(resource_path, manifest, library_roots):
35
+ """
36
+ Validates that TypeScript path aliases in Docker tsconfig will resolve correctly.
37
+
38
+ Problem: Docker builds fail when tsconfig has path aliases to shared packages
39
+ that aren't copied to the Docker context.
40
+
41
+ Solution:
42
+ - Warn about path aliases that point outside Docker context
43
+ - Recommend removing internal_deps from Docker tsconfig
44
+ - Suggest using node_modules resolution instead
45
+
46
+ Returns: (is_valid, warnings, fixes)
47
+ """
48
+ warnings = []
49
+ fixes = []
50
+
51
+ resource_name = manifest.get("appName", "unknown")
52
+ app_type = manifest.get("appType", "backend")
53
+
54
+ # Check if this is a frontend service (most affected)
55
+ if app_type == "frontend":
56
+ # Check for internal dependencies that would break Docker build
57
+ package_json_path = resource_path + "/package.json"
58
+ if os.path.exists(package_json_path):
59
+ package_json = read_json(package_json_path)
60
+ deps = package_json.get("dependencies", {})
61
+
62
+ internal_scope = "@" + PlatformDockerConstants.PROJECT_NAME + "/"
63
+ # Build list manually (Starlark doesn't support list comprehensions with if)
64
+ internal_deps = []
65
+ for name in deps.keys():
66
+ if name.startswith(internal_scope):
67
+ internal_deps.append(name)
68
+
69
+ if internal_deps:
70
+ warnings.append({
71
+ "level": "error",
72
+ "message": "Frontend '{}' has internal deps that will fail Docker build".format(resource_name),
73
+ "details": "The following packages use path aliases that won't resolve in Docker:",
74
+ "packages": internal_deps,
75
+ "impact": "Build will fail with 'Module not found' errors",
76
+ })
77
+
78
+ fixes.append({
79
+ "action": "Remove path aliases from Docker tsconfig",
80
+ "generator": "typescript/frontend_tsconfig.star",
81
+ "change": "Set internal_deps=None when is_docker=True",
82
+ "rationale": "Docker builds should resolve from node_modules, not source paths",
83
+ })
84
+
85
+ # Count errors manually (Starlark doesn't support list comprehensions with if)
86
+ error_count = 0
87
+ for w in warnings:
88
+ if w["level"] == "error":
89
+ error_count += 1
90
+ is_valid = error_count == 0
91
+
92
+ return struct(
93
+ is_valid=is_valid,
94
+ warnings=warnings,
95
+ fixes=fixes,
96
+ resource_name=resource_name,
97
+ )
98
+
99
+ def generate_docker_path_validation_report(resource_path, manifest, write_fn=None):
100
+ """
101
+ Generates a validation report for Docker path aliases.
102
+ Called during config-gen to catch issues before Docker build.
103
+ """
104
+ result = validate_docker_path_aliases(resource_path, manifest, LIBRARY_ROOTS)
105
+
106
+ if not result.is_valid:
107
+ report = {
108
+ "timestamp": "now",
109
+ "service": result.resource_name,
110
+ "status": "FAILED",
111
+ "warnings": result.warnings,
112
+ "fixes": result.fixes,
113
+ "recommendation": "Regenerate tsconfig without Docker path aliases",
114
+ }
115
+
116
+ if write_fn:
117
+ write_fn("docker-path-validation.json", Utils.encode_json(report))
118
+
119
+ # Also print to Tilt UI
120
+ print("⚠️ Docker Path Validation Failed for {}".format(result.resource_name))
121
+ for warning in result.warnings:
122
+ print(" ❌ {}: {}".format(warning["level"].upper(), warning["message"]))
123
+ for fix in result.fixes:
124
+ print(" 💡 Fix: {}".format(fix["action"]))
125
+
126
+ return report
127
+
128
+ return {"status": "PASSED", "service": result.resource_name}
129
+
130
+ # =============================================================================
131
+ # 2. Dependency Graph Validator
132
+ # =============================================================================
133
+
134
+ def validate_dependency_graph(resource_path, manifest, all_services):
135
+ """
136
+ Validates that all declared dependencies actually exist.
137
+
138
+ Problem: Services declare dependencies on libraries that don't exist,
139
+ causing Tilt warnings and runtime failures.
140
+
141
+ Solution:
142
+ - Check all @{npm_scope}/* dependencies exist in library_roots
143
+ - Check dependsOn in manifest exist as services
144
+ - Generate missing dependency report
145
+
146
+ Returns: (is_valid, missing_deps, suggestions)
147
+ """
148
+ missing_deps = []
149
+ warnings = []
150
+
151
+ resource_name = manifest.get("appName", "unknown")
152
+
153
+ # Check package.json dependencies
154
+ package_json_path = resource_path + "/package.json"
155
+ if os.path.exists(package_json_path):
156
+ package_json = read_json(package_json_path)
157
+ deps = package_json.get("dependencies", {})
158
+ dev_deps = package_json.get("devDependencies", {})
159
+ all_deps = dict(deps, **dev_deps)
160
+
161
+ internal_scope = "@" + PlatformDockerConstants.PROJECT_NAME + "/"
162
+
163
+ for dep_name in all_deps.keys():
164
+ if dep_name.startswith(internal_scope):
165
+ lib_name = dep_name.replace(internal_scope, "")
166
+
167
+ # Check if library exists in known library directories
168
+ found = False
169
+ for lib_type, lib_root in LIBRARY_ROOTS.items():
170
+ lib_path = "{}/{}".format(lib_root, lib_name)
171
+ if os.path.exists(lib_path):
172
+ found = True
173
+ break
174
+
175
+ if not found:
176
+ missing_deps.append({
177
+ "name": dep_name,
178
+ "type": "library",
179
+ "source": "package.json",
180
+ })
181
+
182
+ # Check manifest dependsOn
183
+ internal_deps = manifest.get("dependsOn", [])
184
+ for dep in internal_deps:
185
+ dep_exists = False
186
+ for svc in all_services:
187
+ # Check service name/stack match (supports legacy 'stack' field)
188
+ svc_stack = svc.get("stack") or svc.get("stack")
189
+ if svc.get("name") == dep or svc_stack == dep:
190
+ dep_exists = True
191
+ break
192
+ # Check if any resource within the service matches
193
+ for resource in svc.get("resources", []):
194
+ if resource.get("name") == dep:
195
+ dep_exists = True
196
+ break
197
+ if dep_exists:
198
+ break
199
+
200
+ if not dep_exists:
201
+ missing_deps.append({
202
+ "name": dep,
203
+ "type": "service",
204
+ "source": "service.json dependsOn",
205
+ })
206
+
207
+ is_valid = len(missing_deps) == 0
208
+
209
+ return struct(
210
+ is_valid=is_valid,
211
+ missing_deps=missing_deps,
212
+ resource_name=resource_name,
213
+ )
214
+
215
+ def generate_dependency_validation_report(resource_path, manifest, all_services, write_fn=None):
216
+ """
217
+ Generates a validation report for service dependencies.
218
+ """
219
+ result = validate_dependency_graph(resource_path, manifest, all_services)
220
+
221
+ if not result.is_valid:
222
+ report = {
223
+ "timestamp": "now",
224
+ "service": result.resource_name,
225
+ "status": "FAILED",
226
+ "missing_dependencies": result.missing_deps,
227
+ "recommendation": "Create missing libraries or update dependencies",
228
+ }
229
+
230
+ if write_fn:
231
+ write_fn("dependency-validation.json", Utils.encode_json(report))
232
+
233
+ print("⚠️ Dependency Validation Failed for {}".format(result.resource_name))
234
+ for dep in result.missing_deps:
235
+ print(" ❌ Missing {}: {} (from {})".format(
236
+ dep["type"], dep["name"], dep["source"]
237
+ ))
238
+
239
+ return report
240
+
241
+ return {"status": "PASSED", "service": result.resource_name}
242
+
243
+ # =============================================================================
244
+ # 3. Database Readiness Validator
245
+ # =============================================================================
246
+
247
+ def validate_database_readiness(resource_name, db_name, db_config):
248
+ """
249
+ Validates database configuration before service startup.
250
+
251
+ Problem: Services fail to start because database credentials are wrong,
252
+ database doesn't exist, or connection fails.
253
+
254
+ Solution:
255
+ - Check DATABASE_URL is properly formed
256
+ - Validate database credentials format
257
+ - Ensure database name matches manifest
258
+ - Generate proper connection string
259
+
260
+ Returns: (is_valid, connection_string, errors)
261
+ """
262
+ errors = []
263
+
264
+ # Validate database name
265
+ if not db_name:
266
+ errors.append({
267
+ "field": "databaseName",
268
+ "error": "No database name specified in manifest",
269
+ "fix": "Add 'databaseName' to service.json",
270
+ })
271
+
272
+ # Validate database config
273
+ if not db_config:
274
+ errors.append({
275
+ "field": "database",
276
+ "error": "No database configuration found",
277
+ "fix": "Check GLOBAL_CONFIG.database in discovery/config.star",
278
+ })
279
+
280
+ # Build connection string
281
+ connection_string = None
282
+ if db_name and db_config:
283
+ host = db_config.get("host", "localhost")
284
+ port = db_config.get("port", 5432)
285
+ user = db_config.get("user", "postgres")
286
+ # ⚠️ SECURITY: No default password - must be explicitly provided
287
+ password = db_config.get("password")
288
+
289
+ if not password:
290
+ errors.append({
291
+ "field": "database.password",
292
+ "error": "Database password is required but not provided",
293
+ "fix": "Set DB_PASSWORD or POSTGRES_PASSWORD environment variable",
294
+ })
295
+ else:
296
+ connection_string = "postgresql://{}:{}@{}:{}/{}".format(
297
+ user, password, host, port, db_name
298
+ )
299
+
300
+ is_valid = len(errors) == 0
301
+
302
+ return struct(
303
+ is_valid=is_valid,
304
+ connection_string=connection_string,
305
+ errors=errors,
306
+ resource_name=resource_name,
307
+ )
308
+
309
+ def generate_db_readiness_check(resource_name, db_name, db_config, write_fn=None):
310
+ """
311
+ Generates database readiness validation and entrypoint script.
312
+ """
313
+ result = validate_database_readiness(resource_name, db_name, db_config)
314
+
315
+ if not result.is_valid:
316
+ report = {
317
+ "timestamp": "now",
318
+ "service": resource_name,
319
+ "status": "FAILED",
320
+ "errors": result.errors,
321
+ "recommendation": "Fix database configuration in manifest",
322
+ }
323
+
324
+ if write_fn:
325
+ write_fn("db-readiness-validation.json", Utils.encode_json(report))
326
+
327
+ print("⚠️ Database Validation Failed for {}".format(resource_name))
328
+ for error in result.errors:
329
+ print(" ❌ {}: {}".format(error["field"], error["error"]))
330
+
331
+ return report
332
+
333
+ # Generate connection string report
334
+ if write_fn:
335
+ write_fn("db-connection-string.txt", result.connection_string)
336
+
337
+ return {
338
+ "status": "PASSED",
339
+ "service": resource_name,
340
+ "connection_string": result.connection_string,
341
+ }
342
+
343
+ # =============================================================================
344
+ # 4. Package Publish Validator
345
+ # =============================================================================
346
+
347
+ def validate_package_publishing(resource_path, manifest, verdaccio_url):
348
+ """
349
+ Validates that all @{npm_scope} dependencies are published to Verdaccio.
350
+
351
+ Problem: Docker builds fail because shared packages aren't published,
352
+ causing 'npm package not found' errors.
353
+
354
+ Solution:
355
+ - Check each @{npm_scope} dependency exists in Verdaccio
356
+ - Compare local package version with published version
357
+ - Warn if local is newer than published
358
+
359
+ Returns: (is_valid, unpublished_packages, version_mismatches)
360
+ """
361
+ unpublished = []
362
+ version_mismatches = []
363
+
364
+ resource_name = manifest.get("appName", "unknown")
365
+
366
+ package_json_path = resource_path + "/package.json"
367
+ if not os.path.exists(package_json_path):
368
+ return struct(
369
+ is_valid=True,
370
+ unpublished_packages=[],
371
+ version_mismatches=[],
372
+ resource_name=resource_name,
373
+ )
374
+
375
+ package_json = read_json(package_json_path)
376
+ deps = package_json.get("dependencies", {})
377
+
378
+ internal_scope = "@" + PlatformDockerConstants.PROJECT_NAME + "/"
379
+
380
+ for dep_name, dep_version in deps.items():
381
+ if not dep_name.startswith(internal_scope):
382
+ continue
383
+
384
+ lib_name = dep_name.replace(internal_scope, "")
385
+
386
+ # Check if package exists in Verdaccio
387
+ # (This would be an actual HTTP check in real implementation)
388
+ # For now, we check if library source exists
389
+ found = False
390
+ for lib_root in LIBRARY_ROOTS.values():
391
+ lib_path = "{}/{}".format(lib_root, lib_name)
392
+ if os.path.exists(lib_path):
393
+ found = True
394
+
395
+ # Check local package.json version
396
+ lib_package_path = "{}/package.json".format(lib_path)
397
+ if os.path.exists(lib_package_path):
398
+ lib_package = read_json(lib_package_path)
399
+ local_version = lib_package.get("version", "0.0.0")
400
+
401
+ # Parse requested version
402
+ requested_version = dep_version.replace("^", "").replace("~", "")
403
+
404
+ if local_version != requested_version:
405
+ version_mismatches.append({
406
+ "package": dep_name,
407
+ "requested": requested_version,
408
+ "local": local_version,
409
+ })
410
+ break
411
+
412
+ if not found:
413
+ unpublished.append(dep_name)
414
+
415
+ is_valid = len(unpublished) == 0
416
+
417
+ return struct(
418
+ is_valid=is_valid,
419
+ unpublished_packages=unpublished,
420
+ version_mismatches=version_mismatches,
421
+ resource_name=resource_name,
422
+ )
423
+
424
+ def generate_package_publish_report(resource_path, manifest, verdaccio_url, write_fn=None):
425
+ """
426
+ Generates a report of package publishing status.
427
+ """
428
+ result = validate_package_publishing(resource_path, manifest, verdaccio_url)
429
+
430
+ if not result.is_valid or result.version_mismatches:
431
+ report = {
432
+ "timestamp": "now",
433
+ "service": result.resource_name,
434
+ "status": "WARNING" if not result.is_valid else "VERSION_MISMATCH",
435
+ "unpublished_packages": result.unpublished_packages,
436
+ "version_mismatches": result.version_mismatches,
437
+ "recommendation": "Run 'bun run publish:all' to publish packages",
438
+ }
439
+
440
+ if write_fn:
441
+ write_fn("package-publish-validation.json", Utils.encode_json(report))
442
+
443
+ if not result.is_valid:
444
+ print("⚠️ Package Publishing Validation Failed for {}".format(result.resource_name))
445
+ for pkg in result.unpublished_packages:
446
+ print(" ❌ Package not found: {}".format(pkg))
447
+
448
+ if result.version_mismatches:
449
+ print("⚠️ Version Mismatches for {}".format(result.resource_name))
450
+ for mismatch in result.version_mismatches:
451
+ print(" ⚡ {}: requested {} but local is {}".format(
452
+ mismatch["package"],
453
+ mismatch["requested"],
454
+ mismatch["local"]
455
+ ))
456
+
457
+ return report
458
+
459
+ return {"status": "PASSED", "service": result.resource_name}
460
+
461
+ # =============================================================================
462
+ # 5. Environment Variable Validator
463
+ # =============================================================================
464
+
465
+ def validate_environment_variables(resource_path, manifest, required_vars):
466
+ """
467
+ Validates that all required environment variables are defined.
468
+
469
+ Problem: Services fail at runtime because environment variables are missing.
470
+
471
+ Solution:
472
+ - Define required vars in manifest
473
+ - Check .env files exist
474
+ - Validate variables are set in Tilt context
475
+
476
+ Returns: (is_valid, missing_vars, env_files)
477
+ """
478
+ missing_vars = []
479
+ env_files = []
480
+
481
+ resource_name = manifest.get("appName", "unknown")
482
+
483
+ # Check for .env files
484
+ for env_file in [".env", ".env.local", ".env.docker"]:
485
+ env_path = "{}/{}".format(resource_path, env_file)
486
+ if os.path.exists(env_path):
487
+ env_files.append(env_file)
488
+
489
+ # Check required variables
490
+ manifest_required = manifest.get("requiredEnvVars", [])
491
+ all_required = list(set(required_vars + manifest_required))
492
+
493
+ for var in all_required:
494
+ if not os.environ.get(var):
495
+ missing_vars.append(var)
496
+
497
+ is_valid = len(missing_vars) == 0
498
+
499
+ return struct(
500
+ is_valid=is_valid,
501
+ missing_vars=missing_vars,
502
+ env_files=env_files,
503
+ resource_name=resource_name,
504
+ )
505
+
506
+ def generate_env_validation_report(resource_path, manifest, required_vars, write_fn=None):
507
+ """
508
+ Generates environment variable validation report.
509
+ """
510
+ result = validate_environment_variables(resource_path, manifest, required_vars)
511
+
512
+ if not result.is_valid:
513
+ report = {
514
+ "timestamp": "now",
515
+ "service": result.resource_name,
516
+ "status": "FAILED",
517
+ "missing_variables": result.missing_vars,
518
+ "env_files_found": result.env_files,
519
+ "recommendation": "Set missing environment variables or add .env file",
520
+ }
521
+
522
+ if write_fn:
523
+ write_fn("env-validation.json", Utils.encode_json(report))
524
+
525
+ print("⚠️ Environment Variable Validation Failed for {}".format(result.resource_name))
526
+ for var in result.missing_vars:
527
+ print(" ❌ Missing: {}".format(var))
528
+
529
+ return report
530
+
531
+ return {
532
+ "status": "PASSED",
533
+ "service": result.resource_name,
534
+ "env_files": result.env_files,
535
+ }
536
+
537
+ # =============================================================================
538
+ # 6. Service Health Pre-Flight Validator
539
+ # =============================================================================
540
+
541
+ def generate_resource_health_check(resource_name, resource_path, manifest, checks):
542
+ """
543
+ Generates a comprehensive pre-flight health check script.
544
+
545
+ Runs before service starts to validate:
546
+ - File structure is correct
547
+ - Required files exist
548
+ - Dependencies are resolvable
549
+ - Ports are available
550
+
551
+ Returns: health_check_script (bash)
552
+ """
553
+ app_type = manifest.get("appType", "backend")
554
+
555
+ health_checks = []
556
+
557
+ # Check 1: Required files exist
558
+ required_files = {
559
+ "backend": ["package.json", "prisma/schema.prisma"],
560
+ "frontend": ["package.json", "index.html", "src/main.tsx"],
561
+ "library": ["package.json"],
562
+ }.get(app_type, ["package.json"])
563
+
564
+ for req_file in required_files:
565
+ health_checks.append('''
566
+ if [ ! -f "{}" ]; then
567
+ echo "❌ Missing required file: {}"
568
+ exit 1
569
+ fi
570
+ '''.format(req_file, req_file))
571
+
572
+ # Check 2: Package.json is valid JSON
573
+ health_checks.append('''
574
+ if ! cat package.json | head -1 > /dev/null 2>&1; then
575
+ echo "❌ package.json is not valid"
576
+ exit 1
577
+ fi
578
+ ''')
579
+
580
+ # Check 3: Port availability (for local dev)
581
+ port = manifest.get("port", BASE_PORT_FRONTEND)
582
+ health_checks.append('''
583
+ # Check if port is already in use
584
+ if command -v lsof > /dev/null 2>&1; then
585
+ if lsof -Pi :{} -sTCP:LISTEN -t >/dev/null 2>&1; then
586
+ echo "⚠️ Port {} is already in use"
587
+ fi
588
+ fi
589
+ '''.format(port, port))
590
+
591
+ # Combine into script
592
+ script = '''#!/bin/bash
593
+ # Auto-generated health check for {}
594
+ # Generated: {}
595
+
596
+ echo "🔍 Running pre-flight health checks for {}..."
597
+
598
+ {}
599
+
600
+ echo "✅ All health checks passed for {}"
601
+ '''.format(
602
+ resource_name,
603
+ "now",
604
+ resource_name,
605
+ "\n".join(health_checks),
606
+ resource_name
607
+ )
608
+
609
+ return script
610
+
611
+ def generate_health_check_resource(resource_path, resource_name, manifest, write_fn=None):
612
+ """
613
+ Generates health check files and optionally writes them.
614
+ """
615
+ checks = {} # Could be expanded with more check types
616
+
617
+ script = generate_resource_health_check(resource_name, resource_path, manifest, checks)
618
+
619
+ if write_fn:
620
+ write_fn("health-check.sh", script)
621
+
622
+ return script
623
+
624
+ # =============================================================================
625
+ # 7. Shared Package Copier (for Docker Context)
626
+ # =============================================================================
627
+
628
+ def generate_shared_package_copy_list(resource_path, manifest):
629
+ """
630
+ Generates a list of shared packages that need to be copied to Docker context.
631
+
632
+ Problem: Frontend builds fail because shared packages are referenced via
633
+ path aliases but not available in Docker build context.
634
+
635
+ Solution: Copy required shared packages to service directory before Docker build.
636
+
637
+ Returns: list of {source, destination, package_name} dicts
638
+ """
639
+ packages_to_copy = []
640
+
641
+ resource_name = manifest.get("appName", "unknown")
642
+
643
+ package_json_path = resource_path + "/package.json"
644
+ if not os.path.exists(package_json_path):
645
+ return packages_to_copy
646
+
647
+ package_json = read_json(package_json_path)
648
+ deps = package_json.get("dependencies", {})
649
+
650
+ internal_scope = "@" + PlatformDockerConstants.PROJECT_NAME + "/"
651
+
652
+ for dep_name in deps.keys():
653
+ if not dep_name.startswith(internal_scope):
654
+ continue
655
+
656
+ lib_name = dep_name.replace(internal_scope, "")
657
+
658
+ # Find library source path
659
+ for lib_root in LIBRARY_ROOTS.values():
660
+ lib_path = "{}/{}".format(lib_root, lib_name)
661
+ if os.path.exists(lib_path):
662
+ # Destination: .docker-shared-packages/{lib_name}
663
+ dest = ".docker-shared-packages/{}".format(lib_name)
664
+
665
+ packages_to_copy.append({
666
+ "source": lib_path,
667
+ "destination": dest,
668
+ "package_name": dep_name,
669
+ "lib_name": lib_name,
670
+ })
671
+ break
672
+
673
+ return packages_to_copy
674
+
675
+ def generate_docker_shared_packages_config(resource_path, manifest, write_fn=None):
676
+ """
677
+ Generates configuration for copying shared packages to Docker context.
678
+
679
+ This creates a JSON file that can be used by a local_resource to copy
680
+ packages before Docker build.
681
+ """
682
+ packages = generate_shared_package_copy_list(resource_path, manifest)
683
+
684
+ config = {
685
+ "timestamp": "now",
686
+ "service": manifest.get("appName", "unknown"),
687
+ "packages": packages,
688
+ "copy_script": "#!/bin/bash\n# Copy shared packages to Docker context\n" + "\n".join([
689
+ "mkdir -p {dest} && cp -r {src}/* {dest}/".format(
690
+ src=p["source"],
691
+ dest=p["destination"]
692
+ )
693
+ for p in packages
694
+ ]) if packages else "# No shared packages to copy",
695
+ }
696
+
697
+ if write_fn:
698
+ write_fn("docker-shared-packages.json", Utils.encode_json(config))
699
+
700
+ return config
701
+
702
+ # =============================================================================
703
+ # Master Validation Orchestrator
704
+ # =============================================================================
705
+
706
+ def run_all_validations(resource_path, manifest, all_services, global_config, write_fn=None):
707
+ """
708
+ Runs all validators and generates a comprehensive report.
709
+
710
+ This is the main entry point called during config-gen.
711
+ """
712
+ reports = {}
713
+ all_valid = True
714
+
715
+ # 1. Docker Path Validation
716
+ reports["docker_paths"] = generate_docker_path_validation_report(
717
+ resource_path, manifest, write_fn
718
+ )
719
+ if reports["docker_paths"].get("status") == "FAILED":
720
+ all_valid = False
721
+
722
+ # 2. Dependency Validation
723
+ reports["dependencies"] = generate_dependency_validation_report(
724
+ resource_path, manifest, all_services, write_fn
725
+ )
726
+ if reports["dependencies"].get("status") == "FAILED":
727
+ all_valid = False
728
+
729
+ # 3. Database Validation
730
+ db_config = global_config.get("database", {})
731
+ db_name = manifest.get("databaseName", "")
732
+ reports["database"] = generate_db_readiness_check(
733
+ manifest.get("appName"), db_name, db_config, write_fn
734
+ )
735
+ if reports["database"].get("status") == "FAILED":
736
+ all_valid = False
737
+
738
+ # 4. Package Publishing Validation
739
+ verdaccio_url = global_config.get("verdaccio_url_local", PlatformDockerConstants.VERDACCIO_URL_LOCAL)
740
+ reports["packages"] = generate_package_publish_report(
741
+ resource_path, manifest, verdaccio_url, write_fn
742
+ )
743
+ # Warnings don't fail validation
744
+
745
+ # 5. Environment Variable Validation
746
+ required_vars = ["VERDACCIO_URL_DOCKER", "TILT_ENV"]
747
+ reports["environment"] = generate_env_validation_report(
748
+ resource_path, manifest, required_vars, write_fn
749
+ )
750
+ if reports["environment"].get("status") == "FAILED":
751
+ all_valid = False
752
+
753
+ # 6. Health Check Script
754
+ reports["health_check"] = generate_health_check_resource(
755
+ resource_path, manifest.get("appName"), manifest, write_fn
756
+ )
757
+
758
+ # 7. Shared Package Copy Config
759
+ reports["shared_packages"] = generate_docker_shared_packages_config(
760
+ resource_path, manifest, write_fn
761
+ )
762
+
763
+ # Master Report
764
+ # Count passed, failed, and warnings using regular loops (Starlark doesn't support generator expressions)
765
+ passed_count = 0
766
+ failed_count = 0
767
+ warnings_count = 0
768
+ for r in reports.values():
769
+ if type(r) == "dict":
770
+ status = r.get("status")
771
+ if status == "PASSED":
772
+ passed_count += 1
773
+ elif status == "FAILED":
774
+ failed_count += 1
775
+ elif status == "WARNING":
776
+ warnings_count += 1
777
+
778
+ master_report = {
779
+ "service": manifest.get("appName", "unknown"),
780
+ "overall_status": "PASSED" if all_valid else "FAILED",
781
+ "reports": reports,
782
+ "summary": {
783
+ "validations_run": 7,
784
+ "passed": passed_count,
785
+ "failed": failed_count,
786
+ "warnings": warnings_count,
787
+ }
788
+ }
789
+
790
+ if write_fn:
791
+ write_fn("validation-master-report.json", Utils.encode_json(master_report))
792
+
793
+ # Print compact validation summary
794
+ resource_name = manifest.get("appName", "unknown")
795
+
796
+ # Build compact validation summary - only show failures prominently
797
+ failed_validations = []
798
+ passed_count = 0
799
+ unknown_count = 0
800
+
801
+ for name, report in reports.items():
802
+ if type(report) == "dict":
803
+ status = report.get("status", "UNKNOWN")
804
+ if status == "FAILED":
805
+ failed_validations.append(name)
806
+ elif status == "PASSED":
807
+ passed_count += 1
808
+ elif status == "UNKNOWN":
809
+ unknown_count += 1
810
+
811
+ # Print compact summary
812
+ if all_valid:
813
+ # All passed - just show summary line
814
+ print("✅ {}: {} validations passed".format(resource_name, passed_count))
815
+ else:
816
+ # Some failed - show service and failures
817
+ print("❌ {}: {} validation(s) failed".format(resource_name, len(failed_validations)))
818
+ for failed in failed_validations:
819
+ print(" ❌ {}".format(failed))
820
+
821
+ # Show warnings/unknown only in verbose mode
822
+ is_verbose = os.environ.get('TILT_LOG_LEVEL') == 'verbose'
823
+ if is_verbose and unknown_count > 0:
824
+ print(" ○ {} not checked".format(unknown_count))
825
+
826
+ return master_report
827
+
828
+ # =============================================================================
829
+ # Exports
830
+ # =============================================================================
831
+
832
+ Validators = struct(
833
+ # Individual validators
834
+ validate_docker_path_aliases=validate_docker_path_aliases,
835
+ validate_dependency_graph=validate_dependency_graph,
836
+ validate_database_readiness=validate_database_readiness,
837
+ validate_package_publishing=validate_package_publishing,
838
+ validate_environment_variables=validate_environment_variables,
839
+
840
+ # Report generators
841
+ generate_docker_path_validation_report=generate_docker_path_validation_report,
842
+ generate_dependency_validation_report=generate_dependency_validation_report,
843
+ generate_db_readiness_check=generate_db_readiness_check,
844
+ generate_package_publish_report=generate_package_publish_report,
845
+ generate_env_validation_report=generate_env_validation_report,
846
+ generate_health_check_resource=generate_health_check_resource,
847
+ generate_docker_shared_packages_config=generate_docker_shared_packages_config,
848
+
849
+ # Master orchestrator
850
+ run_all_validations=run_all_validations,
851
+ )
852
+
853
+ GLOBAL_CONFIG = {}