feat(phase9): isolate forms and counters for nonproduction

This commit is contained in:
DeCentN2Madness committed 2026-10-21 23:02:13 -07:00
1 parent e874b26bb9
commit d20372fe33
20 files changed
+454 -157

No files matched your search

@@ -0,0 +1,48 @@
# Phase 9 P9-03 — Local Astro Form Isolation
Date: 2026-10-21
Status: Implemented and verified locally; Jotform creation and live integration remain unauthorized.
## Scope
The native empty-action forms were replaced with an explicit fail-closed presentation layer. `PUBLIC_AIA_FORMS_MODE` defaults to `off`; invalid values and `live` without an explicit approval flag resolve to `off`. The runtime currently exposes only `off` and `mock`; no live Jotform adapter or URL exists.
### Modes
- **off:** no native `<form>`, no action, no POST surface, no Jotform resource, disabled controls, and a localized telephone/contact fallback.
- **mock:** local synthetic button states (`success`, `failed`, or `unavailable`) bound by `mock-form.ts`; no persistence, backend, notification, cookie, analytics, or external request.
- **live:** reserved for a separately authorized adapter and approved form IDs. It fails closed today. The historical source-template ID `250727122848156` is not embedded.
The logical route map records nine existing native enquiry instances and five campaign journeys. It is data only and does not activate a submission path.
## Changed files
- `src/utils/form-integration.ts` — typed mode resolver, logical form map, mock-result resolver.
- `src/data/form-integrations.ts` — public mapping export.
- `src/scripts/mock-form.ts` — local mock form and counter interaction binder.
- `src/components/ContactForm.astro` — off/mock presentation with telephone fallback.
- `src/components/FormShell.astro` — off/mock presentation and localized status.
- `src/components/ServiceInquiryDrawer.astro` — off/mock drawer presentation; existing drawer behavior retained.
- `src/layouts/PageLayout.astro` — explicit referral/service logical form mapping.
- `src/utils/form-messages.ts` — localized mock and fallback messages.
- `.env.example` — off-by-default mode, approval flag and mock result settings.
- `tools/seo.test.mjs`, `tools/library.test.mjs`, `tools/phase8-interactions.mjs` — regression assertions for the inactive form surface.
- `tools/phase9-nonproduction.test.mjs` — mode, mapping and source-isolation coverage.
## Mapping
The shared implementation covers `/contact`, `/es/contact`, `/client-consultation`, `/es/client-consultation`, `/schedule-consultation`, `/referrals`, `/aba-therapy`, `/autism-evaluations`, and `/learner-social-club`. The campaign journeys `/lp/aba-therapy`, `/lp/aba-insurance`, `/lp/aba-ahcccs`, `/lp/aba-private-pay`, and `/lp/early-intervention` are mapped to the future Service Consultations form without changing their designs or routes.
## Validation
- `npm run check` — passed (125 files, no diagnostics).
- Markdown 20/20; publication 33/33; SEO 35/35; Library 53/53; routes 10/10; Phase 8 5/5; campaign 11/11; P9 nonproduction 5/5.
- Normal build — passed (128 pages).
- Mock build (`PUBLIC_AIA_FORMS_MODE=mock`, failed fixture) — passed; no Jotform URL or external form request was emitted.
- Guarded Chromium — 41 checks, 0 failures, with the off-mode Spanish form and no-JavaScript checks passing. `productionAttempt: false`; external Leaflet requests were blocked by the test guard.
- Link, image and blog audits — passed with zero findings.
- Explicit offline route reconciliation was regenerated as `reports/route-reconciliation-2026-10-22-offline.json` from saved request evidence and passed its subsequent `--check`; no production crawl was performed. The final normal staging build contained 128 HTML pages, all `noindex,nofollow`, an empty sitemap and zero hreflang links.
## Deferred gates
The owner-created three-form Jotform architecture, field requirements, Builder settings, bilingual behavior, notification privacy, synthetic submission testing, CSP/referrer policy, and production activation remain P9-03/P9-07/P9-09 decisions. No form data reaches Contabo, Google, GA4 or a Jotform endpoint in this batch.
@@ -0,0 +1,63 @@
# Phase 9 P9-09 — Contabo Deployment Readiness and Rollback Plan
Date: 2026-10-21
Status: Planning only; no VPS, DNS, Cloudflare, nginx or TLS system was contacted or changed.
## Proposed topology
The preferred target is a static Astro artifact served by an owner-controlled Contabo VPS, with the existing non-PHI API kept separate. Jotform would receive protected lead submissions directly after independent approval. The Raspberry Pi 4B remains a fallback. HubSpot remains the current public host until Phase 10 authorization.
This is a proposal, not a verified description of the production machine. The owner must supply sanitized facts for the VPS operating system/NixOS generation, deployment user and permissions, nginx or equivalent service, TLS termination, Cloudflare/DNS ownership, current API boundary, backup location, monitoring, and rollback authority. No secrets, private keys or credentials are required for this planning report.
## Artifact and release layout
Build in a clean, locked toolchain and publish an immutable artifact such as:
```text
/srv/aia/releases/<git-sha>/dist/
/srv/aia/current -> /srv/aia/releases/<git-sha>/dist
/srv/aia/shared/ # only reviewed non-secret shared files
```
Upload to a temporary release directory, verify the manifest and hashes, apply ownership/permissions, then atomically switch `current`. Keep at least the last known-good release and record the build SHA, Node/npm versions, lockfile hash and environment mode. Never put `.env` secrets in the static artifact.
## Cutover and rollback
1. Build and audit locally in normal staging mode, then separately build the approved indexing-enabled artifact.
2. Verify route, asset, robots, sitemap, redirect and 404 manifests before upload.
3. Upload the immutable release without changing DNS.
4. Run loopback or host-local checks through the intended web server.
5. During an approved window, atomically switch the symlink and verify HTTPS, canonical host, slashless routes, query preservation, static assets, real 404s and redirect targets.
6. If health checks fail, stop traffic changes and atomically point `current` back to the prior release. Preserve logs and manifests for review; do not hot-edit the failed artifact.
Rollback triggers include unexpected 5xx responses, wrong host/canonical behavior, missing assets, a non-empty staging sitemap, indexing headers on a staging artifact, redirect loops, unapproved form/API/counter traffic, or inability to reproduce the release manifest.
## Required server behavior
- HTTPS and canonical `www.azinstitute4autism.com` behavior must be verified by the hosting owner.
- Slashless public URLs, query strings and fragments must remain intact.
- Static assets need long-lived immutable caching only when their names are content/version safe; HTML should use short revalidation appropriate to the cutover plan.
- Staging must retain `noindex,nofollow`, an empty sitemap and no hreflang. `noindex` is not access control; access restriction must be separately configured if needed.
- Production requires the approved sitemap/robots policy and real 404 handling.
- The temporary `/lp` review index must be excluded from the intended production artifact or explicitly owner-approved before a release.
## Integration isolation
`PUBLIC_COUNTERS_MODE=off` and `PUBLIC_AIA_FORMS_MODE=off` are the safe staging defaults. A live counter adapter, Jotform IDs, analytics, advertising and conversion events require separate approvals and environment gates. Jotform answers must not traverse Contabo; the existing API may handle only approved non-PHI operations. No arbitrary query strings, referrers or form answers may enter logs or tracking.
## Local rehearsal
The installed environment did not expose an `nginx` executable, so no nginx service or configuration was touched. The normal Astro artifact was built successfully and inspected locally; the guarded loopback Chromium run recorded zero production attempts. A future rehearsal may use an isolated temporary nginx prefix or a loopback static server, provided it cannot affect active services or reach production systems.
## Phase 10 acceptance checklist
- Owner supplies and reviews sanitized topology/configuration facts.
- Reproducible build and artifact manifest are archived.
- HTTPS, canonical host, redirects, 404s, query handling and assets pass from the intended server.
- Staging/indexing modes are proven separate.
- Counter/form modes and third-party requests are verified in the target environment.
- Backups, release retention, monitoring and rollback operator are named.
- Real accessibility, language, clinical, privacy and legal approvals are recorded.
- A release owner authorizes go/no-go and rollback authority.
P9-09 remains pending. This report does not authorize deployment or infrastructure changes.
@@ -0,0 +1,44 @@
# Phase 9 P9-04 — Likes/Views Isolation
Date: 2026-10-21
Status: Implemented and verified locally; live activation remains prohibited.
## Scope
This batch removes the previous implicit production API fallback from the article engagement component. `LikeViewCounter.astro` now resolves an explicit `off`, `mock`, or future `live` configuration through `src/utils/counter-mode.ts`. The default is `off`; an API URL by itself cannot enable live behavior.
`live` is accepted only when `PUBLIC_COUNTERS_LIVE_APPROVED=true` and the configured origin is HTTPS, then remains fail-closed at runtime because no live adapter is implemented in this batch. `counterModeForRuntime()` exposes only `off` or `mock` until a separately authorized production adapter exists.
## Runtime contract
| Mode | Runtime behavior | Network/cookie behavior |
| --- | --- | --- |
| `off` (default) | Disabled like control, unavailable message, no real metric value | No API request, credential, cookie read or cookie write |
| `mock` | Deterministic local interaction and demo-only status | No external request, persistence, credential or cookie |
| `live` | Fails closed to `off` in this release | No live traffic; future activation requires a separate approval and adapter |
`PUBLIC_COUNTERS_MOCK_RESULT` controls only the deterministic local fixture state. It does not represent a production metric. English, Spanish and Arabic article messages remain localized, including the unavailable state and RTL direction attributes.
## Changed files
- `src/components/LikeViewCounter.astro` — removed fetch/cookie/API fallback and added explicit mode presentation.
- `src/utils/counter-mode.ts` — typed resolver and fail-closed runtime mode.
- `src/scripts/likes-views.ts` — exports the resolver rather than a live client.
- `src/utils/article-messages.ts` — localized unavailable engagement text.
- `src/scripts/mock-form.ts` — deterministic local counter interaction without persistence.
- `.env.example` — documents off-by-default mode, approval flag and mock result.
- `tools/phase9-nonproduction.test.mjs` — mode, source-isolation and deterministic behavior coverage.
## Validation
- `npm run check` — passed (125 files, no diagnostics).
- Existing Markdown, publication, SEO, Library, route, Phase 8 and campaign suites — passed (167 tests total).
- `node --experimental-strip-types --test tools/phase9-nonproduction.test.mjs` — 5/5 passed.
- Normal Astro build — passed (128 pages).
- Mock build with counter/forms mock settings — passed; no external form URL or API URL was emitted.
- Guarded Chromium interaction run — 41 checks, 0 failures, `productionAttempt: false`. The only review result was the pre-existing native dialog/browser focus boundary; no production request was transmitted. Leaflet requests were blocked by the guard.
- A separate loopback Chromium probe opened `/library/aba-therapy-benefits` in off mode: the control was disabled, the unavailable message remained, `document.cookie` stayed empty, and the guarded request list contained zero non-loopback or mutating requests.
## Future approval requirements
P9-04 remains pending. Before any live adapter is implemented, AIA/privacy/security owners must approve the API origin, CORS and credential policy, cookie behavior, environment allowlist, staging isolation, consent implications, and production monitoring. A future live test must use an approved environment and synthetic data; this batch intentionally performs no production API request.