Compare commits

...

37 Commits

Author SHA1 Message Date
renovate-bot 446e98d15d Update Node.js to v24.22.0
CI / full-gate (push) Successful in 3m20s
Release-Bump: minor
2026-10-18 04:18:46 +00:00
renovate-bot 194557fb49 Update dependency lucide-static to v1.58.0
CI / full-gate (push) Successful in 3m9s
Mirror / github-mirror (push) Successful in 4s
Release-Bump: minor
2026-10-17 04:18:09 +00:00
renovate-bot 4a0fc2b493 Update axllent/mailpit Docker tag to v1.31.6
CI / full-gate (push) Successful in 4m6s
Mirror / github-mirror (push) Successful in 4s
2026-10-16 04:17:53 +00:00
renovate-bot 946c45663f Update Playwright to v1.64.1
CI / full-gate (push) Successful in 4m48s
Mirror / github-mirror (push) Successful in 3s
2026-10-15 04:19:16 +00:00
renovate-bot 41ab968b20 Update dependency lucide-static to v1.56.0
CI / full-gate (push) Successful in 4m55s
Mirror / github-mirror (push) Successful in 4s
Release-Bump: minor
2026-10-14 04:18:41 +00:00
renovate-bot ff548a30d2 Update Playwright to v1.64.0
CI / full-gate (push) Successful in 4m4s
Mirror / github-mirror (push) Successful in 3s
2026-10-13 04:18:09 +00:00
renovate-bot f80c6c6426 Update dependency lucide-static to v1.55.0
CI / full-gate (push) Successful in 3m0s
Mirror / github-mirror (push) Successful in 4s
Release-Bump: minor
2026-10-12 04:18:07 +00:00
renovate-bot 3658797764 Update axllent/mailpit Docker tag to v1.31.5
CI / full-gate (push) Successful in 2m59s
Mirror / github-mirror (push) Successful in 4s
2026-10-11 04:17:52 +00:00
renovate-bot 23f1158211 Update dependency @types/node to v24.19.2
CI / full-gate (push) Successful in 3m12s
Mirror / github-mirror (push) Successful in 4s
2026-10-10 04:18:04 +00:00
renovate-bot bf9302ce8e Update dependency lucide-static to v1.53.0
CI / full-gate (push) Successful in 3m11s
Mirror / github-mirror (push) Successful in 4s
Release-Bump: minor
2026-10-09 04:18:47 +00:00
renovate-bot 2ed134fc86 Update renovate/renovate Docker tag to v44.145.1
CI / full-gate (push) Successful in 2m59s
Mirror / github-mirror (push) Successful in 4s
2026-10-08 04:18:53 +00:00
renovate-bot e07edeb6ae Update renovate/renovate Docker tag to v44.141.0
CI / full-gate (push) Successful in 3m2s
Mirror / github-mirror (push) Successful in 4s
2026-10-07 04:18:18 +00:00
renovate-bot e9cd7ba2b3 Update dependency lucide-static to v1.52.0
CI / full-gate (push) Successful in 3m10s
Mirror / github-mirror (push) Successful in 4s
Release-Bump: minor
2026-10-06 04:18:18 +00:00
renovate-bot a49bd4f7b0 Update dependency @types/node to v24.19.1
CI / full-gate (push) Successful in 3m0s
Mirror / github-mirror (push) Successful in 3s
2026-10-05 04:18:14 +00:00
renovate-bot e680552961 Update axllent/mailpit Docker tag to v1.31.4
CI / full-gate (push) Successful in 4m29s
Mirror / github-mirror (push) Successful in 4s
2026-10-04 04:18:27 +00:00
renovate-bot 12977bc296 Update dependency lucide-static to v1.50.0
CI / full-gate (push) Successful in 4m20s
Mirror / github-mirror (push) Successful in 4s
Release-Bump: minor
2026-10-03 04:18:40 +00:00
renovate-bot dac189b124 Update dependency lucide-static to v1.49.0
CI / full-gate (push) Successful in 4m1s
Mirror / github-mirror (push) Successful in 4s
Release-Bump: minor
2026-09-30 04:18:43 +00:00
renovate-bot c9e2f1a9e4 Update renovate/renovate Docker tag to v44.117.2
CI / full-gate (push) Successful in 3m11s
Mirror / github-mirror (push) Successful in 3s
2026-09-29 04:18:14 +00:00
renovate-bot 7a17ec11de Update axllent/mailpit Docker tag to v1.31.3
CI / full-gate (push) Successful in 3m36s
Mirror / github-mirror (push) Successful in 4s
2026-09-28 04:18:22 +00:00
renovate-bot ec1579a039 Update renovate/renovate Docker tag to v44.115.10
CI / full-gate (push) Successful in 3m7s
Mirror / github-mirror (push) Successful in 4s
2026-09-27 04:18:21 +00:00
renovate-bot 153e77174d Update dependency @types/node to v24.19.0
CI / full-gate (push) Successful in 3m36s
Mirror / github-mirror (push) Successful in 5s
2026-09-26 04:18:08 +00:00
renovate-bot 6e21eb2d4b Update dependency lucide-static to v1.48.0
CI / full-gate (push) Successful in 3m18s
Mirror / github-mirror (push) Successful in 3s
Release-Bump: minor
2026-09-25 04:18:38 +00:00
renovate-bot d8a31def52 Update renovate/renovate Docker tag to v44.111.4
CI / full-gate (push) Successful in 4m5s
Mirror / github-mirror (push) Successful in 4s
2026-09-24 04:18:07 +00:00
renovate-bot 5b49bce690 Update renovate/renovate Docker tag to v44.108.2
CI / full-gate (push) Successful in 2m55s
Mirror / github-mirror (push) Successful in 3s
2026-09-23 04:18:13 +00:00
renovate-bot 584a383d22 Update renovate/renovate Docker tag to v44.106.0
CI / full-gate (push) Successful in 2m54s
Mirror / github-mirror (push) Successful in 4s
2026-09-22 04:18:10 +00:00
renovate-bot 28dbc1a0ff Update renovate/renovate Docker tag to v44.104.2
CI / full-gate (push) Successful in 2m55s
Mirror / github-mirror (push) Successful in 3s
2026-09-21 04:17:58 +00:00
renovate-bot 0f0a842f34 Update axllent/mailpit Docker tag to v1.31.2
CI / full-gate (push) Successful in 2m51s
Mirror / github-mirror (push) Successful in 3s
2026-09-20 04:17:54 +00:00
renovate-bot 88c5357268 Update dependency @types/node to v24.13.6
CI / full-gate (push) Successful in 3m54s
Mirror / github-mirror (push) Successful in 3s
2026-09-19 04:18:32 +00:00
renovate-bot 3bd9adc73b Update dependency lucide-static to v1.47.0
CI / full-gate (push) Successful in 3m3s
Mirror / github-mirror (push) Successful in 2s
Release-Bump: minor
2026-09-18 04:18:38 +00:00
renovate-bot 51c95b32c1 Update renovate/renovate Docker tag to v44.95.0
CI / full-gate (push) Successful in 3m45s
Mirror / github-mirror (push) Successful in 2s
2026-09-17 04:18:20 +00:00
renovate-bot 3593b39e43 Update dependency @types/node to v24.13.5
CI / full-gate (push) Successful in 3m4s
Mirror / github-mirror (push) Successful in 2s
2026-09-16 04:18:00 +00:00
lilleman 5f9d74ae4f Record that state lives in the URL or on the server, never in a cookie
CI / full-gate (push) Successful in 2s
Mirror / github-mirror (push) Successful in 3s
2026-09-15 14:21:44 +02:00
renovate-bot 79cee25b66 Update dependency lucide-static to v1.46.0
CI / full-gate (push) Successful in 3m3s
Mirror / github-mirror (push) Successful in 3s
Release-Bump: minor
2026-09-15 04:18:12 +00:00
lilleman 2993b462a1 Ask for dependent form fields in steps, one GET form each
CI / full-gate (push) Successful in 2s
Mirror / github-mirror (push) Successful in 3s
2026-09-14 17:06:03 +02:00
renovate-bot 7645f0302a Update renovate/renovate Docker tag to v44.83.2
CI / full-gate (push) Successful in 2m51s
Mirror / github-mirror (push) Successful in 2s
2026-09-14 04:18:17 +00:00
renovate-bot e5531a44cd Update renovate/renovate Docker tag to v44.82.5
CI / full-gate (push) Successful in 2m49s
Mirror / github-mirror (push) Successful in 2s
2026-09-13 04:17:52 +00:00
renovate-bot 3b1cd891ed Update dependency lucide-static to v1.45.0
CI / full-gate (push) Successful in 3m52s
Mirror / github-mirror (push) Successful in 2s
Release-Bump: minor
2026-09-12 04:18:26 +00:00
14 changed files with 58 additions and 45 deletions
+1 -1
View File
@@ -19,4 +19,4 @@ jobs:
run: |
docker run --rm -v "$PWD:/repo" -w /repo \
-e REGISTRY_TOKEN -e REGISTRY_USER -e REPO_TOKEN -e REPOSITORY -e SERVER_URL \
node:24.21.0-alpine3.24 node registry-cleanup/cleanup.ts
node:24.22.0-alpine3.24 node registry-cleanup/cleanup.ts
+3 -3
View File
@@ -21,7 +21,7 @@ jobs:
GIT_TAG: ${{ github.ref_name }}
run: |
set -euo pipefail
docker run --rm -v "$PWD:/repo" -w /repo node:24.21.0-alpine3.24 \
docker run --rm -v "$PWD:/repo" -w /repo node:24.22.0-alpine3.24 \
node release-tooling/contract-version.ts "$GIT_TAG" src/plugin-host/plugin.ts
- name: Promote the commit-hash image to semver + latest
env:
@@ -98,9 +98,9 @@ jobs:
VERSION=${INPUT_VERSION:-${GIT_TAG#v}}
VERSION=${VERSION#v}
# An empty dispatch input falls back to the branch name, so gate this like a tag.
docker run --rm -v "$PWD:/repo" -w /repo node:24.21.0-alpine3.24 \
docker run --rm -v "$PWD:/repo" -w /repo node:24.22.0-alpine3.24 \
node release-tooling/contract-version.ts "$VERSION" src/plugin-host/plugin.ts
docker run --rm -v "$PWD:/repo" -w /repo \
-e DOCKERHUB_REPO -e DOCKERHUB_TOKEN -e DOCKERHUB_USER \
node:24.21.0-alpine3.24 \
node:24.22.0-alpine3.24 \
node release-tooling/dockerhub-overview.ts "$VERSION"
+3 -3
View File
@@ -21,7 +21,7 @@ jobs:
-e RENOVATE_PLATFORM=gitea \
-e RENOVATE_REPOSITORIES=${{ github.repository }} \
-e RENOVATE_TOKEN \
renovate/renovate:44.75.1
renovate/renovate:44.145.1
# After the renovate job, cut ONE tag covering the renovate-bot commits merged to main since the
# last tag (batch per run). Targets origin/main — the real post-merge tip; the checkout SHA is the
@@ -58,11 +58,11 @@ jobs:
if [ -z "$BUMPS" ]; then
echo "Renovate commits since ${LATEST}, but none carry Release-Bump — nothing reached a running Plainpages; skipping"; exit 0
fi
NEXT=$(docker run --rm -v "$PWD:/repo" -w /repo node:24.21.0-alpine3.24 \
NEXT=$(docker run --rm -v "$PWD:/repo" -w /repo node:24.22.0-alpine3.24 \
node release-tooling/next-version.ts "$LATEST" $BUMPS)
# Read the constant off origin/main, not the checkout, which lags the merges this run made.
git show origin/main:src/plugin-host/plugin.ts \
| docker run -i --rm -v "$PWD:/repo" -w /repo node:24.21.0-alpine3.24 \
| docker run -i --rm -v "$PWD:/repo" -w /repo node:24.22.0-alpine3.24 \
node release-tooling/contract-version.ts "$NEXT" -
echo "Releasing $LATEST -> $NEXT"
git tag "$NEXT" origin/main
+6 -3
View File
@@ -447,9 +447,12 @@ one-time setup. A file-map or table row gets a clause, not a paragraph.
same rule in their own language. An unmapped Kratos id renders Kratos' own wording — map the id when
it matters. **Held by the author, never by a test:** slightly different wording is often the right
call, and a build-failing check takes that judgment away.
- Use well formed, standard compliant, rich URIs. Prefer state in the URL over POSTing it, for
example on list pages with filters and pagination. Do `ids=x&ids=y`, not `ids[]=x&ids[]=y` and not
`ids=x,y`.
- Use well formed, standard compliant, rich URIs. **State lives in the URL or on the server, never in
a cookie.** Prefer state in the URL over POSTing it, for example on list pages with filters and
pagination. A message for the page a redirect lands on rides its query string — `info-msg`,
`warn-msg`, `error-msg` — since a fragment never reaches the server. A cookie carries only what
must be bound to the browser: the session (`plainpages_jwt`) and the CSRF token (`plainpages_csrf`).
Do `ids=x&ids=y`, not `ids[]=x&ids[]=y` and not `ids=x,y`.
## Comments
+1 -1
View File
@@ -1,5 +1,5 @@
# Node 24 runs TypeScript directly (type stripping) — no build step. Pinned exact tag.
FROM node:24.21.0-alpine3.24
FROM node:24.22.0-alpine3.24
# Above WORKDIR so dev's `.:/app` bind mount can't shadow them; a volume at /app/node_modules
# instead leaves a root-owned dir in the checkout (the daemon creates mount destinations as root).
+10
View File
@@ -961,6 +961,16 @@ underneath it — cramped, but nothing is unreachable. List state
(`?q=…&status=…&sort=…&page=…`) lives **in the URL**, so a view is bookmarkable and shareable; the
URL is the only state the UI keeps.
**A field whose options depend on another field is asked for in steps, one GET form each**, so every
choice is in the URL, and nothing typed is lost to one because nothing is typed until they are made.
Once the query names a value, that field renders read-only (`field` with `readonly`, and a `link` back
to the URL without it) above the next step's form, which carries the earlier choices as hidden inputs,
plus `locale` from `localeParam`. The form that writes comes last and posts to the URL naming every
choice, so its handler reads them from `ctx.query`, never from the body; a value the query names that
the step does not offer is that step's error, never a silent fallback. Don't redraw a half-filled form
through a submit that writes nothing instead: a `required` field blocks it, and the choice never
reaches the URL.
Plugins that genuinely need it — live dashboards, bulk actions, client-side validation — may **opt
into progressive enhancement** (htmx, Alpine, vanilla JS) on top of working server-rendered HTML.
The baseline never depends on it.
+2 -2
View File
@@ -49,7 +49,7 @@ services:
# backs it (PLUGIN_SETTING_SCHEDULING_UPSTREAM above points here). Stand-in for the customer's real service —
# stdlib-only, in-memory, no auth. Prod points PLUGIN_SETTING_SCHEDULING_UPSTREAM at the real backend instead.
shifts-upstream:
image: node:24.21.0-alpine3.24
image: node:24.22.0-alpine3.24
command: node /srv/server.ts
restart: unless-stopped
volumes:
@@ -58,7 +58,7 @@ services:
# Dev mail catcher — Kratos recovery/verification emails land here (web UI on 8025).
# kratos.yml points the courier at smtp://mailpit:1025; prod uses a real SMTP via env.
mailpit:
image: axllent/mailpit:v1.31.1
image: axllent/mailpit:v1.31.6
ports:
- "8025:8025"
restart: unless-stopped
+1 -1
View File
@@ -1,6 +1,6 @@
# Playwright runner — browsers preinstalled, pinned to match @playwright/test in e2e-tests/.
# Built/run via e2e-tests/compose.visual.yml; targets the `web` service over the network.
FROM mcr.microsoft.com/playwright:v1.63.0-noble
FROM mcr.microsoft.com/playwright:v1.64.1-noble
WORKDIR /e2e-tests
+3 -3
View File
@@ -53,7 +53,7 @@ services:
# The reference plugin's upstream (examples/shifts-upstream) so /scheduling/shifts shows real rows.
shifts-upstream:
image: node:24.21.0-alpine3.24
image: node:24.22.0-alpine3.24
command: ["node", "/server.ts"]
volumes:
- ./examples/shifts-upstream/server.ts:/server.ts:ro
@@ -66,7 +66,7 @@ services:
# Mock OIDC provider for the SSO login test — stdlib Node, auto-approves, signs an id_token Kratos
# verifies via its jwks. Reachable as the same host (mock-oidc:9000) by both the browser and Kratos.
mock-oidc:
image: node:24.21.0-alpine3.24
image: node:24.22.0-alpine3.24
command: ["node", "/mock-oidc.ts"]
environment:
ISSUER: http://mock-oidc:9000
@@ -81,7 +81,7 @@ services:
# Same-origin gateway: Kratos-owned paths → kratos, everything else → web (e2e-tests/proxy.ts).
proxy:
image: node:24.21.0-alpine3.24
image: node:24.22.0-alpine3.24
command: ["node", "/proxy.ts"]
depends_on:
web:
+12 -12
View File
@@ -6,17 +6,17 @@
"": {
"name": "plainpages-e2e",
"devDependencies": {
"@playwright/test": "1.63.0"
"@playwright/test": "1.64.1"
}
},
"node_modules/@playwright/test": {
"version": "1.63.0",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.63.0.tgz",
"integrity": "sha512-oxMK4vllB9RK5NQ2l1pq1IfOf2AvnEuj/vYGDj0H2nMtmtZpKtCwt/l00GEO6xjGfpBNAvjovvYdCm50dRQkpQ==",
"version": "1.64.1",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.64.1.tgz",
"integrity": "sha512-IaYGml/nSOiZWROfPtuIL7neuu9qDOZ3TNvNljUIrhDMxiGTgPjzj/g9p9RxpS2tSepPDRY+UwAaEeiKtUvIAg==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"playwright": "1.63.0"
"playwright": "1.64.1"
},
"bin": {
"playwright": "cli.js"
@@ -26,13 +26,13 @@
}
},
"node_modules/playwright": {
"version": "1.63.0",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.63.0.tgz",
"integrity": "sha512-+7ziBLidS4NaNCdt57SUDT+wYmmd5fmiQejUic/kb+YsYSCPyOOE9sebzMjNmQrsnNpDJqd4WHvV/8lfKfUDUg==",
"version": "1.64.1",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.64.1.tgz",
"integrity": "sha512-HCrVhHr5QQuwYoswEUGTb7gGp522yflbv/ST8nF4sFWGuLjQCt17Q/EubpGGSNKYn1tsTCPZxqHhHCfVURu7UA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"playwright-core": "1.63.0"
"playwright-core": "1.64.1"
},
"bin": {
"playwright": "cli.js"
@@ -42,9 +42,9 @@
}
},
"node_modules/playwright-core": {
"version": "1.63.0",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.63.0.tgz",
"integrity": "sha512-rYCsBF/M5HjUch52bbtVONEFjv6Xu8sm8h72dNlR5bzIE1fvC/bxgspzkjSfU+MweEMmPM8KJebG6nnyxo5mCg==",
"version": "1.64.1",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.64.1.tgz",
"integrity": "sha512-BC4s8y6SEVA6Q1rSxZTto8hI1KUI3xXlHGZgvGqP4IqPdI/a6FX9H29IDNz7vKo9l21b6LfYosScPL6M3xxyDQ==",
"dev": true,
"license": "Apache-2.0",
"bin": {
+1 -1
View File
@@ -7,6 +7,6 @@
"test": "playwright test"
},
"devDependencies": {
"@playwright/test": "1.63.0"
"@playwright/test": "1.64.1"
}
}
+12 -12
View File
@@ -8,12 +8,12 @@
"dependencies": {
"@larvit/log": "2.3.0",
"ejs": "6.0.1",
"lucide-static": "1.44.0",
"lucide-static": "1.58.0",
"postgres": "3.4.9"
},
"devDependencies": {
"@types/ejs": "3.1.5",
"@types/node": "24.13.4",
"@types/node": "24.19.2",
"typescript": "7.0.2"
},
"engines": {
@@ -37,13 +37,13 @@
"license": "MIT"
},
"node_modules/@types/node": {
"version": "24.13.4",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.4.tgz",
"integrity": "sha512-YJ7EqCstVTzIr0fMr7qul/977en+pQHrfmuKIo6Zr9i75Be21dr3MovcfvGtyvi2HAUrRerWps5sMO9I7WaxDw==",
"version": "24.19.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.19.2.tgz",
"integrity": "sha512-93d49wCWJkCyN87MxLpNN6KXPCwFw7bVUg79mGUV1OS40JGWwVCr8n61DXCSqz7CV6/VfPkb7xec7uP2M+QHWQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~7.18.0"
"undici-types": ">=7.24.0 <7.24.7"
}
},
"node_modules/@typescript/typescript-aix-ppc64": {
@@ -399,9 +399,9 @@
}
},
"node_modules/lucide-static": {
"version": "1.44.0",
"resolved": "https://registry.npmjs.org/lucide-static/-/lucide-static-1.44.0.tgz",
"integrity": "sha512-u1PAHVq1Ka06FDcXFY8r8fLtS5efVHaawXEETW5tmfnMbd9NU6sPK3GAvZgrbJzY5JmbjHoTTQDcoQOBmW1RKg==",
"version": "1.58.0",
"resolved": "https://registry.npmjs.org/lucide-static/-/lucide-static-1.58.0.tgz",
"integrity": "sha512-VFE2ZEq3yEwjBH0El9CA9lHgDWKKXPKgKxFzX+/JN1FPa4maQbtl/pT4B62aJkUEpODT5octDsyGy7tPVE2svQ==",
"license": "ISC"
},
"node_modules/postgres": {
@@ -453,9 +453,9 @@
}
},
"node_modules/undici-types": {
"version": "7.18.2",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz",
"integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==",
"version": "7.24.6",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz",
"integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==",
"dev": true,
"license": "MIT"
}
+2 -2
View File
@@ -18,12 +18,12 @@
"dependencies": {
"@larvit/log": "2.3.0",
"ejs": "6.0.1",
"lucide-static": "1.44.0",
"lucide-static": "1.58.0",
"postgres": "3.4.9"
},
"devDependencies": {
"@types/ejs": "3.1.5",
"@types/node": "24.13.4",
"@types/node": "24.19.2",
"typescript": "7.0.2"
}
}
+1 -1
View File
@@ -131,7 +131,7 @@ services:
# Catches Kratos' recovery/verification emails — UI on http://localhost:8025
mailpit:
image: axllent/mailpit:v1.31.1
image: axllent/mailpit:v1.31.6
ports:
- "8025:8025"
restart: unless-stopped