|
|
4e97fb619e
|
§7 review checkpoint (todo §7); ran the architecture + product reviewers on the whole project and addressed findings, no Critical from either. Made permissions honest + decoupled the host from the plugin: new pure seedRoles + bootstrap discoverPlugins() seeds the demo admin admin(/ADMIN_ROLES) ∪ every discovered plugin's declared tokens, dropped the hardcoded scheduling:* from compose ADMIN_ROLES (clean-clone unchanged); docs now state a route/nav permission is a coarse role granted as Keto Role:<token>#members. Added src/plugin-api.ts — the stable author barrel the reference plugin now imports from instead of deep src/* (the contract boundary in code). Made per-plugin CSS usable: shell styles slot + plugins/scheduling/public/scheduling.css linked from the views. Reference now demonstrates hooks.onBoot validating SCHEDULING_UPSTREAM fail-loud (assertHttpUrl). Build ctx.chrome at most once per request (memoized). Doc honesty: fixed the false visual.spec coverage comment, softened the "every plugin ships a Playwright test" claim (authed flow = §8), added an Upstream contract block to the plugin README. Added LICENSE (MIT). Stability-reviewer APPROVE, no Critical/High; addressed both Low nits. typecheck + 301 units green. Deferred: internal route-table (M1)→§9, safeUrl()→§9, data-table empty-state + success-flash→§8/polish, apiVersion-literal enforcement (prose), permission→requireRole rename (future minor).
|
2026-06-19 15:31:53 +02:00 |
|
|
|
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 |
|
|
|
3c8090e8e3
|
Built-in OAuth2 login-challenge handler (todo §6); /oauth2/login resolves a Hydra login challenge via the Kratos session — skip→accept(subject), live session→accept(identity id), no session→bounce to /login?return_to back here so Kratos lands on the challenge once signed in. New src/hydra-admin.ts (fetch client: get/accept/reject login request + HydraError, mirrors the kratos/keto clients) + src/oauth-login.ts (pure resolveLoginChallenge); wired in app.ts (the absolute return URL derives from the request Host + the SECURE_COOKIES scheme — a spoofed Host can't escape, Kratos validates return_to against its allow-list; /login now bakes return_to into the flow init), config.hydraAdminUrl (default http://hydra:4445), server builds the client, compose web now gates on hydra healthy (the app consumes it). A stale/invalid/consumed challenge (Hydra 4xx — back button, slow login) degrades to a recoverable 400, not a 500; a genuine Hydra 5xx outage still surfaces as 500. Tests-first: hydra-admin/oauth-login units + app/config/compose HTTP integration + full-stack e2e/oauth-login.spec.ts (compose.e2e-oauth.yml — registers an OAuth2 client, starts an auth flow, asserts the unauthenticated bounce and the authenticated accept; boot-verified then torn down). Stability-reviewer run as a local PR: APPROVE, no Critical/High; addressed its one warning (4xx→400 degrade). Deferred §9: document that prod allowed_return_urls entries must be exact origins with a trailing /. typecheck + 253 units + 8 visual + oauth-login E2E green. Consent handler + client registration are the next §6 items.
|
2026-06-18 21:45:24 +02:00 |
|
|
|
4b2173cb84
|
Secure cookie flags + CSRF for our own POST forms (todo §4); SECURE_COOKIES toggle on session/CSRF cookies; csrf.ts signed double-submit token + body.ts form reader; logout is now a CSRF-guarded POST form
|
2026-06-18 11:12:32 +02:00 |
|
|
|
360449e76b
|
Tighten §3 comments (todo §3); drop stale 'next §3 item' forward-refs, condense compose/Ory/bootstrap headers
|
2026-06-17 17:00:47 +02:00 |
|
|
|
e83cf4da88
|
Address project-wide review (todo §3); fix JWKS_URL default → tokenizer signing key + read-only web mount, cap bootstrap restart, --no-deps for unit commands
|
2026-06-17 16:49:37 +02:00 |
|
|
|
4d65665063
|
Bootstrap: print first-run login banner (URL + seeded creds + change-before-prod warning)
|
2026-06-17 16:22:48 +02:00 |
|
|
|
a6900217cb
|
One-command bootstrap (todo §3); idempotent first-boot seed: JWKS-if-absent, demo admin in Kratos, admin role in Keto
|
2026-06-17 16:18:21 +02:00 |
|
|
|
4af090f803
|
Split dev/prod compose wiring (todo §3); Ory readiness healthchecks, web gated on kratos+keto, dev-only host ports, Ory-free E2E
|
2026-06-17 16:06:05 +02:00 |
|
|
|
93e62d8661
|
Add Hydra service + migrate (todo §3); pin oryd/hydra:v26.2.0, OAuth2 issuer + login/consent URLs → our app routes
|
2026-06-17 15:45:37 +02:00 |
|
|
|
fa87280f46
|
Add Keto service + migrate (todo §3); OPL role/group/resource namespaces, fine-grained resource permits
|
2026-06-17 15:12:01 +02:00 |
|
|
|
f2898696e6
|
Wire Kratos self-service flows to themed routes (todo §3); enable recovery/verification via email code, add mailpit dev courier + --watch-courier
|
2026-06-17 10:19:29 +02:00 |
|
|
|
120e1a0929
|
Add kratos service + migrate (todo §3); pin oryd/kratos:v26.2.0, identity schema (email, name), bootable password config
|
2026-06-16 23:24:32 +02:00 |
|
|
|
bc15f00c44
|
Add postgres service (todo §3); pin postgres:18.4-alpine3.23, one DB per Kratos/Keto/Hydra via init.sql
|
2026-06-16 17:13:40 +02:00 |
|
|
|
a070362649
|
Drop NODE_ENV for explicit config toggles (todo §0.1); app is environment-agnostic
|
2026-06-15 10:53:33 +02:00 |
|
|
|
c544387d3a
|
Add RequestContext primitive (todo §0); harden static serving (HEAD, control-char, stream-error logging)
|
2026-06-14 19:33:17 +02:00 |
|
|
|
4eed701419
|
Scaffold Docker-only Node 24 + TypeScript EJS web backend
|
2026-06-14 11:45:30 +02:00 |
|