Skip to content

feat(cli): AI-conducted Capgo Builder onboarding via MCP (2-tool spine)#2370

Closed
WcaleNieWolny wants to merge 19 commits into
mainfrom
wolny/mcp-builder-onboarding
Closed

feat(cli): AI-conducted Capgo Builder onboarding via MCP (2-tool spine)#2370
WcaleNieWolny wants to merge 19 commits into
mainfrom
wolny/mcp-builder-onboarding

Conversation

@WcaleNieWolny
Copy link
Copy Markdown
Contributor

@WcaleNieWolny WcaleNieWolny commented May 30, 2026

Summary

Adds AI-conducted onboarding for Capgo Builder (native iOS/Android cloud builds) to the CLI's MCP server. Instead of the TTY-only Ink wizard, the MCP server now drives the whole flow as a server-owned state machine: the AI only ever calls a 2-tool spinestart_capgo_builder_onboarding (orient/resume, no args) and capgo_builder_onboarding_next_step (advance) — and every tool result tells the AI exactly what to do next via a kind (auto / human_gate / choice / done / error) and a literal next action. Heavy work runs server-side by reusing the existing headless build/onboarding/ modules; secrets travel by file path / the local credential store, never through the chat.

End-to-end, a developer goes from zero to a first cloud build for either platform:

preflight → login gate → register app → platform choice
  ├─ iOS:     provide ASC API key (.p8 path + Key ID + Issuer ID)               [human_gate]
  │           → verify key + create distribution cert + provisioning profile + save   [auto]
  └─ Android: generate keystore                                                  [auto]
              → provide Play service-account JSON (file path)                    [human_gate]
              → validate + save                                                  [auto]
  → "Run your first build?"   [choice] → capgo_request_build   [auto] → done 🎉

Architecture: pure deciders (decideStart / decideAndroid / decideIos / decideBuildPhase) + a deps-injected drive() auto-executor that performs side-effect steps and coalesces them until the next human gate/choice. All IO is injected (EngineDeps) so the flow is unit-testable headlessly — mirroring the existing getResumeStep / getAndroidResumeStep pattern.

New files (under cli/src/build/onboarding/mcp/):

  • contract.ts — the NextStepResult result contract + renderResult() (directive-first text)
  • engine.ts — the state machine (pure deciders + injected orchestrators)
  • onboarding-tools.ts — registers the 2 MCP tools and wires real deps to the existing modules

Reuses without rewrites: apple-api.ts, csr.ts, android/keystore.ts, android/service-account-validation.ts, credentials.ts, onboarding/progress.ts, android/progress.ts, init/app-conflict.ts. Touches mcp/server.ts to register the tools.

Design notes are committed under docs/superpowers/specs/ (architecture + end-user journey, as HTML) and docs/superpowers/plans/ (the phased implementation plans).

Scope / deliberate deferrals

  • Android uses the bring-your-own service account path (user supplies a Google Play service-account JSON). The OAuth "generate a service account via Google" path is intentionally not built (the oauth-google/gcp-api/play-api modules remain available for a follow-up).
  • iOS is the create-new path. The import-from-Keychain path and interactive cert-limit / duplicate-profile recovery surface as a clear error + re-prompt rather than a guided revoke/delete flow.
  • The build step triggers the cloud build and reports the job id/status; it does not poll to completion in-tool (avoids long-blocking tool calls).

Test plan

cd cli
bun test/test-mcp-onboarding.mjs   # 40 headless unit tests: deciders, auto-executor, both platform flows
bun run typecheck                  # tsgo
bun run build                      # tsc + bundle (authoritative typecheck)
node test/test-mcp.mjs             # MCP integration smoke: server boots + both new tools exposed

All green locally: 40/40 unit tests, build OK, smoke OK.

Manual MCP walkthrough (from a Capacitor project dir, server connected):

  1. Call start_capgo_builder_onboarding → returns preflight + roadmap + the first step.
  2. Follow each result's next: relay human_gate instructions to the user, pass choice/collected values back via capgo_builder_onboarding_next_step.
  3. Android: keystore auto-generates → supply a Play service-account JSON path → creds save. iOS: supply ASC .p8 path + Key ID + Issuer ID → distribution cert + provisioning profile create → creds save.
  4. Choose "Run the first build" → capgo_request_build is triggered.

A full live run creates real Apple/Google resources, so it needs a real Apple Developer / Play account + valid keys. The automated checks above cover the state machine, wiring, and server boot; the live API calls reuse already-shipped code paths (apple-api, validateServiceAccountJson, requestBuild).

Screenshots

N/A — MCP/CLI backend feature, no UI. The architecture and end-user journey are documented as HTML under docs/superpowers/specs/2026-05-30-capgo-builder-mcp-onboarding-*.html.

Checklist

  • My code follows the code style of this project and passes bun run lint:backend && bun run lint. — ⚠️ oxlint isn't installed in this dev environment, so I could not run lint locally (CI will). New files follow the existing import/style conventions; please flag any oxlint nits.
  • My change requires a change to the documentation. — the user-facing CLI docs (README / usage skill) should mention the two new MCP tools.
  • I have updated the documentation accordingly. — not yet (website docs); design docs added under docs/superpowers/.
  • My change has adequate E2E test coverage. — 40 headless unit tests + an MCP integration smoke; no Playwright/E2E (the CLI uses bun test scripts, consistent with the existing suite).
  • I have tested my code manually, and I have provided steps to reproduce — see Test plan (unit + build + smoke). A full live Apple/Google run was not performed (needs real accounts).

Summary by CodeRabbit

  • New Features

    • Added guided Capgo Builder onboarding flow to MCP server with two new tools for starting and advancing through onboarding steps.
    • Onboarding now guides users through app registration and platform-specific credential setup for iOS and Android builds.
  • Documentation

    • Added comprehensive onboarding design documentation, user journey guides, and implementation plan.
  • Tests

    • Added test suite validating end-to-end onboarding flow and MCP tool integration.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 30, 2026

Warning

Review limit reached

@WcaleNieWolny, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 15 minutes and 40 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 399900da-a7fa-4839-8e0c-6754e9ff8635

📥 Commits

Reviewing files that changed from the base of the PR and between 3f94ac9 and f5c7892.

📒 Files selected for processing (8)
  • cli/src/build/onboarding/mcp/engine.ts
  • cli/src/build/onboarding/mcp/onboarding-tools.ts
  • cli/src/schemas/onboarding.ts
  • cli/test/test-mcp-onboarding.mjs
  • docs/superpowers/plans/2026-05-30-capgo-builder-mcp-onboarding-plan-3-android-brief.md
  • docs/superpowers/plans/2026-05-30-capgo-builder-mcp-onboarding.md
  • docs/superpowers/specs/2026-05-30-capgo-builder-mcp-onboarding-design.html
  • docs/superpowers/specs/2026-05-30-capgo-builder-onboarding-user-journey.html
📝 Walkthrough

Walkthrough

This PR implements a complete MCP-driven onboarding system for Capgo Builder that guides users through iOS and Android credential setup via two registered MCP tools. It includes a state-machine engine with pure decision logic, dependency-injected side effects, comprehensive tests, and design documentation.

Changes

Capgo Builder MCP Onboarding

Layer / File(s) Summary
Onboarding result contract and rendering
cli/src/build/onboarding/mcp/contract.ts
NextStepResult defines the step outcome shape with phase, kind, progress, roadmap, options, collection prompts, human instructions, and next-tool directive. ONBOARDING_RULES encode model constraints. renderResult serializes results into directive text with embedded JSON.
Engine core models and fact gathering
cli/src/build/onboarding/mcp/engine.ts (1–25, 316–347)
PreflightFacts model captures app id, authentication, native platforms, app registration status, and persisted progress. EngineDeps interface defines all side-effect operations. gatherFacts assembles facts by calling dependencies without performing side effects.
Engine platform routing and credential decision flows
cli/src/build/onboarding/mcp/engine.ts (26–137, 140–203, 204–269, 271–314)
decideStart validates Capacitor setup, enforces login, detects platforms, and routes to a platform-choice or selected platform. decideIos gates API-key collection, auto-finalize, then build. decideAndroid gates keystore, service-account, auto-finalize, then build. decideAdvance interprets user input and re-routes decisions.
Engine orchestration, side effects, and loop control
cli/src/build/onboarding/mcp/engine.ts (349–537)
appConflictResult handles app-id conflicts. executeAuto performs side effects (register app, generate keystore, finalize credentials) and returns terminal or human-gate results. drive loop gathers facts, decides, executes auto steps (capped at MAX_AUTO_STEPS), handles build triggering, and reports stall errors. runStart and runAdvance are the entry points.
Tool registration and MCP server integration
cli/src/build/onboarding/mcp/onboarding-tools.ts, cli/src/mcp/server.ts (7, 62–64)
buildDeps constructs EngineDeps by reading config, checking app registration, and provisioning iOS/Android credentials. registerOnboardingTools registers two MCP tools (start_capgo_builder_onboarding and capgo_builder_onboarding_next_step) with handlers that call the orchestration loop and render results. startMcpServer wires the tools into the MCP server.
Comprehensive test suite and validation
cli/test/test-mcp-onboarding.mjs, cli/test/test-mcp.mjs (71–72), cli/package.json (108–109)
Headless tests validate contract rendering, all decision paths (auth, platform choice, single-platform, missing platforms), fact gathering, orchestration, MCP tool registration, app registration with conflict handling and loop guards, Android credential flow (keystore → service-account → finalize → build), and iOS credential flow (API-key collection → auto-finalize → profile → build). Extended test-mcp.mjs to require the two new tools. Updated npm test script to run test:mcp-onboarding.
Design documentation and implementation plans
docs/superpowers/plans/2026-05-30-capgo-builder-mcp-onboarding*.md, docs/superpowers/specs/2026-05-30-capgo-builder-*.html
Five-plan roadmap with Plan 1 walking skeleton, Plan 2 app-phase and auto-executor, Plan 3 Android brief. Static HTML specs detail the MCP primitives, state machine, step contract, tabbed iOS/Android credentials flow, example transcripts, and user journey with platform-specific walkthroughs and recovery cards.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • Cap-go/capgo#2208: Updates cli/test/test-mcp.mjs to require the two new MCP tools added in this PR, ensuring the onboarding tools are registered and validated at the server level.

Suggested labels

codex

Suggested reviewers

  • zinc-builds
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding AI-conducted onboarding for Capgo Builder to MCP with a 2-tool interface.
Description check ✅ Passed The PR description is comprehensive and mostly complete with clear summary, test plan, and manual walkthrough. However, the checklist shows several items unchecked (lint not run, website docs not updated, no E2E tests).
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@codspeed-hq
Copy link
Copy Markdown
Contributor

codspeed-hq Bot commented May 30, 2026

Merging this PR will not alter performance

✅ 43 untouched benchmarks
⏩ 2 skipped benchmarks1


Comparing wolny/mcp-builder-onboarding (f5c7892) with main (318801c)

Open in CodSpeed

Footnotes

  1. 2 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@coderabbitai coderabbitai Bot added the codex label May 30, 2026
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3f94ac9770

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread cli/src/build/onboarding/mcp/engine.ts
Comment thread cli/src/build/onboarding/mcp/engine.ts
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 14

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cli/src/build/onboarding/mcp/contract.ts`:
- Around line 56-62: Rename the exported constant ONBOARDING_RULES to a
camelCase name (e.g., onboardingRules) and update its declaration to export
const onboardingRules: string[] = [...]; then search the repo for all
references/imports of ONBOARDING_RULES and update them to onboardingRules
(including any tests or re-exports) so imports remain consistent; ensure
TypeScript compiles after the rename and run tests to verify no remaining
references to ONBOARDING_RULES.

In `@cli/src/build/onboarding/mcp/engine.ts`:
- Around line 19-26: The constants are using SCREAMING_SNAKE_CASE; rename
ROADMAP to roadmap, NEXT_STEP_TOOL to nextStepTool, and MAX_AUTO_STEPS to
maxAutoSteps (and any other similarly cased constants) and update all
references/usages within this module so imports, function calls, and tests
(e.g., any use in engine.ts) reference the new camelCase names; ensure exports
(if any) keep the same external behavior but follow camelCase in declarations
and update any internal comments or documentation strings that mention the old
names.
- Around line 305-310: Reject out-of-order onboarding inputs by validating the
session’s expected step and allowed values before mutating state: in the code
paths that call drive and decideAdvance (and where decideStart/platformChosen
are invoked), first check that the session/progress is currently awaiting a
platform or credential input and that input.platform exists in
platformsDetected; if not, return the non-mutating decideStart/appropriate error
instead of persisting credentials or calling platformChosen/decideAdvance.
Ensure capgo_builder_onboarding_next_step calls are only reached after these
guards so no direct call can jump past the active step.
- Around line 276-294: decideBuildPhase presents a "skip" option but the
onboarding runner ("drive") only checks for runBuild === true, so returning
runBuild: false falls through and never completes onboarding; update the logic
so that a skip ends onboarding: in decideBuildPhase adjust the option/next
messaging to explicitly indicate skip should return { runBuild: false } and in
the onboarding executor (drive) add a branch that treats runBuild === false as a
terminal success (set onboarding complete/state 'complete' and stop further
steps); ensure you update both decideBuildPhase and drive to reference runBuild
(and NEXT_STEP_TOOL usage) so skip is handled as a final outcome.

In `@cli/src/build/onboarding/mcp/onboarding-tools.ts`:
- Around line 208-216: Extract the inline Zod schema object from
onboarding-tools.ts into a new exported schema (e.g., OnboardingMcpInputSchema)
under cli/src/schemas/, then import that schema into onboarding-tools.ts and
replace the inline schema with the imported OnboardingMcpInputSchema; update the
async handler signature to use z.infer<typeof OnboardingMcpInputSchema> for its
parameter type (replacing the manual annotation that references Platform,
serviceAccountJsonPath, runBuild, keyId, issuerId, p8Path) so runtime validation
and the TS type are derived from the single shared Zod schema.
- Around line 80-97: generateAndroidKeystore currently writes secret artifacts
(p12 base64 and passwords) into onboarding progress via saveAndroidProgress and
the _keystoreBase64 / keystoreStorePassword / keystoreKeyPassword fields;
similarly finalizeAndroidCredentials and updateSavedCredentials propagate those
secrets into saved progress and completedSteps. Change these functions so
onboarding progress only stores non-secret metadata (e.g.,
keystoreReady.isGenerated, keystoreAlias, keystoreCommonName, timestamps, and
flags) and do NOT persist _keystoreBase64, keystoreStorePassword,
keystoreKeyPassword, p12Base64, profileBase64, or any secret blob; instead
transfer secrets directly into the secure credential store in
finalizeAndroidCredentials/updateSavedCredentials and then scrub any transient
secret properties from the in-memory prog before calling saveAndroidProgress (or
avoid setting them at all). Locate usages in generateAndroidKeystore,
finalizeAndroidCredentials, updateSavedCredentials, loadAndroidProgress,
saveAndroidProgress and completedSteps to remove secret fields and ensure only
metadata is persisted.
- Around line 181-182: The catch block in onboarding-tools.ts currently returns
raw exception text (return { ok: false, error: err instanceof Error ?
err.message : String(err) }); change it to use the shared formatter by calling
formatError(err) and return { ok: false, error: formatError(err) } (import
formatError if not already imported) so iOS/provider/filesystem internals are
not leaked and onboarding errors stay consistent; update the catch in the
function that produces the MCP response accordingly.

In
`@docs/superpowers/plans/2026-05-30-capgo-builder-mcp-onboarding-plan-3-android-brief.md`:
- Line 48: Fix the malformed fragment "pastes/【provides" in the Play developer
id instruction: replace it with a clean phrasing such as "pastes/provides their
Play developer id (non-secret identifier → fine for chat); parse with
extractDeveloperId. Then call inviteServiceAccount (auto)." Keep the
`human_gate` example and the note about non-secret identifiers intact and ensure
extractDeveloperId and inviteServiceAccount are mentioned exactly as shown.
- Around line 9-13: The doc contains a contradiction between the line that drops
"OAuth / GCP-generate / Play-invite-via-API" and the Goal that still lists
"Google sign-in → GCP service account → Play invite"; decide which direction to
take and update the text to be consistent: either remove the OAuth/GCP/Play
invite flow from the Goal and change "Google sign-in → GCP service account →
Play invite" to a headless/managed credential path (keeping references to
capgo_request_build and cli/src/build/onboarding/android/*), or re-enable the
OAuth flow by deleting the "dropped for v1" statement and make the earlier line
match the Goal; ensure the phrases "OAuth / GCP-generate / Play-invite-via-API"
and "Google sign-in → GCP service account → Play invite" are reconciled so the
plan unambiguously reflects the chosen implementation.

In `@docs/superpowers/plans/2026-05-30-capgo-builder-mcp-onboarding.md`:
- Around line 112-114: Add a language tag to the fenced code block that contains
"&& bun run test:mcp-onboarding" by changing the opening fence from ``` to
```bash (or ```text) so the block is properly recognized and MD040 is resolved;
locate the fenced block around the "&& bun run test:mcp-onboarding" line and add
the language identifier after the opening backticks.

In `@docs/superpowers/specs/2026-05-30-capgo-builder-mcp-onboarding-design.html`:
- Around line 355-356: The spec uses outdated tool names like "..._status" and
"..._advance"; update all occurrences (including the repeated locations) to
match the implemented contract by replacing those stale names with
start_capgo_builder_onboarding and capgo_builder_onboarding_next_step so the
document references the actual tool identifiers used in code and tests (search
for the phrases "..._status" and "..._advance" and swap them to the two concrete
symbols: start_capgo_builder_onboarding and capgo_builder_onboarding_next_step).
- Around line 452-453: The tab buttons (<button role="tab" aria-selected="true"
data-tab="ios"> and <button role="tab" aria-selected="false"
data-tab="android">) lack an explicit type and will default to submit in forms;
update both button elements to include type="button" to avoid accidental form
submission and satisfy HTMLHint, keeping the existing attributes (role,
aria-selected, data-tab) unchanged.

In
`@docs/superpowers/specs/2026-05-30-capgo-builder-onboarding-user-journey.html`:
- Around line 289-290: The two tab control buttons (the <button> elements with
data-tab="ios" and data-tab="android") lack an explicit type and can act as
implicit submit buttons; update both button elements to include type="button"
(e.g., the buttons that have aria-selected and data-tab attributes) so they
won’t trigger form submission and to satisfy HTMLHint.
- Line 396: The onboarding copy inside the rcard that currently reads "Let's
connect Capgo first — here's the link to grab an API key, paste it here." must
be changed to remove any instruction to paste secrets and instead instruct users
to use the local terminal login flow; update the HTML fragment that contains the
sentence (the <div class="rcard"> / text "Let's connect Capgo first — here's the
link to grab an API key, paste it here.") to instead say something like "Run
`capgo login` in your terminal to authenticate locally" (or equivalent
messaging), and apply the same replacement to the other identical snippet noted
in the file so no guidance suggests sharing/pasting API keys in chat.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 34a20523-4aaf-4379-953c-154bf7afa798

📥 Commits

Reviewing files that changed from the base of the PR and between 123800e and 3f94ac9.

📒 Files selected for processing (12)
  • cli/package.json
  • cli/src/build/onboarding/mcp/contract.ts
  • cli/src/build/onboarding/mcp/engine.ts
  • cli/src/build/onboarding/mcp/onboarding-tools.ts
  • cli/src/mcp/server.ts
  • cli/test/test-mcp-onboarding.mjs
  • cli/test/test-mcp.mjs
  • docs/superpowers/plans/2026-05-30-capgo-builder-mcp-onboarding-plan-2-app-phase.md
  • docs/superpowers/plans/2026-05-30-capgo-builder-mcp-onboarding-plan-3-android-brief.md
  • docs/superpowers/plans/2026-05-30-capgo-builder-mcp-onboarding.md
  • docs/superpowers/specs/2026-05-30-capgo-builder-mcp-onboarding-design.html
  • docs/superpowers/specs/2026-05-30-capgo-builder-onboarding-user-journey.html

Comment thread cli/src/build/onboarding/mcp/contract.ts
Comment on lines +19 to +26
const ROADMAP: string[] = [
'Preflight — detect your project & account',
'Register the app in Capgo',
'Set up signing credentials',
'Run your first cloud build',
]

const NEXT_STEP_TOOL = 'capgo_builder_onboarding_next_step'
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot May 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Rename the new constants to camelCase.

ROADMAP, NEXT_STEP_TOOL, and MAX_AUTO_STEPS don't follow the repository's TS naming rule.

As per coding guidelines, **/*.{ts,tsx,js}: Use camelCase for variable and function names.

Also applies to: 349-349

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cli/src/build/onboarding/mcp/engine.ts` around lines 19 - 26, The constants
are using SCREAMING_SNAKE_CASE; rename ROADMAP to roadmap, NEXT_STEP_TOOL to
nextStepTool, and MAX_AUTO_STEPS to maxAutoSteps (and any other similarly cased
constants) and update all references/usages within this module so imports,
function calls, and tests (e.g., any use in engine.ts) reference the new
camelCase names; ensure exports (if any) keep the same external behavior but
follow camelCase in declarations and update any internal comments or
documentation strings that mention the old names.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not changing — same reason: SCREAMING_SNAKE is the established convention for module constants here (csr.ts, gcp-api.ts, play-api.ts).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Resolve the review comment via GitHub CLI
gh api graphql -f query='
mutation {
  resolveReviewThread(input: { threadId: "PRRT_kwDOBXFWNs5mHfXQ" }) {
    thread {
      isResolved
    }
  }
}'

Length of output: 714



I wasn't able to auto-resolve the comment due to permission constraints — you can dismiss it manually. The learning about SCREAMING_SNAKE_CASE being the established convention for module-level constants in the Capgo CLI codebase has been recorded for future reviews.

Comment thread cli/src/build/onboarding/mcp/engine.ts
Comment thread cli/src/build/onboarding/mcp/engine.ts
Comment on lines +80 to +97
generateAndroidKeystore: async (appId: string) => {
const storePassword = generateRandomPassword()
const keyPassword = generateRandomPassword()
const alias = 'release'
const ks = generateKeystore({ alias, storePassword, keyPassword, dname: { commonName: appId } })
const base = (await loadAndroidProgress(appId)) ?? { platform: 'android' as const, appId, startedAt: new Date().toISOString(), completedSteps: {} }
await saveAndroidProgress(appId, {
...base,
platform: 'android',
appId,
keystoreMethod: 'generate',
keystoreAlias: alias,
keystoreStorePassword: storePassword,
keystoreKeyPassword: keyPassword,
keystoreCommonName: appId,
_keystoreBase64: ks.p12Base64,
completedSteps: { ...base.completedSteps, keystoreReady: { keystorePath: '', alias, isGenerated: true } },
})
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot May 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Do not persist credential blobs and passwords in onboarding progress.

generateAndroidKeystore stores the keystore blob and passwords in progress, finalizeAndroidCredentials preserves them via ...prog, and iOS finalization adds p12Base64 / profileBase64 to completedSteps after those values were already written to updateSavedCredentials. That leaves long-lived secrets outside the credential store and increases the leak surface. Persist only non-secret progress metadata here, and scrub transient secrets once they have been transferred.

Also applies to: 132-135, 170-177

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cli/src/build/onboarding/mcp/onboarding-tools.ts` around lines 80 - 97,
generateAndroidKeystore currently writes secret artifacts (p12 base64 and
passwords) into onboarding progress via saveAndroidProgress and the
_keystoreBase64 / keystoreStorePassword / keystoreKeyPassword fields; similarly
finalizeAndroidCredentials and updateSavedCredentials propagate those secrets
into saved progress and completedSteps. Change these functions so onboarding
progress only stores non-secret metadata (e.g., keystoreReady.isGenerated,
keystoreAlias, keystoreCommonName, timestamps, and flags) and do NOT persist
_keystoreBase64, keystoreStorePassword, keystoreKeyPassword, p12Base64,
profileBase64, or any secret blob; instead transfer secrets directly into the
secure credential store in finalizeAndroidCredentials/updateSavedCredentials and
then scrub any transient secret properties from the in-memory prog before
calling saveAndroidProgress (or avoid setting them at all). Locate usages in
generateAndroidKeystore, finalizeAndroidCredentials, updateSavedCredentials,
loadAndroidProgress, saveAndroidProgress and completedSteps to remove secret
fields and ensure only metadata is persisted.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not changing in this PR — this mirrors the existing wizard persistence model (shared progress types include _keystoreBase64 and CertificateData.p12Base64, and resume depends on them); the progress file is written mode 0600 in a 0700 dir. Re-architecting secret storage is tracked as a follow-up.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@WcaleNieWolny, understood — given that the shared progress types already include _keystoreBase64 / CertificateData.p12Base64 and resume logic depends on them, keeping the current persistence model consistent within this PR is reasonable. The 0600/0700 file permissions mitigate the immediate exposure risk.

Would you like me to open a follow-up GitHub issue to track the secret-storage re-architecture (moving credential blobs out of progress files and into a secure credential store, scrubbing transient secrets after transfer)?


✏️ Learnings added
Learnt from: WcaleNieWolny
Repo: Cap-go/capgo PR: 2370
File: cli/src/build/onboarding/mcp/onboarding-tools.ts:81-98
Timestamp: 2026-05-30T10:49:28.863Z
Learning: In `cli/src/build/onboarding/mcp/onboarding-tools.ts` (and related Android/iOS progress files), the onboarding progress intentionally persists secret artifacts such as `_keystoreBase64`, `keystoreStorePassword`, `keystoreKeyPassword`, `p12Base64`, and `profileBase64`. This mirrors the existing wizard persistence model where shared progress types (e.g., `CertificateData.p12Base64`) include these fields and resume logic depends on them. The progress file is written with mode 0600 in a 0700 directory. A follow-up refactor to move secrets exclusively into a secure credential store is planned but out of scope for the current PR.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Comment thread docs/superpowers/plans/2026-05-30-capgo-builder-mcp-onboarding.md Outdated
Comment thread docs/superpowers/specs/2026-05-30-capgo-builder-mcp-onboarding-design.html Outdated
Comment thread docs/superpowers/specs/2026-05-30-capgo-builder-onboarding-user-journey.html Outdated
Comment thread docs/superpowers/specs/2026-05-30-capgo-builder-onboarding-user-journey.html Outdated
…erminal, formatError, shared Zod schema; docs + security nits
@sonarqubecloud
Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants