Skip to content

Commit a26abd2

Browse files
committed
feat: v0.1.0 release preparation
- Add money setup: creates config, env, encrypted DB in one command - Add money doctor: config/store/provider diagnostics with --json and --fix - Add money providers configure: writes credentials to .env with env: refs - Fix money version: plain text default, --json for envelope, ldflags injection - Add tablewriter for human-mode accounts/transactions list output - Remove dead writeTransactions function - Add CI workflow (go vet, test -race, build on ubuntu/macos) - Add release workflow with goreleaser (linux/darwin amd64/arm64) - Update README and CONTRACTS.md for all shipped commands
1 parent 7d9ee21 commit a26abd2

11 files changed

Lines changed: 1107 additions & 31 deletions

File tree

.github/workflows/ci.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
test:
11+
strategy:
12+
matrix:
13+
os: [ubuntu-latest, macos-latest]
14+
runs-on: ${{ matrix.os }}
15+
steps:
16+
- uses: actions/checkout@v4
17+
18+
- uses: actions/setup-go@v5
19+
with:
20+
go-version: "1.25"
21+
cache: true
22+
23+
- run: go vet ./...
24+
- run: go test ./... -race
25+
- run: go build ./...

.github/workflows/release.yml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags: ["v*"]
6+
7+
permissions:
8+
contents: write
9+
10+
jobs:
11+
release:
12+
runs-on: ubuntu-latest
13+
steps:
14+
- uses: actions/checkout@v4
15+
with:
16+
fetch-depth: 0
17+
18+
- uses: actions/setup-go@v5
19+
with:
20+
go-version: "1.25"
21+
cache: true
22+
23+
- run: go test ./...
24+
25+
- uses: goreleaser/goreleaser-action@v6
26+
with:
27+
version: "~> v2"
28+
args: release --clean
29+
env:
30+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.goreleaser.yaml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
version: 2
2+
3+
builds:
4+
- main: ./cmd/money
5+
binary: money
6+
ldflags:
7+
- -s -w
8+
- -X github.com/thedavidweng/money/internal/cli.Version={{.Version}}
9+
- -X github.com/thedavidweng/money/internal/cli.Commit={{.ShortCommit}}
10+
goos:
11+
- linux
12+
- darwin
13+
goarch:
14+
- amd64
15+
- arm64
16+
17+
archives:
18+
- format: tar.gz
19+
name_template: "money_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
20+
21+
checksum:
22+
name_template: "checksums.txt"
23+
24+
release:
25+
github:
26+
owner: thedavidweng
27+
name: money

README.md

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,13 @@ go install github.com/thedavidweng/money/cmd/money@latest
4141
# Try it without real credentials
4242
money demo accounts list --json
4343

44-
# After creating ~/.money/config.yaml and ~/.money/.env
44+
# Initialize configuration and encrypted database
45+
money setup
46+
47+
# Configure a provider
48+
money providers configure plaid --client-id ... --secret ... --environment sandbox
49+
50+
# Link and sync
4551
money link
4652
money sync
4753
money accounts list --json
@@ -51,18 +57,22 @@ money transactions search "Costco" --json
5157
## Commands
5258

5359
```text
54-
money accounts list List financial accounts
55-
money accounts create-manual Create a local manual account
56-
money transactions list List transactions with filters
57-
money transactions search Search transactions by text
58-
money categories list List transaction categories
59-
money tags list List transaction tags
60-
money recurring list List recurring transactions
61-
money link Link a financial institution
62-
money providers plaid link Link a Plaid Provider Item
63-
money providers bridge link Link a Bridge Provider Item
64-
money sync Sync linked provider data
65-
money demo <command> Run against non-persistent sample data
60+
money setup Initialize configuration and encrypted database
61+
money doctor Check configuration and system health
62+
money accounts list List financial accounts
63+
money accounts create-manual Create a local manual account
64+
money transactions list List transactions with filters
65+
money transactions search Search transactions by text
66+
money categories list List transaction categories
67+
money tags list List transaction tags
68+
money recurring list List recurring transactions
69+
money link Link a financial institution
70+
money providers configure <provider> Configure provider credentials
71+
money providers plaid link Link a Plaid Provider Item
72+
money providers bridge link Link a Bridge Provider Item
73+
money sync Sync linked provider data
74+
money demo <command> Run against non-persistent sample data
75+
money version Print version
6676
```
6777

6878
Read commands and provisional sync diagnostics support `--json` for machine-readable output. Manual write operations require `--dry-run` or `--confirm`.

RELEASE_PLAN.md

Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
# Release Plan: v0.1.0
2+
3+
This plan closes the gap between the current codebase and a first public release. It assumes `IMPLEMENTATION_PLAN.md` Phases 1–7 are complete (they are) and focuses only on the remaining work that blocks a tagged, installable, agent-usable release.
4+
5+
## Release Definition
6+
7+
A release is ready when all of the following hold:
8+
9+
- Every command listed as an "Initial command" in `docs/PRD.md` and `IMPLEMENTATION_PLAN.md` is implemented and covered by contract tests.
10+
- A new user with no prior `~/.money` can run a single bootstrap command to reach a working encrypted store.
11+
- `money doctor` returns structured diagnostics for config, store, providers, links, and sync readiness.
12+
- `money version` obeys the `--json` flag and reports the real build version injected at link time.
13+
- `go test ./...` and `go vet ./...` run in CI on every push and pull request.
14+
- A tagged release (`v0.1.0`) exists on GitHub with prebuilt binaries for the supported platforms and a matching Go module proxy entry, so `go install github.com/thedavidweng/money/cmd/money@latest` resolves to that tag.
15+
- README, `docs/PRD.md`, `docs/CONTRACTS.md`, and `docs/CONFIG.md` describe exactly what ships; no documented command or flag is missing from the binary.
16+
- No runtime code references donor AI, Ray hosted proxy, subscription billing, or chat concepts (`rg` verification passes).
17+
18+
## Required Reading Before Implementation
19+
20+
1. `AGENTS.md`
21+
2. `docs/PRD.md`
22+
3. `docs/CONFIG.md`
23+
4. `docs/CONTRACTS.md`
24+
5. `docs/SCHEMA.md`
25+
6. `IMPLEMENTATION_PLAN.md`
26+
27+
## Principles
28+
29+
- Occam's razor: build the minimum surface that closes each release criterion. Do not add speculative commands, flags, or configuration.
30+
- No hidden fallbacks: every missing credential, missing file, or unopenable store must produce a stable error code.
31+
- Small deep modules: keep onboarding helpers inside `internal/config` and `internal/cli`; do not introduce a new top-level package unless two or more callers need it.
32+
- Dead-code sweep: after each phase, remove code paths that were only used by now-replaced scaffolding.
33+
34+
## Phase R1: Onboarding Commands
35+
36+
Goal: a new user can go from zero to a working encrypted store and diagnose problems without reading source.
37+
38+
### R1.1 `money setup`
39+
40+
Steps:
41+
42+
1. Add `money setup` command. Human mode runs an arrow-key interactive flow using `charm.land/huh/v2`; JSON mode requires all inputs via flags and fails with `VALIDATION` if required flags are missing.
43+
2. Resolve config path with the same rules as `internal/config` load order; create `~/.money/` when using the default path.
44+
3. Write a `config.yaml` skeleton with `database.path`, `database.encryption_key: {env: MONEY_DB_ENCRYPTION_KEY}`, and empty `providers:` block.
45+
4. Generate a 32-byte random `MONEY_DB_ENCRYPTION_KEY`, base64url-encoded without padding, and write it to the resolved `.env` file with `0600` permissions on POSIX platforms.
46+
5. Open the encrypted store and run migrations so that read commands work immediately after setup.
47+
6. Never print the encryption key. Setup output reports file paths and boolean `secret_created: true`.
48+
7. Support `--config <path>` to target an alternate location. Support `--force` in JSON mode to overwrite an existing env var value; human mode asks with the arrow-key selector.
49+
8. On any write failure after partial writes, stop, report what was written and what failed, return exit code `1` (`INTERNAL` or `CONFIG_WRITE_FAILED`).
50+
9. On DB open/migration failure after config/env writes, keep the written files, report the DB failure, and suggest running `money doctor`.
51+
10. After success, run the shared doctor checks (see R1.2) and include their results in setup output.
52+
53+
Acceptance:
54+
55+
- First-time `money setup` on an empty home directory produces a working config, env, and encrypted DB.
56+
- `money accounts list --json` succeeds with an empty `accounts` array immediately after setup.
57+
- Re-running `money setup` on an already-configured install is a no-op for files that already exist and does not rotate the encryption key.
58+
- Setup never prints secret values. JSON output exposes only booleans and paths for secrets.
59+
- Setup does not attempt DB repair or re-encryption.
60+
61+
### R1.2 `money doctor`
62+
63+
Steps:
64+
65+
1. Add `money doctor` with sections `Config`, `Store`, `Providers`, `Links`, `Sync`, and `Warnings`. Each diagnostic is a `{ code, status, message, category }` record with status `ok`, `warn`, or `error`.
66+
2. Implement config checks: config file exists, env file exists, required `database.path` and `database.encryption_key` resolvable, optional provider credentials resolvable.
67+
3. Implement store checks: DB file exists at configured path, opens with the configured key, schema version matches latest migration.
68+
4. Implement provider checks: for each registered provider, report configured vs available state (credentials present but valid/invalid distinction is `warn`-level only until sync is run).
69+
5. Implement links check: count linked provider items per provider from the store.
70+
6. Implement sync check: last `sync_runs` entry status and time; no runs is `warn` only if at least one provider item exists.
71+
7. Implement warnings check: broad env-file permissions on POSIX, direct secret scalars in YAML, config pointing at non-default path without `--config` or `MONEY_CONFIG`.
72+
8. Implement `money doctor --json`: return an envelope with `data.diagnostics[]` and `meta.command: "doctor"`. Do not include secret values.
73+
9. Implement `money doctor --fix` with exactly these repairs: create missing `~/.money/`, create missing config skeleton, create missing env skeleton, generate missing DB encryption key, chmod env file to `0600` on POSIX.
74+
10. Run the same diagnostic code from `money setup` so setup summary and doctor never diverge.
75+
76+
Acceptance:
77+
78+
- `money doctor` on an unconfigured system reports `Config: error` and exits non-zero.
79+
- `money doctor --json` returns a parseable envelope even when config is missing.
80+
- `money doctor --fix` is idempotent, never rotates keys, never edits user-set values, and never migrates donor config paths.
81+
- `money doctor --fix --dry-run` prints the repair plan without writing.
82+
- No diagnostic prints secret values or reversible partial previews.
83+
84+
### R1.3 `money providers configure <provider>`
85+
86+
Steps:
87+
88+
1. Add `money providers configure plaid` and `money providers configure bridge` commands.
89+
2. Human mode uses the arrow-key selector for overwrite confirmation and free-text prompts for scalar credentials, displaying mask characters while typing secrets.
90+
3. JSON mode requires all credential flags; partial credentials return `VALIDATION` and write nothing.
91+
4. Write secrets to the resolved env file and corresponding `env:` references to `config.yaml`. Never write raw secret values into `config.yaml`.
92+
5. Existing env vars are not overwritten unless human user confirms via the arrow-key selector or JSON caller passes `--force`.
93+
6. After writing, run only that provider's doctor diagnostics plus global blocking diagnostics.
94+
7. Configuration is atomic per provider. If any required field is missing or any write fails, stop immediately, report what was written, and return `CONFIG_WRITE_FAILED`.
95+
96+
Acceptance:
97+
98+
- `money providers configure plaid --client-id ... --secret ... --environment sandbox --json` writes env entries and YAML `env:` references, then prints Plaid-only diagnostics.
99+
- Re-running with the same values is a no-op.
100+
- Missing any required Plaid or Bridge field fails atomically before any file write.
101+
102+
## Phase R2: Version and Output Correctness
103+
104+
Goal: every command obeys the contract for stdout, `--json`, and reports the real build version.
105+
106+
### R2.1 Fix `money version`
107+
108+
Steps:
109+
110+
1. Change the default mode: when `--json` is not set, print a single plain-text line such as `money 0.1.0 (commit abc1234)`.
111+
2. When `--json` is set, print the existing envelope.
112+
3. Replace the hardcoded `"0.0.0"` with a package-level variable populated via `-ldflags "-X github.com/thedavidweng/money/internal/cli.Version=... -X github.com/thedavidweng/money/internal/cli.Commit=..."`.
113+
4. `go build` without ldflags yields `dev` for both fields, never a stale semver.
114+
115+
Acceptance:
116+
117+
- `money version` prints plain text on stdout.
118+
- `money version --json` prints the JSON envelope on stdout.
119+
- A binary built with ldflags reports its tag and commit.
120+
- Contract test covers both modes.
121+
122+
### R2.2 Table rendering for human mode
123+
124+
Steps:
125+
126+
1. Add `github.com/olekukonko/tablewriter` to `go.mod`.
127+
2. Render `accounts list` human mode with columns `NAME`, `TYPE`, `BALANCE`, `AVAILABLE`, `CURRENCY`, `SOURCE`, `UPDATED`. Add `--verbose` for provider IDs and deeper provenance.
128+
3. Render `transactions list` / `transactions search` human mode with columns `DATE`, `ACCOUNT`, `MERCHANT`, `AMOUNT`, `CATEGORY`, `STATUS`. Add `--verbose` for local IDs, provider category, tags, note, and source.
129+
4. Render monetary values with explicit text signs; color is auxiliary only (green for positive, red for negative when stdout is a TTY).
130+
5. JSON output must remain byte-equivalent to the current contract. Contract tests stay unchanged.
131+
132+
Acceptance:
133+
134+
- Human `accounts list` and `transactions list|search` produce aligned tables.
135+
- Non-TTY stdout suppresses color escapes.
136+
- JSON envelopes are unchanged.
137+
138+
### R2.3 Dead code sweep
139+
140+
Steps:
141+
142+
1. Run `go vet ./...` and address any warnings.
143+
2. Review `internal/cli`, `internal/linking`, and `internal/providers` for helpers that have no callers after R1 lands.
144+
3. Remove comments, fixtures, and branches that only existed to scaffold Phase 1–3 work.
145+
146+
## Phase R3: Release Infrastructure
147+
148+
Goal: every push is tested, and a tag produces published binaries.
149+
150+
### R3.1 CI workflow
151+
152+
Steps:
153+
154+
1. Create `.github/workflows/ci.yml` that triggers on `push` to `main` and on `pull_request`.
155+
2. Steps: checkout, setup Go 1.25, `go vet ./...`, `go test ./... -race`, verify `go build ./...`.
156+
3. Cache Go modules and the Go build cache keyed on `go.sum`.
157+
4. Run on `ubuntu-latest` and `macos-latest`.
158+
5. Make the README CI badge resolve to this workflow.
159+
160+
Acceptance:
161+
162+
- CI badge is green on `main`.
163+
- A pull request that breaks a test fails CI.
164+
165+
### R3.2 Release workflow
166+
167+
Steps:
168+
169+
1. Add a `.goreleaser.yaml` configured for Linux amd64/arm64 and macOS amd64/arm64 binaries, archived as tarballs.
170+
2. Inject `Version` and `Commit` via `-ldflags`.
171+
3. Skip Docker images and Homebrew taps for v0.1.0; add them only if there is a real maintainer commitment.
172+
4. Add `.github/workflows/release.yml` triggered on tags matching `v*`.
173+
5. Release workflow: checkout with full history, setup Go, run `go test ./...`, run `goreleaser release --clean`.
174+
6. Generate SHA256 checksums for every archive and include them in the GitHub release.
175+
176+
Acceptance:
177+
178+
- Pushing a tag `v0.1.0-rc.1` produces a draft GitHub release with platform archives and checksums.
179+
- Downloaded binaries report the tag version via `money version`.
180+
181+
### R3.3 Module and tag
182+
183+
Steps:
184+
185+
1. Confirm the Go module path matches the repository path and that no replace directives leak into the public module.
186+
2. Tag `v0.1.0` after R1–R3.2 land and CI is green on `main`.
187+
3. Verify `go install github.com/thedavidweng/money/cmd/money@v0.1.0` succeeds on a clean machine.
188+
4. Update the README install instructions to reference `@latest` and to mention the release page for prebuilt binaries.
189+
190+
Acceptance:
191+
192+
- `go install github.com/thedavidweng/money/cmd/money@latest` installs a binary that prints `money v0.1.0` on `version`.
193+
- The release page contains archives for the four target platforms plus checksums.
194+
195+
## Phase R4: Documentation Alignment
196+
197+
Goal: every documented command and flag exists in the binary, and every binary command is documented.
198+
199+
Steps:
200+
201+
1. Walk `docs/PRD.md` "Initial commands" list; mark each as implemented or remove it from the initial list.
202+
2. Update `docs/CONTRACTS.md` to cover `setup`, `doctor`, `version`, and `providers configure` JSON shapes.
203+
3. Update `README.md` command list to exactly match the binary.
204+
4. Remove any deferred capability from user-facing docs that is not behind a flag or subcommand in v0.1.0.
205+
5. Verify `docs/ROADMAP.md` Phase 1 and Phase 2 descriptions match what shipped.
206+
207+
Acceptance:
208+
209+
- Running `money --help` and comparing against the README command list shows no missing or extra commands.
210+
- Every `--json` command named in `docs/CONTRACTS.md` returns a valid envelope in a contract test.
211+
212+
## Verification Before Tagging
213+
214+
Run all of the following on a clean workspace. All must pass:
215+
216+
```bash
217+
go vet ./...
218+
go test ./... -race
219+
go run ./cmd/money version --json
220+
go run ./cmd/money setup --config /tmp/money/config.yaml --json
221+
go run ./cmd/money --config /tmp/money/config.yaml doctor --json
222+
go run ./cmd/money --config /tmp/money/config.yaml accounts list --json
223+
rg -n "RAY_API_KEY|RAY_PROXY_BASE|rayfinance\.app|Anthropic|OpenAI|conversation_history|ai_audit_log|memories" --glob '!donors/**'
224+
git status --short --ignored
225+
```
226+
227+
The `rg` search must return zero matches outside `donors/`. `git status` must be clean.
228+
229+
## Out of Scope for v0.1.0
230+
231+
These are deferred to v0.2.0 or later and must not block the tag:
232+
233+
- `money accounts update <id> --alias ...`
234+
- `money transactions cleanup --removed ...`
235+
- Monarch, CSV, and Apple Card import sources
236+
- MX and Finicity provider adapters
237+
- Budgeting, rules, cashflow, net worth primitives
238+
- Homebrew tap, Docker image, Windows builds
239+
240+
If any of these reappear in implementation work before v0.1.0, move them back to `IMPLEMENTATION_PLAN.md` under a new phase instead of expanding this release plan.

0 commit comments

Comments
 (0)