Update project conventions and infrastructure docs

This commit is contained in:
Claudio Ortolina
2026-04-22 21:01:52 +01:00
parent f7f38d580e
commit 71936f6173
2 changed files with 16 additions and 10 deletions
+14 -8
View File
@@ -25,9 +25,9 @@ push via GitHub Actions.
The Docker image is a multi-stage build: The Docker image is a multi-stage build:
1. **Builder**`hexpm/elixir:1.20.0-rc.4-erlang-28.4.2-debian-trixie-20260406-slim` with 1. **Builder**`hexpm/elixir:1.20.0-rc.4-erlang-28.4.3-debian-trixie-20260421-slim` with
Node.js 25, compiles deps, builds assets (`mix assets.deploy`), generates an OTP release. Node.js 25, compiles deps, builds assets (`mix assets.deploy`), generates an OTP release.
2. **Runner**`debian:trixie-20260406-slim` with minimal runtime deps (`libstdc++6`, 2. **Runner**`debian:trixie-20260421-slim` with minimal runtime deps (`libstdc++6`,
`openssl`, `libncurses6`, `ca-certificates`). Runs as unprivileged `nobody` user. `openssl`, `libncurses6`, `ca-certificates`). Runs as unprivileged `nobody` user.
Fluxon UI (licensed dependency) is fetched during build via Docker build secrets Fluxon UI (licensed dependency) is fetched during build via Docker build secrets
@@ -61,18 +61,24 @@ Configured inline in `compose.yaml`. Runs as a separate Docker Compose service
|---------|-------| |---------|-------|
| S3 endpoint | `https://nbg1.your-objectstorage.com` | | S3 endpoint | `https://nbg1.your-objectstorage.com` |
| Bucket | `ffmusiclibrary` | | Bucket | `ffmusiclibrary` |
| Sync interval | 24 hours | | Sync interval | 60 minutes |
| Snapshot interval | 24 hours | | Retention | 672 hours (28 days) |
| Retention | 168 hours (1 week) |
| Healthcheck | `litestream databases` every 30s (timeout 10s, 3 retries) | | Healthcheck | `litestream databases` every 30s (timeout 10s, 3 retries) |
Credentials via environment: `LITESTREAM_ACCESS_KEY_ID`, `LITESTREAM_SECRET_ACCESS_KEY`. Credentials via environment: `LITESTREAM_ACCESS_KEY_ID`, `LITESTREAM_SECRET_ACCESS_KEY`.
### Manual backup ### Manual backup
`mise run prod:backup` pulls the production database via `rsync` and saves it locally Two manual options are available:
as `data/music_library_prod_<timestamp>.db`. Old backups can be cleaned with
`mise run prod:prune-backups`. - `mise run prod:backup` — takes an atomic snapshot of the live database on the
production server using `sqlite3 .backup`, then rsyncs it locally as
`data/music_library_prod_<timestamp>.db`. Safe under concurrent writes.
- `mise run prod:litestream-backup` — restores the production database locally from
the S3 Litestream replica. Requires `LITESTREAM_ACCESS_KEY_ID` and
`LITESTREAM_SECRET_ACCESS_KEY`.
Old backups can be cleaned with `mise run prod:prune-backups`.
--- ---
+2 -2
View File
@@ -100,9 +100,9 @@ Rules extracted from commit history that are specific to this project and not al
- **Alias nested modules at the top** rather than referencing them inline (e.g. `alias LastFm.Fixtures.RecentTracks` then `RecentTracks.get()`, not `LastFm.Fixtures.RecentTracks.get()`). Enforced by Credo's `AliasUsage` check. - **Alias nested modules at the top** rather than referencing them inline (e.g. `alias LastFm.Fixtures.RecentTracks` then `RecentTracks.get()`, not `LastFm.Fixtures.RecentTracks.get()`). Enforced by Credo's `AliasUsage` check.
- **Markdown sanitization via MDEx (ammonia).** Use `Markdown.to_html/1` for user content. Annotate raw output with `# sobelow_skip ["XSS.Raw"]` and a comment explaining the sanitization. - **Markdown sanitization via MDEx (ammonia).** Use `Markdown.to_html/1` for user content. Annotate raw output with `# sobelow_skip ["XSS.Raw"]` and a comment explaining the sanitization.
- **Sobelow runs on CI and pre-commit** in skip mode for security analysis. - **Sobelow runs on CI and pre-commit** in skip mode for security analysis.
- **ExSlop checks run via Credo** for code quality: no narrator/boilerplate docs (use `@moduledoc false` instead), no obvious/step/narrator comments, no identity `case`/`with` patterns, no `Repo.all` then filter, no `Enum.map` with inline queries. Violations are caught by CI. - **ExSlop checks run via Credo** for code quality: no narrator/boilerplate docs (use `@moduledoc false` instead), no obvious/step/narrator comments, no identity `case`/`with` patterns, no `Repo.all` then filter, no `Enum.map` with inline queries, no unaliased nested module use (nested modules must be aliased at the top). Violations are caught by CI.
- **All modules require `@moduledoc`.** The Credo `ModuleDoc` check is enforced in strict mode. - **All modules require `@moduledoc`.** The Credo `ModuleDoc` check is enforced in strict mode.
- **The project does not use dialyzer**. If any skill suggests its usage, ignore it. - **Dialyzer is enabled via `dialyxir` (dev/test only) with the `:no_opaque` flag.** Specs are required and checked. Opaque type checking is disabled to tolerate third-party opaque types (e.g., `Ecto.Changeset`).
- **Validate Docker builder image before updating versions.** When changing `ELIXIR_VERSION`, `OTP_VERSION`, or `DEBIAN_VERSION` in the Dockerfile, run `mise run dev:validate-docker-image` to confirm the generated `hexpm/elixir` tag exists on Docker Hub and supports both `linux/amd64` and `linux/arm64`. - **Validate Docker builder image before updating versions.** When changing `ELIXIR_VERSION`, `OTP_VERSION`, or `DEBIAN_VERSION` in the Dockerfile, run `mise run dev:validate-docker-image` to confirm the generated `hexpm/elixir` tag exists on Docker Hub and supports both `linux/amd64` and `linux/arm64`.
## Reviews & Audits ## Reviews & Audits