Skip to content

Add interactive defaults and password storage#3

Merged
VectoDE merged 1 commit intomainfrom
codex/fix-password-checker-startup-failure
Oct 21, 2025
Merged

Add interactive defaults and password storage#3
VectoDE merged 1 commit intomainfrom
codex/fix-password-checker-startup-failure

Conversation

@VectoDE
Copy link
Copy Markdown
Owner

@VectoDE VectoDE commented Oct 21, 2025

Summary

  • add a local file-backed password store and expose save/list commands
  • default the CLI to interactive mode without arguments and prompt to save passwords after checks or generation
  • extend configuration and documentation to cover the new vault behaviour

Testing

  • go test ./...
  • go run ./cmd/password-checker list

https://chatgpt.com/codex/tasks/task_e_68f7e36cbc8c832cb00f2086c912a0c5

@VectoDE VectoDE merged commit 45a5670 into main Oct 21, 2025
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.

ℹ️ 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 internal/storage/store.go
Comment on lines +54 to +96
// Save stores or updates a password under the provided label.
func (s *FileStore) Save(label, password string) (StoredPassword, error) {
cleanLabel := strings.TrimSpace(label)
if cleanLabel == "" {
return StoredPassword{}, errors.New("label cannot be empty")
}
if password == "" {
return StoredPassword{}, errors.New("password cannot be empty")
}

s.mu.Lock()
defer s.mu.Unlock()

entries, err := s.readAll()
if err != nil {
return StoredPassword{}, err
}

now := time.Now().UTC()
for idx := range entries {
if strings.EqualFold(entries[idx].Label, cleanLabel) {
entries[idx].Label = cleanLabel
entries[idx].Password = password
entries[idx].UpdatedAt = now
if err := s.writeAll(entries); err != nil {
return StoredPassword{}, err
}
return entries[idx], nil
}
}

record := StoredPassword{
Label: cleanLabel,
Password: password,
CreatedAt: now,
UpdatedAt: now,
}
entries = append(entries, record)
if err := s.writeAll(entries); err != nil {
return StoredPassword{}, err
}

return record, nil
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Prevent concurrent saves from clobbering password store

The new file-backed password store only guards Save with an in-process mutex and rewrites the entire JSON file after loading it into memory. Because the mutex is not shared across processes, two CLI invocations executed in parallel will both read the same snapshot, append their own entry, and then writeAll replaces the file with whichever write finishes last. The earlier save is silently discarded, resulting in lost credentials whenever users run concurrent save commands or the CLI auto-prompts from multiple shells at once. Consider adding a filesystem lock or another inter-process synchronization mechanism to ensure writes are serialized.

Useful? React with 👍 / 👎.

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.

1 participant