Scope My shifts at the upstream, and give Route and NavNode one gate declaration
CI / full-gate (push) Successful in 2m56s

This commit is contained in:
2026-09-02 08:15:08 +02:00
parent 8da75b4ca7
commit c7e6d66750
9 changed files with 51 additions and 32 deletions
+1
View File
@@ -39,6 +39,7 @@ export { CSRF_FIELD } from "../auth/csrf.ts";
// reference consumer. The Ory client types + their error classes are re-exported so a system
// plugin can type against them and `instanceof`-match their errors. See README → System capabilities.
export type { SystemCapabilities } from "./system.ts";
export type { Gate } from "../auth/gate.ts";
export type { Identity, KratosAdmin, RecoveryCode } from "../auth/kratos-admin.ts";
export type { ExpandTree, KetoClient, RelationQuery, RelationTuple, SubjectSet } from "../auth/keto-client.ts";
export type { HydraAdmin, OAuth2Client } from "../auth/hydra-admin.ts";
+3 -8
View File
@@ -4,6 +4,7 @@
// A plugin's identity is its folder under plugins/: folder name = `id` (isValidPluginId), mount =
// `/<id>`. Neither is in the manifest — the host derives them, so they can't drift or be claimed twice.
import type { Gate } from "../auth/gate.ts";
import type { RequestContext } from "../http/context.ts";
import type { NavNode } from "../ui/nav.ts";
import { envName, type SettingDecl, type SettingsOf } from "./settings.ts";
@@ -24,17 +25,11 @@ export type RouteResult =
export type RouteHandler = (ctx: RequestContext) => Promise<RouteResult | void> | RouteResult | void;
export interface Route {
// `Gate` carries `permission`/`public`/`session`, checked before the handler runs.
export interface Route extends Gate {
handler: RouteHandler;
method: HttpMethod;
path: string; // relative to the plugin's mount path `/<id>`; ":name" segments → ctx.params.name
permission?: string; // coarse gate — the Keto Permission the caller must hold; checked before the handler runs
// Same as omitting `permission`, but stated outright so public is a deliberate choice rather than
// a forgotten gate. Mutually exclusive with `permission` (discovery refuses both).
public?: boolean;
// Any signed-in user, no grant to hold — for a plugin whose data is the visitor's own. Anonymous
// is bounced to /login, never 403. Mutually exclusive with the other two (discovery refuses both).
session?: boolean;
}
// A Keto Permission this plugin gates on — declared for docs/seeding. Names are a shared global