Serve canonical root-relative DAV URLs on a configured hostname while preserving the existing /dav mount. Reconcile Cloudflare rewrite rules and Worker custom domains during fork deployments, and expose the effective URL through site options.
The Docker image was only built on release tags (`v*`), so there was no
published image tracking the latest code on main.
- ci.yml: add `docker-dev` job that pushes `:dev`/`:dev-cli` on every green
push to main (gated on check + docker-smoke; skipped on PRs/forks).
- docker-nightly.yml: scheduled (03:27 UTC) no-cache rebuild publishing
`:nightly`/`:nightly-cli` so base-image/OS security patches land daily even
when no code changes.
- docs/deploy/docker.md: document the tag scheme. `:latest` stays pinned to
releases; `:dev`/`:nightly` are moving, unreviewed tags.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat: v2.6 Z11 — prod public key, Docker cron docs, release notes
- Replace DEV placeholder in public-keys.ts with cloud.zpan.space
production Ed25519 key (k4.public.sphdaogcyIh2_6_yZnO4_xQsi2m52HH9j2CPHcKlGGw)
from cloud C5 cross-repo PR
- Add external cron section to docs/deploy/docker.md for the
POST /api/licensing/refresh-cron endpoint (Z6)
- Create docs/v2.6-release-notes.md with what's new, retroactive gate
notice (open_registration, teams_unlimited, team_quotas), upgrade guide
Agent-Profile: https://agent-kanban.dev/agents/a6bb038c4226a87f
* test(licensing): decouple verify/entitlement tests from DEV secret key
Tests were hardcoded to the old DEV placeholder key. Now they generate
a fresh throwaway keypair per suite (beforeAll/afterAll), inject the
public key into PUBLIC_KEYS, and restore the original on teardown.
This keeps the tests independent of whichever production key is in
PUBLIC_KEYS, so rotating the key never breaks the test suite.
Agent-Profile: https://agent-kanban.dev/agents/a6bb038c4226a87f
---------
Co-authored-by: Bob <aibob@mails.agent-kanban.dev>
* feat: add libSQL (Turso) platform adapter and Docker opt-in
- server/platform/libsql.ts: createLibsqlPlatform() using @libsql/client +
drizzle-orm/libsql; accepts plain env record; async migrate at boot;
authToken optional for file:// URLs
- server/entry-node.ts: select platform at startup — libsql when
TURSO_DATABASE_URL is set, otherwise existing SQLite via createNodePlatform()
- drizzle.config.ts: switch to turso dialect when TURSO_DATABASE_URL is set
- vitest.libsql.config.ts + server/platform/libsql.libsql-test.ts: smoke suite
covering connect, migrations, insert/select against users + storages tables
- package.json: add @libsql/client dependency; add test:libsql script;
externalize @libsql/client in build:node tsup command
- vitest.config.ts: exclude *.libsql-test.ts from coverage
- docs/deploy/docker.md: document Turso opt-in with copy-pasteable
docker-compose snippet
- CONTRIBUTING.md: add Turso migrate path paragraph under Database Migrations
Agent-Profile: https://agent-kanban.dev/agents/a6bb038c4226a87f
* refactor: turn bootstrap.ts into a Platform-accepting factory
- server/bootstrap.ts: replace singleton module-scope script with
exportable createBootstrap(platform) async factory; reads
BETTER_AUTH_SECRET/BETTER_AUTH_URL/TRUSTED_ORIGINS from platform.getEnv
so every future entry (Lambda, Vercel, Netlify, Azure) can reuse it
- server/entry-node.ts: slim down to platform selection + createBootstrap
call; no more duplicate auth/app wiring
- server/dev.ts: thin vite-dev-server entry that creates NodePlatform and
calls createBootstrap; replaces the former default export in bootstrap.ts
- vite.config.ts: update node dev server entry to server/dev.ts
- server/platform/libsql.ts: fix getEnv to check env record before
falling back to process.env, matching the cloudflare.ts pattern
Agent-Profile: https://agent-kanban.dev/agents/a6bb038c4226a87f
* style: apply biome auto-fixes for pre-existing lint issues
Agent-Profile: https://agent-kanban.dev/agents/a6bb038c4226a87f
---------
Co-authored-by: Bob <aibob@mails.agent-kanban.dev>