Telemetry Service Integration
Layer 2 feature, not yet implemented. Telemetry is a separate Go service (
services/telemetry/) that ingests patient exercise-engagement events and pose-tracking landmark batches from the Patient Portal. Noaudit_logforwarding, no ClickHouse, no separate compliance Postgres — see ../../telemetry/index.md for the locked design and decisions.md → Why telemetry is PG + S3, not ClickHouse for the rationale.
At-a-glance
| Concern | Where |
|---|---|
| Service | services/telemetry/ (separate Fargate task, same VPC + ALB as Core API) |
| Auth on hot path | Short-lived signed session token issued by Core API at exercise-session start; verified by signature only on Telemetry API |
| Storage — aggregates | Same RDS Postgres as Core API (pose_session_metrics, pose_rep_metrics monthly partitioned, media_session_metrics, media_buffering_events monthly partitioned) |
| Storage — replay | S3 bucket restartix-telemetry-{env}, blobs at {org_id}/{session_id}.bin.gz (binary float32 + gzip, ~3 MB per 30-min session) |
| Cross-service comms | Telemetry → Core API via Cat F service-account principal, publishes via events.Bus; Core API subscriber writes the aggregate rows |
| Reads | All on Core API; Telemetry API exposes no read endpoints to clients |
Endpoints (Telemetry API)
| Endpoint | Consumer | Purpose |
|---|---|---|
POST /v1/pose/frames | Patient Portal browser | Batched MediaPipe landmark frames (binary, 1-sec batches) |
POST /v1/media/events | Patient Portal browser | Video lifecycle events (play/pause/heartbeat/buffering/end) |
POST /v1/sessions/{id}/end | Patient Portal browser | Session finalizer; triggers aggregation + S3 blob write + events.Bus publish |
GET /v1/healthz | ALB | Health check |
The earlier POST /v1/audit/ingest, POST /v1/analytics/track, POST /v1/errors/report, and admin/dashboard endpoints have been removed — see ../../telemetry/api.md for the rationale and the canonical reference.
Cross-tenant isolation
- All ingest carries
org_idin the signed session token; Telemetry API rejects mismatched scope with 401. - S3 blob paths are partitioned by
org_idfrom the bucket prefix. - PG aggregate writes happen on the Core API side under the existing RLS-scoped subscriber — Telemetry never has direct DB write access.
- Reads in Clinic / Portal / Console all flow through Core API and inherit the same RLS, audit, classification, and per-org permission surface.
Network paths
- Patient Portal browser → Telemetry API: public HTTPS, signed token in
Authorizationheader. - Telemetry API → S3: VPC endpoint (private).
- Telemetry API → Core API (events.Bus publish): private subnet, service-account credential.
- No public Core-API-to-Telemetry path. No Telemetry-to-Postgres direct path.
Security checklist
- [ ] Signed-session-token secret rotated via Secrets Manager per credential-rotation runbook
- [ ] Cat F service-account credential for Telemetry → Core API rotated on the same cadence
- [ ] S3 bucket
restartix-telemetry-{env}is KMS-encrypted, no public access, lifecycled - [ ] Mandatory
analyticsconsent for media events; mandatorybiometricconsent for pose ingest — Telemetry API rejects with 403 otherwise - [ ] CI guard
cmd/check-telemetry-boundsrejects direct PG/S3 imports from Telemetry handlers (swap-point interfaces only) - [ ] No PII in observability logs from Telemetry API (
pseudonym.UserIDif any cross-tenant aggregate logging needed; not used for PG aggregates which are clinic-scoped)