From 66438836de15ce1c7ea37c9cb4c4c3af9802c888 Mon Sep 17 00:00:00 2001 From: Mischa Date: Sat, 4 Jul 2026 23:59:44 +0200 Subject: [PATCH] docs: capture stale-GRAV_VERSION api-plugin-install failure (ce-compound) Fresh prod install ran Grav rc.10 (stale .env.prod GRAV_VERSION), so GPM would not serve the api plugin (needs >=2.0.4); admin2 (auth via /api/v1) then 404'd login silently. Documents the dead ends (deploying api config, gpm index -f, same-channel assumption) and the fix (self-upgrade core + reinstall + bump .env.prod). Adds reciprocal 'same 2026-07-04 cutover' cross-links across the three sibling deploy gotchas. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01Np4cMQLF77i664CAQXySzU --- ...av-double-content-encoding-garbage-page.md | 1 + ...-grav-version-blocks-api-plugin-install.md | 94 +++++++++++++++++++ ...new-user-grants-api-not-admin-on-admin2.md | 1 + 3 files changed, 96 insertions(+) create mode 100644 docs/solutions/integration-issues/stale-grav-version-blocks-api-plugin-install.md diff --git a/docs/solutions/integration-issues/grav-double-content-encoding-garbage-page.md b/docs/solutions/integration-issues/grav-double-content-encoding-garbage-page.md index 975d623..e7db895 100644 --- a/docs/solutions/integration-issues/grav-double-content-encoding-garbage-page.md +++ b/docs/solutions/integration-issues/grav-double-content-encoding-garbage-page.md @@ -119,4 +119,5 @@ Setting `close_connection: false` means Grav never enters the manual connection- - **Grav per-environment override mechanism** — `deploy/env/prod/system.yaml` applied via `make remote-apply-env-prod`, described in `CLAUDE.md` §1 ("Production mode — per-environment override"). The pattern that lets a prod-only setting like `debugger.shutdown.close_connection: false` ship without mutating the committed dev `system.yaml`. - **`docs/working/git-sync-notes.md`** — documents the `user/env//config/` override tree (where this fix physically lives on the server) and the caveat that config saved via Admin on the server stays server-only. +- **`docs/solutions/integration-issues/stale-grav-version-blocks-api-plugin-install.md`** — sibling from the same cutover: Admin2 login failed because a stale `GRAV_VERSION` installed an rc core and GPM wouldn't serve the `api` plugin. Different root cause, same deploy. - **`docs/solutions/test-failures/new-user-grants-api-not-admin-on-admin2.md`** — a sibling gotcha from the same 2026-07-04 Grav 2.0.4 production cutover (account permission provisioning); different root cause, same deploy. diff --git a/docs/solutions/integration-issues/stale-grav-version-blocks-api-plugin-install.md b/docs/solutions/integration-issues/stale-grav-version-blocks-api-plugin-install.md new file mode 100644 index 0000000..b58c11c --- /dev/null +++ b/docs/solutions/integration-issues/stale-grav-version-blocks-api-plugin-install.md @@ -0,0 +1,94 @@ +--- +title: "Admin2 login fails silently because a stale GRAV_VERSION installs an rc core below the api plugin's version floor" +date: 2026-07-04 +category: docs/solutions/integration-issues +module: "grav / production deploy / plugin install" +problem_type: integration_issue +component: authentication +severity: high +symptoms: + - "Admin2 login at /admin silently fails: button disables then re-enables, no visible error, nothing written to grav.log" + - "admin2 SPA background login POST to /api/... returns 404" + - "/api/v1/pages returns 404 on prod but 401 locally (api plugin route not registered)" + - "user/plugins/api directory does not exist on prod (plugin never installed)" + - "gpm install api reports 'These packages were not found on Grav: api' even after gpm index -f" +root_cause: config_error +resolution_type: environment_setup +related_components: + - "gpm" + - "admin2 plugin" + - "api plugin" + - "scripts/server-install.sh" + - "Makefile remote targets" + - ".env.prod" +tags: + - grav + - gpm + - admin2 + - api-plugin + - plugin-dependency + - version-compatibility + - production-deploy + - env-config +--- + +# Admin2 login fails silently because a stale GRAV_VERSION installs an rc core below the api plugin's version floor + +## Problem + +On a fresh Grav production install, Admin2 login fails silently because the `api` plugin — which Admin2 authenticates through — never installed. GPM refused to serve it: a stale `GRAV_VERSION` in `.env.prod` had installed Grav `2.0.0-rc.10`, and the `api` plugin requires Grav core `>=2.0.4`. GPM filters offered packages by the installed core version, so on an rc.10 core the `api` plugin was excluded from results entirely and reported as "not found." Admin2 was present (and depends on `api`), but its login POST hit an `/api/...` route that was never registered, so authentication silently 404'd before it ever reached Grav's auth layer. + +## Symptoms + +- Admin login at `/admin` silently fails: the login button disables briefly, re-enables, and shows no error. **Nothing appears in `logs/grav.log`** — a wrong password *would* log a failed-attempt warning, so its absence means auth was never reached. +- The Admin2 SPA's background login request (to an `/api/...` endpoint) returns **HTTP 404** with `content-type: application/json`. +- `GET /api/v1/pages` returns **404** on prod, but **401 Unauthorized** on the working local install — i.e. the api route isn't registered on prod at all. +- `ls user/plugins/api` on the server: **No such file or directory** — the plugin was never installed, even though `admin2` (which depends on it) was. +- `php bin/gpm install ... api -y` → `"These packages were not found on Grav: api"`, even after `php bin/gpm index -f`. + +## What Didn't Work + +- **Committing/deploying the api plugin config** (`enabled` / `route` / `session_enabled`, moved from the untracked `user/plugins/api/api.yaml` into the tracked `user/config/plugins/api.yaml`). This was a real, necessary fix for a *different* latent problem, but it did not fix login: you cannot configure a plugin that isn't installed. Still 404. +- **Forcing a GPM index refresh** (`php bin/gpm index -f`). No effect. "Package not found" here is not a stale-index problem — GPM filters the packages it offers by the installed Grav **core** version, and rc.10 is below the api plugin's `>=2.0.4` requirement, so `api` is excluded from results entirely. +- **Assuming "same channel = same availability."** Local (Grav 2.0.4, `stable` channel) found `api` via `gpm info api`; prod (also `stable`) reported it "not found." The channel was identical — the difference was the Grav **core** version, which silently filtered the plugin out. + +## Solution + +The real cause is that prod was running the wrong Grav core. `scripts/server-install.sh` downloads `grav-admin-v${GRAV_VERSION}.zip`, and `.env.prod` still carried the stale pre-upgrade `GRAV_VERSION=2.0.0-rc.10`. + +1. Upgrade the Grav core in place to stable (rc.10 → 2.0.7): + ```bash + make remote-upgrade-grav-prod # php bin/gpm self-upgrade -y && php bin/grav cache + ``` +2. Install the plugins now that a compatible core is present (the api plugin resolves): + ```bash + make remote-install-plugins-prod # php bin/gpm index -f && php bin/gpm install -y + # => "Preparing to install API [v1.0.8] ... Success!" + ``` +3. Clear cache, then verify the api route is live and login works: + ```bash + make remote-clean-prod + curl -s -o /dev/null -w '%{http_code}\n' https://site/api/v1/pages + # 401 (was 404) => plugin installed + routed + ``` +4. **Prevent recurrence:** update `.env.prod` to `GRAV_VERSION=2.0.4` so a future *fresh* install doesn't reinstall rc.10 (self-upgrade fixed the running server, not the env file). Keep the api plugin's functional config in the tracked `user/config/plugins/api.yaml` so it deploys on a clean clone. + +## Why This Works + +GPM (Grav Package Manager) only offers a plugin version whose declared Grav requirement is satisfied by the **installed core**. The `api` plugin requires Grav `>=2.0.4`; on a `2.0.0-rc.10` core there is no compatible version, so GPM reports the package as "not found" rather than a version conflict. Admin2 declares `api` as a hard dependency and performs all authentication over the api plugin's `/api/v1` JWT endpoints, so with `api` absent the login POST hits a route that doesn't exist (404) and never reaches Grav's auth layer — hence the silent failure with no `grav.log` entry. Upgrading the core to a stable `>=2.0.4` build makes GPM offer `api` again; installing it registers `/api/v1`, and Admin2's login flow succeeds. + +## Prevention + +- **Keep `.env.` `GRAV_VERSION` current.** It is the version a *fresh* `make remote-install-` bakes in; a stale value silently installs an old core. After any core upgrade, bump the env file too — self-upgrade only moves the running server. Note this is a *third* version-authority surface alongside `user/config/system.yaml` `gpm.releases` (channel) and `plugins.txt` — they must stay in sync. +- **When GPM says "package not found" for a package you know is on your channel, check the target's Grav core version first** (`php bin/grav --version` on the server, or `make remote-diag-`). GPM filters by core compatibility; "not found" often means "no version compatible with your core," not "missing from the index." `gpm index -f` will not help. +- **Don't trust a top-level install "Success" to mean dependencies installed.** A fresh install can leave a plugin's declared dependency unsatisfied (here `admin2` installed but its `api` dependency didn't). Verify with `ls user/plugins/`. +- **Know the Admin2 ⇄ api coupling.** Admin2 authenticates via the api plugin's `/api/v1` endpoints; a missing or unrouted api plugin makes admin login fail *silently* (login POST 404s, nothing logged). A quick `curl /api/v1/pages` expecting `401` (not `404`) is a good post-deploy smoke check. + +## Related + +This is one of three independent gotchas from the same **2026-07-04 Grav 2.0.4 production cutover**: + +- `docs/solutions/integration-issues/grav-double-content-encoding-garbage-page.md` — sibling: garbage-rendered pages from a double `Content-Encoding` header on a non-FastCGI host. Different root cause (HTTP compression), same deploy. +- `docs/solutions/test-failures/new-user-grants-api-not-admin-on-admin2.md` — sibling: an authenticated account is denied an admin-gated page because `login new-user` auto-detect granted `api.*` but not `admin.*`. Different root cause (permission provisioning), same admin2/api area. +- `docs/working/plans/2026-07-04-grav-2.0.4-upgrade.md` — the upgrade plan whose Global Constraints spell out the GPM version floors (`grav >=2.0.4`, `api >=1.0.6`) that cause the "package not found" on an rc core. +- **api plugin config** in the tracked `user/config/plugins/api.yaml` (`enabled` / `route` / `session_enabled`) — must ship on a clean clone; necessary but not sufficient (the plugin must be installed first). See CLAUDE.md §0 "Plugin management". diff --git a/docs/solutions/test-failures/new-user-grants-api-not-admin-on-admin2.md b/docs/solutions/test-failures/new-user-grants-api-not-admin-on-admin2.md index 890a6e0..e20104a 100644 --- a/docs/solutions/test-failures/new-user-grants-api-not-admin-on-admin2.md +++ b/docs/solutions/test-failures/new-user-grants-api-not-admin-on-admin2.md @@ -78,5 +78,6 @@ This site runs **Admin2 only** (the classic `admin` plugin is disabled), so auto ## Related Issues - `docs/working/plans/2026-07-04-grav-2.0.4-upgrade.md` — the self-contained test-account infrastructure shipped alongside the Grav 2.0.4 upgrade. +- Sibling gotchas from the same 2026-07-04 Grav 2.0.4 production cutover (all surface around admin2/api but with distinct root causes): `docs/solutions/integration-issues/stale-grav-version-blocks-api-plugin-install.md` (stale `GRAV_VERSION` → rc core → GPM won't serve the `api` plugin → login 404s) and `docs/solutions/integration-issues/grav-double-content-encoding-garbage-page.md` (double `Content-Encoding` header → garbage page). - `docs/solutions/architecture-patterns/dual-repo-submodule-workflow.md` — accounts live in the `user/` repo; the `testrunner` account is gitignored so it never reaches production. - GPX manager auth model (`access.admin.login: true` frontmatter + Login plugin) — see the project's GPX manager notes.