@capgo/cli 8.4.1 → 8.5.1

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": "8.4.1",
4
+ "version": "8.5.1",
5
5
  "description": "A CLI to upload to capgo servers",
6
6
  "author": "Martin martin@capgo.app",
7
7
  "license": "Apache 2.0",
@@ -72,6 +72,7 @@
72
72
  "test:upload": "bun test/test-upload-validation.mjs",
73
73
  "test:fail-on-incompatible": "bun test/test-fail-on-incompatible.mjs",
74
74
  "test:credentials": "bun test/test-credentials.mjs",
75
+ "test:asc-key-protocol": "bun test/test-asc-key-protocol.mjs",
75
76
  "test:credentials-validation": "bun test/test-credentials-validation.mjs",
76
77
  "test:android-service-account-validation": "bun test/test-android-service-account-validation.mjs",
77
78
  "test:build-zip-filter": "bun test/test-build-zip-filter.mjs",
@@ -138,7 +139,7 @@
138
139
  "test:ios-verify-app": "bun test/test-ios-verify-app.mjs",
139
140
  "test:platform-flow-contract": "bun test/test-platform-flow-contract.mjs",
140
141
  "test:tail-engine-shared": "bun test/test-tail-engine-shared.mjs",
141
- "test": "bun run build && bun run test:helper-dce && 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:preview-qr && 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:apple-api-app-list && bun run test:app-verification && bun run test:pbxproj-parser && bun run test:ai-log-capture && bun run test:ai-analyze-flow && bun run test:ai-sse-parser && bun run test:ai-render-markdown && bun run test:ai-stream-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 && bun run test:ai-analyze-stream && bun run test:support-mailto && bun run test:support-redact && bun run test:support-internal-log && bun run test:support-help-menu && bun run test:support-contact && bun run test:support-bundle-files && bun run test:self-update && bun run test:update-prompt && bun run test:apple-api-cert-create && bun run test:android-tail-engine && bun run test:android-tail-render && bun run test:android-tail-routing && bun run test:dev-gate-stripped && bun run test:frame-fit-ios-shared && bun run test:ios-confirm-app-id && bun run test:ios-create-new && bun run test:ios-e2e && bun run test:ios-flow-contract && bun run test:ios-import-discovery && bun run test:ios-import-export && bun run test:ios-import-pickers && bun run test:ios-import-recovery && bun run test:ios-recovery && bun run test:ios-resume && bun run test:ios-tail-handoff && bun run test:ios-tui-render && bun run test:p8-error && bun run test:ios-tui-routing && bun run test:ios-updater-sync-validation && bun run test:ios-verify-app && bun run test:platform-flow-contract && bun run test:tail-engine-shared",
142
+ "test": "bun run build && bun run test:helper-dce && 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:preview-qr && 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:asc-key-protocol && bun run test:apple-api-import-helpers && bun run test:bundle-id-detector && bun run test:apple-api-app-list && bun run test:app-verification && bun run test:pbxproj-parser && bun run test:ai-log-capture && bun run test:ai-analyze-flow && bun run test:ai-sse-parser && bun run test:ai-render-markdown && bun run test:ai-stream-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 && bun run test:ai-analyze-stream && bun run test:support-mailto && bun run test:support-redact && bun run test:support-internal-log && bun run test:support-help-menu && bun run test:support-contact && bun run test:support-bundle-files && bun run test:self-update && bun run test:update-prompt && bun run test:apple-api-cert-create && bun run test:android-tail-engine && bun run test:android-tail-render && bun run test:android-tail-routing && bun run test:dev-gate-stripped && bun run test:frame-fit-ios-shared && bun run test:ios-confirm-app-id && bun run test:ios-create-new && bun run test:ios-e2e && bun run test:ios-flow-contract && bun run test:ios-import-discovery && bun run test:ios-import-export && bun run test:ios-import-pickers && bun run test:ios-import-recovery && bun run test:ios-recovery && bun run test:ios-resume && bun run test:ios-tail-handoff && bun run test:ios-tui-render && bun run test:p8-error && bun run test:ios-tui-routing && bun run test:ios-updater-sync-validation && bun run test:ios-verify-app && bun run test:platform-flow-contract && bun run test:tail-engine-shared",
142
143
  "test:build-platform-selection": "bun test/test-build-platform-selection.mjs",
143
144
  "test:ai-log-capture": "bun test/test-ai-log-capture.mjs",
144
145
  "test:ai-analyze-flow": "bun test/test-ai-analyze-flow.mjs",
@@ -175,8 +176,8 @@
175
176
  "string-width": "^8.2.1"
176
177
  },
177
178
  "optionalDependencies": {
178
- "@capgo/cli-keychain-darwin-arm64": "^1.0.0",
179
- "@capgo/cli-keychain-darwin-x64": "^1.0.0"
179
+ "@capgo/cli-helper-darwin-arm64": "^1.1.0",
180
+ "@capgo/cli-helper-darwin-x64": "^1.1.0"
180
181
  },
181
182
  "devDependencies": {
182
183
  "@antfu/eslint-config": "^9.0.0",
@@ -0,0 +1,17 @@
1
+ export interface CreateAppleKeyOptions {
2
+ apikey?: string;
3
+ /** When set, the captured key is saved into this app's iOS build credentials. */
4
+ appId?: string;
5
+ /** Save into the per-project .capgo-credentials.json instead of the global file. */
6
+ local?: boolean;
7
+ /** Print the captured Key ID / Issuer ID / .p8 path as JSON on stdout. */
8
+ json?: boolean;
9
+ }
10
+ /**
11
+ * Guided creation of an App Store Connect **team** API key. Launches the native
12
+ * macOS helper (a precompiled Swift app that walks the user through Apple's web
13
+ * UI in an embedded browser), streams its stats protocol to PostHog, and
14
+ * captures the resulting key — issuer id, key id and the one-time .p8 — without
15
+ * the user ever copy-pasting a credential.
16
+ */
17
+ export declare function createAppleKeyCommand(options?: CreateAppleKeyOptions): Promise<void>;
@@ -0,0 +1,146 @@
1
+ import type { AscCredentials, AscEventLine, AscLogLine } from './protocol';
2
+ import type { CodesignRunner } from '../macos-signing';
3
+ /**
4
+ * Where a resolved helper binary came from. `package` is the signed npm bundle —
5
+ * the ONLY source we spawn-time signature-verify. `override`/`cache`/`local` are
6
+ * dev/CI paths (unsigned or ad-hoc) that skip verification.
7
+ */
8
+ export type AscHelperSource = 'override' | 'package' | 'cache' | 'local';
9
+ export interface ResolvedAscHelper {
10
+ /** Inner executable to spawn. */
11
+ binary: string;
12
+ /** Where it came from (drives whether we verify the signature at spawn). */
13
+ source: AscHelperSource;
14
+ /**
15
+ * The enclosing `.app` bundle path — present only for the signed `package`
16
+ * source, where it is the target of the designated-requirement check.
17
+ */
18
+ bundlePath?: string;
19
+ }
20
+ /** Thrown when the helper is requested on a non-macOS host. */
21
+ export declare class NotMacOSError extends Error {
22
+ constructor();
23
+ }
24
+ export declare function isMacOS(): boolean;
25
+ /**
26
+ * Locate the precompiled Swift helper, in priority order:
27
+ * 1. `CAPGO_ASC_KEY_HELPER_PATH` — explicit override (dev / CI / tests). Only
28
+ * honored in dev builds (DCE'd from release bundles, like the keychain
29
+ * helper's CAPGO_KEYCHAIN_HELPER_PATH); skips signature verification.
30
+ * 2. The signed `CapgoAscKeyHelper.app` in the arch-matching
31
+ * `@capgo/cli-helper-darwin-*` package — verified at spawn time.
32
+ * 3. `~/.capgo/asc-key-helper/<binary>` — the legacy cached download location.
33
+ * 4. A local `swift build` of the vendored package (dev, running from src).
34
+ * Returns `null` (caller shows install / manual guidance) when none exists OR on
35
+ * macOS < 14 — the packaged SwiftUI/WKWebView app requires macOS 14, so the
36
+ * guided path must never be offered where it can't launch.
37
+ *
38
+ * Synchronous on purpose: it gates the guided path in several call sites that
39
+ * cannot await. Signature verification of the package source is deferred to
40
+ * {@link runAscKeyHelper} (just before spawn), which can await.
41
+ */
42
+ export declare function resolveAscHelper(): ResolvedAscHelper | null;
43
+ /**
44
+ * Path-only resolver kept for the many synchronous gating call sites. Returns
45
+ * the inner executable to spawn, or `null`. See {@link resolveAscHelper} for the
46
+ * source metadata that drives spawn-time signature verification.
47
+ */
48
+ export declare function resolveHelperBinary(): string | null;
49
+ /** Why the guided helper can't be offered. See {@link probeGuidedHelper}. */
50
+ export type GuidedHelperUnusableReason = 'not-macos' /** Not a Mac — the helper is a macOS app (Linux/Windows). */ | 'unsupported-os' /** macOS < 14 — the SwiftUI/WKWebView app can't launch. */ | 'not-installed' /** No helper resolved (optional package absent, no cache/build). */ | 'untrusted'; /** Helper present but its Developer-ID signature/team didn't verify. */
51
+ export type GuidedHelperProbe = {
52
+ usable: true;
53
+ source: AscHelperSource;
54
+ } | {
55
+ usable: false;
56
+ reason: GuidedHelperUnusableReason;
57
+ detail?: string;
58
+ };
59
+ export interface ProbeGuidedHelperOptions {
60
+ /**
61
+ * Inject a pre-resolved helper instead of calling {@link resolveAscHelper}
62
+ * (tests). `null` models "nothing resolved". Omit in production.
63
+ */
64
+ resolved?: ResolvedAscHelper | null;
65
+ /** Forward an injected codesign runner to signature verification (tests). */
66
+ codesignRunner?: CodesignRunner;
67
+ }
68
+ /**
69
+ * Decide — once, up front — whether guided ASC-key creation can ACTUALLY run on
70
+ * this machine, so the onboarding flow never offers the guided path it would
71
+ * then have to reject. Unlike the sync {@link resolveHelperBinary} existence
72
+ * check, this also verifies the Developer-ID signature + Capgo team of a
73
+ * packaged bundle, so a helper that is installed but wrongly signed / wrong-team /
74
+ * tampered is reported `untrusted` (treated exactly like not-installed: the
75
+ * guided option is withheld and the user goes straight to manual instructions,
76
+ * the same as on Linux).
77
+ *
78
+ * Async because the signature check spawns `codesign`. Mirrors the spawn-time
79
+ * verification in {@link runAscKeyHelper} (same bundle id, same verifier), so a
80
+ * `usable` verdict here means the later spawn won't be refused for trust.
81
+ */
82
+ export declare function probeGuidedHelper(options?: ProbeGuidedHelperOptions): Promise<GuidedHelperProbe>;
83
+ /**
84
+ * Dismiss the helper window. The outcome resolves as soon as the helper delivers
85
+ * its terminal `result` line — BEFORE the process exits — so the helper can keep
86
+ * its window open (showing a success screen) while the CLI advances. The caller
87
+ * invokes `close()` once the flow has moved on (e.g. the key verified) to close
88
+ * the window; until then it stays open. Safe to call more than once / after the
89
+ * window already closed.
90
+ */
91
+ export type CloseHelper = () => void;
92
+ export interface AscHelperSuccess {
93
+ ok: true;
94
+ credentials: AscCredentials;
95
+ runId: string;
96
+ /** Number of stats events the helper emitted during the run. */
97
+ eventCount: number;
98
+ /** Number of diagnostic `log` lines routed to the internal support log. */
99
+ logCount: number;
100
+ /** Dismiss the still-open helper window. See {@link CloseHelper}. */
101
+ close: CloseHelper;
102
+ }
103
+ export interface AscHelperFailure {
104
+ ok: false;
105
+ errorCode: string;
106
+ message: string;
107
+ runId: string;
108
+ /** Number of diagnostic `log` lines routed to the internal support log. */
109
+ logCount: number;
110
+ /** Dismiss the helper window (no-op once it has exited). See {@link CloseHelper}. */
111
+ close: CloseHelper;
112
+ }
113
+ export type AscHelperOutcome = AscHelperSuccess | AscHelperFailure;
114
+ export interface RunAscKeyHelperOptions {
115
+ /** Pre-resolved helper binary path (tests inject a fake; prod auto-resolves). */
116
+ helperPathOverride?: string;
117
+ /** API key for analytics attribution; falls back to the saved key. */
118
+ apikey?: string;
119
+ /** Optional observer for every event line (UI progress / tests). */
120
+ onEvent?: (event: AscEventLine) => void;
121
+ /** Optional observer for every diagnostic log line (UI / tests). */
122
+ onLog?: (line: AscLogLine) => void;
123
+ /** Forward events to PostHog via trackEvent. Defaults to true. */
124
+ forwardToAnalytics?: boolean;
125
+ /**
126
+ * Append diagnostic `log` lines (and a per-run summary) to the CLI's internal
127
+ * support log via {@link appendInternalLog}. Defaults to true. The append is
128
+ * best-effort and no-ops when no internal log has been started for this run.
129
+ */
130
+ forwardToInternalLog?: boolean;
131
+ /**
132
+ * Abort signal. When it fires — e.g. the onboarding TUI unmounts because the
133
+ * user quit — the helper child is terminated (SIGTERM, then SIGKILL) so its
134
+ * stdio pipes stop keeping the CLI process alive. Without this the CLI hangs
135
+ * after exit while the helper window is still open.
136
+ */
137
+ signal?: AbortSignal;
138
+ }
139
+ /**
140
+ * Launch the precompiled helper, stream its NDJSON stats protocol, forward each
141
+ * `event` line to PostHog, and resolve with the credentials from the terminal
142
+ * `result` line. The private key is returned to the caller but NEVER forwarded
143
+ * to analytics. Never rejects on a helper-side failure — returns a structured
144
+ * failure outcome instead (it throws only for {@link NotMacOSError}).
145
+ */
146
+ export declare function runAscKeyHelper(options?: RunAscKeyHelperOptions): Promise<AscHelperOutcome>;
@@ -0,0 +1,97 @@
1
+ /** Protocol version understood by this CLI. Bumped on breaking changes. */
2
+ export declare const ASC_PROTOCOL_VERSION = 1;
3
+ /** Analytics channel every forwarded helper event is sent on. */
4
+ export declare const ASC_KEY_CHANNEL = "app-store-connect-key";
5
+ /** A non-sensitive analytics event emitted by the helper. */
6
+ export interface AscEventLine {
7
+ capgoAscKey: number;
8
+ kind: 'event';
9
+ /** Milliseconds since the helper started. */
10
+ ts: number;
11
+ /** Correlates every line of a single helper run. */
12
+ runId: string;
13
+ /** snake_case event name, e.g. `step_changed`, `validation_succeeded`. */
14
+ name: string;
15
+ /** Non-sensitive properties. NEVER contains the private key. */
16
+ props: Record<string, unknown>;
17
+ }
18
+ /** Severity levels a helper diagnostic `log` line may carry. */
19
+ export declare const ASC_LOG_LEVELS: readonly ["debug", "info", "warn", "error"];
20
+ export type AscLogLevel = (typeof ASC_LOG_LEVELS)[number];
21
+ /**
22
+ * A verbose diagnostic line. Unlike an `event` (which feeds PostHog analytics),
23
+ * a `log` line is routed into the CLI's **internal support log** — the bundle a
24
+ * user emails to support when a run goes wrong. Use it generously for anything
25
+ * that helps a human diagnose a stuck/failed run after the fact: a finder that
26
+ * matched nothing, an unexpected navigation, the detail of a validation error.
27
+ * It is NOT analytics and, like an event, NEVER carries the private key.
28
+ */
29
+ export interface AscLogLine {
30
+ capgoAscKey: number;
31
+ kind: 'log';
32
+ /** Milliseconds since the helper started. */
33
+ ts: number;
34
+ /** Correlates every line of a single helper run. */
35
+ runId: string;
36
+ /** Severity, defaulting to `info` when the helper omits/garbles it. */
37
+ level: AscLogLevel;
38
+ /** Human-readable diagnostic message. */
39
+ message: string;
40
+ /** Optional structured context. NEVER contains the private key. */
41
+ props: Record<string, unknown>;
42
+ }
43
+ /** The captured credentials, delivered on the terminal success line. */
44
+ export interface AscCredentials {
45
+ keyId: string;
46
+ issuerId: string;
47
+ privateKey: string;
48
+ }
49
+ /** Terminal line: success carries credentials, failure carries an error. */
50
+ export interface AscResultLine {
51
+ capgoAscKey: number;
52
+ kind: 'result';
53
+ ts: number;
54
+ runId: string;
55
+ ok: boolean;
56
+ keyId?: string;
57
+ issuerId?: string;
58
+ privateKey?: string;
59
+ errorCode?: string;
60
+ message?: string;
61
+ }
62
+ export type AscProtocolLine = AscEventLine | AscLogLine | AscResultLine;
63
+ /**
64
+ * Parse a single raw stdout line into a protocol envelope, or `null` when the
65
+ * line is not part of the protocol (blank line, incidental chatter, wrong
66
+ * version, or malformed JSON). Never throws — a misbehaving helper must not
67
+ * crash the CLI.
68
+ */
69
+ export declare function parseAscProtocolLine(line: string): AscProtocolLine | null;
70
+ /**
71
+ * Incremental line splitter for a streamed stdout. Push raw chunks as they
72
+ * arrive; get back the protocol lines completed by that chunk. Partial trailing
73
+ * data is buffered until its newline arrives. Call {@link flush} at EOF to parse
74
+ * any final newline-less remainder.
75
+ */
76
+ export declare class AscProtocolParser {
77
+ private buffer;
78
+ push(chunk: string): AscProtocolLine[];
79
+ flush(): AscProtocolLine[];
80
+ }
81
+ /**
82
+ * Build the `trackEvent` tags for a forwarded helper event: the helper's
83
+ * `props` (secret-stripped + scalar-coerced) plus protocol context. Exported
84
+ * for testing.
85
+ */
86
+ export declare function buildEventTags(event: AscEventLine): Record<string, string | number | boolean>;
87
+ /**
88
+ * Map a helper event line to a `trackEvent` input. The `event` field is a
89
+ * human-readable Title Case rendering of the snake_case name (e.g.
90
+ * `step_changed` -> "Step Changed"), under the {@link ASC_KEY_CHANNEL} channel.
91
+ */
92
+ export declare function ascEventToTrack(event: AscEventLine): {
93
+ channel: string;
94
+ event: string;
95
+ icon: string;
96
+ tags: Record<string, string | number | boolean>;
97
+ };
@@ -1,2 +1,2 @@
1
1
  import type { OnboardingProgress, OnboardingStep } from '../types.js';
2
- export declare function getIosResumeStep(progress: OnboardingProgress | null): OnboardingStep;
2
+ export declare function getIosResumeStep(progress: OnboardingProgress | null, canAutomate?: boolean): OnboardingStep;
@@ -122,6 +122,13 @@ export declare function filterProfilesForApp(profiles: readonly DiscoveredProfil
122
122
  * exported PKCS#12. 32 bytes of entropy → 64-char hex string.
123
123
  */
124
124
  export declare function generateP12Passphrase(): string;
125
+ /**
126
+ * Bundle identifier of the App Store Connect key helper's CapgoAscKeyHelper.app.
127
+ * Pinned in its designated requirement exactly like the keychain helper above —
128
+ * same team, same Developer ID, different bundle id. Must match
129
+ * cli/scripts/package-asc-key-helper-app.sh and publish_cli_helper.yml's sign step.
130
+ */
131
+ export declare const ASC_KEY_HELPER_BUNDLE_IDENTIFIER = "app.capgo.asc-key-helper";
125
132
  /**
126
133
  * Map a Node `process.arch` value to the matching helper package name, or
127
134
  * null when no precompiled helper exists for that architecture.
@@ -129,14 +136,16 @@ export declare function generateP12Passphrase(): string;
129
136
  export declare function helperPackageName(arch: string): string | null;
130
137
  /**
131
138
  * codesign designated requirement asserting: the exact helper bundle identifier
132
- * (app.capgo.cli.helper), an Apple-rooted chain, a Developer ID Application leaf
133
- * cert (OID 1.2.840.113635.100.6.1.13), and the given Apple Team ID as the
134
- * signing team. The identifier clause is what scopes the requirement to THIS
135
- * binary — without it, any other binary signed with Capgo's Developer ID cert
136
- * (a future tool, a leaked artifact) would also satisfy the check.
137
- */
138
- export declare function helperSignatureRequirement(teamId?: string): string;
139
- interface CodesignRunner {
139
+ * (defaults to the keychain helper's app.capgo.cli.helper), an Apple-rooted
140
+ * chain, a Developer ID Application leaf cert (OID 1.2.840.113635.100.6.1.13),
141
+ * and the given Apple Team ID as the signing team. The identifier clause is what
142
+ * scopes the requirement to THIS binary — without it, any other binary signed
143
+ * with Capgo's Developer ID cert (a future tool, a leaked artifact) would also
144
+ * satisfy the check. Pass `bundleIdentifier` to scope it to a different Capgo
145
+ * helper (e.g. the ASC key helper) signed with the same Developer ID + team.
146
+ */
147
+ export declare function helperSignatureRequirement(teamId?: string, bundleIdentifier?: string): string;
148
+ export interface CodesignRunner {
140
149
  (args: readonly string[]): Promise<SpawnResult>;
141
150
  }
142
151
  export interface ResolveHelperBinaryOptions {
@@ -158,10 +167,36 @@ export interface ResolveHelperBinaryOptions {
158
167
  *
159
168
  * Resolution order:
160
169
  * 1. CAPGO_KEYCHAIN_HELPER_PATH (dev builds only — see the build-time flag)
161
- * 2. The arch-matching @capgo/cli-keychain-darwin-* optional dependency
170
+ * 2. The arch-matching @capgo/cli-helper-darwin-* optional dependency
162
171
  * 3. Hard error with install guidance. There is no compile fallback.
163
172
  */
164
173
  export declare function resolveHelperBinary(options?: ResolveHelperBinaryOptions): Promise<string>;
174
+ export interface VerifyAppBundleSignatureOptions {
175
+ /**
176
+ * Bundle identifier to pin in the designated requirement (e.g.
177
+ * app.capgo.cli.helper for the keychain helper, app.capgo.asc-key-helper for
178
+ * the ASC key helper). Both are signed with the same Developer ID + team.
179
+ */
180
+ bundleIdentifier: string;
181
+ /** Human-readable name for the helper, used in the thrown error message. */
182
+ label?: string;
183
+ /** Extra guidance appended to the error message (e.g. a reinstall hint). */
184
+ reinstallHint?: string;
185
+ /** Override the codesign spawn (tests). */
186
+ codesignRunner?: CodesignRunner;
187
+ }
188
+ /**
189
+ * Verify an app bundle's (or binary's) code signature against Capgo's designated
190
+ * requirement (Apple-rooted chain + Developer ID Application leaf + Capgo Team ID
191
+ * + the given bundle identifier). macOS validates the certificate chain and the
192
+ * seal, so this also detects post-install tampering. Throws — never returns —
193
+ * on any failure, so callers can verify-then-spawn safely.
194
+ *
195
+ * Shared by the keychain helper and the App Store Connect key helper: both ship
196
+ * inside the same npm package, signed with the same Developer ID, distinguished
197
+ * only by their bundle identifiers.
198
+ */
199
+ export declare function verifyAppBundleSignature(bundlePath: string, options: VerifyAppBundleSignatureOptions): Promise<void>;
165
200
  /**
166
201
  * Output shape from the Swift helper's stdout — always emitted as one line of
167
202
  * JSON regardless of success or failure. See cli-helper/src/helper.swift for
@@ -204,7 +239,7 @@ export interface ExportP12Options {
204
239
  * runs against the same identity from the same binary are silent.
205
240
  *
206
241
  * Internally runs the precompiled, signature-verified `helper keychain-export`
207
- * subcommand from the arch-matching `@capgo/cli-keychain-darwin-*` package.
242
+ * subcommand from the arch-matching `@capgo/cli-helper-darwin-*` package.
208
243
  *
209
244
  * @param targetSha1 SHA1 of the identity to export (from {@link listSigningIdentities})
210
245
  * @param options See {@link ExportP12Options}
@@ -20,7 +20,7 @@ export declare function deleteProgress(appId: string, baseDir?: string): Promise
20
20
  * into the create-new path's `creating-certificate` step (which would trigger
21
21
  * the Apple 3-cert-limit error for users at the limit).
22
22
  */
23
- export declare function getResumeStep(progress: OnboardingProgress | null): OnboardingStep;
23
+ export declare function getResumeStep(progress: OnboardingProgress | null, canAutomate?: boolean): OnboardingStep;
24
24
  /**
25
25
  * Pure routing decision used by the `import-scanning` useEffect to skip
26
26
  * questions the user already answered on a previous attempt.
@@ -17,7 +17,7 @@ export interface OnboardingResult {
17
17
  /** Present only when outcome === 'completed'. */
18
18
  summary?: OnboardingCompletionSummary;
19
19
  }
20
- export type OnboardingStep = 'welcome' | 'resume-prompt' | 'platform-select' | 'adding-platform' | 'credentials-exist' | 'backing-up' | 'setup-method-select' | '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-exporting' | 'api-key-instructions' | 'p8-method-select' | 'input-p8-path' | 'input-key-id' | 'input-issuer-id' | 'verifying-key' | 'verify-app' | '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' | 'support-confirm' | 'support-log-view' | 'support-uploading';
20
+ export type OnboardingStep = 'welcome' | 'resume-prompt' | 'platform-select' | 'adding-platform' | 'credentials-exist' | 'backing-up' | 'setup-method-select' | '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-exporting' | 'p8-source-select' | 'asc-key-generating' | 'asc-key-created' | 'api-key-instructions' | 'p8-method-select' | 'input-p8-path' | 'input-key-id' | 'input-issuer-id' | 'verifying-key' | 'verify-app' | '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' | 'support-confirm' | 'support-log-view' | 'support-uploading';
21
21
  export type OnboardingErrorCategory = 'apple_api_unauthorized' | 'apple_api_rate_limited' | 'cert_limit_reached' | 'profile_creation_failed' | 'p8_invalid' | 'keychain_no_identities' | 'keychain_export_failed' | 'profile_no_match' | 'profile_read_failed' | 'unknown';
22
22
  export interface ApiKeyData {
23
23
  keyId: string;
@@ -107,6 +107,22 @@ export interface OnboardingProgress extends TailProgress {
107
107
  * resume defaults to `create-new` for backward compatibility.
108
108
  */
109
109
  setupMethod?: 'create-new' | 'import-existing';
110
+ /**
111
+ * Records how the user chose to obtain the .p8 in the create-new flow's
112
+ * source fork (`p8-source-select`):
113
+ * - `automated` — picked "No — create one for me": the guided macOS helper
114
+ * creates + captures the key. (Its in-window intro screen
115
+ * still lets the user switch to manual, which re-persists
116
+ * `manual` from the asc-key-generating effect.)
117
+ * - `manual` — the user has a .p8, or chose to create one by hand at App
118
+ * Store Connect, and enters it via `api-key-instructions`.
119
+ *
120
+ * Persisted so a quit-and-resume lands the user back where they chose to be:
121
+ * an `automated` user resumes on the helper (`asc-key-generating`), NOT the
122
+ * manual .p8 picker. Absent on legacy files and on the import flow.
123
+ * Only meaningful when `setupMethod === 'create-new'`.
124
+ */
125
+ p8CreateMethod?: 'automated' | 'manual';
110
126
  /**
111
127
  * Records the distribution mode picked at `import-distribution-mode`.
112
128
  *
@@ -24,12 +24,23 @@ interface AppProps {
24
24
  initialProgress: OnboardingProgress | null;
25
25
  /** Resolved iOS directory from capacitor.config (defaults to 'ios') */
26
26
  iosDir: string;
27
+ /**
28
+ * Whether guided ASC-key creation may be offered: macOS + the signed helper
29
+ * installed + its Developer-ID signature/team verified (computed once in
30
+ * command.ts via probeGuidedHelper). Gates every "create one for me" / "do
31
+ * you already have a .p8?" branch — when false (not installed, wrong
32
+ * signature, wrong team, or non-macOS) the user goes straight to the manual
33
+ * .p8 instructions, exactly as before the helper existed and as on Linux.
34
+ */
35
+ guidedHelperUsable: boolean;
27
36
  /** Optional Capgo API key passed via -a/--apikey flag; takes precedence over saved key */
28
37
  apikey?: string;
29
38
  supaHost?: string;
30
- /** Reports the wizard outcome to the shell when it reaches build-complete, so
39
+ /**
40
+ * Reports the wizard outcome to the shell when it reaches build-complete, so
31
41
  * the caller prints an accurate post-exit message + durable summary instead of
32
- * always claiming success. Never fires on cancel/missing-platform exits. */
42
+ * always claiming success. Never fires on cancel/missing-platform exits.
43
+ */
33
44
  onResult?: (result: OnboardingResult) => void;
34
45
  }
35
46
  declare const OnboardingApp: FC<AppProps>;
@@ -17,6 +17,12 @@ export interface OnboardingShellProps {
17
17
  iosBundleIdInitial: string;
18
18
  iosDir: string;
19
19
  androidDir: string;
20
+ /**
21
+ * Whether guided ASC-key creation may be offered (macOS + signed helper
22
+ * installed + signature/team verified — see the probe in command.ts).
23
+ * Threaded into the iOS OnboardingApp; the Android app ignores it.
24
+ */
25
+ guidedHelperUsable: boolean;
20
26
  apikey?: string;
21
27
  supaHost?: string;
22
28
  /** Pre-resolved platform (--platform flag or the single existing native dir); skips the picker. */
@@ -15,10 +15,26 @@ export interface SetupMethodSelectStepProps {
15
15
  onChange: (value: string) => void | Promise<void>;
16
16
  }
17
17
  export declare const SetupMethodSelectStep: FC<SetupMethodSelectStepProps>;
18
+ export interface P8SourceSelectStepProps {
19
+ dense?: boolean;
20
+ /** True when the guided macOS helper is available (macOS + binary present). */
21
+ canAutomate: boolean;
22
+ onChange: (value: string) => void | Promise<void>;
23
+ }
24
+ export declare const P8SourceSelectStep: FC<P8SourceSelectStepProps>;
25
+ export declare const AscKeyGeneratingStep: FC;
26
+ export interface AscKeyCreatedStepProps {
27
+ keyId: string;
28
+ onContinue: () => void;
29
+ }
30
+ export declare const AscKeyCreatedStep: FC<AscKeyCreatedStepProps>;
18
31
  export interface ApiKeyInstructionsStepProps {
19
32
  canUseFilePicker: boolean;
33
+ /** macOS + helper available: also offer "✨ Create one for me (guided)" as an
34
+ * alternative to providing the .p8 by hand. Defaults to false. */
35
+ canCreateGuided?: boolean;
20
36
  dense?: boolean;
21
- onMethodChange: (value: string) => void;
37
+ onMethodChange: (value: string) => void | Promise<void>;
22
38
  onPathSubmit: (value: string) => void | Promise<void>;
23
39
  }
24
40
  export declare const ApiKeyInstructionsStep: FC<ApiKeyInstructionsStepProps>;
@@ -60,6 +60,10 @@ export interface ErrorStepProps {
60
60
  /** A captured build log exists for this run (e.g. a build was attempted), so
61
61
  * the help menu may offer the "Ask AI for help" option. Defaults to false. */
62
62
  hasBuildLog?: boolean;
63
+ /** Offer "✨ Create a new key for me (guided)" as the first recovery option —
64
+ * set when an App Store Connect key failed to validate on a host where the
65
+ * guided macOS helper is available. Defaults to false. */
66
+ showGuidedKey?: boolean;
63
67
  onChange: (value: string) => void | Promise<void>;
64
68
  }
65
69
  export declare function formatErrorViewerLines(error: string, recoveryAdvice: BuildOnboardingRecoveryAdvice | null, supportBundlePath: string | null): string[];
@@ -79,7 +83,7 @@ export declare function formatErrorViewerLines(error: string, recoveryAdvice: Bu
79
83
  * chrome (boxed header + completed-steps log + padding) is a fixed ~15 rows the
80
84
  * caller reserves on top.
81
85
  */
82
- export declare function estimateErrorBodyRows(error: string, recoveryAdvice: BuildOnboardingRecoveryAdvice | null, supportBundlePath: string | null, cols: number, showRetry: boolean, hasBuildLog: boolean): number;
86
+ export declare function estimateErrorBodyRows(error: string, recoveryAdvice: BuildOnboardingRecoveryAdvice | null, supportBundlePath: string | null, cols: number, showRetry: boolean, hasBuildLog: boolean, showGuidedKey?: boolean): number;
83
87
  export declare const ErrorStep: FC<ErrorStepProps>;
84
88
  export interface BuildCompleteStepProps {
85
89
  buildUrl: string;
@@ -33,8 +33,8 @@ export declare const onboardingNextStepSchema: z.ZodObject<{
33
33
  keystoreKeyPassword: z.ZodOptional<z.ZodString>;
34
34
  keystoreNewAlias: z.ZodOptional<z.ZodString>;
35
35
  keystorePasswordMethod: z.ZodOptional<z.ZodEnum<{
36
- random: "random";
37
36
  manual: "manual";
37
+ random: "random";
38
38
  }>>;
39
39
  keystoreCommonName: z.ZodOptional<z.ZodString>;
40
40
  }, z.core.$strip>;