import type { Questionnaire } from 'fhir/r4'; import type { PublishedPublicForm } from '../services/PublicFormService'; import { isPublicFormDraft } from './publicFormKind'; /** * SPLITTING ONE LIST INTO TWO SECTIONS -, and the reason is measured rather than aesthetic. * * Spencer, watching the Platform Manager's screen: *"lumping public forms in with questionnaires is * confusing since technically they're two totally different things that are just leveraging the same * questionnaire form builder."* * * THE CONFUSION IS MEASURED. That screen read *"1 active questionnaire"* above a list containing the * practice's **public website contact form** and a clinical intake draft, with the same `Delete` on both - * one of which takes a page off the practice's public website. **It fooled a session that had just read * the code**: claude-4 concluded Great River had no public form and reported a card blocked on Spencer * publishing one, and Spencer answered *"I also have a public form there called 'contact us'."* It had been * live, with CAPTCHA, the whole time. * * ONE BUILDER, ONE PRIMITIVE - this splits SECTIONS, never engines. A public form **is** a published * questionnaire, and that is the product's value rather than an implementation detail: because it is * authored in the questionnaire builder, every field is FHIR-shaped from the moment it is captured, which * is what makes a submission promotable onto a patient's record later. */ /** Whether we know which questionnaires are published publicly. Three states, never two. */ export type PublicFormRead = 'loading' | 'ready' | 'failed'; export interface FormRow { questionnaire: Questionnaire; /** Present this row is a public form, and this is what the server says about it. */ publicForm?: PublishedPublicForm; } export interface FormsSections { /** * FALSE UNTIL THE PUBLIC-FORM READ SUCCEEDS, and this is the field the whole module turns on. * * The kind of a row is not a property of the Questionnaire - it is the answer to *"has this been * published as a public form?"*, which comes from a separate read. If that read failed we do not know * which list anything belongs in, and **two labelled groups would be a claim we cannot support**: every * row would land in "Clinical questionnaires", including a live contact form with a Delete beside it. * So the sections are not offered at all, and the caller shows one list with the warning it already * has. **An empty group and an unknown group must never render the same** is that exact * defect one layer down, where a failed read and "no public forms" produced identical unbadged rows. */ grouped: boolean; publicForms: FormRow[]; clinical: FormRow[]; /** All rows, in their original order - what the caller renders when `grouped` is false. */ all: FormRow[]; } /** * Group a complete questionnaire list by kind. * * `questionnaires` MUST be the whole list, not a page. Counting or grouping a page produces a number * that reads as a measurement and is not one - the same family as this header's three previous defects * (an absent count rendering as zero; a count describing a set the reader cannot see; a count including * public forms while naming them clinical). */ export const groupFormsByKind = ( questionnaires: Questionnaire[], publicForms: PublishedPublicForm[], read: PublicFormRead, ): FormsSections => { const byQuestionnaireId = new Map(); for (const form of publicForms) { // A public form stays public once unpublished: unpublishing takes it off the website, it does // not make it clinical. An active registration outranks an inactive one for the same form. if (!form.questionnaireId) continue; const held = byQuestionnaireId.get(form.questionnaireId); if (!held || (!held.active && form.active)) byQuestionnaireId.set(form.questionnaireId, form); } const all: FormRow[] = questionnaires.map((questionnaire) => { const publicForm = questionnaire.id ? byQuestionnaireId.get(questionnaire.id) : undefined; return publicForm ? { questionnaire, publicForm } : { questionnaire }; }); if (read !== 'ready') { // No grouping and no counts. See `grouped` - we cannot tell the kinds apart, and a screen that // splits them anyway is asserting something it does not know. return { grouped: false, publicForms: [], clinical: [], all }; } return { grouped: true, publicForms: all.filter((row) => row.publicForm !== undefined || isPublicFormDraft(row.questionnaire)), clinical: all.filter((row) => row.publicForm === undefined && !isPublicFormDraft(row.questionnaire)), all, }; }; /** * WHAT A PUBLIC-FORM ROW CAN HONESTLY SAY ABOUT BEING LIVE. * * THE SERVER DOES NOT KNOW WHETHER THE SHORTCODE IS ON A PAGE. `FormRegistrationSummary` carries a * `publicUrl`, and **nothing ever writes it** - registration happens when the form is published, which is * before anyone has embedded it, and only WordPress ever learns where a shortcode ended up. * So *"not on a page yet"* is **not a fact this screen can assert**. On akashic.health there is no * `wp_options` to read at all, and claiming a form is not embedded because we cannot see WordPress is the * same defect as every other one on this board: an absence rendered as an answer. * * THE COPY IS THEREFORE AN INSTRUCTION, NOT A STATE - *"add the shortcode to a page"* is true whether or * not it is already on one, and it is the thing the reader needs either way. The `live` state is claimed * ONLY when something actually told us the page. * * ADDED THE STATE THAT IS ACTUALLY OBSERVED, and it does not soften anything above. The public * read now records that a visitor was served this form, so `served` is a MEASUREMENT - the server watched * it happen - while `live` remains a report about where a shortcode was pasted and `unknown` remains an * instruction rather than the answer *"not on a page yet."* * The page in `served` comes from the `Referer` and is SPOOFABLE. Render it as text, never as a link, * and never decide anything on it. */ export type PublicFormPlacement = /** * - SOMEBODY ACTUALLY LOADED IT, and the server watched that happen. The strongest of the * three, and the only one that is a measurement. */ | { state: 'served'; page?: string; at: string } /** WordPress told us which page the shortcode is on. True about the SHORTCODE, not about a visitor. */ | { state: 'live'; page: string } | { state: 'unknown' }; export const describePlacement = ( form: PublishedPublicForm, /** Page titles keyed by form handle, from WordPress where it is available. Absent everywhere else. */ pagesByHandle?: Record, ): PublicFormPlacement => { /* * THE OBSERVATION OUTRANKS THE PLACEMENT, and the case that decides it is not hypothetical: a * shortcode sitting on an UNPUBLISHED DRAFT page reads as embedded to WordPress and has never been * served to anyone. *"Somebody loaded this"* is the stronger sentence, so it wins when we have both. */ if (form.lastServedAt) { return { state: 'served', page: form.lastServedFrom?.trim() || undefined, at: form.lastServedAt }; } const page = pagesByHandle?.[form.formHandle]?.trim() || form.publicUrl?.trim(); return page ? { state: 'live', page } : { state: 'unknown' }; }; /** * - WILL THIS FORM ACTUALLY WORK ON THE HOST WE ARE LOOKING AT IT FROM? * * THE FAILURE IS SILENT AND TOTAL, AND NOBODY IS WATCHING FOR IT. A practice builds their site on a * staging host, publishes their intake forms there, and switches to the real domain at go-live. The * authorized-domain fence is enforced at the token mint, the submission and the framed render, so on the * new host EVERY published form stops working at once - and to a visitor it reads as a broken website * rather than a wrong setting. **The screen that manages these forms is the one place it can be caught * before a patient hits it.** * * THIS IS THE SAME MATCH THE SERVER MAKES, deliberately duplicated rather than approximated. `domainMatches` * in `aws/sam/services/api/src/utils/form-origin.ts` compares a host against the list with a suffix rule and * a `www.` strip; a screen that guessed differently would either cry wolf on a working form or stay quiet on * a broken one, and the second is the one that ships an outage. * It is a WARNING, never a gate - the server is the authority, and nothing here decides anything. */ export const hostIsAuthorized = (host: string, authorizedDomains: string[]): boolean => { if (!host || authorizedDomains.length === 0) return false; const normalizedHost = host.toLowerCase().replace(/^www\./, ''); return authorizedDomains.some((domain) => { const normalizedDomain = domain.toLowerCase().replace(/^www\./, ''); return normalizedHost === normalizedDomain || normalizedHost.endsWith(`.${normalizedDomain}`); }); }; /** * The published forms that will NOT work on `host`. * * `host` MUST BE THE PRACTICE'S OWN SITE, and the caller is responsible for that. On akashic.health the * browser's host is ours, not theirs - comparing against it would report every form on every practice as * broken, which is the cry-wolf failure that gets a warning ignored forever. Callers pass a host only on * the WordPress mount, where the address bar genuinely IS the practice's domain. * * A form whose `authorizedDomains` we do not have is NOT reported. An absent list is *"we were not told"*, * and rendering that as *"authorized nowhere"* would be the same defect this module already carries two * warnings about: an absence rendered as an answer. */ export const formsNotServedOnHost = (forms: FormRow[], host: string | null): FormRow[] => { if (!host) return []; return forms.filter((row) => { const domains = row.publicForm?.authorizedDomains; if (!domains || domains.length === 0) return false; return !hostIsAuthorized(host, domains); }); };