feat(10-01): serve the embedded admin SPA at backend.uri with cookie login

- backend.uri prefix (default /backend) mounts the admin API at {prefix}/api/v1
  and the embedded SPA shell at {prefix} with an api/ JSON 404 fallback
- cookie transport: an X-Requested-With login sets the HttpOnly summer_admin
  cookie and returns no token; the backend guard reads the cookie after Bearer
- CSRF wrapper refuses cookie-only POST/PUT/DELETE without X-Requested-With
- boardwalk package embeds boardwalk/dist, rewrites index.html once per prefix
  and sets cache and security headers
- framework admin OpenAPI pipeline (swag, swagger2openapi, openapi-typescript)
  with prefix-relative paths and typed envelopes for the tracer routes
- admin/ Vite SPA: login, plugin rail, section panel and read-only list
  through the openapi-fetch client typed by the generated schema
This commit is contained in:
Jakub Zych
2026-09-27 15:21:48 +02:00
parent 8c3e131111
commit 5f9353841b
79 changed files with 10745 additions and 147 deletions

60
scripts/check-admin-openapi.sh Executable file
View File

@@ -0,0 +1,60 @@
#!/usr/bin/env bash
# Generate the framework admin OpenAPI document and the admin SPA's TypeScript
# types from the swag annotations in cabana (D-15):
# swag v1.16.6 (Swagger 2.0) -> internal/tools/swagger2openapi (OpenAPI 3.0)
# -> openapi-typescript (admin devDependency) -> admin/src/api/schema.d.ts
# Without arguments the outputs replace admin/openapi/admin.json and
# admin/src/api/schema.d.ts. With --check nothing is written and the script
# exits non-zero when either committed file differs from a fresh generation.
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$ROOT"
CHECK=0
case "${1:-}" in
"") ;;
--check) CHECK=1 ;;
*)
echo "usage: scripts/check-admin-openapi.sh [--check]" >&2
exit 2
;;
esac
if [[ ! -d admin/node_modules ]]; then
npm --prefix admin ci
fi
TMP="$(mktemp -d)"
trap 'rm -rf "$TMP"' EXIT
go run github.com/swaggo/swag/cmd/swag@v1.16.6 init \
--dir cabana \
--generalInfo admin_openapi.go \
--output "$TMP" \
--outputTypes json \
--requiredByDefault \
--quiet
if [[ ! -s "$TMP/swagger.json" ]]; then
echo "check-admin-openapi: swag did not generate swagger.json" >&2
exit 1
fi
go run ./internal/tools/swagger2openapi "$TMP/swagger.json" > "$TMP/admin.json"
admin/node_modules/.bin/openapi-typescript "$TMP/admin.json" -o "$TMP/schema.d.ts"
if [[ "$CHECK" -eq 1 ]]; then
status=0
diff -u admin/openapi/admin.json "$TMP/admin.json" || status=1
diff -u admin/src/api/schema.d.ts "$TMP/schema.d.ts" || status=1
if [[ "$status" -ne 0 ]]; then
echo "check-admin-openapi: committed admin OpenAPI output is stale; run scripts/check-admin-openapi.sh" >&2
fi
exit "$status"
fi
mkdir -p admin/openapi admin/src/api
cp "$TMP/admin.json" admin/openapi/admin.json
cp "$TMP/schema.d.ts" admin/src/api/schema.d.ts
echo "check-admin-openapi: wrote admin/openapi/admin.json and admin/src/api/schema.d.ts"