Skip to content

Add apw doctor --bundle redacted diagnostic export#62

Open
jmcte wants to merge 6 commits into
mainfrom
claude/diagnostic-bundle-56
Open

Add apw doctor --bundle redacted diagnostic export#62
jmcte wants to merge 6 commits into
mainfrom
claude/diagnostic-bundle-56

Conversation

@jmcte
Copy link
Copy Markdown
Contributor

@jmcte jmcte commented May 21, 2026

Summary

Implements apw doctor --bundle <path> per #56. Operators can now produce a
single redacted tarball to attach to support requests instead of copy-pasting
each output stream individually.

Closes #56.

Layout

apw-doctor-bundle/
  manifest.json                # bundleVersion, files, redaction guarantees
  doctor.json                  # full `apw doctor --json` payload
  environment.json             # `apw doctor --ci` environment checks
  os.json                      # uname + sw_vers (macOS)
  native-app/file-listing.json # path/size/mode for files under ~/.apw/native-app/

The archive file is written mode 0600. Bundle staging happens under the
system temp dir (not under ~/.apw/native-app/) so it cannot race the
file-listing walk and leak its own UUID-suffixed name into the metadata.

Redaction guarantees

  • Environment variables are never read or copied into the bundle.
  • File contents under ~/.apw/native-app/ are never read; only the metadata listing is included.
  • credentials.json, config.json, and broker.log are explicitly excluded.
  • Every staged JSON string and object key is scanned for token-like patterns. A match aborts the bundle and the archive is never written.
  • Vendor key prefixes embedded inside longer diagnostic strings are treated as unsafe.

Review follow-up

  • --ci now conflicts with --bundle at the clap layer so apw doctor --ci --bundle <path> cannot silently exit without writing the archive.
  • Added unit and e2e regressions proving the conflict fails before any archive is created.

Verification

  • cargo fmt --check
  • cargo clippy --all-targets -- -D warnings
  • cargo test
  • cargo test --manifest-path rust/Cargo.toml cli::tests::doctor_ci_and_bundle_are_mutually_exclusive -- --nocapture
  • cargo test --manifest-path rust/Cargo.toml --test native_app_e2e doctor_ci_and_bundle_fail_before_writing_archive -- --nocapture
  • bash scripts/ci/run-fast-checks.sh

Notes

  • Mutation testing / CRAP indicator coverage remains in the dedicated quality PR; this PR adds issue-specific bundle redaction and CLI conflict regressions.

Closes #56.

Introduces an `apw doctor --bundle <path>` flag that writes a tar.gz
operators can attach to support requests without leaking credentials.

Layout (apw-doctor-bundle/):
- manifest.json            bundleVersion, file list, redaction guarantees
- doctor.json              full `apw doctor --json` payload
- environment.json         `apw doctor --ci` environment checks
- os.json                  uname + sw_vers on macOS
- native-app/file-listing.json  metadata-only listing of ~/.apw/native-app/

Redaction guarantees:
- env vars never read or copied
- no file contents from ~/.apw/native-app/ (only path/size/mode/type)
- credentials.json, config.json, broker.log explicitly excluded
- every string in the staged JSON is scanned for token-like patterns
  (long high-entropy alphanumeric runs, vendor key prefixes such as
  ghp_/AKIA/sk-, and the in-tree demo password sentinel); a match
  aborts the bundle with an InvalidConfig (102) error and the archive
  is never written
- archive file is mode 0600

Bundle staging happens under the system temp dir (not under
~/.apw/native-app/) so it cannot race the file-listing walk and leak
its own UUID-suffixed name into the metadata. Tar is invoked via
`std::process::Command` to keep dependencies unchanged.

Tests:
- 5 unit tests in src/bundle.rs covering the redaction heuristic
  (paths, version strings, and explicit secret patterns) and the
  fail-closed audit
- 2 e2e tests in tests/native_app_e2e.rs that
  - write a plausible-secret credentials.json, build the bundle, and
    grep every extracted byte for the secret (none survives)
  - inject a sentinel into APW_RUNNER_LABELS and confirm the bundle
    aborts with InvalidConfig and never writes the archive

Docs:
- docs/SECURITY_POSTURE_AND_TESTING.md describes layout and
  redaction guarantees
- README.md adds the flag to the common-commands list
@jmcte jmcte marked this pull request as ready for review May 22, 2026 17:35
@jmcte jmcte requested a review from pheidon as a code owner May 22, 2026 17:35
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

apw-cli/rust/src/cli.rs

Lines 472 to 476 in 3160bfd

if args.ci {
// CI mode always emits the structured envelope so downstream
// tooling can parse `[FAIL]` deterministically.
print_output(&environment_json, Status::Success, true);
return Ok(());

P2 Badge Disallow --ci from silently skipping bundle creation

run_doctor returns immediately when args.ci is set, so apw doctor --ci --bundle <path> exits सफल without ever attempting write_diagnostic_bundle. This creates a silent success path where operators think a bundle was produced but no archive exists; either mark these flags as conflicting in clap or explicitly error when both are provided.

ℹ️ 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 rust/src/bundle.rs
Comment thread rust/src/bundle.rs
@jmcte jmcte enabled auto-merge (squash) May 22, 2026 18:35
Copy link
Copy Markdown
Contributor

@pheidon pheidon left a comment

Choose a reason for hiding this comment

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

I cannot approve this yet. The --ci path still returns before --bundle is handled, so apw doctor --ci --bundle <path> exits successfully without writing the requested archive. That is a silent-success failure for the exact operator workflow this PR adds.

Please either make --ci and --bundle conflict at the clap layer, or return an explicit error when both are supplied. The existing CI is green, but this behavior remains a release blocker for the bundle flag.

@athena-omt athena-omt added area:infra Infrastructure, CI, release, governance, scripts, or repo setup. lane:daedalus Daedalus implementation/forge lane. review:athena Athena review governance requested. risk:medium Medium-risk change; normal care required. state:waiting-checks Waiting for CI/check status to settle. status:needs-review PR is ready for Athena review. labels May 23, 2026
@jmcte jmcte removed the state:waiting-checks Waiting for CI/check status to settle. label May 24, 2026
@jmcte
Copy link
Copy Markdown
Contributor Author

jmcte commented May 24, 2026

Requested-change follow-up is addressed and ready for re-review.

  • apw doctor --ci --bundle <path> is now rejected at the clap layer instead of silently succeeding without writing an archive.
  • Added regressions for both the CLI parse path and the native app e2e archive path:
    • cli::tests::doctor_ci_and_bundle_are_mutually_exclusive
    • native_app_e2e::doctor_ci_and_bundle_fail_before_writing_archive
  • Current live checks are green.
  • Thread-aware review query shows no current non-outdated unresolved review threads.

Verification recorded on the PR:

  • cargo fmt --check
  • cargo clippy --all-targets -- -D warnings
  • cargo test
  • focused CLI/e2e regressions
  • bash scripts/ci/run-fast-checks.sh

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

Labels

area:infra Infrastructure, CI, release, governance, scripts, or repo setup. lane:daedalus Daedalus implementation/forge lane. review:athena Athena review governance requested. risk:medium Medium-risk change; normal care required. status:needs-review PR is ready for Athena review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Roadmap: diagnostic-bundle export from apw doctor

4 participants