@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,427 @@
1
+ /**
2
+ * Brand-monorepo scaffolding — the file plan the onboard wizard writes.
3
+ *
4
+ * buildScaffoldPlan() turns the wizard's answers into the plan-§0 skeleton:
5
+ * config/omega.json5, root package.json (targets/* workspaces), .gitignore, the
6
+ * .env credential stub, README.md, and a minimal package.json per enabled
7
+ * target's own dir. applyScaffoldPlan() writes it with fill-missing
8
+ * semantics: existing files are NEVER touched, so onboarding is idempotent
9
+ * and re-running it into a partial brand only fills the gaps.
10
+ *
11
+ * Target package.jsons carry their framework dep, so install → setup works
12
+ * without hand-editing; each framework's own setup still owns the consumer
13
+ * INTERIOR (scripts, config, scaffolded files). The backend's framework is a
14
+ * RUNTIME dependency (it rides the staged dist/package.json — src/dist
15
+ * pillar); every other target declares its framework as a devDependency
16
+ * (build-time only).
17
+ *
18
+ * Every `@omega.js/*` spec is an EXACT PIN at the manager's own version
19
+ * (#794): the family ships lockstep, one number for the whole set, so a
20
+ * brand can never install a backend from one release beside a client from
21
+ * another. A caret (or the old `*`) let one target float ahead alone on an
22
+ * `npm update`; pinned, only `omega update --apply` at the brand root moves it,
23
+ * and it moves every target together. The local era is untouched — an
24
+ * existing `file:` spec is never rewritten, because applyScaffoldPlan()
25
+ * leaves every file that already exists exactly as it is.
26
+ */
27
+
28
+ const path = require('node:path');
29
+ const jetpack = require('fs-jetpack');
30
+ const chalk = require('chalk').default;
31
+
32
+ const { TARGET_DIRS, TARGET_FRAMEWORKS } = require('../config.js');
33
+ // The environment vocabulary is @omega.js/config's — the same three names the
34
+ // overlay files are suffixed with and every runtime's environment() answers
35
+ const { ENV_ENVIRONMENTS } = require('../vendor/config/index.js');
36
+ // The canonical group list + renderer live in env-order.js (the ordering
37
+ // SSOT, cp137) — the stub is just a canonical render with generated Omega
38
+ // keys, so a scaffolded .env and a reordered one have the same shape.
39
+ const { renderCanonicalEnv, envLine } = require('./env-order.js');
40
+ // What gets generated (the env schema's `generated` entries) — with
41
+ // env-order.js's serializer above, the same two SSOTs writeEnvValue rides.
42
+ const { generatedEnvKeys } = require('../vendor/config/index.js');
43
+ // The heal's value is the SSOT for the manage script — a scaffolded brand
44
+ // must never be born needing the migration the heal just learned (#229)
45
+ const { MANAGE_SCRIPT } = require('./package-scripts.js');
46
+
47
+ // The backend framework is a Cloud Functions RUNTIME dependency — the stage
48
+ // step derives dist/package.json from the target manifest's `dependencies`
49
+ // (src/dist pillar). Every other target's framework is build-time only.
50
+ const RUNTIME_DEP_TARGETS = ['backend'];
51
+
52
+ // The pin every scaffolded @omega.js/* spec carries — the manager's OWN
53
+ // version, read at run time (#794). The family releases lockstep, so the
54
+ // manager's number IS the family's number; nothing here keeps a copy of it.
55
+ const FAMILY_VERSION = require('../../package.json').version;
56
+
57
+ /**
58
+ * Render the brand-level config/omega.json5 (fresh brands only — an existing
59
+ * config is never regenerated). String values go through JSON.stringify, so
60
+ * user input can't break the file.
61
+ */
62
+ function renderOmegaConfig(answers) {
63
+ const lines = [
64
+ `// ${answers.name} — brand-level omega.json5: the shared config layer every target`,
65
+ '// under targets/ inherits. Local files override any key per-surface; key presence',
66
+ '// under `targets` = this brand supports that target. Secrets NEVER live here —',
67
+ '// they go in the gitignored .env (the loader hard-fails on secret-shaped keys).',
68
+ '{',
69
+ ' brand: {',
70
+ ` id: ${JSON.stringify(answers.id)},`,
71
+ ` name: ${JSON.stringify(answers.name)},`,
72
+ ];
73
+
74
+ if (answers.description) {
75
+ lines.push(` description: ${JSON.stringify(answers.description)},`);
76
+ }
77
+ if (answers.tagline) {
78
+ lines.push(` tagline: ${JSON.stringify(answers.tagline)},`);
79
+ }
80
+
81
+ lines.push(
82
+ ` url: ${JSON.stringify(answers.url)},`,
83
+ ' contact: {',
84
+ ` email: ${JSON.stringify(answers.email)},`,
85
+ );
86
+
87
+ // The human who signs the personal sends (welcome, nudge, checkup) — asked
88
+ // for at onboarding, never derived, so an unanswered person writes no key
89
+ // at all instead of a placeholder identity (#770).
90
+ if (answers.person) {
91
+ lines.push(' person: {');
92
+ for (const [key, value] of Object.entries(answers.person)) {
93
+ lines.push(` ${key}: ${JSON.stringify(value)},`);
94
+ }
95
+ lines.push(' },');
96
+ }
97
+
98
+ lines.push(
99
+ ' },',
100
+ ' },',
101
+ '',
102
+ ' // Social handles (platform: "handle") — each entry lights its footer icon, its JSON-LD sameAs entry, and a /<platform> shortlink.',
103
+ ' socials: {},',
104
+ '',
105
+ ' // Project-owned theme — seeded at onboarding, yours to change.',
106
+ ' theme: {',
107
+ ' id: "classy",',
108
+ ' appearance: "system", // "system" | "light" | "dark"',
109
+ ' },',
110
+ '',
111
+ ' // AI translation (web /{lang}/ pages, extension _locales). Provider',
112
+ ' // "claude" (default) rides the local Claude Code install — no API key;',
113
+ ' // "chatgpt" needs OPENAI_API_KEY in .env. Uncomment to enable:',
114
+ ' // translation: {',
115
+ ' // languages: ["es", "fr", "de"],',
116
+ ' // },',
117
+ '',
118
+ );
119
+
120
+ // Only a CUSTOMIZED admin list lands here — an inherited one (company
121
+ // config or the built-in support@{domain} default) stays unwritten so the
122
+ // source layer keeps owning it.
123
+ if (answers.accountAdmins) {
124
+ lines.push(
125
+ ' // Managed Firebase Auth accounts (account service). Passwords never live',
126
+ ' // here — OMEGA_ACCOUNT_PASSWORD__* env vars, config/hooks/account/password.js,',
127
+ ' // or the generated ACCOUNT_PASSWORD_SEED.',
128
+ ' account: {',
129
+ ' admins: [',
130
+ );
131
+ for (const entry of answers.accountAdmins) {
132
+ lines.push(` { email: ${JSON.stringify(entry.email)}, account: ${!!entry.account}, marketing: ${!!entry.marketing} },`);
133
+ }
134
+ lines.push(' ],', ' },', '');
135
+ }
136
+
137
+ // Backend brands get a bootable cloud project out of the box: demo-* ids
138
+ // are the emulator-only convention (never touch live Firebase), so the
139
+ // emulator boots before any real project exists (dogfood friction #3).
140
+ if (answers.targets.includes('backend')) {
141
+ lines.push(
142
+ ' // Cloud project (backend target). demo-* ids are EMULATOR-ONLY — the',
143
+ ' // emulators boot against this immediately; swap in a real Firebase project',
144
+ ' // id at launch (the cloud service can create one).',
145
+ ' cloud: {',
146
+ ' provider: "firebase",',
147
+ ' config: {',
148
+ ` projectId: ${JSON.stringify(`demo-${answers.id}`)},`,
149
+ ' },',
150
+ ' },',
151
+ '',
152
+ );
153
+ }
154
+
155
+ lines.push(
156
+ ' // Payment catalog — pricing pages render THESE products (no products =',
157
+ ' // honest empty state). Uncomment + edit to start selling; ids are',
158
+ ' // permanent once live. Provider id fields (stripe/paypal/chargebee) are',
159
+ ' // filled by the payment service — leave them null. Presentation fields',
160
+ ' // (tagline, popular, features) are optional card garnish.',
161
+ ' // payment: {',
162
+ ' // products: [',
163
+ ' // {',
164
+ ' // id: "premium",',
165
+ ' // name: "Premium",',
166
+ ' // type: "subscription",',
167
+ ' // tagline: "best for teams",',
168
+ ' // popular: true,',
169
+ ' // prices: { monthly: 9.99, annually: 99.99 },',
170
+ ' // trial: { days: 14 },',
171
+ ' // limits: { requests: 10000 },',
172
+ ' // features: [{ id: "requests", name: "Requests", icon: "sparkles" }],',
173
+ ' // },',
174
+ ' // { id: "launch-kit", name: "Launch Kit", type: "one-time", prices: { once: 49.99 } },',
175
+ ' // ],',
176
+ ' // },',
177
+ '',
178
+ );
179
+
180
+ // App-signing brands get their reverse-DNS bundle prefix derived at
181
+ // onboarding (parent company's domain when one exists, else the brand's)
182
+ if (answers.targets.includes('desktop') && answers.bundleIdPrefix) {
183
+ lines.push(
184
+ ' // Apple signing (certificates service): reverse-DNS prefix derived from',
185
+ ' // the company/brand domain at onboarding. Bundle IDs mint as',
186
+ ' // <prefix>.<brand id with dashes as dots>.',
187
+ ' certificates: {',
188
+ ' providers: {',
189
+ ' apple: {',
190
+ ` bundleIdPrefix: ${JSON.stringify(answers.bundleIdPrefix)},`,
191
+ ' },',
192
+ ' },',
193
+ ' },',
194
+ '',
195
+ );
196
+ }
197
+
198
+ lines.push(
199
+ ' // Key presence = target enabled; the value is that target\'s type-wide',
200
+ ' // config (any shared key inside overrides it for that surface).',
201
+ ' targets: {',
202
+ );
203
+
204
+ for (const target of answers.targets) {
205
+ lines.push(` ${target}: {},`);
206
+ }
207
+
208
+ lines.push(' },', '}');
209
+
210
+ return `${lines.join('\n')}\n`;
211
+ }
212
+
213
+ function renderRootPackageJson(answers) {
214
+ return `${JSON.stringify({
215
+ name: answers.id,
216
+ private: true,
217
+ ...(answers.description ? { description: answers.description } : {}),
218
+ workspaces: ['targets/*'],
219
+ // npm scripts put node_modules/.bin on PATH, so plain `omega` (the
220
+ // context-aware dispatcher) resolves — never the retired omega-manager name
221
+ // `npm start` boots the dev stack (`dev` stays as its alias); the bare
222
+ // manage cycle is `npm run manage`
223
+ scripts: {
224
+ start: 'omega dev',
225
+ dev: 'omega dev',
226
+ manage: MANAGE_SCRIPT,
227
+ deploy: 'omega deploy',
228
+ },
229
+ // Brand-level verbs (`omega dev`, manage, the `start` script above) resolve
230
+ // @omega.js/manager FROM THE BRAND ROOT (omega-bin dispatch) — without this
231
+ // declaration nothing installs it outside the monorepo and every brand-root
232
+ // command dies (cp195 journey catch). Pinned exactly: the root and every
233
+ // target ride ONE family version (#794).
234
+ devDependencies: {
235
+ '@omega.js/manager': FAMILY_VERSION,
236
+ },
237
+ }, null, 2)}\n`;
238
+ }
239
+
240
+ function renderGitignore() {
241
+ return [
242
+ '# Dependencies',
243
+ 'node_modules/',
244
+ '',
245
+ '# Build output',
246
+ 'dist/',
247
+ '',
248
+ '# OMEGA manager state (derived data — never committed)',
249
+ '.omega/',
250
+ '',
251
+ '# Run logs (truncated on every launch — never committed)',
252
+ 'logs/',
253
+ '',
254
+ '# Secrets',
255
+ '.env',
256
+ '.env.*',
257
+ '',
258
+ '# OS',
259
+ '.DS_Store',
260
+ '',
261
+ ].join('\n');
262
+ }
263
+
264
+ function renderEnvStub(answers) {
265
+ return renderCanonicalEnv({
266
+ header: [
267
+ `# ${answers.name} — brand secrets (gitignored; loaded before every omega run).`,
268
+ '# Uncomment and fill what this brand uses. Services without their credentials',
269
+ '# skip cleanly, so add these as the brand adopts each service.',
270
+ ],
271
+ // The generated keys and their line form come from the SSOTs the
272
+ // manage-time mint uses too (#569), so a brand born here and a brand
273
+ // healed by the env-keys op carry byte-identical shapes.
274
+ entries: new Map(Object.entries(generatedEnvKeys()).map(([key, generate]) => [key, { raw: envLine(key, generate()) }])),
275
+ });
276
+ }
277
+
278
+ /**
279
+ * An environment overlay stub — a header comment and NOTHING else
280
+ * ([#586](https://github.com/Omega-JS-Stack/omega/issues/586)). The base `.env`
281
+ * stays the one file that documents every key (it carries the canonical
282
+ * placeholder list); an overlay only ever holds the handful a brand wants
283
+ * different for one environment, so pre-listing anything here would be a second
284
+ * inventory to drift.
285
+ *
286
+ * @param {string} environment - `development` | `testing` | `production`.
287
+ * @returns {string} The file contents.
288
+ */
289
+ function renderEnvOverlayStub(environment) {
290
+ return [
291
+ `# .env.${environment} — overlays .env when this brand runs in ${environment} (gitignored).`,
292
+ '# Only the keys that differ — anything not set here falls through to .env.',
293
+ '',
294
+ ].join('\n');
295
+ }
296
+
297
+ function renderReadme(answers) {
298
+ const targetList = answers.targets
299
+ .map((target) => {
300
+ const dir = TARGET_DIRS[target] || target;
301
+ const framework = TARGET_FRAMEWORKS[target];
302
+ return `- \`targets/${dir}/\` — the ${target} target${framework ? ` (framework: \`${framework}\`)` : ''}`;
303
+ })
304
+ .join('\n');
305
+
306
+ return `# ${answers.name}
307
+
308
+ ${answers.description || 'An OMEGA brand monorepo.'}
309
+
310
+ One repo, every surface of the brand. \`config/omega.json5\` is the single
311
+ source of user choices; \`omega\` reconciles every external service
312
+ to it, idempotently.
313
+
314
+ ## Structure
315
+
316
+ - \`config/omega.json5\` — brand-level shared config (targets inherit + override)
317
+ ${targetList}
318
+ - \`.env\` — credentials (gitignored; see the stub for every service's keys)
319
+ - \`.env.<environment>\` — the per-environment overlay (\`development\`, \`testing\`, \`production\`): only the keys that differ there
320
+ - \`.omega/\` — manager state + run output (gitignored, machine-owned)
321
+
322
+ ## Next steps
323
+
324
+ 1. \`npm install\` — each target declares its framework (workspace link in a
325
+ monorepo; standalone pre-publish: \`npx mgr i local\` inside each target).
326
+ 2. Fill in \`.env\` as the brand adopts external services.
327
+ 3. \`npm run manage\` — reconcile everything; rerun any time.
328
+ 4. \`npm start\` (\`npx omega dev\`) — boot the local stack; each target's verbs
329
+ scaffold its consumer interior on first run.
330
+ `;
331
+ }
332
+
333
+ function renderTargetPackageJson(answers, target, dir) {
334
+ const framework = TARGET_FRAMEWORKS[target];
335
+ // The exact family pin (#794): satisfied by a workspace link in-monorepo,
336
+ // `mgr i local` pre-publish (which flips the spec to `file:`), and the npm
337
+ // registry once @omega.js/* publish — where the pin is what keeps every
338
+ // target on ONE framework version.
339
+ const depKey = RUNTIME_DEP_TARGETS.includes(target) ? 'dependencies' : 'devDependencies';
340
+
341
+ // version + author: electron-builder hard-requires version and warns on
342
+ // author (the cp142 rehearsal catch) — every target gets both, they're healthy
343
+ return `${JSON.stringify({
344
+ name: `${answers.id}-${dir}`,
345
+ version: '0.0.1',
346
+ author: answers.name,
347
+ private: true,
348
+ description: `${answers.name} ${target} target`,
349
+ ...(framework ? { [depKey]: { [framework]: FAMILY_VERSION } } : {}),
350
+ }, null, 2)}\n`;
351
+ }
352
+
353
+ /**
354
+ * Build the scaffold plan for a brand.
355
+ *
356
+ * @param {Object} answers - { id, name, description, tagline, url, email, person, targets }
357
+ * @returns {Array<{ path: string, contents: string }>} - Brand-root-relative file plan
358
+ */
359
+ function buildScaffoldPlan(answers) {
360
+ const plan = [
361
+ { path: 'config/omega.json5', contents: renderOmegaConfig(answers) },
362
+ { path: 'package.json', contents: renderRootPackageJson(answers) },
363
+ { path: '.gitignore', contents: renderGitignore() },
364
+ { path: '.env', contents: renderEnvStub(answers) },
365
+ ...ENV_ENVIRONMENTS.map((environment) => ({ path: `.env.${environment}`, contents: renderEnvOverlayStub(environment) })),
366
+ { path: 'README.md', contents: renderReadme(answers) },
367
+ ];
368
+
369
+ for (const target of answers.targets) {
370
+ const dir = TARGET_DIRS[target] || target;
371
+ plan.push({ path: `targets/${dir}/package.json`, contents: renderTargetPackageJson(answers, target, dir) });
372
+ }
373
+
374
+ return plan;
375
+ }
376
+
377
+ /**
378
+ * Write a scaffold plan with fill-missing semantics: files that already
379
+ * exist are never touched (rerunning onboard converges instead of clobbering).
380
+ *
381
+ * @param {string} brandRoot - Absolute brand root to scaffold into
382
+ * @param {Array<{ path, contents }>} plan - From buildScaffoldPlan()
383
+ * @param {Object} [options] - { dryRun } — plan only, zero writes
384
+ * @returns {{ created: string[], kept: string[], planned: string[] }}
385
+ */
386
+ function applyScaffoldPlan(brandRoot, plan, { dryRun = false } = {}) {
387
+ const created = [];
388
+ const kept = [];
389
+ const planned = [];
390
+
391
+ for (const file of plan) {
392
+ const destination = path.join(brandRoot, file.path);
393
+
394
+ if (jetpack.exists(destination)) {
395
+ kept.push(file.path);
396
+ continue;
397
+ }
398
+
399
+ if (dryRun) {
400
+ planned.push(file.path);
401
+ continue;
402
+ }
403
+
404
+ jetpack.write(destination, file.contents);
405
+ created.push(file.path);
406
+ }
407
+
408
+ return { created, kept, planned };
409
+ }
410
+
411
+ /**
412
+ * Print what a plan did — the one rendering of created/kept/planned, shared
413
+ * by every scaffolding verb (onboard's brand plan, company init's).
414
+ */
415
+ function printPlanResults({ created, kept, planned }) {
416
+ for (const file of planned) {
417
+ console.log(` ${chalk.dim('⊘')} would create ${chalk.cyan(file)}`);
418
+ }
419
+ for (const file of created) {
420
+ console.log(` ${chalk.green('✓')} created ${chalk.cyan(file)}`);
421
+ }
422
+ for (const file of kept) {
423
+ console.log(` ${chalk.dim('•')} kept ${chalk.dim(file)} ${chalk.dim('(exists)')}`);
424
+ }
425
+ }
426
+
427
+ module.exports = { buildScaffoldPlan, applyScaffoldPlan, printPlanResults };
@@ -0,0 +1,207 @@
1
+ /**
2
+ * The ONE setup contract every service asks its inputs through (#608, Ian
3
+ * 2026-08-25) — the env-side twin of config-flow's resolveConfigValue, and the
4
+ * successor to cp114's two-outcome ensureEnvSecrets.
5
+ *
6
+ * When a service runs and an input it needs is missing, it asks RIGHT THEN,
7
+ * with the same three outcomes everywhere:
8
+ *
9
+ * Provide — the Enter-gated open of the exact page that mints
10
+ * the value, a masked paste, persisted to the brand
11
+ * .env (lib/env-secret.js) and exported for THIS run,
12
+ * so a fresh brand configures itself mid-walk.
13
+ * Skip for now — this run steps aside; the next one asks again.
14
+ * Disable permanently — `<service>.enabled: false` lands in omega.json5
15
+ * (the tri-state opt-out, #33) and nothing ever asks
16
+ * again until the line is deleted.
17
+ *
18
+ * Non-interactive runs (CI, a piped `omega dev` boot, `--dry-run`) NEVER
19
+ * prompt: the missing keys print as a loud skip line and ride back as the
20
+ * machine-readable `missingEnv` list the run summary's 🔑 section aggregates.
21
+ *
22
+ * One class of input is never PASTED: a key OMEGA mints for ITSELF (the env
23
+ * schema's `generated:` set) has nobody to ask, so it is minted in place and
24
+ * never appears in `missingEnv` (#635). When it is the only thing missing no
25
+ * gate opens at all, headless runs included; when a pasted key is missing
26
+ * beside it the gate runs FIRST and the mint happens only past it, so
27
+ * "Disable permanently" never leaves a minted secret behind.
28
+ *
29
+ * WHAT each service needs is the REQUIRES registry's to say (src/config.js —
30
+ * one home, checked up front by lib/preflight.js and asked for here through
31
+ * `serviceInputSpec(name)`); the env schema (@omega.js/config, #581) is what
32
+ * says which of those keys OMEGA mints for itself and which a human acquires,
33
+ * and the sweep test holds the registry to it.
34
+ *
35
+ * Values are never printed — names, labels and mint URLs only.
36
+ */
37
+ const chalk = require('chalk').default;
38
+
39
+ const { generatedEnvKeys } = require('../vendor/config/index.js');
40
+ const { canPrompt, dryRunPlan } = require('./run-gates.js');
41
+ const { writeEnvValue, mintGeneratedKey } = require('./env-secret.js');
42
+ const { confirmSetup, readTriState } = require('./config-flow.js');
43
+
44
+ /**
45
+ * Ask for a service's missing inputs, with the three-outcome gate.
46
+ *
47
+ * @param {object} context - Service context ({ brandRoot, brandConfig, brandId, options }).
48
+ * @param {object} spec - The input spec (serviceInputSpec(name) builds one from
49
+ * the REQUIRES registry):
50
+ * @param {string} spec.service - Service name (names the rerun hint).
51
+ * @param {string} spec.label - Human name the gate opens with ("Cloudflare").
52
+ * @param {string} spec.disablePath - Where "Disable permanently" writes `false`.
53
+ * @param {string[]} [spec.instructions] - Guidance lines shown before the gate.
54
+ * @param {boolean} [spec.gate] - false = the caller already ran the gate.
55
+ * @param {Array<{ name, label?, url?, hint?, when? }>} spec.inputs - The env
56
+ * vars the service needs; `when(brandConfig)` drops the ones this brand
57
+ * doesn't, `url` is the page that mints one, `hint` says what to make there.
58
+ * @param {object} [deps] - Test seam: { prompt } overrides devkit/prompt members.
59
+ * @returns {Promise<object|null>} null to proceed, or the setup skip shape
60
+ * ({ skip, reason, missingEnv, disabled? }).
61
+ */
62
+ async function requestServiceInput(context, spec, deps = {}) {
63
+ const { brandConfig = {}, options = {} } = context;
64
+
65
+ const wanted = spec.inputs.filter((input) => !input.when || input.when(brandConfig));
66
+ const missing = wanted.filter((input) => !process.env[input.name]);
67
+ if (missing.length === 0) {
68
+ return null;
69
+ }
70
+
71
+ // Already opted out (#33): the value — or any ancestor section — is `false`.
72
+ // Every service gates on its own key too; this is the backstop that keeps a
73
+ // disabled service from ever reaching a prompt.
74
+ if (readTriState(brandConfig, spec.disablePath).optedOut) {
75
+ return {
76
+ skip: true,
77
+ reason: `${spec.disablePath} is disabled — delete the line in omega.json5 to be asked again`,
78
+ missingEnv: missing.map((input) => input.name),
79
+ disabled: true,
80
+ };
81
+ }
82
+
83
+ // A key OMEGA mints for itself (the env schema's `generated:` set, #581) is
84
+ // MINTED, not pasted: there is nobody to ask for it, so it never joins the
85
+ // 🔑 "add these to your .env" list — the two kinds of missing input split
86
+ // here and are handled apart (#635).
87
+ const generated = generatedEnvKeys();
88
+ const mintable = missing.filter((input) => generated[input.name]);
89
+ const pending = missing.filter((input) => !generated[input.name]);
90
+
91
+ const mintAll = () => {
92
+ for (const input of mintable) {
93
+ mintGeneratedKey(context.brandRoot, input.name, { indent: ' ' });
94
+ }
95
+ };
96
+
97
+ // A dry run says what a real run would mint and writes nothing, exactly as
98
+ // the workspace env-keys op does.
99
+ if (options.dryRun) {
100
+ for (const input of mintable) {
101
+ dryRunPlan(`mint ${input.name} into the brand .env`);
102
+ }
103
+ }
104
+
105
+ // Nothing a human could supply is missing: mint and proceed, no gate, on a
106
+ // headless run too.
107
+ if (pending.length === 0) {
108
+ if (options.dryRun) {
109
+ // Named, but NOT as missingEnv — telling someone to paste a key only
110
+ // OMEGA can produce would be a lie the 🔑 section then repeats.
111
+ return {
112
+ skip: true,
113
+ reason: `${mintable.map((input) => input.name).join(', ')} will be minted on a real run`,
114
+ missingEnv: [],
115
+ };
116
+ }
117
+
118
+ mintAll();
119
+ return null;
120
+ }
121
+
122
+ const names = pending.map((input) => input.name);
123
+
124
+ if (!canPrompt(options)) {
125
+ // Loud: a run that cannot ask still says exactly which keys it wants and
126
+ // where they go, instead of a bare "skipped".
127
+ console.log(` ${chalk.yellow('🔑')} ${spec.label} needs ${chalk.bold(names.join(', '))} ${chalk.dim('— not in the brand .env')}`);
128
+ for (const input of pending) {
129
+ if (input.url) {
130
+ console.log(` ${chalk.dim(`→ ${input.name}: mint it at ${input.url}`)}`);
131
+ }
132
+ }
133
+
134
+ return {
135
+ skip: true,
136
+ reason: `missing ${names.join(', ')} — add to the brand .env, or rerun interactively to paste`,
137
+ missingEnv: names,
138
+ };
139
+ }
140
+
141
+ // The uniform gate — its wording lives once, in config-flow's confirmSetup,
142
+ // and its Disable lands the tri-state `false` for us. `gate: false` is the
143
+ // chained ask (resolveConfigValue's convention): the caller already opened
144
+ // this flow's gate, so asking twice would be the same question.
145
+ const action = spec.gate === false
146
+ ? 'yes'
147
+ : await confirmSetup(context, {
148
+ label: spec.label,
149
+ instructions: spec.instructions,
150
+ disablePath: spec.disablePath,
151
+ });
152
+
153
+ if (action === 'disable') {
154
+ return {
155
+ skip: true,
156
+ reason: `${spec.disablePath} disabled in omega.json5 — delete the line to be asked again`,
157
+ missingEnv: names,
158
+ disabled: true,
159
+ };
160
+ }
161
+
162
+ if (action !== 'yes') {
163
+ return {
164
+ skip: true,
165
+ reason: `skipped this run — ${spec.service} still needs ${names.join(', ')}`,
166
+ missingEnv: names,
167
+ };
168
+ }
169
+
170
+ // Past the gate: only NOW are OMEGA's own keys minted, so a "Disable
171
+ // permanently" never leaves a freshly minted secret in a brand that just
172
+ // said it wants none of this.
173
+ mintAll();
174
+
175
+ const prompt = { ...require('../vendor/devkit/prompt.js'), ...deps.prompt };
176
+
177
+ for (const input of pending) {
178
+ const label = input.label || input.name;
179
+ if (input.hint) {
180
+ console.log(` ${chalk.dim(input.hint)}`);
181
+ }
182
+
183
+ // The exact-page guide: Enter opens the page that mints the value
184
+ // (pressEnterToOpen always prints the URL, so it stays clickable when the
185
+ // user would rather not open a browser).
186
+ if (input.url) {
187
+ await prompt.pressEnterToOpen(input.url, `the ${label} page`);
188
+ }
189
+
190
+ const value = (await prompt.password({ message: `Paste ${input.name}:` }) || '').trim();
191
+ if (!value) {
192
+ return {
193
+ skip: true,
194
+ reason: `nothing entered for ${input.name} — ${spec.service} still needs ${names.join(', ')}`,
195
+ missingEnv: names,
196
+ };
197
+ }
198
+
199
+ writeEnvValue(context.brandRoot, input.name, value);
200
+ process.env[input.name] = value;
201
+ console.log(` ${chalk.green('✓')} ${input.name} saved to the brand .env`);
202
+ }
203
+
204
+ return null;
205
+ }
206
+
207
+ module.exports = { requestServiceInput };