Commit Graph

9 Commits

Author SHA1 Message Date
bvandeusen 3cf829752b chore(ci): migrate workflows to gitea + consolidate keystore secret
flutter / analyze-test-build (push) Failing after 2s
test-go / test (push) Successful in 33s
android / Build + lint + test (push) Failing after 41s
test-web / test (push) Successful in 41s
android / Build signed release APK (push) Has been skipped
test-go / integration (push) Successful in 11m16s
- rename .forgejo/workflows/ to .gitea/workflows/ (git mv preserves
  history); Gitea Actions reads either path, but the directory now
  matches the active platform
- collapse ANDROID_STORE_PASSWORD + ANDROID_KEY_PASSWORD into a
  single ANDROID_KEYSTORE_PASSWORD secret (PKCS12 keystores require
  the two passwords to be identical, so the duplication carried no
  information); build.gradle.kts still reads two env vars to stay
  format-agnostic, both now sourced from the same secret in CI
- ignore android/*.keystore, android/*.keystore.*, android/*.jks,
  android/keystore.properties so the regenerated signing material
  never reaches a remote on accident
- update prose references from Forgejo to Gitea in CLAUDE.md and
  the docs; the historical "migrated from Forgejo" note in CLAUDE.md
  is kept intentionally; forgejo/upload-artifact@v3 action refs are
  left untouched (canonical artifact action, resolves cleanly under
  Gitea Actions)

Operator side: ANDROID_KEY_ALIAS, ANDROID_KEYSTORE_PASSWORD, and
ANDROID_KEYSTORE_B64 secrets registered in Gitea before this lands.
2026-05-31 23:05:03 -04:00
bvandeusen 760b4a7c6c feat(cli,ci): admin reset-password + migrate subcommands; test-DB isolation + CI integration job
#321 — `minstrel admin reset-password [-user admin] [-password X]`:
loads config, updates BOTH password_hash (bcrypt) and subsonic_password
(plaintext, for Subsonic t+s) so neither auth path is left stale;
generates+prints a strong password when -password is omitted. Recovers
a locked-out operator without DB surgery. Subcommand dispatch added to
main.go (os.Args switch before flag-parse; server path untouched) plus
a `minstrel migrate` subcommand exposing db.Migrate standalone.

#339 — integration tests no longer truncate the dev DB:
- deploy/initdb creates minstrel_test on a fresh compose volume;
  `make test-integration` ensures it idempotently and points
  MINSTREL_TEST_DATABASE_URL at minstrel_test.
- docker-compose.yml + README updated.

CI integration job (test-go.yml): the prior workflow only ran
`go test -short -race` with no DB, so the entire integration suite
silently t.Skip'd — "CI green" never covered API/db/scanner. New
`integration` job runs the full `go test -race` against an ephemeral
Postgres service, using the act_runner shared-daemon pattern: no
published ports, discover the service container by job-name filter via
the docker socket, reach it by bridge IP, hard exactly-one assertion +
dev-compose-name reject (a wrong target would truncate real data),
TCP-wait, `minstrel migrate`, then test. Fast `test` job kept as the
quick gate.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 23:36:36 -04:00
bvandeusen c4cccea775 refactor(server): remove bootstrap admin path
The bootstrap-admin-from-env-vars flow was a holdover from before
self-registration could create the first admin. Now that handleRegister
+ CreateUserFirstAdminRace promotes the first user to register on an
empty users table (verified shipped in v2026.05.08.2 / #376), the
bootstrap path is just a second source of truth that confuses operators
(and leaves an "admin" account in the DB that nobody asked for).

Removes:
- internal/auth/bootstrap.go + its test
- The auth.Bootstrap call from cmd/minstrel/main.go
- AuthConfig + AdminBootstrapConfig structs from config
- MINSTREL_AUTH_ADMIN_USERNAME / _PASSWORD env reads + their test
- The auth: block from config.example.yaml
- Bootstrap-related comments in docker-compose.yml + README.md

The README quickstart now points operators at /register on first start
instead of "watch the logs for a one-time password."

Existing instances keep their bootstrap-admin row in the DB; operators
who want it gone can register a new admin via /register, promote them
in /admin/users, then delete the old bootstrap user (last-admin guard
will require the new admin to be promoted first). No migration needed.

Recovery story for forgotten admin passwords now hinges on Fable #321
(admin password reset CLI) — currently the only path back in if no
other admin exists.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 22:14:33 -04:00
bvandeusen 5207fae653 fix(deploy): writable data_dir in container + fatal-on-mkdir
The Dockerfile created the minstrel user but never set a WORKDIR or
pre-created a writable data dir. With the default DataDir of "./data"
and CWD of "/", every MkdirAll attempt failed with "permission denied"
under the non-root user, and the boot code only logged a Warn before
continuing. Result: every artist-art enrichment failed at
"mkdir artist-art: mkdir data: permission denied"; the operator saw
"0 successes" with no signal as to why.

Three changes:
- Dockerfile: WORKDIR /app, pre-create /app/data with minstrel
  ownership, and ENV MINSTREL_STORAGE_DATA_DIR=/app/data so the
  binary doesn't fall back to the broken "./data" default even if
  the operator forgets to set it.
- docker-compose.yml: explicit MINSTREL_STORAGE_DATA_DIR + a named
  volume mounted at /app/data so cached art persists across
  container recreates.
- cmd/minstrel/main.go: MkdirAll failure is now fatal. Silent breakage
  here cascades into every cache (playlist covers, artist art,
  album-cover fallbacks); refusing to start surfaces the misconfig
  immediately. Also wires Enricher.DataDir from cfg in preparation
  for the album-cover sidecar fallback (next commit).
2026-05-06 23:28:54 -04:00
bvandeusen ca82862346 chore(config): rename SMARTMUSIC_ env prefix to MINSTREL_; default admin user
The legacy SMARTMUSIC_ prefix dates from when the project was specced
as "smart-music" before being renamed to Minstrel. Hard cutover to
MINSTREL_* across config.go, tests, config.example.yaml, README, and
docker-compose. Also renames SMARTMUSIC_CONFIG in cmd/minstrel/main.go
which was missed in the original audit.

Also seeds Auth.AdminBootstrap.Username = "admin" in Default() so
MINSTREL_DATABASE_URL is the only env var required for a fresh prod
deployment — the bootstrap auto-generates a password and prints it
to stderr. Drops the now-redundant MINSTREL_AUTH_ADMIN_USERNAME=admin
line from the README quickstart and docker-compose.

M1 follow-up from the #363 final review: guards
MINSTREL_BRANDING_APP_NAME and _DESCRIPTION against empty-string
overrides — empty would have shipped <title></title> to share-preview
crawlers.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 18:40:59 -04:00
bvandeusen 64582b21e3 fix(auth): set subsonic_password on admin bootstrap
Bootstrap was creating password_hash + api_token but leaving
subsonic_password nil, which meant Subsonic clients (Feishin, Symfonium)
got ErrTokenNotSupported on t+s auth — the server had no plaintext to
hash against. Mirror the bootstrap password into subsonic_password so
the admin can sign in to Subsonic clients with the same credential
printed on first boot. Plaintext at rest is the cost of Subsonic's
legacy auth; matches Navidrome's posture.

Also folds in the local dev compose tweaks: dedicated bridge network
with postgres unpublished from the host, and a bind-mount aimed at the
operator's real library path.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-19 18:30:54 -04:00
bvandeusen e6b84190e7 chore(compose): bake in dev mount + scan defaults
Dev stack can now `docker compose up --build` with no extra env: mounts
./music read-only, enables startup scan, and bootstraps admin with a
generated password printed to stderr on first boot.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-19 18:12:13 -04:00
bvandeusen c252608558 M1/#291: add minstrel service to compose stack 2026-04-19 01:12:31 +00:00
bvandeusen b40e379b84 feat(skel): docker-compose for local Postgres (integration-test stack) 2026-04-18 21:21:01 +00:00