@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,206 @@
1
+ /**
2
+ * Install + build every target-mapped dir.
3
+ *
4
+ * Install is ONE `npm install` at the brand root (npm workspaces cover every
5
+ * target), and it's dependency-resolution-gated for idempotency: if every
6
+ * target's
7
+ * declared deps already resolve through the node_modules climb, the install
8
+ * is skipped — so a second run is a no-op, and a brand nested inside a larger
9
+ * workspace (the monorepo's sandbox brand) never grows a stray node_modules.
10
+ *
11
+ * Build runs each target's own `npm run build`; targets without a build script are
12
+ * recorded as skipped, not failed (a backend's "build" is its deploy story).
13
+ * Those builds are the slow tail of every walk, so they are INCREMENTAL
14
+ * (#445): a target whose own files AND whose installed `@omega.js/*` frameworks
15
+ * are both unchanged since its last successful build is converged and skips
16
+ * with one line (lib/fingerprint.js), the fingerprint pair living in
17
+ * `.omega/cache/update.json` (lib/cache.js). Either set fresh → the full build
18
+ * for that target; `--force` ignores the cache, and so does a brand whose cache
19
+ * is missing or unreadable.
20
+ *
21
+ * Output shape matches omega-manager's update service so RunSummary's
22
+ * drill-down works unchanged: { results: { [target]: { steps: [{ phase,
23
+ * success, error?, skipped? }] } } }.
24
+ */
25
+ const path = require('node:path');
26
+ const chalk = require('chalk').default;
27
+ const jetpack = require('fs-jetpack');
28
+
29
+ const { envLayerFiles, ENV_ENVIRONMENTS } = require('../../../vendor/config/index.js');
30
+
31
+ const { runCommand } = require('../../../lib/run-command.js');
32
+ const { readCompanyMarker } = require('../../../lib/company.js');
33
+ const { fingerprintTarget, resolvePackageDir } = require('../lib/fingerprint.js');
34
+ const { readCache, writeCache, CACHE_VERSION } = require('../lib/cache.js');
35
+
36
+ /**
37
+ * One env LAYER's files: the base `.env` plus its `.env.<environment>` overlays.
38
+ *
39
+ * The overlay spelling is @omega.js/config's (`envLayerFiles`, #586), never a
40
+ * join written out here, and EVERY environment is fingerprinted because a build
41
+ * can run under any of them and an absent file digests as `absent` either way.
42
+ * Fingerprinting the base file by exact path was the gap ([#681](https://github.com/Omega-JS-Stack/omega/issues/681)):
43
+ * an overlay is a real layer of the cascade and carries the values that DIFFER
44
+ * per environment, so an overlay edit left the target converged and its build
45
+ * served the old value.
46
+ *
47
+ * @param {string} label - The layer's fingerprint label ('brand-env').
48
+ * @param {string} root - The dir whose `.env` is this layer.
49
+ * @returns {Array<{ label: string, file: string }>} One entry per layer file.
50
+ */
51
+ function envLayerEntries(label, root) {
52
+ const base = path.join(root, '.env');
53
+ const files = [...new Set(ENV_ENVIRONMENTS.flatMap((environment) => envLayerFiles(base, environment)))];
54
+
55
+ return files.map((file) => ({
56
+ label: file === base ? label : `${label}.${file.slice(base.length + 1)}`,
57
+ file,
58
+ }));
59
+ }
60
+
61
+ /**
62
+ * The merge-chain files OUTSIDE the target tree that its build still reads:
63
+ * brand config/.env, and the company pair when the brand carries a marker.
64
+ * A brand-config edit must dirty every target's fingerprint, or the
65
+ * converged skip serves stale output.
66
+ */
67
+ function chainFiles(brandRoot) {
68
+ const files = [
69
+ { label: 'brand-config', file: path.join(brandRoot, 'config', 'omega.json5') },
70
+ ...envLayerEntries('brand-env', brandRoot),
71
+ ];
72
+
73
+ const marker = readCompanyMarker(brandRoot);
74
+ if (marker) {
75
+ files.push(
76
+ { label: 'company-config', file: path.join(marker.companyRoot, 'config', 'omega.json5') },
77
+ ...envLayerEntries('company-env', marker.companyRoot),
78
+ );
79
+ }
80
+
81
+ return files;
82
+ }
83
+
84
+ /**
85
+ * Collect declared deps (dependencies + devDependencies) missing from an
86
+ * target's resolution climb.
87
+ */
88
+ function missingDeps(targetPath) {
89
+ const pkg = jetpack.read(path.join(targetPath, 'package.json'), 'json');
90
+ if (!pkg) return [];
91
+
92
+ const declared = Object.keys({ ...pkg.dependencies, ...pkg.devDependencies });
93
+ return declared.filter((name) => !resolvePackageDir(targetPath, name));
94
+ }
95
+
96
+ module.exports = async ({ brandRoot, targets, options }) => {
97
+ const mappedTargets = targets.filter((entry) => entry.target);
98
+ const results = {};
99
+ let failed = false;
100
+
101
+ // ─── Install phase (once, at the brand root) ──────────────────────────────
102
+ const missing = mappedTargets.flatMap((entry) => missingDeps(entry.path).map((dep) => `${entry.name}:${dep}`));
103
+ const installSteps = [];
104
+
105
+ if (missing.length === 0) {
106
+ console.log(` ${chalk.dim('⊘ install: all dependencies resolve')}`);
107
+ installSteps.push({ phase: 'install', success: true, skipped: true });
108
+ } else if (options.dryRun) {
109
+ console.log(` ${chalk.yellow('⊘')} install: would run npm install ${chalk.dim(`(missing: ${missing.join(', ')})`)} ${chalk.dim('[DRY RUN]')}`);
110
+ installSteps.push({ phase: 'install', success: true, skipped: true, dryRun: true });
111
+ } else {
112
+ console.log(` ${chalk.dim('→')} npm install ${chalk.dim(`(missing: ${missing.join(', ')})`)}`);
113
+ const result = await runCommand('npm', ['install', '--no-audit', '--no-fund'], brandRoot);
114
+ installSteps.push({ phase: 'install', ...result });
115
+ if (!result.success) {
116
+ failed = true;
117
+ // Local-first era: the frameworks aren't on the registry yet
118
+ if (missing.some((entry) => entry.includes('@omega.js/'))) {
119
+ console.log(` ${chalk.yellow('⚠')} @omega.js/* packages are not published yet — link them per target with ${chalk.bold('mgr i local')} (or a workspace/file: reference).`);
120
+ }
121
+ }
122
+ }
123
+
124
+ results.root = { steps: installSteps };
125
+
126
+ // ─── Build phase (per target, incremental) ────────────────────────────────
127
+ const cache = readCache(brandRoot);
128
+ const chain = chainFiles(brandRoot);
129
+ const nextTargets = {};
130
+
131
+ for (const entry of mappedTargets) {
132
+ const steps = [];
133
+ const cached = cache.targets[entry.name];
134
+
135
+ if (failed) {
136
+ // Nothing was rebuilt, so last run's verdict for this target still stands
137
+ if (cached) nextTargets[entry.name] = cached;
138
+ steps.push({ phase: 'build', success: true, skipped: true, reason: 'install failed' });
139
+ results[entry.name] = { steps };
140
+ continue;
141
+ }
142
+
143
+ const pkg = jetpack.read(path.join(entry.path, 'package.json'), 'json');
144
+ // Only worth sweeping when there's a cached verdict to compare against
145
+ // and the run is allowed to honour it
146
+ const fingerprint = cached && pkg?.scripts?.build && !options.force
147
+ ? fingerprintTarget(entry.path, chain)
148
+ : null;
149
+ const converged = Boolean(fingerprint)
150
+ && cached.files === fingerprint.files
151
+ && cached.frameworks === fingerprint.frameworks;
152
+
153
+ if (!pkg?.scripts?.build) {
154
+ console.log(` ${chalk.dim(`⊘ ${entry.name}: no build script`)}`);
155
+ steps.push({ phase: 'build', success: true, skipped: true, reason: 'no build script' });
156
+ } else if (converged) {
157
+ console.log(` ${chalk.dim(`⊘ ${entry.name}: converged (target files + @omega.js/* unchanged)`)}`);
158
+ nextTargets[entry.name] = cached;
159
+ steps.push({ phase: 'build', success: true, skipped: true, reason: 'converged' });
160
+ } else if (options.dryRun) {
161
+ console.log(` ${chalk.yellow('⊘')} ${entry.name}: would run npm run build ${chalk.dim('[DRY RUN]')}`);
162
+ steps.push({ phase: 'build', success: true, skipped: true, dryRun: true });
163
+ } else {
164
+ // Non-interactive runs (pipeline, CI, and `omega dev`'s boot manage
165
+ // cycle — #228) must be deterministic: web builds use the committed
166
+ // translation cache only — never a live LLM pass mid-run (the same law
167
+ // deploys follow). New strings translate on the next interactive run.
168
+ const buildArgs = ['run', 'build'];
169
+ if (entry.target === 'web' && process.env.OMEGA_NON_INTERACTIVE === '1') {
170
+ buildArgs.push('--', '--cached-only');
171
+ }
172
+ console.log(` ${chalk.dim('→')} ${entry.name}: npm ${buildArgs.join(' ')}`);
173
+ const result = await runCommand('npm', buildArgs, entry.path);
174
+ steps.push({ phase: 'build', ...result });
175
+
176
+ if (result.success) {
177
+ // Re-fingerprint AFTER the build: a build that writes back into its
178
+ // own sources (the web translation cache) would otherwise leave the
179
+ // target looking fresh forever. A failed build records nothing, so the
180
+ // next run retries it.
181
+ nextTargets[entry.name] = { ...fingerprintTarget(entry.path, chain), updatedAt: new Date().toISOString() };
182
+ } else {
183
+ failed = true;
184
+ }
185
+ }
186
+
187
+ results[entry.name] = { steps };
188
+ }
189
+
190
+ // One write, only when something moved (a build landed, a target left the
191
+ // brand, or the file was missing/unreadable and this rebuilds it). Keys are
192
+ // sorted so a converged rerun produces the byte-identical file it read.
193
+ const nextCache = {
194
+ version: CACHE_VERSION,
195
+ targets: Object.fromEntries(Object.keys(nextTargets).sort().map((name) => [name, nextTargets[name]])),
196
+ };
197
+
198
+ if (!options.dryRun && JSON.stringify(nextCache) !== JSON.stringify(cache)) {
199
+ writeCache(brandRoot, nextCache);
200
+ }
201
+
202
+ return {
203
+ status: failed ? 'error' : 'success',
204
+ output: { results },
205
+ };
206
+ };
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Ensure the brand agent-docs chain (Ian 2026-07-20): root AGENTS.md opens
3
+ * with the framework-guide import, root CLAUDE.md is the one-line
4
+ * `@AGENTS.md` pointer. Consumer content is preserved; a content-bearing
5
+ * CLAUDE.md warns with the move-it message instead of being clobbered.
6
+ */
7
+ const chalk = require('chalk').default;
8
+
9
+ const { ensureAgentsMd, ensureClaudePointer, ensureGuideLink, IMPORT_LINE, CLAUDE_POINTER } = require('../../../lib/agents-md.js');
10
+
11
+ module.exports = async ({ brandRoot, brand }) => {
12
+ const brandName = brand.config?.brand?.name || brand.id;
13
+
14
+ const guide = ensureGuideLink(brandRoot);
15
+ const guideLabel = {
16
+ present: 'node_modules/@omega.js/AGENTS.md links the framework map',
17
+ created: 'Linked node_modules/@omega.js/AGENTS.md at the framework map',
18
+ healed: 'Relinked node_modules/@omega.js/AGENTS.md at the framework map',
19
+ skipped: 'No resolvable framework map yet (pre-install) — link skipped',
20
+ }[guide];
21
+ console.log(` ${chalk.green('✓')} ${guideLabel}`);
22
+
23
+ const agents = ensureAgentsMd(brandRoot, brandName);
24
+ const agentsLabel = {
25
+ present: `AGENTS.md imports the framework guide (${IMPORT_LINE})`,
26
+ created: 'Created AGENTS.md with the framework-guide import',
27
+ healed: 'Healed AGENTS.md — framework-guide import moved to line 1 (your content preserved)',
28
+ }[agents];
29
+ console.log(` ${chalk.green('✓')} ${agentsLabel}`);
30
+
31
+ const claude = ensureClaudePointer(brandRoot);
32
+ if (claude === 'content-bearing') {
33
+ console.log(` ${chalk.yellow('⚠')} CLAUDE.md carries content — move it into AGENTS.md (below the import) and reduce CLAUDE.md to the one-line \`${CLAUDE_POINTER}\` pointer`);
34
+ return { status: 'warned', reason: 'CLAUDE.md carries content — move it into AGENTS.md', output: { guide, agents, claude } };
35
+ }
36
+ console.log(` ${chalk.green('✓')} CLAUDE.md ${claude === 'created' ? 'created as' : 'is'} the \`${CLAUDE_POINTER}\` pointer`);
37
+
38
+ if (agents === 'present' && claude === 'present' && (guide === 'present' || guide === 'skipped')) {
39
+ return null;
40
+ }
41
+ return { output: { guide, agents, claude } };
42
+ };
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Ensure the brand's committed `.claude/settings.json` registers the omega
3
+ * marketplace from the installed manager package and enables the plugin
4
+ * ([#62](https://github.com/Omega-JS-Stack/omega/issues/62)) — the consumer
5
+ * half of the plugin install. Only a PUBLISHED install carries the vendored
6
+ * marketplace; the local era skips (the developer's user-scope install serves
7
+ * those sessions). Consumer settings are never clobbered.
8
+ */
9
+ const chalk = require('chalk').default;
10
+
11
+ const { ensureClaudeSettings, SETTINGS_FILE, PLUGIN_ID } = require('../../../lib/claude-settings.js');
12
+
13
+ module.exports = async ({ brandRoot }) => {
14
+ const result = ensureClaudeSettings(brandRoot);
15
+
16
+ if (result === 'skipped') {
17
+ console.log(` ${chalk.green('✓')} No vendored omega plugin in node_modules/@omega.js/manager (local era) — ${SETTINGS_FILE} left alone`);
18
+ return null;
19
+ }
20
+
21
+ if (result === 'invalid') {
22
+ console.log(` ${chalk.yellow('⚠')} ${SETTINGS_FILE} is not valid JSON — fix it so the omega plugin (${PLUGIN_ID}) can be registered`);
23
+ return { status: 'warned', reason: `${SETTINGS_FILE} is not valid JSON`, output: { claudeSettings: result } };
24
+ }
25
+
26
+ const label = {
27
+ present: `${SETTINGS_FILE} enables the omega plugin (${PLUGIN_ID})`,
28
+ created: `Created ${SETTINGS_FILE} — the omega plugin loads in every session here`,
29
+ healed: `Healed ${SETTINGS_FILE} — omega plugin registered (your other settings preserved)`,
30
+ }[result];
31
+ console.log(` ${chalk.green('✓')} ${label}`);
32
+
33
+ return result === 'present' ? null : { output: { claudeSettings: result } };
34
+ };
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Ensure omega.json5 health. The brand file is the manager's input — a brand
3
+ * config that fails to load (parse error, secret-shaped keys, legacy targets
4
+ * array) or fails schema validation is an ERROR: there is nothing sound to
5
+ * reconcile services against. Target-level findings are warnings — each
6
+ * framework's own setup/audit is the hard gate for its surface.
7
+ */
8
+ const chalk = require('chalk').default;
9
+
10
+ const { loadConfig, hasOmegaConfig } = require('../../../vendor/config/index.js');
11
+
12
+ module.exports = async ({ brand, targets }) => {
13
+ // Brand config failed to LOAD (thrown by @omega.js/config — secrets, parse, targets array)
14
+ if (brand.configError) {
15
+ console.log(` ${chalk.red('✗')} ${brand.configError}`);
16
+ return { status: 'error', error: brand.configError };
17
+ }
18
+
19
+ // Brand config loaded but has schema findings
20
+ if (brand.configErrors.length > 0) {
21
+ for (const error of brand.configErrors) {
22
+ console.log(` ${chalk.red('✗')} brand: ${error}`);
23
+ }
24
+ return { status: 'error', error: `brand config invalid: ${brand.configErrors.join('; ')}` };
25
+ }
26
+
27
+ console.log(` ${chalk.green('✓')} brand config valid ${chalk.dim(`(${brand.files?.app || 'config/omega.json5'})`)}`);
28
+
29
+ // Per-target validation for dirs that carry their own config and map to a target
30
+ const findings = [];
31
+ for (const entry of targets) {
32
+ if (!entry.target || !hasOmegaConfig(entry.path)) continue;
33
+
34
+ try {
35
+ const { errors } = loadConfig(entry.path, entry.target);
36
+ for (const error of errors) {
37
+ findings.push(`${entry.name}: ${error}`);
38
+ }
39
+ } catch (error) {
40
+ // A target config that cannot load at all (secrets, parse) is still a hard stop
41
+ console.log(` ${chalk.red('✗')} ${entry.name}: ${error.message}`);
42
+ return { status: 'error', error: `${entry.name}: ${error.message}` };
43
+ }
44
+ }
45
+
46
+ if (findings.length > 0) {
47
+ for (const finding of findings) {
48
+ console.log(` ${chalk.yellow('⚠')} ${finding}`);
49
+ }
50
+ return { status: 'warned', reason: findings.join('; '), output: { findings } };
51
+ }
52
+
53
+ return null;
54
+ };
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Self-healing config ([#478](https://github.com/Omega-JS-Stack/omega/issues/478)):
3
+ * every manage run materializes the schema-defaulted blocks the brand's
4
+ * omega.json5 does not carry yet, so a subsystem that exists has its config
5
+ * structure visible and editable in the file — never an invisible framework
6
+ * fallback. A newly added default therefore appears in every consumer's config
7
+ * on the next run.
8
+ *
9
+ * What it never does: overwrite. `missingDefaults()` names only the keys the
10
+ * brand has not authored, the comment-preserving editor inserts them (each
11
+ * block documented with the schema's own description), and a converged config
12
+ * leaves the file byte-identical. Keys with no sane framework answer — owner
13
+ * decisions, provisioned ids, anything secret-shaped — carry no schema default
14
+ * and are never written here.
15
+ */
16
+ const { join } = require('node:path');
17
+ const jetpack = require('fs-jetpack');
18
+ const chalk = require('chalk').default;
19
+ const JSON5 = require('json5');
20
+
21
+ const { missingDefaults, defaultComments, writeConfigValues, resolveConfigPath, FILE_NAME } = require('../../../vendor/config/index.js');
22
+ const { dryRunPlan } = require('../../../lib/run-gates.js');
23
+
24
+ module.exports = async ({ brandRoot, options = {} }) => {
25
+ const configPath = resolveConfigPath(brandRoot);
26
+ if (!configPath) {
27
+ console.log(` ${chalk.dim(`⊘ no ${join('config', FILE_NAME)} yet (the config operation reports it)`)}`);
28
+ return null;
29
+ }
30
+
31
+ // The RAW file, not the resolved config: resolution already merged the
32
+ // defaults in, so every block would read as present.
33
+ const missing = missingDefaults(JSON5.parse(jetpack.read(configPath)));
34
+
35
+ if (missing.length === 0) {
36
+ console.log(` ${chalk.green('✓')} ${FILE_NAME} carries every schema default`);
37
+ return null;
38
+ }
39
+
40
+ const blocks = missing.map((entry) => entry.path);
41
+
42
+ if (options.dryRun) {
43
+ return dryRunPlan(
44
+ `materialize ${blocks.join(', ')} in ${FILE_NAME}`,
45
+ { output: { defaults: { planned: blocks } } },
46
+ );
47
+ }
48
+
49
+ writeConfigValues(
50
+ brandRoot,
51
+ Object.fromEntries(missing.map((entry) => [entry.path, entry.value])),
52
+ { comments: defaultComments() },
53
+ );
54
+
55
+ for (const block of blocks) {
56
+ console.log(` ${chalk.green('+')} ${FILE_NAME} ← ${chalk.cyan(block)} ${chalk.dim('(schema default)')}`);
57
+ }
58
+
59
+ return { output: { defaults: { materialized: blocks } } };
60
+ };
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Ensure the brand .env carries every key OMEGA generates for itself — the
3
+ * env schema's `generated` entries (@omega.js/config, #581) — the manage-time
4
+ * half of the mint the onboard scaffold does for a fresh brand (#569). A brand
5
+ * onboarded before a key existed gains it here instead of discovering the hole
6
+ * at the first send.
7
+ *
8
+ * Presence is judged on the RESOLVED value (`process.env`, which manage
9
+ * already layered shell > brand .env > company .env), so a company-managed
10
+ * brand never shadows its company's value with a fresh one. A minted value
11
+ * is published into `process.env` too, so the same run's builds compose it
12
+ * into their targets — the key is live one manage after the gap, not two.
13
+ * Values are never printed: the run says WHICH key it minted, never what.
14
+ *
15
+ * The mint itself is lib/env-secret.js's `mintGeneratedKey` — shared with the
16
+ * setup contract, which mints a single key for a service that reached it
17
+ * before this op ran (#635).
18
+ */
19
+ const chalk = require('chalk').default;
20
+
21
+ const { generatedEnvKeys } = require('../../../vendor/config/index.js');
22
+ const { mintGeneratedKey } = require('../../../lib/env-secret.js');
23
+ const { dryRunPlan } = require('../../../lib/run-gates.js');
24
+
25
+ module.exports = async (context) => {
26
+ const { brandRoot, options = {} } = context;
27
+
28
+ const minted = [];
29
+ const planned = [];
30
+ const present = [];
31
+
32
+ for (const name of Object.keys(generatedEnvKeys())) {
33
+ if (process.env[name]) {
34
+ present.push(name);
35
+ continue;
36
+ }
37
+
38
+ if (options.dryRun) {
39
+ dryRunPlan(`mint ${name} into the brand .env`);
40
+ planned.push(name);
41
+ continue;
42
+ }
43
+
44
+ // The mint — and its success line — live once, in lib/env-secret.js, so
45
+ // this op and the setup contract report an identical key identically
46
+ mintGeneratedKey(brandRoot, name);
47
+ minted.push(name);
48
+ }
49
+
50
+ if (present.length > 0) {
51
+ console.log(` ${chalk.green('✓')} generated keys (${present.length} present)`);
52
+ }
53
+
54
+ return { output: { envKeys: { minted, planned, present } } };
55
+ };
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Ensure the brand .env (and the company .env when the brand is
3
+ * company-managed) is in the canonical order — groups, comments, and
4
+ * placeholders from the env-order SSOT, hand comments travelling with
5
+ * their keys, duplicates collapsed to the dotenv winner. A converged file
6
+ * rewrites nothing; a file the reorderer can't parse (multi-line values,
7
+ * export forms) is left untouched with a note, never a failure.
8
+ */
9
+ const { join } = require('node:path');
10
+ const jetpack = require('fs-jetpack');
11
+ const chalk = require('chalk').default;
12
+
13
+ const { applyEnvOrder } = require('../../../lib/env-order.js');
14
+ const { dryRunPlan } = require('../../../lib/run-gates.js');
15
+
16
+ module.exports = async (context) => {
17
+ const { brandRoot, companyRoot, brandConfig, options = {} } = context;
18
+
19
+ const roots = [
20
+ { label: 'brand', root: brandRoot, isBrand: true },
21
+ ...(companyRoot ? [{ label: 'company', root: companyRoot, isBrand: false }] : []),
22
+ ];
23
+
24
+ const summary = {};
25
+ for (const { label, root, isBrand } of roots) {
26
+ const envPath = join(root, '.env');
27
+ if (!jetpack.exists(envPath)) {
28
+ console.log(` ${chalk.dim(`⊘ no ${label} .env yet`)}`);
29
+ summary[label] = 'missing';
30
+ continue;
31
+ }
32
+
33
+ const result = applyEnvOrder(jetpack.read(envPath), {
34
+ // Only the brand file gets a default header minted (we know its name);
35
+ // an existing header always wins
36
+ defaultHeader: isBrand
37
+ ? [`# ${brandConfig.brand.name} — brand secrets (gitignored; loaded before every omega run).`]
38
+ : [],
39
+ });
40
+
41
+ if (result.skipped) {
42
+ console.log(` ${chalk.dim(`⊘ ${label} .env left as-is (${result.skipped})`)}`);
43
+ summary[label] = 'skipped';
44
+ continue;
45
+ }
46
+ if (!result.changed) {
47
+ console.log(` ${chalk.green('✓')} ${label} .env order (current)`);
48
+ summary[label] = 'current';
49
+ continue;
50
+ }
51
+ if (options.dryRun) {
52
+ dryRunPlan(`reorder the ${label} .env into canonical groups`);
53
+ summary[label] = 'planned';
54
+ continue;
55
+ }
56
+
57
+ jetpack.write(envPath, result.content);
58
+ const dupNote = result.duplicatesCollapsed > 0
59
+ ? chalk.dim(` (${result.duplicatesCollapsed} duplicate line${result.duplicatesCollapsed === 1 ? '' : 's'} collapsed, last value kept)`)
60
+ : '';
61
+ console.log(` ${chalk.green('✓')} ${label} .env reordered${dupNote}`);
62
+ summary[label] = 'reordered';
63
+ }
64
+
65
+ return { output: { envOrder: summary } };
66
+ };
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Say, at MANAGE time, which env keys the brand's OWN config made mandatory
3
+ * and nobody has filled in — the env schema's `requiredWhen` rules
4
+ * ([#626](https://github.com/Omega-JS-Stack/omega/issues/626)).
5
+ *
6
+ * Every one of those rules used to be discovered LATE and per target: the
7
+ * extension's build threw on a GA4 stream with no Measurement Protocol secret,
8
+ * the backend 403'd every protected POST when a reCAPTCHA site key had no
9
+ * secret half, the captcha service paired the halves with its own if. The
10
+ * schema declares each rule once, checkEnvRules (@omega.js/config) evaluates
11
+ * it, and this op is the earliest place a human hears about it.
12
+ *
13
+ * Evaluated PER ENABLED TARGET, against that target's RESOLVED config
14
+ * ([#627](https://github.com/Omega-JS-Stack/omega/issues/627) review): the
15
+ * values these rules read live where the services write them, and that is the
16
+ * target section — the analytics service provisions one GA4 stream per surface
17
+ * (targets.<t>.analytics.providers.google.id) and leaves the shared slot null.
18
+ * A brand-ROOT evaluation therefore saw NOTHING for the canonical brand shape,
19
+ * and over-fired for the shared-id one (every per-target secret at once,
20
+ * including targets the brand does not even enable). The resolution is
21
+ * @omega.js/config's own (loadConfig with a target overlays targets.<type>);
22
+ * entries no enabled target claims are never evaluated.
23
+ *
24
+ * The few entries no target reads at all (SENTRY_AUTH_TOKEN — the monitoring
25
+ * SERVICE's) are judged against the brand config AND every enabled target's
26
+ * resolved one ([#683](https://github.com/Omega-JS-Stack/omega/issues/683)):
27
+ * the same disease one level over. A target-less key belongs to a SERVICE, but
28
+ * the config path that requires it is written wherever that service writes its
29
+ * values — the monitoring service provisions one Sentry project per surface
30
+ * and lands the DSN in targets.<t>.monitoring.providers.sentry.dsn with the
31
+ * shared slot null. Truthy in ANY enabled target (or at the root) owes the key
32
+ * once; the per-key dedupe below is what makes the union one violation.
33
+ *
34
+ * It WARNS and never fails. A half-configured brand is a normal step on the way
35
+ * to a configured one (the key is a dashboard visit away), and a manage run
36
+ * that refuses to reconcile over it would be a hostage note. The lanes that
37
+ * CANNOT proceed — a production backend boot — refuse on their own.
38
+ *
39
+ * Presence is judged on the RESOLVED cascade (`process.env`, which manage
40
+ * layered shell > brand .env > company .env before any service ran), so a
41
+ * company-supplied value counts. Violations name the BRAND-LEVEL key
42
+ * (GOOGLE_ANALYTICS_SECRET_WEB, not the GOOGLE_ANALYTICS_SECRET it is
43
+ * delivered to a target as): that is the name a human puts in the .env.
44
+ */
45
+ const chalk = require('chalk').default;
46
+
47
+ const { ENV_SCHEMA, loadConfig, getEnabledTargets, TARGETS } = require('../../../vendor/config/index.js');
48
+ const { checkEnvRules } = require('../../../vendor/config/env-rules.js');
49
+ const { DEFAULTS } = require('../../../config.js');
50
+
51
+ // The entries no target reads (`targets: []`) — a service's own key, which no
52
+ // target-resolved view could ever raise. The checker's `schema` seam scopes a
53
+ // pass to them without this op ever reading a rule itself.
54
+ const TARGETLESS_SCHEMA = ENV_SCHEMA.filter((entry) => entry.targets && entry.targets.length === 0);
55
+
56
+ module.exports = async (context) => {
57
+ const { brandRoot, brandConfig } = context;
58
+
59
+ // Key presence in `targets` IS the enablement signal; a custom target (#603)
60
+ // is a brand's own dir, not a framework the schema delivers keys to.
61
+ const enabled = getEnabledTargets(brandConfig).filter((target) => TARGETS.includes(target));
62
+
63
+ const violations = [];
64
+ const seen = new Set();
65
+ const collect = (found) => {
66
+ for (const violation of found) {
67
+ if (violation.rule !== 'requiredWhen' || seen.has(violation.key)) continue;
68
+ seen.add(violation.key);
69
+ violations.push(violation);
70
+ }
71
+ };
72
+
73
+ collect(checkEnvRules(brandConfig, process.env, { schema: TARGETLESS_SCHEMA }));
74
+
75
+ for (const target of enabled) {
76
+ // The per-target view is @omega.js/config's resolution, not a merge of our
77
+ // own: same chain as every framework's own load (company ← brand shared ←
78
+ // brand targets.<type>), so this op and the target's build read one config.
79
+ const { config } = loadConfig(brandRoot, target, { defaults: DEFAULTS });
80
+ collect(checkEnvRules(config, process.env, { target }));
81
+ // …and the service's own keys against that same view (#683): a target-less
82
+ // entry names no target, so nothing here scopes it — this asks whether the
83
+ // path that requires it is truthy on THIS surface.
84
+ collect(checkEnvRules(config, process.env, { schema: TARGETLESS_SCHEMA }));
85
+ }
86
+
87
+ if (violations.length === 0) {
88
+ console.log(` ${chalk.green('✓')} config-required env keys (all present)`);
89
+ return { output: { envRules: { violations } } };
90
+ }
91
+
92
+ for (const { key, path } of violations) {
93
+ console.log(` ${chalk.yellow('⚠')} ${chalk.cyan(key)} is missing from the .env cascade — ${chalk.cyan(path)} in omega.json5 requires it`);
94
+ }
95
+
96
+ return { output: { envRules: { violations } } };
97
+ };
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Ensure .omega/ and logs/ are gitignored at the brand root — the secrets
3
+ * store and run output never get committed. Idempotent: checks for existing entries
4
+ * before appending. The shared ensure also covers company roots (runCompany).
5
+ */
6
+ const chalk = require('chalk').default;
7
+
8
+ const { ensureOmegaIgnored } = require('../../../lib/gitignore.js');
9
+
10
+ module.exports = async ({ brandRoot }) => {
11
+ if (ensureOmegaIgnored(brandRoot) === 'present') {
12
+ console.log(` ${chalk.green('✓')} .gitignore has the omega entries`);
13
+ return null;
14
+ }
15
+
16
+ console.log(` ${chalk.green('✓')} Added missing omega entries to .gitignore`);
17
+ return { output: { gitignore: 'added' } };
18
+ };