feat(phase9): isolate forms and counters for nonproduction
This commit is contained in:
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.
|
||||
Reference in new issue
Block a user