Skip to content

feat(cli): add build credentials manage interactive command#2052

Merged
riderx merged 7 commits into
mainfrom
feat/credentials-manage
May 13, 2026
Merged

feat(cli): add build credentials manage interactive command#2052
riderx merged 7 commits into
mainfrom
feat/credentials-manage

Conversation

@WcaleNieWolny
Copy link
Copy Markdown
Contributor

@WcaleNieWolny WcaleNieWolny commented May 6, 2026

Summary

Adds npx @capgo/cli build credentials manage — a keyboard-driven TUI for browsing, exporting, and editing the build credentials saved at ~/.capgo-credentials/credentials.json (or the project-local .capgo-credentials.json). Reuses the same Ink runtime as capgo init so no new dependencies.

The motivating use case: a user setting up CI for the first time wants to inspect what they have stored, paste the right env vars into GitHub Actions / GitLab / etc., and tweak booleans like BUILD_OUTPUT_UPLOAD_ENABLED without touching JSON by hand.

What it does

Action menu (per app, no platform pre-pick):

  • View credentials — flat inspector across both platforms. Each row tagged [SHARED], [SHARED·ios], [SHARED·android], [ios], or [android]. Drift between platforms surfaces as two rows so the user can resolve it explicitly.
  • Export to .env — writes a CI/CD-ready file. macOS uses the native Save As… sheet via osascript choose file name; other platforms fall back to a text prompt. The provisioning map is emitted as CAPGO_IOS_PROVISIONING_MAP_BASE64 (already supported on main) to dodge newline/quoting issues in CI secret stores.
  • Delete — wipes credentials for one platform.

Per-field actions in the inspector:

  • Show — print the raw value.
  • Decode — smart base64 → JSON pretty-print / printable text / binary, N bytes depending on the payload.
  • Copy to clipboardpbcopy / clip / wl-copy / xclip / xsel with a graceful fallback message.
  • Edit — type-aware:
    • boolean (BUILD_OUTPUT_UPLOAD_ENABLED, SKIP_BUILD_NUMBER_BUMP) → true / false select.
    • enum (CAPGO_IOS_DISTRIBUTION) → select from app_store / ad_hoc.
    • duration (BUILD_OUTPUT_RETENTION_SECONDS) → text prompt accepting 1h, 6h, 2d (1h–7d range), stored as seconds.
    • everything else → temp file written to os.tmpdir() (mode 0600), opened in the user's editor of choice, read back on confirm. JSON-validated for CAPGO_IOS_PROVISIONING_MAP.
  • Explain — short authoritative description sourced from the Capgo wiki pages code-signing, cli-native-builds, and android-keystore-handling.
  • Remove — deletes the field from all source platforms (e.g. a [SHARED] row writes/removes on both).

UX details:

  • Auto-detects the current app from capacitor.config.* (mirrors listCredentialsCommand's pattern) — single-app users skip the picker entirely.
  • "Back" only appears when there's somewhere to go back to.
  • Logs cleared only when entering a new field's submenu, so the success line of the previous action stays visible while the user navigates back to the list.
  • openSaveFilePicker helper is generic and reusable for any future "save file" prompt in the CLI.

Files

  • cli/src/build/credentials-manage.ts (new, ~1170 lines) — command implementation, knowledge map, action handlers.
  • cli/src/build/onboarding/file-picker.ts — adds openSaveFilePicker.
  • cli/src/index.ts — wires the manage subcommand under build credentials.

Test plan

  • bun run build succeeds (verified locally — typecheck + bundle clean).
  • node cli/dist/index.js build credentials manage --help prints the new subcommand.
  • Run with one app stored: app picker auto-skips, action menu shows.
  • Run with no credentials stored: graceful "no saved credentials" message.
  • View → flat list shows fields tagged correctly across iOS + Android.
  • Pick a boolean field → Edit offers true / false.
  • Pick CAPGO_IOS_DISTRIBUTION → Edit offers app_store / ad_hoc.
  • Pick BUILD_OUTPUT_RETENTION_SECONDS → Edit accepts 2h, rejects 0, rejects 8d.
  • Pick CAPGO_IOS_PROVISIONING_MAP → Edit opens temp file; saving invalid JSON aborts with an error and keeps the previous value.
  • Copy on macOS goes to pbcopy; failure path shows the warn line.
  • Explain prints the wiki-sourced description for known fields.
  • Export on macOS opens the native Save As… sheet, written file has mode 0600.
  • Export on Linux/Windows falls back to text prompt + manual overwrite confirm.
  • Delete platform with one platform configured: confirm + wipe.

Notes

  • Wiki provenance — the per-field "Explain" strings are baked into CREDENTIAL_KNOWLEDGE in the source. If those wiki pages change, the strings need to be regenerated. BUILD_OUTPUT_* and SKIP_BUILD_NUMBER_BUMP don't have dedicated wiki pages yet, so their explanations were synthesised from the CLI flag descriptions on cli-native-builds.
  • Drift surfacing — when BUILD_OUTPUT_UPLOAD_ENABLED is stored differently per platform (a real wart in the underlying data model), the inspector shows two rows so the user can edit each side. Closing the underlying duplication is out of scope for this PR.
  • No tests added — this is a TUI command driven by user input; meaningful coverage would require Ink-test-utils plumbing the project doesn't have yet. Happy to add unit tests for the pure helpers (gatherFieldRows, escapeDotenvValue, parseOutputRetentionLocal, inferScope, tagOrder) if you want them in this PR.

Summary by CodeRabbit

  • New Features
    • Interactive CLI credential manager to view, edit, add, export, remove, or wipe iOS/Android build credentials per app.
    • View credentials as a flat field list with previews, base64 decode, copy-to-clipboard, and inline explanations.
    • Edit fields by type (boolean/enum/duration/text) with validation and safe handling for complex values.
    • Export CI/CD-ready .env files with secure permissions and base64 handling for multiline data.
    • macOS save dialog support and a new CLI subcommand to launch the manager.

Review Change Stack

A keyboard-driven TUI for browsing, exporting, and editing build
credentials stored under ~/.capgo-credentials/credentials.json (or the
project-local .capgo-credentials.json). Reuses the same Ink runtime
as `capgo init` — no new dependencies.

Top-level actions per app:
- View credentials  — flat inspector across both platforms with [SHARED]
                      / [SHARED·ios] / [SHARED·android] / [ios] /
                      [android] tags. Drift between platforms surfaces
                      as two rows so users can resolve it.
- Export to .env    — writes a CI/CD-ready file. macOS uses the native
                      "Save As…" sheet (osascript `choose file name`);
                      other platforms get a text prompt. Provisioning
                      map is emitted as base64 to dodge newline/quoting
                      issues in CI secret stores.
- Delete            — clears credentials for one platform.

Per-field actions in the inspector:
- Show              — print the raw value.
- Decode            — base64 → JSON pretty-print / printable text /
                      "binary, N bytes" depending on the payload.
- Copy to clipboard — pbcopy / clip / wl-copy / xclip / xsel.
- Edit              — type-aware:
                        boolean → true / false select
                        enum    → select from allowed values
                        duration→ text prompt accepting 1h/6h/2d
                        else    → temp file in $EDITOR, JSON-validated
                                  for CAPGO_IOS_PROVISIONING_MAP.
- Explain           — short authoritative description sourced from the
                      Capgo wiki (code-signing, cli-native-builds,
                      android-keystore-handling pages).
- Remove            — deletes the field from all source platforms.

UX details:
- Auto-detects the current app from capacitor.config so single-app users
  skip the picker entirely.
- "Back" only appears when there is somewhere to go back to.
- Logs cleared only when entering a new field's submenu, so action
  confirmations stay visible while the user navigates back to the list.
- New helper `openSaveFilePicker` in file-picker.ts is reusable for any
  future "save file" prompt in the CLI.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 6, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8e784995-9f5d-42aa-b3d6-3c4a7057a470

📥 Commits

Reviewing files that changed from the base of the PR and between 7d77499 and 883c35e.

📒 Files selected for processing (1)
  • cli/src/build/credentials-manage.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • cli/src/build/credentials-manage.ts

📝 Walkthrough

Walkthrough

Adds an interactive CLI credentials manager (view/edit/export/delete/add) driven by a credential knowledge map, a macOS save-file picker, and a new build credentials manage command wiring into the CLI.

Changes

Interactive Credentials Manager

Layer / File(s) Summary
Credential data model and knowledge map
cli/src/build/credentials-manage.ts
Defines public entrypoint types and an authoritative CREDENTIAL_KNOWLEDGE map with secret-key identification and helpers used to drive UI ordering and edit routing.
Field view-model and platform filtering
cli/src/build/credentials-manage.ts
Flattens per-app credentials into FieldRow view models, infers scopes/types, handles shared-key drift, and provides platform-presence and filter helpers.
Main orchestration loop
cli/src/build/credentials-manage.ts
manageCredentialsCommand validates options, loads entries, applies --platform/--appId constraints, runs the interactive loop, and refreshes state on mutations with cancel/error handling.
TUI helpers and entry pickers
cli/src/build/credentials-manage.ts
Screen management, platform summaries, field/entry descriptions, Capacitor appId detection, entry loading, and top-level app picker.
Action navigation and inspection UI
cli/src/build/credentials-manage.ts
Per-app action menu, per-field inspection loop, mutation tracking, and flattened field-list picker with counts and previews.
Field actions (view/decode/explain)
cli/src/build/credentials-manage.ts
Per-field action availability, masking/preview, base64 detection and decoding to JSON/text, explanation lookup, and sensitive-key redaction.
Clipboard and edit routing
cli/src/build/credentials-manage.ts
Copy-to-clipboard with OS fallbacks and dispatch to typed editors based on field knowledge.
Typed edit flows and persistence
cli/src/build/credentials-manage.ts
Boolean/enum/duration/text editors (temp-file + confirm), duration parsing/validation, provisioning-map JSON validation, and writing updates to source platforms.
Field removal and helpers
cli/src/build/credentials-manage.ts
Confirm-and-remove per-key or full-platform deletions and helpers for JSON detection, filename sanitization, and provisioning-map summarization.
Export to .env and file selection
cli/src/build/credentials-manage.ts
Interactive export target selection (file picker or path prompt), .env rendering with dotenv-safe escaping, provisioning map embedded base64, and file write with mode handling.
Platform deletion clearing
cli/src/build/credentials-manage.ts
Interactive platform deletion confirmation that clears saved credentials.
Add credential flow and onboarding handoff
cli/src/build/credentials-manage.ts
Add loop for missing platforms (handoff to onboarding) or configuration-only key addition; blocks base64/JSON credential-material keys from the config-only path.
Addable configuration enumeration and insertion
cli/src/build/credentials-manage.ts
Enumerates addable configuration candidates (shared/write-platform choices), presents pickers, writes via updateSavedCredentials, and reloads entries.
Prompt helpers and validation for adds
cli/src/build/credentials-manage.ts
Prompt/format helpers for boolean/enum/duration/string inputs and validation for configuration-only additions.
macOS save file picker
cli/src/build/onboarding/file-picker.ts
Exports SaveFilePickerOptions and openSaveFilePicker that construct an AppleScript save dialog with escaped prompt/default values and return a POSIX path or null.
CLI command registration
cli/src/index.ts
Imports manageCredentialsCommand and registers build credentials manage with --appId, --platform, and --local options.

Sequence Diagram

sequenceDiagram
  participant User
  participant CLI as Capgo CLI
  participant Store as CredentialsStore
  participant FilePicker as SaveFilePicker/FS
  User->>CLI: open manage credentials
  CLI->>Store: load entries (local/global)
  CLI->>User: render TUI (apps, fields)
  User->>CLI: request export / add / edit / delete
  CLI->>FilePicker: choose save path (when exporting)
  CLI->>Store: write/update/delete credentials
  CLI->>User: show result / confirmation
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

  • Cap-go/capgo#2025: Exports provisioning map in base64 for CI; aligns with this PR's base64 provisioning-map export.

Suggested reviewers

  • zinc-builds

Poem

🐰 In a terminal burrow I gently tread,

I list and edit keys, then tuck them to bed.
Base64 snug for CI's little nest,
Capgo's secrets tidy, validated, dressed. 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 3.45% 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 and concisely summarizes the main addition: a new interactive credentials management command with appropriate feature scope marker.
Description check ✅ Passed The pull request description comprehensively covers the summary, features, test plan, and implementation notes following repository conventions, with only the checklist items unchecked (expected for author submission).
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.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/credentials-manage

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 6, 2026

Merging this PR will not alter performance

✅ 43 untouched benchmarks
⏩ 2 skipped benchmarks1


Comparing feat/credentials-manage (883c35e) with main (2a0f6b6)

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.

Copy link
Copy Markdown

@adamsardo adamsardo left a comment

Choose a reason for hiding this comment

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

I spotted one functional gap in the new command surface: build credentials manage --platform ios|android is documented and registered, but ManageCredentialsOptions.platform is never used in manageCredentialsCommand.

That means --platform ios still shows/manages/export/deletes Android credentials when both platforms exist, and --platform android likewise does not constrain the flow. This is especially risky on the delete/export paths because the CLI help implies the caller has already scoped the operation to one platform.

A small fix would be to validate options.platform early and filter currentEntry.platforms / saved views to that platform, or remove the option from the command until it is implemented.

Copy link
Copy Markdown

One security UX issue I’d tighten before this ships: Decode (base64 -> readable) pretty-prints decoded JSON/text for decode-eligible fields, including PLAY_CONFIG_JSON and APPLE_KEY_CONTENT. For a Google service-account JSON this can dump the private_key into terminal scrollback, even though the field is marked as secret and hidden in the main list.

Show value already exists for intentional raw disclosure, so Decode could either redact known sensitive keys such as private_key / private_key_id, or require an extra confirmation before printing decoded secret material. Otherwise a user trying to inspect the credential structure can accidentally persist signing/upload credentials in terminal logs.

Copy link
Copy Markdown

@zinc-builds zinc-builds left a comment

Choose a reason for hiding this comment

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

Security Review: #2052build credentials manage interactive command

Looks Good ✅

  • File permissions 0o600 for exported .env files and temp edit files — prevents other users from reading secrets
  • Temp files in tmpdir() with unique names (capgo-{timestamp}-{random}-{key}.{ext}) — avoids predictable paths
  • finally block cleanup of temp files after editing — best-effort unlinking
  • Secret maskingSECRET_KEYS set defines which fields show **** by default in the picker UI
  • No network transmission — all operations are local-only (read/write to local credential stores)
  • .env export warns about .gitignore — user is told "never commit this file" and given the docs URL
  • escapeDotenvValue properly handles special characters ($, `, ", , newlines) in exported env values
  • Validation on edit — boolean/enum/duration fields validated before write; JSON parsing validated for provisioning map
  • CSV/JSON export uses base64 for multi-line values (CAPGO_IOS_PROVISIONING_MAP exported as _BASE64 variant) — avoids newline injection in .env
  • sanitizeForFilename strips non-alphanumeric chars from temp filenames — prevents path traversal via key names

Warnings ⚠️

  • Clipboard copy of secrets: actionCopyField pipes raw secrets to pbcopy/xclip/wl-copy. Once in the clipboard, the secret persists until overwritten. Some clipboard managers retain history. Consider adding a warning after copy or using platform-specific transient clipboard APIs where available.
  • Temp file crash persistence: If the process is killed (SIGKILL) during editTextField, the temp file at /tmp/capgo-* containing the credential value remains on disk. The finally block cannot run on SIGKILL. Mitigated by unique naming and /tmp cleanup policies, but worth noting.
  • readFileSync of temp file: If an attacker replaces the temp file between the user saving and the confirm prompt (TOCTOU), the edited content could be different from what the user saved. Mitigated by 0o600 permissions on the temp file and the confirm prompt, but worth documenting.
  • Export to arbitrary path: resolveExportTarget writes to any path the user specifies. No check that the target is within the project directory. Users could accidentally export to system paths. The overwrite confirmation mitigates accidental overwrites.

Suggestions 💡

  • After clipboard copy of a secret key, consider displaying a brief warning: "Copied — clear your clipboard after use"
  • For editTextField, consider reading the file immediately after the user confirms and comparing mtime to detect external modification
  • Consider adding a --dry-run flag for export that prints to stdout instead of writing a file
  • The SANITIZE_KEYS set is comprehensive but consider making it a shared constant with credentials-command.ts to avoid drift

Summary

Solid local credential management tool with good security hygiene. File permissions, secret masking, and input validation are all properly handled. The clipboard and temp-file concerns are inherent to any local CLI tool working with secrets and are adequately mitigated. No injection, no exposure, no privilege escalation. Approved.

Extends `build credentials manage` with a new top-level action — "Add
credential…" — that branches into two paths:

- Add platform support
  Shows only platforms not yet configured for the app. After a confirm
  that explicitly warns the user the manager will close and they will
  not return automatically, hands off to `onboardingBuilderCommand`
  (the existing `build init` Ink wizard). The manager's Ink session is
  stopped via `stopInitInkSession` before the wizard takes over.

- Add configuration option
  Lists every CREDENTIAL_KNOWLEDGE entry tagged `category: 'configuration'`
  that is NOT already set on the relevant platform(s). Reuses the
  type-aware editor — boolean → true/false select, enum → enum select,
  duration → 1h/6h/2d text prompt with range validation, string →
  single-line text prompt. Shared keys ask whether to write to both
  platforms or one, when multiple are configured and missing.

Categorisation:
- credential — signing/auth material (certs, keystores, API keys,
  passwords). Added through the onboarding wizard, not this menu.
- configuration — behaviour knobs (BUILD_OUTPUT_UPLOAD_ENABLED,
  BUILD_OUTPUT_RETENTION_SECONDS, SKIP_BUILD_NUMBER_BUMP,
  CAPGO_IOS_DISTRIBUTION, CAPGO_ANDROID_FLAVOR, CAPGO_IOS_SCHEME,
  CAPGO_IOS_TARGET).

Main loop changes:
- New `add` branch wired between `view` and `export`.
- `handedOffToOnboarding` flag skips the final `pOutro('Done.')` so the
  user sees only the wizard's own outcome after a platform handoff.
Comment thread cli/src/build/credentials-manage.ts Fixed
…ling

Both `handleAddCredential` and `handleAddConfiguration` previously called
their inner prompts once and returned on any cancel, so pressing Esc in
the value/target picker or the config picker bubbled straight back to
the main action menu.

Wrap each in a while-loop:

- `handleAddCredential` re-shows the Add sub-menu after Add platform
  (handoff declined) or Add configuration (whether something was added
  or not). Only Esc/Back from the Add sub-menu itself returns to the
  main action menu.
- `handleAddConfiguration` re-shows the configuration picker after the
  platform-target or value prompts cancel, and after a successful add.
  Only Esc from the picker returns to the Add credential menu.

After a successful add the working entry is reloaded from disk so the
just-added key drops out of the next picker iteration.

Also updates the status-line wording on the sub-screens to make the new
"Esc returns to the previous menu" semantics explicit.
The --platform option was advertised in the command help and declared on
ManageCredentialsOptions, but the flat-inspector refactor removed the
only line that read it. Result: --platform ios still showed Android
fields in the inspector and let Export/Delete operate on the unscoped
platform — a real inconsistency between help and behaviour, with
medium-severity risk on the destructive paths.

Honour the flag end-to-end:

- Validate the value at entry: reject anything other than ios/android.
- After the appId filter, run entries through applyPlatformFilter:
  every entry is narrowed to just the requested platform via
  narrowEntryToPlatform (drops the other platform's saved data from the
  working copy; on-disk credentials are untouched).
- Entries that don't have the requested platform configured drop out.
  If nothing remains, fail fast with a clear message.
- Re-apply narrowing at every refresh site: post-view-mutate,
  post-add-mutate, and post-delete. When the user deletes the last
  field of the scoped platform via the inspector, exit cleanly with
  "All <platform> credentials cleared." instead of falling back to the
  other platform.

The narrowing is a view filter only — it never modifies on-disk
credentials for the non-scoped platform.
@WcaleNieWolny WcaleNieWolny marked this pull request as ready for review May 13, 2026 08:35
# Conflicts:
#	cli/src/build/onboarding/file-picker.ts
#	cli/src/index.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: 3

🤖 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/credentials-manage.ts`:
- Around line 813-845: actionDecodeField currently prints decoded secrets
directly to the terminal which can expose sensitive fields; update this function
to either (A) redact known sensitive keys when the decoded payload is JSON —
detect JSON in actionDecodeField, walk object keys (e.g., private_key,
private_key_id, client_secret, api_key, secret, password) and replace their
values with a placeholder before logging — and log a single line indicating
redaction, or (B) if row.tag or row.key indicates a secret, require an explicit
user confirmation flag (e.g., --confirm-decode) before printing the decoded
content; implement one approach, keep JSON pretty-printing for non-sensitive
keys, and ensure binary/text handling remains unchanged while avoiding printing
raw secret values.
- Around line 1109-1111: Replace the custom character class in
sanitizeForFilename with the \w shorthand and allow hyphens: change the regex
from /[^a-z0-9_-]/gi to /[^\w-]/g (drop the i flag since \w covers letters
regardless of case) so sanitizeForFilename(value: string) uses
value.replace(/[^\w-]/g, '_').slice(0, 40); keep the function name
sanitizeForFilename and the slice(0, 40) behavior unchanged.
- Around line 23-31: Reorder the import statements so that the module
'./credentials' is imported before './onboarding/file-picker' to satisfy the
perfectionist/sort-imports rule; locate the import block that includes symbols
like clearSavedCredentials, getGlobalCredentialsPath, getLocalCredentialsPath,
listAllApps, loadSavedCredentials, removeSavedCredentialKeys,
updateSavedCredentials and move that whole import above the import for
'./onboarding/file-picker', then run the linter to confirm the import ordering
issue is resolved.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 13d9e3eb-90b0-4121-bc6c-2b819bb29573

📥 Commits

Reviewing files that changed from the base of the PR and between a0483d0 and a20c10d.

📒 Files selected for processing (3)
  • cli/src/build/credentials-manage.ts
  • cli/src/build/onboarding/file-picker.ts
  • cli/src/index.ts

Comment thread cli/src/build/credentials-manage.ts
Comment thread cli/src/build/credentials-manage.ts
Comment thread cli/src/build/credentials-manage.ts
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: a20c10d45a

ℹ️ 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/credentials-manage.ts
Comment thread cli/src/build/credentials-manage.ts
Addresses three review comments on credentials-manage.ts plus one lint
error surfaced while validating them.

- actionDecodeField redacts known-sensitive JSON object keys
  (private_key, private_key_id, client_secret, api_key, secret,
  password, access_token, refresh_token; case-insensitive) before
  printing the pretty-printed JSON. The decoded service-account JSON
  for PLAY_CONFIG_JSON would otherwise dump the RSA private key to
  the terminal. Binary and printable-text decode paths are unchanged.
  A warn line lists which keys were redacted; the success summary now
  notes the redacted count. Users who really want the raw value can
  still pick "Show value" to dump the base64.

- Import block reordered so './credentials' precedes './onboarding/…'
  to satisfy perfectionist/sort-imports.

- sanitizeForFilename now uses /[^\w-]/g (functionally equivalent to
  the previous /[^a-z0-9_-]/gi but accepted by regexp/prefer-w).

- Removed unused getFieldScope helper (dead since the flat-inspector
  refactor; was a lint baseline failure).

Verified: bun run lint → clean, bun run typecheck → clean,
bun run build → green.
Node's writeFile mode option only applies when the file is newly
created — overwriting an existing file leaves the inode's permission
bits untouched. A pre-existing 0644 .env.capgo.* file would therefore
stay world-readable after Export, even though the success log claims
"(mode 0600)".

Add an explicit chmod(target.path, 0o600) after writeFile so the
on-disk mode always matches the message and credential files never
end up group- or world-readable.

Verified empirically: pre-existing 0644 file → after writeFile still
0644 → after chmod correctly 0600.
@sonarqubecloud
Copy link
Copy Markdown

@riderx riderx merged commit 49ed105 into main May 13, 2026
52 checks passed
@riderx riderx deleted the feat/credentials-manage branch May 13, 2026 09:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants