diff --git a/CHANGELOG.md b/CHANGELOG.md index f2fad16..7b790f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,18 @@ skip versions are the composition of each intervening adjacent release's steps in order — no A-to-B path is pre-computed beyond that. +## 0.52.2 — 2026-06-09 + +**Patch — admin sidebar nav links no longer accumulate URL segments (no +operator action required).** + +- **The `/admin` left-rail links were relative**, so under the `/admin/*` + nested route each click resolved against the current URL and *appended* a + segment — e.g. clicking Users → Allowlist → Graduation produced + `/admin/users/allowlist/graduation` instead of `/admin/graduation`. Fixed: + the rail `NavLink`s now use absolute targets (`/admin/`) with `end` + for exact active-state matching. + ## 0.52.1 — 2026-06-08 **Patch — collection-scoped entry-detail fetch fix (no operator action diff --git a/VERSION b/VERSION index d06c2d4..fbb7b19 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.52.1 \ No newline at end of file +0.52.2 \ No newline at end of file diff --git a/e2e/metadata.spec.js b/e2e/metadata.spec.js index b50e4ef..fee09a9 100644 --- a/e2e/metadata.spec.js +++ b/e2e/metadata.spec.js @@ -43,15 +43,22 @@ test('SLICE-4: edit one entry\'s priority from the detail panel', async ({ page const panel = page.locator('.metadata-fields-panel') await expect(panel).toBeVisible() - // Seeded at P1; change to P2 and save (direct sidecar commit, D7). - await expect(panel.locator('#mf-priority')).toHaveValue('P1') - await panel.locator('#mf-priority').selectOption('P2') + const select = panel.locator('#mf-priority') + // Value-agnostic so the test is idempotent across retries and re-runs: a + // prior (committed) edit may have already moved it off the P1 seed. Pick a + // target distinct from the current value so Save is a real change. + const current = await select.inputValue() + const target = current === 'P2' ? 'P1' : 'P2' + await select.selectOption(target) await panel.getByRole('button', { name: 'Save' }).click() - await expect(panel.getByText('Saved')).toBeVisible() + // The save is a real git sidecar commit via the bot (D7); over the deployed + // edge the round trip can take tens of seconds — wait generously for the + // confirmation rather than the default expect timeout. + await expect(panel.getByText('Saved')).toBeVisible({ timeout: 60_000 }) // Persisted across a reload (read back from the committed sidecar). await page.reload() - await expect(page.locator('.metadata-fields-panel #mf-priority')).toHaveValue('P2') + await expect(page.locator('.metadata-fields-panel #mf-priority')).toHaveValue(target) }) // SLICE-5 (PUC-2) — multi-select + bulk action bar, one commit (authed). @@ -71,8 +78,10 @@ test('SLICE-5: bulk-set priority on multiple selected entries', async ({ page }) await expect(bar.getByText('2 selected')).toBeVisible() // Set priority P1 across both → one commit; a toast reports the result. + // Like SLICE-4, the bulk write is a real git commit via the bot; allow the + // deployed-edge round trip generous time before the result toast appears. await bar.getByLabel('Set Priority').selectOption('P1') - await expect(page.getByText(/2 updated/)).toBeVisible() + await expect(page.getByText(/2 updated/)).toBeVisible({ timeout: 60_000 }) // The change is reflected server-side: the Priority P1 facet now counts the // two newly-updated entries plus the pre-existing P1 (checkout-returning was diff --git a/frontend/package.json b/frontend/package.json index 6844759..0a31e1c 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,7 +1,7 @@ { "name": "rfc-app-frontend", "private": true, - "version": "0.52.1", + "version": "0.52.2", "type": "module", "scripts": { "dev": "vite", diff --git a/frontend/src/components/Admin.jsx b/frontend/src/components/Admin.jsx index a9a83b1..a08c504 100644 --- a/frontend/src/components/Admin.jsx +++ b/frontend/src/components/Admin.jsx @@ -59,7 +59,8 @@ export default function Admin({ viewer }) { {tabs.map(t => (
  • `admin-rail-link ${isActive ? 'active' : ''}`} > {t.label} diff --git a/testing/seed-ppe.sh b/testing/seed-ppe.sh index 5f7453d..8342a5a 100755 --- a/testing/seed-ppe.sh +++ b/testing/seed-ppe.sh @@ -103,6 +103,17 @@ put_file() { 201 "create $_repo/$_path" } +# delete_file — remove the file if it exists (no-op if absent). +delete_file() { + _repo="$1"; _path="$2" + _sha=$(file_sha "$_repo" "$_path") + [ -n "$_sha" ] || { echo "seed-ppe: $_repo/$_path absent, nothing to delete"; return 0; } + echo "seed-ppe: deleting $_repo/$_path" + mutate DELETE "$GITEA/api/v1/repos/$ORG/$_repo/contents/$_path" \ + "{\"message\":\"reseed: drop sidecar $_path\",\"sha\":\"$_sha\",\"branch\":\"main\"}" \ + 200 "delete $_repo/$_path" +} + ensure_repo "$REGISTRY_REPO" ensure_repo "$CONTENT_REPO" @@ -182,4 +193,17 @@ tags: [search] Faceted search scenario. " "$RESEED" +# RESEED also drops any metadata sidecars (.meta.yaml) left by prior +# SLICE-4/5 edits. A sidecar takes precedence over the .md frontmatter +# (dual-read, §22.4a), so without this a re-run inherits the edited +# priorities (everything ends up P1) and the faceted preconditions drift — +# SLICE-3 expects P0 count = 2. Dropping the sidecars restores the +# frontmatter as the source of truth: checkout-guest=P0, search-facets=P0, +# checkout-returning=P1. +if [ "$RESEED" = "1" ]; then + for _slug in checkout-guest checkout-returning search-facets; do + delete_file "$CONTENT_REPO" "bdd/rfcs/$_slug.meta.yaml" + done +fi + echo "seed-ppe: done. Set REGISTRY_REPO=$REGISTRY_REPO on rfc-app-ppe and redeploy."