feat: PocketBase backend + account/profile schema (epic #6, issue #9)
Foundation for the user-accounts platform. Self-hosted PocketBase v0.39.6,
version-pinned from the official release binary, schema-as-code so the
collections auto-apply on boot and never drift from hand-clicking.
Collections: users (auth, admin-only nsfwEnabled), profiles, watch_state,
watchlist, prefs. Per-owner access rules traverse profile.user; nsfwEnabled
is never client-writable (superuser-only). Relations cascadeDelete; unique
indexes keep one resume/watchlist row per (profile,itemId) and one prefs per
profile.
Verified locally against v0.39.6: migration applies clean, and scripts/verify.py
proves two users can't read/write each other's data and can't set their own
nsfwEnabled (19/19 checks). Coolify deploy (domain/TLS, superuser, SMTP,
backups) documented in README as the manual half.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 18:22:45 +00:00
|
|
|
# myanime-backend — PocketBase, version-pinned from the official release.
|
|
|
|
|
#
|
|
|
|
|
# We download the official static binary from GitHub releases (rather than a
|
|
|
|
|
# third-party image) so the deploy is reproducible and easy to audit.
|
|
|
|
|
FROM alpine:3.20 AS fetch
|
|
|
|
|
|
|
|
|
|
# Bump this to upgrade PocketBase. Keep it in sync with the README.
|
|
|
|
|
ARG PB_VERSION=0.39.6
|
|
|
|
|
ARG TARGETARCH=amd64
|
|
|
|
|
|
|
|
|
|
RUN apk add --no-cache ca-certificates unzip wget \
|
|
|
|
|
&& wget -q "https://github.com/pocketbase/pocketbase/releases/download/v${PB_VERSION}/pocketbase_${PB_VERSION}_linux_${TARGETARCH}.zip" -O /tmp/pb.zip \
|
|
|
|
|
&& unzip /tmp/pb.zip -d /pb \
|
|
|
|
|
&& rm /tmp/pb.zip
|
|
|
|
|
|
|
|
|
|
FROM alpine:3.20
|
|
|
|
|
|
2026-07-15 19:08:12 +00:00
|
|
|
RUN apk add --no-cache ca-certificates
|
feat: PocketBase backend + account/profile schema (epic #6, issue #9)
Foundation for the user-accounts platform. Self-hosted PocketBase v0.39.6,
version-pinned from the official release binary, schema-as-code so the
collections auto-apply on boot and never drift from hand-clicking.
Collections: users (auth, admin-only nsfwEnabled), profiles, watch_state,
watchlist, prefs. Per-owner access rules traverse profile.user; nsfwEnabled
is never client-writable (superuser-only). Relations cascadeDelete; unique
indexes keep one resume/watchlist row per (profile,itemId) and one prefs per
profile.
Verified locally against v0.39.6: migration applies clean, and scripts/verify.py
proves two users can't read/write each other's data and can't set their own
nsfwEnabled (19/19 checks). Coolify deploy (domain/TLS, superuser, SMTP,
backups) documented in README as the manual half.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 18:22:45 +00:00
|
|
|
|
|
|
|
|
COPY --from=fetch /pb/pocketbase /usr/local/bin/pocketbase
|
|
|
|
|
|
|
|
|
|
# Schema-as-code: migrations are baked in and auto-applied on serve.
|
|
|
|
|
COPY pb_migrations /pb_migrations
|
|
|
|
|
|
feat(device-auth): codeless device sign-in backend (#12)
A new device (TV) signs into an account with no password typed on it and
no pairing code, approved from an already-logged-in phone/PC.
- device_auth collection (migration): code (unique), deviceName, status,
user, expiresAt + hidden authToken/keyCiphertext/pollSecret/devicePubKey.
Owner-scoped list/view/delete only (the device list + revoke); create/
update locked to the hooks.
- pb_hooks/device_auth.pb.js: public request + info + pollSecret-gated
poll routes (the TV is unauthenticated), auth-gated approve (mints
e.auth.newAuthToken(), stores the E2E vault-key ciphertext) + decline,
and a cleanup cron that scrubs delivered tokens and stale rows.
- pb_hooks/device_page.pb.js: self-contained approve page at GET /device.
Signs in, derives the addon-config vault key (#20) with WebCrypto PBKDF2,
seals {salt,keyB64} to the TV's X25519 pubkey (vendored TweetNaCl +
WebCrypto HKDF/AES-GCM), and approves. The server never sees the key.
- Dockerfile ships pb_hooks (--hooksDir); verify.py covers the schema +
that the routes are served.
Crypto matches the app byte-for-byte (proven by the app's fixed-vector
tests). Full contract: docs/device-auth-contract.md. JWT-revocation
limitation documented (v1).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 12:36:15 +00:00
|
|
|
# JS hooks (custom routes + the device sign-in approve page, issue #12). Loaded
|
|
|
|
|
# from --hooksDir on serve.
|
|
|
|
|
COPY pb_hooks /pb_hooks
|
|
|
|
|
|
2026-07-22 16:23:05 +00:00
|
|
|
# Static distribution/onboarding site (landing + account wizard) served at /.
|
|
|
|
|
COPY pb_public /pb_public
|
|
|
|
|
|
2026-07-15 19:08:12 +00:00
|
|
|
# Persist DB, uploaded files, and any admin-created migrations here. Runs as root
|
|
|
|
|
# so it can always write the volume Coolify attaches — Coolify's persistent mount
|
|
|
|
|
# is root-owned, and a non-root user hitting it fails with SQLite "unable to open
|
|
|
|
|
# database file (14)".
|
|
|
|
|
RUN mkdir -p /pb_data
|
feat: PocketBase backend + account/profile schema (epic #6, issue #9)
Foundation for the user-accounts platform. Self-hosted PocketBase v0.39.6,
version-pinned from the official release binary, schema-as-code so the
collections auto-apply on boot and never drift from hand-clicking.
Collections: users (auth, admin-only nsfwEnabled), profiles, watch_state,
watchlist, prefs. Per-owner access rules traverse profile.user; nsfwEnabled
is never client-writable (superuser-only). Relations cascadeDelete; unique
indexes keep one resume/watchlist row per (profile,itemId) and one prefs per
profile.
Verified locally against v0.39.6: migration applies clean, and scripts/verify.py
proves two users can't read/write each other's data and can't set their own
nsfwEnabled (19/19 checks). Coolify deploy (domain/TLS, superuser, SMTP,
backups) documented in README as the manual half.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 18:22:45 +00:00
|
|
|
VOLUME ["/pb_data"]
|
|
|
|
|
|
|
|
|
|
EXPOSE 8090
|
|
|
|
|
|
|
|
|
|
# Coolify terminates TLS at Traefik; PocketBase listens plain on 8090 behind it.
|
|
|
|
|
ENTRYPOINT ["pocketbase"]
|
2026-07-22 16:23:05 +00:00
|
|
|
CMD ["serve", "--http=0.0.0.0:8090", "--dir=/pb_data", "--migrationsDir=/pb_migrations", "--hooksDir=/pb_hooks", "--publicDir=/pb_public"]
|