mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 13:01:00 +00:00
- Render a record-keyed status view for managed profiles\n- Refuse shared Settings links before actor controls mount\n- Localize intentional unavailable states
53 lines
1.6 KiB
TypeScript
53 lines
1.6 KiB
TypeScript
export type RecordSettingsRelationship = "guardian" | "self" | "adult-manager";
|
|
|
|
export interface RecordSettingsAccess {
|
|
actorId: string;
|
|
recordId: string;
|
|
recordKind: "managed" | "self" | "shared";
|
|
relationship: RecordSettingsRelationship;
|
|
}
|
|
|
|
/**
|
|
* Assert a record-settings capability that is deliberately narrower than a
|
|
* general MANAGE grant. A MANAGE grant on an adult's ordinary record is not a
|
|
* route into their identity or configuration.
|
|
*/
|
|
export function assertRecordSettingsAccess(
|
|
access: RecordSettingsAccess,
|
|
destination: "guardian",
|
|
): void {
|
|
if (
|
|
destination === "guardian" &&
|
|
(access.recordKind !== "managed" || access.relationship !== "guardian")
|
|
) {
|
|
throw new Error("Guardian configuration is unavailable for this record");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Convert the resolver's authenticated record into the explicit settings
|
|
* boundary. The resolver authenticates the active grant; this function keeps
|
|
* the managed-record marker and relationship requirement visible at every
|
|
* record-settings route.
|
|
*/
|
|
export function resolveGuardianRecordSettingsAccess(context: {
|
|
actor: { id: string };
|
|
grantId: string | null;
|
|
user: { id: string; managedProfileAt: Date | null };
|
|
}): RecordSettingsAccess | null {
|
|
const access: RecordSettingsAccess = {
|
|
actorId: context.actor.id,
|
|
recordId: context.user.id,
|
|
recordKind: context.user.managedProfileAt ? "managed" : "self",
|
|
relationship: context.grantId ? "guardian" : "self",
|
|
};
|
|
|
|
try {
|
|
assertRecordSettingsAccess(access, "guardian");
|
|
} catch {
|
|
return null;
|
|
}
|
|
|
|
return access;
|
|
}
|