@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,354 @@
1
+ /**
2
+ * PayPal REST API wrapper — OAuth2 client credentials with live/sandbox
3
+ * auto-detection (first auth probes both endpoints in parallel). Ported from
4
+ * omega-manager minus the subscription-inspection methods (they belong to
5
+ * the migrations port) and the unused plan/webhook helpers.
6
+ */
7
+ const LIVE_URL = 'https://api-m.paypal.com';
8
+ const SANDBOX_URL = 'https://api-m.sandbox.paypal.com';
9
+
10
+ class PayPalAPI {
11
+ constructor(clientId, clientSecret) {
12
+ this.clientId = clientId;
13
+ this.clientSecret = clientSecret;
14
+ this.baseUrl = null; // Resolved on first auth
15
+ this.accessToken = null;
16
+ this.tokenExpiry = 0;
17
+ this.appId = null; // From token response
18
+ }
19
+
20
+ /**
21
+ * Try to authenticate against a specific PayPal endpoint.
22
+ * Returns the token response data on success, null on auth failure.
23
+ */
24
+ static async tryAuth(clientId, clientSecret, baseUrl) {
25
+ const credentials = Buffer.from(`${clientId}:${clientSecret}`).toString('base64');
26
+
27
+ const response = await fetch(`${baseUrl}/v1/oauth2/token`, {
28
+ method: 'POST',
29
+ headers: {
30
+ 'Authorization': `Basic ${credentials}`,
31
+ 'Content-Type': 'application/x-www-form-urlencoded',
32
+ },
33
+ body: 'grant_type=client_credentials',
34
+ });
35
+
36
+ if (!response.ok) {
37
+ return null;
38
+ }
39
+
40
+ return response.json();
41
+ }
42
+
43
+ /**
44
+ * Get OAuth2 access token (cached until expiry).
45
+ * On first call, tries both live and sandbox simultaneously to detect the right endpoint.
46
+ */
47
+ async getAccessToken() {
48
+ if (this.accessToken && Date.now() < this.tokenExpiry) {
49
+ return this.accessToken;
50
+ }
51
+
52
+ // First auth — try both endpoints in parallel
53
+ if (!this.baseUrl) {
54
+ const [liveResult, sandboxResult] = await Promise.all([
55
+ PayPalAPI.tryAuth(this.clientId, this.clientSecret, LIVE_URL),
56
+ PayPalAPI.tryAuth(this.clientId, this.clientSecret, SANDBOX_URL),
57
+ ]);
58
+
59
+ if (liveResult) {
60
+ this._applyToken(liveResult, LIVE_URL);
61
+ return this.accessToken;
62
+ }
63
+
64
+ if (sandboxResult) {
65
+ this._applyToken(sandboxResult, SANDBOX_URL);
66
+ return this.accessToken;
67
+ }
68
+
69
+ throw new Error('PayPal auth failed on both live and sandbox — check paypal.clientId and PAYPAL_CLIENT_SECRET');
70
+ }
71
+
72
+ // Subsequent auths — use the resolved endpoint
73
+ const result = await PayPalAPI.tryAuth(this.clientId, this.clientSecret, this.baseUrl);
74
+ if (!result) {
75
+ throw new Error(`PayPal auth failed (${this.baseUrl})`);
76
+ }
77
+
78
+ this._applyToken(result);
79
+ return this.accessToken;
80
+ }
81
+
82
+ /**
83
+ * Store token data from an auth response
84
+ */
85
+ _applyToken(data, baseUrl) {
86
+ if (baseUrl) {
87
+ this.baseUrl = baseUrl;
88
+ }
89
+ this.accessToken = data.access_token;
90
+ this.tokenExpiry = Date.now() + (data.expires_in - 60) * 1000;
91
+ this.appId = data.app_id || this.appId;
92
+ }
93
+
94
+ /**
95
+ * Get account info derived from the token response.
96
+ * Must call getAccessToken() first.
97
+ */
98
+ getAccountInfo() {
99
+ return {
100
+ appId: this.appId,
101
+ environment: this.baseUrl === SANDBOX_URL ? 'sandbox' : 'live',
102
+ clientId: this.clientId,
103
+ };
104
+ }
105
+
106
+ /**
107
+ * Make an authenticated request to PayPal API
108
+ */
109
+ async makeRequest(method, path, body, extraHeaders) {
110
+ const token = await this.getAccessToken();
111
+
112
+ const options = {
113
+ method,
114
+ headers: {
115
+ 'Authorization': `Bearer ${token}`,
116
+ 'Content-Type': 'application/json',
117
+ ...extraHeaders,
118
+ },
119
+ };
120
+
121
+ if (body) {
122
+ options.body = JSON.stringify(body);
123
+ }
124
+
125
+ const response = await fetch(`${this.baseUrl}${path}`, {
126
+ ...options,
127
+ signal: AbortSignal.timeout(30000),
128
+ });
129
+
130
+ // PATCH returns 204 No Content on success
131
+ if (response.status === 204) {
132
+ return null;
133
+ }
134
+
135
+ if (!response.ok) {
136
+ const text = await response.text();
137
+ throw new Error(`PayPal API error (${response.status} ${method} ${path}): ${text}`);
138
+ }
139
+
140
+ return response.json();
141
+ }
142
+
143
+ /**
144
+ * Paginate through a PayPal list endpoint, collecting all items.
145
+ *
146
+ * @param {string} basePath - Base API path (e.g. '/v1/catalogs/products')
147
+ * @param {string} itemsKey - Key in response containing items (e.g. 'products')
148
+ * @param {Object} [extraParams] - Additional query params
149
+ * @param {Object} [extraHeaders] - Additional request headers
150
+ * @returns {Array} All items across all pages
151
+ */
152
+ async paginate(basePath, itemsKey, extraParams = {}, extraHeaders) {
153
+ const allItems = [];
154
+ let page = 1;
155
+ const pageSize = 20;
156
+
157
+ while (true) {
158
+ const params = new URLSearchParams({
159
+ page_size: pageSize,
160
+ page: page,
161
+ total_required: true,
162
+ ...extraParams,
163
+ });
164
+
165
+ const response = await this.makeRequest('GET', `${basePath}?${params}`, null, extraHeaders);
166
+ const items = response?.[itemsKey] || [];
167
+ allItems.push(...items);
168
+
169
+ const total = response?.total_items || 0;
170
+ if (allItems.length >= total || items.length < pageSize) {
171
+ break;
172
+ }
173
+
174
+ page++;
175
+ }
176
+
177
+ return allItems;
178
+ }
179
+
180
+ // ---------------------------------------------------------------------------
181
+ // Catalog Products
182
+ // ---------------------------------------------------------------------------
183
+
184
+ /**
185
+ * List all catalog products (paginated)
186
+ */
187
+ async listProducts() {
188
+ return this.paginate('/v1/catalogs/products', 'products');
189
+ }
190
+
191
+ /**
192
+ * Retrieve a catalog product by ID
193
+ */
194
+ async getProduct(productId) {
195
+ return this.makeRequest('GET', `/v1/catalogs/products/${productId}`);
196
+ }
197
+
198
+ /**
199
+ * Create a catalog product
200
+ */
201
+ async createProduct({ name, description, type = 'SERVICE', imageUrl, homeUrl }) {
202
+ const body = {
203
+ name,
204
+ type,
205
+ };
206
+
207
+ if (description) {
208
+ body.description = description.slice(0, 256); // PayPal limit
209
+ }
210
+ if (imageUrl) {
211
+ body.image_url = imageUrl;
212
+ }
213
+ if (homeUrl) {
214
+ body.home_url = homeUrl;
215
+ }
216
+
217
+ return this.makeRequest('POST', '/v1/catalogs/products', body);
218
+ }
219
+
220
+ /**
221
+ * Update a catalog product using JSON Patch format
222
+ *
223
+ * @param {string} productId - PayPal product ID
224
+ * @param {Array} patches - Array of JSON Patch operations
225
+ * e.g. [{ op: 'replace', path: '/description', value: 'new desc' }]
226
+ */
227
+ async updateProduct(productId, patches) {
228
+ return this.makeRequest('PATCH', `/v1/catalogs/products/${productId}`, patches);
229
+ }
230
+
231
+ // ---------------------------------------------------------------------------
232
+ // Billing Plans (subscriptions)
233
+ // ---------------------------------------------------------------------------
234
+
235
+ /**
236
+ * List billing plans filtered by product ID (with full details including billing_cycles).
237
+ * Paginated — returns ALL plans for the product.
238
+ */
239
+ async listPlansForProduct(productId) {
240
+ return this.paginate(
241
+ '/v1/billing/plans',
242
+ 'plans',
243
+ { product_id: productId },
244
+ { 'Prefer': 'return=representation' },
245
+ );
246
+ }
247
+
248
+ /**
249
+ * Deactivate a billing plan (stops new subscriptions, existing ones continue)
250
+ */
251
+ async deactivatePlan(planId) {
252
+ return this.makeRequest('POST', `/v1/billing/plans/${planId}/deactivate`);
253
+ }
254
+
255
+ /**
256
+ * Create a billing plan for a product
257
+ *
258
+ * @param {Object} options
259
+ * @param {string} options.productId - PayPal catalog product ID
260
+ * @param {string} options.name - Plan name (e.g. "Chatsy - Plus (Monthly)")
261
+ * @param {string} options.interval - 'monthly' or 'annually'
262
+ * @param {number} options.amount - Price amount (e.g. 28)
263
+ * @param {string} [options.currency='USD'] - Currency code
264
+ * @param {number} [options.trialDays=0] - Trial period in days
265
+ */
266
+ async createPlan({ productId, name, interval, amount, currency = 'USD', trialDays = 0 }) {
267
+ const billingCycles = [];
268
+
269
+ // Add trial cycle if specified
270
+ if (trialDays > 0) {
271
+ billingCycles.push({
272
+ frequency: {
273
+ interval_unit: 'DAY',
274
+ interval_count: 1,
275
+ },
276
+ tenure_type: 'TRIAL',
277
+ sequence: 1,
278
+ total_cycles: trialDays,
279
+ pricing_scheme: {
280
+ fixed_price: {
281
+ value: '0',
282
+ currency_code: currency,
283
+ },
284
+ },
285
+ });
286
+ }
287
+
288
+ // Regular billing cycle
289
+ billingCycles.push({
290
+ frequency: {
291
+ interval_unit: { annually: 'YEAR', monthly: 'MONTH', weekly: 'WEEK', daily: 'DAY' }[interval] || 'MONTH',
292
+ interval_count: 1,
293
+ },
294
+ tenure_type: 'REGULAR',
295
+ sequence: trialDays > 0 ? 2 : 1,
296
+ total_cycles: 0, // 0 = infinite
297
+ pricing_scheme: {
298
+ fixed_price: {
299
+ value: amount.toFixed(2),
300
+ currency_code: currency,
301
+ },
302
+ },
303
+ });
304
+
305
+ const body = {
306
+ product_id: productId,
307
+ name,
308
+ billing_cycles: billingCycles,
309
+ payment_preferences: {
310
+ auto_bill_outstanding: true,
311
+ payment_failure_threshold: 3,
312
+ },
313
+ };
314
+
315
+ return this.makeRequest('POST', '/v1/billing/plans', body);
316
+ }
317
+
318
+ // ---------------------------------------------------------------------------
319
+ // Webhooks
320
+ // ---------------------------------------------------------------------------
321
+
322
+ /**
323
+ * List all webhook endpoints
324
+ */
325
+ async listWebhooks() {
326
+ return this.makeRequest('GET', '/v1/notifications/webhooks');
327
+ }
328
+
329
+ /**
330
+ * Create a webhook endpoint
331
+ */
332
+ async createWebhook(url, eventTypes) {
333
+ return this.makeRequest('POST', '/v1/notifications/webhooks', {
334
+ url,
335
+ event_types: eventTypes.map((name) => ({ name })),
336
+ });
337
+ }
338
+
339
+ /**
340
+ * Update a webhook endpoint using JSON Patch format
341
+ */
342
+ async updateWebhook(webhookId, patches) {
343
+ return this.makeRequest('PATCH', `/v1/notifications/webhooks/${webhookId}`, patches);
344
+ }
345
+
346
+ /**
347
+ * Delete a webhook endpoint (204 No Content on success)
348
+ */
349
+ async deleteWebhook(webhookId) {
350
+ return this.makeRequest('DELETE', `/v1/notifications/webhooks/${webhookId}`);
351
+ }
352
+ }
353
+
354
+ module.exports = { PayPalAPI };
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Interactive payment-provider credential entry — one provider's instance of
3
+ * the shared setup contract (#608): the same Provide / Skip / Disable gate
4
+ * every service opens with (lib/config-flow.js confirmSetup, the ONE home of
5
+ * that wording), then the provider dashboard and its keys. Public halves
6
+ * (publishable key, client id, site) land in omega.json5 via the
7
+ * comment-preserving writeback — a provider with no public half declares none
8
+ * (coinbase, whose API key is the whole credential) — and the SECRET half rides
9
+ * the shared helper
10
+ * (lib/service-input.js), which persists it to the brand .env and exports it
11
+ * so the current run proceeds immediately. Disable writes
12
+ * `payment.providers.<name>: false` so the run stops asking — permanently.
13
+ *
14
+ * Non-interactive or dry-run sessions return false without prompting — the
15
+ * provider stays unconfigured and its operations print their dim note.
16
+ */
17
+ const chalk = require('chalk').default;
18
+ const { input } = require('../../../vendor/devkit/prompt.js');
19
+ const { serviceInputSpec } = require('../../../config.js');
20
+ const { writeBrandConfig } = require('../../../lib/config-write.js');
21
+ const { confirmSetup, setAtPath } = require('../../../lib/config-flow.js');
22
+ const { requestServiceInput } = require('../../../lib/service-input.js');
23
+ const { canPrompt } = require('../../../lib/run-gates.js');
24
+
25
+ // Per provider: the dashboard to open, and the PUBLIC halves that land in
26
+ // omega.json5. The secret half's descriptor (name, mint URL, hint) lives once,
27
+ // in the REQUIRES registry — never re-spelled here.
28
+ const PROVIDERS = {
29
+ stripe: {
30
+ label: 'Stripe',
31
+ url: 'https://dashboard.stripe.com/apikeys',
32
+ instructions: 'Create or switch to the brand\'s Stripe account, then go to Developers → API keys.',
33
+ secret: 'STRIPE_SECRET_KEY',
34
+ fields: [
35
+ {
36
+ message: 'Stripe publishable key (pk_live_... or pk_test_...):',
37
+ validate: (val) => (val?.trim().startsWith('pk_') ? true : 'Must start with pk_live_ or pk_test_'),
38
+ configPath: 'payment.providers.stripe.publishableKey',
39
+ },
40
+ ],
41
+ },
42
+ paypal: {
43
+ label: 'PayPal',
44
+ url: 'https://developer.paypal.com/dashboard/applications',
45
+ instructions: 'Create or open the brand\'s REST API app (live), then copy its credentials.',
46
+ secret: 'PAYPAL_CLIENT_SECRET',
47
+ fields: [
48
+ {
49
+ message: 'PayPal client ID:',
50
+ validate: (val) => (val?.trim() ? true : 'Required'),
51
+ configPath: 'payment.providers.paypal.clientId',
52
+ },
53
+ ],
54
+ },
55
+ chargebee: {
56
+ label: 'Chargebee',
57
+ url: 'https://app.chargebee.com/',
58
+ instructions: 'Open the brand\'s Chargebee site, then go to Settings → API keys.',
59
+ secret: 'CHARGEBEE_API_KEY',
60
+ fields: [
61
+ {
62
+ message: 'Chargebee site (the {site}.chargebee.com subdomain):',
63
+ validate: (val) => (val?.trim() ? true : 'Required'),
64
+ configPath: 'payment.providers.chargebee.site',
65
+ },
66
+ ],
67
+ },
68
+ // The one provider with NO public half ([#642](https://github.com/Omega-JS-Stack/omega/issues/642)):
69
+ // the Coinbase Commerce API key is the entire credential, so `fields` is empty
70
+ // and nothing is written to omega.json5 — the gate and the secret ask are the
71
+ // whole flow. Its Disable therefore lands on `enabled`, the switch the schema
72
+ // declares and the checkout reads, rather than on the provider block the
73
+ // siblings turn off.
74
+ coinbase: {
75
+ label: 'Coinbase Commerce',
76
+ url: 'https://commerce.coinbase.com/settings/security',
77
+ instructions: 'Open the brand\'s Coinbase Commerce account, then go to Settings → Security → API keys.',
78
+ secret: 'COINBASE_COMMERCE_API_KEY',
79
+ disablePath: 'payment.providers.coinbase.enabled',
80
+ fields: [],
81
+ },
82
+ };
83
+
84
+ /**
85
+ * Run the credential-entry flow for one provider. Returns true when
86
+ * credentials were landed (config + .env + process.env), false otherwise.
87
+ *
88
+ * @param {Object} context - Service context (brandConfig, brandRoot, options)
89
+ * @param {string} name - 'stripe' | 'paypal' | 'chargebee' | 'coinbase'
90
+ */
91
+ async function providerSetupFlow(context, name) {
92
+ if (!canPrompt(context.options)) {
93
+ return false;
94
+ }
95
+
96
+ const provider = PROVIDERS[name];
97
+ // Where Disable lands `false`. The provider BLOCK is the switch for the ones
98
+ // whose public data enables them; a provider carrying its own switch names it
99
+ // (coinbase's `enabled`, #642), so the off state is the one shape the schema
100
+ // declares and every reader already gates on.
101
+ const disablePath = provider.disablePath || `payment.providers.${name}`;
102
+
103
+ // The uniform gate — Disable lands `payment.providers.<name>: false`
104
+ const action = await confirmSetup(context, {
105
+ label: provider.label,
106
+ instructions: [provider.instructions, `URL: ${chalk.cyan(provider.url)}`],
107
+ disablePath,
108
+ });
109
+ if (action !== 'yes') {
110
+ return false;
111
+ }
112
+
113
+ // The public halves land in omega.json5; the dashboard is opened by the
114
+ // secret ask below (Enter-gated, the house rule) — one page, both keys.
115
+ const configEdits = {};
116
+ for (const field of provider.fields) {
117
+ const value = (await input({ message: field.message, validate: field.validate })).trim();
118
+ configEdits[field.configPath] = value;
119
+ setAtPath(context.brandConfig, field.configPath, value);
120
+ }
121
+ writeBrandConfig(context, configEdits);
122
+
123
+ // The secret half through the shared helper — the gate already ran, so it
124
+ // goes straight to the guided paste, the brand .env, and process.env
125
+ const gate = await requestServiceInput(context, serviceInputSpec('payment', {
126
+ names: [provider.secret],
127
+ label: provider.label,
128
+ gate: false,
129
+ }));
130
+
131
+ return gate === null;
132
+ }
133
+
134
+ module.exports = { providerSetupFlow };
@@ -0,0 +1,152 @@
1
+ /**
2
+ * Stripe API wrapper — the official SDK behind the method surface the
3
+ * payment operations actually use (accounts, products, prices, webhook
4
+ * endpoints). omega-manager's wrapper also carried test clocks, customers,
5
+ * subscriptions, and Radar-rule methods; the first three ride the
6
+ * testing-live port and the Radar methods were dead code (Stripe has no
7
+ * Radar rules API — the stripe-radar operation is manual guidance).
8
+ */
9
+ const Stripe = require('stripe');
10
+
11
+ class StripeAPI {
12
+ constructor(secretKey) {
13
+ this.stripe = new Stripe(secretKey);
14
+ }
15
+
16
+ /**
17
+ * Retrieve the current Stripe account
18
+ */
19
+ async getAccount() {
20
+ return this.stripe.accounts.retrieve();
21
+ }
22
+
23
+ /**
24
+ * Update a Stripe account's settings
25
+ */
26
+ async updateAccount(accountId, updates) {
27
+ return this.stripe.accounts.update(accountId, updates);
28
+ }
29
+
30
+ /**
31
+ * Retrieve a product by ID
32
+ */
33
+ async getProduct(productId) {
34
+ return this.stripe.products.retrieve(productId);
35
+ }
36
+
37
+ /**
38
+ * Create a Stripe product with full brand/product details
39
+ */
40
+ async createProduct({ name, brandId, productId, description, images, url }) {
41
+ const params = {
42
+ name,
43
+ metadata: { brandId, productId },
44
+ };
45
+
46
+ if (description) {
47
+ params.description = description;
48
+ }
49
+ if (images?.length) {
50
+ params.images = images;
51
+ }
52
+ if (url) {
53
+ params.url = url;
54
+ }
55
+
56
+ return this.stripe.products.create(params);
57
+ }
58
+
59
+ /**
60
+ * Update an existing Stripe product
61
+ */
62
+ async updateProduct(stripeProductId, updates) {
63
+ return this.stripe.products.update(stripeProductId, updates);
64
+ }
65
+
66
+ /**
67
+ * List all products (auto-paginates)
68
+ */
69
+ async listAllProducts() {
70
+ const products = [];
71
+ for await (const product of this.stripe.products.list({ limit: 100 })) {
72
+ products.push(product);
73
+ }
74
+ return products;
75
+ }
76
+
77
+ /**
78
+ * List all prices for a product (auto-paginates)
79
+ */
80
+ async listPricesForProduct(productId) {
81
+ const prices = [];
82
+ for await (const price of this.stripe.prices.list({ product: productId, limit: 100 })) {
83
+ prices.push(price);
84
+ }
85
+ return prices;
86
+ }
87
+
88
+ /**
89
+ * Create a recurring price (monthly or annually)
90
+ */
91
+ async createRecurringPrice(productId, amount, interval, currency = 'usd') {
92
+ return this.stripe.prices.create({
93
+ product: productId,
94
+ unit_amount: Math.round(amount * 100), // Stripe uses cents
95
+ currency,
96
+ recurring: {
97
+ interval: { annually: 'year', monthly: 'month', weekly: 'week', daily: 'day' }[interval] || 'month',
98
+ },
99
+ });
100
+ }
101
+
102
+ /**
103
+ * Create a one-time price
104
+ */
105
+ async createOneTimePrice(productId, amount, currency = 'usd') {
106
+ return this.stripe.prices.create({
107
+ product: productId,
108
+ unit_amount: Math.round(amount * 100),
109
+ currency,
110
+ });
111
+ }
112
+
113
+ /**
114
+ * Archive a price (set active: false). Stripe does not support deleting prices.
115
+ */
116
+ async archivePrice(priceId) {
117
+ return this.stripe.prices.update(priceId, { active: false });
118
+ }
119
+
120
+ /**
121
+ * List all webhook endpoints on this account
122
+ */
123
+ async listWebhookEndpoints() {
124
+ return this.stripe.webhookEndpoints.list({ limit: 100 });
125
+ }
126
+
127
+ /**
128
+ * Create a webhook endpoint
129
+ */
130
+ async createWebhookEndpoint(url, enabledEvents) {
131
+ return this.stripe.webhookEndpoints.create({
132
+ url,
133
+ enabled_events: enabledEvents,
134
+ });
135
+ }
136
+
137
+ /**
138
+ * Update a webhook endpoint ({ enabled_events }, { disabled }, etc.)
139
+ */
140
+ async updateWebhookEndpoint(webhookId, params) {
141
+ return this.stripe.webhookEndpoints.update(webhookId, params);
142
+ }
143
+
144
+ /**
145
+ * Delete a webhook endpoint
146
+ */
147
+ async deleteWebhookEndpoint(webhookId) {
148
+ return this.stripe.webhookEndpoints.del(webhookId);
149
+ }
150
+ }
151
+
152
+ module.exports = { StripeAPI };
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Ensure the GitHub org profile matches the brand — display name, support
3
+ * email, billing email, description (160-char org limit), blog URL, and
4
+ * location (only when github.location is configured; omega-manager hardcoded
5
+ * a country — company/brand config owns that choice now).
6
+ *
7
+ * Skipped entirely for shared orgs (filtered in the service setup).
8
+ */
9
+ const chalk = require('chalk').default;
10
+ const { dryRunPlan } = require('../../../lib/run-gates.js');
11
+
12
+ module.exports = async function ensureOrg(context) {
13
+ const { brandConfig, options = {}, githubApi: api } = context;
14
+
15
+ const github = brandConfig.repo?.providers?.github;
16
+ const org = api.getOrg(github.org);
17
+
18
+ if (!org) {
19
+ console.log(` ${chalk.dim(`⊘ ${github.org} is not an organization — org-level settings don't apply`)}`);
20
+ return { status: 'success', output: { org: { skipped: 'owner is not an organization' } } };
21
+ }
22
+
23
+ const name = brandConfig.brand?.name;
24
+ const domain = (brandConfig.brand?.url || '').replace(/^https?:\/\//, '');
25
+ // GitHub org description has a 160 character limit
26
+ const fullDescription = brandConfig.brand?.description || '';
27
+ const description = fullDescription.length > 160
28
+ ? fullDescription.slice(0, 157) + '...'
29
+ : fullDescription;
30
+
31
+ const supportEmail = `support@${domain}`;
32
+ const desired = {
33
+ name: name || org.name,
34
+ email: supportEmail,
35
+ billing_email: supportEmail,
36
+ description: description || org.description || '',
37
+ blog: `https://${domain}`,
38
+ };
39
+
40
+ if (github.location) {
41
+ desired.location = github.location;
42
+ }
43
+
44
+ // Diff current vs desired — only drifted fields get patched
45
+ const updates = {};
46
+ for (const [key, value] of Object.entries(desired)) {
47
+ if (org[key] !== value) {
48
+ updates[key] = value;
49
+ console.log(` ${key}: "${org[key] || '(none)'}" ${chalk.dim('→')} "${chalk.cyan(value)}"`);
50
+ }
51
+ }
52
+
53
+ if (Object.keys(updates).length === 0) {
54
+ console.log(` ${chalk.green('✓')} Org settings already configured`);
55
+ return { status: 'success' };
56
+ }
57
+
58
+ if (options.dryRun) {
59
+ return dryRunPlan('update org settings', { status: 'success', output: { org: { planned: Object.keys(updates) } } });
60
+ }
61
+
62
+ try {
63
+ api.updateOrg(github.org, updates);
64
+ console.log(` ${chalk.green('✓')} Org settings updated`);
65
+ return { status: 'success', output: { org: { updated: Object.keys(updates) } } };
66
+ } catch (error) {
67
+ console.log(` ${chalk.red('✗')} Failed to update org${chalk.dim(`: ${error.message}`)}`);
68
+ return { status: 'error', error: error.message };
69
+ }
70
+ };