Commit graph

577 commits

Author SHA1 Message Date
Niels Göttsch
1ea007d330 ci: point deploy pipeline at moby/brewlog after repo move
Some checks failed
Build & Publish / Check (push) Successful in 2m24s
Build & Publish / Build & Publish (push) Failing after 3s
The repo moved from the uberbau owner to moby on the zo forge. Update
the image registry path and Kaniko git context accordingly.
2026-07-17 09:52:06 +02:00
Niels Göttsch
ebb05ed9c1 Merge branch 'feat/additional-invite-links' into dev
Some checks failed
Build & Publish / Check (push) Successful in 2m19s
Build & Publish / Build & Publish (push) Failing after 3s
2026-07-17 09:25:21 +02:00
Niels Göttsch
c108a39f2c fix(cli): use Duration::from_mins for token wait timeout
Satisfies clippy::duration_suboptimal_units by expressing the 2-minute
browser-auth timeout with from_mins(2) instead of from_secs(120).
2026-07-17 09:20:01 +02:00
Niels Göttsch
2312315f34 docs(readme): document prek install via uv in Development Setup
prek is a standalone uv-installed binary, not provided by mise install.
When absent from PATH, `prek run -av` fails with a misleading
"failed to run cargo fmt -- --check" message. Add the `uv tool install
prek` step and a note clarifying the failure mode.
2026-07-17 09:06:25 +02:00
Niels Göttsch
2e55c72522 ci: grant the job token packages:write for the registry push
Some checks failed
Build & Publish / Check (push) Successful in 7m40s
Build & Publish / Build & Publish (push) Failing after 4s
Kaniko's up-front push-permission check 401'd (reqPackageAccess): the Forgejo
auto GITHUB_TOKEN has no package-write scope by default. Declare
`permissions: {contents: read, packages: write}` so the token can push to the
forge container registry (git clone still needs contents:read).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 18:09:32 +02:00
Niels Göttsch
423ddc7870 ci: build image daemonless with Kaniko (no Docker)
Some checks failed
Build & Publish / Check (push) Successful in 2m15s
Build & Publish / Build & Publish (push) Failing after 9s
Replace the docker buildx / build-push-action build job with Kaniko running as
the job container: it builds the Dockerfile from the git context and pushes to
the forge registry, with no Docker daemon, no buildx, and no privileged DinD.

Kaniko cannot handle BuildKit `RUN --mount=type=cache`, so drop the two cache
mounts on the cargo build layer (plain `cargo build` now). Document the pipeline
and this gotcha (plus the node20-only runner and full-github-URL action rules) in
the README so it isn't reintroduced.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 17:17:09 +02:00
Niels Göttsch
168b674efe ci: source build-job actions from github.com, not the forge mirror
Some checks failed
Build & Publish / Check (push) Successful in 2m12s
Build & Publish / Build & Publish (push) Failing after 13m37s
The build job aborted during action preparation while cloning the docker/*
actions from code.forgejo.org (the checkout clone already warned "some refs
were not updated"). The check job proved that full github.com `uses:` URLs
clone reliably on this runner (mise-action@v2 worked), so pull checkout and the
docker actions from github.com directly. All are node20, which the runner
supports.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 16:38:16 +02:00
Niels Göttsch
e6555bd873 ci: install only Rust in the check job, drop sudo
Some checks failed
Build & Publish / Check (push) Successful in 7m36s
Build & Publish / Build & Publish (push) Failing after 13m36s
The check job failed inside mise: mise.toml pulls the full dev toolchain
(tailwind, cargo-watch, flyctl, shellcheck, mvdan/sh, ...) and resolves most of
it via api.github.com, which 401s on the runner (no github.com token) ->
"Failed to install tools" -> exit 1.

CI only needs Rust for fmt/clippy/test, so restrict mise to `install_args: rust`
(rust resolves through rustup, no GitHub API). Also drop `sudo` (the runner
image runs as root and has none) and the redundant `rustup component add`
(mise installs rustfmt/clippy from mise.toml). Keep mold — the .cargo linker
flag requires it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 16:02:53 +02:00
Niels Göttsch
d904689b38 ci: pin actions to the node20 generation for the forge runner
Some checks failed
Build & Publish / Check (push) Failing after 3m28s
Build & Publish / Build & Publish (push) Has been skipped
The forge's forgejo-runner (v6.3.1) only supports node runtimes up to node20,
but resolves bare `uses:` from code.forgejo.org where checkout@v6 (and the
other @v5/v6/v7 actions) declare `runs.using: node24` -> "must be one of
[... node20 ...], got node24" -> job failed before any step ran.

- checkout@v6->v4, cache@v5->v4, docker/{setup-buildx@v4->v3, login@v4->v3,
  build-push@v7->v6}: all node20.
- jdx/mise-action isn't mirrored on code.forgejo.org; reference it by full
  github URL, pinned to @v2 (node20).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 15:55:22 +02:00
Niels Göttsch
97b1d580e3 ci: repair build pipeline for the zo forge fork
Some checks failed
Build & Publish / Check (push) Failing after 16s
Build & Publish / Build & Publish (push) Has been skipped
The workflows were still the upstream GitHub ones and never ran here:
Deploy triggered on `main` (this fork's branch is `dev`), pushed to
`ghcr.io/jnsgruk/brewlog` (unreachable from this forge), and deployed to
jnsgruk's Fly.io.

- Deploy → build on push to `dev`, publish to this forge's own registry
  (git.ziemlichoptimal.de/uberbau/brewlog:{sha,dev}) via the auto GITHUB_TOKEN.
- Drop the Fly.io deploy step and the dead version-extract step; the moby
  homelab deploys the image via Flux GitOps, not from this pipeline.
- Retarget PR CI (push.yml) from `main` to `dev`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 15:50:58 +02:00
Niels Göttsch
8c5697ccc2 Merge feat/additional-invite-links into dev
Add additional invite-link generation (admin page + CLI + API).
2026-07-16 12:38:43 +02:00
Niels Göttsch
9cf8ce5d79 feat(auth): generate additional invite links for onboarding users
Add an authenticated POST /api/v1/invites endpoint that mints a
single-use, 7-day registration link after the first-user bootstrap.
Expose it via a new "Invite" section on the admin page and a
`brewlog invite create` CLI command.

The registration_tokens table, repository, and NewRegistrationToken
already supported additional tokens; this adds the authenticated
surfaces (session cookie or bearer token) to trigger creation.
2026-07-16 12:38:36 +02:00
Jon Seager
22c0a30d38
fix(ai): ground ambiguous coffee lookups with web search 2026-07-15 13:38:48 +01:00
Jon Seager
7563250809 fix: support sqlx 0.9 2026-06-08 10:56:18 +00:00
dependabot[bot]
deefd10a71 build(deps): bump sqlx from 0.8.6 to 0.9.0
Bumps [sqlx](https://github.com/launchbadge/sqlx) from 0.8.6 to 0.9.0.
- [Changelog](https://github.com/transact-rs/sqlx/blob/main/CHANGELOG.md)
- [Commits](https://github.com/launchbadge/sqlx/compare/v0.8.6...v0.9.0)

---
updated-dependencies:
- dependency-name: sqlx
  dependency-version: 0.9.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-08 10:56:03 +00:00
dependabot[bot]
a259b3d06a build(deps): bump thirtyfour from 0.36.1 to 0.37.1
Bumps [thirtyfour](https://github.com/stevepryde/thirtyfour) from 0.36.1 to 0.37.1.
- [Release notes](https://github.com/stevepryde/thirtyfour/releases)
- [Commits](https://github.com/stevepryde/thirtyfour/compare/v0.36.1...v0.37.1)

---
updated-dependencies:
- dependency-name: thirtyfour
  dependency-version: 0.37.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-08 10:40:00 +00:00
dependabot[bot]
d295173458 build(deps): bump askama from 0.15.4 to 0.16.0
Bumps [askama](https://github.com/askama-rs/askama) from 0.15.4 to 0.16.0.
- [Release notes](https://github.com/askama-rs/askama/releases)
- [Commits](https://github.com/askama-rs/askama/compare/v0.15.4...v0.16.0)

---
updated-dependencies:
- dependency-name: askama
  dependency-version: 0.16.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-08 10:38:39 +00:00
dependabot[bot]
ba9eb98815 build(deps): bump uuid from 1.23.1 to 1.23.2 in the cargo-deps group
Bumps the cargo-deps group with 1 update: [uuid](https://github.com/uuid-rs/uuid).

Updates `uuid` from 1.23.1 to 1.23.2
- [Release notes](https://github.com/uuid-rs/uuid/releases)
- [Commits](https://github.com/uuid-rs/uuid/compare/v1.23.1...v1.23.2)

---
updated-dependencies:
- dependency-name: uuid
  dependency-version: 1.23.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-08 10:35:18 +00:00
Jon Seager
f5fcf69e33 fix: clamp bag remaining to zero instead of rejecting brew with excess coffee
Allow creating a brew when coffee_weight exceeds the bag's remaining
amount — remaining is clamped to 0 rather than returning a 409 error.
Brews against open bags with 0g remaining also succeed, keeping
remaining at 0. Only closed bags are rejected.
2026-05-22 15:37:08 +00:00
Jon Seager
bd7d4f3c5f build: run brewlog as non-root user 1000:1000
Add brewlog user/group (UID/GID 1000) to chiseled rootfs via
base-passwd_data slice and useradd. Set USER 1000:1000 in the
runtime stage. Requires a one-time remediation deploy (with
gosu + chown entrypoint) to fix existing volume permissions
before this can be used.
2026-05-22 15:00:04 +00:00
Jon Seager
1d2b071fe9 build: add .dockerignore to reduce Docker build context 2026-05-22 14:59:56 +00:00
Jon Seager
8b49d3fbfe ci: bump Docker actions to latest major versions 2026-05-22 14:59:51 +00:00
Jon Seager
dc31f3a0cb refactor: extract shared find_chrome_for_testing_binary into common module 2026-05-22 14:59:47 +00:00
Jon Seager
08255a8515 chore: clean up stale Nix references 2026-05-22 14:59:39 +00:00
dependabot[bot]
c8d7333f7a
build(deps): bump the cargo-deps group across 1 directory with 8 updates (#23)
Bumps the cargo-deps group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [axum](https://github.com/tokio-rs/axum) | `0.8.8` | `0.8.9` |
| [image](https://github.com/image-rs/image) | `0.25.9` | `0.25.10` |
| [open](https://github.com/Byron/open-rs) | `5.3.3` | `5.3.5` |
| [serde_json](https://github.com/serde-rs/json) | `1.0.149` | `1.0.150` |
| [tracing-subscriber](https://github.com/tokio-rs/tracing) | `0.3.22` | `0.3.23` |
| [tower-http](https://github.com/tower-rs/tower-http) | `0.6.8` | `0.6.11` |
| [uuid](https://github.com/uuid-rs/uuid) | `1.21.0` | `1.23.1` |
| [once_cell](https://github.com/matklad/once_cell) | `1.21.3` | `1.21.4` |



Updates `axum` from 0.8.8 to 0.8.9
- [Release notes](https://github.com/tokio-rs/axum/releases)
- [Changelog](https://github.com/tokio-rs/axum/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tokio-rs/axum/compare/axum-v0.8.8...axum-v0.8.9)

Updates `image` from 0.25.9 to 0.25.10
- [Changelog](https://github.com/image-rs/image/blob/v0.25.10/CHANGES.md)
- [Commits](https://github.com/image-rs/image/compare/v0.25.9...v0.25.10)

Updates `open` from 5.3.3 to 5.3.5
- [Release notes](https://github.com/Byron/open-rs/releases)
- [Changelog](https://github.com/Byron/open-rs/blob/main/changelog.md)
- [Commits](https://github.com/Byron/open-rs/compare/v5.3.3...v5.3.5)

Updates `serde_json` from 1.0.149 to 1.0.150
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.149...v1.0.150)

Updates `tracing-subscriber` from 0.3.22 to 0.3.23
- [Release notes](https://github.com/tokio-rs/tracing/releases)
- [Commits](https://github.com/tokio-rs/tracing/compare/tracing-subscriber-0.3.22...tracing-subscriber-0.3.23)

Updates `tower-http` from 0.6.8 to 0.6.11
- [Release notes](https://github.com/tower-rs/tower-http/releases)
- [Commits](https://github.com/tower-rs/tower-http/compare/tower-http-0.6.8...tower-http-0.6.11)

Updates `uuid` from 1.21.0 to 1.23.1
- [Release notes](https://github.com/uuid-rs/uuid/releases)
- [Commits](https://github.com/uuid-rs/uuid/compare/v1.21.0...v1.23.1)

Updates `once_cell` from 1.21.3 to 1.21.4
- [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md)
- [Commits](https://github.com/matklad/once_cell/compare/v1.21.3...v1.21.4)

---
updated-dependencies:
- dependency-name: axum
  dependency-version: 0.8.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo-deps
- dependency-name: image
  dependency-version: 0.25.10
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo-deps
- dependency-name: open
  dependency-version: 5.3.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo-deps
- dependency-name: serde_json
  dependency-version: 1.0.150
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo-deps
- dependency-name: tracing-subscriber
  dependency-version: 0.3.23
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo-deps
- dependency-name: tower-http
  dependency-version: 0.6.11
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo-deps
- dependency-name: uuid
  dependency-version: 1.23.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: cargo-deps
- dependency-name: once_cell
  dependency-version: 1.21.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-22 14:27:23 +01:00
Jon Seager
6766aa16f2 ci: bump jdx/mise-action from v2 to v4 2026-05-22 13:18:31 +00:00
Jon Seager
cbc741b229 build(deps): bump cargo dependencies from dependabot PRs
Cherry-pick dependency updates from dependabot PRs #16, #18, #19, #21:
- clap 4.5 → 4.6
- tokio 1.38 → 1.52
- rand 0.9 → 0.10 (breaking: RngCore → Rng)
- sha2 0.10 → 0.11
- tempfile 3.8 → 3.27
- once_cell 1.19 → 1.21
- docker/login-action v3 → v4 (already on branch)

Fix rand 0.10 breaking change: RngCore trait renamed to Rng.
2026-05-22 13:07:22 +00:00
Jon Seager
616876e73f fix(ci): Install mold linker and rustfmt in deploy workflow
The Deploy workflow on main failed because .cargo/config.toml requires
the mold linker, but deploy.yml only installed lld. The earlier fix
commit only updated push.yml, missing deploy.yml.
2026-05-22 13:05:51 +00:00
Jon Seager
46b0cb67ef fix(ci): Install mold linker and rustfmt component for CI
Add mold to system deps (needed by .cargo/config.toml linker setting)
and explicitly install rustfmt/clippy components since mise-action
doesn't always install Rust components.
2026-05-22 12:51:34 +00:00
Jon Seager
b55e172d72 chore: Remove djlint from project
djlint corrupts Askama/Jinja templates and cannot be used safely.
Remove .djlintrc, install-py-deps task, and all djlint references
from prek.toml. Restore full README.md that was lost during rebase.
2026-05-22 11:06:18 +00:00
Jon Seager
74e3b600fc chore: Switch e2e tests to Chrome for Testing via mise
Replace snap-installed Chromium/chromedriver with Chrome for Testing
installed via npx @puppeteer/browsers. Binaries live in
$MISE_DATA_DIR/chrome-for-testing/ with version-agnostic path lookup.

Add install-e2e mise task and required apt packages to README and CI.
2026-05-22 12:03:03 +01:00
Jon Seager
b1e0a41797 chore: Switch to mold linker and fix Dockerfile build
Use mold linker in .cargo/config.toml instead of lld. Add binutils
and mkdir -p to Dockerfile builder stage. Update fly.toml model.
2026-05-22 12:03:03 +01:00
Jon Seager
197f0f541b chore: Simplify formatting toolchain
Remove treefmt and djlint from pre-commit hooks. djlint corrupted
Askama template syntax on first run. Use individual formatters
(cargo fmt, shfmt, oxfmt) directly instead. Update prek hooks
to use fmt-rs and fmt-sh separately.
2026-05-22 12:03:03 +01:00
Jon Seager
527358b695 chore: migrate from Nix to mise for dev environment management
Replace Nix flake with mise for toolchain management, treefmt for
formatting, prek for pre-commit hooks, and a Dockerfile for container
builds. Update CI workflows to use jdx/mise-action instead of Nix.

Add system dependency instructions to README.md and CLAUDE.md.
2026-05-22 12:03:03 +01:00
Jon Seager
edffb1679d
chore: update dependencies (#15)
* build(deps): bump actions/cache from 4 to 5

Bump the actions-deps group.

* build(deps): bump cargo-deps group (anyhow, chrono, clap, uuid, tempfile)

- anyhow 1.0.101 → 1.0.102
- chrono 0.4.43 → 0.4.44
- clap 4.5.57 → 4.5.60
- uuid 1.20.0 → 1.21.0
- tempfile 3.24.0 → 3.25.0

* build(deps): bump sqlx from 0.7.4 to 0.8.6

* build(deps): bump rand from 0.8.5 to 0.9.2

Migrate API changes:
- Replace OsRng.fill_bytes() with rand::rng().fill_bytes()
- Replace rand::thread_rng() with rand::rng()

* build(deps): bump thiserror from 1.0.69 to 2.0.18
2026-03-05 11:03:55 +00:00
Jon Seager
937ee4c5f2
feat: store bag finished_at as full datetime for correct timeline ordering
The finished_at field previously stored only a date, causing bag "finished"
timeline events to sort before same-day brews. Now stores a full datetime
and uses the actual close time for timeline ordering.
2026-02-24 21:38:39 +00:00
Jon Seager
6a2bd5e563
fix: allow multiple origins for mixed roasts 2026-02-24 11:03:20 +00:00
Jon Seager
ee145fffe6
feat: add share button to all detail pages
Copy current URL to clipboard with toast feedback on brew, roast,
roaster, bag, cup, cafe, and gear detail pages.
2026-02-22 10:17:14 +00:00
Jon Seager
7b9cf8147e
fix: stabilize flaky timeline CLI test under parallel execution
Fetch timeline with page_size=all so concurrent test data from other
CLI tests doesn't push events off page 1, causing assertion failures.
2026-02-22 10:03:56 +00:00
Jon Seager
dfb7e86f6d
fix: use Axum DefaultBodyLimit so per-route overrides work
Replace tower-http RequestBodyLimitLayer with Axum's DefaultBodyLimit
for the global 5 MB request body cap. RequestBodyLimitLayer enforced a
hard limit that prevented per-route DefaultBodyLimit overrides (backup
restore at 50 MB, scan/image at 10 MB) from taking effect, causing
HTTP 413 on backup restore.
2026-02-22 10:03:43 +00:00
Jon Seager
488e7f9d74
build: add .envrc for direnv integration 2026-02-15 13:51:25 +00:00
Jon Seager
76da3d9bff
fix: require discoverable credentials for passkey registration
The webauthn-rs `start_passkey_registration` sets residentKey to
"discouraged", which iOS Safari respects strictly — creating
non-discoverable credentials that never appear in autofill. Desktop
password managers ignore this flag. Patch the creation challenge to
require resident keys so discoverable passkeys work on all platforms.
2026-02-15 12:29:07 +00:00
Jon Seager
bfe4f7d67d
ci: speed up nix container build with crane dependency caching
Replace rustPlatform.buildRustPackage with crane to split the Rust
compilation into a deps-only derivation (keyed on Cargo.lock) and a
source derivation. The deps derivation is cached in the Nix store
between CI runs, avoiding full recompilation on every deploy.
2026-02-15 12:29:06 +00:00
Jon Seager
1075986554
fix: use form element for registration page
The formatter converted the register container from a div with onclick
to a semantic form with onsubmit, improving accessibility and enabling
native form submission behavior.
2026-02-15 11:39:42 +00:00
Jon Seager
5a0321b226
feat: add WebAuthn Conditional UI for passkey autofill
Enables password managers (1Password, iCloud Keychain) to offer passkey
suggestions via autofill on the login page, matching behavior of other
passkey-enabled websites.
2026-02-15 11:38:53 +00:00
Jon Seager
02235426c4
ci: speed up pipeline with cargo caching and merged jobs
Merge separate lint and test jobs into a single check job so clippy's
compilation artifacts are reused by tests. Add actions/cache for the
Cargo target directory and registry to enable incremental builds across
runs. Drop unnecessary fetch-depth: 0 from CI jobs.
2026-02-15 11:29:45 +00:00
Jon Seager
0e3847ade9
feat: sync timeline events with entity edits
Add background timeline rebuild task (mirroring stats cache pattern)
that refreshes denormalized timeline event snapshots when entities are
updated. Includes cascade logic so editing a roaster refreshes timeline
events for its roasts, bags, brews, and cups.

- Add update_by_entity/delete_by_entity/delete_all to TimelineEventRepository
- Add TimelineInvalidator with debounced background rebuild task
- Add invalidate() calls to all 7 entity update handlers
- Add delete_by_entity cleanup to define_delete_handler! macro
- Add gear_id filter to BrewFilter for cascade traversal
- Add `brewlog timeline rebuild` CLI command for full rebuild
- Add 5 integration tests for timeline sync behavior
2026-02-15 11:11:07 +00:00
Jon Seager
ae016c6437
build: add LD_LIBRARY_PATH to devshell for libssl 2026-02-15 10:36:43 +00:00
Jon Seager
12dcc37cbe
fix: persist session cookie with max-age for Safari PWA support
Session cookie lacked a Max-Age attribute, making it ephemeral. Safari's
standalone PWA mode aggressively clears session cookies on app suspend,
causing frequent logouts. Set Max-Age to 30 days to match the server-side
session lifetime.
2026-02-15 10:36:05 +00:00
Jon Seager
5820c162f6
fix: address static assets code review findings
- Remove dead CSS color property in .tab-mobile
- Fix design token violations (text-red-500, fallback colors)
- Add disconnectedCallback to chip-scroll, image-upload, searchable-select
- Replace innerHTML with safe DOM APIs in world-map screen reader table
- Add credentials: same-origin to WebAuthn fetch calls
- Move page-specific scripts (donut-chart, location) out of base.html
- Add client-side image resizing (1920px max dimension)
- Resize app-icon-512.png from 2048x2048 to 512x512
- Document Datastar unsafe-eval CSP requirement
- Add static asset serving tests (16 routes)
- Add e2e tests for world-map, donut-chart, chip-scroll presence
- Add cache-busting query params to all static asset URLs
2026-02-13 17:13:02 +00:00