mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-10 13:22:14 +00:00
The illness module shipped opt-in/default-off via a bornGated flag, the inverse of the standard disabled-allowlist. Make it a normal optional module that defaults on (opt-out), matching labs and its siblings. No module used bornGated other than illness, so drop the flag, its isBornGatedModule helper, and the gate resolver's born-gated branch entirely. The module stays a normal toggle under What you track and the operator-level availability override is unchanged; an account that wants it off sets an explicit false. Refresh the gate, doctor-report, labs and biomarkers comments plus the OpenAPI route descriptions accordingly.
55 lines
2.1 KiB
TypeScript
55 lines
2.1 KiB
TypeScript
/**
|
|
* Illness / condition-journal feature gate (v1.18.1).
|
|
*
|
|
* The illness journal is a standard optional module (default-on, opt-out)
|
|
* and resolves its enabled-state through the module foundation — there is
|
|
* no per-domain profile row and no second source of truth. `isIllnessEnabled`
|
|
* and the `requireIllnessEnabled` 403 guard both delegate to the module
|
|
* gate's `isModuleEnabled(userId, "illness")`, which reads the disabled
|
|
* allowlist (`modulePreferencesJson.illness !== false`) AND the operator
|
|
* server-wide availability. This mirrors `src/lib/cycle/gate.ts` so every
|
|
* `/api/illness/*` route gates identically.
|
|
*/
|
|
import { apiError } from "@/lib/api-response";
|
|
import { isModuleEnabled, requireModuleEnabled } from "@/lib/modules/gate";
|
|
|
|
/** Wire `errorCode` the iOS retry classifier branches on. */
|
|
export const ILLNESS_DISABLED_ERROR_CODE = "illness.disabled";
|
|
|
|
/**
|
|
* Fully-resolved illness availability for an account: the per-user opt-out
|
|
* AND the operator server-wide kill-switch, via the module foundation.
|
|
*/
|
|
export function isIllnessEnabled(userId: string): Promise<boolean> {
|
|
return isModuleEnabled(userId, "illness");
|
|
}
|
|
|
|
/**
|
|
* Route-guard outcome: a clear pass or a ready 403 envelope to return
|
|
* verbatim — mirrors `CycleGateResult`.
|
|
*/
|
|
export type IllnessGateResult =
|
|
| { enabled: true }
|
|
| { enabled: false; response: Response };
|
|
|
|
/**
|
|
* Enforce the gate for an `/api/illness/*` route. Returns a 403
|
|
* `illness.disabled` envelope when the account has turned the module off
|
|
* (or the operator turned it off server-wide) — even with a valid Bearer
|
|
* token. Delegates to `requireModuleEnabled` but re-stamps the
|
|
* illness-specific `errorCode` so the iOS classifier branches cleanly.
|
|
*/
|
|
export async function requireIllnessEnabled(
|
|
userId: string,
|
|
): Promise<IllnessGateResult> {
|
|
const gate = await requireModuleEnabled(userId, "illness");
|
|
if (gate.enabled) return { enabled: true };
|
|
return {
|
|
enabled: false,
|
|
response: apiError("Illness journal is not enabled", 403, {
|
|
errorCode: ILLNESS_DISABLED_ERROR_CODE,
|
|
module: "illness",
|
|
}),
|
|
};
|
|
}
|