@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/README.md +31 -0
- package/dist/index.js +544 -533
- package/dist/package.json +5 -4
- package/dist/src/build/onboarding/asc-key/command.d.ts +17 -0
- package/dist/src/build/onboarding/asc-key/helper.d.ts +146 -0
- package/dist/src/build/onboarding/asc-key/protocol.d.ts +97 -0
- package/dist/src/build/onboarding/ios/progress.d.ts +1 -1
- package/dist/src/build/onboarding/macos-signing.d.ts +45 -10
- package/dist/src/build/onboarding/progress.d.ts +1 -1
- package/dist/src/build/onboarding/types.d.ts +17 -1
- package/dist/src/build/onboarding/ui/app.d.ts +13 -2
- package/dist/src/build/onboarding/ui/shell.d.ts +6 -0
- package/dist/src/build/onboarding/ui/steps/ios-credentials.d.ts +17 -1
- package/dist/src/build/onboarding/ui/steps/ios-shared.d.ts +5 -1
- package/dist/src/schemas/onboarding.d.ts +1 -1
- package/dist/src/sdk.js +3 -3
- package/package.json +5 -4
package/dist/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capgo/cli",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "8.
|
|
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-
|
|
179
|
-
"@capgo/cli-
|
|
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
|
|
133
|
-
* cert (OID 1.2.840.113635.100.6.1.13),
|
|
134
|
-
* signing team. The identifier clause is what
|
|
135
|
-
* binary — without it, any other binary signed
|
|
136
|
-
* (a future tool, a leaked artifact) would also
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
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-
|
|
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-
|
|
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
|
-
/**
|
|
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>;
|