Files
plainpages/compose.override.yml
lilleman f189f88942 §7 reference plugin (todo §7); plugins/scheduling is the worked example of the plugin contract — a list page fetching upstream data, a CSRF-guarded form forwarding writes upstream, permission-gated nav. shifts.ts: an injectable-fetch upstream REST client (stateless stand-in for the customer backend) + thin handler factories (list filters by ?q + degrades to a recoverable page on upstream-down; create CSRF-guards via ctx.verifyCsrf, validates, forwards, PRG, 502 on upstream 4xx). plugin.ts: apiVersion literal, namespaced scheduling:read/write perms, nav gated so the whole Scheduling header vanishes for non-holders. Views compose the core building blocks around the native app shell, incl. the plugin's own partials/shift-form. New host capability so a plugin page is native + secure (src/chrome.ts buildPluginChrome): ctx.chrome = brand/global-nav/user/theme/csrf for partials/shell (global menu = Dashboard + every plugin nav fragment + gated admin section, role-filtered + current-marked); ctx.verifyCsrf = the host's bound double-submit verifier (secret stays in the host). Both added to RequestContext (defaulted in buildContext), built per plugin route in app.ts (CSRF cookie set when fresh). Dashboard merges plugin nav fragments too (gated => invisible to anonymous, visual E2E byte-identical). Out of the box: bootstrap grants the demo admin scheduling:read/write (seedAdmin generalized to a roles list, env ADMIN_ROLES); dev compose runs a tiny stdlib mock upstream (examples/shifts-upstream, SCHEDULING_UPSTREAM). plugins/ added to tsconfig + the npm test glob. Tests-first across shifts/chrome/app/dashboard/bootstrap. README Building-a-plugin + Layout and docs/plugin-contract.md (ctx.chrome/verifyCsrf, upstream pattern) updated. typecheck + 296 units + the Ory-free visual E2E green (plugin discovered at boot, routes/nav gated, dashboard unchanged); live full-stack boot-verified (stack up with plugin + mock upstream serving the seeded shifts, bootstrap grants in real Keto all allowed:true) then torn down. apiVersion stays 1.0.0 (contract still assembled in §7). Authenticated browser happy-path deferred to §8 full E2E (line 114).
2026-06-19 14:48:27 +02:00

47 lines
1.9 KiB
YAML

# Development overrides, merged automatically by `docker compose up`.
# Mounts the source for live editing and restarts on change via `node --watch`.
services:
web:
command: node --watch src/server.ts
# Dev overrides the base toggles: live template edits, dev-throwaway secrets allowed.
environment:
CACHE_TEMPLATES: "false"
REQUIRE_SECURE_SECRETS: "false"
SECURE_COOKIES: "false" # dev serves http — Secure cookies wouldn't be sent
SCHEDULING_UPSTREAM: "http://shifts-upstream:4000" # reference plugin → the dev mock backend
volumes:
- .:/app
- /app/node_modules
# Dev mock backend for the reference plugin (plugins/scheduling). A stand-in for the customer's
# real scheduling service — stdlib-only, in-memory, no auth. Prod points SCHEDULING_UPSTREAM at
# the real backend instead. Uses the pinned app image so there's nothing extra to build/pull.
shifts-upstream:
image: node:24.16.0-alpine3.24
command: node /srv/server.mjs
restart: unless-stopped
volumes:
- ./examples/shifts-upstream:/srv:ro
# 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.30.1
ports:
- "8025:8025"
restart: unless-stopped
# Ory Kratos dev: expose the public API so the browser can POST self-service flows to
# flow.ui.action (kratos.yml base_url = 127.0.0.1:4433). Prod fronts Ory same-origin,
# so the base file publishes no Ory ports.
kratos:
ports:
- "4433:4433"
# Ory Hydra dev: --dev permits the http issuer/redirect URLs; expose the public port
# so OAuth2 flows reach the host. Prod (base file) drops --dev for an https issuer.
hydra:
command: serve all --dev -c /etc/config/hydra/hydra.yml
ports:
- "4444:4444"