@flisk-sh/flisk 0.0.0-stage → 1.3.190

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 (440) hide show
  1. package/CHANGELOG.md +492 -0
  2. package/LICENSE +21 -0
  3. package/README.md +479 -2
  4. package/Tiltfile +151 -0
  5. package/cli/bin/flisk.js +42 -0
  6. package/cli/dist/agent-runtimes/custom.js +335 -0
  7. package/cli/dist/agent-runtimes/registry.js +34 -0
  8. package/cli/dist/backend-frameworks/elysia.js +38 -0
  9. package/cli/dist/backend-frameworks/express.js +49 -0
  10. package/cli/dist/backend-frameworks/fastify.js +43 -0
  11. package/cli/dist/backend-frameworks/h3.js +37 -0
  12. package/cli/dist/backend-frameworks/koa.js +47 -0
  13. package/cli/dist/backend-frameworks/mcp.js +86 -0
  14. package/cli/dist/backend-frameworks/nestjs.js +55 -0
  15. package/cli/dist/backend-frameworks/registry.js +134 -0
  16. package/cli/dist/backend-frameworks/types.js +1 -0
  17. package/cli/dist/backend-languages/bun.js +76 -0
  18. package/cli/dist/backend-languages/go.js +125 -0
  19. package/cli/dist/backend-languages/node.js +122 -0
  20. package/cli/dist/backend-languages/python.js +94 -0
  21. package/cli/dist/backend-languages/registry.js +37 -0
  22. package/cli/dist/backend-languages/rust.js +82 -0
  23. package/cli/dist/backend-languages/types.js +1 -0
  24. package/cli/dist/cli.js +29 -0
  25. package/cli/dist/commands/__tests__/project-e2e-helpers.js +49 -0
  26. package/cli/dist/commands/__tests__/ui-loading-screen.test.js +16 -0
  27. package/cli/dist/commands/agent.js +182 -0
  28. package/cli/dist/commands/completion-candidates.js +116 -0
  29. package/cli/dist/commands/completion.js +843 -0
  30. package/cli/dist/commands/config.js +362 -0
  31. package/cli/dist/commands/doctor.js +1504 -0
  32. package/cli/dist/commands/down.js +114 -0
  33. package/cli/dist/commands/eject.js +108 -0
  34. package/cli/dist/commands/help.js +152 -0
  35. package/cli/dist/commands/import.js +164 -0
  36. package/cli/dist/commands/logs.js +119 -0
  37. package/cli/dist/commands/maintainers.js +102 -0
  38. package/cli/dist/commands/mcp.js +28 -0
  39. package/cli/dist/commands/networks.js +306 -0
  40. package/cli/dist/commands/project.js +447 -0
  41. package/cli/dist/commands/projects.js +103 -0
  42. package/cli/dist/commands/registry.js +53 -0
  43. package/cli/dist/commands/resource.js +992 -0
  44. package/cli/dist/commands/resources.js +127 -0
  45. package/cli/dist/commands/restart.js +89 -0
  46. package/cli/dist/commands/runtime.js +75 -0
  47. package/cli/dist/commands/stack.js +171 -0
  48. package/cli/dist/commands/stacks.js +71 -0
  49. package/cli/dist/commands/status.js +211 -0
  50. package/cli/dist/commands/ui.js +725 -0
  51. package/cli/dist/commands/up.js +609 -0
  52. package/cli/dist/commands/upgrade.js +840 -0
  53. package/cli/dist/commands/version.js +10 -0
  54. package/cli/dist/components/Accessible.js +11 -0
  55. package/cli/dist/components/BaseTooltip.js +30 -0
  56. package/cli/dist/components/DetailPanel.js +33 -0
  57. package/cli/dist/components/FileTree.js +51 -0
  58. package/cli/dist/components/ResourceSelectInput.js +42 -0
  59. package/cli/dist/components/ResourceTable.js +35 -0
  60. package/cli/dist/components/ServiceIssues.js +13 -0
  61. package/cli/dist/components/TUIHeader.js +27 -0
  62. package/cli/dist/components/TabBar.js +27 -0
  63. package/cli/dist/components/Tooltip.js +13 -0
  64. package/cli/dist/components/index.js +11 -0
  65. package/cli/dist/components/ui-theme.js +120 -0
  66. package/cli/dist/config/platform-standards.js +182 -0
  67. package/cli/dist/frontend-frameworks/lit.js +64 -0
  68. package/cli/dist/frontend-frameworks/preact.js +62 -0
  69. package/cli/dist/frontend-frameworks/qwik.js +61 -0
  70. package/cli/dist/frontend-frameworks/react.js +69 -0
  71. package/cli/dist/frontend-frameworks/registry.js +83 -0
  72. package/cli/dist/frontend-frameworks/solid.js +62 -0
  73. package/cli/dist/frontend-frameworks/svelte.js +67 -0
  74. package/cli/dist/frontend-frameworks/tanstack-router.js +101 -0
  75. package/cli/dist/frontend-frameworks/types.js +1 -0
  76. package/cli/dist/frontend-frameworks/vanilla.js +59 -0
  77. package/cli/dist/frontend-frameworks/vue.js +72 -0
  78. package/cli/dist/generator/__tests__/golden-helpers.js +43 -0
  79. package/cli/dist/generator/extension-fetch.js +291 -0
  80. package/cli/dist/generator/resource-templates.js +133 -0
  81. package/cli/dist/generator/template-engine.js +801 -0
  82. package/cli/dist/index.js +10 -0
  83. package/cli/dist/mcp/server.js +101 -0
  84. package/cli/dist/mcp/tools.js +351 -0
  85. package/cli/dist/program.js +37 -0
  86. package/cli/dist/types/index.js +38 -0
  87. package/cli/dist/utils/agent-host.js +36 -0
  88. package/cli/dist/utils/atomic-write.js +36 -0
  89. package/cli/dist/utils/bun-floor.js +9 -0
  90. package/cli/dist/utils/bun-requirement.js +10 -0
  91. package/cli/dist/utils/cache.js +63 -0
  92. package/cli/dist/utils/cold-preflight.js +257 -0
  93. package/cli/dist/utils/command-helpers.js +57 -0
  94. package/cli/dist/utils/constants.js +160 -0
  95. package/cli/dist/utils/discovery-context.js +71 -0
  96. package/cli/dist/utils/discovery-paths.js +93 -0
  97. package/cli/dist/utils/docker.js +34 -0
  98. package/cli/dist/utils/doctor-crashloop.js +161 -0
  99. package/cli/dist/utils/doctor-fix.js +391 -0
  100. package/cli/dist/utils/doctor-host.js +66 -0
  101. package/cli/dist/utils/doctor-report.js +78 -0
  102. package/cli/dist/utils/doctor-runtime.js +880 -0
  103. package/cli/dist/utils/doctor-starlark.js +132 -0
  104. package/cli/dist/utils/doctor-wiring.js +698 -0
  105. package/cli/dist/utils/down-cleanup.js +125 -0
  106. package/cli/dist/utils/env-validator.js +266 -0
  107. package/cli/dist/utils/errors.js +175 -0
  108. package/cli/dist/utils/exec-async.js +31 -0
  109. package/cli/dist/utils/file-helpers.js +104 -0
  110. package/cli/dist/utils/formatting.js +165 -0
  111. package/cli/dist/utils/generated-paths.js +51 -0
  112. package/cli/dist/utils/help-command.js +11 -0
  113. package/cli/dist/utils/host-port-config.js +140 -0
  114. package/cli/dist/utils/host-port-plan.js +100 -0
  115. package/cli/dist/utils/json-output.js +29 -0
  116. package/cli/dist/utils/machine-output.js +33 -0
  117. package/cli/dist/utils/paths.js +43 -0
  118. package/cli/dist/utils/platform.js +58 -0
  119. package/cli/dist/utils/port-assignment.js +75 -0
  120. package/cli/dist/utils/port-conflict-fix.js +25 -0
  121. package/cli/dist/utils/port-fallback-notice.js +17 -0
  122. package/cli/dist/utils/port-listener-probe.js +20 -0
  123. package/cli/dist/utils/project-config-defaults.js +17 -0
  124. package/cli/dist/utils/project-features.js +91 -0
  125. package/cli/dist/utils/project-templates.js +32 -0
  126. package/cli/dist/utils/prompt.js +97 -0
  127. package/cli/dist/utils/resource-features.js +184 -0
  128. package/cli/dist/utils/resource-kind.js +9 -0
  129. package/cli/dist/utils/schema-version-gate.js +45 -0
  130. package/cli/dist/utils/search-status.js +12 -0
  131. package/cli/dist/utils/secret-redaction.js +73 -0
  132. package/cli/dist/utils/service-config-checks.js +189 -0
  133. package/cli/dist/utils/service-manifest.js +254 -0
  134. package/cli/dist/utils/service-runtime-state.js +66 -0
  135. package/cli/dist/utils/service-urls.js +112 -0
  136. package/cli/dist/utils/services.js +360 -0
  137. package/cli/dist/utils/shared-infra.js +45 -0
  138. package/cli/dist/utils/shared-platform-postgres.js +232 -0
  139. package/cli/dist/utils/single-flight.js +21 -0
  140. package/cli/dist/utils/smoke.js +401 -0
  141. package/cli/dist/utils/spinner.js +40 -0
  142. package/cli/dist/utils/stack-features.js +15 -0
  143. package/cli/dist/utils/stack-status.js +14 -0
  144. package/cli/dist/utils/startup-report.js +78 -0
  145. package/cli/dist/utils/status-message.js +21 -0
  146. package/cli/dist/utils/status-ports.js +33 -0
  147. package/cli/dist/utils/suggestions.js +63 -0
  148. package/cli/dist/utils/tar.js +46 -0
  149. package/cli/dist/utils/tdk-version.js +51 -0
  150. package/cli/dist/utils/terminal-layout.js +19 -0
  151. package/cli/dist/utils/tilt-events.js +194 -0
  152. package/cli/dist/utils/tilt-logs.js +61 -0
  153. package/cli/dist/utils/tilt-port-owner.js +63 -0
  154. package/cli/dist/utils/tilt-process.js +54 -0
  155. package/cli/dist/utils/tilt-resource-state.js +32 -0
  156. package/cli/dist/utils/tilt-startup.js +49 -0
  157. package/cli/dist/utils/tilt-unreachable-message.js +9 -0
  158. package/cli/dist/utils/tilt.js +104 -0
  159. package/cli/dist/utils/ui-keymap.js +129 -0
  160. package/cli/dist/utils/ui-service-state.js +34 -0
  161. package/cli/dist/utils/up-only.js +28 -0
  162. package/cli/dist/utils/up-readiness.js +118 -0
  163. package/cli/dist/utils/url-actions.js +103 -0
  164. package/cli/dist/utils/validation.js +62 -0
  165. package/cli/dist/utils/which.js +56 -0
  166. package/cli/dist/utils/windows-doctor.js +176 -0
  167. package/cli/dist-bundle/chunk-6EA4DGCY.js +2 -0
  168. package/cli/dist-bundle/chunk-BZ4H7MM4.js +3 -0
  169. package/cli/dist-bundle/chunk-CLCUIDBH.js +510 -0
  170. package/cli/dist-bundle/cli.js +2017 -0
  171. package/cli/dist-bundle/cold-preflight-SY26O2IG.js +2 -0
  172. package/cli/dist-bundle/devtools-ZUHXW33W.js +5 -0
  173. package/cli/dist-bundle/extension-fetch-J4FFH7TJ.js +2 -0
  174. package/cli/package.json +83 -0
  175. package/cli/shared-platform-engineering/docker-templates/bun-hoisted-symlink-fix.sh +25 -0
  176. package/cli/shared-platform-engineering/docker-templates/infisical-entrypoint.sh +466 -0
  177. package/cli/shared-platform-engineering/docker-templates/install-deps.sh +154 -0
  178. package/cli/shared-platform-engineering/docker-templates/prisma-bun-client-link-fix.sh +14 -0
  179. package/cli/shared-platform-engineering/docker-templates/prisma-normalize-client.sh +58 -0
  180. package/cli/templates/.tiltignore.hbs +72 -0
  181. package/cli/templates/TILT_RESOURCE_DEFAULTS.star.hbs +220 -0
  182. package/cli/templates/TILT_TECH_STACK.star.hbs +149 -0
  183. package/cli/templates/Tiltfile.hbs +381 -0
  184. package/cli/templates/spec.master.hbs +192 -0
  185. package/discovery/AGENTS.md +362 -0
  186. package/discovery/TILT_DISCOVERY.star +429 -0
  187. package/discovery/Tiltfile +58 -0
  188. package/discovery/config.star +265 -0
  189. package/discovery/constants.star +167 -0
  190. package/discovery/deterministic.star +213 -0
  191. package/discovery/discovery_daemon.star +193 -0
  192. package/discovery/discovery_orchestrator.star +492 -0
  193. package/discovery/filtering.star +7 -0
  194. package/discovery/identity-management-backend/service.yaml +26 -0
  195. package/discovery/identity-management-frontend/service.yaml +29 -0
  196. package/discovery/identity-sdk/service.yaml +9 -0
  197. package/discovery/incremental_discovery.star +215 -0
  198. package/discovery/indexing.star +9 -0
  199. package/discovery/json_manifest_scanner.star +57 -0
  200. package/discovery/libraries.star +48 -0
  201. package/discovery/loading.star +25 -0
  202. package/discovery/manifest/constants.star +106 -0
  203. package/discovery/manifest/loading.star +418 -0
  204. package/discovery/manifest/normalize.star +289 -0
  205. package/discovery/manifest/validation.star +110 -0
  206. package/discovery/normalization.star +13 -0
  207. package/discovery/registry.star +562 -0
  208. package/discovery/resource_snapshot.py +384 -0
  209. package/discovery/resource_snapshot.star +145 -0
  210. package/discovery/schemas.star +3 -0
  211. package/discovery/services/platform/cdc/debezium/nats-connector/service.yaml +9 -0
  212. package/discovery/services/platform/cdc/nats-http-bridge/service.yaml +9 -0
  213. package/discovery/services/platform/orchestrator/orchestrator-glue-backend/service.yaml +26 -0
  214. package/discovery/services/platform/synthetic-monitor/service.yaml +9 -0
  215. package/discovery/test_resource_snapshot.py +253 -0
  216. package/discovery/validation.star +80 -0
  217. package/discovery/versioning.star +3 -0
  218. package/engine/AGENTS.md +706 -0
  219. package/engine/README.md +31 -0
  220. package/engine/REFACTORING_MANIFEST_SYSTEM.md +974 -0
  221. package/engine/Tiltfile +86 -0
  222. package/engine/assets/docker/golden-layers.Dockerfile +204 -0
  223. package/engine/assets/docker/wake-gateway/Dockerfile +28 -0
  224. package/engine/assets/docker/wake-gateway/decide.test.ts +177 -0
  225. package/engine/assets/docker/wake-gateway/decide.ts +135 -0
  226. package/engine/assets/docker/wake-gateway/server.ts +363 -0
  227. package/engine/assets/scripts/cleanup-completed-migrator-images.sh +39 -0
  228. package/engine/assets/scripts/cleanup-tilt-images.sh +122 -0
  229. package/engine/assets/scripts/mac-m1-resource-monitor.sh +123 -0
  230. package/engine/config.star +5 -0
  231. package/engine/entrypoint.star +101 -0
  232. package/engine/lifecycle/orchestrator.star +263 -0
  233. package/engine/paths.star +719 -0
  234. package/engine/schemas/project-schema.json +147 -0
  235. package/engine/schemas/service-schema.json +537 -0
  236. package/engine/scripts/README.md +89 -0
  237. package/engine/scripts/build-and-publish-lib.sh +207 -0
  238. package/engine/scripts/check-lib-publish.sh +87 -0
  239. package/engine/scripts/debug-container.sh +265 -0
  240. package/engine/scripts/generate-manifest.sh +200 -0
  241. package/engine/spec.master +702 -0
  242. package/engine/spec.master.example +341 -0
  243. package/engine/topologies/README.md +33 -0
  244. package/engine/topologies/platform/docker/AGENTS.md +59 -0
  245. package/engine/topologies/platform/docker/auth/auth.star +207 -0
  246. package/engine/topologies/platform/docker/build/frontend_build_plan.star +65 -0
  247. package/engine/topologies/platform/docker/build/golden_image.star +37 -0
  248. package/engine/topologies/platform/docker/build/golden_image_build.star +144 -0
  249. package/engine/topologies/platform/docker/build/golden_image_constants.star +100 -0
  250. package/engine/topologies/platform/docker/build/golden_image_dockerfile.star +263 -0
  251. package/engine/topologies/platform/docker/compose/compose.star +637 -0
  252. package/engine/topologies/platform/docker/compose/compose_helpers.star +54 -0
  253. package/engine/topologies/platform/docker/compose/traefik_standalone.star +171 -0
  254. package/engine/topologies/platform/docker/config/bunignore.star +144 -0
  255. package/engine/topologies/platform/docker/config/dockerignore.star +152 -0
  256. package/engine/topologies/platform/docker/config/healthcheck.star +58 -0
  257. package/engine/topologies/platform/docker/constants.star +211 -0
  258. package/engine/topologies/platform/docker/dockerfile/dockerfile.star +56 -0
  259. package/engine/topologies/platform/docker/dockerfile/language_dockerfile.star +264 -0
  260. package/engine/topologies/platform/docker/generators/golden_docker_generator_v2.star +76 -0
  261. package/engine/topologies/platform/docker/index.star +40 -0
  262. package/engine/topologies/platform/docker/layers/bun_helpers.star +25 -0
  263. package/engine/topologies/platform/docker/layers/infisical/index.star +42 -0
  264. package/engine/topologies/platform/docker/layers/infisical/infisical_docker.star +264 -0
  265. package/engine/topologies/platform/docker/layers/l1_base_layers.star +89 -0
  266. package/engine/topologies/platform/docker/layers/l2_dependency_layers.star +147 -0
  267. package/engine/topologies/platform/docker/layers/l3_builder_layers.star +229 -0
  268. package/engine/topologies/platform/docker/layers/l4_runtime_layers.star +282 -0
  269. package/engine/topologies/platform/docker/layers/prisma/constants.star +138 -0
  270. package/engine/topologies/platform/docker/layers/prisma/db_readiness.star +98 -0
  271. package/engine/topologies/platform/docker/layers/prisma/filesystem_setup.star +131 -0
  272. package/engine/topologies/platform/docker/layers/prisma/migrate_script.star +100 -0
  273. package/engine/topologies/platform/docker/layers/prisma/prisma_build.star +128 -0
  274. package/engine/topologies/platform/docker/layers/prisma/prisma_runtime.star +205 -0
  275. package/engine/topologies/platform/docker/layers/prisma/secret_resolution.star +121 -0
  276. package/engine/topologies/platform/docker/networking/api_path_constants.star +206 -0
  277. package/engine/topologies/platform/docker/networking/sablier_container_cycle.star +31 -0
  278. package/engine/topologies/platform/docker/networking/traefik.star +266 -0
  279. package/engine/topologies/platform/docker/networking/traefik_constants.star +148 -0
  280. package/engine/topologies/platform/docker/networking/traefik_helpers.star +162 -0
  281. package/engine/topologies/platform/docker/networking/traefik_static_routes.star +165 -0
  282. package/engine/topologies/platform/docker/secrets/env_secrets.star +74 -0
  283. package/engine/topologies/platform/docker/secrets/infisical.star +109 -0
  284. package/engine/topologies/platform/net/AGENTS.md +64 -0
  285. package/engine/topologies/platform/net/proxy.star +6 -0
  286. package/engine/topologies/platform/registries/local.star +6 -0
  287. package/engine/topologies/platform/registries/verdaccio_loader.star +20 -0
  288. package/engine/topologies/platform/security/AGENTS.md +49 -0
  289. package/engine/topologies/platform/security/secrets.star +241 -0
  290. package/engine/topologies/platform/state/AGENTS.md +64 -0
  291. package/engine/topologies/platform/state/relational.star +6 -0
  292. package/engine/topologies/tilt/common/AGENTS.md +59 -0
  293. package/engine/topologies/tilt/common/utils.star +409 -0
  294. package/engine/topologies/tilt/common/utils_debug.star +71 -0
  295. package/engine/topologies/tilt/common/utils_deterministic.star +170 -0
  296. package/engine/topologies/tilt/common/utils_docker_networks.star +54 -0
  297. package/engine/topologies/tilt/common/utils_env.star +92 -0
  298. package/engine/topologies/tilt/common/utils_output.star +99 -0
  299. package/engine/topologies/tilt/config/AGENTS.md +68 -0
  300. package/engine/topologies/tilt/config/defaults.star +5 -0
  301. package/engine/topologies/tilt/config/feature_flags.star +12 -0
  302. package/engine/topologies/tilt/config/global.star +57 -0
  303. package/engine/topologies/tilt/config/profiles.star +398 -0
  304. package/engine/topologies/tilt/generators/agents_md.star +64 -0
  305. package/engine/topologies/tilt/generators/api_gateway.star +147 -0
  306. package/engine/topologies/tilt/generators/index.star +126 -0
  307. package/engine/topologies/tilt/generators/infisical/README.md +424 -0
  308. package/engine/topologies/tilt/generators/infisical/examples.star +314 -0
  309. package/engine/topologies/tilt/generators/infisical/index.star +59 -0
  310. package/engine/topologies/tilt/generators/infisical/machine_identity.star +422 -0
  311. package/engine/topologies/tilt/generators/infisical/organization.star +536 -0
  312. package/engine/topologies/tilt/generators/infisical/path_manager.star +478 -0
  313. package/engine/topologies/tilt/generators/infisical/secrets_generator.star +422 -0
  314. package/engine/topologies/tilt/generators/nginx_conf.star +145 -0
  315. package/engine/topologies/tilt/generators/npmrc.star +132 -0
  316. package/engine/topologies/tilt/generators/tsconfig.star +25 -0
  317. package/engine/topologies/tilt/generators/typescript/backend_library_tsconfig.star +73 -0
  318. package/engine/topologies/tilt/generators/typescript/backend_tsconfig.star +137 -0
  319. package/engine/topologies/tilt/generators/typescript/common.star +9 -0
  320. package/engine/topologies/tilt/generators/typescript/frontend_library_tsconfig.star +78 -0
  321. package/engine/topologies/tilt/generators/typescript/frontend_tsconfig.star +140 -0
  322. package/engine/topologies/tilt/generators/typescript/include.star +25 -0
  323. package/engine/topologies/tilt/generators/typescript/playwright_config.star +42 -0
  324. package/engine/topologies/tilt/generators/typescript/prisma_config.star +51 -0
  325. package/engine/topologies/tilt/generators/validators.star +868 -0
  326. package/engine/topologies/tilt/generators/vite/backend.star +80 -0
  327. package/engine/topologies/tilt/generators/vite/frameworks/lit.star +92 -0
  328. package/engine/topologies/tilt/generators/vite/frameworks/preact.star +94 -0
  329. package/engine/topologies/tilt/generators/vite/frameworks/qwik.star +94 -0
  330. package/engine/topologies/tilt/generators/vite/frameworks/react.star +128 -0
  331. package/engine/topologies/tilt/generators/vite/frameworks/solid.star +94 -0
  332. package/engine/topologies/tilt/generators/vite/frameworks/svelte.star +94 -0
  333. package/engine/topologies/tilt/generators/vite/frameworks/vanilla.star +92 -0
  334. package/engine/topologies/tilt/generators/vite/frameworks/vue.star +94 -0
  335. package/engine/topologies/tilt/generators/vite/frontend.star +153 -0
  336. package/engine/topologies/tilt/generators/vite/generators.star +45 -0
  337. package/engine/topologies/tilt/generators/vite/helpers.star +256 -0
  338. package/engine/topologies/tilt/generators/vite/library.star +67 -0
  339. package/engine/topologies/tilt/generators/vite/sdk.star +75 -0
  340. package/engine/topologies/tilt/generators/vite/templates.star +460 -0
  341. package/engine/topologies/tilt/generators/vite_config.star +24 -0
  342. package/engine/topologies/tilt/manifest/AGENTS.md +61 -0
  343. package/engine/topologies/tilt/manifest/README.md +679 -0
  344. package/engine/topologies/tilt/manifest/__init__.star +220 -0
  345. package/engine/topologies/tilt/manifest/constants.star +262 -0
  346. package/engine/topologies/tilt/manifest/errors.star +268 -0
  347. package/engine/topologies/tilt/manifest/integration.star +348 -0
  348. package/engine/topologies/tilt/manifest/json_to_yaml.py +61 -0
  349. package/engine/topologies/tilt/manifest/loader.star +239 -0
  350. package/engine/topologies/tilt/manifest/mapper.star +229 -0
  351. package/engine/topologies/tilt/manifest/parser.star +490 -0
  352. package/engine/topologies/tilt/manifest/schema.star +502 -0
  353. package/engine/topologies/tilt/manifest/tests/test_integration.star +278 -0
  354. package/engine/topologies/tilt/manifest/tests/test_loader_parser.star +475 -0
  355. package/engine/topologies/tilt/manifest/tests/test_manifest.star +319 -0
  356. package/engine/topologies/tilt/manifest/tests/test_validator.star +472 -0
  357. package/engine/topologies/tilt/manifest/validator.star +744 -0
  358. package/engine/topologies/tilt/manifest/yaml_to_json.py +20 -0
  359. package/engine/topologies/tilt/resources/AGENTS.md +71 -0
  360. package/engine/topologies/tilt/resources/build_concurrency.star +56 -0
  361. package/engine/topologies/tilt/resources/conditions.star +5 -0
  362. package/engine/topologies/tilt/resources/databases.star +246 -0
  363. package/engine/topologies/tilt/resources/declaration.star +5 -0
  364. package/engine/topologies/tilt/resources/deps.star +5 -0
  365. package/engine/topologies/tilt/resources/infra-loader.star +504 -0
  366. package/engine/topologies/tilt/resources/libs.star +32 -0
  367. package/engine/topologies/tilt/resources/libs_discovery.star +104 -0
  368. package/engine/topologies/tilt/resources/libs_paths.star +81 -0
  369. package/engine/topologies/tilt/resources/libs_resource_definition.star +153 -0
  370. package/engine/topologies/tilt/resources/libs_setup.star +166 -0
  371. package/engine/topologies/tilt/resources/libs_tsconfig.star +39 -0
  372. package/engine/topologies/tilt/resources/orchestrator/apply.star +79 -0
  373. package/engine/topologies/tilt/resources/orchestrator/apply_compose_resource_registration.star +864 -0
  374. package/engine/topologies/tilt/resources/orchestrator/apply_manifest_orchestration.star +90 -0
  375. package/engine/topologies/tilt/resources/orchestrator/apply_migrator_orchestration.star +150 -0
  376. package/engine/topologies/tilt/resources/orchestrator/apply_resource_validation.star +38 -0
  377. package/engine/topologies/tilt/resources/orchestrator/apply_runtime_flags.star +46 -0
  378. package/engine/topologies/tilt/resources/orchestrator/builders/typescript.star +193 -0
  379. package/engine/topologies/tilt/resources/orchestrator/generators/dependencies/AGENTS.md +75 -0
  380. package/engine/topologies/tilt/resources/orchestrator/generators/dependencies/index.star +23 -0
  381. package/engine/topologies/tilt/resources/orchestrator/generators/dependencies/resolver.star +136 -0
  382. package/engine/topologies/tilt/resources/orchestrator/generators/env.star +219 -0
  383. package/engine/topologies/tilt/resources/orchestrator/generators/frontend.star +172 -0
  384. package/engine/topologies/tilt/resources/orchestrator/generators/manifest_resource.star +577 -0
  385. package/engine/topologies/tilt/resources/orchestrator/helpers.star +35 -0
  386. package/engine/topologies/tilt/resources/orchestrator.star +56 -0
  387. package/engine/topologies/tilt/resources/ordering.star +5 -0
  388. package/engine/topologies/tilt/resources/shared-platform-postgres.star +30 -0
  389. package/engine/topologies/tilt/resources/triggers.star +5 -0
  390. package/engine/topologies/tilt/resources/watchers.star +304 -0
  391. package/engine/where-things-live.star +719 -0
  392. package/examples/tdk-example/LICENSE +21 -0
  393. package/examples/tdk-example/README.md +23 -0
  394. package/examples/tdk-example/TILT_SERVICE_DEFAULTS.star +42 -0
  395. package/examples/tdk-example/TILT_TECH_STACK.star +67 -0
  396. package/examples/tdk-example/Tiltfile +25 -0
  397. package/examples/tdk-example/services/platform/messaging/docker-compose.yml +26 -0
  398. package/examples/tdk-example/services/shop/orders-api/package.json +20 -0
  399. package/examples/tdk-example/services/shop/orders-api/service.json +14 -0
  400. package/examples/tdk-example/services/shop/orders-api/src/index.ts +81 -0
  401. package/examples/tdk-example/services/shop/orders-app/index.html +12 -0
  402. package/examples/tdk-example/services/shop/orders-app/package.json +23 -0
  403. package/examples/tdk-example/services/shop/orders-app/public/.gitkeep +0 -0
  404. package/examples/tdk-example/services/shop/orders-app/service.json +9 -0
  405. package/examples/tdk-example/services/shop/orders-app/src/main.tsx +9 -0
  406. package/examples/tdk-example/services/shop/orders-app/src/orders.tsx +67 -0
  407. package/examples/tdk-example/services/shop/orders-app/src/style.css +15 -0
  408. package/examples/tdk-example/services/shop/orders-worker/package.json +18 -0
  409. package/examples/tdk-example/services/shop/orders-worker/service.json +13 -0
  410. package/examples/tdk-example/services/shop/orders-worker/src/index.ts +33 -0
  411. package/ext/Tiltfile +66 -0
  412. package/ext/ide-components/README.md +221 -0
  413. package/ext/ide-components/code_viewer/server.py +208 -0
  414. package/ext/ide-components/config_inspector/server.py +1052 -0
  415. package/ext/ide-components/file_browser/server.py +287 -0
  416. package/ext/ide-components/shared/config_service.py +471 -0
  417. package/ext/ide-components/shared/file_utils.py +300 -0
  418. package/ext/ide-components/shared/http_utils.py +234 -0
  419. package/ext/ide-components/shared/static/styles.css +1334 -0
  420. package/ext/ide-components/shared/syntax_highlighter.py +142 -0
  421. package/ext/ide-components/shared/template_engine.py +125 -0
  422. package/ext/ide-components/shared/templates/base.html +121 -0
  423. package/ext/ide-components/shared/test_config_service.py +328 -0
  424. package/ext/ide-components/shared/tilt_integration.py +160 -0
  425. package/ext/ui-enhancements/cron-status-server.sh +51 -0
  426. package/ext/ui-enhancements/cron-status-tracker.sh +148 -0
  427. package/ext/ui-enhancements/extension.yaml +36 -0
  428. package/ext/ui-enhancements/tiltfile.py +101 -0
  429. package/ext/ui-enhancements/ui/cron-jobs-tab.css +396 -0
  430. package/ext/ui-enhancements/ui/help-panel.css +279 -0
  431. package/ext/ui-enhancements/ui/icons.css +125 -0
  432. package/ext/ui-enhancements/ui/tooltips.css +114 -0
  433. package/package.json +94 -4
  434. package/shared-platform-engineering/docker-templates/bun-hoisted-symlink-fix.sh +25 -0
  435. package/shared-platform-engineering/docker-templates/infisical-entrypoint.sh +466 -0
  436. package/shared-platform-engineering/docker-templates/install-deps.sh +154 -0
  437. package/shared-platform-engineering/docker-templates/prisma-bun-client-link-fix.sh +14 -0
  438. package/shared-platform-engineering/docker-templates/prisma-normalize-client.sh +58 -0
  439. package/specs/specs/TILT_SERVICE_DEFAULTS.star +207 -0
  440. package/specs/specs/TILT_TECH_STACK.star +161 -0
@@ -0,0 +1,328 @@
1
+ #!/usr/bin/env python3
2
+ # Copyright (c) 2026 Flisk Landscape contributors
3
+ # SPDX-License-Identifier: MIT
4
+ """
5
+ Automated tests for ConfigService
6
+ Tests path validation, file operations, backups, and security features.
7
+ """
8
+
9
+ import os
10
+ import sys
11
+ import tempfile
12
+ import shutil
13
+ from pathlib import Path
14
+
15
+ # Add parent to path
16
+ sys.path.insert(0, str(Path(__file__).parent))
17
+ from config_service import ConfigService, SaveResult
18
+
19
+
20
+ class TestConfigService:
21
+ """Test suite for ConfigService"""
22
+
23
+ def __init__(self):
24
+ self.passed = 0
25
+ self.failed = 0
26
+ self.temp_dir = None
27
+
28
+ def setup(self):
29
+ """Create temporary test directory"""
30
+ self.temp_dir = tempfile.mkdtemp()
31
+ # Create structure mimicking project
32
+ (Path(self.temp_dir) / '.tilt-engine' / 'topologies').mkdir(parents=True)
33
+ (Path(self.temp_dir) / '.tilt-engine' / 'topologies' / 'test.star').write_text('# test')
34
+
35
+ # Create root master configs
36
+ (Path(self.temp_dir) / 'TILT_RESOURCE_DEFAULTS.star').write_text('# defaults')
37
+ (Path(self.temp_dir) / 'spec.master').write_text('# spec')
38
+
39
+ # Override PROJECT_ROOT for testing by patching the module directly
40
+ import config_service
41
+ self.original_root = config_service.PROJECT_ROOT
42
+ config_service.PROJECT_ROOT = Path(self.temp_dir)
43
+ # Also patch in file_utils
44
+ import file_utils
45
+ self.original_file_utils_root = file_utils.PROJECT_ROOT
46
+ file_utils.PROJECT_ROOT = Path(self.temp_dir)
47
+
48
+ def teardown(self):
49
+ """Cleanup temporary directory"""
50
+ # Restore original
51
+ import config_service
52
+ config_service.PROJECT_ROOT = self.original_root
53
+ import file_utils
54
+ file_utils.PROJECT_ROOT = self.original_file_utils_root
55
+
56
+ if self.temp_dir and os.path.exists(self.temp_dir):
57
+ shutil.rmtree(self.temp_dir)
58
+
59
+ def assert_true(self, condition, msg):
60
+ """Assert condition is true"""
61
+ if condition:
62
+ self.passed += 1
63
+ print(f" ✓ {msg}")
64
+ else:
65
+ self.failed += 1
66
+ print(f" ✗ {msg}")
67
+
68
+ def assert_false(self, condition, msg):
69
+ """Assert condition is false"""
70
+ self.assert_true(not condition, msg)
71
+
72
+ def assert_equals(self, a, b, msg):
73
+ """Assert two values are equal"""
74
+ if a == b:
75
+ self.passed += 1
76
+ print(f" ✓ {msg}")
77
+ else:
78
+ self.failed += 1
79
+ print(f" ✗ {msg}: expected {b}, got {a}")
80
+
81
+ def run_all_tests(self):
82
+ """Run all test methods"""
83
+ print("\n" + "="*60)
84
+ print("ConfigService Test Suite")
85
+ print("="*60)
86
+
87
+ self.setup()
88
+ try:
89
+ self.test_path_validation()
90
+ self.test_file_type_validation()
91
+ self.test_hash_computation()
92
+ self.test_backup_rotation()
93
+ self.test_conflict_detection()
94
+ self.test_atomic_write()
95
+ self.test_csrf_validation()
96
+ self.test_content_length_validation()
97
+ finally:
98
+ self.teardown()
99
+
100
+ print("\n" + "="*60)
101
+ print(f"Results: {self.passed} passed, {self.failed} failed")
102
+ print("="*60)
103
+ return self.failed == 0
104
+
105
+ def test_path_validation(self):
106
+ """Test 7.4, 7.10, 7.11: Path validation and traversal prevention"""
107
+ print("\n📁 Testing Path Validation (Tasks 7.4, 7.10, 7.11)")
108
+
109
+ # Valid paths - topologies
110
+ valid_paths = [
111
+ '.tilt-engine/topologies/test.star',
112
+ '.tilt-engine/topologies/tilt/discovery/registry.star',
113
+ ]
114
+
115
+ for path in valid_paths:
116
+ result = ConfigService.validate_write_path(path)
117
+ self.assert_true(result is not None, f"Valid path accepted: {path}")
118
+
119
+ # Valid paths - project root master configs (Task 7.11)
120
+ root_configs = [
121
+ 'TILT_RESOURCE_DEFAULTS.star',
122
+ 'spec.master',
123
+ '.tilt-engine/spec.master',
124
+ ]
125
+
126
+ for path in root_configs:
127
+ result = ConfigService.validate_write_path(path)
128
+ self.assert_true(result is not None, f"Root config accepted: {path}")
129
+
130
+ # Invalid paths - traversal attempts
131
+ invalid_paths = [
132
+ '../outside.star',
133
+ '.tilt-engine/../../etc/passwd',
134
+ '%2e%2e%2fsecret.star',
135
+ '/etc/passwd',
136
+ 'random/file.star',
137
+ 'README.md',
138
+ ]
139
+
140
+ for path in invalid_paths:
141
+ result = ConfigService.validate_write_path(path)
142
+ self.assert_true(result is None, f"Invalid path rejected: {path}")
143
+
144
+ def test_file_type_validation(self):
145
+ """Test 7.12: File extension validation"""
146
+ print("\n📄 Testing File Type Validation (Task 7.12)")
147
+
148
+ # Valid file types
149
+ valid_files = [
150
+ 'test.star',
151
+ 'spec.master',
152
+ '.tilt-engine/spec.master',
153
+ 'TILT_RESOURCE_DEFAULTS.star',
154
+ ]
155
+
156
+ for path in valid_files:
157
+ is_valid, _ = ConfigService.validate_file_type(path)
158
+ self.assert_true(is_valid, f"Valid file type: {path}")
159
+
160
+ # Invalid file types
161
+ invalid_files = [
162
+ 'README.md',
163
+ 'file.txt',
164
+ 'script.py',
165
+ 'config.json',
166
+ ]
167
+
168
+ for path in invalid_files:
169
+ is_valid, _ = ConfigService.validate_file_type(path)
170
+ self.assert_false(is_valid, f"Invalid file type rejected: {path}")
171
+
172
+ def test_hash_computation(self):
173
+ """Test 7.9: Hash computation for conflict detection"""
174
+ print("\n🔐 Testing Hash Computation (Task 7.9)")
175
+
176
+ # Same content produces same hash
177
+ content1 = "Hello, World!"
178
+ hash1 = ConfigService.compute_content_hash(content1)
179
+ hash2 = ConfigService.compute_content_hash(content1)
180
+ self.assert_equals(hash1, hash2, "Same content produces same hash")
181
+
182
+ # Different content produces different hash
183
+ content2 = "Hello, World"
184
+ hash3 = ConfigService.compute_content_hash(content2)
185
+ self.assert_true(hash1 != hash3, "Different content produces different hash")
186
+
187
+ # Hash is SHA-256 (64 hex characters)
188
+ self.assert_equals(len(hash1), 64, "Hash is 64 hex chars (SHA-256)")
189
+
190
+ def test_backup_rotation(self):
191
+ """Test 7.8: Backup creation and rotation"""
192
+ print("\n💾 Testing Backup Rotation (Task 7.8)")
193
+
194
+ import time
195
+
196
+ # Create test file
197
+ test_file = Path(self.temp_dir) / '.tilt-engine' / 'topologies' / 'backup_test.star'
198
+ test_file.write_text('version 1')
199
+
200
+ # Create multiple backups with small delays to ensure different timestamps
201
+ for i in range(5):
202
+ time.sleep(0.01) # Small delay to ensure different timestamps
203
+ test_file.write_text(f'version {i+2}')
204
+ backup_path, msg = ConfigService.create_backup_with_rotation(test_file, max_backups=3)
205
+ self.assert_true(backup_path is not None, f"Backup {i+1} created: {msg}")
206
+
207
+ # Check only 3 backups exist
208
+ backup_dir = test_file.parent / '.backups'
209
+ if backup_dir.exists():
210
+ backups = list(backup_dir.glob('backup_test.star.*.backup'))
211
+ self.assert_true(len(backups) <= 3, f"Rotation keeps max 3 backups (found {len(backups)})")
212
+ else:
213
+ self.assert_true(False, "Backup directory should exist")
214
+
215
+ def test_conflict_detection(self):
216
+ """Test 7.9: File content hash conflict detection"""
217
+ print("\n⚠️ Testing Conflict Detection (Task 7.9)")
218
+
219
+ # Create test file
220
+ test_file = Path(self.temp_dir) / '.tilt-engine' / 'topologies' / 'conflict_test.star'
221
+ original_content = "Original content"
222
+ test_file.write_text(original_content)
223
+
224
+ # Get original hash
225
+ original_hash = ConfigService.compute_content_hash(original_content)
226
+
227
+ # No conflict when file unchanged
228
+ has_conflict, msg = ConfigService.check_conflict(test_file, original_hash)
229
+ self.assert_false(has_conflict, "No conflict when file unchanged")
230
+
231
+ # Modify file
232
+ test_file.write_text("Modified content")
233
+
234
+ # Conflict detected after modification
235
+ has_conflict, msg = ConfigService.check_conflict(test_file, original_hash)
236
+ self.assert_true(has_conflict, "Conflict detected after file modification")
237
+
238
+ def test_atomic_write(self):
239
+ """Test 7.7, 7.20: Atomic write and failure recovery"""
240
+ print("\n📝 Testing Atomic Write (Tasks 7.7, 7.20)")
241
+
242
+ # Use relative path that will pass validation
243
+ rel_path = '.tilt-engine/topologies/atomic_test.star'
244
+ abs_path = Path(self.temp_dir) / rel_path
245
+
246
+ # Verify path validation works
247
+ validated = ConfigService.validate_write_path(rel_path)
248
+ self.assert_true(validated is not None, "Path validation for atomic write")
249
+
250
+ # Test successful write (using relative path)
251
+ result = ConfigService.atomic_write(validated, "Test content", create_backup=False)
252
+ self.assert_true(result.success, f"Atomic write succeeds: {result.message}")
253
+ self.assert_true(abs_path.exists(), "File created")
254
+ self.assert_equals(abs_path.read_text(), "Test content", "Content written correctly")
255
+
256
+ # Test write with backup
257
+ result = ConfigService.atomic_write(validated, "Updated content", create_backup=True)
258
+ self.assert_true(result.success, f"Atomic write with backup succeeds: {result.message}")
259
+ self.assert_true(result.backup_path is not None, "Backup created")
260
+
261
+ # Test conflict detection during write
262
+ original_hash = ConfigService.compute_content_hash("Wrong hash")
263
+ result = ConfigService.atomic_write(
264
+ validated,
265
+ "New content",
266
+ original_hash=original_hash,
267
+ create_backup=False
268
+ )
269
+ self.assert_false(result.success, "Write fails with hash conflict")
270
+
271
+ def test_csrf_validation(self):
272
+ """Test 7.13: CSRF protection"""
273
+ print("\n🛡️ Testing CSRF Protection (Task 7.13)")
274
+
275
+ # Valid token with localhost origin
276
+ is_valid, _ = ConfigService.validate_csrf_token(
277
+ "valid_token_12345",
278
+ referer="http://localhost:9767/",
279
+ origin="http://localhost:9767"
280
+ )
281
+ self.assert_true(is_valid, "Valid CSRF token with localhost origin")
282
+
283
+ # Invalid token (too short)
284
+ is_valid, _ = ConfigService.validate_csrf_token(
285
+ "short",
286
+ referer="http://localhost:9767/",
287
+ origin="http://localhost:9767"
288
+ )
289
+ self.assert_false(is_valid, "Short token rejected")
290
+
291
+ # Valid token but wrong origin
292
+ is_valid, _ = ConfigService.validate_csrf_token(
293
+ "valid_token_12345",
294
+ referer="https://evil.com/",
295
+ origin="https://evil.com"
296
+ )
297
+ self.assert_false(is_valid, "Wrong origin rejected")
298
+
299
+ def test_content_length_validation(self):
300
+ """Test content length limits"""
301
+ print("\n📏 Testing Content Length Validation")
302
+
303
+ # Valid content length
304
+ is_valid, _ = ConfigService.validate_request_content_length("1024")
305
+ self.assert_true(is_valid, "Valid content length accepted")
306
+
307
+ # Too large
308
+ is_valid, _ = ConfigService.validate_request_content_length(str(2 * 1024 * 1024))
309
+ self.assert_false(is_valid, "Oversized content rejected")
310
+
311
+ # Missing
312
+ is_valid, _ = ConfigService.validate_request_content_length(None)
313
+ self.assert_false(is_valid, "Missing content length rejected")
314
+
315
+ # Invalid format
316
+ is_valid, _ = ConfigService.validate_request_content_length("invalid")
317
+ self.assert_false(is_valid, "Invalid content length rejected")
318
+
319
+
320
+ def run_tests():
321
+ """Run all tests and return exit code"""
322
+ tester = TestConfigService()
323
+ success = tester.run_all_tests()
324
+ return 0 if success else 1
325
+
326
+
327
+ if __name__ == '__main__':
328
+ sys.exit(run_tests())
@@ -0,0 +1,160 @@
1
+ #!/usr/bin/env python3
2
+ # Copyright (c) 2026 Flisk Landscape contributors
3
+ # SPDX-License-Identifier: MIT
4
+ """
5
+ Tilt integration utilities for IDE components
6
+ """
7
+
8
+ import subprocess
9
+ import json
10
+
11
+ from file_utils import PROJECT_ROOT
12
+
13
+
14
+ class TiltIntegration:
15
+ """Utilities for calling Tilt commands from Python"""
16
+
17
+ @staticmethod
18
+ def trigger_resource(resource_name: str) -> dict:
19
+ """
20
+ Trigger a Tilt resource (e.g., config-gen for a service)
21
+
22
+ Returns: {'success': bool, 'output': str, 'error': str}
23
+ """
24
+ try:
25
+ result = subprocess.run(
26
+ ['tilt', 'trigger', resource_name],
27
+ cwd=PROJECT_ROOT,
28
+ capture_output=True,
29
+ text=True,
30
+ timeout=30
31
+ )
32
+
33
+ return {
34
+ 'success': result.returncode == 0,
35
+ 'output': result.stdout,
36
+ 'error': result.stderr if result.returncode != 0 else None
37
+ }
38
+ except subprocess.TimeoutExpired:
39
+ return {'success': False, 'output': '', 'error': 'Command timed out'}
40
+ except FileNotFoundError:
41
+ return {'success': False, 'output': '', 'error': 'tilt command not found. Is Tilt installed?'}
42
+ except Exception as e:
43
+ return {'success': False, 'output': '', 'error': str(e)}
44
+
45
+ @staticmethod
46
+ def get_resources() -> list:
47
+ """
48
+ Get list of all Tilt resources
49
+
50
+ Returns: List of resource names
51
+ """
52
+ try:
53
+ result = subprocess.run(
54
+ ['tilt', 'get', 'uiresources', '-o', 'json'],
55
+ cwd=PROJECT_ROOT,
56
+ capture_output=True,
57
+ text=True,
58
+ timeout=10
59
+ )
60
+
61
+ if result.returncode != 0:
62
+ return []
63
+
64
+ data = json.loads(result.stdout)
65
+ resources = []
66
+
67
+ for item in data.get('items', []):
68
+ name = item.get('metadata', {}).get('name', '')
69
+ if name:
70
+ resources.append(name)
71
+
72
+ return resources
73
+ except Exception:
74
+ return []
75
+
76
+ @staticmethod
77
+ def get_resource_status(resource_name: str) -> dict:
78
+ """
79
+ Get status of a specific Tilt resource
80
+
81
+ Returns: {'exists': bool, 'status': str, 'error': str}
82
+ """
83
+ try:
84
+ result = subprocess.run(
85
+ ['tilt', 'get', 'uiresources', resource_name, '-o', 'json'],
86
+ cwd=PROJECT_ROOT,
87
+ capture_output=True,
88
+ text=True,
89
+ timeout=10
90
+ )
91
+
92
+ if result.returncode != 0:
93
+ return {'exists': False, 'status': 'unknown', 'error': result.stderr}
94
+
95
+ data = json.loads(result.stdout)
96
+ status = data.get('status', {}).get('runtimeStatus', 'unknown')
97
+
98
+ return {'exists': True, 'status': status, 'error': None}
99
+ except Exception as e:
100
+ return {'exists': False, 'status': 'unknown', 'error': str(e)}
101
+
102
+ @staticmethod
103
+ def regenerate_resource_configs(resource_name: str) -> dict:
104
+ """
105
+ Trigger config regeneration for a service
106
+
107
+ Tries common config-gen resource naming patterns:
108
+ - <service>-config-gen
109
+ - <service>-yaml
110
+
111
+ Returns: {'success': bool, 'message': str}
112
+ """
113
+ # Try different resource name patterns
114
+ patterns = [
115
+ f'{resource_name}-config-gen',
116
+ f'{resource_name}-yaml',
117
+ f'{resource_name}-config',
118
+ ]
119
+
120
+ for pattern in patterns:
121
+ result = TiltIntegration.trigger_resource(pattern)
122
+ if result['success']:
123
+ return {
124
+ 'success': True,
125
+ 'message': f'Regenerated configs for {resource_name} via {pattern}'
126
+ }
127
+
128
+ return {
129
+ 'success': False,
130
+ 'message': f'Could not find config-gen resource for {resource_name}. Tried: {", ".join(patterns)}'
131
+ }
132
+
133
+ @staticmethod
134
+ def is_tilt_running() -> bool:
135
+ """Check if Tilt is currently running"""
136
+ try:
137
+ result = subprocess.run(
138
+ ['tilt', 'status'],
139
+ cwd=PROJECT_ROOT,
140
+ capture_output=True,
141
+ text=True,
142
+ timeout=5
143
+ )
144
+ return result.returncode == 0
145
+ except Exception:
146
+ return False
147
+
148
+
149
+ if __name__ == '__main__':
150
+ # Test
151
+ print(f"Project root: {PROJECT_ROOT}")
152
+ print(f"Tilt running: {TiltIntegration.is_tilt_running()}")
153
+
154
+ resources = TiltIntegration.get_resources()
155
+ print(f"Found {len(resources)} resources")
156
+
157
+ # Show first 5
158
+ for name in resources[:5]:
159
+ status = TiltIntegration.get_resource_status(name)
160
+ print(f" - {name}: {status['status']}")
@@ -0,0 +1,51 @@
1
+ #!/bin/bash
2
+ # Copyright (c) 2026 Flisk Landscape contributors
3
+ # SPDX-License-Identifier: MIT
4
+ # ============================================================================
5
+ # Cron Jobs Status HTTP Server
6
+ # Serves cron job status as JSON for the UI extension
7
+ # ============================================================================
8
+
9
+ STATUS_FILE="/tmp/cron-jobs-status.json"
10
+ PORT=10352
11
+
12
+ echo "🌐 Cron Jobs Status Server starting on port ${PORT}..."
13
+
14
+ # Simple HTTP server using Python
15
+ python3 << 'PYEOF'
16
+ import http.server
17
+ import socketserver
18
+ import json
19
+ import os
20
+
21
+ STATUS_FILE = "/tmp/cron-jobs-status.json"
22
+ PORT = 10352
23
+
24
+ class Handler(http.server.SimpleHTTPRequestHandler):
25
+ def do_GET(self):
26
+ if self.path == '/api/cron-jobs-status':
27
+ self.send_response(200)
28
+ self.send_header('Content-Type', 'application/json')
29
+ self.send_header('Access-Control-Allow-Origin', '*')
30
+ self.end_headers()
31
+
32
+ # Read status file or return default
33
+ if os.path.exists(STATUS_FILE):
34
+ with open(STATUS_FILE, 'r') as f:
35
+ data = f.read()
36
+ self.wfile.write(data.encode())
37
+ else:
38
+ default = {"jobs": [], "updatedAt": None}
39
+ self.wfile.write(json.dumps(default).encode())
40
+ else:
41
+ self.send_response(404)
42
+ self.end_headers()
43
+
44
+ def log_message(self, format, *args):
45
+ # Suppress log messages
46
+ pass
47
+
48
+ with socketserver.TCPServer(("", PORT), Handler) as httpd:
49
+ print(f"Cron Jobs Status Server running on port {PORT}")
50
+ httpd.serve_forever()
51
+ PYEOF
@@ -0,0 +1,148 @@
1
+ #!/bin/bash
2
+ # Copyright (c) 2026 Flisk Landscape contributors
3
+ # SPDX-License-Identifier: MIT
4
+ # ============================================================================
5
+ # Cron Jobs Status Tracker
6
+ # Tracks execution status of all cron jobs
7
+ # ============================================================================
8
+
9
+ STATUS_FILE="/tmp/cron-jobs-status.json"
10
+ CONTROL_DIR="/tmp/cron-jobs-control"
11
+ LOG_DIR="/tmp/cron-jobs-logs"
12
+
13
+ # Ensure directories exist
14
+ mkdir -p "$CONTROL_DIR" "$LOG_DIR"
15
+
16
+ # Initialize status file
17
+ init_status() {
18
+ cat > "$STATUS_FILE" << 'EOF'
19
+ {
20
+ "jobs": [
21
+ {
22
+ "name": "cron-lint",
23
+ "status": "idle",
24
+ "lastRun": null,
25
+ "nextRun": null,
26
+ "history": []
27
+ },
28
+ {
29
+ "name": "cron-format",
30
+ "status": "idle",
31
+ "lastRun": null,
32
+ "nextRun": null,
33
+ "history": []
34
+ },
35
+ {
36
+ "name": "auto-prune-dangling",
37
+ "status": "running",
38
+ "lastRun": null,
39
+ "nextRun": null,
40
+ "history": []
41
+ },
42
+ {
43
+ "name": "auto-prune-migrator-images",
44
+ "status": "running",
45
+ "lastRun": null,
46
+ "nextRun": null,
47
+ "history": []
48
+ }
49
+ ],
50
+ "updatedAt": null
51
+ }
52
+ EOF
53
+ }
54
+
55
+ # Update job status
56
+ update_job() {
57
+ local name=$1
58
+ local status=$2
59
+ local duration=$3
60
+ local timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
61
+
62
+ # Read current status
63
+ local current=$(cat "$STATUS_FILE" 2>/dev/null || echo '{"jobs":[]}')
64
+
65
+ # Calculate next run (60 seconds from now for cron jobs)
66
+ local nextRun=$(date -u -v+60S +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || date -u -d '+60 seconds' +"%Y-%m-%dT%H:%M:%SZ")
67
+
68
+ # Update using Python for reliable JSON manipulation
69
+ python3 << PYEOF
70
+ import json
71
+ import sys
72
+ from datetime import datetime, timedelta
73
+
74
+ data = json.loads('''$current''')
75
+ job_name = '''$name'''
76
+ status = '''$status'''
77
+ timestamp = '''$timestamp'''
78
+ duration = '''$duration'''
79
+ next_run = '''$nextRun'''
80
+
81
+ # Find and update job
82
+ for job in data.get('jobs', []):
83
+ if job['name'] == job_name:
84
+ job['status'] = status
85
+ job['lastRun'] = timestamp
86
+ job['nextRun'] = next_run
87
+
88
+ # Add to history
89
+ if 'history' not in job:
90
+ job['history'] = []
91
+
92
+ job['history'].insert(0, {
93
+ 'time': timestamp,
94
+ 'status': status,
95
+ 'duration': duration if duration else 'N/A'
96
+ })
97
+
98
+ # Keep only last 10 entries
99
+ job['history'] = job['history'][:10]
100
+ break
101
+
102
+ data['updatedAt'] = timestamp
103
+ print(json.dumps(data, indent=2))
104
+ PYEOF
105
+ }
106
+
107
+ # Check if job should pause
108
+ check_pause() {
109
+ local name=$1
110
+ if [[ -f "$CONTROL_DIR/$name.pause" ]]; then
111
+ return 0
112
+ fi
113
+ return 1
114
+ }
115
+
116
+ # Check if manual trigger requested
117
+ check_trigger() {
118
+ local name=$1
119
+ if [[ -f "$CONTROL_DIR/$name.trigger" ]]; then
120
+ rm "$CONTROL_DIR/$name.trigger"
121
+ return 0
122
+ fi
123
+ return 1
124
+ }
125
+
126
+ # Main execution
127
+ command=$1
128
+ shift
129
+
130
+ case $command in
131
+ init)
132
+ init_status
133
+ echo "Status file initialized at $STATUS_FILE"
134
+ ;;
135
+ update)
136
+ update_job "$1" "$2" "$3" > "${STATUS_FILE}.tmp" && mv "${STATUS_FILE}.tmp" "$STATUS_FILE"
137
+ ;;
138
+ pause-check)
139
+ check_pause "$1"
140
+ ;;
141
+ trigger-check)
142
+ check_trigger "$1"
143
+ ;;
144
+ *)
145
+ echo "Usage: $0 {init|update <name> <status> [duration]|pause-check <name>|trigger-check <name>}"
146
+ exit 1
147
+ ;;
148
+ esac