@omega.js/manager 0.1.0

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 (416) hide show
  1. package/.claude-plugin/marketplace.json +14 -0
  2. package/LICENSE +98 -0
  3. package/README.md +165 -0
  4. package/bin/omega +2 -0
  5. package/bin/omg +2 -0
  6. package/claude-plugin/.claude-plugin/plugin.json +11 -0
  7. package/claude-plugin/.mcp.json +9 -0
  8. package/claude-plugin/README.md +139 -0
  9. package/claude-plugin/hooks/gate/mark.sh +58 -0
  10. package/claude-plugin/hooks/gate/run.sh +97 -0
  11. package/claude-plugin/hooks/guard/run.sh +249 -0
  12. package/claude-plugin/hooks/hooks.json +63 -0
  13. package/claude-plugin/hooks/inject/run.sh +127 -0
  14. package/claude-plugin/hooks/lib/omega-gate.sh +20 -0
  15. package/claude-plugin/hooks/lib/omega-scope.sh +41 -0
  16. package/claude-plugin/hooks/lib/omega-skills.sh +209 -0
  17. package/claude-plugin/hooks/quality/run.sh +132 -0
  18. package/claude-plugin/hooks/shape/run.sh +45 -0
  19. package/claude-plugin/mcp-router-launch.js +29 -0
  20. package/claude-plugin/skills/README.md +48 -0
  21. package/claude-plugin/skills/accessibility/SKILL.md +31 -0
  22. package/claude-plugin/skills/analytics/SKILL.md +30 -0
  23. package/claude-plugin/skills/backend/SKILL.md +25 -0
  24. package/claude-plugin/skills/brandcheck/SKILL.md +29 -0
  25. package/claude-plugin/skills/browser/SKILL.md +64 -0
  26. package/claude-plugin/skills/client/SKILL.md +24 -0
  27. package/claude-plugin/skills/desktop/SKILL.md +25 -0
  28. package/claude-plugin/skills/extension/SKILL.md +25 -0
  29. package/claude-plugin/skills/main/SKILL.md +54 -0
  30. package/claude-plugin/skills/manager/SKILL.md +25 -0
  31. package/claude-plugin/skills/seo/SKILL.md +36 -0
  32. package/claude-plugin/skills/theme/SKILL.md +33 -0
  33. package/claude-plugin/skills/web/SKILL.md +29 -0
  34. package/dist/cli-run.js +34 -0
  35. package/dist/cli.js +29 -0
  36. package/dist/commands/build.js +17 -0
  37. package/dist/commands/clean.js +16 -0
  38. package/dist/commands/company.js +46 -0
  39. package/dist/commands/deploy.js +143 -0
  40. package/dist/commands/dev.js +437 -0
  41. package/dist/commands/devlog.js +25 -0
  42. package/dist/commands/help.js +48 -0
  43. package/dist/commands/manage.js +53 -0
  44. package/dist/commands/migrate.js +76 -0
  45. package/dist/commands/onboard.js +31 -0
  46. package/dist/commands/pipeline.js +319 -0
  47. package/dist/commands/test.js +380 -0
  48. package/dist/commands/update.js +128 -0
  49. package/dist/commands/version.js +8 -0
  50. package/dist/company-init.js +167 -0
  51. package/dist/company.js +283 -0
  52. package/dist/config.js +1359 -0
  53. package/dist/devlog/index.js +226 -0
  54. package/dist/devlog/lib/collect-commits.js +136 -0
  55. package/dist/devlog/lib/generate-post.js +201 -0
  56. package/dist/devlog/lib/ghostii.js +122 -0
  57. package/dist/devlog/lib/project-map.js +98 -0
  58. package/dist/devlog/lib/publish-website.js +88 -0
  59. package/dist/index.js +45 -0
  60. package/dist/lib/agents-md.js +201 -0
  61. package/dist/lib/analytics-secret.js +22 -0
  62. package/dist/lib/argv.js +21 -0
  63. package/dist/lib/auth-admin.js +120 -0
  64. package/dist/lib/automation-client.js +210 -0
  65. package/dist/lib/backend-marketing.js +49 -0
  66. package/dist/lib/brand.js +240 -0
  67. package/dist/lib/bundle-id.js +53 -0
  68. package/dist/lib/claude-settings.js +125 -0
  69. package/dist/lib/company-scaffold.js +213 -0
  70. package/dist/lib/company.js +227 -0
  71. package/dist/lib/config-flow.js +350 -0
  72. package/dist/lib/config-write.js +41 -0
  73. package/dist/lib/custom-target.js +75 -0
  74. package/dist/lib/domain-utils.js +19 -0
  75. package/dist/lib/duration.js +39 -0
  76. package/dist/lib/env-order.js +236 -0
  77. package/dist/lib/env-secret.js +78 -0
  78. package/dist/lib/firestore-rest.js +326 -0
  79. package/dist/lib/framework-bin.js +156 -0
  80. package/dist/lib/gitignore.js +63 -0
  81. package/dist/lib/google-auth.js +495 -0
  82. package/dist/lib/google-token.js +66 -0
  83. package/dist/lib/jwt.js +31 -0
  84. package/dist/lib/legacy-oauth.js +59 -0
  85. package/dist/lib/node-version.js +127 -0
  86. package/dist/lib/owner-plan.js +78 -0
  87. package/dist/lib/package-scripts.js +152 -0
  88. package/dist/lib/preflight.js +470 -0
  89. package/dist/lib/product-create.js +144 -0
  90. package/dist/lib/run-command.js +74 -0
  91. package/dist/lib/run-gates.js +70 -0
  92. package/dist/lib/run-output.js +42 -0
  93. package/dist/lib/run-summary.js +384 -0
  94. package/dist/lib/scaffold.js +427 -0
  95. package/dist/lib/service-input.js +207 -0
  96. package/dist/lib/service-runner.js +466 -0
  97. package/dist/lib/stale.js +24 -0
  98. package/dist/lib/target-selection.js +155 -0
  99. package/dist/lib/verb-fanout.js +128 -0
  100. package/dist/lib/verify-live.js +188 -0
  101. package/dist/manage.js +311 -0
  102. package/dist/omega-bin.js +7 -0
  103. package/dist/onboard.js +532 -0
  104. package/dist/services/account/ensure/users.js +259 -0
  105. package/dist/services/account/index.js +97 -0
  106. package/dist/services/account/lib/backend-client.js +107 -0
  107. package/dist/services/account/lib/password.js +36 -0
  108. package/dist/services/account/lib/resolve-password.js +100 -0
  109. package/dist/services/advertising/ensure/sites.js +101 -0
  110. package/dist/services/advertising/index.js +101 -0
  111. package/dist/services/advertising/lib/adsense-api.js +41 -0
  112. package/dist/services/ai/ensure/keys.js +21 -0
  113. package/dist/services/ai/index.js +36 -0
  114. package/dist/services/analytics/ensure/google-firebase-link.js +230 -0
  115. package/dist/services/analytics/ensure/google-streams.js +256 -0
  116. package/dist/services/analytics/ensure/meta-pixel.js +22 -0
  117. package/dist/services/analytics/ensure/tiktok-pixel.js +22 -0
  118. package/dist/services/analytics/index.js +134 -0
  119. package/dist/services/analytics/lib/analytics-api.js +156 -0
  120. package/dist/services/analytics/lib/meta-api.js +83 -0
  121. package/dist/services/analytics/lib/pixel-account.js +78 -0
  122. package/dist/services/analytics/lib/pixel-provision.js +152 -0
  123. package/dist/services/analytics/lib/pixel-specs.js +57 -0
  124. package/dist/services/analytics/lib/pixel-token.js +88 -0
  125. package/dist/services/analytics/lib/property-flow.js +77 -0
  126. package/dist/services/analytics/lib/tiktok-api.js +157 -0
  127. package/dist/services/analytics/lib/tiktok-auth.js +153 -0
  128. package/dist/services/assets/ensure/logo-gen.js +68 -0
  129. package/dist/services/assets/index.js +109 -0
  130. package/dist/services/assets/lib/assets-config.js +168 -0
  131. package/dist/services/assets/lib/brandmark-api.js +160 -0
  132. package/dist/services/assets/lib/derived.js +113 -0
  133. package/dist/services/assets/lib/font-loader.js +67 -0
  134. package/dist/services/assets/lib/reconcile.js +122 -0
  135. package/dist/services/assets/lib/reset.js +118 -0
  136. package/dist/services/assets/lib/svg-logo-generator.js +154 -0
  137. package/dist/services/assets/lib/svg-to-black.js +32 -0
  138. package/dist/services/assets/write/favicons.js +82 -0
  139. package/dist/services/assets/write/icons.js +64 -0
  140. package/dist/services/assets/write/process.js +96 -0
  141. package/dist/services/assets/write/reconcile.js +30 -0
  142. package/dist/services/assets/write/social-icons.js +108 -0
  143. package/dist/services/assets/write/templates.js +345 -0
  144. package/dist/services/bookmark/ensure/sync.js +255 -0
  145. package/dist/services/bookmark/index.js +17 -0
  146. package/dist/services/campaigns/ensure/contact-person.js +40 -0
  147. package/dist/services/campaigns/ensure/custom-fields.js +84 -0
  148. package/dist/services/campaigns/ensure/domain-auth.js +92 -0
  149. package/dist/services/campaigns/ensure/event-webhook.js +89 -0
  150. package/dist/services/campaigns/ensure/link-branding.js +187 -0
  151. package/dist/services/campaigns/ensure/list.js +50 -0
  152. package/dist/services/campaigns/ensure/segments.js +109 -0
  153. package/dist/services/campaigns/ensure/sender-identity.js +153 -0
  154. package/dist/services/campaigns/ensure/unsubscribe-groups.js +116 -0
  155. package/dist/services/campaigns/index.js +79 -0
  156. package/dist/services/campaigns/lib/dns-sync.js +81 -0
  157. package/dist/services/campaigns/lib/segment-query.js +138 -0
  158. package/dist/services/campaigns/lib/sendgrid-api.js +287 -0
  159. package/dist/services/captcha/ensure/site-key.js +83 -0
  160. package/dist/services/captcha/index.js +78 -0
  161. package/dist/services/captcha/lib/console-url.js +45 -0
  162. package/dist/services/captcha/lib/recaptcha-api.js +36 -0
  163. package/dist/services/certificates/ensure/api-key.js +22 -0
  164. package/dist/services/certificates/ensure/bundle-ids.js +115 -0
  165. package/dist/services/certificates/ensure/certificates.js +187 -0
  166. package/dist/services/certificates/ensure/profiles.js +143 -0
  167. package/dist/services/certificates/index.js +225 -0
  168. package/dist/services/certificates/lib/apple-api.js +183 -0
  169. package/dist/services/certificates/lib/certificate-manager.js +252 -0
  170. package/dist/services/certificates/lib/identifier-manager.js +107 -0
  171. package/dist/services/certificates/lib/keychain.js +135 -0
  172. package/dist/services/certificates/lib/manual-walkthrough.js +165 -0
  173. package/dist/services/certificates/lib/profile-manager.js +115 -0
  174. package/dist/services/chat/data/baseline-knowledge.md +96 -0
  175. package/dist/services/chat/ensure/chat.js +106 -0
  176. package/dist/services/chat/ensure/user.js +45 -0
  177. package/dist/services/chat/index.js +139 -0
  178. package/dist/services/chat/lib/baseline-knowledge.js +137 -0
  179. package/dist/services/cloud/ensure/authentication.js +267 -0
  180. package/dist/services/cloud/ensure/billing.js +120 -0
  181. package/dist/services/cloud/ensure/cloud-messaging.js +105 -0
  182. package/dist/services/cloud/ensure/database.js +60 -0
  183. package/dist/services/cloud/ensure/firestore.js +79 -0
  184. package/dist/services/cloud/ensure/functions.js +49 -0
  185. package/dist/services/cloud/ensure/hosting.js +398 -0
  186. package/dist/services/cloud/ensure/oauth-consent.js +248 -0
  187. package/dist/services/cloud/ensure/project-settings.js +72 -0
  188. package/dist/services/cloud/ensure/sdk-config.js +95 -0
  189. package/dist/services/cloud/ensure/service-account.js +152 -0
  190. package/dist/services/cloud/ensure/services.js +103 -0
  191. package/dist/services/cloud/ensure/storage.js +47 -0
  192. package/dist/services/cloud/index.js +130 -0
  193. package/dist/services/cloud/lib/access-heal.js +130 -0
  194. package/dist/services/cloud/lib/firebase-api.js +662 -0
  195. package/dist/services/cloud/lib/project-flow.js +102 -0
  196. package/dist/services/directory/ensure/entry.js +48 -0
  197. package/dist/services/directory/index.js +64 -0
  198. package/dist/services/directory/lib/blocks.js +104 -0
  199. package/dist/services/disperse/index.js +45 -0
  200. package/dist/services/disperse/write/certs.js +117 -0
  201. package/dist/services/domain/ensure/nameservers.js +179 -0
  202. package/dist/services/domain/index.js +69 -0
  203. package/dist/services/domain/lib/namecheap-api.js +167 -0
  204. package/dist/services/domain/lib/registrars.js +46 -0
  205. package/dist/services/domain/lib/whitelist-walkthrough.js +76 -0
  206. package/dist/services/edge/ensure/cache-rules.js +105 -0
  207. package/dist/services/edge/ensure/dns-records.js +304 -0
  208. package/dist/services/edge/ensure/email-routing.js +292 -0
  209. package/dist/services/edge/ensure/rules-configuration.js +98 -0
  210. package/dist/services/edge/ensure/rules-managed-transforms.js +101 -0
  211. package/dist/services/edge/ensure/rules-redirect.js +107 -0
  212. package/dist/services/edge/ensure/rules-response-headers.js +90 -0
  213. package/dist/services/edge/ensure/rules-security.js +142 -0
  214. package/dist/services/edge/ensure/speed-scheduled-tests.js +98 -0
  215. package/dist/services/edge/ensure/workers.js +219 -0
  216. package/dist/services/edge/ensure/zone-settings.js +108 -0
  217. package/dist/services/edge/ensure/zone.js +183 -0
  218. package/dist/services/edge/index.js +73 -0
  219. package/dist/services/edge/lib/cloudflare-api.js +84 -0
  220. package/dist/services/edge/lib/dns-records-helpers.js +518 -0
  221. package/dist/services/edge/lib/read-cache.js +16 -0
  222. package/dist/services/edge/lib/ruleset-helper.js +108 -0
  223. package/dist/services/edge/workers/omega-api-proxy.js +43 -0
  224. package/dist/services/email/data/baseline-filter.md +4 -0
  225. package/dist/services/email/data/baseline-knowledge.md +86 -0
  226. package/dist/services/email/ensure/agent.js +107 -0
  227. package/dist/services/email/ensure/user.js +45 -0
  228. package/dist/services/email/index.js +138 -0
  229. package/dist/services/email/lib/baseline.js +82 -0
  230. package/dist/services/email/lib/knowledge-file.js +53 -0
  231. package/dist/services/forms/ensure/form.js +46 -0
  232. package/dist/services/forms/ensure/user.js +45 -0
  233. package/dist/services/forms/index.js +138 -0
  234. package/dist/services/migrations/ensure/notifications.js +189 -0
  235. package/dist/services/migrations/ensure/orders.js +34 -0
  236. package/dist/services/migrations/ensure/payment-provider.js +132 -0
  237. package/dist/services/migrations/ensure/payments-intents.js +34 -0
  238. package/dist/services/migrations/ensure/state-retirement.js +266 -0
  239. package/dist/services/migrations/ensure/targets-rename.js +124 -0
  240. package/dist/services/migrations/ensure/users.js +1176 -0
  241. package/dist/services/migrations/index.js +101 -0
  242. package/dist/services/migrations/lib/attribution-touch.js +64 -0
  243. package/dist/services/migrations/lib/ensure-metadata.js +144 -0
  244. package/dist/services/migrations/lib/migration-runner.js +473 -0
  245. package/dist/services/migrations/lib/sanitize-strings.js +112 -0
  246. package/dist/services/migrations/lib/schema-validator.js +154 -0
  247. package/dist/services/monitoring/ensure/dsn.js +54 -0
  248. package/dist/services/monitoring/ensure/projects.js +135 -0
  249. package/dist/services/monitoring/index.js +54 -0
  250. package/dist/services/monitoring/lib/sentry-api.js +94 -0
  251. package/dist/services/newsletter/ensure/custom-fields.js +90 -0
  252. package/dist/services/newsletter/ensure/publication.js +94 -0
  253. package/dist/services/newsletter/ensure/segments.js +140 -0
  254. package/dist/services/newsletter/ensure/webhook.js +108 -0
  255. package/dist/services/newsletter/index.js +64 -0
  256. package/dist/services/newsletter/lib/beehiiv-api.js +124 -0
  257. package/dist/services/newsletter/lib/segment-automation.js +577 -0
  258. package/dist/services/payment/ensure/chargebee-account.js +30 -0
  259. package/dist/services/payment/ensure/chargebee-products.js +359 -0
  260. package/dist/services/payment/ensure/chargebee-webhook.js +113 -0
  261. package/dist/services/payment/ensure/paypal-account.js +36 -0
  262. package/dist/services/payment/ensure/paypal-products.js +374 -0
  263. package/dist/services/payment/ensure/paypal-webhook.js +128 -0
  264. package/dist/services/payment/ensure/stripe-account.js +93 -0
  265. package/dist/services/payment/ensure/stripe-disputes.js +56 -0
  266. package/dist/services/payment/ensure/stripe-products.js +245 -0
  267. package/dist/services/payment/ensure/stripe-radar.js +74 -0
  268. package/dist/services/payment/ensure/stripe-webhook.js +130 -0
  269. package/dist/services/payment/index.js +163 -0
  270. package/dist/services/payment/lib/chargebee-api.js +338 -0
  271. package/dist/services/payment/lib/payment-utils.js +116 -0
  272. package/dist/services/payment/lib/paypal-api.js +354 -0
  273. package/dist/services/payment/lib/provider-setup.js +134 -0
  274. package/dist/services/payment/lib/stripe-api.js +152 -0
  275. package/dist/services/repo/ensure/org.js +70 -0
  276. package/dist/services/repo/ensure/pages.js +72 -0
  277. package/dist/services/repo/ensure/repo.js +90 -0
  278. package/dist/services/repo/index.js +52 -0
  279. package/dist/services/repo/lib/github-api.js +196 -0
  280. package/dist/services/search/ensure/ga-link.js +57 -0
  281. package/dist/services/search/ensure/property.js +137 -0
  282. package/dist/services/search/ensure/sitemaps.js +70 -0
  283. package/dist/services/search/index.js +61 -0
  284. package/dist/services/search/lib/search-console-api.js +92 -0
  285. package/dist/services/seo/ensure/github-repos.js +271 -0
  286. package/dist/services/seo/index.js +55 -0
  287. package/dist/services/seo/lib/gh-api.js +161 -0
  288. package/dist/services/seo/templates/developer-tool/.github/workflows/maintenance.yml +25 -0
  289. package/dist/services/seo/templates/developer-tool/.nvmrc +1 -0
  290. package/dist/services/seo/templates/developer-tool/_README.md.js +121 -0
  291. package/dist/services/seo/templates/developer-tool/_package.json.js +33 -0
  292. package/dist/services/seo/templates/developer-tool/src/index.js +120 -0
  293. package/dist/services/seo/templates/index.js +57 -0
  294. package/dist/services/server/ensure/brands.js +63 -0
  295. package/dist/services/server/index.js +42 -0
  296. package/dist/services/testing/ensure/target-checks.js +97 -0
  297. package/dist/services/testing/index.js +11 -0
  298. package/dist/services/testing/lib/checks.js +467 -0
  299. package/dist/services/update/index.js +20 -0
  300. package/dist/services/update/lib/cache.js +59 -0
  301. package/dist/services/update/lib/fingerprint.js +157 -0
  302. package/dist/services/update/write/targets.js +206 -0
  303. package/dist/services/workspace/ensure/agents.js +42 -0
  304. package/dist/services/workspace/ensure/claude-settings.js +34 -0
  305. package/dist/services/workspace/ensure/config.js +54 -0
  306. package/dist/services/workspace/ensure/defaults.js +60 -0
  307. package/dist/services/workspace/ensure/env-keys.js +55 -0
  308. package/dist/services/workspace/ensure/env-order.js +66 -0
  309. package/dist/services/workspace/ensure/env-rules.js +97 -0
  310. package/dist/services/workspace/ensure/gitignore.js +18 -0
  311. package/dist/services/workspace/ensure/scripts.js +126 -0
  312. package/dist/services/workspace/ensure/structure.js +97 -0
  313. package/dist/services/workspace/ensure/translation-sdk.js +148 -0
  314. package/dist/services/workspace/ensure/workflows.js +54 -0
  315. package/dist/services/workspace/index.js +8 -0
  316. package/dist/vendor/account/engine.js +182 -0
  317. package/dist/vendor/account/features.js +220 -0
  318. package/dist/vendor/account/index.js +53 -0
  319. package/dist/vendor/account/schema.js +272 -0
  320. package/dist/vendor/account/subscription.js +38 -0
  321. package/dist/vendor/config/company.js +31 -0
  322. package/dist/vendor/config/defaults.js +173 -0
  323. package/dist/vendor/config/demo.js +18 -0
  324. package/dist/vendor/config/desktop-artifacts.js +110 -0
  325. package/dist/vendor/config/edit.js +769 -0
  326. package/dist/vendor/config/env-delivery.js +145 -0
  327. package/dist/vendor/config/env-rules.js +93 -0
  328. package/dist/vendor/config/env-schema.js +1078 -0
  329. package/dist/vendor/config/env.js +445 -0
  330. package/dist/vendor/config/hooks.js +97 -0
  331. package/dist/vendor/config/index.js +237 -0
  332. package/dist/vendor/config/instances.js +208 -0
  333. package/dist/vendor/config/load.js +490 -0
  334. package/dist/vendor/config/merge.js +68 -0
  335. package/dist/vendor/config/order.js +139 -0
  336. package/dist/vendor/config/ports.js +374 -0
  337. package/dist/vendor/config/providers.js +32 -0
  338. package/dist/vendor/config/repo.js +142 -0
  339. package/dist/vendor/config/retired-keys.js +430 -0
  340. package/dist/vendor/config/schema.js +1610 -0
  341. package/dist/vendor/config/secrets.js +50 -0
  342. package/dist/vendor/config/seed.js +34 -0
  343. package/dist/vendor/config/site-global.js +205 -0
  344. package/dist/vendor/config/validate.js +554 -0
  345. package/dist/vendor/config/winback.js +61 -0
  346. package/dist/vendor/devkit/attach-log-file.js +262 -0
  347. package/dist/vendor/devkit/certs.js +199 -0
  348. package/dist/vendor/devkit/ci-workflows.js +520 -0
  349. package/dist/vendor/devkit/cli-router.js +156 -0
  350. package/dist/vendor/devkit/command-path.js +46 -0
  351. package/dist/vendor/devkit/deploy-record.js +180 -0
  352. package/dist/vendor/devkit/flows.js +317 -0
  353. package/dist/vendor/devkit/local-https.js +360 -0
  354. package/dist/vendor/devkit/local.js +1905 -0
  355. package/dist/vendor/devkit/logger.js +128 -0
  356. package/dist/vendor/devkit/omega-bin.js +345 -0
  357. package/dist/vendor/devkit/prompt.js +187 -0
  358. package/dist/vendor/devkit/safe-install.js +18 -0
  359. package/dist/vendor/devkit/stop-signals.js +28 -0
  360. package/dist/vendor/devkit/test/scope.js +162 -0
  361. package/dist/vendor/devkit/translate/cache.js +84 -0
  362. package/dist/vendor/devkit/translate/engine.js +243 -0
  363. package/dist/vendor/devkit/translate/index.js +49 -0
  364. package/dist/vendor/devkit/translate/languages.js +134 -0
  365. package/dist/vendor/devkit/translate/providers.js +188 -0
  366. package/dist/vendor/devkit/update.js +569 -0
  367. package/docs/AGENTS.md +200 -0
  368. package/docs/account.md +45 -0
  369. package/docs/advertising.md +46 -0
  370. package/docs/ai.md +34 -0
  371. package/docs/analytics.md +69 -0
  372. package/docs/assets.md +57 -0
  373. package/docs/bookmark.md +26 -0
  374. package/docs/brand.md +151 -0
  375. package/docs/campaigns.md +96 -0
  376. package/docs/captcha.md +46 -0
  377. package/docs/certificates.md +68 -0
  378. package/docs/chat.md +47 -0
  379. package/docs/cloud.md +110 -0
  380. package/docs/company.md +64 -0
  381. package/docs/directory.md +140 -0
  382. package/docs/disperse.md +46 -0
  383. package/docs/domain.md +56 -0
  384. package/docs/edge.md +234 -0
  385. package/docs/email.md +42 -0
  386. package/docs/forms.md +48 -0
  387. package/docs/index.md +109 -0
  388. package/docs/migration.md +203 -0
  389. package/docs/migrations.md +56 -0
  390. package/docs/monitoring.md +41 -0
  391. package/docs/newsletter.md +48 -0
  392. package/docs/payment.md +83 -0
  393. package/docs/repo.md +48 -0
  394. package/docs/search.md +44 -0
  395. package/docs/seo.md +34 -0
  396. package/docs/server.md +37 -0
  397. package/docs/shared/agent-docs.md +89 -0
  398. package/docs/shared/analytics.md +612 -0
  399. package/docs/shared/brands.md +51 -0
  400. package/docs/shared/breaking-changes.md +497 -0
  401. package/docs/shared/config.md +1387 -0
  402. package/docs/shared/deploys.md +215 -0
  403. package/docs/shared/icons.md +201 -0
  404. package/docs/shared/local-dev.md +147 -0
  405. package/docs/shared/logging.md +202 -0
  406. package/docs/shared/monitoring.md +153 -0
  407. package/docs/shared/publishing.md +183 -0
  408. package/docs/shared/rulings.md +34 -0
  409. package/docs/shared/testing.md +147 -0
  410. package/docs/shared/theming.md +604 -0
  411. package/docs/shared/translation.md +291 -0
  412. package/docs/shared/updates.md +61 -0
  413. package/docs/testing.md +34 -0
  414. package/docs/update.md +36 -0
  415. package/docs/workspace.md +64 -0
  416. package/package.json +88 -0
@@ -0,0 +1,128 @@
1
+ /**
2
+ * The brand-root VERB fan-out — one target-independent verb run over every
3
+ * target the brand has, framework and custom alike (#603).
4
+ *
5
+ * `omega build` and `omega clean` are the two verbs a brand root had for no
6
+ * target type at all: start, test and deploy each fanned out already, so a
7
+ * brand could compile or wipe its targets only one `cd` at a time. Both are the
8
+ * SAME walk with a different word, so they share this one implementation —
9
+ * commands/build.js and commands/clean.js are its two callers.
10
+ *
11
+ * The shape is the deploy fan-out's, deliberately: the same target discovery,
12
+ * the same `--target=` picker and the same dependency ORDER
13
+ * (selectTargets — backend first, custom targets last), the same flag
14
+ * forwarding, and `resolveTargetRun` as the one place a verb becomes a command
15
+ * (a framework's own `omega <verb>`, or the target's `npm run <verb>`).
16
+ *
17
+ * What differs from deploy: targets are INDEPENDENT here. Neither verb
18
+ * publishes anything, so a failure never stops the walk — knowing every broken
19
+ * target after one run beats discovering them one build at a time — and any
20
+ * failure still exits 1. A target that declares no such script steps aside
21
+ * LOUDLY, naming the target and the verb, and is never counted a failure. And
22
+ * --dry-run is CONSUMED here rather than forwarded: no framework's build/clean
23
+ * honors it, so every target prints the command it would have run and the walk
24
+ * executes nothing.
25
+ *
26
+ * The brand-root log tee lives HERE, not in the two verb files (#623): every
27
+ * other fan-out attaches at the top of its own command, but build and clean
28
+ * share this one walk and this is the only place that knows the brand root, so
29
+ * one attach keyed by the verb serves both — logs/build.log and logs/clean.log.
30
+ */
31
+ const path = require('node:path');
32
+ const chalk = require('chalk').default;
33
+ const attachLogFile = require('../vendor/devkit/attach-log-file.js');
34
+
35
+ const { resolveBrandRoot, discoverTargets } = require('./brand.js');
36
+ const { resolveTargetRun } = require('./framework-bin.js');
37
+ const { runCommand } = require('./run-command.js');
38
+ const { PICKER_FLAG, assertPickerFlags, selectTargets, buildForwardedFlags } = require('./target-selection.js');
39
+
40
+ // Both yargs spellings of the flag this fan-out consumes (see the header)
41
+ const DRY_RUN_KEYS = ['dry-run', 'dryRun'];
42
+
43
+ /**
44
+ * Run one verb across the brand's targets.
45
+ *
46
+ * @param {string} verb - The verb ('build' | 'clean').
47
+ * @param {object} [options] - The parsed CLI options (--target= consumed, the rest forwarded).
48
+ * @param {object} [deps] - Test seam: { run } replaces runCommand.
49
+ * @returns {Promise<void>} - Failures land on process.exitCode; only a retired
50
+ * picker (#780) throws, and it throws before any work.
51
+ */
52
+ async function runVerbFanout(verb, options = {}, deps = {}) {
53
+ assertPickerFlags(options);
54
+
55
+ const run = deps.run || runCommand;
56
+
57
+ const brandRoot = resolveBrandRoot(process.cwd());
58
+ if (!brandRoot) {
59
+ console.error(chalk.red(`✗ Not inside a brand monorepo (no config/omega.json5 up the tree) — run inside a brand, or inside a target for that target's ${verb}.`));
60
+ process.exitCode = 1;
61
+ return;
62
+ }
63
+
64
+ // Tee the whole fan-out to <brandRoot>/logs/<verb>.log (#623) — the walk's
65
+ // OWN verdict on disk (a target's output rides its own log: runCommand
66
+ // inherits the terminal, so a child never passes through these writers).
67
+ attachLogFile(path.join(brandRoot, 'logs', `${verb}.log`));
68
+
69
+ const targets = discoverTargets(brandRoot).filter((entry) => entry.target || entry.custom);
70
+ const { selected } = selectTargets({ targets, target: options[PICKER_FLAG] });
71
+
72
+ if (selected.length === 0) {
73
+ console.error(chalk.red(`✗ This brand has no targets under targets/ — nothing ${verb === 'clean' ? 'cleaned' : 'built'}.`));
74
+ process.exitCode = 1;
75
+ return;
76
+ }
77
+
78
+ const forwarded = buildForwardedFlags(options, DRY_RUN_KEYS);
79
+ const dryRun = !!(options['dry-run'] || options.dryRun);
80
+
81
+ console.log(chalk.bold(`\nOMEGA brand ${verb} — ${path.basename(brandRoot)}${dryRun ? chalk.dim(' (dry run)') : ''} ${chalk.dim(`(${selected.map((entry) => entry.target || entry.name).join(' → ')})`)}`));
82
+
83
+ const summary = [];
84
+
85
+ for (const [index, entry] of selected.entries()) {
86
+ const label = `[${index + 1}/${selected.length}] ${entry.name}`;
87
+ const resolved = resolveTargetRun(entry, verb, forwarded, { dryRun });
88
+
89
+ // A target that declares no such script has nothing to do and nothing
90
+ // broken — the skip NAMES the target and the verb, because a verb that
91
+ // quietly did nothing is indistinguishable from one that worked (#603)
92
+ if (resolved.kind === 'skip') {
93
+ console.log(chalk.dim(`\n⊘ ${label}: ${resolved.detail} — skipped`));
94
+ continue;
95
+ }
96
+
97
+ // Under --dry-run the run IS the plan line — nothing executes on either
98
+ // lane, and a target that would have been skipped still says so above
99
+ if (resolved.kind === 'plan') {
100
+ console.log(chalk.dim(`\n⊘ ${label}: dry run — ${resolved.detail}`));
101
+ continue;
102
+ }
103
+
104
+ if (resolved.kind === 'error') {
105
+ console.log(chalk.red(`\n✗ ${label}: ${resolved.detail}`));
106
+ summary.push({ name: entry.name, ok: false, detail: resolved.detail });
107
+ continue;
108
+ }
109
+
110
+ console.log(chalk.cyan(`${`\n─── ${label} ${chalk.dim(`(${resolved.framework || 'custom'})`)} — ${resolved.label}`.trimEnd()} ───`));
111
+ const result = await run(resolved.command, resolved.args, entry.path);
112
+
113
+ summary.push({ name: entry.name, ok: result.success, detail: result.error });
114
+ }
115
+
116
+ console.log(chalk.bold(`\n${verb.charAt(0).toUpperCase()}${verb.slice(1)} summary`));
117
+ for (const entry of summary) {
118
+ console.log(entry.ok
119
+ ? ` ${chalk.green('✓')} ${entry.name}`
120
+ : ` ${chalk.red('✗')} ${entry.name} ${chalk.dim(`— ${entry.detail}`)}`);
121
+ }
122
+
123
+ if (summary.some((entry) => !entry.ok)) {
124
+ process.exitCode = 1;
125
+ }
126
+ }
127
+
128
+ module.exports = { runVerbFanout };
@@ -0,0 +1,188 @@
1
+ /**
2
+ * Live-launch verification — the last mile of the one-command launch
3
+ * (`omega pipeline --deploy=web`): after the deploy legs push, these checks
4
+ * confirm the launch surface is actually LIVE from the outside.
5
+ *
6
+ * - site: HTTPS GET on the brand's canonical URL → 200 + text/html +
7
+ * a non-trivial body (a 200 empty shell is not a live site).
8
+ * - domain: the apex (and www, when the brand owns the apex) resolve.
9
+ * - cloudflare: the response arrives THROUGH Cloudflare (cf-ray, or
10
+ * server: cloudflare).
11
+ *
12
+ * Both transports are seams: `{ fetch, resolve }` default to the real
13
+ * globals and tests pass fakes, so no test ever touches the network.
14
+ *
15
+ * Gating mirrors the cloud service: a demo-* (emulator-only) brand has no
16
+ * live surface to check, so every leg records a gated skip with its reason
17
+ * and NO transport is called.
18
+ */
19
+ const dns = require('node:dns').promises;
20
+
21
+ const { isDemoProject } = require('../vendor/config/index.js');
22
+ const { getApexDomain } = require('./domain-utils.js');
23
+
24
+ // deploy target → the checks that prove THAT target's surface is live. Only
25
+ // the web target has an outside-observable launch surface; backend/desktop/
26
+ // extension prove themselves through their own deploy legs.
27
+ const VERIFY_LEGS = { web: ['site', 'domain', 'cloudflare'] };
28
+
29
+ // A live page is bigger than this; a 200 carrying less is an empty shell
30
+ // (a hosting placeholder, a stub 404 page served with the wrong status).
31
+ const MIN_BODY_BYTES = 500;
32
+
33
+ // Live checks talk to the internet — never let one hang the pipeline.
34
+ const REQUEST_TIMEOUT_MS = 15_000;
35
+
36
+ /**
37
+ * Resolve what a brand's live surface IS, and whether it may be checked.
38
+ *
39
+ * @param {object} brandConfig - Merged brand config (omega.json5).
40
+ * @returns {{ url: string|null, hostnames: string[], gated: string|null }} - `gated` is the skip reason when live checks must not run.
41
+ */
42
+ function resolveVerifySurface(brandConfig) {
43
+ const projectId = brandConfig?.cloud?.config?.projectId;
44
+ if (!projectId) {
45
+ return { url: null, hostnames: [], gated: 'no cloud project configured — no live surface to verify' };
46
+ }
47
+ if (isDemoProject(projectId)) {
48
+ return { url: null, hostnames: [], gated: `${projectId} is a demo-* (emulator-only) project — no live surface to verify` };
49
+ }
50
+
51
+ const url = (brandConfig?.brand?.url || '').replace(/\/$/, '');
52
+ if (!url) {
53
+ return { url: null, hostnames: [], gated: 'no brand.url configured' };
54
+ }
55
+
56
+ const hostname = new URL(url).hostname;
57
+ // www is a platform DNS record on the apex only — a subdomain brand's www
58
+ // belongs to the parent brand, so it is not this brand's to verify.
59
+ const hostnames = getApexDomain(hostname) === hostname ? [hostname, `www.${hostname}`] : [hostname];
60
+
61
+ return { url, hostnames, gated: null };
62
+ }
63
+
64
+ /** Real-fetch wrapper carrying the timeout; fakes ignore the options. */
65
+ function request(surface, transports) {
66
+ const fetchImpl = transports.fetch || globalThis.fetch;
67
+ return fetchImpl(surface.url, { redirect: 'follow', signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS) });
68
+ }
69
+
70
+ /**
71
+ * The canonical URL serves a real page.
72
+ *
73
+ * @param {object} surface - From resolveVerifySurface().
74
+ * @param {object} transports - { fetch }.
75
+ * @returns {Promise<{ status: string, error: string|null }>}
76
+ */
77
+ async function checkSite(surface, transports) {
78
+ let response;
79
+ try {
80
+ response = await request(surface, transports);
81
+ } catch (error) {
82
+ return { status: 'error', error: `${surface.url} unreachable — ${error.message}` };
83
+ }
84
+
85
+ if (response.status !== 200) {
86
+ return { status: 'error', error: `${surface.url} returned ${response.status} (expected 200)` };
87
+ }
88
+
89
+ const contentType = response.headers.get('content-type') || '(none)';
90
+ if (!contentType.includes('text/html')) {
91
+ return { status: 'error', error: `${surface.url} served content-type ${contentType} (expected text/html)` };
92
+ }
93
+
94
+ const body = await response.text();
95
+ if (body.length < MIN_BODY_BYTES) {
96
+ return { status: 'error', error: `${surface.url} served a ${body.length}-byte body (expected ≥ ${MIN_BODY_BYTES} — a 200 empty shell is not a live site)` };
97
+ }
98
+
99
+ return { status: 'success', error: null };
100
+ }
101
+
102
+ /**
103
+ * Every hostname the brand owns resolves in DNS.
104
+ *
105
+ * @param {object} surface - From resolveVerifySurface().
106
+ * @param {object} transports - { resolve }.
107
+ * @returns {Promise<{ status: string, error: string|null }>}
108
+ */
109
+ async function checkDomain(surface, transports) {
110
+ const resolve = transports.resolve || dns.resolve4;
111
+
112
+ for (const hostname of surface.hostnames) {
113
+ try {
114
+ await resolve(hostname);
115
+ } catch (error) {
116
+ return { status: 'error', error: `${hostname} does not resolve — ${error.message}` };
117
+ }
118
+ }
119
+
120
+ return { status: 'success', error: null };
121
+ }
122
+
123
+ /**
124
+ * The response arrives through Cloudflare (proxied, not origin-direct).
125
+ *
126
+ * @param {object} surface - From resolveVerifySurface().
127
+ * @param {object} transports - { fetch }.
128
+ * @returns {Promise<{ status: string, error: string|null }>}
129
+ */
130
+ async function checkCloudflare(surface, transports) {
131
+ let response;
132
+ try {
133
+ response = await request(surface, transports);
134
+ } catch (error) {
135
+ return { status: 'error', error: `${surface.url} unreachable — ${error.message}` };
136
+ }
137
+
138
+ const ray = response.headers.get('cf-ray');
139
+ const server = response.headers.get('server') || '(none)';
140
+ if (!ray && !/cloudflare/i.test(server)) {
141
+ return { status: 'error', error: `${surface.url} did not arrive through Cloudflare (no cf-ray, server: ${server})` };
142
+ }
143
+
144
+ return { status: 'success', error: null };
145
+ }
146
+
147
+ const CHECKS = { site: checkSite, domain: checkDomain, cloudflare: checkCloudflare };
148
+
149
+ /**
150
+ * Run the verify sweep for a set of deploy targets.
151
+ *
152
+ * @param {string[]} targets - Deploy targets to verify (web, backend, …).
153
+ * @param {object} brandConfig - Merged brand config.
154
+ * @param {object} [transports] - { fetch, resolve } seams; real globals by default.
155
+ * @param {object} [options] - { dryRun }: a plan-only pass records the legs it WOULD run and touches nothing.
156
+ * @returns {Promise<Array<object>>} - Run-record rows (`verify:<name>`), judged exactly like deploy legs.
157
+ */
158
+ async function runVerifyLegs(targets, brandConfig, transports = {}, options = {}) {
159
+ const names = [];
160
+ for (const target of targets) {
161
+ for (const name of VERIFY_LEGS[target] || []) {
162
+ if (!names.includes(name)) names.push(name);
163
+ }
164
+ }
165
+
166
+ if (names.length === 0) {
167
+ return [];
168
+ }
169
+
170
+ const surface = resolveVerifySurface(brandConfig);
171
+
172
+ // A dry run is plan-only everywhere else in the manager — the live sweep is
173
+ // no exception: it reports the legs it would run and sends no traffic.
174
+ const gated = options.dryRun ? 'dry-run — the live sweep is plan-only here' : surface.gated;
175
+ if (gated) {
176
+ return names.map((name) => ({ service: `verify:${name}`, status: 'skipped', output: null, error: null, reason: gated }));
177
+ }
178
+
179
+ const rows = [];
180
+ for (const name of names) {
181
+ const result = await CHECKS[name](surface, transports);
182
+ rows.push({ service: `verify:${name}`, status: result.status, output: null, error: result.error });
183
+ }
184
+
185
+ return rows;
186
+ }
187
+
188
+ module.exports = { VERIFY_LEGS, resolveVerifySurface, checkSite, checkDomain, checkCloudflare, runVerifyLegs };
package/dist/manage.js ADDED
@@ -0,0 +1,311 @@
1
+ /**
2
+ * The manage orchestrator — omega-manager's src/manage/index.js reborn for
3
+ * brand monorepos. Resolves the brand root from the cwd, loads the brand
4
+ * (omega.json5 + enabled targets + target dirs), then walks SERVICE_ORDER running
5
+ * each service's operations idempotently. Every provisioned fact a service
6
+ * resolves lands in config/omega.json5 (secrets in .env) as it goes;
7
+ * transient output lands in .omega/runs/{timestamp}.json; the summary
8
+ * prints last.
9
+ *
10
+ * Company mode (many brands from one workspace — Ian's omega-manager case)
11
+ * layers on top of this later: runManage() is already per-brand, so the
12
+ * company runner is a loop + the parallel logger, both ported when that
13
+ * mode lands.
14
+ */
15
+
16
+ const chalk = require('chalk').default;
17
+ const { loadEnvRoots } = require('./vendor/config/index.js');
18
+
19
+ const { SERVICE_ORDER, BOOT_SERVICES, OPERATIONS } = require('./config.js');
20
+ const { resolveBrandRoot, loadBrand } = require('./lib/brand.js');
21
+ const { readCompanyMarker, loadCompanyConfig } = require('./lib/company.js');
22
+ const { writeRunOutput } = require('./lib/run-output.js');
23
+ const { formatDuration } = require('./lib/duration.js');
24
+ const { runPreflight, assertFamilyVersions } = require('./lib/preflight.js');
25
+ const ensureTargetsRename = require('./services/migrations/ensure/targets-rename.js');
26
+ const { CONSENT_REQUIRED } = require('./lib/google-auth.js');
27
+ const { RunSummary } = require('./lib/run-summary.js');
28
+
29
+ // Timestamp for this process run — used in .omega/runs/{RUN_TIMESTAMP}.json
30
+ const RUN_TIMESTAMP = new Date().toISOString().replace(/[:.]/g, '-');
31
+
32
+ /**
33
+ * Run a single service for the brand.
34
+ *
35
+ * @param {string} serviceName - Service to run
36
+ * @param {Object} brand - Loaded brand (from loadBrand)
37
+ * @param {Object} options - Run options
38
+ * @returns {Object} - { status, error?, state?, output? }
39
+ */
40
+ async function runService(serviceName, brand, options = {}) {
41
+ const operations = OPERATIONS[serviceName] || [];
42
+
43
+ if (operations.length === 0) {
44
+ return { status: 'skipped', reason: 'no operations' };
45
+ }
46
+
47
+ try {
48
+ const serviceModule = require(`./services/${serviceName}/index.js`);
49
+
50
+ if (!serviceModule.run) {
51
+ console.log(` Service ${serviceName} has no run() export`);
52
+ return { status: 'skipped', reason: 'no run export' };
53
+ }
54
+
55
+ // No cross-run seed: a service reads what it needs from brandConfig (the
56
+ // one home for provisioned facts) or re-derives it from the platform, and
57
+ // a setup() may still seed serviceData for its own operations (#434)
58
+ return await serviceModule.run({
59
+ brandId: brand.id,
60
+ brandRoot: brand.root,
61
+ // Company workspace root when the brand carries a valid company marker
62
+ // — company-shared resources (Apple signing material) live there
63
+ companyRoot: brand.companyRoot || null,
64
+ // The company config layer (already merged into brandConfig) for
65
+ // provenance checks — null for standalone brands
66
+ companyConfig: brand.companyConfig || null,
67
+ brandConfig: brand.config,
68
+ brand,
69
+ targets: brand.targets,
70
+ operations,
71
+ options,
72
+ });
73
+ } catch (error) {
74
+ // A consent gate thrown at setup time is a pending HUMAN step, not a
75
+ // failure (#228) — warned keeps the walk going and lands the item in the
76
+ // summary's ⚑ list instead of stopping the cycle (and any dev boot on it)
77
+ if (error?.code === CONSENT_REQUIRED) {
78
+ console.log(` ${chalk.yellow('⚑')} ${serviceName}: ${error.message}`);
79
+ return {
80
+ status: 'warned',
81
+ warned: [{ operation: 'auth', reason: 'needs an interactive run' }],
82
+ output: { auth: { needsInteractive: error.message } },
83
+ };
84
+ }
85
+
86
+ console.error(` Error in ${serviceName}: ${error.message}`);
87
+ return { status: 'error', error: error.message };
88
+ }
89
+ }
90
+
91
+ /**
92
+ * Run all services (in order) against the brand monorepo containing startDir.
93
+ *
94
+ * @param {string} startDir - Any directory inside the brand monorepo
95
+ * @param {Object} options - { service?, lane? ('boot' = the local slice a dev
96
+ * boot needs; omitted = every service), continueOnError?, dryRun?, verbose?,
97
+ * strict? (preflight failures fail hard instead of skipping),
98
+ * migration? (true = all, string = one), execute? (the migrations write
99
+ * gate — without it the run only audits), limit?, ids? (migrations service),
100
+ * resetAssets? (true = both kinds, string = 'logos'/'templates'; assets
101
+ * service), force? (ignore the update service's incremental cache and
102
+ * rebuild every target) }
103
+ * @returns {{ hasErrors: boolean, results: Object, brand: Object }}
104
+ */
105
+ async function runManage(startDir, options = {}) {
106
+ const brandRoot = resolveBrandRoot(startDir);
107
+
108
+ if (!brandRoot) {
109
+ throw new Error(
110
+ `No brand monorepo found at or above ${startDir} — `
111
+ + `expected a config/omega.json5 at the brand root (see docs/shared/config.md).`,
112
+ );
113
+ }
114
+
115
+ // One vocabulary (#443): the apps/ → targets/ rename is a ONE-TIME
116
+ // migration, never healing inside a run. The brand it fixes cannot be
117
+ // walked — discovery fails loud on the old shape and every service below
118
+ // reads targets/ — so this ONE migration runs ALONE, ahead of the load that
119
+ // would throw on it, and stops there. It is registered like every other
120
+ // migration too (config.js OPERATIONS.migrations), so a bare `--migration`
121
+ // walk re-checks it on a converged brand.
122
+ if (options.migration === ensureTargetsRename.MIGRATION_NAME) {
123
+ console.log('');
124
+ console.log(chalk.bold.cyan(`🚀 Omega Manager ${chalk.dim(`— migration: ${ensureTargetsRename.MIGRATION_NAME}`)}`));
125
+ console.log(` ${chalk.dim('Root:')} ${brandRoot}`);
126
+
127
+ const result = await ensureTargetsRename({ brandRoot, options });
128
+
129
+ return { hasErrors: false, results: { migrations: result }, brand: null };
130
+ }
131
+
132
+ // Company layer: a company-managed brand carries a .omega/company.json
133
+ // stamp (written idempotently by company runs) pointing at its company
134
+ // root — its config becomes the layer between manager DEFAULTS and the
135
+ // brand file, and its .env fills the gaps under the brand .env.
136
+ const marker = readCompanyMarker(brandRoot);
137
+ let companyConfig = null;
138
+
139
+ if (marker?.stale) {
140
+ console.log(chalk.yellow(`⚠ .omega/company.json points at ${marker.companyRoot}, which is no longer a company workspace — running standalone (delete the file to silence this)`));
141
+ } else if (marker) {
142
+ companyConfig = loadCompanyConfig(marker.companyRoot);
143
+ }
144
+
145
+ // Secrets chain: shell env > brand .env > company .env — the shared
146
+ // cascade (files load strongest-first, never overriding what's set), each
147
+ // layer overlaid by its own `.env.<environment>` file
148
+ // ([#586](https://github.com/Omega-JS-Stack/omega/issues/586)). The manage
149
+ // walk judges every key on the RESOLVED cascade, so a value that lives only
150
+ // in an overlay must be visible here or the mint lane would re-mint it.
151
+ //
152
+ // `production` is PINNED, never the shell's answer: manage reconciles REAL
153
+ // infrastructure with production credentials, and the mint lane has to see
154
+ // the key it would otherwise re-mint.
155
+ loadEnvRoots([
156
+ brandRoot,
157
+ companyConfig ? marker.companyRoot : null,
158
+ ], { environment: 'production' });
159
+
160
+ // The company layer itself is folded by @omega.js/config off the same stamp
161
+ // (#83) — loadBrand takes no company argument; what we resolved here is
162
+ // provenance and the .env chain.
163
+ const brand = loadBrand(brandRoot);
164
+
165
+ // Company-shared resources (Apple signing material) live at the company
166
+ // workspace root — services resolve it via context.companyRoot
167
+ brand.companyRoot = companyConfig ? marker.companyRoot : null;
168
+
169
+ // The inheritable company layer itself rides along for provenance: its
170
+ // values are already merged into brand.config, but flows that want to say
171
+ // "this came from the company" (e.g. the GA account default) compare
172
+ // against it via context.companyConfig
173
+ brand.companyConfig = companyConfig;
174
+
175
+ console.log('');
176
+ console.log(chalk.bold.cyan('🚀 Omega Manager'));
177
+ console.log('');
178
+
179
+ // Skip disabled brands
180
+ if (brand.config.enabled === false) {
181
+ console.log(chalk.dim('━'.repeat(70)));
182
+ console.log(` ${chalk.bold(brand.config.brand?.name || brand.id)} ${chalk.yellow('DISABLED')}`);
183
+ console.log(chalk.dim('━'.repeat(70)));
184
+ return { hasErrors: false, results: {}, brand, skipped: true };
185
+ }
186
+
187
+ // Determine which services to run. --service is the most specific ask and
188
+ // wins outright; a lane narrows the walk to its slice (#228) — 'boot' is the
189
+ // local one `omega dev` runs before its legs, in SERVICE_ORDER order.
190
+ if (options.lane && options.lane !== 'boot') {
191
+ throw new Error(`Unknown lane: ${options.lane}. Available: boot`);
192
+ }
193
+
194
+ const servicesToRun = options.service
195
+ ? [options.service]
196
+ : (options.lane === 'boot'
197
+ ? SERVICE_ORDER.filter((serviceName) => BOOT_SERVICES.includes(serviceName))
198
+ : SERVICE_ORDER);
199
+
200
+ if (options.service && !SERVICE_ORDER.includes(options.service)) {
201
+ throw new Error(`Unknown service: ${options.service}. Available: ${SERVICE_ORDER.join(', ')}`);
202
+ }
203
+
204
+ console.log(chalk.cyan('━'.repeat(70)));
205
+ console.log(` ${chalk.bold.white(brand.config.brand?.name || brand.id)} ${chalk.cyan(brand.config.brand?.url || '')} ${chalk.dim(`@ ${new Date().toLocaleTimeString()}`)}`);
206
+ console.log(chalk.cyan('━'.repeat(70)));
207
+ console.log(` ${chalk.dim('Root:')} ${brand.root}`);
208
+ if (companyConfig) {
209
+ console.log(` ${chalk.dim('Company:')} ${marker.companyRoot}`);
210
+ }
211
+ console.log(` ${chalk.dim('Enabled:')} ${brand.enabledTargets.join(', ') || chalk.yellow('none enabled')}`);
212
+ console.log(` ${chalk.dim('Targets:')} ${brand.targets.map((entry) => `${entry.name}${entry.target ? chalk.dim(`→${entry.target}`) : chalk.yellow('→?')}`).join(', ') || chalk.yellow('none')}`);
213
+ console.log(` ${chalk.dim('Services:')} ${options.service || servicesToRun.join(chalk.dim(' → '))}`);
214
+
215
+ // Lockstep (#794): the @omega.js family ships ONE version, so a brand
216
+ // running a framework from one release beside a client from another is
217
+ // refused HERE — before any service reconciles anything on top of two
218
+ // copies of the runtime and two copies of the config validator. `file:`
219
+ // links (the local era) and targets with nothing installed are exempt.
220
+ assertFamilyVersions({ brandRoot, targets: brand.targets });
221
+
222
+ // Preflight (the REQUIRES registry): check the enabled services' declared
223
+ // env vars + Google scopes up front — ONE consolidated fix walkthrough
224
+ // instead of N mid-run skips. Failing services skip (the cycle continues —
225
+ // absorb, never crash) unless the run can collect the fix itself
226
+ // (interactive paste/consent flows) or --strict makes them fail hard.
227
+ // A lane narrows the WALK, never the preflight (#228): preflight is local
228
+ // (env presence + token-store read, zero network), and its walkthrough is
229
+ // how a boot names what the full setup still owes. Gates are only consulted
230
+ // for the services this run actually walks, so an unwalked finding records
231
+ // nothing and fails nothing.
232
+ const preflight = runPreflight({
233
+ services: options.service ? [options.service] : SERVICE_ORDER,
234
+ brandConfig: brand.config,
235
+ brandRoot,
236
+ options,
237
+ });
238
+
239
+ const summary = new RunSummary();
240
+ const results = {};
241
+
242
+ // Run each service in order
243
+ for (const serviceName of servicesToRun) {
244
+ console.log('');
245
+ console.log(` ${chalk.bold.magenta(`[${serviceName.toUpperCase()}]`)}`);
246
+
247
+ // Preflight verdicts: 'skip' steps the service aside with the printed
248
+ // walkthrough (missingEnv rides along for the 🔑 aggregate); 'error' is
249
+ // the --strict hard failure; 'run' (or no gate) proceeds normally
250
+ const gate = preflight.gates[serviceName];
251
+ let result;
252
+ if (gate?.action === 'error') {
253
+ console.log(` ${chalk.red(`✗ Preflight failed (${gate.reason})`)}`);
254
+ result = {
255
+ status: 'error',
256
+ error: gate.reason,
257
+ ...(gate.missingEnv.length > 0 ? { missingEnv: gate.missingEnv } : {}),
258
+ };
259
+ } else if (gate?.action === 'skip') {
260
+ console.log(` ${chalk.dim(`⊘ Skipped (${gate.reason})`)}`);
261
+ result = {
262
+ status: 'skipped',
263
+ reason: gate.reason,
264
+ ...(gate.missingEnv.length > 0 ? { missingEnv: gate.missingEnv } : {}),
265
+ // A consent/scope gap is a pending HUMAN step: it rides the ⚑
266
+ // aggregate with its rerun hint (#228), not just the walkthrough
267
+ // scroll-back a dev boot's leg output buries
268
+ ...(gate.needsInteractive ? { output: { preflight: { needsInteractive: gate.needsInteractive } } } : {}),
269
+ };
270
+ } else {
271
+ const startedAt = Date.now();
272
+ result = await runService(serviceName, brand, options);
273
+ // Wall time for the services that actually ran — the gated branches
274
+ // above step aside instantly, so timing them is noise
275
+ result.durationMs = Date.now() - startedAt;
276
+ // Printed only for the services that did work — a service that stepped
277
+ // aside already said so on its own line, and 20 `⏱ 0ms` lines under a
278
+ // mostly-skipping walk is noise (the run record keeps every number)
279
+ if (result.status !== 'skipped') {
280
+ console.log(` ${chalk.dim(`⏱ ${formatDuration(result.durationMs)}`)}`);
281
+ }
282
+ }
283
+ results[serviceName] = result;
284
+
285
+ summary.add(brand.id, brand.config.brand?.name || brand.id, serviceName, result);
286
+
287
+ if (result.status === 'error' && !options.continueOnError) {
288
+ console.log(` ${chalk.red(`Stopping due to error in ${serviceName}`)} ${chalk.dim('(--continue-on-error to keep going)')}`);
289
+ break;
290
+ }
291
+ }
292
+
293
+ // Persist run output — this run's transients, for post-mortem debugging
294
+ writeRunOutput(brandRoot, RUN_TIMESTAMP, brand.id, Object.entries(results).map(([service, result]) => ({
295
+ service,
296
+ status: result.status,
297
+ // Absent for services the preflight gated aside — they never ran
298
+ ...(result.durationMs !== undefined ? { durationMs: result.durationMs } : {}),
299
+ output: result.output ?? null,
300
+ error: result.error ?? null,
301
+ // Machine-readable WHY for skips — the pipeline command asserts on it
302
+ ...(result.reason ? { reason: result.reason } : {}),
303
+ ...(result.missingEnv ? { missingEnv: result.missingEnv } : {}),
304
+ })));
305
+
306
+ summary.printSummary();
307
+
308
+ return { hasErrors: summary.hasErrors(), results, brand };
309
+ }
310
+
311
+ module.exports = { runManage, runService, RUN_TIMESTAMP };
@@ -0,0 +1,7 @@
1
+ // Entry for the `omega`/`omg`/`mgr` bins — dispatches to the framework that owns
2
+ // the cwd's target; a brand root runs the manager's CLI, and so does a fresh clone
3
+ // with nothing installed yet (`npx omega onboard`, the bootstrap case).
4
+ require('./vendor/devkit/omega-bin.js').run({
5
+ hostName: '@omega.js/manager',
6
+ hostRun: () => require('./cli-run.js').run(),
7
+ });