List the endpoints the panel had stopped keeping up with

The Overview's tables documented 31 routes where the server serves 53. Everything
added since the plugin cascade went in was simply absent: the logbook, the fleet,
documents, and the integrations surface itself.

Cross-checked against every mux.HandleFunc in server.go, so the only routes left
unlisted are GET /assets/ and GET /favicon.svg — the panel serving itself.

Two judgement calls worth naming:

The integrations triplet is written once as /api/integrations/{plugin} with the
five plugin names in the description, rather than seventeen near-identical rows.
The routes are registered individually, not by wildcard, so that path is an
abstraction the server would not match — flagged in a comment above the list.

/api/health and /api/status are public and belong to no audience in particular.
They sit beside /healthz, which was already in the Device table, retitled
"Device uplink · public" rather than mint a table for three rows.

Logbook/fleet and documents each get their own table, mirroring how the Web App's
nav splits them.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
tajniak81
2026-07-16 18:48:00 +02:00
co-authored by Claude Opus 4.8
parent 183c83c177
commit 11fb1e060d
4 changed files with 65 additions and 21 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="theme-color" content="#0F1E3D" /> <meta name="theme-color" content="#0F1E3D" />
<title>PilotVault · API Server</title> <title>PilotVault · API Server</title>
<script type="module" crossorigin src="/assets/index-Dh-j3HLZ.js"></script> <script type="module" crossorigin src="/assets/index-B3oSnK0w.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-4CKxSIBg.css"> <link rel="stylesheet" crossorigin href="/assets/index-4CKxSIBg.css">
</head> </head>
<body> <body>
+47 -3
View File
@@ -854,6 +854,43 @@ const clientApi = [
{ method: "GET", path: "/ws/ui", desc: "Live telemetry stream (WebSocket)" }, { method: "GET", path: "/ws/ui", desc: "Live telemetry stream (WebSocket)" },
]; ];
// Logbook + fleet — the pilot's drones and flight records (BEK 1649 §5).
// Every route is scoped in Go: a user sees their own flights and their org's
// drones, an admin their whole org, a superadmin everything.
const logbookApi = [
{ method: "GET", path: "/api/drones", desc: "List the fleet in scope" },
{ method: "POST", path: "/api/drones", desc: "Register a drone by hand" },
{ method: "POST", path: "/api/drones/auto", desc: "Upsert the drone a device just connected, keyed on its flight controller's serial" },
{ method: "PATCH", path: "/api/drones/{id}", desc: "Edit a drone (whole-record write)" },
{ method: "DELETE", path: "/api/drones/{id}", desc: "Delete a drone" },
{ method: "GET", path: "/api/flights", desc: "List flight records in scope" },
{ method: "POST", path: "/api/flights", desc: "Log a flight" },
{ method: "PATCH", path: "/api/flights/{id}", desc: "Edit a flight record" },
{ method: "DELETE", path: "/api/flights/{id}", desc: "Delete a flight record" },
{ method: "GET", path: "/api/logbook/export", desc: "Export the logbook as CSV, compliance flags included" },
];
// Documents — the operator's document store (certificates, insurance, permits),
// with expiry alerting. File blobs live on PocketBase.
const documentsApi = [
{ method: "GET", path: "/api/documents", desc: "List documents (?expiring filters to those near expiry)" },
{ method: "POST", path: "/api/documents", desc: "Upload a document (multipart)" },
{ method: "PATCH", path: "/api/documents/{id}", desc: "Edit a document, or replace its file" },
{ method: "DELETE", path: "/api/documents/{id}", desc: "Delete a document" },
{ method: "GET", path: "/api/documents/{id}/file", desc: "Stream a document's file down" },
];
// Plugin integrations for end users. Each plugin is routed explicitly rather
// than by wildcard; {plugin} here stands for the five that exist today.
// Settings resolve through the superadmin → org → user cascade, per field.
const integrationsApi = [
{ method: "GET", path: "/api/integrations/{plugin}", desc: "Resolved settings + per-field lock state (opensky · filetransfer · localstorage · webdav · openweather)" },
{ method: "PUT", path: "/api/integrations/{plugin}", desc: "Save settings at a scope ({scope: user | org}; org needs admin)" },
{ method: "POST", path: "/api/integrations/{plugin}/health", desc: "Probe the plugin with the caller's resolved config" },
{ method: "GET", path: "/api/integrations/opensky/states", desc: "Live aircraft state vectors for a bbox (map overlay)" },
{ method: "GET", path: "/api/integrations/openweather/current", desc: "Current weather + 5-day forecast for a point" },
];
// Management API — user + organization management. Requires a manager // Management API — user + organization management. Requires a manager
// (admin or superadmin) token; admins are scoped to their own organization, // (admin or superadmin) token; admins are scoped to their own organization,
// superadmins span all of them. // superadmins span all of them.
@@ -871,16 +908,20 @@ const managementApi = [
{ method: "PUT", path: "/api/admin/pb-config", desc: "Update + persist the PocketBase connection (superadmin)" }, { method: "PUT", path: "/api/admin/pb-config", desc: "Update + persist the PocketBase connection (superadmin)" },
{ method: "GET", path: "/api/admin/plugins", desc: "List plugins + state + last health (superadmin)" }, { method: "GET", path: "/api/admin/plugins", desc: "List plugins + state + last health (superadmin)" },
{ method: "POST", path: "/api/admin/plugins", desc: "Register an external plugin {name, baseURL} (superadmin)" }, { method: "POST", path: "/api/admin/plugins", desc: "Register an external plugin {name, baseURL} (superadmin)" },
{ method: "GET", path: "/api/admin/plugins/{name}", desc: "Read one plugin's state + config (superadmin)" },
{ method: "PUT", path: "/api/admin/plugins/{name}", desc: "Enable/disable + configure a plugin (superadmin)" }, { method: "PUT", path: "/api/admin/plugins/{name}", desc: "Enable/disable + configure a plugin (superadmin)" },
{ method: "DELETE", path: "/api/admin/plugins/{name}", desc: "Remove an external plugin (superadmin)" }, { method: "DELETE", path: "/api/admin/plugins/{name}", desc: "Remove an external plugin (superadmin)" },
{ method: "POST", path: "/api/admin/plugins/{name}/health", desc: "Run a plugin health check (superadmin)" }, { method: "POST", path: "/api/admin/plugins/{name}/health", desc: "Run a plugin health check (superadmin)" },
]; ];
// Device API — used by the Fly App running on the drone/controller. // Device API — used by the Fly App running on the drone/controller — plus the
// health/status routes, which are public and belong to no audience in particular.
const deviceApi = [ const deviceApi = [
{ method: "GET", path: "/ws/device?id={id}", desc: "Device telemetry uplink (WebSocket)" }, { method: "GET", path: "/ws/device?id={id}", desc: "Device telemetry uplink (WebSocket)" },
{ method: "POST", path: "/api/telemetry?id={id}", desc: "Push a single telemetry event over HTTP" }, { method: "POST", path: "/api/telemetry?id={id}", desc: "Push a single telemetry event over HTTP" },
{ method: "GET", path: "/healthz", desc: "Readiness probe" }, { method: "GET", path: "/healthz", desc: "Readiness probe (public)" },
{ method: "GET", path: "/api/health", desc: "Readiness probe, same answer under the /api prefix (public)" },
{ method: "GET", path: "/api/status", desc: "Server status + PocketBase reachability (public)" },
]; ];
</script> </script>
@@ -1013,8 +1054,11 @@ const deviceApi = [
</div> </div>
<EndpointTable title="Client API" auth="PocketBase session" :endpoints="clientApi" /> <EndpointTable title="Client API" auth="PocketBase session" :endpoints="clientApi" />
<EndpointTable title="Logbook &amp; fleet API" auth="PocketBase session · org-scoped" :endpoints="logbookApi" />
<EndpointTable title="Documents API" auth="PocketBase session · org-scoped" :endpoints="documentsApi" />
<EndpointTable title="Integrations API" auth="PocketBase session" :endpoints="integrationsApi" />
<EndpointTable title="Management API" auth="Admin · superadmin" :endpoints="managementApi" /> <EndpointTable title="Management API" auth="Admin · superadmin" :endpoints="managementApi" />
<EndpointTable title="Device API" auth="Device uplink" :endpoints="deviceApi" /> <EndpointTable title="Device API" auth="Device uplink · public" :endpoints="deviceApi" />
</div> </div>
<!-- Users tab --> <!-- Users tab -->