diff --git a/CLAUDE.md b/CLAUDE.md index c286b30..de76158 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -254,21 +254,27 @@ Comments explain **why**, not what. If a line looks odd, the comment says what w it. No emoji, no exclamation marks, no "obviously". Prose in the UI and docs is plain English and addressed to the person using it. -Every change gets one line under `## [Unreleased]` in [CHANGELOG.md](CHANGELOG.md), in its -[Keep a Changelog](https://keepachangelog.com/en/1.1.0/) group: Added, Changed, Deprecated, -Removed, Fixed or Security. Say it the way someone using ipx would notice it. When there is more to +Every change gets one line under `## [Unreleased]` in the changelog of the service it changes, in +its [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) group: Added, Changed, Deprecated, +Removed, Fixed or Security. One changelog a service: [crates/ipx/CHANGELOG.md](crates/ipx/CHANGELOG.md) +(the daemon and its API; until 0.12.0 everything), [web/CHANGELOG.md](web/CHANGELOG.md) (the page +and ipx-web) and [crates/directory/CHANGELOG.md](crates/directory/CHANGELOG.md) (ipx-directory). A +change to more than one gets a line in each, each saying what that service does differently. The +monitoring (the Grafana dashboard, the prod-check skill) and the repository's own tooling are not +a service anyone uses and get no line. Say it the way someone using ipx would notice it. When there is more to say, such as what was wrong before or what it cost to find out, it goes in the commit message's body, where `git log` and `git blame` find it beside the change. (There was a long-form `docs/history.md` until 0.7.0; it grew too large to be useful and was removed. It is in git.) -Cutting a release: first read `[Unreleased]` against the last release, not line by line, and rewrite +Cutting a release, of the three together while they share one version: in each changelog, first read `[Unreleased]` against the last release, not line by line, and rewrite it as what changed between the two. Lines go in as the work happens, so they record the way there: a feature added and then reworked in the same release is one line saying what it is now, under Added; something added and taken out again before the release, or a fix for a bug no release ever had, is not there at all; and "instead of" and "no longer" compare with the last release, not with last week. Issue numbers stay, all of them, on the line that survives. Then rename `[Unreleased]` to `## [X.Y.Z] - YYYY-MM-DD` and open a new empty `[Unreleased]` above it, set `version` in the root `Cargo.toml` (`[workspace.package]`) to `X.Y.Z` (dropping `-dev`), tag the commit -`vX.Y.Z`, and update the compare links at the bottom of the changelog. Then, in the next commit, +`vX.Y.Z`, and update the compare links at the bottom of each changelog. A service with nothing +under `[Unreleased]` gets no entry for that release. Then, in the next commit, set `version` to the next patch with `-dev` (after 0.9.0, `0.9.1-dev`), so a build between releases says so in the logo's tooltip instead of claiming to be the last release. The release that follows can still be a minor or major one; `-dev` only says the work comes after `X.Y.Z`. diff --git a/README.md b/README.md index d66b064..79decc5 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ The UI is plain HTTP, so put TLS in front of it if it is reachable from outside | [docs/users.md](docs/users.md) | Accounts, and what several people share | | [docs/sso.md](docs/sso.md) | Signing in through Cloudflare Zero Trust or Authentik | | [docs/architecture.md](docs/architecture.md) | How it works: modules, schema, control socket, HTTP API | -| [CHANGELOG.md](CHANGELOG.md) | What changed, by release | +| [crates/ipx/CHANGELOG.md](crates/ipx/CHANGELOG.md), [web/CHANGELOG.md](web/CHANGELOG.md), [crates/directory/CHANGELOG.md](crates/directory/CHANGELOG.md) | What changed, by release, for ipx, the page and the directory | | [CLAUDE.md](CLAUDE.md) | Notes for working on the code, including how production is deployed | ## Tests diff --git a/crates/directory/CHANGELOG.md b/crates/directory/CHANGELOG.md new file mode 100644 index 0000000..e141bb3 --- /dev/null +++ b/crates/directory/CHANGELOG.md @@ -0,0 +1,14 @@ +# Changelog: ipx-directory + +The directory of public podcasts that ipx servers share (docs/directory.md). ipx's changelog is +[crates/ipx/CHANGELOG.md](../ipx/CHANGELOG.md), the page's [web/CHANGELOG.md](../../web/CHANGELOG.md). + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +### Added + +- `ipx-directory`, a directory of public podcasts that ipx servers share: each sends the public feeds its people subscribe to, and any server with a token browses them, each feed listed once it has been read. Tokens are in its config file, each read-only, read-write or admin, and revoked one at a time (#204, #205). +- Traces: a span a request, joining the trace of the ipx server that called, and a trace a refresher round with a span a feed (#213). diff --git a/CHANGELOG.md b/crates/ipx/CHANGELOG.md similarity index 96% rename from CHANGELOG.md rename to crates/ipx/CHANGELOG.md index 7c74b5e..288169c 100644 --- a/CHANGELOG.md +++ b/crates/ipx/CHANGELOG.md @@ -1,6 +1,9 @@ -# Changelog +# Changelog: ipx -All notable changes to this project will be documented in this file. +The daemon: the API, scans, downloads, DeadAir and the database. The page has its own changelog, +[web/CHANGELOG.md](../../web/CHANGELOG.md), and the directory service its own, +[crates/directory/CHANGELOG.md](../directory/CHANGELOG.md). Until 0.12.0 this was the changelog of +all of ipx, the page included; they were split with the services (#207). The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). @@ -9,30 +12,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- ipx-directory sends traces, and ipx passes its trace on when it calls the directory, so a Directory page is one trace from the browser through ipx-web and ipx to the directory; each refresher round is a trace too (#213). -- ipx-web sends a trace span for each request when `WEB_TRACING=on`, continuing the page's trace into ipx, so one trace runs from the browser through Caddy to ipx (#213). -- The Grafana dashboard is laid out by container: an overview of all three, Tower's load, CPU, memory and disks, then ipx-web (from its new request log), ipx's API, worker and process, and the directory, each with its own warnings (#210). -- `ipx-directory`, a directory of public podcasts that ipx servers share: each sends the public feeds its people subscribe to, and any server with a token browses them. Tokens are in its config file, each read-only, read-write or admin, and revoked one at a time (#204). +- ipx passes its trace on when it calls the directory, so a Directory page is one trace from the browser to the directory (#213). ### Changed -- The Directory shows a directory service that iPX servers share, set up in Admin, Directory with its address and this server's token, instead of only this server's feeds. Sharing this server's public feeds with it is a switch there, and subscriber counts are every sharing server's (#205). -- A feed's settings have a Private switch: a private feed is never shared with the directory. A feed with a login, or whose address carries a key, is private already (#205). -- The page is served by its own container, ipx-web (Caddy), which passes the API to ipx on the same address, so a change to the page deploys without rebuilding ipx, and ipx is built without node (#203). -- Add a feed no longer asks for a folder; a feed's folder is its title (#201). +- The Directory comes from a directory service that iPX servers share, set up in Admin, Directory with its address and this server's token, instead of only this server's feeds. Sharing this server's public feeds with it is a setting, never a private one, and subscriber counts are every sharing server's (#205). +- A feed can be marked private, which keeps it out of the directory. A feed with a login, or whose address carries a key, is private already (#205). +- ipx serves no page: the page is ipx-web's, which passes the API on to ipx, and ipx is built without node (#203). - `docker-compose.yml` is a sample to start from, ipx alone on SQLite with its folders beside the file, instead of a copy of the author's server (#208). - The source is a Cargo workspace: the daemon in `crates/ipx`, feed fetching and parsing in `crates/feed`. `cargo build --release` still makes `target/release/ipx` (#202). ### Fixed -- On a phone, the Subscribe button on a Directory feed's page is full size again, not squashed to a sliver (#212). - ipx sends the directory its feeds when they change, and every half hour, instead of after every scan, which was every half minute or so (#211). ## [0.12.0] - 2026-10-11 ### Added -- With `[web] metrics_bind` set, ipx serves Prometheus metrics on a port and thread of their own: the database pool, the worker's job and queue, jobs done and their time, scans, downloads and requests in progress, download speed, live-update listeners and missed updates, DeadAir's backlog, the artwork cache's fill, hit rate and evictions, memory, open files and the library's counts. The iPX dashboard graphs them in a Daemon row (#194, #195, #198, #199). +- With `[web] metrics_bind` set, ipx serves Prometheus metrics on a port and thread of their own: the database pool, the worker's job and queue, jobs done and their time, scans, downloads and requests in progress, download speed, live-update listeners and missed updates, DeadAir's backlog, the artwork cache's fill, hit rate and evictions, memory, open files and the library's counts. (#194, #195, #198, #199). - The page reports its errors, the player's, how long play takes to start and how long it stalls to the server's log, and the requests one tap sets off share a trace, the playlist, audio and saved place of what it played included (#190, #192). - Saving an episode from a show with DeadAir on saves it without its dead air, at your breathing room (#186). - Choose the pause DeadAir leaves where it cuts a silence, from 0.2 to 0.5 seconds, for each show in its settings, as its breathing room, on a slider from brisk to relaxed. It is 0.3 seconds unless you change it, up from 0.2, which made speech sound rushed (#182, #183). @@ -172,7 +170,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `IPX_LOG_FORMAT=json` logs one JSON object a line, for Loki and the like: a request's method, route, status and `duration_ms`, a scan's or download's details, a failure's kind in `error.type` (and its HTTP status in `http.response.status_code`), and each line's `trace_id` and `span_id`. -- A Grafana dashboard for iPX, from its log in Loki and its traces in Tempo (`grafana/dashboard.py`). - With `OTEL_EXPORTER_OTLP_ENDPOINT` set, the daemon sends traces of its scans, downloads and web requests to a collector such as Tempo; a scan's shows the time each feed spends fetching, on its artwork and in the database. diff --git a/web/CHANGELOG.md b/web/CHANGELOG.md new file mode 100644 index 0000000..7aec20a --- /dev/null +++ b/web/CHANGELOG.md @@ -0,0 +1,27 @@ +# Changelog: ipx-web + +The page, and the container that serves it (Caddy). ipx's changelog is +[crates/ipx/CHANGELOG.md](../crates/ipx/CHANGELOG.md), which was the page's too until 0.12.0, and the +directory's [crates/directory/CHANGELOG.md](../crates/directory/CHANGELOG.md). + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +### Added + +- The page is served by its own container, ipx-web (Caddy), which passes the API to ipx on the same address, so a change to the page deploys without rebuilding ipx (#203). +- Admin, Directory sets the directory's address and this server's token, and whether to share, and says how the last share went (#205). +- A feed's settings have a Private switch, which keeps it out of the directory; on and locked for a feed whose address or login shows it is private (#205). +- ipx-web logs one line a request, without the request's headers or a sign-in token in the address (#210). +- ipx-web sends a trace span for each request when `WEB_TRACING=on`, continuing the page's trace into ipx (#213). + +### Changed + +- The Directory says when no directory is set up, and its counts are of everyone on every sharing server (#205). +- Add a feed no longer asks for a folder; a feed's folder is its title (#201). + +### Fixed + +- On a phone, the Subscribe button on a Directory feed's page is full size again, not squashed to a sliver (#212).