@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.
- package/.claude-plugin/marketplace.json +14 -0
- package/LICENSE +98 -0
- package/README.md +165 -0
- package/bin/omega +2 -0
- package/bin/omg +2 -0
- package/claude-plugin/.claude-plugin/plugin.json +11 -0
- package/claude-plugin/.mcp.json +9 -0
- package/claude-plugin/README.md +139 -0
- package/claude-plugin/hooks/gate/mark.sh +58 -0
- package/claude-plugin/hooks/gate/run.sh +97 -0
- package/claude-plugin/hooks/guard/run.sh +249 -0
- package/claude-plugin/hooks/hooks.json +63 -0
- package/claude-plugin/hooks/inject/run.sh +127 -0
- package/claude-plugin/hooks/lib/omega-gate.sh +20 -0
- package/claude-plugin/hooks/lib/omega-scope.sh +41 -0
- package/claude-plugin/hooks/lib/omega-skills.sh +209 -0
- package/claude-plugin/hooks/quality/run.sh +132 -0
- package/claude-plugin/hooks/shape/run.sh +45 -0
- package/claude-plugin/mcp-router-launch.js +29 -0
- package/claude-plugin/skills/README.md +48 -0
- package/claude-plugin/skills/accessibility/SKILL.md +31 -0
- package/claude-plugin/skills/analytics/SKILL.md +30 -0
- package/claude-plugin/skills/backend/SKILL.md +25 -0
- package/claude-plugin/skills/brandcheck/SKILL.md +29 -0
- package/claude-plugin/skills/browser/SKILL.md +64 -0
- package/claude-plugin/skills/client/SKILL.md +24 -0
- package/claude-plugin/skills/desktop/SKILL.md +25 -0
- package/claude-plugin/skills/extension/SKILL.md +25 -0
- package/claude-plugin/skills/main/SKILL.md +54 -0
- package/claude-plugin/skills/manager/SKILL.md +25 -0
- package/claude-plugin/skills/seo/SKILL.md +36 -0
- package/claude-plugin/skills/theme/SKILL.md +33 -0
- package/claude-plugin/skills/web/SKILL.md +29 -0
- package/dist/cli-run.js +34 -0
- package/dist/cli.js +29 -0
- package/dist/commands/build.js +17 -0
- package/dist/commands/clean.js +16 -0
- package/dist/commands/company.js +46 -0
- package/dist/commands/deploy.js +143 -0
- package/dist/commands/dev.js +437 -0
- package/dist/commands/devlog.js +25 -0
- package/dist/commands/help.js +48 -0
- package/dist/commands/manage.js +53 -0
- package/dist/commands/migrate.js +76 -0
- package/dist/commands/onboard.js +31 -0
- package/dist/commands/pipeline.js +319 -0
- package/dist/commands/test.js +380 -0
- package/dist/commands/update.js +128 -0
- package/dist/commands/version.js +8 -0
- package/dist/company-init.js +167 -0
- package/dist/company.js +283 -0
- package/dist/config.js +1359 -0
- package/dist/devlog/index.js +226 -0
- package/dist/devlog/lib/collect-commits.js +136 -0
- package/dist/devlog/lib/generate-post.js +201 -0
- package/dist/devlog/lib/ghostii.js +122 -0
- package/dist/devlog/lib/project-map.js +98 -0
- package/dist/devlog/lib/publish-website.js +88 -0
- package/dist/index.js +45 -0
- package/dist/lib/agents-md.js +201 -0
- package/dist/lib/analytics-secret.js +22 -0
- package/dist/lib/argv.js +21 -0
- package/dist/lib/auth-admin.js +120 -0
- package/dist/lib/automation-client.js +210 -0
- package/dist/lib/backend-marketing.js +49 -0
- package/dist/lib/brand.js +240 -0
- package/dist/lib/bundle-id.js +53 -0
- package/dist/lib/claude-settings.js +125 -0
- package/dist/lib/company-scaffold.js +213 -0
- package/dist/lib/company.js +227 -0
- package/dist/lib/config-flow.js +350 -0
- package/dist/lib/config-write.js +41 -0
- package/dist/lib/custom-target.js +75 -0
- package/dist/lib/domain-utils.js +19 -0
- package/dist/lib/duration.js +39 -0
- package/dist/lib/env-order.js +236 -0
- package/dist/lib/env-secret.js +78 -0
- package/dist/lib/firestore-rest.js +326 -0
- package/dist/lib/framework-bin.js +156 -0
- package/dist/lib/gitignore.js +63 -0
- package/dist/lib/google-auth.js +495 -0
- package/dist/lib/google-token.js +66 -0
- package/dist/lib/jwt.js +31 -0
- package/dist/lib/legacy-oauth.js +59 -0
- package/dist/lib/node-version.js +127 -0
- package/dist/lib/owner-plan.js +78 -0
- package/dist/lib/package-scripts.js +152 -0
- package/dist/lib/preflight.js +470 -0
- package/dist/lib/product-create.js +144 -0
- package/dist/lib/run-command.js +74 -0
- package/dist/lib/run-gates.js +70 -0
- package/dist/lib/run-output.js +42 -0
- package/dist/lib/run-summary.js +384 -0
- package/dist/lib/scaffold.js +427 -0
- package/dist/lib/service-input.js +207 -0
- package/dist/lib/service-runner.js +466 -0
- package/dist/lib/stale.js +24 -0
- package/dist/lib/target-selection.js +155 -0
- package/dist/lib/verb-fanout.js +128 -0
- package/dist/lib/verify-live.js +188 -0
- package/dist/manage.js +311 -0
- package/dist/omega-bin.js +7 -0
- package/dist/onboard.js +532 -0
- package/dist/services/account/ensure/users.js +259 -0
- package/dist/services/account/index.js +97 -0
- package/dist/services/account/lib/backend-client.js +107 -0
- package/dist/services/account/lib/password.js +36 -0
- package/dist/services/account/lib/resolve-password.js +100 -0
- package/dist/services/advertising/ensure/sites.js +101 -0
- package/dist/services/advertising/index.js +101 -0
- package/dist/services/advertising/lib/adsense-api.js +41 -0
- package/dist/services/ai/ensure/keys.js +21 -0
- package/dist/services/ai/index.js +36 -0
- package/dist/services/analytics/ensure/google-firebase-link.js +230 -0
- package/dist/services/analytics/ensure/google-streams.js +256 -0
- package/dist/services/analytics/ensure/meta-pixel.js +22 -0
- package/dist/services/analytics/ensure/tiktok-pixel.js +22 -0
- package/dist/services/analytics/index.js +134 -0
- package/dist/services/analytics/lib/analytics-api.js +156 -0
- package/dist/services/analytics/lib/meta-api.js +83 -0
- package/dist/services/analytics/lib/pixel-account.js +78 -0
- package/dist/services/analytics/lib/pixel-provision.js +152 -0
- package/dist/services/analytics/lib/pixel-specs.js +57 -0
- package/dist/services/analytics/lib/pixel-token.js +88 -0
- package/dist/services/analytics/lib/property-flow.js +77 -0
- package/dist/services/analytics/lib/tiktok-api.js +157 -0
- package/dist/services/analytics/lib/tiktok-auth.js +153 -0
- package/dist/services/assets/ensure/logo-gen.js +68 -0
- package/dist/services/assets/index.js +109 -0
- package/dist/services/assets/lib/assets-config.js +168 -0
- package/dist/services/assets/lib/brandmark-api.js +160 -0
- package/dist/services/assets/lib/derived.js +113 -0
- package/dist/services/assets/lib/font-loader.js +67 -0
- package/dist/services/assets/lib/reconcile.js +122 -0
- package/dist/services/assets/lib/reset.js +118 -0
- package/dist/services/assets/lib/svg-logo-generator.js +154 -0
- package/dist/services/assets/lib/svg-to-black.js +32 -0
- package/dist/services/assets/write/favicons.js +82 -0
- package/dist/services/assets/write/icons.js +64 -0
- package/dist/services/assets/write/process.js +96 -0
- package/dist/services/assets/write/reconcile.js +30 -0
- package/dist/services/assets/write/social-icons.js +108 -0
- package/dist/services/assets/write/templates.js +345 -0
- package/dist/services/bookmark/ensure/sync.js +255 -0
- package/dist/services/bookmark/index.js +17 -0
- package/dist/services/campaigns/ensure/contact-person.js +40 -0
- package/dist/services/campaigns/ensure/custom-fields.js +84 -0
- package/dist/services/campaigns/ensure/domain-auth.js +92 -0
- package/dist/services/campaigns/ensure/event-webhook.js +89 -0
- package/dist/services/campaigns/ensure/link-branding.js +187 -0
- package/dist/services/campaigns/ensure/list.js +50 -0
- package/dist/services/campaigns/ensure/segments.js +109 -0
- package/dist/services/campaigns/ensure/sender-identity.js +153 -0
- package/dist/services/campaigns/ensure/unsubscribe-groups.js +116 -0
- package/dist/services/campaigns/index.js +79 -0
- package/dist/services/campaigns/lib/dns-sync.js +81 -0
- package/dist/services/campaigns/lib/segment-query.js +138 -0
- package/dist/services/campaigns/lib/sendgrid-api.js +287 -0
- package/dist/services/captcha/ensure/site-key.js +83 -0
- package/dist/services/captcha/index.js +78 -0
- package/dist/services/captcha/lib/console-url.js +45 -0
- package/dist/services/captcha/lib/recaptcha-api.js +36 -0
- package/dist/services/certificates/ensure/api-key.js +22 -0
- package/dist/services/certificates/ensure/bundle-ids.js +115 -0
- package/dist/services/certificates/ensure/certificates.js +187 -0
- package/dist/services/certificates/ensure/profiles.js +143 -0
- package/dist/services/certificates/index.js +225 -0
- package/dist/services/certificates/lib/apple-api.js +183 -0
- package/dist/services/certificates/lib/certificate-manager.js +252 -0
- package/dist/services/certificates/lib/identifier-manager.js +107 -0
- package/dist/services/certificates/lib/keychain.js +135 -0
- package/dist/services/certificates/lib/manual-walkthrough.js +165 -0
- package/dist/services/certificates/lib/profile-manager.js +115 -0
- package/dist/services/chat/data/baseline-knowledge.md +96 -0
- package/dist/services/chat/ensure/chat.js +106 -0
- package/dist/services/chat/ensure/user.js +45 -0
- package/dist/services/chat/index.js +139 -0
- package/dist/services/chat/lib/baseline-knowledge.js +137 -0
- package/dist/services/cloud/ensure/authentication.js +267 -0
- package/dist/services/cloud/ensure/billing.js +120 -0
- package/dist/services/cloud/ensure/cloud-messaging.js +105 -0
- package/dist/services/cloud/ensure/database.js +60 -0
- package/dist/services/cloud/ensure/firestore.js +79 -0
- package/dist/services/cloud/ensure/functions.js +49 -0
- package/dist/services/cloud/ensure/hosting.js +398 -0
- package/dist/services/cloud/ensure/oauth-consent.js +248 -0
- package/dist/services/cloud/ensure/project-settings.js +72 -0
- package/dist/services/cloud/ensure/sdk-config.js +95 -0
- package/dist/services/cloud/ensure/service-account.js +152 -0
- package/dist/services/cloud/ensure/services.js +103 -0
- package/dist/services/cloud/ensure/storage.js +47 -0
- package/dist/services/cloud/index.js +130 -0
- package/dist/services/cloud/lib/access-heal.js +130 -0
- package/dist/services/cloud/lib/firebase-api.js +662 -0
- package/dist/services/cloud/lib/project-flow.js +102 -0
- package/dist/services/directory/ensure/entry.js +48 -0
- package/dist/services/directory/index.js +64 -0
- package/dist/services/directory/lib/blocks.js +104 -0
- package/dist/services/disperse/index.js +45 -0
- package/dist/services/disperse/write/certs.js +117 -0
- package/dist/services/domain/ensure/nameservers.js +179 -0
- package/dist/services/domain/index.js +69 -0
- package/dist/services/domain/lib/namecheap-api.js +167 -0
- package/dist/services/domain/lib/registrars.js +46 -0
- package/dist/services/domain/lib/whitelist-walkthrough.js +76 -0
- package/dist/services/edge/ensure/cache-rules.js +105 -0
- package/dist/services/edge/ensure/dns-records.js +304 -0
- package/dist/services/edge/ensure/email-routing.js +292 -0
- package/dist/services/edge/ensure/rules-configuration.js +98 -0
- package/dist/services/edge/ensure/rules-managed-transforms.js +101 -0
- package/dist/services/edge/ensure/rules-redirect.js +107 -0
- package/dist/services/edge/ensure/rules-response-headers.js +90 -0
- package/dist/services/edge/ensure/rules-security.js +142 -0
- package/dist/services/edge/ensure/speed-scheduled-tests.js +98 -0
- package/dist/services/edge/ensure/workers.js +219 -0
- package/dist/services/edge/ensure/zone-settings.js +108 -0
- package/dist/services/edge/ensure/zone.js +183 -0
- package/dist/services/edge/index.js +73 -0
- package/dist/services/edge/lib/cloudflare-api.js +84 -0
- package/dist/services/edge/lib/dns-records-helpers.js +518 -0
- package/dist/services/edge/lib/read-cache.js +16 -0
- package/dist/services/edge/lib/ruleset-helper.js +108 -0
- package/dist/services/edge/workers/omega-api-proxy.js +43 -0
- package/dist/services/email/data/baseline-filter.md +4 -0
- package/dist/services/email/data/baseline-knowledge.md +86 -0
- package/dist/services/email/ensure/agent.js +107 -0
- package/dist/services/email/ensure/user.js +45 -0
- package/dist/services/email/index.js +138 -0
- package/dist/services/email/lib/baseline.js +82 -0
- package/dist/services/email/lib/knowledge-file.js +53 -0
- package/dist/services/forms/ensure/form.js +46 -0
- package/dist/services/forms/ensure/user.js +45 -0
- package/dist/services/forms/index.js +138 -0
- package/dist/services/migrations/ensure/notifications.js +189 -0
- package/dist/services/migrations/ensure/orders.js +34 -0
- package/dist/services/migrations/ensure/payment-provider.js +132 -0
- package/dist/services/migrations/ensure/payments-intents.js +34 -0
- package/dist/services/migrations/ensure/state-retirement.js +266 -0
- package/dist/services/migrations/ensure/targets-rename.js +124 -0
- package/dist/services/migrations/ensure/users.js +1176 -0
- package/dist/services/migrations/index.js +101 -0
- package/dist/services/migrations/lib/attribution-touch.js +64 -0
- package/dist/services/migrations/lib/ensure-metadata.js +144 -0
- package/dist/services/migrations/lib/migration-runner.js +473 -0
- package/dist/services/migrations/lib/sanitize-strings.js +112 -0
- package/dist/services/migrations/lib/schema-validator.js +154 -0
- package/dist/services/monitoring/ensure/dsn.js +54 -0
- package/dist/services/monitoring/ensure/projects.js +135 -0
- package/dist/services/monitoring/index.js +54 -0
- package/dist/services/monitoring/lib/sentry-api.js +94 -0
- package/dist/services/newsletter/ensure/custom-fields.js +90 -0
- package/dist/services/newsletter/ensure/publication.js +94 -0
- package/dist/services/newsletter/ensure/segments.js +140 -0
- package/dist/services/newsletter/ensure/webhook.js +108 -0
- package/dist/services/newsletter/index.js +64 -0
- package/dist/services/newsletter/lib/beehiiv-api.js +124 -0
- package/dist/services/newsletter/lib/segment-automation.js +577 -0
- package/dist/services/payment/ensure/chargebee-account.js +30 -0
- package/dist/services/payment/ensure/chargebee-products.js +359 -0
- package/dist/services/payment/ensure/chargebee-webhook.js +113 -0
- package/dist/services/payment/ensure/paypal-account.js +36 -0
- package/dist/services/payment/ensure/paypal-products.js +374 -0
- package/dist/services/payment/ensure/paypal-webhook.js +128 -0
- package/dist/services/payment/ensure/stripe-account.js +93 -0
- package/dist/services/payment/ensure/stripe-disputes.js +56 -0
- package/dist/services/payment/ensure/stripe-products.js +245 -0
- package/dist/services/payment/ensure/stripe-radar.js +74 -0
- package/dist/services/payment/ensure/stripe-webhook.js +130 -0
- package/dist/services/payment/index.js +163 -0
- package/dist/services/payment/lib/chargebee-api.js +338 -0
- package/dist/services/payment/lib/payment-utils.js +116 -0
- package/dist/services/payment/lib/paypal-api.js +354 -0
- package/dist/services/payment/lib/provider-setup.js +134 -0
- package/dist/services/payment/lib/stripe-api.js +152 -0
- package/dist/services/repo/ensure/org.js +70 -0
- package/dist/services/repo/ensure/pages.js +72 -0
- package/dist/services/repo/ensure/repo.js +90 -0
- package/dist/services/repo/index.js +52 -0
- package/dist/services/repo/lib/github-api.js +196 -0
- package/dist/services/search/ensure/ga-link.js +57 -0
- package/dist/services/search/ensure/property.js +137 -0
- package/dist/services/search/ensure/sitemaps.js +70 -0
- package/dist/services/search/index.js +61 -0
- package/dist/services/search/lib/search-console-api.js +92 -0
- package/dist/services/seo/ensure/github-repos.js +271 -0
- package/dist/services/seo/index.js +55 -0
- package/dist/services/seo/lib/gh-api.js +161 -0
- package/dist/services/seo/templates/developer-tool/.github/workflows/maintenance.yml +25 -0
- package/dist/services/seo/templates/developer-tool/.nvmrc +1 -0
- package/dist/services/seo/templates/developer-tool/_README.md.js +121 -0
- package/dist/services/seo/templates/developer-tool/_package.json.js +33 -0
- package/dist/services/seo/templates/developer-tool/src/index.js +120 -0
- package/dist/services/seo/templates/index.js +57 -0
- package/dist/services/server/ensure/brands.js +63 -0
- package/dist/services/server/index.js +42 -0
- package/dist/services/testing/ensure/target-checks.js +97 -0
- package/dist/services/testing/index.js +11 -0
- package/dist/services/testing/lib/checks.js +467 -0
- package/dist/services/update/index.js +20 -0
- package/dist/services/update/lib/cache.js +59 -0
- package/dist/services/update/lib/fingerprint.js +157 -0
- package/dist/services/update/write/targets.js +206 -0
- package/dist/services/workspace/ensure/agents.js +42 -0
- package/dist/services/workspace/ensure/claude-settings.js +34 -0
- package/dist/services/workspace/ensure/config.js +54 -0
- package/dist/services/workspace/ensure/defaults.js +60 -0
- package/dist/services/workspace/ensure/env-keys.js +55 -0
- package/dist/services/workspace/ensure/env-order.js +66 -0
- package/dist/services/workspace/ensure/env-rules.js +97 -0
- package/dist/services/workspace/ensure/gitignore.js +18 -0
- package/dist/services/workspace/ensure/scripts.js +126 -0
- package/dist/services/workspace/ensure/structure.js +97 -0
- package/dist/services/workspace/ensure/translation-sdk.js +148 -0
- package/dist/services/workspace/ensure/workflows.js +54 -0
- package/dist/services/workspace/index.js +8 -0
- package/dist/vendor/account/engine.js +182 -0
- package/dist/vendor/account/features.js +220 -0
- package/dist/vendor/account/index.js +53 -0
- package/dist/vendor/account/schema.js +272 -0
- package/dist/vendor/account/subscription.js +38 -0
- package/dist/vendor/config/company.js +31 -0
- package/dist/vendor/config/defaults.js +173 -0
- package/dist/vendor/config/demo.js +18 -0
- package/dist/vendor/config/desktop-artifacts.js +110 -0
- package/dist/vendor/config/edit.js +769 -0
- package/dist/vendor/config/env-delivery.js +145 -0
- package/dist/vendor/config/env-rules.js +93 -0
- package/dist/vendor/config/env-schema.js +1078 -0
- package/dist/vendor/config/env.js +445 -0
- package/dist/vendor/config/hooks.js +97 -0
- package/dist/vendor/config/index.js +237 -0
- package/dist/vendor/config/instances.js +208 -0
- package/dist/vendor/config/load.js +490 -0
- package/dist/vendor/config/merge.js +68 -0
- package/dist/vendor/config/order.js +139 -0
- package/dist/vendor/config/ports.js +374 -0
- package/dist/vendor/config/providers.js +32 -0
- package/dist/vendor/config/repo.js +142 -0
- package/dist/vendor/config/retired-keys.js +430 -0
- package/dist/vendor/config/schema.js +1610 -0
- package/dist/vendor/config/secrets.js +50 -0
- package/dist/vendor/config/seed.js +34 -0
- package/dist/vendor/config/site-global.js +205 -0
- package/dist/vendor/config/validate.js +554 -0
- package/dist/vendor/config/winback.js +61 -0
- package/dist/vendor/devkit/attach-log-file.js +262 -0
- package/dist/vendor/devkit/certs.js +199 -0
- package/dist/vendor/devkit/ci-workflows.js +520 -0
- package/dist/vendor/devkit/cli-router.js +156 -0
- package/dist/vendor/devkit/command-path.js +46 -0
- package/dist/vendor/devkit/deploy-record.js +180 -0
- package/dist/vendor/devkit/flows.js +317 -0
- package/dist/vendor/devkit/local-https.js +360 -0
- package/dist/vendor/devkit/local.js +1905 -0
- package/dist/vendor/devkit/logger.js +128 -0
- package/dist/vendor/devkit/omega-bin.js +345 -0
- package/dist/vendor/devkit/prompt.js +187 -0
- package/dist/vendor/devkit/safe-install.js +18 -0
- package/dist/vendor/devkit/stop-signals.js +28 -0
- package/dist/vendor/devkit/test/scope.js +162 -0
- package/dist/vendor/devkit/translate/cache.js +84 -0
- package/dist/vendor/devkit/translate/engine.js +243 -0
- package/dist/vendor/devkit/translate/index.js +49 -0
- package/dist/vendor/devkit/translate/languages.js +134 -0
- package/dist/vendor/devkit/translate/providers.js +188 -0
- package/dist/vendor/devkit/update.js +569 -0
- package/docs/AGENTS.md +200 -0
- package/docs/account.md +45 -0
- package/docs/advertising.md +46 -0
- package/docs/ai.md +34 -0
- package/docs/analytics.md +69 -0
- package/docs/assets.md +57 -0
- package/docs/bookmark.md +26 -0
- package/docs/brand.md +151 -0
- package/docs/campaigns.md +96 -0
- package/docs/captcha.md +46 -0
- package/docs/certificates.md +68 -0
- package/docs/chat.md +47 -0
- package/docs/cloud.md +110 -0
- package/docs/company.md +64 -0
- package/docs/directory.md +140 -0
- package/docs/disperse.md +46 -0
- package/docs/domain.md +56 -0
- package/docs/edge.md +234 -0
- package/docs/email.md +42 -0
- package/docs/forms.md +48 -0
- package/docs/index.md +109 -0
- package/docs/migration.md +203 -0
- package/docs/migrations.md +56 -0
- package/docs/monitoring.md +41 -0
- package/docs/newsletter.md +48 -0
- package/docs/payment.md +83 -0
- package/docs/repo.md +48 -0
- package/docs/search.md +44 -0
- package/docs/seo.md +34 -0
- package/docs/server.md +37 -0
- package/docs/shared/agent-docs.md +89 -0
- package/docs/shared/analytics.md +612 -0
- package/docs/shared/brands.md +51 -0
- package/docs/shared/breaking-changes.md +497 -0
- package/docs/shared/config.md +1387 -0
- package/docs/shared/deploys.md +215 -0
- package/docs/shared/icons.md +201 -0
- package/docs/shared/local-dev.md +147 -0
- package/docs/shared/logging.md +202 -0
- package/docs/shared/monitoring.md +153 -0
- package/docs/shared/publishing.md +183 -0
- package/docs/shared/rulings.md +34 -0
- package/docs/shared/testing.md +147 -0
- package/docs/shared/theming.md +604 -0
- package/docs/shared/translation.md +291 -0
- package/docs/shared/updates.md +61 -0
- package/docs/testing.md +34 -0
- package/docs/update.md +36 -0
- package/docs/workspace.md +64 -0
- package/package.json +88 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Devlog backlink SSOT — map every known brand repo to its public project
|
|
3
|
+
* (name + URL) so the writer can link each mentioned repo to the product it
|
|
4
|
+
* belongs to. Repos not in the map are treated as standalone and linked to
|
|
5
|
+
* GitHub instead.
|
|
6
|
+
*
|
|
7
|
+
* In the brand-monorepo world every brand is ONE repo, addressed by
|
|
8
|
+
* `@omega.js/config`'s `brandRepo` — the typed `repo.providers.github.repo` slug
|
|
9
|
+
* (whose owner half wins when it carries one), else `<brand.id>-omega` under
|
|
10
|
+
* `repo.providers.github.org`, the ONE derivation the github service reads too;
|
|
11
|
+
* omega-manager's per-target + subdomain repo fan-out collapsed at the
|
|
12
|
+
* redesign. Brands without a repo.providers.github.org are skipped (the github service
|
|
13
|
+
* skips them too).
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const { brandRepo: deriveBrandRepo, brandRepoName } = require('../../vendor/config/index.js');
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Resolve a loaded brand's repo identity, or null when it has none.
|
|
20
|
+
*
|
|
21
|
+
* @param {object} brand - Loaded brand (lib/brand.js loadBrand shape)
|
|
22
|
+
* @returns {{ owner: string, repo: string }|null}
|
|
23
|
+
*/
|
|
24
|
+
function brandRepo(brand) {
|
|
25
|
+
const github = brand.config.repo?.providers?.github;
|
|
26
|
+
|
|
27
|
+
if (!github.org) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// BOTH halves from the one derivation: an `owner/name` slug houses the repo
|
|
32
|
+
// under its own owner. The loaded brand's own id stands in for a config that
|
|
33
|
+
// names none.
|
|
34
|
+
const { owner, name } = deriveBrandRepo(brand.config);
|
|
35
|
+
|
|
36
|
+
return { owner, repo: name || brandRepoName({ brand: { id: brand.id } }) };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Build the repo → project map across every loaded brand.
|
|
41
|
+
*
|
|
42
|
+
* @param {Array} brands - Loaded brands
|
|
43
|
+
* @param {object} [params] - { excludeRepos }
|
|
44
|
+
* @returns {Object<string, {project: string, url: string}>} repoName → project
|
|
45
|
+
*/
|
|
46
|
+
function buildProjectMap(brands, { excludeRepos = [] } = {}) {
|
|
47
|
+
const map = {};
|
|
48
|
+
|
|
49
|
+
for (const brand of brands) {
|
|
50
|
+
const identity = brandRepo(brand);
|
|
51
|
+
|
|
52
|
+
if (!identity || excludeRepos.includes(identity.repo)) {
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
map[identity.repo] = {
|
|
57
|
+
project: brand.config.brand?.name || brand.id,
|
|
58
|
+
url: brand.config.brand?.url || '',
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return map;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Build the complete brand repo list. The brand configs are the SSOT for
|
|
67
|
+
* where every repo lives, so scanning is never limited to the hand-maintained
|
|
68
|
+
* `orgs` list — that list only supplements this with non-brand repos
|
|
69
|
+
* (frameworks, tooling).
|
|
70
|
+
*
|
|
71
|
+
* @param {Array} brands - Loaded brands
|
|
72
|
+
* @param {object} [params] - { excludeRepos }
|
|
73
|
+
* @returns {Array<{ owner: string, repo: string }>} Unique owner/repo pairs
|
|
74
|
+
*/
|
|
75
|
+
function buildBrandRepos(brands, { excludeRepos = [] } = {}) {
|
|
76
|
+
const seen = new Set();
|
|
77
|
+
const repos = [];
|
|
78
|
+
|
|
79
|
+
for (const brand of brands) {
|
|
80
|
+
const identity = brandRepo(brand);
|
|
81
|
+
|
|
82
|
+
if (!identity || excludeRepos.includes(identity.repo)) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const key = `${identity.owner}/${identity.repo}`.toLowerCase();
|
|
87
|
+
if (seen.has(key)) {
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
seen.add(key);
|
|
92
|
+
repos.push(identity);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return repos;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
module.exports = { buildProjectMap, buildBrandRepos };
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Devlog publish stage — write the post into the brand's website target and
|
|
3
|
+
* push it live. In the brand-monorepo world the website is a target INSIDE the brand
|
|
4
|
+
* repo (targets/{website}/src), so the commit lands in the brand monorepo itself.
|
|
5
|
+
* Publishing IS the push — the site auto-builds and deploys on push. Only the
|
|
6
|
+
* post file is committed; unrelated dirty files are untouched.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const { execSync } = require('node:child_process');
|
|
10
|
+
const { join } = require('node:path');
|
|
11
|
+
|
|
12
|
+
const jetpack = require('fs-jetpack');
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Local YYYY-MM-DD stamp — local (not UTC) so a late-night run never
|
|
16
|
+
* future-dates the post, which the site build would silently skip.
|
|
17
|
+
*
|
|
18
|
+
* @param {Date} date - Date to stamp
|
|
19
|
+
* @returns {string} YYYY-MM-DD
|
|
20
|
+
*/
|
|
21
|
+
function localDateStamp(date) {
|
|
22
|
+
const year = date.getFullYear();
|
|
23
|
+
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
24
|
+
const day = String(date.getDate()).padStart(2, '0');
|
|
25
|
+
|
|
26
|
+
return `${year}-${month}-${day}`;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Render the post file (blueprint front matter + markdown body).
|
|
31
|
+
*
|
|
32
|
+
* @param {object} brandConfig - Merged brand config
|
|
33
|
+
* @param {object} post - Generated post { title, slug, description, tags, categories, body }
|
|
34
|
+
* @returns {string} Full post file contents
|
|
35
|
+
*/
|
|
36
|
+
function renderPostFile(brandConfig, post) {
|
|
37
|
+
return [
|
|
38
|
+
'---',
|
|
39
|
+
'layout: blueprint/blog/post',
|
|
40
|
+
'',
|
|
41
|
+
'post:',
|
|
42
|
+
` title: ${JSON.stringify(post.title)}`,
|
|
43
|
+
` description: ${JSON.stringify(post.description)}`,
|
|
44
|
+
` author: ${brandConfig.brand.id}`,
|
|
45
|
+
` id: ${Math.floor(Date.now() / 1000)}`,
|
|
46
|
+
` tags: ${JSON.stringify(post.tags)}`,
|
|
47
|
+
` categories: ${JSON.stringify(post.categories)}`,
|
|
48
|
+
'---',
|
|
49
|
+
'',
|
|
50
|
+
post.body,
|
|
51
|
+
'',
|
|
52
|
+
].join('\n');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Write the post into the brand's website target, commit only the post file in
|
|
57
|
+
* the brand monorepo, and push.
|
|
58
|
+
*
|
|
59
|
+
* @param {object} params - { brand, post } (brand = lib/brand.js loadBrand shape)
|
|
60
|
+
* @returns {{ postPath: string, url: string }} Written file + eventual live URL
|
|
61
|
+
*/
|
|
62
|
+
function publishToWebsite({ brand, post }) {
|
|
63
|
+
const webTarget = brand.targets.find((entry) => entry.target === 'web');
|
|
64
|
+
|
|
65
|
+
if (!webTarget) {
|
|
66
|
+
throw new Error(`Brand ${brand.id} has no website target under targets/ — devlog's 'website' destination needs one`);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const now = new Date();
|
|
70
|
+
const date = localDateStamp(now);
|
|
71
|
+
const relativePath = join(webTarget.dir, 'src', '_posts', String(now.getFullYear()), brand.config.devlog.providers.ghostii.postPath, `${date}-${post.slug}.md`);
|
|
72
|
+
const postPath = join(brand.root, relativePath);
|
|
73
|
+
|
|
74
|
+
jetpack.write(postPath, renderPostFile(brand.config, post));
|
|
75
|
+
|
|
76
|
+
const git = (args) => execSync(`git ${args}`, { cwd: brand.root, encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] });
|
|
77
|
+
|
|
78
|
+
git(`add "${relativePath}"`);
|
|
79
|
+
git(`commit -m "📦 Omega: Add devlog post ${date}-${post.slug}" -- "${relativePath}"`);
|
|
80
|
+
git('push');
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
postPath,
|
|
84
|
+
url: `${brand.config.brand.url}/blog/${post.slug}`,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
module.exports = { publishToWebsite, renderPostFile };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @omega.js/manager — the OMEGA orchestration engine for brand monorepos.
|
|
3
|
+
* Public surface: the manage runner, the service-runner factory (services
|
|
4
|
+
* and tests build on it), brand loading, and the registry.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { runManage } = require('./manage.js');
|
|
8
|
+
const { createServiceRunner, splitReturn, getOperationHandler } = require('./lib/service-runner.js');
|
|
9
|
+
const { RunSummary } = require('./lib/run-summary.js');
|
|
10
|
+
const { resolveBrandRoot, loadBrand, discoverTargets, targetFromDirName } = require('./lib/brand.js');
|
|
11
|
+
const { writeRunOutput } = require('./lib/run-output.js');
|
|
12
|
+
const {
|
|
13
|
+
SERVICE_ORDER,
|
|
14
|
+
OPERATIONS,
|
|
15
|
+
DEFAULTS,
|
|
16
|
+
DIR_TARGETS,
|
|
17
|
+
TARGET_DIRS,
|
|
18
|
+
templateObject,
|
|
19
|
+
} = require('./config.js');
|
|
20
|
+
|
|
21
|
+
module.exports = {
|
|
22
|
+
// Orchestrator
|
|
23
|
+
runManage,
|
|
24
|
+
|
|
25
|
+
// Service framework
|
|
26
|
+
createServiceRunner,
|
|
27
|
+
splitReturn,
|
|
28
|
+
getOperationHandler,
|
|
29
|
+
RunSummary,
|
|
30
|
+
|
|
31
|
+
// Brand + run output
|
|
32
|
+
resolveBrandRoot,
|
|
33
|
+
loadBrand,
|
|
34
|
+
discoverTargets,
|
|
35
|
+
targetFromDirName,
|
|
36
|
+
writeRunOutput,
|
|
37
|
+
|
|
38
|
+
// Registry
|
|
39
|
+
SERVICE_ORDER,
|
|
40
|
+
OPERATIONS,
|
|
41
|
+
DEFAULTS,
|
|
42
|
+
DIR_TARGETS,
|
|
43
|
+
TARGET_DIRS,
|
|
44
|
+
templateObject,
|
|
45
|
+
};
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Brand agent-docs chain (Ian 2026-07-20, amended 2026-07-27): every brand
|
|
3
|
+
* root carries an AGENTS.md whose FIRST line imports the TOP-LEVEL omega
|
|
4
|
+
* AGENTS.md — the map, the one agent entry — through the scope path
|
|
5
|
+
* `node_modules/@omega.js/AGENTS.md`, plus a one-line CLAUDE.md pointer
|
|
6
|
+
* (`@AGENTS.md`). The scope file is a symlink this service maintains: it
|
|
7
|
+
* resolves the framework monorepo through the installed manager package and
|
|
8
|
+
* links straight at the live top-level map; a published install has no
|
|
9
|
+
* monorepo, so it links at the map the prepare lane vendored into the package
|
|
10
|
+
* (`docs/AGENTS.md`). Idempotent: create when missing, heal a missing/stale
|
|
11
|
+
* first-line import in place, never touch consumer content below the import.
|
|
12
|
+
*/
|
|
13
|
+
const { join, dirname } = require('node:path');
|
|
14
|
+
const fs = require('node:fs');
|
|
15
|
+
const jetpack = require('fs-jetpack');
|
|
16
|
+
|
|
17
|
+
const GUIDE_SUBPATH = 'node_modules/@omega.js/AGENTS.md';
|
|
18
|
+
const IMPORT_LINE = `@${GUIDE_SUBPATH}`;
|
|
19
|
+
const CLAUDE_POINTER = '@AGENTS.md';
|
|
20
|
+
|
|
21
|
+
const SCOPE_PREFIXES = ['', '../', '../../', '../../../'];
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Is this line an import of the framework guide (any relative depth)?
|
|
25
|
+
*
|
|
26
|
+
* @param {string} line - A single file line
|
|
27
|
+
* @returns {boolean}
|
|
28
|
+
*/
|
|
29
|
+
function isImportLine(line) {
|
|
30
|
+
const trimmed = line.trim();
|
|
31
|
+
return trimmed.startsWith('@') && trimmed.endsWith(GUIDE_SUBPATH);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* The @omega.js scope directory serving this brand: the brand's own
|
|
36
|
+
* node_modules normally, an ancestor's when hoisted (npm workspaces).
|
|
37
|
+
*
|
|
38
|
+
* @param {string} brandRoot - Absolute brand monorepo root
|
|
39
|
+
* @returns {{prefix: string, scopeDir: string}|null}
|
|
40
|
+
*/
|
|
41
|
+
function findScope(brandRoot) {
|
|
42
|
+
for (const prefix of SCOPE_PREFIXES) {
|
|
43
|
+
const scopeDir = join(brandRoot, prefix, 'node_modules', '@omega.js');
|
|
44
|
+
if (jetpack.exists(scopeDir) !== 'dir') continue;
|
|
45
|
+
// Only a scope that can back the import counts: the map link is already
|
|
46
|
+
// there, or the manager package is present for ensureGuideLink to resolve
|
|
47
|
+
// it. An empty dir from a partial install would leave the import dangling
|
|
48
|
+
// while the real scope sits a level up (#153).
|
|
49
|
+
if (jetpack.exists(join(scopeDir, 'AGENTS.md')) !== false
|
|
50
|
+
|| jetpack.exists(join(scopeDir, 'manager')) !== false) {
|
|
51
|
+
return { prefix, scopeDir };
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Resolve the import line for THIS brand — the depth that reaches the scope
|
|
59
|
+
* directory holding `@omega.js/AGENTS.md`. Falls back to the canonical
|
|
60
|
+
* brand-local path when nothing is installed yet (pre-install).
|
|
61
|
+
*
|
|
62
|
+
* @param {string} brandRoot - Absolute brand monorepo root
|
|
63
|
+
* @returns {string} - The `@<relative path>` import line
|
|
64
|
+
*/
|
|
65
|
+
function resolveImportLine(brandRoot) {
|
|
66
|
+
const scope = findScope(brandRoot);
|
|
67
|
+
return scope ? `@${scope.prefix}${GUIDE_SUBPATH}` : IMPORT_LINE;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Ensure `node_modules/@omega.js/AGENTS.md` links at the omega map. The
|
|
72
|
+
* installed manager package's real path (the local-era file: symlink) names
|
|
73
|
+
* both candidates, in this order: the monorepo's LIVE map two dirs up, then
|
|
74
|
+
* the copy the prepare lane vendors into the package (`docs/AGENTS.md`, #144).
|
|
75
|
+
* The live map wins wherever it exists, so a locally linked brand never lands
|
|
76
|
+
* on the generated copy sitting in that same monorepo's packages/manager.
|
|
77
|
+
* Neither present (pre-install) → the link is left alone and the step skips.
|
|
78
|
+
*
|
|
79
|
+
* @param {string} brandRoot - Absolute brand monorepo root
|
|
80
|
+
* @returns {'present'|'created'|'healed'|'skipped'} - What happened
|
|
81
|
+
*/
|
|
82
|
+
function ensureGuideLink(brandRoot) {
|
|
83
|
+
const scope = findScope(brandRoot);
|
|
84
|
+
if (!scope) {
|
|
85
|
+
return 'skipped';
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
let mapFile;
|
|
89
|
+
try {
|
|
90
|
+
const managerReal = fs.realpathSync(join(scope.scopeDir, 'manager'));
|
|
91
|
+
mapFile = [
|
|
92
|
+
join(dirname(dirname(managerReal)), 'AGENTS.md'),
|
|
93
|
+
join(managerReal, 'docs', 'AGENTS.md'),
|
|
94
|
+
].find((candidate) => jetpack.exists(candidate) === 'file');
|
|
95
|
+
} catch {
|
|
96
|
+
return 'skipped';
|
|
97
|
+
}
|
|
98
|
+
if (!mapFile) {
|
|
99
|
+
return 'skipped';
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const linkPath = join(scope.scopeDir, 'AGENTS.md');
|
|
103
|
+
try {
|
|
104
|
+
if (fs.readlinkSync(linkPath) === mapFile) {
|
|
105
|
+
return 'present';
|
|
106
|
+
}
|
|
107
|
+
} catch {
|
|
108
|
+
// Not a symlink (missing, or a stale regular file) — fall through and place it.
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const existed = jetpack.exists(linkPath) !== false;
|
|
112
|
+
jetpack.remove(linkPath);
|
|
113
|
+
fs.symlinkSync(mapFile, linkPath);
|
|
114
|
+
return existed ? 'healed' : 'created';
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Render a fresh brand AGENTS.md.
|
|
119
|
+
*
|
|
120
|
+
* @param {string} brandName - Display name for the brand-notes heading
|
|
121
|
+
* @returns {string} - Full file content
|
|
122
|
+
*/
|
|
123
|
+
function renderAgentsMd(brandName, importLine = IMPORT_LINE) {
|
|
124
|
+
return [
|
|
125
|
+
importLine,
|
|
126
|
+
'',
|
|
127
|
+
`# ${brandName} — brand notes`,
|
|
128
|
+
'',
|
|
129
|
+
].join('\n');
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Ensure the brand-root AGENTS.md exists with the framework import as its
|
|
134
|
+
* first line. Existing consumer content is preserved verbatim; a stray copy
|
|
135
|
+
* of the import lower in the file is removed when healing (no duplicates).
|
|
136
|
+
*
|
|
137
|
+
* @param {string} brandRoot - Absolute brand monorepo root
|
|
138
|
+
* @param {string} brandName - Display name used when creating fresh
|
|
139
|
+
* @returns {'present'|'created'|'healed'} - What happened
|
|
140
|
+
*/
|
|
141
|
+
function ensureAgentsMd(brandRoot, brandName) {
|
|
142
|
+
const file = join(brandRoot, 'AGENTS.md');
|
|
143
|
+
const importLine = resolveImportLine(brandRoot);
|
|
144
|
+
const existing = jetpack.read(file);
|
|
145
|
+
|
|
146
|
+
if (existing === undefined) {
|
|
147
|
+
jetpack.write(file, renderAgentsMd(brandName, importLine));
|
|
148
|
+
return 'created';
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const lines = existing.split('\n');
|
|
152
|
+
const hasCruft = lines.some((line, i) => i > 0 && isImportLine(line));
|
|
153
|
+
|
|
154
|
+
if (lines[0].trim() === importLine && !hasCruft) {
|
|
155
|
+
return 'present';
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Heal: the resolved import goes to the top; drop any stray/stale-depth
|
|
159
|
+
// import copy so heals never stack cruft
|
|
160
|
+
const body = lines.filter((line) => !isImportLine(line));
|
|
161
|
+
jetpack.write(file, [importLine, ...(body[0]?.trim() === '' ? [] : ['']), ...body].join('\n'));
|
|
162
|
+
return 'healed';
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Ensure the brand-root CLAUDE.md is the one-line `@AGENTS.md` pointer.
|
|
167
|
+
* A content-bearing CLAUDE.md is NEVER clobbered — that content belongs in
|
|
168
|
+
* AGENTS.md (the caller warns with the move-it message).
|
|
169
|
+
*
|
|
170
|
+
* @param {string} brandRoot - Absolute brand monorepo root
|
|
171
|
+
* @returns {'present'|'created'|'content-bearing'} - What happened
|
|
172
|
+
*/
|
|
173
|
+
function ensureClaudePointer(brandRoot) {
|
|
174
|
+
const file = join(brandRoot, 'CLAUDE.md');
|
|
175
|
+
const existing = jetpack.read(file);
|
|
176
|
+
|
|
177
|
+
if (existing === undefined) {
|
|
178
|
+
jetpack.write(file, `${CLAUDE_POINTER}\n`);
|
|
179
|
+
return 'created';
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const meaningful = existing.split('\n').map((line) => line.trim()).filter(Boolean);
|
|
183
|
+
if (meaningful.includes(CLAUDE_POINTER)) {
|
|
184
|
+
return 'present';
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return 'content-bearing';
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
module.exports = {
|
|
191
|
+
GUIDE_SUBPATH,
|
|
192
|
+
IMPORT_LINE,
|
|
193
|
+
CLAUDE_POINTER,
|
|
194
|
+
isImportLine,
|
|
195
|
+
findScope,
|
|
196
|
+
resolveImportLine,
|
|
197
|
+
ensureGuideLink,
|
|
198
|
+
renderAgentsMd,
|
|
199
|
+
ensureAgentsMd,
|
|
200
|
+
ensureClaudePointer,
|
|
201
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The brand-.env home of each target's GA4 Measurement Protocol secret — the
|
|
3
|
+
* ONE name the analytics service resolves from GA and writes. Per-target
|
|
4
|
+
* because every surface measures through its own stream; the per-target name
|
|
5
|
+
* is delivered as GOOGLE_ANALYTICS_SECRET on every verb (composed into
|
|
6
|
+
* dist/.env for backend, loaded into process.env for the others) — the env
|
|
7
|
+
* schema's rename, #678.
|
|
8
|
+
*
|
|
9
|
+
* It is a secret, so config/omega.json5 is not an option (the loader
|
|
10
|
+
* hard-fails secret-shaped keys) — before #434 it lived in .omega/state.json
|
|
11
|
+
* and the composition read it from there.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @param {string} target - Target key (web/backend/desktop/extension/mobile)
|
|
16
|
+
* @returns {string} The brand .env variable name, e.g. GOOGLE_ANALYTICS_SECRET_BACKEND
|
|
17
|
+
*/
|
|
18
|
+
function streamSecretEnvName(target) {
|
|
19
|
+
return `GOOGLE_ANALYTICS_SECRET_${target.toUpperCase()}`;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
module.exports = { streamSecretEnvName };
|
package/dist/lib/argv.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* argv shaping — the one rule about the leading VERB (#229).
|
|
3
|
+
*
|
|
4
|
+
* Every manager invocation now names its command (`omega manage --service=x`),
|
|
5
|
+
* so anything that REBUILDS an invocation from the raw argv — the run
|
|
6
|
+
* summary's copy-pasteable retry line, the company runner's per-brand child
|
|
7
|
+
* args — has to drop that verb first, or it doubles into `omega manage manage`.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The argv without its leading command verb. A first entry that starts with
|
|
12
|
+
* `-` is a flag, not a verb, and is left alone.
|
|
13
|
+
*
|
|
14
|
+
* @param {string[]} argv - Raw arguments (process.argv.slice(2) shaped).
|
|
15
|
+
* @returns {string[]} The arguments after the verb.
|
|
16
|
+
*/
|
|
17
|
+
function stripLeadingVerb(argv) {
|
|
18
|
+
return argv[0] && !argv[0].startsWith('-') ? argv.slice(1) : argv;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
module.exports = { stripLeadingVerb };
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Firebase Auth admin client over the Identity Toolkit REST API — the
|
|
3
|
+
* non-interactive replacement for omega-manager's firebase-admin
|
|
4
|
+
* `getAuth(brandId)`. Authenticates with the brand's own service account
|
|
5
|
+
* (.omega/secrets/service-account.json, provisioned by the firebase
|
|
6
|
+
* service) via the shared google-token provider; custom tokens are signed
|
|
7
|
+
* locally with the shared jwt helper, so there is no SDK dependency.
|
|
8
|
+
* Shared by the account service (required accounts) and the migrations
|
|
9
|
+
* service (orphaned-doc detection + creation-time reconciliation).
|
|
10
|
+
*
|
|
11
|
+
* Handlers call named methods, so tests fake this surface
|
|
12
|
+
* method-for-method. Lookups return null for missing users (instead of
|
|
13
|
+
* firebase-admin's auth/user-not-found throw).
|
|
14
|
+
*/
|
|
15
|
+
const { createTokenProvider } = require('./google-token.js');
|
|
16
|
+
const { signJwt } = require('./jwt.js');
|
|
17
|
+
|
|
18
|
+
const IDENTITY_TOOLKIT_BASE = 'https://identitytoolkit.googleapis.com/v1';
|
|
19
|
+
const SCOPE = 'https://www.googleapis.com/auth/identitytoolkit';
|
|
20
|
+
|
|
21
|
+
// Fixed audience for Firebase custom tokens (not the project)
|
|
22
|
+
const CUSTOM_TOKEN_AUD = 'https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Map an Identity Toolkit user record to the subset the services use.
|
|
26
|
+
* createdAt is Identity Toolkit's ms-since-epoch string; it surfaces as
|
|
27
|
+
* metadata.creationTime (ISO) to mirror firebase-admin's UserRecord shape.
|
|
28
|
+
*/
|
|
29
|
+
function toUser(record) {
|
|
30
|
+
return {
|
|
31
|
+
uid: record.localId,
|
|
32
|
+
email: record.email,
|
|
33
|
+
providerData: (record.providerUserInfo || []).map((p) => ({ providerId: p.providerId })),
|
|
34
|
+
metadata: {
|
|
35
|
+
creationTime: record.createdAt ? new Date(Number(record.createdAt)).toISOString() : null,
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Create the auth admin client.
|
|
42
|
+
*
|
|
43
|
+
* @param {Object} serviceAccount - Parsed service-account JSON
|
|
44
|
+
* @returns {Object} { getUserByEmail, getUser, createUser, updateUser, createCustomToken }
|
|
45
|
+
*/
|
|
46
|
+
function createAuthAdmin(serviceAccount) {
|
|
47
|
+
const projectId = serviceAccount.project_id;
|
|
48
|
+
const tokenProvider = createTokenProvider(serviceAccount, SCOPE);
|
|
49
|
+
|
|
50
|
+
async function request(method, body) {
|
|
51
|
+
const token = await tokenProvider.getAccessToken();
|
|
52
|
+
|
|
53
|
+
const response = await fetch(`${IDENTITY_TOOLKIT_BASE}/projects/${projectId}/${method}`, {
|
|
54
|
+
method: 'POST',
|
|
55
|
+
headers: {
|
|
56
|
+
'Authorization': `Bearer ${token}`,
|
|
57
|
+
'Content-Type': 'application/json',
|
|
58
|
+
},
|
|
59
|
+
body: JSON.stringify(body),
|
|
60
|
+
signal: AbortSignal.timeout(30000),
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
const data = await response.json();
|
|
64
|
+
|
|
65
|
+
if (!response.ok) {
|
|
66
|
+
throw new Error(`Identity Toolkit API error: ${data.error?.message || JSON.stringify(data)}`);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return data;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
/** Look up a user by email. Missing → null. */
|
|
74
|
+
async getUserByEmail(email) {
|
|
75
|
+
const data = await request('accounts:lookup', { email: [email] });
|
|
76
|
+
return data.users?.[0] ? toUser(data.users[0]) : null;
|
|
77
|
+
},
|
|
78
|
+
|
|
79
|
+
/** Look up a user by uid. Missing → null. */
|
|
80
|
+
async getUser(uid) {
|
|
81
|
+
const data = await request('accounts:lookup', { localId: [uid] });
|
|
82
|
+
return data.users?.[0] ? toUser(data.users[0]) : null;
|
|
83
|
+
},
|
|
84
|
+
|
|
85
|
+
/** Create a user with email + password. */
|
|
86
|
+
async createUser({ email, password }) {
|
|
87
|
+
const data = await request('accounts', { email, password });
|
|
88
|
+
return { uid: data.localId, email };
|
|
89
|
+
},
|
|
90
|
+
|
|
91
|
+
/** Update a user's password. */
|
|
92
|
+
async updateUser(uid, { password }) {
|
|
93
|
+
await request('accounts:update', { localId: uid, password });
|
|
94
|
+
},
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Mint a Firebase custom token for a uid — signed locally with the
|
|
98
|
+
* service account's key (RS256), exchangeable for an ID token via the
|
|
99
|
+
* public signInWithCustomToken endpoint.
|
|
100
|
+
*/
|
|
101
|
+
createCustomToken(uid) {
|
|
102
|
+
const now = Math.floor(Date.now() / 1000);
|
|
103
|
+
|
|
104
|
+
return signJwt(
|
|
105
|
+
{ alg: 'RS256', typ: 'JWT' },
|
|
106
|
+
{
|
|
107
|
+
iss: serviceAccount.client_email,
|
|
108
|
+
sub: serviceAccount.client_email,
|
|
109
|
+
aud: CUSTOM_TOKEN_AUD,
|
|
110
|
+
iat: now,
|
|
111
|
+
exp: now + 3600,
|
|
112
|
+
uid,
|
|
113
|
+
},
|
|
114
|
+
serviceAccount.private_key,
|
|
115
|
+
);
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
module.exports = { createAuthAdmin, CUSTOM_TOKEN_AUD };
|