From 0eb3fcc3f6f47b3d1219fd3ae78f105fa2376c7a Mon Sep 17 00:00:00 2001 From: Jeffrey Hales Date: Wed, 28 Oct 2026 18:13:32 -0700 Subject: [PATCH] feat(forms): gate Form A production embedding --- www/.env.example | 7 +- www/integrations/jotform/README.md | 19 ++++- www/reports/SESSION_HANDOFF.md | 1 + ...-technical-readiness-package-2026-10-22.md | 2 +- ...ase-9-form-a-production-gate-2026-10-28.md | 54 ++++++++++++++ ...-jotform-implementation-plan-2026-10-18.md | 6 +- ...jotform-integration-contract-2026-10-18.md | 12 +-- ...form-verification-checklist-2026-10-18.csv | 3 +- www/src/components/JotformIframe.astro | 4 +- .../campaign/ConsultationForm.astro | 1 + .../campaign/EarlyInterventionPage.astro | 3 +- www/src/components/pages/ContactPage.astro | 1 + www/src/utils/form-integration.ts | 45 +++++++++--- www/tools/jotform-form-a-browser.mjs | 10 ++- www/tools/jotform-form-a.test.mjs | 39 +++++++++- www/tools/phase10-artifact-verify.mjs | 73 ++++++++++++++++--- www/tools/phase10-artifact.test.mjs | 51 +++++++++++-- 17 files changed, 284 insertions(+), 47 deletions(-) create mode 100644 www/reports/phase-9-form-a-production-gate-2026-10-28.md diff --git a/www/.env.example b/www/.env.example index d208c8a..cf5f459 100644 --- a/www/.env.example +++ b/www/.env.example @@ -5,10 +5,13 @@ PUBLIC_COUNTERS_MOCK_RESULT=success PUBLIC_AIA_FORMS_MODE=off PUBLIC_AIA_FORMS_LIVE_APPROVED=false PUBLIC_AIA_FORMS_MOCK_RESULT=success -# The real Form A adapter is test-only. All three gates below are required; -# indexing-enabled builds always fail closed even when they are set. +# 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 +# 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/integrations/jotform/README.md b/www/integrations/jotform/README.md index 46f7b65..1951a60 100644 --- a/www/integrations/jotform/README.md +++ b/www/integrations/jotform/README.md @@ -31,7 +31,22 @@ PUBLIC_AIA_FORMS_LIVE_APPROVED=false PUBLIC_ALLOW_INDEXING=false ``` -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. A missing gate, any other environment role, an indexing-enabled build, a route outside that seven-route allowlist, or `live` mode renders the normal fail-closed Astro fallback instead. +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. + +## Production-gated Form A adapter + +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: + +```sh +PUBLIC_AIA_FORMS_MODE=live +PUBLIC_AIA_FORMS_LIVE_APPROVED=true +PUBLIC_AIA_FORMS_ENVIRONMENT=production +PUBLIC_AIA_FORM_A_PRODUCTION_APPROVED=true +``` + +`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 Forms B/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 `