Files
PilotVault/API Server/pocketbase
tajniak81andClaude Opus 4.8 52f84ad6cf Add compliance & operational document store (PocketBase)
Introduces a `documents` collection and full-stack UI for tracking pilot
certificates, aircraft registrations, insurance, airspace authorisations,
contracts, and other paperwork.

- Migration 1720300800_add_documents.js (also provisioned live on remote PB):
  doc_type/owner/expiry/status/access_tier + file blob, a self-referential
  `replaces` version chain, audit fields, and a partial index on expiry_date.
- API Server (documents.go): role-scoped CRUD, server-computed expiry
  assessment, ?expiring=N query, versioning (replaces -> version+1, old row
  auto-archived), and streamed blob download. admin.go gains multipart upload,
  file tokens, and protected-file streaming.
- Web App: BFF passthrough (multipart create + streamed download), api.js
  client fns, and Documents.vue wired into the Documents nav slot.

Blobs live in PocketBase file storage for now; only that backend swaps when
S3-compatible object storage lands.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 19:46:18 +02:00
..

PocketBase — PilotVault schema

PilotVault adds an organizations collection and three fields to the users auth collection:

  • preferences (JSON) — each user's settings blob. Written with the user's own token, so PocketBase's default owner-only update rule (@request.auth.id = id) is all the authorization needed.
  • role (select: superadmin | admin | user) — the user-rights level. A superadmin spans every organization; an admin is scoped to their own organization (may manage its users and admins, but not superadmins); a user has no management rights. Missing/empty is treated as user.
  • organization (relation → organizations, maxSelect 1, optional) — which org the user belongs to. Nullable: a user may belong to no organization.

The organizations collection is a plain base collection with a unique name. It is reached only through the API Server's superuser service account (its API rules stay locked to superusers), the same way user management works.

User + org management requires a service account

Listing/creating/deleting users and organizations is done by the API Server using a superuser service account (POCKETBASE_ADMIN_EMAIL / POCKETBASE_ADMIN_PASSWORD), but only after verifying the caller's own token resolves to a manager role (admin for user management, superadmin for org management). This is the single place the server uses elevated PocketBase credentials; without the env vars, the /api/users and /api/orgs endpoints return 503 and the rest is unaffected.

Preferences never need the service account — they use the caller's own token.

Add the schema

Pick one of the following.

Copy the migration files into your PocketBase deployment's pb_migrations/ directory and restart PocketBase (migrations run automatically on boot; they target the PocketBase v0.22+/v0.23 JS migration API). They are idempotent, so they are safe even if the schema was already provisioned live:

Option B — Admin UI (any version)

  1. Open the PocketBase Admin UI → Collections → New collection organizations (base); add a text field name (required) with a unique index.
  2. Collections → users → New field. Add JSON field preferences, not required, max size ~5 MB.
  3. Add Select field role, values superadmin, admin, user, max select 1.
  4. Add Relation field organizationorganizations, max select 1, not required, cascade delete off.
  5. Save.

Verify

With a normal user token you should be able to round-trip the field:

# 1) log in (PocketBase directly, or via the API Server /api/auth/login)
TOKEN=... # the "token" from the auth response

# 2) save
curl -X PATCH "$PB_URL/api/collections/users/records/$USER_ID" \
  -H "Authorization: $TOKEN" -H "Content-Type: application/json" \
  -d '{"preferences":{"fontSize":"lg","themeMode":"dark"}}'

# 3) read back
curl "$PB_URL/api/collections/users/auth-refresh" -X POST -H "Authorization: $TOKEN"

In the app the round-trip is: browser → GET/PUT /bff/preferences → API Server GET/PUT /api/preferences → PocketBase user record.