Correct the stale and false comments and docs the comprehension seats flagged
CI / full-gate (push) Successful in 3m40s
CI / full-gate (push) Successful in 3m40s
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
// One-command bootstrap (the MVP bar). One-shot compose service: runs after
|
||||
// kratos+keto are healthy (web waits on it), idempotent on every `docker compose up`:
|
||||
// 1. generate the JWKS signing key if absent (committed dev key makes this a safety net);
|
||||
// 2. seed a demo admin (admin@plainpages.local / admin) in Kratos;
|
||||
// 3. grant it its permissions in Keto so menu/permission checks resolve out of the box — every
|
||||
// 2. create a database and login role for each discovered plugin that declares storage;
|
||||
// 3. seed a demo admin (admin@plainpages.local / admin) in Kratos;
|
||||
// 4. grant it its permissions in Keto so menu/permission checks resolve out of the box — every
|
||||
// discovered plugin's declared permission names (plus any ADMIN_PERMISSIONS), so a dropped-in
|
||||
// plugin is usable by the demo admin with no host config edit (the host stays plugin-agnostic).
|
||||
// Then prints a first-run banner; fails loud on any unexpected upstream error.
|
||||
|
||||
+3
-2
@@ -4,8 +4,9 @@ import type { JsonWebKey } from "./jwks.ts";
|
||||
|
||||
// JWS signature verification with the Node stdlib — no `jose`/JWT dep:
|
||||
// `createPublicKey({format:"jwk"})` imports a JWK and verifies the RS*/ES* signatures
|
||||
// the Kratos tokenizer produces (see AGENTS.md). Signature only — adds claim checks
|
||||
// (exp/iss/aud, clock skew), JWKS-by-`kid` fetch/cache/rotation, and `token` bounds.
|
||||
// the Kratos tokenizer produces (see AGENTS.md). Signature only: the caller
|
||||
// (`jwt-middleware.ts`) adds claim checks (exp/iss/aud, clock skew) and picks the key by `kid`
|
||||
// from the cached JWKS (`jwks.ts` fetches and rotates it).
|
||||
|
||||
// JOSE `alg` → Node verify parameters. ES* signatures are raw r‖s (IEEE P1363), not DER.
|
||||
// Extend this map to widen support. Security invariant: never add `HS*`/`none` — this map
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@ export interface CompletedLogin {
|
||||
// The coarse permissions a user holds — directly (`Permission:<name>#granted@user:<id>`) or transitively via a
|
||||
// group granted the permission. Enumerates the defined permissions (the distinct objects in the Permission
|
||||
// namespace) and asks Keto to check each grant, so a permission granted to a group reaches the JWT —
|
||||
// matching the OPL model and the admin "Effective access" view. At login/refresh only, never per
|
||||
// matching the OPL model. At login/refresh only, never per
|
||||
// request; permission count is small, so the per-permission checks are cheap and run in parallel.
|
||||
export async function readPermissions(keto: KetoClient, userId: string): Promise<string[]> {
|
||||
const subject_id = `user:${userId}`;
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
// Router: pure core mapping method + pathname → a discovered plugin route. I/O-free;
|
||||
// app.ts is the shell (build context, gate, call handler, render RouteResult). A route mounts at
|
||||
// `/<id>` + its path (fullPath, shared with conflict detection); `:name` segments → path params.
|
||||
// Specificity: a literal segment beats a `:param` (/users/new wins /users/:id), order-independent.
|
||||
// Specificity: the route with fewer `:param` segments wins (/users/new beats /users/:id). A tie, such
|
||||
// as /a/:x/b against /a/b/:y, falls to discovery order.
|
||||
|
||||
import { fullPath, type Plugin, type Route } from "./plugin.ts";
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// System capabilities: privileged host services a first-party/system plugin (the built-in admin
|
||||
// screens are the reference consumer) needs but an ordinary domain plugin does not — the Ory admin
|
||||
// System capabilities: privileged host services a first-party/system plugin (the `auth-admin`
|
||||
// example plugin is the reference consumer) needs but an ordinary domain plugin does not — the Ory admin
|
||||
// clients and the instant-revoke hook. Exposed on ctx.system and re-exported via @plainpages/plugin-api.
|
||||
//
|
||||
// Every field is optional: it is present only when the host wired that dependency (Ory configured,
|
||||
|
||||
+2
-2
@@ -66,7 +66,7 @@ export function buildPluginChrome(opts: ChromeOptions): PageChrome {
|
||||
const nav = composeNav(fragments, opts.menu.override, opts.user ?? null, t);
|
||||
if (opts.currentPath) {
|
||||
// Mark by the *best* (longest) href that is the path or a parent of it, so a sub-path like
|
||||
// /admin/users/new marks the Users base leaf (/admin/users) and the dashboard marks Dashboard.
|
||||
// /auth-admin/users/new marks the Users base leaf (/auth-admin/users) and the dashboard marks Dashboard.
|
||||
// Marked before the locale rides along, so an href still matches the plain request path.
|
||||
const target = bestHref(nav, opts.currentPath);
|
||||
if (target) markCurrent(nav, target);
|
||||
@@ -140,7 +140,7 @@ function carryLocaleInto(nodes: NavNode[], carryLocale: (href: string) => string
|
||||
}
|
||||
|
||||
// The href of the leaf that owns `path`: an exact match, else the longest href that is a parent of
|
||||
// it (href + "/" prefixes path), so /admin/users/123 resolves to the /admin/users leaf. "/" never
|
||||
// it (href + "/" prefixes path), so /auth-admin/users/123 resolves to the /auth-admin/users leaf. "/" never
|
||||
// counts as a parent (it would own everything). Returns undefined when nothing matches.
|
||||
function bestHref(nodes: NavNode[], path: string): string | undefined {
|
||||
let best: string | undefined;
|
||||
|
||||
Reference in New Issue
Block a user