@capgo/cli 7.122.6 → 7.122.7

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/dist/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@capgo/cli",
3
3
  "type": "module",
4
- "version": "7.122.6",
4
+ "version": "7.122.7",
5
5
  "description": "A CLI to upload to capgo servers",
6
6
  "author": "Martin martin@capgo.app",
7
7
  "license": "Apache 2.0",
@@ -105,8 +105,9 @@
105
105
  "test:payload-split": "bun test/test-payload-split.mjs",
106
106
  "test:macos-signing": "bun test/test-macos-signing.mjs",
107
107
  "test:apple-api-import-helpers": "bun test/test-apple-api-import-helpers.mjs",
108
+ "test:bundle-id-detector": "bun test/test-bundle-id-detector.mjs",
108
109
  "test:manifest-path-encoding": "bun test/test-manifest-path-encoding.mjs",
109
- "test": "bun run build && bun run test:version-detection:setup && bun run test:bundle && bun run test:functional && bun run test:semver && bun run test:version-edge-cases && bun run test:regex && bun run test:upload && bun run test:fail-on-incompatible && bun run test:credentials && bun run test:credentials-validation && bun run test:android-service-account-validation && bun run test:build-zip-filter && bun run test:checksum && bun run test:build-needed && bun run test:ci-prompts && bun run test:ci-secrets && bun run test:android-onboarding-progress && bun run test:onboarding-telemetry && bun run test:v2-event-migration && bun run test:analytics && bun run test:analytics-error-category && bun run test:analytics-org-resolver && bun run test:supabase-perf && bun run test:mcp-analytics && bun run test:app-created-source && bun run test:doctor-analytics && bun run test:posthog-exception && bun run test:build-platform-selection && bun run test:onboarding-recovery && bun run test:onboarding-progress && bun run test:onboarding-run-targets && bun run test:run-device-command && bun run test:init-app-conflict && bun run test:init-guardrails && bun run test:prompt-preferences && bun run test:esm-sdk && bun run test:mcp && bun run test:version-detection && bun run test:platform-paths && bun run test:payload-split && bun run test:manifest-path-encoding && bun run test:macos-signing && bun run test:apple-api-import-helpers && bun run test:ai-log-capture && bun run test:ai-analyze-flow && bun run test:ai-render-markdown && bun run test:ai-onboarding-mode && bun run test:ai-fit && bun run test:platform-layout && bun run test:frame-fit && bun run test:onboarding-min-size && bun run test:min-size-gate && bun run test:shell-size-gate && bun run test:build-log-sanitize && bun run test:build-output-viewport && bun run test:diff-viewer-viewport && bun run test:build-complete-exit",
110
+ "test": "bun run build && bun run test:version-detection:setup && bun run test:bundle && bun run test:functional && bun run test:semver && bun run test:version-edge-cases && bun run test:regex && bun run test:upload && bun run test:fail-on-incompatible && bun run test:credentials && bun run test:credentials-validation && bun run test:android-service-account-validation && bun run test:build-zip-filter && bun run test:checksum && bun run test:build-needed && bun run test:ci-prompts && bun run test:ci-secrets && bun run test:android-onboarding-progress && bun run test:onboarding-telemetry && bun run test:v2-event-migration && bun run test:analytics && bun run test:analytics-error-category && bun run test:analytics-org-resolver && bun run test:supabase-perf && bun run test:mcp-analytics && bun run test:app-created-source && bun run test:doctor-analytics && bun run test:posthog-exception && bun run test:build-platform-selection && bun run test:onboarding-recovery && bun run test:onboarding-progress && bun run test:onboarding-run-targets && bun run test:run-device-command && bun run test:init-app-conflict && bun run test:init-guardrails && bun run test:prompt-preferences && bun run test:esm-sdk && bun run test:mcp && bun run test:version-detection && bun run test:platform-paths && bun run test:payload-split && bun run test:manifest-path-encoding && bun run test:macos-signing && bun run test:apple-api-import-helpers && bun run test:bundle-id-detector && bun run test:ai-log-capture && bun run test:ai-analyze-flow && bun run test:ai-render-markdown && bun run test:ai-onboarding-mode && bun run test:ai-fit && bun run test:platform-layout && bun run test:frame-fit && bun run test:onboarding-min-size && bun run test:min-size-gate && bun run test:shell-size-gate && bun run test:build-log-sanitize && bun run test:build-output-viewport && bun run test:diff-viewer-viewport && bun run test:build-complete-exit",
110
111
  "test:build-platform-selection": "bun test/test-build-platform-selection.mjs",
111
112
  "test:ai-log-capture": "bun test/test-ai-log-capture.mjs",
112
113
  "test:ai-analyze-flow": "bun test/test-ai-analyze-flow.mjs",
@@ -130,7 +131,8 @@
130
131
  "jsonwebtoken": "^9.0.3",
131
132
  "node-forge": "^1.4.0",
132
133
  "qrcode": "^1.5.4",
133
- "react": "^19.2.6"
134
+ "react": "^19.2.6",
135
+ "string-width": "^8.2.1"
134
136
  },
135
137
  "devDependencies": {
136
138
  "@antfu/eslint-config": "^9.0.0",
@@ -3,6 +3,10 @@
3
3
  * Uses ES256 algorithm with the .p8 private key.
4
4
  */
5
5
  export declare function generateJwt(keyId: string, issuerId: string, p8Content: string): string;
6
+ export declare class AppleApiHttpError extends Error {
7
+ readonly status: number;
8
+ constructor(status: number, message: string);
9
+ }
6
10
  /**
7
11
  * Verify the API key works and try to detect the team ID from existing certificates.
8
12
  * Throws on 401/403 with a user-friendly message.
@@ -23,6 +27,50 @@ export interface AscDistributionCert {
23
27
  */
24
28
  certificateContent?: string;
25
29
  }
30
+ /**
31
+ * Why a local Keychain cert can't be used to ship builds.
32
+ *
33
+ * Concrete enumeration so the import-pick-identity UI can render a stable
34
+ * Reason column and so we can add specific guidance per reason (e.g.
35
+ * "managed" certs get a "can't sign locally" note, "not-visible" certs get
36
+ * a "Open Developer Portal to verify" note).
37
+ */
38
+ export type CertAvailabilityReason = 'expired' | 'managed' | 'not-visible' | 'check-failed' | 'no-private-key';
39
+ export interface CertAvailability {
40
+ available: boolean;
41
+ reason?: CertAvailabilityReason;
42
+ /** Short human-readable reason for display in the picker. */
43
+ reasonText?: string;
44
+ /** When available — Apple-side cert resource id for downstream API calls. */
45
+ appleCertId?: string;
46
+ }
47
+ /**
48
+ * Pure classifier: given a local cert + the result of an Apple-side lookup,
49
+ * decide whether it's usable for shipping builds and surface a short
50
+ * reasonText for the picker UI.
51
+ *
52
+ * Exported separately from the lookup function so we can unit-test the
53
+ * decision logic without mocking network calls. Callers compose:
54
+ *
55
+ * const certId = await findCertIdBySha1(token, identity.sha1)
56
+ * .catch(err => { lookupError = err; return null })
57
+ * const availability = classifyCertAvailability({
58
+ * localExpirationDate: identity.expirationDate,
59
+ * appleCertId: certId,
60
+ * lookupError,
61
+ * })
62
+ *
63
+ * The `expired` and `managed` branches don't need a lookup — they're checked
64
+ * up-front from local metadata. Callers can pass null `appleCertId` without
65
+ * having run the lookup at all when those local-side conditions already
66
+ * disqualify the identity.
67
+ */
68
+ export declare function classifyCertAvailability(args: {
69
+ localExpirationDate?: string;
70
+ isManaged?: boolean;
71
+ appleCertId: string | null;
72
+ lookupError?: unknown;
73
+ }): CertAvailability;
26
74
  /**
27
75
  * List all iOS distribution certificates.
28
76
  *
@@ -51,6 +99,20 @@ export declare function computeCertSha1(certificateContentBase64: string): strin
51
99
  * creation. Returns null if no Apple-side cert matches the SHA1.
52
100
  */
53
101
  export declare function findCertIdBySha1(token: string, sha1: string): Promise<string | null>;
102
+ /**
103
+ * Like {@link findCertIdBySha1} but returns the full Apple-side cert
104
+ * record (id + name + expirationDate + serialNumber) when matched. Used
105
+ * by the eager batch validation so the picker / manual-portal-walkthrough
106
+ * step can surface concrete disambiguators (expiration date, last few
107
+ * chars of serial number — both visible in the Apple Developer Portal
108
+ * when the user clicks into a cert) that help the user pick the right
109
+ * row when multiple distribution certs are listed for the same team.
110
+ *
111
+ * Apple's API does NOT expose a "created by" field on certs (the portal
112
+ * UI shows it, but `/v1/certificates` doesn't return that column). The
113
+ * disambiguators we can give are expirationDate + serialNumber.
114
+ */
115
+ export declare function findCertBySha1(token: string, sha1: string): Promise<AscDistributionCert | null>;
54
116
  /**
55
117
  * List all provisioning profiles linked to a specific Apple-side certificate.
56
118
  * Used by the import-flow no-match-recovery menu to surface profiles that
@@ -0,0 +1,74 @@
1
+ export type BundleIdSource = 'pbxproj-release' | 'pbxproj-fallback' | 'plist' | 'capacitor-config';
2
+ export interface BundleIdCandidate {
3
+ value: string;
4
+ source: BundleIdSource;
5
+ /** Short human-readable label for the picker, e.g. "project.pbxproj (Release)". */
6
+ label: string;
7
+ }
8
+ export interface DetectedBundleIds {
9
+ /** PRODUCT_BUNDLE_IDENTIFIER from project.pbxproj, preferring Release config. */
10
+ pbxproj: BundleIdCandidate | null;
11
+ /**
12
+ * Info.plist CFBundleIdentifier when it's a literal value (not the common
13
+ * `$(PRODUCT_BUNDLE_IDENTIFIER)` placeholder, which we drop because it
14
+ * adds nothing the pbxproj source doesn't already cover).
15
+ */
16
+ plist: BundleIdCandidate | null;
17
+ /** capacitor.config.ts/json's appId — always present (it's a required arg). */
18
+ capacitor: BundleIdCandidate;
19
+ /**
20
+ * The best-guess Apple-side bundle ID, picked in priority order:
21
+ * pbxproj-release > pbxproj-fallback > plist > capacitor. Returned for
22
+ * convenience so callers don't have to re-implement the precedence.
23
+ */
24
+ recommended: BundleIdCandidate;
25
+ /**
26
+ * True when the recommended value differs from capacitor.config.appId.
27
+ * Used by the confirm-app-id step to decide whether to surface a question
28
+ * at all — when they match, nothing's worth asking about.
29
+ */
30
+ mismatch: boolean;
31
+ /**
32
+ * Deduplicated, ordered list of candidates ready to render as Select
33
+ * options. Empty list is impossible (capacitor is always included).
34
+ */
35
+ candidates: BundleIdCandidate[];
36
+ }
37
+ /**
38
+ * Parse `PRODUCT_BUNDLE_IDENTIFIER = "..."` lines from pbxproj content.
39
+ * Returns the Release-config value if present, else the first non-Release
40
+ * value. Returns null when no bundle id can be extracted.
41
+ *
42
+ * Looks like a re-implementation of pbxproj-parser.ts's resolveBundleId, but
43
+ * that one needs an XCConfigurationList id (it walks from a target). This
44
+ * one needs to work standalone given only the file contents — so it
45
+ * collects all PRODUCT_BUNDLE_IDENTIFIER values, groups by adjacent
46
+ * `name = Release`/`name = Debug` markers, and prefers Release. Less
47
+ * accurate for multi-target projects but good enough for the "what should
48
+ * we pre-fill" use case here.
49
+ */
50
+ export declare function parsePbxprojBundleId(pbxprojContent: string): BundleIdCandidate | null;
51
+ /**
52
+ * Parse Info.plist's CFBundleIdentifier from raw XML.
53
+ * Returns null when the file is empty, when CFBundleIdentifier is absent,
54
+ * or when it's a `$(PRODUCT_BUNDLE_IDENTIFIER)` variable reference (we drop
55
+ * the placeholder so the picker doesn't list a non-actionable option).
56
+ */
57
+ export declare function parseInfoPlistBundleId(plistContent: string): BundleIdCandidate | null;
58
+ /**
59
+ * Read project.pbxproj and Info.plist from the iOS dir and return all
60
+ * available bundle id candidates, plus the recommended one and a
61
+ * mismatch flag.
62
+ *
63
+ * Filesystem reads are best-effort — when either file is missing or
64
+ * unreadable, we silently skip that source. The capacitor candidate is
65
+ * always present.
66
+ */
67
+ export declare function detectIosBundleIds(opts: {
68
+ /** Project root (typically `process.cwd()`). */
69
+ cwd: string;
70
+ /** Subdirectory under cwd holding the iOS project (typically "ios"). */
71
+ iosDir: string;
72
+ /** Bundle id read from capacitor.config.ts/json — always known. */
73
+ capacitorAppId: string;
74
+ }): DetectedBundleIds;
@@ -25,6 +25,16 @@ export declare function openSaveFilePicker(opts: SaveFilePickerOptions): Promise
25
25
  * Accepts .jks, .keystore, and .p12 extensions.
26
26
  */
27
27
  export declare function openKeystorePicker(): Promise<string | null>;
28
+ /**
29
+ * Open the macOS native file picker filtered to .mobileprovision files.
30
+ * Returns the selected path, or null if the user cancelled.
31
+ *
32
+ * Used by the no-match-recovery "Use a .mobileprovision file from disk"
33
+ * option — covers users who have a profile downloaded somewhere outside
34
+ * Xcode's standard provisioning-profile directories (e.g. a downloads
35
+ * folder, an artifact from another machine, a shared team archive).
36
+ */
37
+ export declare function openMobileprovisionPicker(): Promise<string | null>;
28
38
  /**
29
39
  * Open the macOS native file picker filtered to Google Play service account
30
40
  * JSON files. Used by the Android onboarding "import existing SA" path.
@@ -86,6 +86,37 @@ export declare function scanProvisioningProfiles(homeDirOverride?: string): Prom
86
86
  * Pure function — no I/O.
87
87
  */
88
88
  export declare function matchIdentitiesToProfiles(identities: readonly SigningIdentity[], profiles: readonly DiscoveredProfile[]): IdentityProfileMatch[];
89
+ /**
90
+ * Compare a provisioning profile's bundle id against the app's concrete bundle
91
+ * id, honoring Apple's wildcard syntax. The mobileprovision parser leaves the
92
+ * asterisk in place after stripping the team-id prefix, so a wildcard profile
93
+ * arrives here as either the bare `*` (matches everything the team owns) or a
94
+ * suffix wildcard like `com.example.*` (matches `com.example.<anything>`).
95
+ *
96
+ * Exported so the file-picker validation in the Ink UI can reuse the same
97
+ * matching rule as `filterProfilesForApp` — otherwise a wildcard
98
+ * `.mobileprovision` picked manually would be hard-rejected even though the
99
+ * underlying profile is valid for the current app.
100
+ */
101
+ export declare function bundleIdMatches(profileBundleId: string, appId: string): boolean;
102
+ /**
103
+ * Filter profiles that are actually usable for a given Capacitor app + iOS
104
+ * distribution mode. Used by the import-existing flow to detect dead-end
105
+ * situations where an identity has profiles for a different app or the wrong
106
+ * distribution mode — in which case the no-match-recovery menu can offer
107
+ * "fetch / create via Apple" instead of dropping the user at an empty picker.
108
+ *
109
+ * `importDistribution` is null/undefined when the user hasn't picked yet —
110
+ * in that case any profileType is accepted.
111
+ *
112
+ * Bundle-id comparison goes through {@link bundleIdMatches} so wildcard
113
+ * profiles (the norm for ad_hoc/enterprise teams that share one profile
114
+ * across many apps) are accepted alongside literal-equality matches. Apple
115
+ * never issues wildcard `app_store` profiles in practice, so when the caller
116
+ * pins `importDistribution = 'app_store'` the conjunction naturally drops
117
+ * any ad_hoc/enterprise wildcards that happen to be installed.
118
+ */
119
+ export declare function filterProfilesForApp(profiles: readonly DiscoveredProfile[], appId: string, importDistribution: 'app_store' | 'ad_hoc' | null | undefined): DiscoveredProfile[];
89
120
  /**
90
121
  * Generate a cryptographically random passphrase suitable for wrapping the
91
122
  * exported PKCS#12. 32 bytes of entropy → 64-char hex string.
@@ -16,12 +16,52 @@ export interface OnboardingResult {
16
16
  /** Present only when outcome === 'completed'. */
17
17
  summary?: OnboardingCompletionSummary;
18
18
  }
19
- export type OnboardingStep = 'welcome' | 'platform-select' | 'adding-platform' | 'credentials-exist' | 'backing-up' | 'setup-method-select' | 'import-scanning' | 'import-distribution-mode' | 'import-pick-identity' | 'import-pick-profile' | 'import-no-match-recovery' | 'import-fetching-profile' | 'import-create-profile-only' | 'import-export-warning' | 'import-compiling-helper' | 'import-exporting' | 'api-key-instructions' | 'p8-method-select' | 'input-p8-path' | 'input-key-id' | 'input-issuer-id' | 'verifying-key' | 'creating-certificate' | 'cert-limit-prompt' | 'revoking-certificate' | 'creating-profile' | 'duplicate-profile-prompt' | 'deleting-duplicate-profiles' | 'saving-credentials' | 'detecting-ci-secrets' | 'ci-secrets-setup' | 'ci-secrets-target-select' | 'ask-ci-secrets' | 'checking-ci-secrets' | 'confirm-ci-secret-overwrite' | 'uploading-ci-secrets' | 'ci-secrets-failed' | 'ask-github-actions-setup' | 'confirm-secrets-push' | 'ask-export-env' | 'exporting-env' | 'confirm-env-export-overwrite' | 'overwrite-and-export-env' | 'pick-package-manager' | 'pick-build-script' | 'pick-build-script-custom' | 'preview-workflow-file' | 'view-workflow-diff' | 'writing-workflow-file' | 'ask-build' | 'requesting-build' | 'ai-analysis-prompt' | 'ai-analysis-running' | 'ai-analysis-result' | 'ai-analysis-result-scroll' | 'build-complete' | 'no-platform' | 'error';
19
+ export type OnboardingStep = 'welcome' | 'resume-prompt' | 'platform-select' | 'adding-platform' | 'credentials-exist' | 'backing-up' | 'setup-method-select' | 'confirm-app-id' | 'import-scanning' | 'import-distribution-mode' | 'import-pick-identity' | 'import-pick-profile' | 'import-validating-all-certs' | 'import-checking-apple-cert' | 'import-no-match-recovery' | 'import-portal-explanation' | 'import-provide-profile-path' | 'import-create-profile-only' | 'import-export-warning' | 'import-compiling-helper' | 'import-exporting' | 'api-key-instructions' | 'p8-method-select' | 'input-p8-path' | 'input-key-id' | 'input-issuer-id' | 'verifying-key' | 'creating-certificate' | 'cert-limit-prompt' | 'revoking-certificate' | 'creating-profile' | 'duplicate-profile-prompt' | 'deleting-duplicate-profiles' | 'saving-credentials' | 'detecting-ci-secrets' | 'ci-secrets-setup' | 'ci-secrets-target-select' | 'ask-ci-secrets' | 'checking-ci-secrets' | 'confirm-ci-secret-overwrite' | 'uploading-ci-secrets' | 'ci-secrets-failed' | 'ask-github-actions-setup' | 'confirm-secrets-push' | 'ask-export-env' | 'exporting-env' | 'confirm-env-export-overwrite' | 'overwrite-and-export-env' | 'pick-package-manager' | 'pick-build-script' | 'pick-build-script-custom' | 'preview-workflow-file' | 'view-workflow-diff' | 'writing-workflow-file' | 'ask-build' | 'requesting-build' | 'ai-analysis-prompt' | 'ai-analysis-running' | 'ai-analysis-result' | 'ai-analysis-result-scroll' | 'build-complete' | 'no-platform' | 'error';
20
20
  export type OnboardingErrorCategory = 'apple_api_unauthorized' | 'apple_api_rate_limited' | 'cert_limit_reached' | 'profile_creation_failed' | 'p8_invalid' | 'keychain_no_identities' | 'keychain_export_failed' | 'keychain_helper_compile_failed' | 'profile_no_match' | 'profile_read_failed' | 'unknown';
21
21
  export interface ApiKeyData {
22
22
  keyId: string;
23
23
  issuerId: string;
24
24
  }
25
+ /**
26
+ * Per-identity result of the eager Apple-side validation run. Populated by
27
+ * the `import-validating-all-certs` step useEffect, consumed by the two-
28
+ * table picker in `import-pick-identity`. Kept here (alongside the Step
29
+ * type) so the renderer and the validation logic share a single shape.
30
+ */
31
+ export interface EnrichedIdentityAvailability {
32
+ /** True when Apple's API returned a SHA1 match for this identity. */
33
+ available: boolean;
34
+ /**
35
+ * Stable reason code for unavailable identities. Drives the per-reason
36
+ * detail rendering in the unavailable table (e.g. notice about the
37
+ * Apple-managed signing constraint, or about private-key-missing).
38
+ */
39
+ reason?: 'expired' | 'managed' | 'not-visible' | 'check-failed' | 'no-private-key';
40
+ /** One-line summary shown in the Reason column of the unavailable table. */
41
+ reasonText?: string;
42
+ /** When available — Apple-side cert resource id, reused downstream. */
43
+ appleCertId?: string;
44
+ /**
45
+ * Apple-side cert name as returned by /v1/certificates. Useful when
46
+ * the local Keychain name differs from the portal name (e.g. multiple
47
+ * "iOS Distribution" certs in the same team — the portal column says
48
+ * exactly which one).
49
+ */
50
+ appleCertName?: string;
51
+ /**
52
+ * ISO timestamp from Apple's expiration field. Shown in the manual-
53
+ * portal walkthrough so the user can tell which row to click when
54
+ * multiple certs are listed.
55
+ */
56
+ appleCertExpirationDate?: string;
57
+ /**
58
+ * Full serial number from Apple. The portal shows it in the cert
59
+ * detail view; surfacing the last 8 chars here gives the user a
60
+ * concrete disambiguator without leaking the full 40-byte serial
61
+ * into the terminal.
62
+ */
63
+ appleCertSerialNumber?: string;
64
+ }
25
65
  export interface CertificateData {
26
66
  certificateId: string;
27
67
  expirationDate: string;
@@ -64,6 +104,28 @@ export interface OnboardingProgress {
64
104
  * Only meaningful when `setupMethod === 'import-existing'`.
65
105
  */
66
106
  importDistribution?: 'app_store' | 'ad_hoc';
107
+ /**
108
+ * When set, the user explicitly confirmed an iOS bundle id different from
109
+ * `capacitor.config.appId`. Used for Apple-side operations (cert lookup,
110
+ * profile filtering, `ensureBundleId`, `createProfile`) and as the key in
111
+ * the provisioning_map. The progress-file key and Capgo SaaS API calls
112
+ * still use `appId` so existing build commands continue to find these
113
+ * credentials without forcing the user to edit `capacitor.config`.
114
+ *
115
+ * Persisted so the confirm-app-id step doesn't re-ask on resume — once
116
+ * confirmed, the override sticks unless the configuration context (see
117
+ * `iosBundleIdContextAppId`) changes between CLI runs.
118
+ */
119
+ iosBundleIdOverride?: string;
120
+ /**
121
+ * Snapshot of `config.appId` at the time the user confirmed the
122
+ * `iosBundleIdOverride`. On the next run we compare this to the current
123
+ * `config.appId`; if it changed (user renamed the app, added/removed a
124
+ * dev-tunnel suffix, etc.) the saved override is stale and we re-ask
125
+ * via the confirm-app-id step. Without this we'd silently keep using a
126
+ * bundle id the user already moved on from.
127
+ */
128
+ iosBundleIdContextAppId?: string;
67
129
  completedSteps: {
68
130
  apiKeyVerified?: ApiKeyData;
69
131
  certificateCreated?: CertificateData;
@@ -1,7 +1,25 @@
1
1
  import type { FC } from 'react';
2
2
  import type { OnboardingProgress, OnboardingResult } from '../types.js';
3
3
  interface AppProps {
4
+ /**
5
+ * Capgo lookup key (progress files, saved credentials, Capgo SaaS build
6
+ * API). Resolved by `getAppId()`, which prefers
7
+ * `config.plugins.CapacitorUpdater.appId` over `config.appId` so dev-tunnel
8
+ * sandboxes can override the Capgo-side identifier without renaming the
9
+ * iOS bundle. Do NOT use for Apple-side operations — see
10
+ * `iosBundleIdInitial`.
11
+ */
4
12
  appId: string;
13
+ /**
14
+ * Default value for the iOS bundle ID used for Apple-side operations
15
+ * (cert lookup, profile filtering, ensureBundleId, createProfile, and the
16
+ * provisioning_map key). Sourced from `config.appId` directly — what
17
+ * `cap sync` writes into project.pbxproj's PRODUCT_BUNDLE_IDENTIFIER.
18
+ * The user can override at the `confirm-app-id` step when pbxproj and
19
+ * config.appId disagree. command.ts falls back to `appId` if config.appId
20
+ * is missing, so this prop is always a valid string.
21
+ */
22
+ iosBundleIdInitial: string;
5
23
  initialProgress: OnboardingProgress | null;
6
24
  /** Resolved iOS directory from capacitor.config (defaults to 'ios') */
7
25
  iosDir: string;
@@ -6,6 +6,36 @@ export declare const Divider: FC<{
6
6
  export declare const BOX_HEADER_ROWS = 5;
7
7
  export declare const COMPACT_HEADER_ROWS = 1;
8
8
  export declare const WIZARD_PADDING_ROWS = 2;
9
+ /**
10
+ * Minimal in-house Table component. Auto-sizes each column to the widest
11
+ * value (header or any row cell) up to `maxColumnWidth`, truncates with
12
+ * an ellipsis when a cell exceeds that width, and renders box-drawing
13
+ * borders.
14
+ *
15
+ * Why inline instead of `ink-table`: the published `ink-table@3.1.0` is
16
+ * CommonJS and modern `ink` (v5+) is ESM with top-level await, so bundling
17
+ * fails. This component is the small subset of ink-table's API we need
18
+ * (rows of plain string cells) without the compat headache.
19
+ *
20
+ * The `data` rows must share a single key order so columns line up — we
21
+ * derive the column list from the first row's keys.
22
+ *
23
+ * `cellColor` runs per-cell and returns an Ink color name (or undefined
24
+ * for default). Used by the available/unavailable-certs tables to colour
25
+ * the status column green/red while keeping Name/Team dim.
26
+ */
27
+ export interface TableProps {
28
+ data: Record<string, string>[];
29
+ /** Hard cap on column width before truncation. Default 50. */
30
+ maxColumnWidth?: number;
31
+ /** Optional per-cell color function. */
32
+ cellColor?: (column: string, value: string, rowIndex: number) => string | undefined;
33
+ /** Optional per-cell dim flag (defaults to false). */
34
+ cellDim?: (column: string, value: string, rowIndex: number) => boolean;
35
+ /** Padding inside each cell (left/right). Default 1. */
36
+ cellPadding?: number;
37
+ }
38
+ export declare const Table: FC<TableProps>;
9
39
  export declare const SpinnerLine: FC<{
10
40
  text: string;
11
41
  }>;
@@ -29,8 +59,40 @@ export declare const AiResultBanner: FC<{
29
59
  */
30
60
  export declare const FilteredTextInput: FC<{
31
61
  placeholder?: string;
62
+ /**
63
+ * Blacklist of characters to strip from input. Each char in this string is
64
+ * removed from the buffer after every keystroke. Used for casual filtering
65
+ * (e.g. stripping `=` from env-var values).
66
+ */
32
67
  filter?: string;
68
+ /**
69
+ * Whitelist regex matched per-character. Anything not matching is dropped.
70
+ * Takes precedence over `filter` when both are set. Used when the field has
71
+ * a tight format (Apple Key ID is exactly 10 alphanumeric chars; Issuer ID
72
+ * is a UUID; etc.) so users can't even type invalid characters.
73
+ */
74
+ allowedPattern?: RegExp;
75
+ /**
76
+ * Hard cap on input length. Extra characters past the cap are dropped
77
+ * silently (paste-safe). Pair with `allowedPattern` for known-format fields
78
+ * — e.g. Apple Key ID has `maxLength=10` so a paste of "Key ID: KDTXMK292V"
79
+ * truncates to the first 10 valid chars after filtering.
80
+ */
81
+ maxLength?: number;
82
+ /**
83
+ * Post-filter transform applied to the entire buffer after each keystroke.
84
+ * Most common use: `(s) => s.toUpperCase()` for fields that are case-
85
+ * insensitive but conventionally uppercase. Runs after filter + maxLength.
86
+ */
87
+ transform?: (value: string) => string;
33
88
  mask?: boolean;
89
+ /**
90
+ * Pre-fills the input. Used when the user is editing an already-entered
91
+ * value (e.g. fixing a typo in their ASC Key ID / Issuer ID after a
92
+ * verifying-key failure) so they don't have to retype everything.
93
+ * Backspace works normally to delete from the pre-filled value.
94
+ */
95
+ initialValue?: string;
34
96
  onSubmit: (value: string) => void;
35
97
  }>;
36
98
  export declare const Header: FC<{
@@ -6,6 +6,15 @@ export declare function useTerminalSize(): {
6
6
  };
7
7
  export interface OnboardingShellProps {
8
8
  appId: string;
9
+ /**
10
+ * iOS-side bundle id default — sourced from `config.appId` (top-level), which
11
+ * is what `cap sync` writes into `PRODUCT_BUNDLE_IDENTIFIER`. Distinct from
12
+ * `appId` above, which `getAppId()` may resolve to
13
+ * `config.plugins.CapacitorUpdater.appId` (a Capgo lookup key — wrong for
14
+ * Apple signing). Threaded down to the iOS OnboardingApp; the Android app
15
+ * ignores it.
16
+ */
17
+ iosBundleIdInitial: string;
9
18
  iosDir: string;
10
19
  androidDir: string;
11
20
  apikey?: string;
@@ -3,6 +3,30 @@ export interface SelectOption {
3
3
  label: string;
4
4
  value: string;
5
5
  }
6
+ /**
7
+ * Why the wizard ended up on the no-match recovery menu. Drives the Alert
8
+ * + hint copy in `ImportNoMatchRecoveryStep` so each route gets accurate
9
+ * context — previously the screen claimed "no profile linked to this cert"
10
+ * even when the parent had just logged "Apple linked them to X" (cases 3
11
+ * and 4 below). Set by the parent right before each setStep call; absent
12
+ * (undefined) is treated as the legacy `no-profile-on-disk` default for
13
+ * back-compat with call sites that haven't been audited yet.
14
+ *
15
+ * - 'no-profile-on-disk' : identity picked, no usable on-disk
16
+ * profile, and no ASC key to query Apple.
17
+ * - 'apple-no-cert-match' : findCertIdBySha1 returned null — Apple
18
+ * doesn't recognize this cert.
19
+ * - 'apple-no-profiles-linked' : Apple has the cert but zero profiles
20
+ * linked to it.
21
+ * - 'apple-bundle-mismatch' : Apple has profiles but none target the
22
+ * current app's bundle id.
23
+ * - 'apple-distribution-mismatch': Apple has profiles for this bundle id
24
+ * but none in the requested distribution
25
+ * mode (app_store vs ad_hoc).
26
+ * - 'apple-other' : catch-all when none of the specific
27
+ * filters above explain the empty result.
28
+ */
29
+ export type NoMatchReason = 'no-profile-on-disk' | 'apple-no-cert-match' | 'apple-no-profiles-linked' | 'apple-bundle-mismatch' | 'apple-distribution-mismatch' | 'apple-other';
6
30
  export declare const ImportScanningStep: FC;
7
31
  export interface ImportDistributionModeStepProps {
8
32
  dense?: boolean;
@@ -28,11 +52,19 @@ export declare const ImportPickProfileStep: FC<ImportPickProfileStepProps>;
28
52
  export interface ImportNoMatchRecoveryStepProps {
29
53
  identityName: string;
30
54
  options: SelectOption[];
55
+ /**
56
+ * Why the wizard ended up here. Optional for back-compat — undefined
57
+ * renders the legacy `no-profile-on-disk` wording.
58
+ */
59
+ reason?: NoMatchReason;
60
+ /** Concrete iOS bundle id; used by the bundle-mismatch + distribution-mismatch alerts. */
61
+ appId?: string;
62
+ /** Active distribution mode; used by the distribution-mismatch alert. */
63
+ importDistribution?: 'app_store' | 'ad_hoc' | null;
31
64
  dense?: boolean;
32
65
  onChange: (value: string) => void;
33
66
  }
34
67
  export declare const ImportNoMatchRecoveryStep: FC<ImportNoMatchRecoveryStepProps>;
35
- export declare const ImportFetchingProfileStep: FC;
36
68
  export declare const ImportCreateProfileOnlyStep: FC;
37
69
  export interface ImportExportWarningStepProps {
38
70
  identityName: string;