mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-10 13:22:14 +00:00
fix(settings): a fresh managed connection reads as connected again
The managed-record integration projection mapped the ledger's new `unknown` state to `disconnected`, but that mapping runs after the connection map has already established a real credential. A guardian who connected Withings on a child's record saw "Not connected" until the first hourly sync landed, beside a row whose own `connected` field said true — an invitation to revoke and redo the grant they had just made. `state` on this projection reports that a pipe exists, not that it is live; liveness is the sync verdict the card beside the pill already reads. With no ledger row and a credential present, the pipe exists.
This commit is contained in:
1 parent
e991fdf65d
commit
5c194cc9b9
2 files changed
+41
-6
No files matched your search
@@ -171,6 +171,33 @@ describe("record settings contract", () => {
|
||||
).toBe("error_reauth");
|
||||
});
|
||||
|
||||
it("reports a real credential with no ledger row as connected", () => {
|
||||
// The connection map is the credential: this branch is only reached once
|
||||
// it says a pipe exists. `unknown` on top of it means the sync ledger
|
||||
// holds no row yet — an hourly provider connected minutes ago — and this
|
||||
// projection's `state` is documented as "a pipe exists", not as liveness.
|
||||
// Calling it "Not connected" invites a guardian to revoke the grant they
|
||||
// just made.
|
||||
const connected = {
|
||||
withings: true,
|
||||
whoop: false,
|
||||
fitbit: false,
|
||||
nightscout: false,
|
||||
polar: false,
|
||||
oura: false,
|
||||
"google-health": false,
|
||||
strava: false,
|
||||
} as const;
|
||||
|
||||
expect(
|
||||
resolveManagedIntegrationState("unknown", connected, "withings"),
|
||||
).toBe("connected");
|
||||
// No credential still outranks it.
|
||||
expect(resolveManagedIntegrationState("unknown", connected, "oura")).toBe(
|
||||
"disconnected",
|
||||
);
|
||||
});
|
||||
|
||||
it("rejects a late response for another record in a second tab", () => {
|
||||
expect(() =>
|
||||
assertRecordSettingsResponseForRecord(
|
||||
|
||||
@@ -5,9 +5,14 @@ import type {
|
||||
|
||||
/**
|
||||
* A status-ledger row alone cannot prove a connection: integrations without a
|
||||
* row synthesize a healthy ledger state for the owner Settings dashboard. The
|
||||
* row synthesize a ledger state the owner Settings dashboard reads. The
|
||||
* managed projection must instead report those as disconnected until its
|
||||
* record carries a real credential or connection row.
|
||||
*
|
||||
* This projection's `state` says whether a pipe exists, never whether it is
|
||||
* live — liveness is `syncHealth.verdict`, and the card beside this pill
|
||||
* reads that. So the connection map decides first, and only then does the
|
||||
* ledger state refine the answer.
|
||||
*/
|
||||
export function resolveManagedIntegrationState(
|
||||
state: IntegrationState,
|
||||
@@ -15,9 +20,12 @@ export function resolveManagedIntegrationState(
|
||||
integration: IntegrationKey,
|
||||
): IntegrationState {
|
||||
if (!connected[integration]) return "disconnected";
|
||||
// v1.38.19 — `unknown` is the ledger saying it holds no row. The managed
|
||||
// projection publishes a closed vocabulary its card paints from, and
|
||||
// "no history" is not one of its states, so it reads as `disconnected`
|
||||
// here exactly as it does everywhere else.
|
||||
return state === "unknown" ? "disconnected" : state;
|
||||
// v1.38.19 — `unknown` is the ledger saying it holds no row, and past the
|
||||
// gate above that means a real credential exists whose first sync has not
|
||||
// landed yet. "A pipe exists" is exactly what this field reports, so it
|
||||
// reads `connected`. Reporting "Not connected" over a credential the
|
||||
// guardian created minutes ago invites them to revoke and redo the grant,
|
||||
// and it would contradict the `connected: true` the same row carries. The
|
||||
// closed vocabulary this projection publishes stays closed either way.
|
||||
return state === "unknown" ? "connected" : state;
|
||||
}
|
||||
Reference in new issue
Block a user