From 762ee95d4aecc388911af66c2b5c5c834c96ebe7 Mon Sep 17 00:00:00 2001 From: valgulnecron <39313199+ValgulNecron@users.noreply.github.com> Date: Wed, 11 Nov 2026 01:12:27 +0100 Subject: [PATCH 1/3] docs: correct stale v0.4.0 status in FEATURES, roadmap and docs - FEATURES.md: localization (spec 019) shipped in v0.4.0, beta/on; edit game configuration beta/on; version-trend row beta/off; status date 2026-11-11. - docs/roadmap.md: In progress refreshed from each spec's tasks.md (013 and 022 done and archived, 019 shipped, 023 51/52); v0.4 in the Blocking v1 line; Postgres e2e/upgrade coverage now exists. - CHANGELOG [0.4.0]: the admin-level permission list includes cluster:manage (api/internal/handlers/privileged_grants.go:21). - docs/install.md: Postgres is covered by e2e-postgres and the postgres-availability upgrade bucket. - docs/networking.md: kubelet probes reach only probe ports by default. - docs/contributing.md, docs/dependencies.md, docs/security.md: stale counts, spec status and a garbled sentence. The website features page mirrors the FEATURES.md rows; the submodule pointer bump follows once the website PR is ready. Co-Authored-By: Claude Opus 5.5 Signed-off-by: valgulnecron <39313199+ValgulNecron@users.noreply.github.com> --- CHANGELOG.md | 2 +- FEATURES.md | 8 ++++---- docs/contributing.md | 4 ++-- docs/dependencies.md | 2 +- docs/install.md | 7 ++++--- docs/networking.md | 6 ++++-- docs/roadmap.md | 18 ++++++++++-------- docs/security.md | 2 +- 8 files changed, 27 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6cfdc17b9..25557e617 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,7 +41,7 @@ does not claim v1 or production support; see [`docs/roadmap.md`](docs/roadmap.md ### Upgrade Notes - **Breaking: admin-level grants need a full administrator:** holders of - `users:manage`, `roles:manage` or `config:manage` without `*` can no longer + `users:manage`, `roles:manage`, `config:manage` or `cluster:manage` without `*` can no longer grant `*` or another admin-level permission, edit or reset an administrator, or edit auth providers (`/admin/config/auth`, `/admin/auth` need `*`) (PR #862). diff --git a/FEATURES.md b/FEATURES.md index 85f90e730..5c994fc7e 100644 --- a/FEATURES.md +++ b/FEATURES.md @@ -6,7 +6,7 @@ Default column: **on** (enabled by the chart or the product), **off** (opt-in, s Notification rows take effect once a notification sink is configured. -Status date: 2026-11-10 (v0.4.0, pre-v1). +Status date: 2026-11-11 (v0.4.0, pre-v1). See [docs/roadmap.md](docs/roadmap.md) for what is planned and in progress. @@ -25,7 +25,7 @@ See [docs/roadmap.md](docs/roadmap.md) for what is planned and in progress. | Wipe world data with typed confirmation | beta | on | Suspends the server, erases the world volume and resumes, for owners or admins only. | [architecture](docs/architecture.md) | | Browse and filter the server list across namespaces | beta | on | The Servers page lists servers from every namespace the viewer may read and filters them with All, Running and Stopped tabs. | [unified-dashboard](docs/unified-dashboard.md) | | Keep game data on a PVC with clear storage errors | beta | on | Game data stays on its PVC when the game pod is deleted, and a missing storage class sets Ready to False with reason PVCProvisioningFailed; an install-time default storage class is opt-in. | [architecture](docs/architecture.md#start-a-server) | -| Edit game configuration from the Settings tab | in progress | n/a | Lets an operator change a server game configuration from its Settings tab, with validation. | [roadmap](docs/roadmap.md#in-progress) | +| Edit game configuration from the Settings tab | beta | on | Lets an operator change a server game configuration from its Settings tab, with validation. | [roadmap](docs/roadmap.md#in-progress) | ## Console and admin actions @@ -215,7 +215,7 @@ See [docs/roadmap.md](docs/roadmap.md) for what is planned and in progress. | Limit and proof-of-work gate report ingestion on the receiver | beta | off | INGEST_SOURCE_DAILY_LIMIT caps accepted reports per source per UTC day, with a default of 20, and INGEST_POW makes reporters solve a challenge whose difficulty rises with request rate. | [telemetry-provider](docs/telemetry-provider.md#configuration) | | Expose receiver summary, dashboard and metrics | beta | off | GET /v1/summary returns five fixed counts without credentials when PUBLIC_SUMMARY is true, the receiver dashboard on port 8081 starts only when DASHBOARD_TOKEN is at least 32 characters, and /metrics accepts only the Bearer token. | [telemetry-provider](docs/telemetry-provider.md#public-summary) | | Run a standalone telemetry provider | beta | n/a | A runbook covers deploying the receiver image, TLS, secrets, Cloudflare settings, metrics and backups for a provider serving other installs. | [telemetry-provider](docs/telemetry-provider.md) | -| Show a version-trend view in the receiver dashboard | in progress | n/a | A version-trend view in the telemetry dashboard is in progress under the spec 022 amendment T101 to T110. | [roadmap](docs/roadmap.md) | +| Show a version-trend view in the receiver dashboard | beta | off | A version-trend card in the telemetry receiver dashboard's extended section shows daily upgraded, downgraded and unordered version changes. | [roadmap](docs/roadmap.md) | ## Observability and admin @@ -230,7 +230,7 @@ See [docs/roadmap.md](docs/roadmap.md) for what is planned and in progress. | Capability | Maturity | Default | Description | Docs | |---|---|---|---|---| -| Localized dashboard and community language packs | in progress | n/a | Spec 019 adds app localization and community language packs; the work is on open PR #668 and is not yet on master. | [roadmap](docs/roadmap.md#in-progress) | +| Localized dashboard and community language packs | beta | on | Shipped in v0.4.0 (spec 019): per-account or browser language choice with an admin instance default, translated server messages, per-destination notification language and module translations. A language is listed once its pack is at least 80% translated; missing strings fall back to English. | [translating](docs/translating.md) | ## Developer and operator tooling diff --git a/docs/contributing.md b/docs/contributing.md index d21917845..1368cd70b 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -99,7 +99,7 @@ Reopen the container with one of the named profiles (or `full`) and run the targ **Any change to the web dashboard's visual surface starts in `design.pen` (Pencil), not in code.** Open `design.pen`, update the relevant screen, review with the maintainers, *then* translate to -React. This keeps the 18 designed screens the source of truth and +React. This keeps the 84 designed screens (`assets/design-export/MANIFEST.md`, re-measured 2026-09-12) the source of truth and prevents the dashboard from drifting into code-led redesigns. Backend/operator/API changes do not need a Pencil pass. @@ -146,7 +146,7 @@ Every job in every workflow must have: - An explicit `permissions` block granting only what that job needs (top-level default is `contents: read`; anything more is granted only to the specific job that needs it) - An explicit `timeout-minutes` (default budget is ≤30 minutes; anything above it requires an inline justification comment) -Documented exceptions with longer timeouts are the five e2e jobs (60 minutes each) and the image build in `publish-edge.yaml` (35 minutes). +Documented exceptions with longer timeouts are the e2e jobs that set 45 to 75 minutes (the multicluster, upgrade, web live and game bot jobs at 60 minutes each, the PostgreSQL job at 75, the capture overhead job at 45, and the matrix-driven `e2e-go` jobs) and the image build in `publish-edge.yaml` (35 minutes). ### Security and drift gates diff --git a/docs/dependencies.md b/docs/dependencies.md index d43326fc9..7e1280d23 100644 --- a/docs/dependencies.md +++ b/docs/dependencies.md @@ -114,7 +114,7 @@ is the shared telemetry report contract: the basic and extended report types, the fixed category enumerations and band functions, the strict decoder, the embedded official-module catalog, and Ed25519 report signing. -Imported by (spec 022, in progress): +Imported by (spec 022): - `telemetry-receiver/` — to decode and validate reports (`Decode`) and to verify signatures (`Verify`). - `api/` — to build, encode and sign the reporter's payload and the admin preview. diff --git a/docs/install.md b/docs/install.md index f0b5767d7..70d744bed 100644 --- a/docs/install.md +++ b/docs/install.md @@ -176,7 +176,7 @@ Top-level knobs (see `values.yaml` for the full list): GameServer enters Pending with a `PVCProvisioningFailed` condition (visible in the dashboard); no pod starts until resolved. Example: `--set operator.gameDataStorage.storageClassName=fast-nvme` -- `api.db.driver` — `sqlite` (default, production-tested) or `postgres` [experimental] (requires an api image built with `-tags postgres`; not yet covered by e2e or upgrade tests) +- `api.db.driver` — `sqlite` (default, production-tested) or `postgres` [experimental] (requires an api image built with `-tags postgres`; the published image is built without it). The CI `api (postgres)` job and the PostgreSQL E2E buckets, including `postgres-availability` (`TestUpgrade_PostgresAvailability`), exercise it. - `api.db.dsn` — connection string; SQLite default persists to a PVC - `api.storage.existingClaim` — pre-existing PVC for the API's SQLite database (default `""`). PostgreSQL standalone deployments create no local database PVC or mount. The chart annotates `gameplane-api-data` with `helm.sh/resource-policy: keep` so switching to an existing claim preserves the previous PVC. - `api.panelKey.storage.existingClaim` — pre-existing key-only PVC for generated standalone encryption keys; independent of database storage. `api.panelKey.storage.size` and `storageClassName` configure a new key PVC when no existing claim is selected. @@ -952,8 +952,9 @@ test and asserts that migrations ran against the populated SQLite volume without data loss. See `test/e2e/upgrade_e2e_test.go`. What this does **not** yet cover: upgrades -that skip several releases at once, and Postgres (still an experimental -driver — see [`roadmap.md`](roadmap.md)). Take a backup before upgrading +that skip several releases at once. A PostgreSQL combined-install upgrade has +its own `postgres-availability` bucket, but Postgres remains an experimental +driver (see [`roadmap.md`](roadmap.md)). Take a backup before upgrading production either way. ### SQLite database adoption (Kestrel → Gameplane) diff --git a/docs/networking.md b/docs/networking.md index fd3259012..65fda8d33 100644 --- a/docs/networking.md +++ b/docs/networking.md @@ -54,8 +54,10 @@ and validate kubelet source handling for your Cilium configuration as well. Before enabling strict mode, inventory the actual endpoints and configured game probes, observe their traffic in the CNI, then validate game readiness, agent heartbeats, wake requests and API/operator agent access in a staging -namespace. The default profile retains RFC1918/link-local API egress and -unrestricted probe ports for compatibility; it does not isolate those paths. +namespace. The default profile retains RFC1918/link-local API egress for +compatibility, and admits kubelet probes only to each server's probe ports +(`networkPolicies.probeIngress.enabled`, on by default). It does not isolate +those paths. Narrowing sentinel traffic alone cannot remove those separate grants. The dedicated CI `network-isolation` bucket installs pinned Cilium, exercises diff --git a/docs/roadmap.md b/docs/roadmap.md index 8e7aee91e..533fccec2 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -32,6 +32,7 @@ discovered along the way gets added. - Removed: the Hell Let Loose module is withdrawn from the official catalog ([changelog](../CHANGELOG.md)). - Upgrade-note behaviour changes: telemetry is on by default for new installs after a first-login notice; installs with a saved basic toggle start sending to the default receiver after upgrade; an empty `api.telemetry.endpoint` means the project default receiver; the receiver `/metrics` moved to `:8081` and needs the dashboard token; the bundled receiver stores data on a PVC by default; receiver `DASHBOARD_TOKEN` must be at least 32 characters ([changelog](../CHANGELOG.md)). - Breaking: selected-cluster module and template grants need a cluster-wide grant for remote catalogs ([changelog](../CHANGELOG.md)). +- Language selection and community language packs (spec 019): dashboard language per account with an admin instance default, shared language packs, and a per-destination notification language ([changelog](../CHANGELOG.md)). Follow-ups are listed under In progress. - Feature catalog: [FEATURES.md](../FEATURES.md) lists every capability with its maturity and default, mirrored on the website and kept in step by `make check-features-sync` (spec 024, PR #703). ### Shipped in v0.3.0 @@ -264,22 +265,22 @@ opt-out), and a monthly workflow refreshes the pins. Authoring rules live in ## In progress -Status as of 2026-10-14. Task counts come from each spec's `tasks.md`. +Status as of 2026-11-11. Task counts come from each spec's `tasks.md`. - **Spec 002, Nuclear Option module and load-balancer IP pool override** (`specs/002-nuclear-option-ip-pool/`): 136 of 143 tasks done. Blocked: the server does not bind UDP 7777, so no join client can be built until a real-client packet capture documents the handshake (maintainer decision, 2026-10-11). Unblocked by: that packet capture. The join test, its bucket and the coverage row wait on it. - **Spec 009, code scanning remediation and Dependabot** (`specs/009-remediate-security-dependabot/`): 80 of 82 tasks done. Blocked: TypeScript 7 is blocked because the `@typescript-eslint` peer range stops before TypeScript 7, and ESLint 10 is blocked because `eslint-plugin-react` does not accept `^10`. Unblocked by: a `@typescript-eslint` release that accepts TypeScript 7 (then T055/T056 and PR #272), and an `eslint-plugin-react` release that accepts `^10` (then PR #386, and #387 if open). -- **Spec 013, expand test coverage** (`specs/done_013-expand-test-coverage/`): 39 of 62 tasks done. No external blocker is named. Open work is the live web e2e specs, the optional-components e2e, the Postgres e2e, docs and checks, and the archive step. Some tasks wait for the first green CI run of their job, and the archive waits until every PR is merged. Open PRs for this spec are in progress. -- **Spec 019, app localization and community language packs** (`specs/019-localization-language-packs/`): 0 of 105 tasks checked; the four design decisions are settled. The implementation is on open PR #668 and is not yet on `master`. Unblocked by: merging PR #668, which needs human approval. The first step is the `i18n/` module and checker. +- **Spec 013, expand test coverage** (`specs/done_013-expand-test-coverage/`): done. All 62 tasks complete; archived. +- **Spec 019, app localization and community language packs** (`specs/019-localization-language-packs/`): shipped in v0.4.0 (PR #668 is on `master`). 102 of 105 tasks done. Open: T080, the French Reviewers group and reviewer rules; T103, the quickstart run against a `make dev-up` cluster; T105, the archive to `done_019` after every task is complete or withdrawn and the PR is merged. - **Spec 021, edit game configuration from server Settings** (`specs/done_021-settings-game-config/`): done. All 24 tasks complete; merged in PR #568 and PR #652, then archived. -- **Spec 022, default telemetry destination, extended telemetry and telemetry dashboard** (`specs/done_022-default-telemetry-dashboard/`): 109 of 119 tasks done. The shipped feature is unchanged until the version-trend amendment (2026-10-14, T101 to T110) lands. Blocked: T104 needs Pencil design work on the machine where Pencil runs; T109 needs the user's sign-off before editing existing tests `lifecycle_test.go:11` and `charts_test.go:83`; T110 waits for the PR to merge. Unblocked by: the design work, that sign-off, and the merge. -- **Spec 023, change-based test selection** (`specs/023-change-based-test-selection/`): 0 of 52 tasks done; no open decisions remain. No blocker is named. T001 creates the `ci: full-run` label. T052 needs 30 merged PRs to measure runner minutes. +- **Spec 022, default telemetry destination, extended telemetry and telemetry dashboard** (`specs/done_022-default-telemetry-dashboard/`): done. All 126 tasks complete, including the 2026-10-14 version-trend amendment (Phase 11 of its `tasks.md`); archived. +- **Spec 023, change-based test selection** (`specs/023-change-based-test-selection/`): 51 of 52 tasks done. The open task is T052, which measures median runner-minutes after 30 merged PRs. No blocker is named. - **Spec 025, standalone panel and API** (`specs/025-standalone-panel/`, see [standalone panel](standalone-panel.md)): implemented and merged in PR #630; all 51 tasks done, with known gaps listed in the spec. The folder was renumbered from `023-standalone-panel` and written after the fact. Next step: archive to `done_025`. --- ## Blocking v1 -Nothing hard-blocks v1 anymore. What stands between v0.3 and a v1 GA is the +Nothing hard-blocks v1 anymore. What stands between v0.4 and a v1 GA is the production-readiness hardening below — tracked items, not code gaps. --- @@ -306,8 +307,9 @@ every later migration is one portable file both drivers run `$n`, and runtime timestamps are generated in Go. The `api (postgres)` CI job builds the api with the tag and runs `api/internal/db`'s tests against a real PostgreSQL server. It stays **experimental** until the rest lands: running the -handler/auth/audit test suites and the kind e2e and upgrade suites against -Postgres, a published image built with `-tags postgres`, and multi-replica +handler/auth/audit test suites against Postgres (the `e2e-postgres` CI job already +runs the auth, roles and RBAC e2e buckets and the `postgres-availability` upgrade +bucket on it), a published image built with `-tags postgres`, and multi-replica safety (the user-management lock and the audit hash chain assume a single API process). diff --git a/docs/security.md b/docs/security.md index bf2a0a202..5be7ee0e2 100644 --- a/docs/security.md +++ b/docs/security.md @@ -868,7 +868,7 @@ When a receiver sets `INGEST_POW=true`, `/ingest` requires a solved challenge from `GET /v1/challenge` in the `Gameplane-Telemetry-PoW` header. Challenges are HMAC-signed with a key held only in the receiver's memory, expire after 15 minutes and work once. The difficulty is `INGEST_POW_MIN_BITS` (default zero) while at most -than `INGEST_POW_TARGET_PER_MIN` challenges a minute are issued, then rises +`INGEST_POW_TARGET_PER_MIN` challenges a minute are issued, then rises with the rate (up to `INGEST_POW_MAX_BITS`, at most 26) and falls one bit per five minutes. The check runs before the body is read, so a refused report costs the receiver one HMAC and one hash, and it answers `428` From c29cef1191a089bf54b776cff24c775f51ea51e5 Mon Sep 17 00:00:00 2001 From: valgulnecron <39313199+ValgulNecron@users.noreply.github.com> Date: Wed, 11 Nov 2026 21:39:22 +0100 Subject: [PATCH 2/3] chore: bump website submodule to 262105c Includes: - docs: point install and upgrade docs at the v0.4.0 release (#29) - docs: update the site for v0.4.0 (#30) The website features page now mirrors this PR's FEATURES.md rows, so check-features-sync passes. Co-Authored-By: Claude Opus 5.5 Signed-off-by: valgulnecron <39313199+ValgulNecron@users.noreply.github.com> --- website | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website b/website index 5457d75bd..262105c3d 160000 --- a/website +++ b/website @@ -1 +1 @@ -Subproject commit 5457d75bd1a2c006f5da18986c44560fff7e74cf +Subproject commit 262105c3d4ec2a97dd611e5534090d20b1367a0f From 9cefcd8a833fe0ce2354ae4f63a29dfe07bae859 Mon Sep 17 00:00:00 2001 From: valgulnecron <39313199+ValgulNecron@users.noreply.github.com> Date: Wed, 11 Nov 2026 21:48:37 +0100 Subject: [PATCH 3/3] docs: describe postgres-availability and PoW difficulty accurately - install.md, roadmap.md: the postgres-availability bucket tests a combined-install deployment-strategy change and outage recovery with the working-tree chart (test/e2e/api_availability_e2e_test.go), not an upgrade from a previous release. - security.md, telemetry-provider.md: the rate adds no difficulty at or below INGEST_POW_TARGET_PER_MIN, but the receiver keeps a peak that decays one bit per five minutes (telemetry-receiver/pow.go), so the difficulty can stay above INGEST_POW_MIN_BITS after a flood. Addresses CodeRabbit review comments on #927. Co-Authored-By: Claude Opus 5.5 Signed-off-by: valgulnecron <39313199+ValgulNecron@users.noreply.github.com> --- docs/install.md | 9 +++++---- docs/roadmap.md | 6 ++++-- docs/security.md | 11 +++++++---- docs/telemetry-provider.md | 10 ++++++---- 4 files changed, 22 insertions(+), 14 deletions(-) diff --git a/docs/install.md b/docs/install.md index 70d744bed..803bf5085 100644 --- a/docs/install.md +++ b/docs/install.md @@ -952,10 +952,11 @@ test and asserts that migrations ran against the populated SQLite volume without data loss. See `test/e2e/upgrade_e2e_test.go`. What this does **not** yet cover: upgrades -that skip several releases at once. A PostgreSQL combined-install upgrade has -its own `postgres-availability` bucket, but Postgres remains an experimental -driver (see [`roadmap.md`](roadmap.md)). Take a backup before upgrading -production either way. +that skip several releases at once. The `postgres-availability` bucket tests a +PostgreSQL combined-install deployment-strategy change and outage recovery +using the working-tree chart. It does not test an upgrade from a previous +release. Postgres remains an experimental driver (see [`roadmap.md`](roadmap.md)). +Take a backup before upgrading production either way. ### SQLite database adoption (Kestrel → Gameplane) diff --git a/docs/roadmap.md b/docs/roadmap.md index 533fccec2..d43e7ac17 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -308,8 +308,10 @@ every later migration is one portable file both drivers run builds the api with the tag and runs `api/internal/db`'s tests against a real PostgreSQL server. It stays **experimental** until the rest lands: running the handler/auth/audit test suites against Postgres (the `e2e-postgres` CI job already -runs the auth, roles and RBAC e2e buckets and the `postgres-availability` upgrade -bucket on it), a published image built with `-tags postgres`, and multi-replica +runs the auth, roles and RBAC e2e buckets on it, plus the `postgres-availability` +bucket, a deployment-strategy change and outage recovery on the working-tree +chart, not an upgrade from a previous release), a published image built with +`-tags postgres`, and multi-replica safety (the user-management lock and the audit hash chain assume a single API process). diff --git a/docs/security.md b/docs/security.md index 5be7ee0e2..a67d58424 100644 --- a/docs/security.md +++ b/docs/security.md @@ -867,10 +867,13 @@ self-reported, and the dashboard labels them that way. When a receiver sets `INGEST_POW=true`, `/ingest` requires a solved challenge from `GET /v1/challenge` in the `Gameplane-Telemetry-PoW` header. Challenges are HMAC-signed with a key held only in the receiver's memory, -expire after 15 minutes and work once. The difficulty is `INGEST_POW_MIN_BITS` (default zero) while at most -`INGEST_POW_TARGET_PER_MIN` challenges a minute are issued, then rises -with the rate (up to `INGEST_POW_MAX_BITS`, at most 26) and falls one bit per -five minutes. The check runs before the body is read, so a refused report +expire after 15 minutes and work once. The rate-derived difficulty is zero +while at most `INGEST_POW_TARGET_PER_MIN` challenges a minute are issued and +rises with the rate above that (up to `INGEST_POW_MAX_BITS`, at most 26). The +receiver keeps the highest recent difficulty as a peak that falls one bit per +five minutes, so after a flood the difficulty can stay above +`INGEST_POW_MIN_BITS` (default zero) for a while; it never drops below that +minimum. The check runs before the body is read, so a refused report costs the receiver one HMAC and one hash, and it answers `428` (`pow_required` or `pow_invalid`) or, when its used-challenge set (1,000,000 entries) is full, `503 pow_busy`. Challenge requests have their own diff --git a/docs/telemetry-provider.md b/docs/telemetry-provider.md index 3a0a7943a..a186eb1ab 100644 --- a/docs/telemetry-provider.md +++ b/docs/telemetry-provider.md @@ -549,10 +549,12 @@ automatic retry. ### Tune it from `/metrics` Difficulty depends on `r`, the challenges issued in the last 60 seconds, and -`INGEST_POW_TARGET_PER_MIN` (`T`). At or below `T` the difficulty is -`INGEST_POW_MIN_BITS` (default `0`: no work). Above it, it is -`ceil(2 * log2(r / T))`, capped at `INGEST_POW_MAX_BITS`; it rises at once and -falls one bit every five minutes. An install's expected work is about +`INGEST_POW_TARGET_PER_MIN` (`T`). At or below `T` the rate adds no +difficulty; above it, it asks for `ceil(2 * log2(r / T))` bits, capped at +`INGEST_POW_MAX_BITS`. The difficulty rises at once and keeps that peak, +falling one bit every five minutes, so it can stay above +`INGEST_POW_MIN_BITS` (default `0`: no work) for a while after `r` drops back +to `T` or below; it is never below the minimum. An install's expected work is about `2^bits` hashes, and installs refuse anything above 26 bits. Each daily report asks for one challenge, so challenges per minute are