@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,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bundle ID CRUD + capability management against the App Store Connect
|
|
3
|
+
* API. Apple's `platform` field on the bundle ID record is decorative — a
|
|
4
|
+
* single IOS-platform bundle ID works for all Apple platforms; the
|
|
5
|
+
* provisioning profile's profileType selects the actual platform.
|
|
6
|
+
*/
|
|
7
|
+
const { API_BASE } = require('./apple-api.js');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* List all bundle IDs (paginated).
|
|
11
|
+
*/
|
|
12
|
+
async function listBundleIds(client) {
|
|
13
|
+
return client.paginate(`${API_BASE}/bundleIds?limit=200`);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* List the capabilities currently enabled on a bundle ID.
|
|
18
|
+
*/
|
|
19
|
+
async function listBundleIdCapabilities(client, bundleIdId) {
|
|
20
|
+
return client.paginate(`${API_BASE}/bundleIds/${bundleIdId}/bundleIdCapabilities`);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Create a bundle ID and enable the requested capabilities.
|
|
25
|
+
*/
|
|
26
|
+
async function createBundleId(client, identifier, name, platform = 'IOS', capabilities = []) {
|
|
27
|
+
const data = await client.request(`${API_BASE}/bundleIds`, {
|
|
28
|
+
method: 'POST',
|
|
29
|
+
body: JSON.stringify({
|
|
30
|
+
data: {
|
|
31
|
+
type: 'bundleIds',
|
|
32
|
+
attributes: { identifier, name, platform },
|
|
33
|
+
},
|
|
34
|
+
}),
|
|
35
|
+
});
|
|
36
|
+
const bundleId = data.data;
|
|
37
|
+
|
|
38
|
+
if (capabilities.length > 0) {
|
|
39
|
+
await enableCapabilities(client, bundleId.id, capabilities);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return bundleId;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Enable each capability on a bundle ID, tolerating per-capability
|
|
47
|
+
* failures (some capabilities reject benignly depending on account
|
|
48
|
+
* entitlements — the caller logs each result).
|
|
49
|
+
*
|
|
50
|
+
* APPLE_ID_AUTH (Sign in with Apple) requires a `settings` block marking
|
|
51
|
+
* the app as the primary consent app — Apple rejects it otherwise.
|
|
52
|
+
*
|
|
53
|
+
* @returns {Array<{ capability, success, error? }>}
|
|
54
|
+
*/
|
|
55
|
+
async function enableCapabilities(client, bundleIdId, capabilities) {
|
|
56
|
+
if (!capabilities?.length) {
|
|
57
|
+
return [];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const results = [];
|
|
61
|
+
for (const capabilityType of capabilities) {
|
|
62
|
+
const body = {
|
|
63
|
+
data: {
|
|
64
|
+
type: 'bundleIdCapabilities',
|
|
65
|
+
attributes: { capabilityType },
|
|
66
|
+
relationships: {
|
|
67
|
+
bundleId: { data: { type: 'bundleIds', id: bundleIdId } },
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
if (capabilityType === 'APPLE_ID_AUTH') {
|
|
73
|
+
body.data.attributes.settings = [
|
|
74
|
+
{
|
|
75
|
+
key: 'APPLE_ID_AUTH_APP_CONSENT',
|
|
76
|
+
options: [{ key: 'PRIMARY_APP_CONSENT', enabled: true }],
|
|
77
|
+
},
|
|
78
|
+
];
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
try {
|
|
82
|
+
await client.request(`${API_BASE}/bundleIdCapabilities`, {
|
|
83
|
+
method: 'POST',
|
|
84
|
+
body: JSON.stringify(body),
|
|
85
|
+
});
|
|
86
|
+
results.push({ capability: capabilityType, success: true });
|
|
87
|
+
} catch (error) {
|
|
88
|
+
results.push({ capability: capabilityType, success: false, error: error.message });
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return results;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Find an existing bundle ID matching `identifier` (case-sensitive).
|
|
96
|
+
*/
|
|
97
|
+
function findBundleId(existingBundleIds, identifier) {
|
|
98
|
+
return existingBundleIds.find((b) => b.attributes.identifier === identifier) || null;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
module.exports = {
|
|
102
|
+
listBundleIds,
|
|
103
|
+
listBundleIdCapabilities,
|
|
104
|
+
createBundleId,
|
|
105
|
+
enableCapabilities,
|
|
106
|
+
findBundleId,
|
|
107
|
+
};
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* macOS keychain import for the exported .p12 files, kept fully
|
|
3
|
+
* non-interactive:
|
|
4
|
+
*
|
|
5
|
+
* 1. .p12 password — Sonoma+ rejects empty-password .p12 with "MAC
|
|
6
|
+
* verification failed", so exports always carry CSC_KEY_PASSWORD.
|
|
7
|
+
* 2. Trusted tools (-T) — codesign/productbuild/productsign/xcodebuild
|
|
8
|
+
* are whitelisted so they can use the key without a GUI prompt.
|
|
9
|
+
* 3. Partition list — with APPLE_KEYCHAIN_PASSWORD provided, the
|
|
10
|
+
* "<tool> wants to use the keychain" prompt is suppressed entirely;
|
|
11
|
+
* without it, it fires once on first signing then never again.
|
|
12
|
+
* 4. Allowed-types filter — only cert types currently in config import;
|
|
13
|
+
* .p12 files for deprecated types stay on disk but are skipped.
|
|
14
|
+
*
|
|
15
|
+
* Failures print manual-import guidance (omega-manager auto-opened
|
|
16
|
+
* Keychain Access — the port stays non-interactive). Non-macOS platforms
|
|
17
|
+
* skip entirely.
|
|
18
|
+
*/
|
|
19
|
+
const os = require('node:os');
|
|
20
|
+
const path = require('node:path');
|
|
21
|
+
const { execFileSync } = require('node:child_process');
|
|
22
|
+
const jetpack = require('fs-jetpack');
|
|
23
|
+
const chalk = require('chalk').default;
|
|
24
|
+
|
|
25
|
+
// execFileSync gets no shell, so no ~ expansion — resolve the keychain path here
|
|
26
|
+
const LOGIN_KEYCHAIN = path.join(os.homedir(), 'Library/Keychains/login.keychain-db');
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Import .p12 files into the macOS login keychain (best-effort).
|
|
30
|
+
*
|
|
31
|
+
* @param {Object} options
|
|
32
|
+
* @param {string} options.certificatesDir - Directory containing .p12 files
|
|
33
|
+
* @param {string} [options.keychainPassword] - Mac login password (unlock + partition list)
|
|
34
|
+
* @param {string} [options.certificatePassword] - Password on the .p12 files
|
|
35
|
+
* @param {string[]} [options.allowedTypes] - Cert types (filename sans .p12) to import
|
|
36
|
+
* @returns {{ imported: number, skipped: number, failed: number }}
|
|
37
|
+
*/
|
|
38
|
+
function importP12Files({ certificatesDir, keychainPassword = null, certificatePassword = '', allowedTypes = null }) {
|
|
39
|
+
if (process.platform !== 'darwin') {
|
|
40
|
+
console.log(` ${chalk.dim('⊘ Keychain import skipped (not macOS)')}`);
|
|
41
|
+
return { imported: 0, skipped: 0, failed: 0 };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (!jetpack.exists(certificatesDir)) {
|
|
45
|
+
return { imported: 0, skipped: 0, failed: 0 };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
let p12Files = jetpack.find(certificatesDir, { matching: '*.p12' });
|
|
49
|
+
|
|
50
|
+
if (allowedTypes && Array.isArray(allowedTypes)) {
|
|
51
|
+
const allowSet = new Set(allowedTypes);
|
|
52
|
+
p12Files = p12Files.filter((p) => allowSet.has(p.split('/').pop().replace('.p12', '')));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (p12Files.length === 0) {
|
|
56
|
+
return { imported: 0, skipped: 0, failed: 0 };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
let imported = 0;
|
|
60
|
+
let skipped = 0;
|
|
61
|
+
const failed = [];
|
|
62
|
+
|
|
63
|
+
// Pre-unlock when the login password was provided — `security import`
|
|
64
|
+
// fails on a locked keychain.
|
|
65
|
+
if (keychainPassword) {
|
|
66
|
+
try {
|
|
67
|
+
execFileSync(
|
|
68
|
+
'security',
|
|
69
|
+
['unlock-keychain', '-p', keychainPassword, LOGIN_KEYCHAIN],
|
|
70
|
+
{ stdio: 'pipe' },
|
|
71
|
+
);
|
|
72
|
+
} catch {
|
|
73
|
+
// Continue — failures below print manual guidance.
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// -T whitelists specific signing binaries (finer-grained than -A).
|
|
78
|
+
const trustedTools = [
|
|
79
|
+
'/usr/bin/codesign',
|
|
80
|
+
'/usr/bin/productbuild',
|
|
81
|
+
'/usr/bin/productsign',
|
|
82
|
+
'/usr/bin/security',
|
|
83
|
+
'/usr/bin/xcodebuild',
|
|
84
|
+
];
|
|
85
|
+
const tFlags = trustedTools.flatMap((tool) => ['-T', tool]);
|
|
86
|
+
|
|
87
|
+
for (const p12Path of p12Files) {
|
|
88
|
+
const certType = p12Path.split('/').pop().replace('.p12', '');
|
|
89
|
+
|
|
90
|
+
try {
|
|
91
|
+
execFileSync(
|
|
92
|
+
'security',
|
|
93
|
+
['import', p12Path, '-k', LOGIN_KEYCHAIN, '-P', certificatePassword, ...tFlags],
|
|
94
|
+
{ stdio: 'pipe' },
|
|
95
|
+
);
|
|
96
|
+
console.log(` ${chalk.green('✓')} Imported ${chalk.cyan(certType)} to Keychain`);
|
|
97
|
+
imported++;
|
|
98
|
+
} catch (error) {
|
|
99
|
+
const message = error?.message || '';
|
|
100
|
+
if (message.includes('already exists') || message.includes('duplicate')) {
|
|
101
|
+
console.log(` ${chalk.dim(`ℹ ${certType} already in Keychain`)}`);
|
|
102
|
+
skipped++;
|
|
103
|
+
} else {
|
|
104
|
+
failed.push({ path: p12Path, type: certType, message });
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Suppress the per-signing keychain prompt (macOS Sierra+ requirement) —
|
|
110
|
+
// without this, codesign prompts for the login keychain password the
|
|
111
|
+
// first time it uses each imported private key.
|
|
112
|
+
if (imported > 0 && keychainPassword) {
|
|
113
|
+
try {
|
|
114
|
+
execFileSync(
|
|
115
|
+
'security',
|
|
116
|
+
['set-key-partition-list', '-S', 'apple-tool:,apple:,codesign:', '-s', '-k', keychainPassword, LOGIN_KEYCHAIN],
|
|
117
|
+
{ stdio: 'pipe' },
|
|
118
|
+
);
|
|
119
|
+
} catch {
|
|
120
|
+
// Non-fatal — codesign may prompt once on first use.
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (failed.length > 0) {
|
|
125
|
+
console.log(` ${chalk.yellow('⚠')} ${failed.length} cert(s) failed keychain import — import manually:`);
|
|
126
|
+
for (const { path, type, message } of failed) {
|
|
127
|
+
console.log(` ${chalk.gray('→')} ${chalk.cyan(type)}: ${chalk.gray(message.split('\n')[0])}`);
|
|
128
|
+
console.log(` ${chalk.gray(`double-click ${path} (password: ${certificatePassword ? 'the CSC_KEY_PASSWORD env value' : 'empty'})`)}`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return { imported, skipped, failed: failed.length };
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
module.exports = { importP12Files };
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interactive walkthrough for portal-only certificate types (DEVELOPER_ID_*).
|
|
3
|
+
* Apple's API can list and download these but only the Account Holder can
|
|
4
|
+
* CREATE them, in the portal UI — so the walkthrough automates everything
|
|
5
|
+
* around that one human step: it generates/reuses the pipeline's CSR (the
|
|
6
|
+
* private key stays local, so the .p12 export pairs), drops a picker-friendly
|
|
7
|
+
* copy in Downloads, opens the portal's create page (Enter-gated), then polls
|
|
8
|
+
* Downloads + the target path for the issued .cer — installing it only when
|
|
9
|
+
* it provably pairs with our key and names the expected certificate type.
|
|
10
|
+
*
|
|
11
|
+
* Restores omega-manager's interactive rescue (the port had reduced it to
|
|
12
|
+
* printed guidance) and goes further: legacy still sent the user to Keychain
|
|
13
|
+
* Access to make the CSR; here upload + download are the only human steps.
|
|
14
|
+
*/
|
|
15
|
+
const { homedir } = require('node:os');
|
|
16
|
+
const { join, basename } = require('node:path');
|
|
17
|
+
const jetpack = require('fs-jetpack');
|
|
18
|
+
const chalk = require('chalk').default;
|
|
19
|
+
const { openBrowserAndPoll } = require('../../../vendor/devkit/flows.js');
|
|
20
|
+
|
|
21
|
+
const {
|
|
22
|
+
getCSRContent,
|
|
23
|
+
validateManualCertificate,
|
|
24
|
+
certificateMatchesKey,
|
|
25
|
+
getCertificateCommonName,
|
|
26
|
+
} = require('./certificate-manager.js');
|
|
27
|
+
|
|
28
|
+
const PORTAL_CREATE_URL = 'https://developer.apple.com/account/resources/certificates/add';
|
|
29
|
+
|
|
30
|
+
// Portal option labels by config type prefix — the radio button the Account
|
|
31
|
+
// Holder must pick on the create page, and the CN prefix Apple stamps on the
|
|
32
|
+
// issued certificate (how a wrong-type download is caught).
|
|
33
|
+
const PORTAL_LABELS = [
|
|
34
|
+
{ prefix: 'DEVELOPER_ID_APPLICATION', label: 'Developer ID Application' },
|
|
35
|
+
{ prefix: 'DEVELOPER_ID_INSTALLER', label: 'Developer ID Installer' },
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
function portalLabelOf(type) {
|
|
39
|
+
const match = PORTAL_LABELS.find((entry) => type.startsWith(entry.prefix));
|
|
40
|
+
return match ? match.label : type;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Find the issued .cer among the candidates: the target path itself (the
|
|
45
|
+
* user saved straight to the printed path) or any .cer that landed in the
|
|
46
|
+
* downloads dir since the walkthrough started. A candidate is accepted only
|
|
47
|
+
* when it pairs with the pipeline's private key (modulus match — proof it
|
|
48
|
+
* was issued from OUR CSR) and carries the expected CN prefix (catches
|
|
49
|
+
* creating the wrong Developer ID type from the right CSR). Rejections are
|
|
50
|
+
* remembered so each bad file warns once, not every poll tick.
|
|
51
|
+
*
|
|
52
|
+
* @returns {string|null} - Path of the accepted .cer, or null
|
|
53
|
+
*/
|
|
54
|
+
function findIssuedCert({ certPath, downloadsDir, keyPath, portalLabel, startedAt, rejected }) {
|
|
55
|
+
const candidates = [];
|
|
56
|
+
|
|
57
|
+
if (jetpack.exists(certPath)) {
|
|
58
|
+
candidates.push(certPath);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
for (const name of jetpack.list(downloadsDir) || []) {
|
|
62
|
+
if (!name.toLowerCase().endsWith('.cer')) {
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
const candidate = join(downloadsDir, name);
|
|
66
|
+
const modified = jetpack.inspect(candidate, { times: true })?.modifyTime;
|
|
67
|
+
if (modified && modified.getTime() >= startedAt) {
|
|
68
|
+
candidates.push(candidate);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
for (const candidate of candidates) {
|
|
73
|
+
if (rejected.has(candidate)) {
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
if (!validateManualCertificate(candidate).valid) {
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (!certificateMatchesKey(candidate, keyPath)) {
|
|
81
|
+
rejected.add(candidate);
|
|
82
|
+
console.log(`\n ${chalk.yellow('⚠')} ${basename(candidate)} was not issued from the CSR I staged — create the certificate with that exact file`);
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const cn = getCertificateCommonName(candidate);
|
|
87
|
+
if (!cn || !cn.startsWith(portalLabel)) {
|
|
88
|
+
rejected.add(candidate);
|
|
89
|
+
console.log(`\n ${chalk.yellow('⚠')} ${basename(candidate)} is "${cn || 'unreadable'}" — expected a ${portalLabel} certificate`);
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return candidate;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Walk the user through creating a portal-only certificate: CSR staged →
|
|
101
|
+
* portal opened → issued .cer detected → installed to certPath. The caller
|
|
102
|
+
* re-validates and continues down its normal valid-local-file path (.p12
|
|
103
|
+
* export + keychain import), exactly as if the file had always been there.
|
|
104
|
+
*
|
|
105
|
+
* @param {Object} options
|
|
106
|
+
* @param {string} options.type - Certificate type (e.g. DEVELOPER_ID_INSTALLER_G2)
|
|
107
|
+
* @param {string} options.certPath - Where the .cer must land
|
|
108
|
+
* @param {string} options.appleDir - The brand's .omega/certificates/apple dir
|
|
109
|
+
* @param {string} options.teamId - Apple team ID (CSR subject)
|
|
110
|
+
* @param {string} [options.downloadsDir] - Where downloads land (test seam)
|
|
111
|
+
* @returns {Promise<{ installed: boolean }>}
|
|
112
|
+
*/
|
|
113
|
+
async function runManualCertWalkthrough({ type, certPath, appleDir, teamId, downloadsDir = join(homedir(), 'Downloads') }) {
|
|
114
|
+
const portalLabel = portalLabelOf(type);
|
|
115
|
+
const startedAt = Date.now();
|
|
116
|
+
|
|
117
|
+
// The same CSR machinery as the automatable types: key + CSR generated
|
|
118
|
+
// once, reused forever — the issued cert must pair with this key or the
|
|
119
|
+
// .p12 export (and CI signing) has nothing to pair with.
|
|
120
|
+
getCSRContent(type, appleDir, teamId);
|
|
121
|
+
const keyPath = join(appleDir, 'csr', type, 'private.key');
|
|
122
|
+
|
|
123
|
+
// Picker-friendly copy: the portal's file dialog starts in Downloads, and
|
|
124
|
+
// some browsers filter for the .certSigningRequest extension.
|
|
125
|
+
const uploadName = `omega-${type}.certSigningRequest`;
|
|
126
|
+
jetpack.copy(join(appleDir, 'csr', type, 'request.csr'), join(downloadsDir, uploadName), { overwrite: true });
|
|
127
|
+
|
|
128
|
+
const g2Note = type.endsWith('_G2')
|
|
129
|
+
? `\n ${chalk.dim('(asked for a profile type? choose "G2 Sub-CA")')}`
|
|
130
|
+
: '';
|
|
131
|
+
const steps = [
|
|
132
|
+
`Apple only lets the ${chalk.bold('Account Holder')} create ${chalk.cyan(portalLabel)} certificates, in the portal:`,
|
|
133
|
+
` 1. Sign in as the Account Holder`,
|
|
134
|
+
` 2. Choose ${chalk.bold(portalLabel)} under Software, then Continue${g2Note}`,
|
|
135
|
+
` 3. Upload ${chalk.cyan(uploadName)} — already staged in your Downloads folder`,
|
|
136
|
+
` 4. Download the issued certificate — I'll detect it in Downloads and take it from there`,
|
|
137
|
+
].join('\n');
|
|
138
|
+
|
|
139
|
+
const rejected = new Set();
|
|
140
|
+
const result = await openBrowserAndPoll({
|
|
141
|
+
url: PORTAL_CREATE_URL,
|
|
142
|
+
promptMessage: steps,
|
|
143
|
+
label: 'the Apple Developer portal',
|
|
144
|
+
waitMessage: `Waiting for the issued ${portalLabel} certificate`,
|
|
145
|
+
intervalMs: 3000,
|
|
146
|
+
check: async () => {
|
|
147
|
+
const found = findIssuedCert({ certPath, downloadsDir, keyPath, portalLabel, startedAt, rejected });
|
|
148
|
+
if (!found) {
|
|
149
|
+
return { done: false };
|
|
150
|
+
}
|
|
151
|
+
if (found !== certPath) {
|
|
152
|
+
jetpack.copy(found, certPath, { overwrite: true });
|
|
153
|
+
}
|
|
154
|
+
return { done: true, result: found };
|
|
155
|
+
},
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
if (result.success) {
|
|
159
|
+
console.log(` ${chalk.green('✓')} Installed ${chalk.gray(certPath)}`);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return { installed: Boolean(result.success) };
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
module.exports = { runManualCertWalkthrough, PORTAL_CREATE_URL };
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provisioning profile CRUD + the cert-type → profile-type mapping.
|
|
3
|
+
* Profiles bind a bundle ID + certificate (+ devices for development
|
|
4
|
+
* profiles), so they're per-brand even though certificates are one set
|
|
5
|
+
* per Apple Developer account.
|
|
6
|
+
*/
|
|
7
|
+
const jetpack = require('fs-jetpack');
|
|
8
|
+
const chalk = require('chalk').default;
|
|
9
|
+
|
|
10
|
+
const { API_BASE } = require('./apple-api.js');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Cert type → the provisioning profile type that consumes it. Installer
|
|
14
|
+
* cert types need no profile (null). Both G1 and G2 Developer ID
|
|
15
|
+
* Application certs use MAC_APP_DIRECT — Apple distinguishes them by the
|
|
16
|
+
* underlying cert chain.
|
|
17
|
+
*/
|
|
18
|
+
const CERT_TYPE_TO_PROFILE_TYPE = {
|
|
19
|
+
DEVELOPMENT: 'IOS_APP_DEVELOPMENT',
|
|
20
|
+
IOS_DISTRIBUTION: 'IOS_APP_STORE',
|
|
21
|
+
MAC_INSTALLER_DISTRIBUTION: null,
|
|
22
|
+
MAC_APP_DISTRIBUTION: 'MAC_APP_STORE',
|
|
23
|
+
DEVELOPER_ID_APPLICATION: 'MAC_APP_DIRECT',
|
|
24
|
+
DEVELOPER_ID_APPLICATION_G2: 'MAC_APP_DIRECT',
|
|
25
|
+
DEVELOPER_ID_INSTALLER: null,
|
|
26
|
+
DEVELOPER_ID_INSTALLER_G2: null,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
function getProfileTypeForCertType(certType) {
|
|
30
|
+
return CERT_TYPE_TO_PROFILE_TYPE[certType];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Whether a cert type applies to a platform: IOS_DISTRIBUTION → IOS only;
|
|
35
|
+
* MAC_* and DEVELOPER_ID_* → MACOS only; DEVELOPMENT → both.
|
|
36
|
+
*/
|
|
37
|
+
function certAppliesToPlatform(certType, platform) {
|
|
38
|
+
if (platform === 'IOS') return certType.includes('IOS') || certType === 'DEVELOPMENT';
|
|
39
|
+
if (platform === 'MACOS') return certType.includes('MAC') || certType.includes('DEVELOPER_ID') || certType === 'DEVELOPMENT';
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async function listProfiles(client) {
|
|
44
|
+
return client.paginate(`${API_BASE}/profiles?limit=200`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function listDevices(client) {
|
|
48
|
+
return client.paginate(`${API_BASE}/devices?limit=200`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Download a provisioning profile's content to disk as .mobileprovision.
|
|
53
|
+
*/
|
|
54
|
+
async function downloadProfile(client, profileId, outputPath) {
|
|
55
|
+
const data = await client.request(`${API_BASE}/profiles/${profileId}`);
|
|
56
|
+
const profileContent = data?.data?.attributes?.profileContent;
|
|
57
|
+
if (!profileContent) {
|
|
58
|
+
throw new Error(`Profile ${profileId} has no profileContent`);
|
|
59
|
+
}
|
|
60
|
+
jetpack.write(outputPath, Buffer.from(profileContent, 'base64'));
|
|
61
|
+
console.log(` ${chalk.green('✓')} Downloaded ${chalk.gray(outputPath)}`);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Create a provisioning profile linking a bundle ID + cert (+ devices for
|
|
66
|
+
* development profiles).
|
|
67
|
+
*/
|
|
68
|
+
async function createProfile(client, name, profileType, bundleIdId, certificateIds, deviceIds = []) {
|
|
69
|
+
const body = {
|
|
70
|
+
data: {
|
|
71
|
+
type: 'profiles',
|
|
72
|
+
attributes: { name, profileType },
|
|
73
|
+
relationships: {
|
|
74
|
+
bundleId: { data: { type: 'bundleIds', id: bundleIdId } },
|
|
75
|
+
certificates: {
|
|
76
|
+
data: certificateIds.map((id) => ({ type: 'certificates', id })),
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
if (deviceIds.length > 0) {
|
|
83
|
+
body.data.relationships.devices = {
|
|
84
|
+
data: deviceIds.map((id) => ({ type: 'devices', id })),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const data = await client.request(`${API_BASE}/profiles`, {
|
|
89
|
+
method: 'POST',
|
|
90
|
+
body: JSON.stringify(body),
|
|
91
|
+
});
|
|
92
|
+
return data.data;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Find a non-expired profile matching the exact name + type.
|
|
97
|
+
*/
|
|
98
|
+
function findValidProfile(existingProfiles, profileType, profileName) {
|
|
99
|
+
const now = new Date();
|
|
100
|
+
return existingProfiles.find((profile) => {
|
|
101
|
+
return profile.attributes.profileType === profileType
|
|
102
|
+
&& profile.attributes.name === profileName
|
|
103
|
+
&& new Date(profile.attributes.expirationDate) > now;
|
|
104
|
+
}) || null;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
module.exports = {
|
|
108
|
+
getProfileTypeForCertType,
|
|
109
|
+
certAppliesToPlatform,
|
|
110
|
+
listProfiles,
|
|
111
|
+
listDevices,
|
|
112
|
+
downloadProfile,
|
|
113
|
+
createProfile,
|
|
114
|
+
findValidProfile,
|
|
115
|
+
};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
<company>
|
|
2
|
+
<facts>
|
|
3
|
+
- Company Description: {description}
|
|
4
|
+
</facts>
|
|
5
|
+
</company>
|
|
6
|
+
|
|
7
|
+
<cancellation_unsubscribe>
|
|
8
|
+
<reasoning>
|
|
9
|
+
- You CANNOT cancel a user's subscription for them, they must do it themselves.
|
|
10
|
+
- Users CANNOT upgrade or downgrade their plans. They must cancel their current plan and re-subscribe to the new plan they want.
|
|
11
|
+
</reasoning>
|
|
12
|
+
<facts>
|
|
13
|
+
- Users CAN cancel by visiting their account at {website}/account#billing and clicking the "Manage Plan" button. From there, they can cancel their subscription.
|
|
14
|
+
- Users CAN change their payment method on an existing subscription by visiting their account at {website}/account#billing and clicking the "Manage Plan" button.
|
|
15
|
+
</facts>
|
|
16
|
+
</cancellation_unsubscribe>
|
|
17
|
+
|
|
18
|
+
<subscription>
|
|
19
|
+
<facts>
|
|
20
|
+
- Users can cancel any time within their 14-day free trial and won't be charged.
|
|
21
|
+
- If the user is outside their free trial window, they can cancel their subscription at any time and won't be charged again.
|
|
22
|
+
- Sometimes, bank statements might show a charge during the free trial, but it's just a pre-authorization and will be refunded if the user cancels within the free trial period.
|
|
23
|
+
</facts>
|
|
24
|
+
</subscription>
|
|
25
|
+
|
|
26
|
+
<refund>
|
|
27
|
+
<reasoning>
|
|
28
|
+
- Before requesting a refund, users must cancel their subscription.
|
|
29
|
+
- DO NOT mention anything about a refund unless the user specifically asks for one.
|
|
30
|
+
</reasoning>
|
|
31
|
+
<facts>
|
|
32
|
+
- Users can receive a partial refund by visiting {website}/refund and filling out the refund request form.
|
|
33
|
+
- Refunds are prorated based on the unused portion of the subscription.
|
|
34
|
+
</facts>
|
|
35
|
+
</refund>
|
|
36
|
+
|
|
37
|
+
<disputes>
|
|
38
|
+
<reasoning>
|
|
39
|
+
- DO NOT ever recommend that a user dispute their charge with their bank.
|
|
40
|
+
- Encourage the user to resolve disputes with us first.
|
|
41
|
+
</reasoning>
|
|
42
|
+
</disputes>
|
|
43
|
+
|
|
44
|
+
<delete_account_gdpr>
|
|
45
|
+
<facts>
|
|
46
|
+
- Users should email customer support. Direct them to {website}/contact to send an email.
|
|
47
|
+
</facts>
|
|
48
|
+
</delete_account_gdpr>
|
|
49
|
+
|
|
50
|
+
<sponsorships>
|
|
51
|
+
<reasoning>
|
|
52
|
+
- ALL sponsorship, guest post, link insertion, and link exchange inquiries must be handled via EMAIL, not chat.
|
|
53
|
+
- Do not discuss pricing, turnaround time, or availability over chat.
|
|
54
|
+
</reasoning>
|
|
55
|
+
<facts>
|
|
56
|
+
- Direct users to submit requests at {sponsorshipsUrl}
|
|
57
|
+
</facts>
|
|
58
|
+
</sponsorships>
|
|
59
|
+
|
|
60
|
+
<bug_bounty>
|
|
61
|
+
<reasoning>
|
|
62
|
+
- We ONLY reward for reports that have not been reported before.
|
|
63
|
+
</reasoning>
|
|
64
|
+
<facts>
|
|
65
|
+
- Direct users to email customer support at {website}/contact to report vulnerabilities.
|
|
66
|
+
</facts>
|
|
67
|
+
</bug_bounty>
|
|
68
|
+
|
|
69
|
+
<contact>
|
|
70
|
+
<reasoning>
|
|
71
|
+
- DO NOT agree to joining a phone call, video call, or any other form of communication outside of email and this chat.
|
|
72
|
+
</reasoning>
|
|
73
|
+
</contact>
|
|
74
|
+
|
|
75
|
+
<resources>
|
|
76
|
+
<facts>
|
|
77
|
+
- Terms of Service: {website}/terms
|
|
78
|
+
- Privacy Policy: {website}/privacy
|
|
79
|
+
</facts>
|
|
80
|
+
</resources>
|
|
81
|
+
|
|
82
|
+
<pricing>
|
|
83
|
+
<facts>
|
|
84
|
+
{pricing}
|
|
85
|
+
</facts>
|
|
86
|
+
</pricing>
|
|
87
|
+
|
|
88
|
+
<something_not_working>
|
|
89
|
+
<facts>
|
|
90
|
+
- Instruct users to try basic troubleshooting steps like signing out and back in, ensuring they are using the correct account, trying again later, etc.
|
|
91
|
+
- If they are using a browser, they should try clearing their cache and cookies and try a different browser.
|
|
92
|
+
- If they are using an app, they should try uninstalling and reinstalling the app.
|
|
93
|
+
- User should be instructed to send a screenshot of the issue.
|
|
94
|
+
- Getting "out of requests" error: Users need to upgrade their plan to get more requests or make sure they are using the right API key.
|
|
95
|
+
</facts>
|
|
96
|
+
</something_not_working>
|