mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-11 22:02:16 +00:00
feat(measurements): add EXTERNAL measurement source
Rows pushed in through a `measurements:write` Bearer token are attributed `MANUAL` today, so afterwards nobody can tell which readings came off the scale and which were typed by hand. Give that write surface its own `MeasurementSource` value, the way 0189 did for TELEGRAM and 0207 did for MCP. Enum extension only: purely additive, no row touched, `IF NOT EXISTS` makes a rerun safe, and the value is not USED in the migration so Postgres' same-transaction restriction does not bite. Declared last in the datamodel so the Prisma member order and the physical order stay identical. No backfill, and none is possible — `measurements` carries no actor or token column, so a bridge-written MANUAL row is byte-identical to a typed one. Existing rows stay MANUAL.
This commit is contained in:
1 parent
9328a4298d
commit
c2999c955d
2 files changed
+42
No files matched your search
@@ -0,0 +1,27 @@
|
||||
-- Ingest-token write provenance.
|
||||
--
|
||||
-- The `measurements:write` Bearer scope mints a token a home-automation
|
||||
-- bridge pastes into a rule; until now the rows it pushed were attributed
|
||||
-- `MANUAL`, the same label a hand-typed reading gets, so afterwards nobody
|
||||
-- could tell which readings came off the scale. Rows written under that
|
||||
-- scope carry their own `MeasurementSource` value instead, so they are
|
||||
-- distinguishable from MANUAL / TELEGRAM / MCP provenance and get an
|
||||
-- isolated idempotency namespace `(userId, type, EXTERNAL, externalId)`.
|
||||
--
|
||||
-- Purely-additive enum extension; no row touched. `ADD VALUE IF NOT EXISTS`
|
||||
-- makes a rerun safe. The new value is NOT used elsewhere in this migration,
|
||||
-- so it is safe to extend the enum in the same step (Postgres only forbids
|
||||
-- USING a freshly-added value in the same transaction). Mirrors the 0189
|
||||
-- extension that added TELEGRAM and the 0207 one that added MCP. The enum is
|
||||
-- `@@map`-ed to the snake_case type name `measurement_source`.
|
||||
--
|
||||
-- No backfill, deliberately, and none is possible: `measurements` carries no
|
||||
-- actor or token column and the audit trail never records the credential, so
|
||||
-- a bridge-written MANUAL row is byte-identical to a hand-typed one. That
|
||||
-- indistinguishability is the bug being fixed; any heuristic would relabel
|
||||
-- real hand entries as machine ones. Existing rows stay MANUAL — still
|
||||
-- editable, and correctly not badged.
|
||||
--
|
||||
-- Reversibility: Postgres cannot remove an enum value, so `EXTERNAL` stays
|
||||
-- (inert with no rows).
|
||||
ALTER TYPE "measurement_source" ADD VALUE IF NOT EXISTS 'EXTERNAL';
|
||||
@@ -1741,6 +1741,21 @@ enum MeasurementSource {
|
||||
// mirrors this exact spelling so the `/api/sync/changes` delta feed decodes
|
||||
// the rows. Feeds Workout rows only — Strava exposes no daily metrics.
|
||||
STRAVA
|
||||
// v1.38.x — measurements pushed in through a `measurements:write` Bearer
|
||||
// token: a home-automation bridge, a smart scale's own uploader, any
|
||||
// third-party sender the user pointed at their own record. Like TELEGRAM
|
||||
// and MCP this is a user-driven write rather than a server-owned
|
||||
// integration, but it does not enter through the cookie/Bearer client
|
||||
// write path, so it carries its own source label — a hand-typed reading
|
||||
// and a bridged one were otherwise indistinguishable after the fact. Its
|
||||
// own value also gives those writes an isolated idempotency namespace
|
||||
// `(userId, type, EXTERNAL, externalId)`. No client may NAME it: the batch
|
||||
// + single-POST surfaces refuse any body that asserts a source under this
|
||||
// scope, and the value is resolved server-side. Unlike the server-owned
|
||||
// sources above the rows stay value-editable, since the hardware is the
|
||||
// user's own. iOS DTO must mirror this exact spelling so the
|
||||
// /api/sync/changes delta feed decodes the rows.
|
||||
EXTERNAL
|
||||
|
||||
@@map("measurement_source")
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user