diff --git a/www/.env.example b/www/.env.example index 2208b06..c653346 100644 --- a/www/.env.example +++ b/www/.env.example @@ -2,19 +2,10 @@ PUBLIC_AIA_API_BASE=https://api.azinstitute4autism.com PUBLIC_COUNTERS_MODE=off PUBLIC_COUNTERS_LIVE_APPROVED=false PUBLIC_COUNTERS_MOCK_RESULT=success -PUBLIC_AIA_FORMS_MODE=off -PUBLIC_AIA_FORMS_LIVE_APPROVED=false +# Optional override only: absent/empty means live on exactly 16 approved routes. +# PUBLIC_AIA_FORMS_MODE=off +# PUBLIC_AIA_FORMS_MODE=mock PUBLIC_AIA_FORMS_MOCK_RESULT=success -# Isolated-test Form A requires this environment role and approval; it remains -# unavailable in indexing-enabled builds even when both are set. -PUBLIC_AIA_FORMS_ENVIRONMENT=local -PUBLIC_AIA_FORMS_ISOLATED_TEST_APPROVED=false -# Separately authorizes the nine Form A consultation placements in an -# isolated-test build only. It has no effect on production eligibility. -PUBLIC_AIA_FORMS_CONSULTATION_TEST_APPROVED=false -# Form A production additionally requires mode=live, LIVE_APPROVED=true and -# environment=production. PUBLIC_ALLOW_INDEXING never authorizes a form. -PUBLIC_AIA_FORM_A_PRODUCTION_APPROVED=false # Explicit, local-only Form A meeting preview; requires PUBLIC_AIA_FORMS_MODE=mock. PUBLIC_AIA_FORM_A_PREVIEW=false PUBLIC_ALLOW_INDEXING=false diff --git a/www/README.md b/www/README.md index d7260d6..021233b 100644 --- a/www/README.md +++ b/www/README.md @@ -582,12 +582,25 @@ The live crawl is optional and may fail in restricted network environments. ## Forms -Forms are intentionally static and do not submit anywhere. Before production: +As of the owner decision on 2026-10-30, `npm run dev` and `npm run build` +use live Jotform Form A on exactly 16 approved placements: 10 immediate frames +and six deferred bilingual service drawers. No Form A flags are required. +Public development-host forms are owner-authorized. This does not authorize cutover. -1. Select a form backend. -2. Connect the forms. -3. Add spam protection. -4. Test validation, confirmation, and failure states. +Use `PUBLIC_AIA_FORMS_MODE=off npm run build` for an offline artifact, or +`PUBLIC_AIA_FORMS_MODE=mock npm run dev` for synthetic fixtures. Missing/empty +mode means live; obsolete `isolated-test` and other invalid values produce an +explicit configuration error. Remove old approval/environment variables from +local settings. Indexing is independent of forms; counters remain off by default. + +See the [current Form A guide](integrations/jotform/README.md) for the exact +registry, safeguards, rollback and owner acceptance requirements. Form C remains +inactive. Employee-portal private input retains its own separate gates. + +Verify matching output with +`node tools/phase10-artifact-verify.mjs --mode=staging --forms=live`; +use `--mode=indexing` for indexing output and `--forms=off` or `--forms=mock` +for those explicit builds. No actual submissions run in automated tests. ### Google Ads consultation-form conversion handoff @@ -597,7 +610,7 @@ instructions are in This is documentation only: **do not install Google tags or conversion snippets** on health-service pages or turn on enhanced conversions until AIA's privacy/HIPAA and advertising-policy review explicitly approves the complete -data flow. Count conversions only after the form API confirms success. +data flow. Any future measurement needs separately approved success and privacy semantics; the former API-success premise is historical and no tracking is active. ## Troubleshooting diff --git a/www/integrations/employee-portal/README.md b/www/integrations/employee-portal/README.md index 410e26a..07ee705 100644 --- a/www/integrations/employee-portal/README.md +++ b/www/integrations/employee-portal/README.md @@ -76,12 +76,11 @@ Use a private ciphertext file generated by `collect` or `rewrite`: ```sh AIA_PORTAL_LOCAL_PREVIEW_APPROVED=true \ AIA_PORTAL_CIPHERTEXT_FILE=/absolute/private/ciphertext-TIMESTAMP.json \ -PUBLIC_AIA_FORMS_ENVIRONMENT=isolated-test \ PUBLIC_AIA_FORMS_MODE=off PUBLIC_ALLOW_INDEXING=false \ npm run dev -- --host 127.0.0.1 ``` -The page defaults to locked/unavailable without approved valid input. Indexing +The 2026-10-30 revision removes dependence on the retired Form A environment role. Form mode is independent; `off` above is optional for local testing and cannot grant portal approval. The page defaults to locked/unavailable without its own explicit approval and valid private input. Indexing builds cannot include it. The codes never go to a server, storage or URL. No native form submits; Enter and Unlock use local WebCrypto. Only the matching stream is displayed; refresh or leaving the page locks it again. diff --git a/www/integrations/jotform/README.md b/www/integrations/jotform/README.md index 1379ca1..28d4f32 100644 --- a/www/integrations/jotform/README.md +++ b/www/integrations/jotform/README.md @@ -1,6 +1,6 @@ # AIA Form A Jotform styling and conditional-button guide -This directory contains the nonproduction visual handoff for the new AIA Form A. [`aia-form-a.css`](./aia-form-a.css) is intended for Jotform Classic Forms' **Form Designer → Styles → Inject Custom CSS** after the form is created and its settings are approved. +This directory contains the accepted CSS backup and integration guidance for AIA Form A. [`aia-form-a.css`](./aia-form-a.css) is intended for Jotform Classic Forms' **Form Designer → Styles → Inject Custom CSS** under owner-controlled configuration review. The existing repository CSS is the accepted backup; do not regenerate it from Astro styles. The CSS translates the existing AIA form treatment: Rubik typography, blue labels and text, `#fcf9f5` inputs with `#edeef3` borders, the `#ffbd59` filled button, the `#ff914d` hover/focus border, four-pixel corners, visible validation errors, and strong keyboard focus. The Astro page supplies the heading, introduction, privacy-policy link, and surrounding card. The stylesheet therefore removes the Jotform surface rather than adding another header, footer, or nested card. @@ -11,54 +11,104 @@ The current Builder theme reconciliation adds narrowly scoped `!important` decla ## Installation and comparison 1. Open the approved Form A in AIA's HIPAA-enabled Jotform account. Do not change its fields or settings from this repository workflow. -2. Keep production activation disabled while embedded-runtime, accessibility, telemetry/privacy, and release review remain pending. +2. Preserve the approved account configuration; account changes and site cutover require their separate authorization. 3. Paste the contents of `aia-form-a.css` into Jotform's custom CSS area. 4. Compare the Jotform preview with the Astro Form A mock at 390px and 1440px. Check the form surface, label rhythm, input height, button fill, outlined hover/focus state, error state, and mobile reflow. 5. Check both English and Spanish configurations. Confirm translated labels, required indicators, validation messages, confirmation copy, and the accessible iframe title supplied by the parent Astro integration. 6. Test the form in a real embedded iframe and on the direct hosted-form fallback. Confirm the iframe has a practical mobile height, does not create horizontal overflow, and does not trap keyboard focus. -The current Astro meeting preview remains `off` by default and can only be shown in a non-indexing mock build. It does not load Jotform and is not a live submission test. +The optional Astro meeting preview requires `PUBLIC_AIA_FORMS_MODE=mock` and `PUBLIC_AIA_FORM_A_PREVIEW=true` in a non-indexing build. It does not load Jotform and is not a live submission test. -## Isolated Form A iframe adapter +## Current Form A operation — superseding decision, 2026-10-30 -The Astro adapter exists only for a separately approved, non-indexing isolated test. It can render Form A at the two contact routes and five explicitly allowlisted landing routes when **all** of the following are set at build time: +The owner authorizes real Form A on the publicly reachable development host +`https://aia.web3app.dev/`. Normal development and static builds use **live** Form A +without environment flags. This intentionally supersedes the former isolated-test +and seven-route production approval gates. It is not site-cutover authorization. + +From `www/`: ```sh -PUBLIC_AIA_FORMS_MODE=isolated-test -PUBLIC_AIA_FORMS_ENVIRONMENT=isolated-test -PUBLIC_AIA_FORMS_ISOLATED_TEST_APPROVED=true -PUBLIC_AIA_FORMS_LIVE_APPROVED=false -PUBLIC_ALLOW_INDEXING=false +npm run dev +npm run build +# Optional offline/restricted artifact: +PUBLIC_AIA_FORMS_MODE=off npm run build +# Optional synthetic fixtures: +PUBLIC_AIA_FORMS_MODE=mock npm run dev ``` -It uses fixed allowlisted hosted URLs only: the contact routes use `formContext=contact` with their fixed English or Spanish language value, and the five landing routes use `formContext=landing&language=en`. `formContext` is the exact case-sensitive Jotform Unique Name supplied by the owner; it is presentation-only and does not accept visitor query values. In `isolated-test` mode, a missing gate, any other environment role, an indexing-enabled build or a route outside that seven-route allowlist renders the normal fail-closed Astro fallback. The separately documented `live` gate uses the same route allowlist and its own independent approvals. +`PUBLIC_AIA_FORMS_MODE` is optional; missing/empty means `live`. The only accepted +values are `live`, `off`, and `mock`. Remove obsolete `isolated-test` settings from +local environment files; invalid explicit values stop the build with actionable +guidance. The former live/isolated/consultation/production approvals and form +environment role are removed, with no replacement gates. `PUBLIC_ALLOW_INDEXING` +controls publication independently: both staging and indexing builds use the same +16 placements. Explicit off/mock builds contain no real Form A iframe. -## Production-gated Form A adapter +One typed registry in `src/utils/form-integration.ts` fixes every route, locale +and context. No visitor query, referrer, arbitrary URL or option preselection is +forwarded. The only origin/ID is `https://form.jotform.com/262946078314059`. +Every URL has exactly `formContext` and `language` parameters: -The adapter remains off in normal builds. A production artifact may render Form A only when all four independent settings are present at build time: +| Context | Routes | Loading | +|---|---|---| +| contact | `/contact` (en), `/es/contact` (es) | Immediate, 2 | +| landing | `/lp/aba-therapy`, `/lp/aba-insurance`, `/lp/aba-ahcccs`, `/lp/aba-private-pay`, `/lp/early-intervention` (en) | Immediate, 5 | +| consultation | `/client-consultation` (en), `/es/client-consultation` (es), `/schedule-consultation` (en) | Immediate, 3 | +| consultation | `/aba-therapy`, `/autism-evaluations`, `/learner-social-club` (en), and their `/es/` counterparts (es) | Deferred, 6 | + +The context is presentation-only. Physical Form B is retired. Form C and +`/referrals` remain inactive; other routes cannot acquire Form A by setting a mode. +The typed future Academy service copy does not publish another page. + +Live service drawers open at four seconds OR 50% scroll, canceling the unused +trigger. Dismissal or verified completion sets the existing shared 30-day +suppression timestamp. The existing service CTA overrides automatic suppression; +without JavaScript it remains a normal consultation-page link. Jotform loads only +when the drawer opens. Off mode never automatically opens an inactive drawer. +Mock mode retains the existing synthetic fixture workflow. + +A verified `submission-completed` message must match the exact approved origin, +actual activated/open iframe window, approved form ID and action. It displays a +localized acknowledgment, waits five seconds, then uses the existing slide-out. +Duplicate messages cannot restart the countdown. Manual close/navigation cancels +it; suppression remains. Deliberate reopening after completion creates a fresh +iframe. Provider-envelope acceptance still requires the owner-controlled real +submission check; synthetic browser messages are not that acceptance. + +The shared iframe preserves fixed responsive heights, accessible EN/ES titles, +`referrerpolicy="no-referrer"`, and +`sandbox="allow-forms allow-scripts allow-same-origin"`. No popup, top-navigation, +camera, microphone, payment or geolocation permissions are added. The hosted +fallback is outside the iframe and hidden without layout space until a 15-second +missing-load timeout. Late load hides it; disposal cancels timers. A localized +`noscript` fallback remains. Load does not prove application health or submission. +No helper script, cross-origin DOM inspection, arbitrary messaging or submission +forwarding is introduced. The official resize handler remains unimplemented and +conditionally acceptable only after its separate security/browser review. + +Owner-reported direct EN/ES synthetic acceptance and sampled embedded acceptance +(English contact, Spanish contact and one ABA landing page) remain recorded as +owner evidence. This change does not independently verify Jotform or resolve its +Spanish consultation dropdown discrepancy, runtime telemetry, fluent-language, +screen-reader, final HTTPS-host or operational recipient review. + +For form rollback, explicitly set `PUBLIC_AIA_FORMS_MODE=off`, rebuild, verify +`--forms=off`, and use the separately authorized artifact-switch procedure. +Removing that override restores live, so removing settings is **not** rollback. +Do not change the Jotform account as part of an Astro rollback. + +Artifact checks (build matching output first): ```sh -PUBLIC_AIA_FORMS_MODE=live -PUBLIC_AIA_FORMS_LIVE_APPROVED=true -PUBLIC_AIA_FORMS_ENVIRONMENT=production -PUBLIC_AIA_FORM_A_PRODUCTION_APPROVED=true +node tools/phase10-artifact-verify.mjs --mode=staging --forms=live +# For PUBLIC_ALLOW_INDEXING=true output: +node tools/phase10-artifact-verify.mjs --mode=indexing --forms=live +# For explicit off or mock output, select the matching --forms value. ``` -`PUBLIC_ALLOW_INDEXING=true` is required for an indexing-enabled release artifact, but it is **not** a Form A authorization setting and cannot activate a frame by itself. The production gate preserves the same fixed seven-route allowlist, URLs, `formContext`, locale parameters, fixed heights, sandbox, no-referrer policy and conditional fallback. It does not enable future Form C, service drawers, native POST forms, analytics, advertising, tracking, webhooks, API forwarding or the Jotform resize handler. - -For a deployment rollback, set `PUBLIC_AIA_FORMS_MODE=off` or remove any one of the three approval/environment values, rebuild the static artifact, verify no Form A identifier is emitted, and switch to the reviewed artifact. This disables Form A in Astro without changing the static site or the Jotform account. Do not change Jotform notification recipients, fields or availability as part of that rollback. - -The adapter has a localized iframe title, a fixed-height responsive frame, a `no-referrer` policy, a minimal sandbox, and a direct hosted-form fallback. The fallback is outside the iframe, initially hidden without layout space, revealed after a 15-second missing-load timeout, cleared on frame load or component disposal, and duplicated only as localized `