import { Coding, FhirResource } from 'fhir/r4'; import { EMAIL_PATTERN } from './registerPatientRequirements'; // The server stamps the Cognito username (the sign-in email) onto the resource it creates for a user, // and re-applies it on every PUT so a client edit cannot change or forge it. See the infrastructure repo: // utils/fhir.ts addOrUpdateCognitoUsernameTag, Practitioner/post.ts, Practitioner/put.ts. // This is read-only from the client's point of view - display it, never write it. export const COGNITO_USERNAME_TAG_SYSTEM = 'https://akashichealthrecords.com/fhir/tags/cognitoUsername'; /** * The email a user signs in with, as recorded by the server at account creation. * Returns undefined for resources created before the tag existed, or for records * with no associated login (e.g. a Practitioner created without a Cognito user). */ export const getCognitoUsername = (resource: FhirResource | undefined): string | undefined => { if (!resource?.meta?.tag) { return undefined; } return resource.meta.tag.find((tag: Coding) => tag.system === COGNITO_USERNAME_TAG_SYSTEM)?.code; }; /** * The sign-in email from the username tag, only when the tag is an email address. A newer account's * username is its UUID, which is not an address: never show it or send to it as one. */ export const getLoginEmail = (resource: FhirResource | undefined): string | undefined => { const username = getCognitoUsername(resource); return username && EMAIL_PATTERN.test(username) ? username : undefined; }; // Written ONLY by the child-activation handler, and it means "a login was activated here". That handler // is the one account-creating route that does NOT also stamp the username tag - ten others do. export const PATIENT_LOGIN_ACTIVATED_TAG_SYSTEM = 'https://akashichealthrecords.com/fhir/tags/patientLoginActivated'; /** * - DOES THIS PATIENT HAVE A LOGIN? A DIFFERENT QUESTION FROM "WHAT IS THEIR ADDRESS". * * Asking `getCognitoUsername` answers the second and was being used for the first. A patient * activated through `Patient/activate.ts` carries ONLY the marker below, never the username tag - so * the chart read "No login" for someone who had just been given one, and went on offering to create a * second. Refusing that second attempt is what produced the message calling a 47-year-old a child. * * THE TWO ARE DELIBERATELY SEPARATE, because they are separate disclosures. Spencer ruled on * 2026-08-25: *"the front desk should know a patient has an akashic account but only see basic profile * info, not clinical records until the patient gives them authorization."* That the account EXISTS is * for the desk; the ADDRESS is only shown when the record actually carries it. Never infer one from * the other, and never invent an address to fill the field. * * This mirrors the server's `utils/patientHasLogin.ts`, which already honours both tags. The two must * agree: the server's activation guard refuses a second login on exactly this test, so a client that * disagreed would keep offering an action the server would always refuse. */ export const patientHasLogin = (resource: FhirResource | undefined): boolean => { if (!resource?.meta?.tag) { return false; } if (getCognitoUsername(resource)) { return true; } return resource.meta.tag.some( (tag: Coding) => tag.system === PATIENT_LOGIN_ACTIVATED_TAG_SYSTEM && tag.code === 'true', ); };