Files
directus/.planning/ROADMAP.md
T
julian a8e808e71c Scaffold directus service planning structure
Initial commit. Establishes the .planning/ tree mirroring processor's
shape (ROADMAP.md as nav hub + per-phase folders with READMEs and
granular task files).

Six phases:

1. Slice 1 schema + deploy pipeline — what Rally Albania 2026 needs.
   Org catalog (orgs, users, vehicles, devices) + event participation
   (events, classes, entries, entry_crew, entry_devices). db-init/
   for the positions hypertable + faulty column. snapshot/apply
   tooling. Gitea CI dry-run. Dogfood seed of Rally Albania 2026.
   Nine task files with full Goal / Deliverables / Specification /
   Acceptance criteria / Risks / Done sections.

2. Course definition — stages, segments, geofences, waypoints, SLZs.
   PostGIS extension introduced here.

3. Timing & penalty tables — co-developed with processor Phase 2.
   entry_segment_starts, entry_crossings, entry_penalties,
   stage_results, penalty_formulas.

4. Permissions & policies — Directus 11 dynamic-filter Policies per
   logical role. Deployment-time work, deferred to keep early phases
   focused on the data model.

5. Custom extensions — TypeScript hooks/endpoints implementing the
   cross-plane workflows the schema implies (faulty-flag → Redis
   stream emit, stage-open materializer, etc.).

6. Future / optional — retroactivity preview UI, command-routing
   Flows, audit trails, federation rule import. Not committed.

Non-negotiable design rules captured in ROADMAP.md: schema authority
in Directus + snapshot-as-code + db-init for non-Directus DDL +
sequential idempotent migrations + entrypoint apply order + no
application logic in Flows + permissions deferred to Phase 4.

Architectural anchors point at the wiki at ../docs/wiki/ — the schema
draft, the Rally Albania 2025 source page, plus the existing
processor/postgres-timescaledb/live-channel pages. Each task file
calls out the wiki refs an implementing agent should read first.

README.md mirrors the processor service README structure: quick start,
local Docker test, prod/stage deployment notes, env vars, CI behavior.
2026-05-01 20:42:44 +02:00

103 lines
8.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# directus — Roadmap
The TRM business plane. Directus 11 instance owning the relational schema and exposing it via REST/GraphQL/WebSockets/Admin UI. Schema-as-code via `snapshots/` + `db-init/`, applied at container startup.
This file is the single navigation hub for all implementation planning. Each phase has its own folder with a README and granular task files. Update statuses here as work lands.
## Status legend
| Symbol | Meaning |
|--------|---------|
| ⬜ | Not started |
| 🟦 | Planned (designed, not coded) |
| 🟨 | In progress |
| 🟩 | Done |
| ⏸ | Paused / blocked |
| ❄️ | Frozen / future / optional |
## Architectural anchors
The service is specified by the wiki at `../docs/wiki/`. Implementing agents should read these pages before starting any task:
- **Architecture** — `docs/wiki/sources/gps-tracking-architecture.md`, `docs/wiki/concepts/plane-separation.md`, `docs/wiki/concepts/failure-domains.md`
- **This service** — `docs/wiki/entities/directus.md`
- **Schema design** — `docs/wiki/synthesis/directus-schema-draft.md`
- **Reference rulebook** — `docs/wiki/sources/rally-albania-regulations-2025.md` (canonical real-world fixture for federation rule shapes)
- **Downstream / sibling** — `docs/wiki/entities/postgres-timescaledb.md`, `docs/wiki/entities/processor.md`, `docs/wiki/concepts/live-channel-architecture.md`
## Non-negotiable design rules
These rules govern every task. Any deviation must be discussed and documented as a decision before code lands.
1. **Schema authority lives in Directus.** Collections, fields, relations are defined through Directus and round-tripped via `directus schema snapshot`. The exception is the `positions` hypertable (owned by [[processor]]) and any other DDL Directus cannot represent (PostGIS-specific syntax, custom indexes, hypertable creation) — those live in `db-init/*.sql`.
2. **`db-init/*.sql` is sequential, idempotent, and guarded.** Files numbered `NNN_name.sql`. Each is internally idempotent (`IF NOT EXISTS`, `ADD COLUMN IF NOT EXISTS`). The runner skips files already recorded in `migrations_applied`. Manual application of out-of-order files is forbidden.
3. **Apply order at boot:** db-init runner → `directus schema apply --yes``directus start`. Any failure halts boot. Implemented in `entrypoint.sh`.
4. **Snapshot lives in git, edited only via the admin UI.** Hand-editing `snapshots/schema.yaml` is forbidden — round-trip through the UI keeps the format consistent with what `directus schema snapshot` produces.
5. **One PR = one snapshot regeneration.** PRs that change schema include the regenerated snapshot. CI verifies the snapshot matches what `directus schema snapshot` would produce against an applied database.
6. **No application logic in Flows.** Flows are reserved for declarative orchestration (notifications, simple field updates, webhook routing). Domain logic lives in `extensions/` (TypeScript hooks/endpoints) where it is reviewed, tested, and version-controlled like any other code.
7. **Permissions are a separate phase.** Adding a collection in Phase 13 does NOT come with its access policies — those land deliberately in Phase 4. Until then collections are admin-only by default. This avoids premature commitment to role definitions before the data model is settled.
8. **Image starts from `directus/directus:11.x`.** No forking the upstream image. Customizations are: bundled extensions under `/directus/extensions/`, snapshot/db-init artifacts under `/directus/snapshots/` and `/directus/db-init/`, and an entrypoint wrapper.
## Phases
### Phase 1 — Slice 1 schema + deploy pipeline
**Status:** ⬜ Not started
**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.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.5 | [Event-participation collections](./phase-1-slice-1-schema/05-event-participation-collections.md) | ⬜ | — |
| 1.6 | [Schema snapshot/apply tooling](./phase-1-slice-1-schema/06-snapshot-tooling.md) | ⬜ | — |
| 1.7 | [Image build & entrypoint](./phase-1-slice-1-schema/07-image-and-dockerfile.md) | ⬜ | — |
| 1.8 | [Gitea CI dry-run workflow](./phase-1-slice-1-schema/08-gitea-ci-dryrun.md) | ⬜ | — |
| 1.9 | [Rally Albania 2026 dogfood seed](./phase-1-slice-1-schema/09-rally-albania-2026-seed.md) | ⬜ | — |
### Phase 2 — Course definition
**Status:** ⬜ Not started — depends on Phase 1
**Outcome:** Stages, segments, geofences (PostGIS polygons), waypoints, and speed_limit_zones as data-layer collections. Operators can define an event's full course before each stage. No processor logic yet — Phase 2 of [[processor]] consumes this data and writes crossings/penalties.
[**See `phase-2-course-definition/README.md`**](./phase-2-course-definition/README.md)
### Phase 3 — Timing & penalty tables
**Status:** ⬜ Not started — co-developed with processor Phase 2
**Outcome:** `entry_segment_starts`, `entry_crossings`, `entry_penalties`, `stage_results`, and `penalty_formulas` collections. The schema half of the paired schema/code work that produces real timing results. Penalty evaluator registry shipped on the [[processor]] side; rule numeric values shipped here.
[**See `phase-3-timing-and-penalty-tables/README.md`**](./phase-3-timing-and-penalty-tables/README.md)
### Phase 4 — Permissions & policies
**Status:** ⬜ Not started — depends on Phases 13
**Outcome:** Dynamic-filter Policies per logical role (org-admin, race-director, marshal, timekeeper, participant, …) covering each collection × action. Multi-tenant isolation enforced by Directus, not by application code. Deployment-time work, not architectural.
[**See `phase-4-permissions-and-policies/README.md`**](./phase-4-permissions-and-policies/README.md)
### Phase 5 — Custom extensions
**Status:** ⬜ Not started — depends on Phase 3
**Outcome:** TypeScript extensions implementing the cross-plane workflows the schema implies: faulty-flag → `recompute:requests` stream emit; `events.discipline` validation hook; stage-open trigger materializing `entry_segment_starts`; CP closing-time computation; entry registration "copy crew from previous entry" custom endpoint.
[**See `phase-5-custom-extensions/README.md`**](./phase-5-custom-extensions/README.md)
### Phase 6 — Future / optional
**Status:** ❄️ Not committed
[**See `phase-6-future/README.md`**](./phase-6-future/README.md)
Ideas on radar: retroactivity preview UI for geometry edits (Phase 2.5 of [[processor]] — needs a UI counterpart here), command-routing Flows ([[phase-2-commands]]), audit trail extensions, federation rule import tooling.
## Operating model
- **Implementation agent contract.** Each task file is self-sufficient: goal, deliverables, specification, acceptance criteria. An agent should be able to complete one task without reading the whole wiki — but should skim the wiki references at the top of the task before starting.
- **Sequence within a phase.** Task numbering reflects intended order. Soft dependencies are explicit in each task's "Depends on" field. Tasks with no dependencies on each other can be done in parallel.
- **Status updates.** When a task is started, change its row in this ROADMAP to 🟨 and the task file's status badge accordingly. When done, 🟩 + a one-line note in the task file's "Done" section pointing at the merging commit/PR.
- **Drift control.** If implementation diverges from a task's spec, update the task file *before* the diverging code lands, with a note explaining why. Do not let plans rot — either fix the plan or fix the code.