@molecule/api-resource-status-page
API resource · status-page · API (Node) · v1.0.5 · Apache-2.0
Status page resource with service monitoring, incidents, and uptime
npm install @molecule/api-resource-status-pageHow it works
@molecule/api-resource-status-page is an API resource: the routes, validation and storage for status-page, built on the database and auth cores so it runs on whichever providers your app has bonded.
import { createRequestHandler } from '@molecule/api-resource'
import { createRequestHandlerMap, routes } from '@molecule/api-resource-status-page'
// The handler map is a FACTORY (like api-resource-device) — build it with
// the createRequestHandler from @molecule/api-resource (mlcl inject does this):
const requestHandlerMap = createRequestHandlerMap(createRequestHandler)
// Public reads: GET /status, GET /status/services, GET /status/services/:id,
// GET /status/incidents, GET /status/uptime
// Admin-only: POST/PATCH/DELETE /status/services(/:id),
// POST/PATCH /status/incidents(/:id)Works with: @molecule/api-bond, @molecule/api-database, @molecule/api-i18n, @molecule/api-locales-status-page, @molecule/api-resource
Live demos
Running apps built with Molecule that install this package — open the app or study the template.
Reference
Status page resource for molecule.dev.
Public status-page backend: monitored services, incidents with lifecycle updates, health-check history, and uptime windows. The read endpoints power a public status page; the mutation endpoints are for operators.
Tables this package owns: four. services is the parent; checks, incidents and
uptimeWindows each join to it on their own serviceId = services.id (a declared FK,
ON DELETE CASCADE) — that serviceId is the column every per-service query filters on.
handlers.* return { statusCode, headers?, body } and never write to res — not through
res.json, not through res.send, not through res.end. The mounted routes apply that object
for you (createRequestHandler does res.set(headers), res.status(statusCode),
res.send(body)); calling a handler directly is only correct if you apply the result yourself:
const { statusCode, headers, body } = await handlers.getStatus(resource)(req, res)
if (headers) res.set(headers)
res.status(statusCode).send(body)
Monkey-patching res.json to re-shape a handler's answer intercepts nothing the handler
produces, so the request it was meant to answer is left unanswered and hangs.
Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit
src/index.tsJSDoc, not this file.
Quick Start
import { createRequestHandler } from '@molecule/api-resource'
import { createRequestHandlerMap, routes } from '@molecule/api-resource-status-page'
// The handler map is a FACTORY (like api-resource-device) — build it with
// the createRequestHandler from @molecule/api-resource (mlcl inject does this):
const requestHandlerMap = createRequestHandlerMap(createRequestHandler)
// Public reads: GET /status, GET /status/services, GET /status/services/:id,
// GET /status/incidents, GET /status/uptime
// Admin-only: POST/PATCH/DELETE /status/services(/:id),
// POST/PATCH /status/incidents(/:id)
Type
resource
Installation
npm install @molecule/api-resource-status-page @molecule/api-bond @molecule/api-database @molecule/api-i18n @molecule/api-locales-status-page @molecule/api-monitoring @molecule/api-notifications @molecule/api-permissions @molecule/api-resource @molecule/api-scheduler zod
API
Types
ServiceProps
Full service record properties.
type ServiceProps = z.infer<typeof servicePropsSchema>
CreateServiceProps
Fields accepted when creating a new service.
type CreateServiceProps = z.infer<typeof createServicePropsSchema>
UpdateServiceProps
Updatable service fields.
type UpdateServiceProps = z.infer<typeof updateServicePropsSchema>
CheckProps
Health check result properties.
type CheckProps = z.infer<typeof checkPropsSchema>
IncidentProps
Full incident record properties.
type IncidentProps = z.infer<typeof incidentPropsSchema>
CreateIncidentProps
Fields accepted when creating a new incident.
type CreateIncidentProps = z.infer<typeof createIncidentPropsSchema>
UpdateIncidentProps
Updatable incident fields.
type UpdateIncidentProps = z.infer<typeof updateIncidentPropsSchema>
UptimeWindowProps
Uptime window statistics properties.
type UptimeWindowProps = z.infer<typeof uptimeWindowPropsSchema>
Functions
isStatusAdmin(res)
Resolves whether the current request's session belongs to an actor authorized
to administer the status page (create/update/delete services + incidents).
Fail-closed: returns false when there is no authenticated session, and
otherwise only true when the session carries an admin claim or a bonded
permissions provider grants the manage status permission.
Use this for in-handler defense-in-depth (it does not depend on the route middleware being preserved by the injector).
function isStatusAdmin(res: MoleculeResponse): Promise<boolean>
res— The response whoselocals.sessionis inspected.
Returns: true when the session is an authorized status page admin.
requireAdmin()
Route middleware that gates the admin-only status page mutation routes. Calls
next() only for an authenticated status page admin; otherwise forwards an
error to the framework error handler — Unauthorized when no session is
present, Forbidden when the session is authenticated but not authorized to
manage the status page.
Exposed as a request-handler-map key so the injector's route scanner keeps it
(unlike the inert global 'auth' string, which is dropped).
function requireAdmin(): MoleculeRequestHandler
Returns: An Express-compatible middleware function.
createRequestHandlerMap(createRequestHandler)
Creates the full request handler map for the Status resource. Maps handler names
(matching route definitions) to Express middleware via createRequestHandler.
requireAdmin is the status-management authorizer middleware referenced by the
mutating routes (createService/updateService/deleteService/createIncident/
updateIncident). It must live here as a real handler-map key so the mlcl
injector's route scanner preserves it — a bare middleware string that isn't a
handler-map key is silently dropped (which is why the previous 'auth' gate was
inert and the mutating routes shipped public). It is already an Express
middleware, so it is NOT wrapped in createRequestHandler.
function createRequestHandlerMap(
createRequestHandler: (
handler: Handler,
) => (req: MoleculeRequest, res: MoleculeResponse, next: MoleculeNextFunction) => Promise<void>,
): Record<string, MoleculeRequestHandler>
createRequestHandler— Factory from@molecule/api-resourcethat wraps handler configs into Express middleware.
Returns: A record mapping handler names to Express middleware functions.
createResource()
Creates a new status resource definition.
function createResource(): types.Resource<unknown>
Returns: The status resource descriptor with name, tableName, and schema.
Constants
STATUS_PERMISSION_ACTION
Permission action checked against @molecule/api-permissions for status page
administration.
const STATUS_PERMISSION_ACTION: 'manage'
STATUS_PERMISSION_RESOURCE
Permission resource checked against @molecule/api-permissions for status page
administration.
const STATUS_PERMISSION_RESOURCE: 'status'
STATUS_ADMIN_PERMISSION
Session-claim permission string ('status:manage') that, when present in a
session's permissions array, grants status page administration without a
bonded permissions provider.
const STATUS_ADMIN_PERMISSION: 'status:manage'
i18nNamespace
The i18n namespace for the status resource.
const i18nNamespace: 'status'
i18nRegistered
The i18n registered.
const i18nRegistered: true
resource
The status resource definition.
const resource: types.Resource<unknown>
routes
Route array for status page endpoints: public read routes and admin-gated mutation routes.
const routes: (
| { method: 'get'; path: string; middlewares: never[]; handler: string }
| { method: 'post'; path: string; middlewares: string[]; handler: string }
| { method: 'patch'; path: string; middlewares: string[]; handler: string }
| { method: 'delete'; path: string; middlewares: string[]; handler: string }
)[]
servicePropsSchema
Full schema for a monitored service.
const servicePropsSchema: z.ZodObject<
{
id: z.ZodString
createdAt: z.ZodString
updatedAt: z.ZodString
name: z.ZodString
url: z.ZodString
method: z.ZodDefault<z.ZodEnum<{ GET: 'GET'; HEAD: 'HEAD'; POST: 'POST' }>>
expectedStatus: z.ZodDefault<z.ZodNumber>
timeoutMs: z.ZodDefault<z.ZodNumber>
intervalMs: z.ZodDefault<z.ZodNumber>
groupName: z.ZodOptional<z.ZodString>
enabled: z.ZodDefault<z.ZodBoolean>
},
z.core.$strip
>
createServicePropsSchema
Schema for creating a new service.
const createServicePropsSchema: z.ZodObject<
{
name: z.ZodString
url: z.ZodString
method: z.ZodDefault<z.ZodEnum<{ GET: 'GET'; HEAD: 'HEAD'; POST: 'POST' }>>
expectedStatus: z.ZodDefault<z.ZodNumber>
timeoutMs: z.ZodDefault<z.ZodNumber>
intervalMs: z.ZodDefault<z.ZodNumber>
groupName: z.ZodOptional<z.ZodString>
enabled: z.ZodDefault<z.ZodBoolean>
},
z.core.$strip
>
updateServicePropsSchema
Schema for updating an existing service (all fields optional).
const updateServicePropsSchema: z.ZodObject<
{
name: z.ZodOptional<z.ZodString>
url: z.ZodOptional<z.ZodString>
method: z.ZodOptional<z.ZodDefault<z.ZodEnum<{ GET: 'GET'; HEAD: 'HEAD'; POST: 'POST' }>>>
expectedStatus: z.ZodOptional<z.ZodDefault<z.ZodNumber>>
timeoutMs: z.ZodOptional<z.ZodDefault<z.ZodNumber>>
intervalMs: z.ZodOptional<z.ZodDefault<z.ZodNumber>>
groupName: z.ZodOptional<z.ZodOptional<z.ZodString>>
enabled: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>
},
z.core.$strip
>
checkPropsSchema
Schema for a single health check result.
const checkPropsSchema: z.ZodObject<
{
id: z.ZodString
serviceId: z.ZodString
status: z.ZodEnum<{ up: 'up'; down: 'down'; degraded: 'degraded' }>
httpStatus: z.ZodOptional<z.ZodNumber>
latencyMs: z.ZodOptional<z.ZodNumber>
error: z.ZodOptional<z.ZodString>
checkedAt: z.ZodString
},
z.core.$strip
>
incidentPropsSchema
Full schema for a service incident.
const incidentPropsSchema: z.ZodObject<
{
id: z.ZodString
createdAt: z.ZodString
updatedAt: z.ZodString
serviceId: z.ZodString
title: z.ZodString
description: z.ZodOptional<z.ZodString>
severity: z.ZodEnum<{ minor: 'minor'; major: 'major'; critical: 'critical' }>
status: z.ZodEnum<{
investigating: 'investigating'
identified: 'identified'
monitoring: 'monitoring'
resolved: 'resolved'
}>
autoDetected: z.ZodDefault<z.ZodBoolean>
startedAt: z.ZodString
resolvedAt: z.ZodOptional<z.ZodString>
},
z.core.$strip
>
createIncidentPropsSchema
Schema for creating a new incident.
const createIncidentPropsSchema: z.ZodObject<
{
serviceId: z.ZodString
title: z.ZodString
description: z.ZodOptional<z.ZodString>
severity: z.ZodEnum<{ minor: 'minor'; major: 'major'; critical: 'critical' }>
status: z.ZodEnum<{
investigating: 'investigating'
identified: 'identified'
monitoring: 'monitoring'
resolved: 'resolved'
}>
autoDetected: z.ZodDefault<z.ZodBoolean>
startedAt: z.ZodString
},
z.core.$strip
>
updateIncidentPropsSchema
Schema for updating an existing incident (all fields optional).
const updateIncidentPropsSchema: z.ZodObject<
{
title: z.ZodOptional<z.ZodString>
description: z.ZodOptional<z.ZodOptional<z.ZodString>>
severity: z.ZodOptional<z.ZodEnum<{ minor: 'minor'; major: 'major'; critical: 'critical' }>>
status: z.ZodOptional<
z.ZodEnum<{
investigating: 'investigating'
identified: 'identified'
monitoring: 'monitoring'
resolved: 'resolved'
}>
>
resolvedAt: z.ZodOptional<z.ZodOptional<z.ZodString>>
},
z.core.$strip
>
uptimeWindowPropsSchema
Schema for a pre-computed uptime statistics window.
const uptimeWindowPropsSchema: z.ZodObject<
{
id: z.ZodString
serviceId: z.ZodString
window: z.ZodEnum<{ '1h': '1h'; '24h': '24h'; '7d': '7d'; '30d': '30d'; '90d': '90d' }>
uptimePct: z.ZodNumber
totalChecks: z.ZodNumber
upChecks: z.ZodNumber
avgLatencyMs: z.ZodNumber
},
z.core.$strip
>
Namespaces
z
Re-exports the zod module — z.<name> is exactly zod.<name>, documented by that package (installed at node_modules/zod).
handlers
Re-exported as a namespace — reach every member below through it (e.g. handlers.<name>).
handlers.createIncident(_resource)
Creates a new incident record. Validates the request body against the create incident schema before inserting.
function createIncident({ tableName: _tableName }: { tableName: string }): (
req: MoleculeRequest,
res: MoleculeResponse,
) => Promise<
| { statusCode: number; body: { error: string; errorKey: string; props?: undefined } }
| {
statusCode: number
body: {
props: {
id: string
createdAt: string
updatedAt: string
serviceId: string
title: string
severity: 'minor' | 'major' | 'critical'
status: 'investigating' | 'identified' | 'monitoring' | 'resolved'
autoDetected: boolean
startedAt: string
description?: string | undefined
resolvedAt?: string | undefined
} | null
error?: undefined
errorKey?: undefined
}
}
>
_resource— The service resource configuration (unused)._resource.tableName— The database table name for services.
Returns: A request handler that creates an incident and responds with the created record.
handlers.createService(resource)
Creates a new monitored service. Validates the request body against the create service schema before inserting into the database.
function createService({ tableName }: { tableName: string }): (
req: MoleculeRequest,
res: MoleculeResponse,
) => Promise<
| { statusCode: number; body: { error: string; errorKey: string; props?: undefined } }
| {
statusCode: number
body: {
props: {
id: string
createdAt: string
updatedAt: string
name: string
url: string
method: 'GET' | 'HEAD' | 'POST'
expectedStatus: number
timeoutMs: number
intervalMs: number
enabled: boolean
groupName?: string | undefined
} | null
error?: undefined
errorKey?: undefined
}
}
>
resource— The service resource configuration.resource.tableName— The database table name for services.
Returns: A request handler that creates a service and responds with the created record.
handlers.deleteService(resource)
Deletes a monitored service by ID. Returns 404 if the service does not exist. Associated checks, incidents, and uptime windows are removed via CASCADE.
function deleteService({
tableName,
}: {
tableName: string
}): (
req: MoleculeRequest,
res: MoleculeResponse,
) => Promise<
| { statusCode: number; body: { error: string; errorKey: string; props?: undefined } }
| { statusCode: number; body: { props: { id: string }; error?: undefined; errorKey?: undefined } }
>
resource— The service resource configuration.resource.tableName— The database table name for services.
Returns: A request handler that deletes a service and responds with 204 on success.
handlers.getService(resource)
Returns a single service by ID along with the last 50 check results.
function getService({ tableName }: { tableName: string }): (req: MoleculeRequest) => Promise<
| { statusCode: number; body: { error: string; errorKey: string; props?: undefined } }
| {
statusCode: number
body: {
props: {
recentChecks: {
id: string
serviceId: string
status: 'up' | 'down' | 'degraded'
checkedAt: string
httpStatus?: number | undefined
latencyMs?: number | undefined
error?: string | undefined
}[]
id: string
createdAt: string
updatedAt: string
name: string
url: string
method: 'GET' | 'HEAD' | 'POST'
expectedStatus: number
timeoutMs: number
intervalMs: number
enabled: boolean
groupName?: string | undefined
}
error?: undefined
errorKey?: undefined
}
}
>
resource— The service resource configuration.resource.tableName— The database table name for services.
Returns: A request handler that responds with a service and its recent checks.
handlers.getStatus(resource)
Returns the aggregated system health status.
Finds all enabled services, fetches the latest check for each,
and computes an overall status: operational, degraded, or down.
function getStatus({ tableName }: { tableName: string }): (_req: MoleculeRequest) => Promise<
| {
statusCode: number
body: {
status: 'down' | 'degraded' | 'operational'
services: { id: string; name: string; status: string; latencyMs: number | null }[]
checkedAt: string
error?: undefined
errorKey?: undefined
}
}
| {
statusCode: number
body: {
error: string
errorKey: string
status?: undefined
services?: undefined
checkedAt?: undefined
}
}
>
resource— The service resource configuration.resource.tableName— The database table name for services.
Returns: A request handler that responds with overall system status.
handlers.getUptime(_resource)
Returns uptime window statistics for all services, or filtered by
?serviceId= query parameter for a specific service.
function getUptime({ tableName: _tableName }: { tableName: string }): (
req: MoleculeRequest,
) => Promise<
| {
statusCode: number
body: {
id: string
serviceId: string
window: '1h' | '24h' | '7d' | '30d' | '90d'
uptimePct: number
totalChecks: number
upChecks: number
avgLatencyMs: number
}[]
}
| { statusCode: number; body: { error: string; errorKey: string } }
>
_resource— The service resource configuration (unused)._resource.tableName— The database table name for services.
Returns: A request handler that responds with uptime window records.
handlers.listIncidents(_resource)
Lists incidents with support for ?status= filtering and pagination
via ?limit= and ?offset= query parameters.
function listIncidents({ tableName: _tableName }: { tableName: string }): (
req: MoleculeRequest,
) => Promise<
| {
statusCode: number
body: {
id: string
createdAt: string
updatedAt: string
serviceId: string
title: string
severity: 'minor' | 'major' | 'critical'
status: 'investigating' | 'identified' | 'monitoring' | 'resolved'
autoDetected: boolean
startedAt: string
description?: string | undefined
resolvedAt?: string | undefined
}[]
}
| { statusCode: number; body: { error: string; errorKey: string } }
>
_resource— The service resource configuration (unused)._resource.tableName— The database table name for services.
Returns: A request handler that responds with a paginated array of incidents.
handlers.listServices(resource)
Lists all services along with each service's latest check result.
function listServices({ tableName }: { tableName: string }): (_req: MoleculeRequest) => Promise<
| {
statusCode: number
body: {
latestCheck: {
id: string
serviceId: string
status: 'up' | 'down' | 'degraded'
checkedAt: string
httpStatus?: number | undefined
latencyMs?: number | undefined
error?: string | undefined
}
id: string
createdAt: string
updatedAt: string
name: string
url: string
method: 'GET' | 'HEAD' | 'POST'
expectedStatus: number
timeoutMs: number
intervalMs: number
enabled: boolean
groupName?: string | undefined
}[]
}
| { statusCode: number; body: { error: string; errorKey: string } }
>
resource— The service resource configuration.resource.tableName— The database table name for services.
Returns: A request handler that responds with an array of services and their latest check.
handlers.updateIncident(_resource)
Updates an existing incident by ID. Validates the request body against the update incident schema (all fields optional) before patching.
function updateIncident({ tableName: _tableName }: { tableName: string }): (
req: MoleculeRequest,
res: MoleculeResponse,
) => Promise<
| { statusCode: number; body: { error: string; errorKey: string; props?: undefined } }
| {
statusCode: number
body: {
props: {
id: string
createdAt: string
updatedAt: string
serviceId: string
title: string
severity: 'minor' | 'major' | 'critical'
status: 'investigating' | 'identified' | 'monitoring' | 'resolved'
autoDetected: boolean
startedAt: string
description?: string | undefined
resolvedAt?: string | undefined
} | null
error?: undefined
errorKey?: undefined
}
}
>
_resource— The service resource configuration (unused)._resource.tableName— The database table name for services.
Returns: A request handler that updates an incident and responds with the updated record.
handlers.updateService(resource)
Updates an existing monitored service by ID. Validates the request body against the update service schema (all fields optional) before patching.
function updateService({ tableName }: { tableName: string }): (
req: MoleculeRequest,
res: MoleculeResponse,
) => Promise<
| { statusCode: number; body: { error: string; errorKey: string; props?: undefined } }
| {
statusCode: number
body: {
props: {
id: string
createdAt: string
updatedAt: string
name: string
url: string
method: 'GET' | 'HEAD' | 'POST'
expectedStatus: number
timeoutMs: number
intervalMs: number
enabled: boolean
groupName?: string | undefined
} | null
error?: undefined
errorKey?: undefined
}
}
>
resource— The service resource configuration.resource.tableName— The database table name for services.
Returns: A request handler that updates a service and responds with the updated record.
types
Re-exported as a namespace — reach every member below through it (e.g. types.<name>).
types.ServiceProps
Full service record properties.
type ServiceProps = z.infer<typeof servicePropsSchema>
types.CreateServiceProps
Fields accepted when creating a new service.
type CreateServiceProps = z.infer<typeof createServicePropsSchema>
types.UpdateServiceProps
Updatable service fields.
type UpdateServiceProps = z.infer<typeof updateServicePropsSchema>
types.CheckProps
Health check result properties.
type CheckProps = z.infer<typeof checkPropsSchema>
types.IncidentProps
Full incident record properties.
type IncidentProps = z.infer<typeof incidentPropsSchema>
types.CreateIncidentProps
Fields accepted when creating a new incident.
type CreateIncidentProps = z.infer<typeof createIncidentPropsSchema>
types.UpdateIncidentProps
Updatable incident fields.
type UpdateIncidentProps = z.infer<typeof updateIncidentPropsSchema>
types.UptimeWindowProps
Uptime window statistics properties.
type UptimeWindowProps = z.infer<typeof uptimeWindowPropsSchema>
types.Resource
An object describing the status resource.
type Resource<T = unknown> = resourceTypes.Resource<T>
Injection Notes
Requirements
Peer dependencies:
@molecule/api-bond^1.0.1@molecule/api-database^1.0.1@molecule/api-i18n^1.0.1@molecule/api-monitoring^1.0.1@molecule/api-notifications^1.0.1@molecule/api-permissions^1.0.1@molecule/api-resource^1.0.1@molecule/api-scheduler^1.0.1@molecule/api-locales-status-page^1.0.1
Runtime Dependencies
@molecule/api-bond@molecule/api-database@molecule/api-i18n@molecule/api-locales-status-page@molecule/api-monitoring@molecule/api-notifications@molecule/api-permissions@molecule/api-resource@molecule/api-schedulerzod
The GET routes are PUBLIC by design — a status page is a public surface; do
not put them behind auth. The mutating routes are ADMIN-ONLY and DENY by
default: they are gated by the requireAdmin middleware AND re-checked
inside every mutation handler via isStatusAdmin — fail-closed
defense-in-depth that holds even if a route scanner drops the middleware.
"Admin" resolves as: an admin session claim (isAdmin: true,
role: 'admin', roles containing 'admin', or a 'status:manage' /
'admin' entry in session.permissions) OR a bonded
@molecule/api-permissions grant of manage on status. Until the app
grants one of those, every mutation is denied — grant the claim/permission
at startup, do NOT strip the gate: an open mutation surface lets any caller
deface the public status page (fabricate outages, delete services).
Handler text flows through t() with English defaults; the companion
locale bond @molecule/api-locales-status-page provides translations.
Tables: src/__setup__/*.sql creates services, incidents, checks, and
uptimeWindows. An mlcl-scaffolded API replays these setup files
automatically on migrate; anywhere else run them once — nothing at runtime
creates them.
E2E Tests
Integration checklist — drive the real UI (live preview, no mocks), adapt each item to this app's actual status-page screens/flows, and check every box off one by one. A box you can't check is an integration bug to fix — not a skip. Verify BEHAVIOR and the public/admin split, not just that CRUD compiles:
- The PUBLIC status page renders every monitored service (component)
with its current status and an OVERALL banner that is DERIVED, never
hardcoded: GET /status returns
operationalwhen no enabled service's latestcheckisdownordegraded("All systems operational"),downif ANY latest check isdown, elsedegradedif any isdegraded— the banner reflects the WORST service, and a service with no check readsunknown(which never turns the banner red). GET /status/services lists each service with its latest check. - An admin creating an INCIDENT (POST /status/incidents with serviceId,
title, severity minor|major|critical, status
investigating, startedAt) persists it and it shows on the public GET /status/incidents. The affected service reads down/degraded on the page because its latestchecksays so (checks are monitor-written, never typed in), so the overall banner goes non-green while the incident is open. - Updating the incident (PATCH /status/incidents/:id) advances its
timeline through the real lifecycle investigating -> identified ->
monitoring -> resolved (bumping updatedAt), and each stage shows on the
public page. Marking it
resolved(with resolvedAt) moves it to history — the public list filtered?status=resolvedincludes it while the active incidents drop it — and once the affected service's latest check returns toup, GET /status recovers to "All systems operational" (the banner tracks live check state, so a still-down check keeps it red). - AUTHORIZATION — reads are PUBLIC: with NO session, every GET (/status, /status/services, /status/services/:id, /status/incidents, /status/uptime) returns 200 — the status page is meant to be seen without signing in.
- AUTHORIZATION — writes are ADMIN-ONLY, deny by default: every mutation
(POST/PATCH/DELETE /status/services(/:id), POST/PATCH
/status/incidents(/:id)) is refused for an anonymous caller (401) and for
a normal signed-in user with no admin claim /
manage statusgrant (403), and nothing changes — enforced twice (therequireAdminroute middleware AND the in-handlerisStatusAdminre-check). A non-admin has NO path to fabricate an outage, delete a service, or post a fake incident, and no endpoint sets a service up/down at all (that is monitor-written).