Session Planning
This document tracks focused 1-hour work sessions for CEREBRAL STRATUM. Each item is scoped to be achievable (or meaningfully advanced) in a single sitting. Sessions are linked to the YouTrack CEREBRALSTRATUM project at youtrack.blueguardian.co.
Current State (as at 2026-05-17)
Repo | State | Next milestone |
|---|---|---|
| 4 services scaffolded; organisations, devices, users, locations resources exist | Device registration flow wired to Keycloak; Kafka telemetry consumer |
| KMP migration active; React web app + |
|
| Rust, ESP32-S3; UUID management + MQTT client stub only | First live CAN frame → MQTT publish loop |
| ADRs complete (ADR-0001–0003); ECS/RDS migration proposed | Infrastructure Terraform; Keycloak ECS cutover |
| OpenShift cluster configs | Terraform modules for ECS + RDS (ADR-0003 Phase 1) |
Session Backlog
Sessions are grouped by area and roughly ordered by dependency. Mark sessions complete by moving them to Completed.
Identity & Infrastructure
[INFRA-S01] Provision RDS for Keycloak (ADR-0003 Phase 1)
Terraform: db.t4g.micro PostgreSQL 16, Single-AZ, private subnet, gp3 20GB, deletion protection enabled, 7-day backup retention. Store credentials in Secrets Manager. Validate connectivity from EC2 bastion.
Outcome: RDS instance exists; keycloak DB and user created; credentials in Secrets Manager; connectivity confirmed. ADR: ADR-0003 Phase 1 YouTrack: CEREBRALSTRATUM project
[INFRA-S02] ECS Task Definition for Keycloak + cloudflared
Author the ECS task definition (Fargate, ARM64, 0.5 vCPU / 1 GB) with Keycloak + cloudflared sidecar containers as per ADR-0003. Deploy ECS service (desired count: 1). Configure cloudflared route: auth.blueguardian.co → http://localhost:8080.
Depends on: INFRA-S01 (RDS endpoint required for KC_DB_URL) Outcome: Keycloak reachable at auth.blueguardian.co; admin console behind Zero Trust Access policy. ADR: ADR-0003 Phase 3
[INFRA-S03] Database migration: containerised → RDS
Export Keycloak DB from EC2-hosted container (pg_dump -Fc), restore into RDS (pg_restore). Validate realm config, client registrations, and LDAP federation settings post-restore.
Depends on: INFRA-S01 Outcome: RDS instance has all realm data; IdM LDAP federation confirmed working. ADR: ADR-0003 Phase 2
[INFRA-S04] Keycloak ECS cutover and EC2 decommission
Validate all Zero Trust applications authenticate via ECS-hosted Keycloak. Validate private_key_jwt device auth flows (backend ADR-0001). Remove Keycloak + PostgreSQL containers from EC2 instance. Evaluate IdM instance right-sizing.
Depends on: INFRA-S02, INFRA-S03 Outcome: EC2 no longer runs Keycloak or PostgreSQL; single authoritative Keycloak on ECS. ADR: ADR-0003 Phase 4
Backend
[BE-S01] Device registration endpoint — platform registration phase
Implement POST /devices in device-registrar: accept device public key, register device client in Keycloak (Keycloak Admin REST API), publish device.platform.registered event to Kafka. Wire up JPA persistence in DeviceEntity.
Outcome: Device can register with the platform; Kafka event emitted; device client exists in Keycloak. ADR: cerebralstratum-backend ADR-0001
[BE-S02] Device registration endpoint — user association phase
Implement POST /devices/{deviceId}/associate in device-registrar: validate user identity (JWT), assign device to user's Keycloak group, publish device.user.associated Kafka event. Include idempotency guard.
Depends on: BE-S01 Outcome: Devices can be associated with users; association event published.
[BE-S03] Kafka telemetry consumer in primary backend
Add a Kafka consumer for device telemetry topic (device.telemetry.raw). Deserialise GPS + CAN payload, persist to locations table via EntityManagerLocationRepository. Implement schema-per-tenant routing (resolve tenant from device → organisation mapping).
Depends on: BE-S01 (device → organisation mapping needed for tenant resolution) Outcome: Telemetry from device arrives in correct tenant's PostgreSQL schema.
[BE-S04] Grafana embed URL generation
Implement server-side Grafana embed URL signing in backend service. Scoped to authenticated user's fleet (organisation filter). Return signed URL via REST endpoint consumed by the frontend FleetDashboardView (backend ADR-0002).
Outcome: Frontend can render a scoped Grafana dashboard per authenticated user.
Frontend
[FE-S01] Audit KMP shared module vs React web app — identify migration gaps
Walk through webApp/ and shared/commonMain/ side-by-side. Catalogue which domain models and API clients exist only in React (TypeScript) vs. which have been migrated to KMP shared/. Produce a gap list as a Writerside topic.
Outcome: Written gap analysis; prioritised list of shared module work remaining.
[FE-S02] FleetDashboardView expect/actual for web target
Implement expect class FleetDashboardView in shared/commonMain/. actual for jsMain: React component rendering Grafana embed URL (fetched from backend). Wire up Coroutines StateFlow for loading/error/success states.
Depends on: BE-S04 (backend endpoint needed for full integration, but stub URL works for UI) Outcome: Grafana fleet dashboard renders in web app via KMP shared abstraction.
[FE-S03] Device list view — KMP shared model
Define Device domain model in shared/commonMain/ with @JsExport. Implement DeviceRepository expect/actual: REST client in jsMain, stub in jvmMain. Wire up device list in composeApp (Android/Desktop) and webApp React.
Outcome: Device list rendered across web and Compose targets from shared model.
Firmware
[FW-S01] CAN frame capture via TWAI (ESP32-S3)
Implement TWAI driver initialisation and a receive loop in Rust (esp-idf-hal TWAI bindings or direct ESP-IDF FFI). Log raw CAN frames to serial. Goal: confirm hardware path works before any network integration.
Outcome: Raw CAN frames (at minimum ignition/RPM/speed from OBD-II) visible in serial monitor. ADR: cerebralstratum-firmware ADR-0001
[FW-S02] OBD-II PID decoder
Implement PID request/response for standard OBD-II PIDs: speed (0x0D), RPM (0x0C), engine coolant temp (0x05), throttle position (0x11). Emit decoded values as a Rust struct. Include VIN request (service 09 PID 02).
Depends on: FW-S01 Outcome: Decoded telemetry struct populated from live CAN bus; no hardcoded values.
[FW-S03] Device authentication — private_key_jwt flow to Keycloak
Generate a device key pair (stored in NVS). On boot, request an OAuth2 token from Keycloak using private_key_jwt grant (backend ADR-0001). Cache token with TTL; refresh before expiry. This is the auth prerequisite for all network telemetry.
Depends on: INFRA-S02 (Keycloak on ECS must be live and reachable) Outcome: Device obtains and refreshes a valid access token from Keycloak.
[FW-S04] MQTT telemetry publish loop (LTE path)
Integrate esp-idf-mqtt to publish decoded telemetry (FW-S02) to Eclipse Hono MQTT adapter. Use device access token from FW-S03 for authentication. Publish at 1 Hz on LTE; implement QoS 1 with local queue for reconnect resilience.
Depends on: FW-S02, FW-S03 Outcome: Live telemetry visible in Hono/Kafka from a device on the bench.
[FW-S05] NTN CoAP fallback path
Implement the NTN transport path: detect LTE link loss, switch to BG95-S5 NTN mode, serialise a 29-byte CBOR snapshot, send via CoAP POST to Hono. Restore LTE path when signal recovers.
Depends on: FW-S04 Outcome: Telemetry continues (at reduced frequency) when LTE is unavailable. ADR: cerebralstratum-firmware ADR-0001 — NTN payload policy section
Completed
Session | Date | Notes |
|---|---|---|
ADR migration — all repos | 2026-05-17 | Migrated all Obsidian ADRs into repo-specific Writerside; created |