Skip to content

Add --no-persist-password option to configure#253

Open
jackson-asmith wants to merge 1 commit into
jamesyc:mainfrom
jackson-asmith:harden/keychain-password
Open

Add --no-persist-password option to configure#253
jackson-asmith wants to merge 1 commit into
jamesyc:mainfrom
jackson-asmith:harden/keychain-password

Conversation

@jackson-asmith

@jackson-asmith jackson-asmith commented Jul 10, 2026

Copy link
Copy Markdown

What

Adds configure --no-persist-password, which writes the config without saving TC_PASSWORD to .env. Later commands then prompt for it or read it from --password-env/--password-stdin.

Why

For users who don't want the device password persisted in .env. This reuses the existing persist_password plumbing (the app already exposes it; the CLI just hardcoded True).

Per your feedback, I dropped the --keychain integration entirely — you're right that a macOS-only path doesn't belong on a core cross-platform command like configure (people script it on Raspberry Pis). No new modules, no platform-specific code.

Changes

  • --no-persist-password flag; threads persist_password into the existing configure flow.
  • Test: --no-persist-password omits TC_PASSWORD from the written config (contrasted with the existing test showing it's saved by default).
  • One DETAIL.md line.

🤖 Generated with Claude Code

@gemini-code-assist gemini-code-assist Bot left a comment

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.

Code Review

This pull request introduces macOS Keychain integration to securely store and retrieve the Time Capsule device password, adding --keychain and --no-persist-password options to the configuration flow. A critical bug was identified in configure.py where the password is cleared from the values dictionary before store_password_in_keychain is called, which prevents the password from being saved to the Keychain. A fix was suggested to preserve the password in a local variable before clearing the dictionary.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/timecapsulesmb/cli/configure.py Outdated
Comment on lines +632 to +633
if args.keychain:
store_password_in_keychain(values.get("TC_HOST", ""), values.get("TC_PASSWORD", ""), json_output=args.json)

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.

critical

When --keychain is specified, persist_password is set to False. This means result.values returned by run_configure_flow will not contain TC_PASSWORD.

Because values.clear() is called and then updated with result.values inside the while True loop (around lines 616-617), the password is wiped from the values dictionary. Consequently, values.get("TC_PASSWORD") is empty when store_password_in_keychain is called after the loop, causing the password to never be stored in the macOS Keychain.

To fix this, you should preserve the password before clearing the values dictionary, or store it in the keychain before breaking the loop. For example, you can capture the password in a local variable inside the loop:

            password_to_store = values.get("TC_PASSWORD", "")
            values.clear()
            values.update(result.values)

And then use password_to_store when calling store_password_in_keychain:

        if args.keychain:
            store_password_in_keychain(values.get("TC_HOST", ""), password_to_store, json_output=args.json)

jackson-asmith added a commit to jackson-asmith/TimeCapsuleSMB that referenced this pull request Jul 10, 2026
Addresses review feedback on jamesyc#253. The keychain store read TC_PASSWORD
from values after values.clear()/update(result.values); it worked only
because result.values happens to retain the password (the non-persist pop
runs on a copy). Capture the password before the clear so the store does
not depend on that, and add a regression test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@jackson-asmith

Copy link
Copy Markdown
Author

Thanks for the review. On the flagged critical: I verified that result.values actually does retain TC_PASSWORD even with --keychainwrite_configure_env_file pops the password from a copy (output = dict(values)), so the store was working. That said, the dependency was fragile, so I applied your suggestion: the password is now captured into password_for_keychain before values.clear(), and I added a regression test (test_configure_keychain_stores_password_when_not_persisted) that drives configure --keychain and asserts keychain_set is called with the password. Pushed in 6b752b0.

@jamesyc

jamesyc commented Jul 13, 2026

Copy link
Copy Markdown
Owner

Adding --keychain is against my design decision; note the README, where the python scripts are very intentionally linux friendly. A key design decision is that all commands must be cross platform. The only exception is repair-xattr, for legacy reasons, and I'm debating removing it.

Some users script this on a raspberry pi, so this is of practical concern. I do not want anything mac-only for a core command like configure, even with gating.

I'm fine with --no-persist-password.

Per maintainer feedback on jamesyc#253: drop the macOS-only Keychain integration
(keeps configure cross-platform) and keep only --no-persist-password, which
writes the config without saving TC_PASSWORD. Later commands then prompt or
read the password from --password-env/--password-stdin.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@jackson-asmith
jackson-asmith force-pushed the harden/keychain-password branch from 6b752b0 to 58cf611 Compare July 13, 2026 21:37
@jackson-asmith jackson-asmith changed the title Add Keychain and no-persist password options to configure Add --no-persist-password option to configure Jul 13, 2026
@jackson-asmith

Copy link
Copy Markdown
Author

Slimmed to just --no-persist-password as you suggested (58cf611, force-pushed). Removed the --keychain flag, the core/credentials.py module, and the runtime Keychain fallback — nothing macOS-only remains, so configure stays fully cross-platform. Diff is now ~10 lines in configure.py plus a test.

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.

2 participants