feat(portal): add service drawers and employee portal preview
This commit is contained in:
39 files changed
+1446
-130
No files matched your search
@@ -0,0 +1,225 @@
|
||||
# Consolidated service-drawer and employee-portal development
|
||||
|
||||
Date: 2026-10-30 UTC. Starting branch: `faithful-astro-migration`.
|
||||
Starting HEAD: `ff80ee516f0185023af1f29937e29dfb30d31f47`.
|
||||
Tracked tree and index were clean; only owner-provided `prompt.txt` was untracked.
|
||||
This is a local development checkpoint, not production authorization.
|
||||
|
||||
## Service implementation
|
||||
|
||||
The six existing EN/ES ABA Therapy, Autism Evaluations and Learner Social Club
|
||||
pages retain their URLs and consultation anchor destinations. Each existing
|
||||
anchor now has an explicit service trigger and accurate consultation label.
|
||||
Only an authorized isolated-test drawer intercepts ordinary anchor activation;
|
||||
modified clicks and no-JavaScript/unauthorized builds preserve navigation.
|
||||
No competing opener is added.
|
||||
|
||||
`service-inquiry.ts` owns four-second and half-scroll triggers, first-trigger-wins,
|
||||
positive scroll-distance handling, restored/changed height, resize observation,
|
||||
disposal, reduced-motion close, native dialog focus and close behavior. Competing
|
||||
modal/field editing cancels an automatic opportunity without polling. Closing
|
||||
stores one shared 30-day expiry timestamp, including manual-close renewals.
|
||||
Invalid, expired and implausibly future values are ignored. Storage denial uses
|
||||
memory for the current document; across full navigation suppression cannot be
|
||||
guaranteed when storage is disabled or cleared. No service or entered value is
|
||||
stored. Closing/reopening preserves the one deferred iframe and its data.
|
||||
|
||||
`service-inquiry.ts` does not modify Jotform or detect submissions. The local
|
||||
preference is functional only. Service-specific EN/ES copy is centralized in
|
||||
`data/service-inquiry.ts`, including an unpublished Academy configuration without
|
||||
an invented route. ABA 18 months–8 years, Academy 2–6 and Social Club 8–17 are
|
||||
kept distinct. No conditional diagnostic note, booking promise or preselection
|
||||
is added. Existing evaluation-page body claims still need the separately tracked
|
||||
clinical/editorial review; this pass changes CTAs and drawer copy only.
|
||||
|
||||
The separate nine-route consultation gate remains isolated-test only. A missing
|
||||
or malformed indexing flag previously passed that consultation check; it now
|
||||
requires explicit `PUBLIC_ALLOW_INDEXING=false`. The seven production-eligible
|
||||
contact/landing paths are unchanged. Full test configuration:
|
||||
|
||||
```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_AIA_FORMS_CONSULTATION_TEST_APPROVED=true
|
||||
PUBLIC_ALLOW_INDEXING=false
|
||||
```
|
||||
|
||||
## Portal implementation and fidelity boundary
|
||||
|
||||
The scoped `EmployeePortal.astro` preserves the route, metadata/noindex, sitemap
|
||||
exclusion and lack of hreflang. It provides the source-backed access-code UI,
|
||||
local Enter/Unlock handling without a native submitting form, accessible feedback,
|
||||
HMAC-before-decrypt compatibility, two-stream selection, focused passive content,
|
||||
password clearing after unlock, refresh/BFCache relocking and no-JavaScript help.
|
||||
No plaintext/code goes to a server, browser storage or URL.
|
||||
|
||||
The original source remains read-only outside Git. Structural inspection verified
|
||||
two streams, PBKDF2-SHA256 200,000 iterations, AES-256-CBC and HMAC-SHA256 over
|
||||
IV plus ciphertext, with 16-byte salt/IV and 32-byte MAC. No legitimate passphrase
|
||||
was available. An independently constructed Node crypto fixture establishes
|
||||
algorithm compatibility, but actual legacy decryption has not been performed.
|
||||
Real content layout, categories, contacts and linked workflows remain unverified.
|
||||
|
||||
Passive DOM reconstruction preserves text, headings, lists, tables and safe
|
||||
links. Scripts, handlers, inline CSS, media and embedded forms are not executed.
|
||||
Any real-source reliance on removed markup requires review; visual parity is not
|
||||
claimed. Shared-code ciphertext remains offline-guessable access friction,
|
||||
not authentication or a compliance certification.
|
||||
|
||||
`portal-input.mjs` accepts only an explicit local-preview approval, isolated
|
||||
role, false indexing and validated private ciphertext. Default, missing and
|
||||
production-shaped builds remain unavailable. The release verifier rejects portal
|
||||
ciphertext and private paths. No real ciphertext or resource is committed.
|
||||
|
||||
## Sanitized resource reconciliation
|
||||
|
||||
| Measure | Verified result |
|
||||
|---|---|
|
||||
| Original encrypted views | 2; structural metadata only |
|
||||
| Total original /hubfs/ references | Unknown, decryption blocked |
|
||||
| Distinct resources / duplicates | Unknown, not assumed to be 43 |
|
||||
| Successfully downloaded real resources | 0 |
|
||||
| Failed/unavailable resource downloads | Not tested; no decrypted URLs available |
|
||||
| Public-approved resources | 0 approved by this task |
|
||||
| Staff/internal and management/internal counts | Unknown pending decryption/classification |
|
||||
| Unresolved resource classifications | All real inventory remains unreviewed; count unknown |
|
||||
| Real links rewritten | 0 |
|
||||
| Links awaiting protected destinations | Unknown pending inventory |
|
||||
| Remaining HubSpot dependencies | Unresolved encrypted references; not declared migrated |
|
||||
| SOPS/NixOS | Inactive template prepared; no real keys or deployment |
|
||||
|
||||
The owner-run utility extracts decrypted references in memory, deduplicates by
|
||||
source URL, collects bounded HTTPS resources into ignored 0700 directories,
|
||||
retains hashes/size/MIME/status in a private 0600 manifest, and defaults to
|
||||
UNRESOLVED. It rejects unapproved redirects and executable/error responses.
|
||||
Approved rewriting requires implemented/verified destinations and server access
|
||||
control for internal files; it regenerates salts/IVs, verifies round trips and
|
||||
keeps the original as rollback. No mapping is considered migrated merely because
|
||||
a proposed URL exists. See [owner commands](../integrations/employee-portal/README.md).
|
||||
|
||||
## Source and infrastructure evidence
|
||||
|
||||
Read-only public source references on this date:
|
||||
[ABA](https://www.azinstitute4autism.com/aba-therapy),
|
||||
[evaluations](https://www.azinstitute4autism.com/autism-evaluations),
|
||||
[Social Club](https://www.azinstitute4autism.com/learner-social-club),
|
||||
[locked portal](https://www.azinstitute4autism.com/employee-portal).
|
||||
These were cache-qualified text captures. No authenticated live view or private
|
||||
source content was retrieved through the web tool. The owner-provided modal copy
|
||||
is the current development authority; fluent review remains pending.
|
||||
|
||||
The existing development flake and deployment plan were inspected. The inactive
|
||||
[NixOS guide](../integrations/nixos/README.md) cites current official SOPS/sops-nix
|
||||
documentation. It separates deployment encryption, browser access friction and
|
||||
server resource authorization. No host topology, real key/recipient or access
|
||||
service is invented. The module is not imported, activated or deployed.
|
||||
|
||||
## Validation
|
||||
|
||||
`npm run check` passed across 149 Astro files with zero diagnostics. Sequential
|
||||
core suites passed: Markdown 20/20, publication 33/33, SEO 35/35, Library 53/53,
|
||||
routes 10/10, campaigns 11/11 and Phase 8 contrast 5/5. The combined current
|
||||
Form A, nonproduction, artifact, drawer, crypto and resource tests passed 33/33;
|
||||
the narrower final artifact/resource rerun passed 18/18. The inactive Nix module
|
||||
also passed `nix-instantiate --parse`.
|
||||
|
||||
Mock, indexing-enabled, production-gated, isolated-test and final off/staging
|
||||
builds passed the artifact verifier. The isolated artifact contains 128 HTML
|
||||
routes, ten approved immediate Form A frames and six approved deferred drawer
|
||||
frames. The production-gated artifact retains exactly the original seven Form A
|
||||
frames. The final restored staging artifact contains 128 `noindex,nofollow`
|
||||
routes, an empty sitemap, zero hreflang and zero Form A frames. Link, image and
|
||||
blog audits each reported zero failures. `git diff --check` passed.
|
||||
|
||||
Guarded Chromium results:
|
||||
|
||||
- Revised service/portal runner: 39 checks, 28 screenshots, six EN/ES services
|
||||
at 320/390/768/1440px, timer and scroll races, shared suppression, storage and
|
||||
modal/editing failure cases, lifecycle reinitialization, and synthetic staff
|
||||
and management portal unlocks. It intercepted 31 fixed Jotform GET attempts.
|
||||
- Nine-placement consultation regression: 45 checks, 36 screenshots and one
|
||||
held-request fallback check; 40 fixed Jotform GET attempts intercepted.
|
||||
- Existing seven-placement Form A regression: 35 checks, 28 screenshots and
|
||||
four fallback-state checks; 38 Form A GET attempts intercepted.
|
||||
- Off-mode browser verification attempted no Jotform request and emitted no
|
||||
Form A adapter.
|
||||
|
||||
The browser guards recorded attempted requests before fulfillment or blocking.
|
||||
No non-GET/HEAD form request, Jotform submission, production API call, portal
|
||||
password transfer, advertising request, analytics request or WebSocket was
|
||||
transmitted. Child Form A responses were local fixtures; these runs do not prove
|
||||
real Jotform application behavior. Portal fixtures used random synthetic codes
|
||||
created in memory and were never written to Git.
|
||||
|
||||
Final ephemeral evidence is outside Git: revised service and synthetic portal
|
||||
screenshots/ledger at `/tmp/aia-service-portal-uncmM3`, consultation regression
|
||||
at `/tmp/aia-form-a-consultation-zMsmpB`, and the frozen seven-placement Form A
|
||||
regression at `/tmp/aia-form-a-iframe-77duED`. The normal staging artifact was
|
||||
restored last and passed with 128 routes, zero sitemap/hreflang/Form A frames and
|
||||
zero active native form actions.
|
||||
|
||||
## Owner acceptance and cutover dependencies
|
||||
|
||||
1. On loopback isolated preview, open each EN/ES service page at 320, 390, 768 and
|
||||
1440px. Verify four-second opening and (after clearing the functional preference)
|
||||
half-scroll opening; dismiss, navigate across services/locales, verify suppression
|
||||
and manual CTA reopening. Inspect real Form A errors, Submit reachability and
|
||||
focus across the frame. Do not infer child application success from frame load.
|
||||
2. Review provisional Spanish/service copy and real assistive-technology behavior.
|
||||
3. Run the private collection utility with legitimate codes, review local manifest,
|
||||
classify resources, resolve failed/redirected downloads and approve destinations.
|
||||
4. Test real staff and management decryption with local ciphertext preview, inspect
|
||||
sanitizer effects, links, responsive directories, keyboard and refresh behavior.
|
||||
5. Supply actual NixOS topology and separate age recipients privately, approve
|
||||
staff/management authorization and recovery, and verify delivery before rewriting.
|
||||
6. Forms C, production consultation routes, portal access, protected document
|
||||
serving and the overall site cutover all require separate authorization.
|
||||
|
||||
## Exact checkpoint file inventory
|
||||
|
||||
- `.gitignore`
|
||||
- `www/.env.example`
|
||||
- `www/integrations/employee-portal/README.md`
|
||||
- `www/integrations/nixos/README.md`
|
||||
- `www/integrations/nixos/portal-secrets.nix`
|
||||
- `www/reports/SESSION_HANDOFF.md`
|
||||
- `www/reports/employee-portal-migration-brief-2026-10-08.md`
|
||||
- `www/reports/migration-summary.md`
|
||||
- `www/reports/phase-10-technical-readiness-package-2026-10-22.md`
|
||||
- `www/reports/phase-9-form-a-consultation-isolated-test-2026-10-29.md`
|
||||
- `www/reports/phase-9-service-portal-consolidated-2026-10-30.md`
|
||||
- `www/reports/phase-9-two-form-integration-specification-2026-10-28.md`
|
||||
- `www/src/components/Button.astro`
|
||||
- `www/src/components/JotformIframe.astro`
|
||||
- `www/src/components/ServiceInquiryDrawer.astro`
|
||||
- `www/src/components/pages/EmployeePortal.astro`
|
||||
- `www/src/content/pages/en/aba-therapy.mdx`
|
||||
- `www/src/content/pages/en/autism-evaluations.mdx`
|
||||
- `www/src/content/pages/en/learner-social-club.mdx`
|
||||
- `www/src/content/pages/es/aba-therapy.mdx`
|
||||
- `www/src/content/pages/es/autism-evaluations.mdx`
|
||||
- `www/src/content/pages/es/learner-social-club.mdx`
|
||||
- `www/src/data/service-inquiry.ts`
|
||||
- `www/src/layouts/PageLayout.astro`
|
||||
- `www/src/scripts/employee-portal.ts`
|
||||
- `www/src/scripts/service-inquiry.ts`
|
||||
- `www/src/utils/drawer-preference.ts`
|
||||
- `www/src/utils/form-integration.ts`
|
||||
- `www/src/utils/portal-crypto.mjs`
|
||||
- `www/src/utils/portal-input.mjs`
|
||||
- `www/tools/employee-portal-migrate.mjs`
|
||||
- `www/tools/jotform-consultation-browser.mjs`
|
||||
- `www/tools/jotform-form-a.test.mjs`
|
||||
- `www/tools/phase10-artifact-verify.mjs`
|
||||
- `www/tools/phase10-artifact.test.mjs`
|
||||
- `www/tools/portal-resources.mjs`
|
||||
- `www/tools/seo.test.mjs`
|
||||
- `www/tools/service-portal-browser.mjs`
|
||||
- `www/tools/service-portal.test.mjs`
|
||||
|
||||
The owner-provided `prompt.txt` remains untracked and outside the checkpoint.
|
||||
Private directories contain no collected real resources in this run. Protected
|
||||
`merge-plan.md`, archived reconciliations and the accepted Jotform CSS backup
|
||||
are untouched.
|
||||
Reference in new issue
Block a user