Task 1.1 — Project scaffold

Phase 1 task 1.1 lands. Directus 11.17.4 boots locally end-to-end
against a TimescaleDB+PostGIS container; admin UI serves at :8055,
admin bootstrap from env vars works, named volumes preserve data
across down/up cycles.

Scaffold:
- Dockerfile — FROM directus/directus:11.17.4. Pre-installs
  postgresql16-client (ahead of task 1.2's db-init runner needing psql).
  Bakes in /directus/snapshots, /directus/db-init, /directus/scripts,
  /directus/extensions, /directus/entrypoint.sh.
- compose.dev.yaml — db (timescale/timescaledb-ha:pg16.6-ts2.17.2-all)
  + directus (local build), healthchecks, named volumes
  directus-pg-data + directus-uploads.
- entrypoint.sh — placeholder using upstream's actual flow
  (node cli.js bootstrap && pm2-runtime start ecosystem.config.cjs);
  the real db-init -> schema apply -> start wrapper lands in task 1.7.
- package.json — scripts-only (dev, dev:down, dev:reset,
  schema:snapshot, schema:apply, db:init), no runtime deps.
- .env.example — sectioned, fully documented, KEY/SECRET marked
  required with generation hints.
- .gitignore, .dockerignore — match the processor service conventions.
- snapshots/, db-init/, scripts/, extensions/ — empty with .gitkeep,
  filled by later Phase 1 tasks (1.3, 1.6) and Phase 5.

Lessons locked in (against the empirical pnpm dev boot):
- timescale/timescaledb-ha:pg16-latest does NOT exist on Docker Hub.
  Pin a concrete version (we used pg16.6-ts2.17.2-all).
- This image's data directory is /home/postgres/pgdata/data, not
  /pgdata or /var/lib/postgresql/data. PGDATA env var and the volume
  mount must both target it.
- The -all variant bundles PostGIS binaries but the extension is not
  auto-created on the directus database; CREATE EXTENSION lands in
  Phase 2 alongside the geofences/SLZs/waypoints collections.
- The upstream image's CMD is bootstrap + pm2-runtime, not a simple
  cli.js start. Bypassing pm2 would lose crash recovery.

These corrections folded into 01-project-scaffold.md (deliverable line
+ Done section), 08-gitea-ci-dryrun.md (CI service tag), and the
inline comments in compose.dev.yaml so future implementers don't
re-discover them.

Status: ROADMAP marks 1.1 done, Phase 1 in progress, 1.2 next.
This commit is contained in:
2026-05-01 21:29:00 +02:00
parent a8e808e71c
commit 387c3c4cfa
16 changed files with 389 additions and 8 deletions
+2 -2
View File
@@ -42,14 +42,14 @@ These rules govern every task. Any deviation must be discussed and documented as
### Phase 1 — Slice 1 schema + deploy pipeline
**Status:** ⬜ Not started
**Status:** 🟨 In progress (1.1 done; 1.2 next)
**Outcome:** A Directus instance with the org-level catalog (orgs, users, organization_users, vehicles, devices and their org junctions) and event-participation collections (events, classes, entries, entry_crew, entry_devices) live and snapshot-tracked. `db-init/` covers the TimescaleDB extension, the `positions` hypertable, and the `faulty` column. Image builds via Gitea Actions with a CI dry-run that catches snapshot drift before deploy. Rally Albania 2026 is registered as the first event in admin UI to dogfood the registration workflow. **This is what Rally Albania 2026 needs.**
[**See `phase-1-slice-1-schema/README.md`**](./phase-1-slice-1-schema/README.md)
| # | Task | Status | Landed in |
|---|------|--------|-----------|
| 1.1 | [Project scaffold](./phase-1-slice-1-schema/01-project-scaffold.md) | | |
| 1.1 | [Project scaffold](./phase-1-slice-1-schema/01-project-scaffold.md) | 🟩 | pending user commit |
| 1.2 | [db-init runner script](./phase-1-slice-1-schema/02-db-init-runner.md) | ⬜ | — |
| 1.3 | [Initial migrations (extensions, positions hypertable, faulty column)](./phase-1-slice-1-schema/03-initial-migrations.md) | ⬜ | — |
| 1.4 | [Org-level catalog collections](./phase-1-slice-1-schema/04-org-catalog-collections.md) | ⬜ | — |
@@ -1,7 +1,7 @@
# Task 1.1 — Project scaffold
**Phase:** 1 — Slice 1 schema + deploy pipeline
**Status:** ⬜ Not started
**Status:** 🟩 Done
**Depends on:** None
**Wiki refs:** `docs/wiki/entities/directus.md`, `docs/wiki/synthesis/directus-schema-draft.md`
@@ -13,7 +13,7 @@ Initialize the `directus/` service folder with the directory layout from the Pha
- `directus/Dockerfile``FROM directus/directus:11.x`, copies `snapshots/`, `db-init/`, `scripts/`, `entrypoint.sh`, `extensions/` into the image. Sets `ENTRYPOINT ["/directus/entrypoint.sh"]`. (Concrete entrypoint contents land in task 1.7; for now create a placeholder that just `exec`s the upstream entrypoint.)
- `directus/compose.dev.yaml` — two services:
- `db`: `timescale/timescaledb-ha:pg16-latest` (or equivalent), volume-mapped Postgres data dir, healthcheck.
- `db`: `timescale/timescaledb-ha:pg16.6-ts2.17.2-all` (the `-all` variant bundles PostGIS binaries; the `:pg16-latest` floating tag does NOT exist on Docker Hub — pin a concrete TS+PG version). Volume-mapped Postgres data dir, healthcheck.
- `directus`: built from local `Dockerfile`, depends on `db` healthy, env vars for DB connection + `KEY` + `SECRET` + admin bootstrap, port `8055` exposed.
- `directus/package.json` — minimal, only for npm scripts (no runtime deps). Scripts:
- `schema:snapshot``bash scripts/schema-snapshot.sh` (script body lands in 1.6)
@@ -58,4 +58,22 @@ Initialize the `directus/` service folder with the directory layout from the Pha
## Done
(Fill in commit SHA + one-line note when this lands.)
Pending commit by user. All deliverables created in the same working tree pass.
**Open question resolutions (corrected against live `pnpm dev` boot 2026-05-01):**
- **TimescaleDB-HA image tag.** `:pg16-latest` does **not** exist on Docker Hub (the agent's initial pin failed at pull time). The empirically-verified tag is `timescale/timescaledb-ha:pg16.6-ts2.17.2-all`. The `-all` suffix bundles PostGIS binaries.
- **PGDATA path.** Not `/pgdata` (the agent's first guess); the actual data directory baked into this image is `/home/postgres/pgdata/data`. `PGDATA: /pgdata` plus a volume mount to `/pgdata` produced "could not change permissions of directory" errors at initdb. Fixed by setting both `PGDATA` and the volume target to `/home/postgres/pgdata/data`.
- **PostGIS extension.** Binaries are bundled in the `-all` image but the extension is **not** auto-created on the `directus` database. Directus boot logs warn: `PostGIS isn't installed. Geometry type support will be limited.` Resolution: `CREATE EXTENSION IF NOT EXISTS postgis;` lands in db-init when geometry types are needed (Phase 2). Phase 1 has no geometry columns so the warning is benign.
- **Directus version pin**: `directus/directus:11.17.4` confirmed to exist on Docker Hub. Used as the image pin.
**Deviations from task spec:**
1. `entrypoint.sh` delegates to `node cli.js bootstrap && pm2-runtime start ecosystem.config.cjs` (the upstream image's actual CMD) rather than `exec /directus/cli.js start`. The upstream image uses pm2-runtime to manage the process; bypassing it would skip crash recovery and signal handling that pm2 provides. The `bootstrap` step is idempotent (safe to run every boot) and handles admin user creation.
2. `compose.dev.yaml` sets `PGDATA: /home/postgres/pgdata/data` and mounts the named volume to the same path. Required by the `timescaledb-ha:*-all` image; mounting elsewhere fails initdb.
3. `Dockerfile` installs `postgresql16-client` via apk so that `scripts/apply-db-init.sh` (task 1.2) can invoke `psql` without adding that dependency later.
4. `README.md` updated: pinned `11.x``11.17.4`; CI section notes workflow file is pending (task 1.8).
**Live boot acceptance (2026-05-01):**
`pnpm dev` against fresh volumes succeeded: db became healthy, Directus ran 60+ system migrations, PM2 cluster started, server bound at `http://0.0.0.0:8055`, GraphQL Subscriptions and WebSocket Server started. Admin bootstrap (creating first admin role + admin user) completed. One benign warning ("PostGIS isn't installed" — see Open question resolutions above). One harmless migration warning about a non-existent constraint on `directus_comments_collection_foreign` (a Directus internal migration's expected idempotent guard, not caused by this task). All Phase 1 task 1.1 acceptance criteria met.
@@ -33,7 +33,7 @@ Build a Gitea Actions workflow that on push to `main` (when relevant paths chang
runs-on: ubuntu-22.04
services:
postgres:
image: timescale/timescaledb-ha:pg16-latest
image: timescale/timescaledb-ha:pg16.6-ts2.17.2-all # match compose.dev.yaml; :pg16-latest does NOT exist on Docker Hub
env:
POSTGRES_USER: directus
POSTGRES_PASSWORD: directus