Commit graph

13 commits

Author SHA1 Message Date
Brian Majewski
110ac514cc v0.2.0.0 feat: sync gradle.properties keys via .secrets-files (EGB-531)
Add a committed .secrets-files manifest that lets secrets track designated
keys from files outside the project root (motivating case:
~/.gradle/gradle.properties for Android Clerk publishable keys, which
Android Studio GUI builds read but terminal env vars can't reach).

- push extracts only the named keys, encrypts under <project>/external/
- pull MERGES them into the target, preserving unrelated keys/comments/order
- pure-bash merge (no sed/regex): exact-string key match, opaque values
- path validator: basename gradle.properties, within $HOME, no symlink/..
- external/ subdir keeps blobs out of the dotenv *.age globs; rekey + list
  recurse explicitly
- which reads back the manifest; list shows [external]; pre-commit blocks
  plaintext gradle.properties

Also fixes two latent bugs in 'secrets rekey' (never completed before, no
prior test): age-keygen refusing to overwrite key.txt, and an EXIT trap
referencing an out-of-scope local under set -u.

Tests: 80 -> 104.

Reviewed via /autoplan (CEO/Eng/DX). EGB-531.
2026-05-26 12:42:04 -07:00
Brian Majewski
ac2195d830 Update repository URLs in README and CHANGELOG to reflect migration to Codeberg 2026-05-15 08:20:56 -07:00
Brian Majewski
7c3a76e8c1
v0.1.1.0 feat: optional remote URL in .secrets-store (EGB-282) (#2)
* chore: ignore .gstack/ (per-project local state)

* feat: optional remote URL in .secrets-store (EGB-282)

A second whitespace-separated token after the store name in .secrets-store
is treated as the store's git remote URL. When a teammate clones a project
bound to a store they don't have locally yet, the directed missing-store
error now fills in `git clone <url> <path>` so they can copy-paste instead
of asking the original setter for the URL.

Backward compatible: single-token .secrets-store files (the v0.1.0.x
format) continue to work and produce the existing `<their-store-remote>`
placeholder.

Security hardening (caught by adversarial review during /ship):
- The rendered git clone line is meant to be copy-pasted by a teammate.
  Without sanitization, `work evil.git;rm -rf ~` would render verbatim
  and execute `rm -rf ~` on paste. The parser now rejects URLs containing
  shell metacharacters (;&|<>$`(){}*?!"'\\), control characters (incl.
  ANSI escape sequences that could spoof terminal output), and embedded
  whitespace. Rejected URLs are dropped with a stderr warning; the error
  falls back to the safe placeholder.
- Switched from `set -- $line` to `read -r spec rest` so the URL field
  isn't glob-expanded or word-split — important so `work *` from a
  populated directory doesn't leak filenames into the URL field.

Tests 72 → 80. New: backward compat, SSH+HTTPS+~/-prefix URL forms,
comment-and-URL form, four named injection vectors (shell metachar,
backtick, $(), ANSI escape), multi-token URL, glob char, and a positive
test asserting standard git URL chars round-trip unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore: bump version and changelog (v0.1.1.0)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 14:54:45 -07:00
Brian Majewski
1bb729f73b fix: secrets which prints full .secrets-store path (v0.1.0.1)
_find_secrets_store_file used to set _LAST_FOUND_AT inside the $(...)
subshell that resolve_store invoked it from, so the parent shell never
received the value and `secrets which` reported `source: .secrets-store
file ()` with empty parens. Function now returns a tab-separated
<dir>\t<source-path> tuple; resolve_store splits it in the parent shell.

Caught by /land-and-deploy post-merge fresh-clone verification — the
existing test grepped for the substring ".secrets-store file" which
matched the broken truncated form. Tightened to assert the full file
path appears in the parenthetical.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 14:33:39 -07:00
Brian Majewski
09a7bdcc46 chore: persist deploy config in CLAUDE.md
CLI tool with no platform deploy. Released via merge to main +
optional version tags. Recorded so /land-and-deploy skips the
dry-run on subsequent invocations.
2026-05-09 14:30:50 -07:00
Brian Majewski
7e6ddf3a12
v0.1.0.0 feat: multi-store support (EGB-281) (#1)
* feat: multi-store support via .secrets-store + --store flag

Layer four-rule store resolution on top of the existing SECRETS_DIR primitive
so users can manage multiple isolated encrypted stores (work vs personal,
per-client, etc.) without giving up the tool's small-bash-script pitch.

Resolution order (highest first):
  1. --store <dir>  flag (parsed in main pre-pass)
  2. .secrets-store file in cwd or any ancestor up to $HOME
  3. SECRETS_DIR    env var (legacy escape hatch)
  4. ~/.secrets     default

resolve_store() updates both SECRETS_DIR and KEY_FILE so existing single-store
codepaths just work. New cmd_which / where / status report the active store.
cmd_init, push, pull, push_workspaces, pull_workspaces, list, rm, rekey, run,
which all call resolve_store at entry.

Hardening from the EGB-281 adversarial review:
- F1: cmd_run EXIT trap is now a named function (not string-interpolated),
  so paths with apostrophes still get plaintext cleaned up
- F2: symlinked .secrets-store files are skipped, never read
- F3/F4: --store flag rejects flag-shaped values and empty --store=
- F5: HOME unset is detected up-front with a directed error
- F11: check_initialized / check_key give context-aware errors that name
  both recovery paths (git clone vs secrets init) when a teammate clones
  a project bound to a non-existent store on their machine

Tests: 37 → 66 (29 new). HOME=\$TEST_TMPDIR added to test setup so the
walk-up logic stays bounded inside fixtures.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs: add Multiple stores section to README

Five subsections walk users through: how store resolution works, how to
set up a second store on a machine, how to bind a project, how teammates
join a bound project, and how to undo or change a binding. SECRETS_DIR
table entry now points readers at the new --store flag and .secrets-store
file as the preferred mechanisms.

* chore: bump version and changelog (v0.1.0.0)

First formal release. EGB-281 adds multi-store support; this commit
seeds the VERSION file (4-digit MAJOR.MINOR.PATCH.MICRO) and the
CHANGELOG.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 14:30:28 -07:00
Brian Majewski
edb1614941 Update README to correct the repository URL for the secrets tool
- Changed the clone command for the secrets tool from SSH to HTTPS for easier access.
- Ensured consistency in instructions for downloading the secrets tool across different sections of the README.
2026-05-04 13:31:36 -07:00
Brian Majewski
11b6ef87fa Update README to enhance documentation on secrets run functionality and improve diagram formatting
- Replaced static diagram with a mermaid flowchart for better visualization of secrets management.
- Expanded section on `secrets run` to clarify its operation as a pull → run → clear pipeline.
- Added examples and syntax details for using `secrets run` in various scenarios.
- Included information on automatic clearing of plaintext files after command execution.
2026-03-30 07:21:45 -07:00
Brian Majewski
f84ec44e29 Refactor secrets CLI to improve error handling and add logging features
- Enhanced error handling for invalid secret file formats and missing configurations.
- Introduced logging functionality to track command execution and errors.
- Updated tests to ensure robust coverage of new error scenarios and logging outputs.
- Revised documentation to include details on error messages and logging usage.
2026-03-30 07:12:21 -07:00
Brian Majewski
cc647b922f Update README to clarify code block formatting for diagrams and shell commands
- Changed code block syntax from generic to specific types (`diagram` and `shell`) for better readability.
- Enhanced the presentation of secrets storage and organization examples.
2026-03-24 07:04:09 -07:00
Brian Majewski
e347e73976 Enhance secrets CLI to support additional secret file types and clear command
- Updated file tracking to include `.dev.vars` alongside `.env` and `.env.*`.
- Improved pre-commit hook to block plaintext secret files, including `.dev.vars`.
- Added `clear` command to remove plaintext secret files from the current directory and workspaces.
- Enhanced tests to cover new functionality for `.dev.vars` and the `clear` command.
- Updated documentation to reflect changes in tracked files and command usage.
2026-03-24 06:58:45 -07:00
Brian Majewski
585367b9a6 Add support for package.json workspaces in secrets CLI
- Introduced `--workspaces` flag for `push` and `pull` commands to handle environment files in monorepos.
- Updated README and CLAUDE.md to reflect new workspace functionality and installation instructions.
- Enhanced test suite with cases for workspace operations, ensuring proper encryption and decryption of environment files.
- Improved error handling for missing package.json and workspaces field.
- Increased test coverage from 20 to 25 tests.
2026-03-23 17:01:22 -07:00
Brian Majewski
7eae4ea9a1 initial commit 2026-03-23 16:49:04 -07:00