Files
technitium-console/hub/routes.ts
T
DenozordecandClaude Opus 5.5 3d8df08fa0 Hub stage 1: apps across servers, read-only
hub/apps/matrix reads apps/list and each app's config on every server (the read
token first, the admin token once if a server refuses) and returns per app and server
the version, available update and a config hash, plus whether versions and configs
match and how many JSON leaf paths differ. Config texts never leave the hub. In hub
mode the Apps section has the server selector: All servers shows the matrix with
filters for differing versions, differing configs and updates; one server shows its
list without write actions. The dev mock takes --variant a|b with differing apps.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-31 15:46:51 +07:00

40 lines
1.3 KiB
TypeScript

/*
What each `/api/<path>` does and who may call it. `kind` says what it touches:
`read` (no change), `write-one` (changes one server) and `write-all` (changes every server).
A path that is not listed is refused. Today every entry is a read.
Not in the table: `status`, `user/login`, `user/session/get` and `user/logout`, which the
server answers itself before the table is consulted.
*/
import type { Capability } from './users.ts'
export type RouteKind = 'read' | 'write-one' | 'write-all'
export interface Route {
kind: RouteKind
capability: Capability
}
const read = (capability: Capability = 'read'): Route => ({ kind: 'read', capability })
export const ROUTES: Record<string, Route> = {
'dashboard/stats/get': read(),
'dashboard/stats/getTop': read(),
'dashboard/metrics/json': read(),
'apps/list': read(),
'logs/query': read(),
'logs/list': read(),
'settings/get': read(),
'user/checkForUpdate': read(),
'admin/cluster/state': read(),
// The hub's own namespace; never forwarded to a server.
'hub/audit/list': read('audit.read'),
'hub/apps/matrix': read(),
}
export function routeFor(apiPath: string): Route | undefined {
return Object.hasOwn(ROUTES, apiPath) ? ROUTES[apiPath] : undefined
}
export const isHubPath = (apiPath: string): boolean => apiPath.startsWith('hub/')