This website requires JavaScript.
Explore
Help
Sign In
larvit
/
plainpages
Watch
3
Star
0
Fork
0
You've already forked plainpages
Code
Issues
Pull Requests
Actions
Packages
Projects
Releases
Wiki
Activity
Files
main
Add File
New File
Upload File
Apply Patch
plainpages
/
views
History
lilleman
58398481ca
§10 review pass: address the architecture + product reviewers (todo §10); hide the gated Dashboard nav node from anonymous visitors in buildPluginChrome (a no-permission link to /dashboard only dead-ended them at /login) and dedup it into a shared DASHBOARD_NAV (admin-nav.ts, reused by chrome + adminNav). New chrome.signInHref bakes the current page in as return_to for the shell's anonymous Sign-in link (shell.ejs + reference overview.ejs), mirrored as optional ShellModel.signInHref so the typed builder is complete. ctx.chrome is now a lazy, memoized getter (context.ts chrome option = a factory) so a json/redirect handler or the public "/" with a standalone home never composes the global menu — app.ts passes the app-level memoized factory at every site. Default /dashboard prints a "Starter dashboard" note framing the mock-data home as a replaceable demo (signals its inert affordances); stale "until §4" comments fixed. RESERVED_PLUGIN_IDS drift-guard test derives the built-in segments from AUTH_FLOWS + ADMIN_*_BASE + host literals (home stays deliberately unreserved). Refreshed the stale plugin-contract status blurb and documented the chrome.*→partials/shell mapping. Reviewers: architecture + product APPROVE (no addressable findings remain), stability APPROVE (no Critical/High/Medium). typecheck + 356 units + visual(10) + full-flow(7) E2E green.
2026-06-21 01:19:40 +02:00
..
admin
Built-in OAuth2 client-registration admin screen (todo §6); /admin/clients lists/registers/deletes the Hydra OAuth2 clients other apps log in through us with. New src/admin-clients.ts (pure builders + handleAdminClients, mirroring the §5 Users/Roles screens): list (search/paginate over one fetched Hydra page), register (GET form + POST), read-only detail, delete-confirm. src/hydra-admin.ts gains the client half of the admin API — createClient/listClients/getClient/deleteClient over /admin/clients (+ a nextPageToken Link parser like kratos-admin) and the registration fields on OAuth2Client. Register builds a standard authorization-code client (+ refresh_token), confidential (client_secret_basic) or public (PKCE/none), with an optional first-party auto-consent flag; Hydra returns the client_secret once, so the register POST renders the new client's detail page with the one-time secret directly (no PRG) and it is never re-shown (getClient carries no secret; the detail test asserts it). Writes go only to Hydra; gated admin-only (anon->/login, non-admin->403) + every mutation CSRF-guarded via requireAdmin/guardedForm like §5; a Hydra 4xx (bad redirect/scope) re-renders the form (400), a 5xx -> 500 (mirrors oauth-login.ts); :id via safeDecode (malformed->404). Wired into app.ts (/admin/clients, gated on the hydra client present) and the shared adminSection (Users.Groups.Roles.OAuth2 clients, i-globe) so it shows for admins and is invisible otherwise. New views (admin/clients, client-form, client-detail + partials/client-{form,detail}-body) reuse the shell/filter-bar/data-table/field blocks; one .detail-list CSS rule; README Layout/§6 updated. Tests-first: hydra-admin.test.ts (client CRUD contracts incl. Link pagination/404->null/204), admin-clients.test.ts (builder/validation/payload matrix), app.test.ts HTTP integration (gate/list/register-shows-secret-once/invalid+CSRF-reject/detail-hides-secret/delete + malformed-%->404). Stability-reviewer run as a local PR: APPROVE, no Critical/High; addressed its one nit (dropped a dead URL.protocol check in validateClientInput). Boot-verified the client CRUD live against real Hydra v26.2.0 (create->201 w/ one-time secret -> list finds it -> get -> delete -> get null); torn down. typecheck + 274 units green.
2026-06-19 11:23:27 +02:00
partials
§10 review pass: address the architecture + product reviewers (todo §10); hide the gated Dashboard nav node from anonymous visitors in buildPluginChrome (a no-permission link to /dashboard only dead-ended them at /login) and dedup it into a shared DASHBOARD_NAV (admin-nav.ts, reused by chrome + adminNav). New chrome.signInHref bakes the current page in as return_to for the shell's anonymous Sign-in link (shell.ejs + reference overview.ejs), mirrored as optional ShellModel.signInHref so the typed builder is complete. ctx.chrome is now a lazy, memoized getter (context.ts chrome option = a factory) so a json/redirect handler or the public "/" with a standalone home never composes the global menu — app.ts passes the app-level memoized factory at every site. Default /dashboard prints a "Starter dashboard" note framing the mock-data home as a replaceable demo (signals its inert affordances); stale "until §4" comments fixed. RESERVED_PLUGIN_IDS drift-guard test derives the built-in segments from AUTH_FLOWS + ADMIN_*_BASE + host literals (home stays deliberately unreserved). Refreshed the stale plugin-contract status blurb and documented the chrome.*→partials/shell mapping. Reviewers: architecture + product APPROVE (no addressable findings remain), stability APPROVE (no Critical/High/Medium). typecheck + 356 units + visual(10) + full-flow(7) E2E green.
2026-06-21 01:19:40 +02:00
403.ejs
Make markup semantic + add semantic DOM principle (todo §1); page <h1>, skip link, row-header <th scope=row>, descriptive error pages
2026-06-15 16:53:07 +02:00
404.ejs
Make markup semantic + add semantic DOM principle (todo §1); page <h1>, skip link, row-header <th scope=row>, descriptive error pages
2026-06-15 16:53:07 +02:00
500.ejs
Make markup semantic + add semantic DOM principle (todo §1); page <h1>, skip link, row-header <th scope=row>, descriptive error pages
2026-06-15 16:53:07 +02:00
503.ejs
§9 whole-project arch+product review pass (todo §9); ran systems-architect + product-owner on the whole project (no Critical/High — a converged scaffold) and addressed the in-scope §9 customer-facing/security findings. (1) return_to deep-link login, open-redirect-safe: a gated request hit while signed out (plugin-route gate, requireSession, requireAdmin) bounces to /login?return_to=<host-relative path> via new loginRedirect(ctx) (GET/HEAD, skips /); /login bakes it into the Kratos flow — a host-relative target is wrapped through <origin>/auth/complete?return_to=<path> so the JWT mints before landing, an absolute target (§6 OAuth2 login challenge) passes to Kratos as-is; /auth/complete redirects to the requested page. (2) safeUrl()+localPath() in new pure src/safe-url.ts: safeUrl sanitises an untrusted href/src to relative-or-http(s) (else "#"), exported via plugin-api.ts (closes the contract's "planned for §9" pointer); localPath is the host-relative redirect-allowlist guard for return_to, re-checked at both /login and /auth/complete. (3) honest 503 on Ory-unreachable sign-in (views/503.ejs) instead of the misattributed catch-all 500; expired-flow 4xx still restarts. Tests-first throughout; stability-reviewer APPROVE (addressed its Medium — scoped the 503 catch so a template bug hits the 500 with a stack, not a 503). typecheck + 339 units + full scripts/ci.sh gate green. Deferred with justification: the app.ts route-table refactor (standalone change + §10 prereq), mock dashboard + public-page blessing (§10 lines 139/140), success-flash (known).
2026-06-20 16:39:09 +02:00
auth.ejs
Render SSO buttons per configured Kratos OIDC provider (todo §4); flow-view collects oidc nodes → auth-card submit buttons, server-side visibility, drop mockup #sso-toggle CSS
2026-06-17 18:20:45 +02:00
home.ejs
§10 split landing into a public "/" + gated "/dashboard", both plugin-replaceable (todo §10 follow-up); per human feedback, "/" is now an ungated public landing (default views/home.ejs: brand + intro + prominent Log in / Create account links, or "go to dashboard" when signed in) and "/dashboard" is the gated post-login app home (anonymous → /login?return_to=/dashboard). Both are fully replaceable via two optional RouteHandlers on PluginManifest — home? (public /) and dashboard? (gated /dashboard) — rendered against the plugin's own views with the native shell via ctx.chrome (full route parity: HEAD, void-return, response hooks, fresh CSRF cookie; a home handler is public so ctx.user may be null). Single-slot + loud: findConflicts errors on >1 owner of either slot (new "home"/"dashboard" kinds), discovery rejects a non-function handler, and "dashboard" is reserved so a plugin folder can't shadow it ("/" can't be shadowed — route paths carry the /<id> prefix). Post-login + already-signed-in redirects and the global Dashboard/People nav hrefs moved to /dashboard. Tests-first (348 units): public-/ + gated-/dashboard + dual plugin-override in app.test; per-slot conflict in plugin.test; non-function/reserved/two-owners in discovery.test. Docs: plugin-contract "The landing pages" section + README. E2E: visual.spec plants a session for /dashboard design-system tests + a cookie-free public-landing test; full-flow repointed to /dashboard. stability-reviewer: APPROVE, no Critical/High/Medium. typecheck + 348 units + visual(10) + full-flow(7) green.
2026-06-20 17:43:01 +02:00
index.ejs
§10 review pass: address the architecture + product reviewers (todo §10); hide the gated Dashboard nav node from anonymous visitors in buildPluginChrome (a no-permission link to /dashboard only dead-ended them at /login) and dedup it into a shared DASHBOARD_NAV (admin-nav.ts, reused by chrome + adminNav). New chrome.signInHref bakes the current page in as return_to for the shell's anonymous Sign-in link (shell.ejs + reference overview.ejs), mirrored as optional ShellModel.signInHref so the typed builder is complete. ctx.chrome is now a lazy, memoized getter (context.ts chrome option = a factory) so a json/redirect handler or the public "/" with a standalone home never composes the global menu — app.ts passes the app-level memoized factory at every site. Default /dashboard prints a "Starter dashboard" note framing the mock-data home as a replaceable demo (signals its inert affordances); stale "until §4" comments fixed. RESERVED_PLUGIN_IDS drift-guard test derives the built-in segments from AUTH_FLOWS + ADMIN_*_BASE + host literals (home stays deliberately unreserved). Refreshed the stale plugin-contract status blurb and documented the chrome.*→partials/shell mapping. Reviewers: architecture + product APPROVE (no addressable findings remain), stability APPROVE (no Critical/High/Medium). typecheck + 356 units + visual(10) + full-flow(7) E2E green.
2026-06-21 01:19:40 +02:00
oauth-consent.ejs
§6 review checkpoint (todo §6); ran the architecture + product reviewers on the whole project (weighted to the Hydra OAuth2 surfaces) and addressed their findings — no Critical from either. Fixed tests-first: (HIGH, arch) /oauth2/logout was published to Hydra (hydra.yml urls.logout) and asserted in hydra.test.ts but had no handler — a dead/published contract; added hydra-admin.acceptLogoutRequest (PUT logout/accept via the shared reqUrl(kind…)) + a GET /oauth2/logout branch that accepts the RP-initiated logout_challenge → 303 to Hydra's post-logout redirect (missing→400, stale 4xx→recoverable 400, 5xx→500, byte-identical degrade to the login/consent siblings; GET-accept is safe since the challenge is Hydra-minted+single-use; the first-party POST /logout still owns ending the Kratos session + JWT cookie). (HIGH, arch) added
oauth2
to RESERVED_PLUGIN_IDS so a plugins/oauth2/ folder can't silently shadow the provider routes (the route surface the §4 reserved-id fix missed; discovery now refuses it loud). (Product Blocker) the third-party consent screen now names the signed-in account — "Signed in as <email>" (ConsentView.account from whoami) — plus a CSRF-guarded "Not you? Sign out" form, so consent is informed on shared devices. (MEDIUM, arch) consent accept() now projects id_token claims only when the live Kratos session subject === the challenge subject Hydra bound at login, never leaking a mismatched session's email/name into the issued token (guards the auto-accept path too). (Product nits) register-form confidential-vs-public guidance + a client-detail "delete and re-register / secret shown once" note (no-edit friction + lost-secret). New tests across discovery (reserved oauth2), hydra-admin (acceptLogoutRequest contract), oauth-consent (subject-match + account-in-view), app.test (logout 303/400/500 matrix, consent identity+sign-out, client form/detail copy); e2e/oauth-login.spec asserts the consent screen names the account. Stability-reviewer run as a local PR: APPROVE, no Critical/High — addressed its doc/comment follow-ups (README §6 documents the logout handler + consent identity line; a comment notes the GET-accept is Hydra-validated). Deferred (reviewer-scoped): the host internal route-table (arch M1, now a pure dedup once H1/H2 are point-fixed) → §9; the RP-initiated-logout browser/live E2E → §8; redirect-URI scheme allowlist + safeUrl() → §7; full client edit / empty-list state / success-flash → §8/polish. typecheck + 279 units green; full-stack OAuth2 login+consent E2E verified live against real Hydra v26.2.0 then torn down.
2026-06-19 11:47:06 +02:00