Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a643383e79
|
||
|
|
2fca442922
|
||
|
|
e002427aef
|
||
|
|
eeff641a1d
|
||
|
|
96288b1eb8
|
||
|
|
8c19266760 | ||
|
|
89cdb00765 | ||
|
|
596246f20a | ||
|
|
475dd3379b
|
||
|
|
81492125f4 | ||
|
|
36d417a422 | ||
|
|
4987f5ee1a | ||
|
|
362b984753 | ||
|
|
ba93a54942 | ||
|
|
5fa54719b2 | ||
|
|
e224616b99 | ||
|
|
a72470459a | ||
|
|
80e0c405bc | ||
|
|
5c8ba2e11e | ||
|
|
85def8466c | ||
|
|
b5e606a839 | ||
|
|
8dff6a5ad0 | ||
|
|
b0cf2d7119 | ||
|
|
3e05458944 | ||
|
|
4d7955fb48 | ||
|
|
81d1f21236 | ||
|
|
aa406e623d | ||
|
|
5d6d4af8bd | ||
|
|
d944cb0afe | ||
|
|
9d6e0b982e | ||
|
|
167277b037 | ||
|
|
db8d90f579 | ||
|
|
16a72caa00 | ||
|
|
95c5f229f5 | ||
|
|
55adb79705 | ||
|
|
e97f0ea9b4 | ||
|
|
ff80ee516f | ||
|
|
6a5e54e130 | ||
|
|
ebc99c0f36 | ||
|
|
0eb3fcc3f6 | ||
|
|
1a56cd7603 | ||
|
|
7cdf209032
|
||
|
|
eecb582665
|
||
|
|
61b2bd0f1e
|
||
|
|
a635a5f55c | ||
|
|
63806f106c | ||
|
|
f41af1966e
|
||
|
|
7a6cab29db
|
||
|
|
b102a061fe
|
||
|
|
356282f61c
|
||
|
|
ce17728e0b
|
||
|
|
704c8d27c9
|
||
|
|
d20372fe33
|
||
|
|
e874b26bb9
|
||
|
|
08612d97e6
|
||
|
|
f98576f3ae
|
||
|
|
537f9864a0
|
||
|
|
59911eb929
|
||
|
|
8e64d32209
|
||
|
|
b5bc95bc2b
|
||
|
|
a699d467f1
|
||
|
|
8192ea71c4 | ||
|
|
8646792d46
|
||
|
|
0957c06a18 | ||
|
|
6f5ac3c0d2
|
||
|
|
b20c253383
|
||
|
|
76a035424d
|
||
|
|
34d5394b3c
|
||
|
|
bc399b43b6
|
||
|
|
051fb7c108
|
||
|
|
4079156776
|
||
|
|
4ed01d7d28
|
||
|
|
c720917627 | ||
|
|
2ce8c849c0 | ||
|
|
32112edbde
|
||
|
|
f28bf9ad06 | ||
|
|
1e1aafa27a
|
||
|
|
cd097d0e76
|
||
|
|
ea2f1eaa05
|
||
|
|
60c534d4a2
|
||
|
|
147b55c586 | ||
|
|
6e0ff0c596 | ||
|
|
21b0ad7461 | ||
|
|
6db91105da | ||
|
|
cc8e861b33 | ||
|
|
d127309a13 | ||
|
|
b592524204 | ||
|
|
5c89f10e9f
|
||
|
|
cfd6e630a3
|
||
|
|
ac43ae3669
|
||
|
|
5554489d70
|
||
|
|
ae6ab88e19
|
||
|
|
a0cbcc7e71
|
||
|
|
679731d3e2
|
||
|
|
96d3c138f6
|
||
|
|
6648d1d7d5
|
||
|
|
9c391c8c05
|
||
|
|
77b83f5d21
|
||
|
|
8c9c581cc0
|
||
|
|
46090e9159
|
||
|
|
fd8e12f925
|
No files matched your search
@@ -59,5 +59,5 @@ temp/
|
|||||||
Thumbs.db
|
Thumbs.db
|
||||||
Desktop.ini
|
Desktop.ini
|
||||||
|
|
||||||
# Read-only wget mirror used as migration source material
|
# Private portal collection, mappings and ciphertext; never a public asset source.
|
||||||
/www.azinstitute4autism.com/
|
/www/private/employee-portal/
|
||||||
@@ -82,6 +82,35 @@ sandboxed command-line tools may fail HTTPS certificate verification. Do not
|
|||||||
disable certificate verification for package installation or sensitive
|
disable certificate verification for package installation or sensitive
|
||||||
retrievals; use live web search or review the retrieval from the host instead.
|
retrievals; use live web search or review the retrieval from the host instead.
|
||||||
|
|
||||||
|
## Optional local browser environment
|
||||||
|
|
||||||
|
The repository now provides a Linux-only `browser` development shell, separate
|
||||||
|
from the default content-editing shell. In a normal host terminal, from the
|
||||||
|
repository root:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
nix --extra-experimental-features "nix-command flakes" develop .#browser
|
||||||
|
```
|
||||||
|
|
||||||
|
It supplies a lockfile-matched Playwright driver, Chromium, headless shell and
|
||||||
|
font configuration. New processes launched inside this shell inherit
|
||||||
|
`PLAYWRIGHT_MODULE` and `PLAYWRIGHT_BROWSERS_PATH`; existing sessions do not.
|
||||||
|
For a guarded real-page smoke test, run from `www`:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
TMPDIR=/tmp npm run build
|
||||||
|
TMPDIR=/tmp node tools/playwright-smoke.mjs
|
||||||
|
```
|
||||||
|
|
||||||
|
Preview and browser run in the same process environment, avoiding dependence on
|
||||||
|
remote MCP transport or cross-execution loopback access. All non-loopback and
|
||||||
|
non-GET/HEAD browser requests are blocked. Results/screenshots stay in `/tmp`.
|
||||||
|
The tool does not grant access to files or sockets denied by the autonomous
|
||||||
|
profile. If Nix realization, Chromium startup or loopback access is denied, keep
|
||||||
|
that result as an environment limitation and use the normal host terminal;
|
||||||
|
do not weaken TLS, identity, signing or sandbox configuration. No global MCP
|
||||||
|
configuration or launcher permissions were changed for this setup.
|
||||||
|
|
||||||
## Git limitation
|
## Git limitation
|
||||||
|
|
||||||
Codex always protects `.git` recursively in its `workspace-write` sandbox.
|
Codex always protects `.git` recursively in its `workspace-write` sandbox.
|
||||||
|
|||||||
@@ -383,7 +383,6 @@ www/
|
|||||||
rtl.css
|
rtl.css
|
||||||
|
|
||||||
tools/
|
tools/
|
||||||
extract-site.mjs
|
|
||||||
crawl-live-site.mjs
|
crawl-live-site.mjs
|
||||||
audit-links.mjs
|
audit-links.mjs
|
||||||
generate-redirects.mjs
|
generate-redirects.mjs
|
||||||
@@ -856,39 +855,17 @@ src/pages/es/[...slug].astro
|
|||||||
|
|
||||||
Implement routing in a clean, maintainable way.
|
Implement routing in a clean, maintainable way.
|
||||||
|
|
||||||
## Extraction scripts
|
## Migration utility scripts
|
||||||
|
|
||||||
Create:
|
Create:
|
||||||
|
|
||||||
```txt
|
```txt
|
||||||
tools/extract-site.mjs
|
|
||||||
tools/crawl-live-site.mjs
|
tools/crawl-live-site.mjs
|
||||||
tools/audit-links.mjs
|
tools/audit-links.mjs
|
||||||
tools/generate-redirects.mjs
|
tools/generate-redirects.mjs
|
||||||
tools/generate-sitemap.mjs
|
tools/generate-sitemap.mjs
|
||||||
```
|
```
|
||||||
|
|
||||||
### `extract-site.mjs`
|
|
||||||
|
|
||||||
This script should:
|
|
||||||
|
|
||||||
- scan the available source and generated output
|
|
||||||
- identify HTML files
|
|
||||||
- infer URL paths
|
|
||||||
- identify page type
|
|
||||||
- identify blog posts
|
|
||||||
- identify listing pages
|
|
||||||
- extract title/meta/H1/body/main content
|
|
||||||
- extract canonical and Open Graph metadata
|
|
||||||
- extract schema/JSON-LD where present
|
|
||||||
- convert blog posts to Markdown where feasible
|
|
||||||
- create page Markdown where useful
|
|
||||||
- copy/normalize assets
|
|
||||||
- rewrite local asset references
|
|
||||||
- create initial reports
|
|
||||||
|
|
||||||
The script does not need to be perfect, but it should be useful and documented.
|
|
||||||
|
|
||||||
### `crawl-live-site.mjs`
|
### `crawl-live-site.mjs`
|
||||||
|
|
||||||
This script should:
|
This script should:
|
||||||
@@ -898,7 +875,7 @@ This script should:
|
|||||||
- compare discovered URLs against the current site source and generated output
|
- compare discovered URLs against the current site source and generated output
|
||||||
- document missing URLs/assets
|
- document missing URLs/assets
|
||||||
- avoid aggressive crawling
|
- avoid aggressive crawling
|
||||||
- respect the scope of `www.azinstitute4autism.com`
|
- respect the live-site scope
|
||||||
|
|
||||||
### `audit-links.mjs`
|
### `audit-links.mjs`
|
||||||
|
|
||||||
@@ -1109,7 +1086,6 @@ Add scripts similar to:
|
|||||||
"dev": "astro dev",
|
"dev": "astro dev",
|
||||||
"build": "astro check && astro build",
|
"build": "astro check && astro build",
|
||||||
"preview": "astro preview",
|
"preview": "astro preview",
|
||||||
"extract": "node tools/extract-site.mjs",
|
|
||||||
"crawl": "node tools/crawl-live-site.mjs",
|
"crawl": "node tools/crawl-live-site.mjs",
|
||||||
"audit:links": "node tools/audit-links.mjs",
|
"audit:links": "node tools/audit-links.mjs",
|
||||||
"generate:sitemap": "node tools/generate-sitemap.mjs",
|
"generate:sitemap": "node tools/generate-sitemap.mjs",
|
||||||
|
|||||||
@@ -2,16 +2,18 @@
|
|||||||
"nodes": {
|
"nodes": {
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1728018373,
|
"lastModified": 1785090369,
|
||||||
"narHash": "sha256-NOiTvBbRLIOe5F6RbHaAh6++BNjsb149fGZd1T4+KBg=",
|
"narHash": "sha256-m0pDuRJG7EDo9ri+4Ksu83VsI+PlxNC9lNBfydejce4=",
|
||||||
"rev": "bc947f541ae55e999ffdb4013441347d83b00feb",
|
"owner": "NixOS",
|
||||||
"revCount": 688563,
|
"repo": "nixpkgs",
|
||||||
"type": "tarball",
|
"rev": "624af665418d3c65d544145b4d34ad696439570e",
|
||||||
"url": "https://api.flakehub.com/f/pinned/NixOS/nixpkgs/0.1.688563%2Brev-bc947f541ae55e999ffdb4013441347d83b00feb/01925b66-3b70-71bd-b277-924a6c208ba7/source.tar.gz"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"type": "tarball",
|
"owner": "NixOS",
|
||||||
"url": "https://flakehub.com/f/NixOS/nixpkgs/0.1.%2A.tar.gz"
|
"ref": "nixos-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"root": {
|
"root": {
|
||||||
|
|||||||
@@ -1,29 +1,63 @@
|
|||||||
{
|
{
|
||||||
description = "A Nix-flake-based Node.js development environment";
|
description = "Arizona Institute for Autism Astro development environment";
|
||||||
|
|
||||||
inputs.nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/0.1.*.tar.gz";
|
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
|
|
||||||
outputs = { self, nixpkgs }:
|
outputs =
|
||||||
|
{ nixpkgs, ... }:
|
||||||
let
|
let
|
||||||
supportedSystems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ];
|
supportedSystems = [
|
||||||
forEachSupportedSystem = f: nixpkgs.lib.genAttrs supportedSystems (system: f {
|
"x86_64-linux"
|
||||||
pkgs = import nixpkgs { inherit system; overlays = [ self.overlays.default ]; };
|
"aarch64-linux"
|
||||||
});
|
"aarch64-darwin"
|
||||||
|
];
|
||||||
|
|
||||||
|
forAllSystems =
|
||||||
|
function: nixpkgs.lib.genAttrs supportedSystems (system: function nixpkgs.legacyPackages.${system});
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
overlays.default = final: prev: rec {
|
devShells = forAllSystems (
|
||||||
nodejs = prev.nodejs_22;
|
pkgs:
|
||||||
yarn = (prev.yarn.override { inherit nodejs; });
|
let
|
||||||
};
|
developmentPackages = with pkgs; [
|
||||||
|
nodejs_24
|
||||||
devShells = forEachSupportedSystem ({ pkgs }: {
|
git
|
||||||
default = pkgs.mkShell {
|
curl
|
||||||
packages = with pkgs; [
|
jq
|
||||||
node2nix nodejs nodePackages.pnpm yarn
|
ripgrep
|
||||||
python3
|
|
||||||
fd
|
fd
|
||||||
|
python3
|
||||||
|
];
|
||||||
|
in
|
||||||
|
{
|
||||||
|
default = pkgs.mkShell { packages = developmentPackages; };
|
||||||
|
}
|
||||||
|
// pkgs.lib.optionalAttrs pkgs.stdenv.hostPlatform.isLinux {
|
||||||
|
# Keep driver and browser revisions paired through the existing lockfile.
|
||||||
|
# Opt-in so ordinary content editing does not require browser downloads.
|
||||||
|
browser = pkgs.mkShell {
|
||||||
|
packages = developmentPackages ++ [ pkgs.playwright-driver ];
|
||||||
|
PLAYWRIGHT_MODULE = "${pkgs.playwright-driver}/index.mjs";
|
||||||
|
PLAYWRIGHT_BROWSERS_PATH = pkgs.playwright-driver.selectBrowsers {
|
||||||
|
withFirefox = true;
|
||||||
|
withWebkit = false;
|
||||||
|
withFfmpeg = false;
|
||||||
|
};
|
||||||
|
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD = "1";
|
||||||
|
# Nix supplies browser libraries via patched runtime paths, not apt.
|
||||||
|
PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS = "true";
|
||||||
|
FONTCONFIG_FILE = pkgs.makeFontsConf {
|
||||||
|
fontDirectories = with pkgs; [
|
||||||
|
dejavu_fonts
|
||||||
|
liberation_ttf
|
||||||
|
noto-fonts
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
});
|
ASTRO_TELEMETRY_DISABLED = "1";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
formatter = forAllSystems (pkgs: pkgs.nixfmt);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -1 +1,19 @@
|
|||||||
PUBLIC_AIA_API_BASE=https://api.azinstitute4autism.com
|
PUBLIC_AIA_API_BASE=https://api.azinstitute4autism.com
|
||||||
|
PUBLIC_COUNTERS_MODE=off
|
||||||
|
PUBLIC_COUNTERS_LIVE_APPROVED=false
|
||||||
|
PUBLIC_COUNTERS_MOCK_RESULT=success
|
||||||
|
# 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
|
||||||
|
# Explicit, local-only Form A meeting preview; requires PUBLIC_AIA_FORMS_MODE=mock.
|
||||||
|
PUBLIC_AIA_FORM_A_PREVIEW=false
|
||||||
|
PUBLIC_ALLOW_INDEXING=false
|
||||||
|
|
||||||
|
# Employee portal ciphertext is a non-PUBLIC build-only input.
|
||||||
|
# Never supply a passphrase through environment variables or build arguments.
|
||||||
|
AIA_PORTAL_LOCAL_PREVIEW_APPROVED=false
|
||||||
|
# AIA_PORTAL_CIPHERTEXT_FILE=/owner-controlled/private/ciphertext.json
|
||||||
|
# Explicit production-indexing input; it is never placed in Git or source snapshots.
|
||||||
|
AIA_PORTAL_PRODUCTION_APPROVED=false
|
||||||
|
# AIA_PORTAL_PRODUCTION_CIPHERTEXT_FILE=/absolute/private/employee-portal/approved-production-ciphertext.json
|
||||||
@@ -26,7 +26,7 @@ edits. Stop it with `Ctrl+C`.
|
|||||||
|
|
||||||
Requirements:
|
Requirements:
|
||||||
|
|
||||||
- Node.js 20.19 or newer; the Nix shell currently supplies Node.js 22
|
- Node.js 22.12 or newer (see `package.json`); the Nix shell supplies Node.js 24
|
||||||
- npm
|
- npm
|
||||||
|
|
||||||
This repository also has a Nix development shell at the repository root:
|
This repository also has a Nix development shell at the repository root:
|
||||||
@@ -38,19 +38,73 @@ cd www
|
|||||||
npm install
|
npm install
|
||||||
```
|
```
|
||||||
|
|
||||||
Copy the example environment file when testing the like/view counter:
|
### Local Playwright environment (Linux)
|
||||||
|
|
||||||
|
From the repository root, enter the opt-in browser shell:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
nix --extra-experimental-features "nix-command flakes" develop .#browser
|
||||||
|
cd www
|
||||||
|
TMPDIR=/tmp npm run build
|
||||||
|
TMPDIR=/tmp node tools/playwright-smoke.mjs
|
||||||
|
```
|
||||||
|
|
||||||
|
The existing `flake.lock` pairs the Nix Playwright driver and Chromium/headless
|
||||||
|
shell. `PLAYWRIGHT_MODULE` points directly to that driver; `PLAYWRIGHT_BROWSERS_PATH`
|
||||||
|
selects its matching browsers. Fontconfig supplies Latin/Arabic fallback fonts.
|
||||||
|
The ordinary development shell and npm dependencies remain unchanged. This
|
||||||
|
browser shell is offered on Linux; the existing Darwin development shell is
|
||||||
|
unchanged. Do not run `npx playwright install` or mix an unrelated npm Playwright
|
||||||
|
version with these browser revisions.
|
||||||
|
|
||||||
|
The smoke test starts Astro preview and Chromium in the **same execution** on an
|
||||||
|
ephemeral `127.0.0.1` port. It blocks external and non-GET/HEAD requests, loads the
|
||||||
|
real Spanish privacy and Library pages, verifies staging robots/title/H1, captures
|
||||||
|
two full-page screenshots in a new `/tmp/aia-playwright-smoke-*` directory, and
|
||||||
|
closes browser/preview. It does not submit forms or exercise production APIs.
|
||||||
|
Success establishes browser transport only, not Phase 8 visual or human acceptance.
|
||||||
|
|
||||||
|
Use the [Phase 8 guarded browser procedure](reports/phase-8-host-browser-verification-2026-10-14.md)
|
||||||
|
for full review. Entering the Nix shell does not repair an already-running remote
|
||||||
|
MCP transport or relax sandbox permissions. If the autonomous environment cannot
|
||||||
|
access the Nix store, trusted certificates, sockets or browser runtime files, run
|
||||||
|
the same smoke test from the host terminal. Do not disable TLS verification or
|
||||||
|
bypass the sandbox. The Nix environment needs host validation before browser
|
||||||
|
availability can be claimed.
|
||||||
|
|
||||||
|
Copy the example environment file when testing the like/view counter or staging
|
||||||
|
SEO behavior:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cp .env.example .env
|
cp .env.example .env
|
||||||
```
|
```
|
||||||
|
|
||||||
The default value is:
|
The default values are:
|
||||||
|
|
||||||
```txt
|
```txt
|
||||||
PUBLIC_AIA_API_BASE=https://api.azinstitute4autism.com
|
PUBLIC_AIA_API_BASE=https://api.azinstitute4autism.com
|
||||||
|
PUBLIC_COUNTERS_MODE=off
|
||||||
|
PUBLIC_COUNTERS_LIVE_APPROVED=false
|
||||||
|
PUBLIC_ALLOW_INDEXING=false
|
||||||
```
|
```
|
||||||
|
|
||||||
The site still renders when that API is unavailable.
|
The site still renders when the AIA API is unavailable. Migration and staging
|
||||||
|
builds emit `noindex,nofollow` by default. `PUBLIC_ALLOW_INDEXING=true` enables
|
||||||
|
production publication policy, including per-page noindex exceptions. Exercise
|
||||||
|
that mode locally with `PUBLIC_ALLOW_INDEXING=true npm run build`; this does
|
||||||
|
not deploy anything or change environment files. Run `npm run build` afterward
|
||||||
|
to restore staging output. Only explicitly authorized production deployments
|
||||||
|
should publish indexing-enabled artifacts.
|
||||||
|
|
||||||
|
Ordinary local builds keep counters off. `npm run deploy` deliberately and
|
||||||
|
non-overridably builds the production artifact with live counters, the approved
|
||||||
|
API origin and `PUBLIC_COUNTERS_LIVE_APPROVED=true`. Article pages post one
|
||||||
|
first-party view per real navigation; Library cards only batch-read statistics.
|
||||||
|
Likes use the existing POST/DELETE API and store only the visitor's chosen slug
|
||||||
|
set in localStorage. No view cookies or visitor identifiers are created. Run
|
||||||
|
`npm run test:counters`, then build in live mode and run `npm run
|
||||||
|
verify:counters -- --browser=chromium` (or `firefox`) for a fully intercepted
|
||||||
|
browser regression that cannot write production counters.
|
||||||
|
|
||||||
## View And Build
|
## View And Build
|
||||||
|
|
||||||
@@ -73,13 +127,12 @@ Useful development URLs include:
|
|||||||
/library
|
/library
|
||||||
/es
|
/es
|
||||||
/es/library
|
/es/library
|
||||||
/ar
|
|
||||||
/ar/library
|
/ar/library
|
||||||
```
|
```
|
||||||
|
|
||||||
### Production Build
|
### Static Build
|
||||||
|
|
||||||
Generate the static production site:
|
Generate the static site with staging indexing protection:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
npm run build
|
npm run build
|
||||||
@@ -169,6 +222,91 @@ Article content goes here.
|
|||||||
|
|
||||||
Set `draft: true` while preparing unpublished content.
|
Set `draft: true` while preparing unpublished content.
|
||||||
|
|
||||||
|
### Display Headings and Social Metadata
|
||||||
|
|
||||||
|
Pages and articles may supply an optional plain-text `displayH1` in frontmatter:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
title: "The existing SEO title"
|
||||||
|
displayH1: "The source-supported visible heading"
|
||||||
|
```
|
||||||
|
|
||||||
|
The override changes only the visible H1. It does not change the document or
|
||||||
|
social title, article cards, navigation labels, or related-post text. Empty,
|
||||||
|
whitespace-only and non-string overrides fail content validation. Without an
|
||||||
|
override, articles keep `title`, regular pages keep their existing service/page
|
||||||
|
heading mappings and title-derived fallback, and homepage/Library components
|
||||||
|
keep their existing headings. Homepage heading markup stays intact unless a
|
||||||
|
plain-text override is explicitly supplied. Library template SEO titles remain
|
||||||
|
unchanged. Front Matter CMS exposes the optional field for pages and blog posts.
|
||||||
|
|
||||||
|
Existing featured images and page banner fallbacks supply `og:image` and
|
||||||
|
`twitter:image`. Relative paths resolve against the public origin in
|
||||||
|
`src/data/site.json`, never a preview host or an external canonical. Existing
|
||||||
|
`alt` text supplies both image-alt metadata tags only when it describes the
|
||||||
|
selected featured image; no descriptions are invented for banner fallbacks.
|
||||||
|
Pages without a selected image omit image tags and retain the `summary` card;
|
||||||
|
image pages retain `summary_large_image`.
|
||||||
|
|
||||||
|
`og:locale` is omitted: the content languages `en`, `es` and `ar` do not establish
|
||||||
|
the regional `language_TERRITORY` values required by the
|
||||||
|
[Open Graph protocol](https://ogp.me/). Regional targeting remains a human
|
||||||
|
localization decision. HTML language/direction and hreflang are unchanged.
|
||||||
|
|
||||||
|
Run `npm run test:seo` for isolated real-Astro builds covering heading defaults,
|
||||||
|
overrides, schema rejection, image metadata and shared publication invariants
|
||||||
|
in staging and indexing modes. Fixtures never modify the working content or
|
||||||
|
the project's `dist/`. See the dated Phase 4A section of
|
||||||
|
[`reports/migration-summary.md`](reports/migration-summary.md) for source evidence.
|
||||||
|
|
||||||
|
### Publication, Canonicals, and Sitemap
|
||||||
|
|
||||||
|
`src/utils/publication-policy.ts` owns route eligibility, normalized public
|
||||||
|
URLs, canonical validation, robots values, and sitemap eligibility.
|
||||||
|
`src/utils/publication.ts` loads the Astro collections into that manifest.
|
||||||
|
`src/pages/[...slug].astro` generates every content route from eligible entries,
|
||||||
|
including home and Library indexes; their existing presentation components are
|
||||||
|
under `src/components/pages/`. Shared SEO and the generated sitemap use that
|
||||||
|
same manifest. The route and source-link audits also reuse the policy.
|
||||||
|
|
||||||
|
- `draft: true` means unpublished: no generated HTML route in either build mode.
|
||||||
|
The Arabic homepage `/ar` remains a draft; published Arabic Library routes
|
||||||
|
remain available. Navigation does not link to the unpublished homepage.
|
||||||
|
- `noindex: true` keeps a published route accessible, emits `noindex,follow`
|
||||||
|
in indexing-enabled builds, and excludes it from the sitemap. It defaults
|
||||||
|
to `false`. Staging always overrides this with `noindex,nofollow`.
|
||||||
|
- An omitted `canonical` gets the normalized public URL from `site.json` and
|
||||||
|
its local route. A supplied local canonical must match that route. Invalid
|
||||||
|
canonicals, duplicate canonical targets, and route collisions fail validation.
|
||||||
|
- Verified syndicated articles use their existing `canonical` field for the
|
||||||
|
external publisher URL. External-canonical routes are excluded from the
|
||||||
|
sitemap even when they are not marked noindex. Do not use canonical values
|
||||||
|
to create local routes or sitemap locations.
|
||||||
|
- `src/pages/sitemap.xml.ts` generates `dist/sitemap.xml` on every build.
|
||||||
|
Staging emits an empty sitemap and does not advertise it in `robots.txt`.
|
||||||
|
Indexing-enabled builds include only eligible, indexable, self-canonical
|
||||||
|
local routes. There is no hand-maintained `public/sitemap.xml`.
|
||||||
|
- `npm run generate:sitemap` is a compatibility command that runs the Astro
|
||||||
|
build; it no longer writes a separate public sitemap from frontmatter strings.
|
||||||
|
|
||||||
|
The verified noindex exceptions are `/schedule-consultation`, `/employee-portal`,
|
||||||
|
`/library/community-highlight-meet-rula-diab`, and
|
||||||
|
`/library/new-aia-scottsdale-office`. The last two also retain their verified
|
||||||
|
external canonicals. The dated evidence is in `reports/migration-summary.md`.
|
||||||
|
|
||||||
|
Run `npm run test:publication` for policy tests and isolated builds of the
|
||||||
|
actual application in staging and indexing-enabled modes. Fixtures test draft
|
||||||
|
content, draft home/Library indexes, missing and external canonicals, and
|
||||||
|
generated head/sitemap consistency without modifying the working site's output.
|
||||||
|
The policy is TypeScript; Node audit/test commands use `--experimental-strip-types`
|
||||||
|
for compatibility with the declared Node 22.12 minimum. Dependencies are unchanged.
|
||||||
|
|
||||||
|
After publication changes, build and run `npm run audit:routes -- --offline`
|
||||||
|
before `npm run audit:routes -- --check`. This creates a newly dated local
|
||||||
|
reconciliation using saved production observations, preserving earlier evidence.
|
||||||
|
Saved rendered metadata is specific to its build mode: after restoring the
|
||||||
|
normal staging build, reconcile that output again before checking it.
|
||||||
|
|
||||||
### Links And Buttons
|
### Links And Buttons
|
||||||
|
|
||||||
Use normal Markdown links for links within prose:
|
Use normal Markdown links for links within prose:
|
||||||
@@ -196,6 +334,46 @@ Available sizes are `default` and `small`. A `_blank` target automatically adds
|
|||||||
|
|
||||||
Normal Markdown links remain preferred for ordinary page and article content.
|
Normal Markdown links remain preferred for ordinary page and article content.
|
||||||
|
|
||||||
|
### Stable Heading Links
|
||||||
|
|
||||||
|
Astro automatically generates an ID for each Markdown heading. In `.md` files,
|
||||||
|
when a section needs a stable, editorially controlled fragment link, add an
|
||||||
|
explicit ID with Sätteri heading-attribute syntax:
|
||||||
|
|
||||||
|
```md
|
||||||
|
## Accepted Insurance Carriers {#accepted-insurance-heading}
|
||||||
|
```
|
||||||
|
|
||||||
|
Link to it with the resulting fragment URL:
|
||||||
|
|
||||||
|
```md
|
||||||
|
[View accepted carriers](/insurance#accepted-insurance-heading)
|
||||||
|
```
|
||||||
|
|
||||||
|
Keep explicit IDs unique within the page, lowercase, and hyphenated. Treat a
|
||||||
|
published ID as permanent so inbound links do not break when heading text is
|
||||||
|
edited. The installed MDX parser rejects this shorthand, independently of
|
||||||
|
directive parsing. In `.mdx` files, use an explicit HTML heading instead:
|
||||||
|
|
||||||
|
```mdx
|
||||||
|
<h2 id="accepted-insurance-heading">Accepted Insurance Carriers</h2>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Markdown Directives
|
||||||
|
|
||||||
|
Sätteri directive parsing is disabled. The content corpus has no intentional
|
||||||
|
container (`:::name`), leaf (`::name`), or text (`:name`) directives, and no
|
||||||
|
directive transformation plugins are registered. Enabling parsing silently
|
||||||
|
removed literal text such as `:1` in `1:1`, `:00` in times, and `:Plan` after
|
||||||
|
an adjacent colon. Heading attributes remain enabled.
|
||||||
|
|
||||||
|
Run `npm run test:markdown` after changing the Markdown/MDX configuration. It
|
||||||
|
builds temporary fixtures and the affected content through the actual Astro
|
||||||
|
configuration, checking ratios, punctuation, times, URLs, code, and explicit
|
||||||
|
heading IDs. It makes no production requests and leaves no fixture routes in
|
||||||
|
the site. Any future directive feature needs compatible rendering and must
|
||||||
|
preserve these literal-content checks.
|
||||||
|
|
||||||
### Front Matter CMS
|
### Front Matter CMS
|
||||||
|
|
||||||
The project includes `frontmatter.json` for the Front Matter CMS VS Code
|
The project includes `frontmatter.json` for the Front Matter CMS VS Code
|
||||||
@@ -222,14 +400,30 @@ benefits
|
|||||||
skills
|
skills
|
||||||
insurance
|
insurance
|
||||||
esa
|
esa
|
||||||
|
hsaFsa (optional; English only where published)
|
||||||
financialHelp
|
financialHelp
|
||||||
process
|
process
|
||||||
director
|
director
|
||||||
testimonials
|
testimonials
|
||||||
|
logos (optional)
|
||||||
```
|
```
|
||||||
|
|
||||||
Keep homepage copy in those named blocks so the page remains easy to scan in
|
Keep homepage copy in those named blocks so the page remains easy to scan in
|
||||||
Front Matter CMS and VS Code. `src/content.config.ts` validates the structure.
|
Front Matter CMS and VS Code. `src/content.config.ts` validates the structure.
|
||||||
|
`hsaFsa` uses `heading`, `body`, `image`, and `imageAlt`; omit the whole block
|
||||||
|
where no section is published. It renders between ESA and financial help.
|
||||||
|
`logos.items` holds `file`/`alt` pairs after testimonials. Process steps accept
|
||||||
|
an optional `href`; use an existing intake route and section ID in the same
|
||||||
|
language. Steps without a destination remain plain content.
|
||||||
|
|
||||||
|
### Edit The Team Page
|
||||||
|
|
||||||
|
The English Team page uses the validated `team:` frontmatter block in
|
||||||
|
`src/content/pages/en/team.md`. That block is the single source for the intro,
|
||||||
|
ordered clinical groups, ABA care team, member names/roles/images, and careers
|
||||||
|
content. The Markdown body contains no second roster. Update the structured
|
||||||
|
frontmatter rather than hardcoding people in `TeamPage.astro`; image filenames
|
||||||
|
refer to `public/assets/images`.
|
||||||
|
|
||||||
### Images And Downloads
|
### Images And Downloads
|
||||||
|
|
||||||
@@ -285,7 +479,10 @@ src/data
|
|||||||
|
|
||||||
### Add A Translation
|
### Add A Translation
|
||||||
|
|
||||||
Use the same `translationKey` across translated entries:
|
Use the same nonempty `translationKey` across genuine translated entries in
|
||||||
|
the **same collection**. The key is an explicit equivalence declaration, not a
|
||||||
|
URL or an entry reference. Slugs may differ; similar slugs alone never create a
|
||||||
|
relationship. Do not change keys to manufacture translation pairs.
|
||||||
|
|
||||||
```txt
|
```txt
|
||||||
src/content/blog/en/post-slug.md
|
src/content/blog/en/post-slug.md
|
||||||
@@ -303,7 +500,32 @@ The URLs become:
|
|||||||
|
|
||||||
Arabic routes automatically render with `lang="ar"` and `dir="rtl"`.
|
Arabic routes automatically render with `lang="ar"` and `dir="rtl"`.
|
||||||
|
|
||||||
Do not publish unreviewed machine translations. Clearly mark placeholders.
|
The shared publication manifest supplies both the language switcher and SEO
|
||||||
|
alternates. A translation set needs at least two eligible members. Drafts,
|
||||||
|
unpublished placeholders, noindex pages, and external-canonical pages do not
|
||||||
|
participate. Mark placeholders `draft: true`; `/ar` remains unpublished.
|
||||||
|
Author records have no generated routes yet and cannot participate.
|
||||||
|
|
||||||
|
One member per language per collection/key is allowed, including draft members;
|
||||||
|
duplicates and blank/whitespace-padded keys fail validation. A lone key is valid
|
||||||
|
and emits no alternate: it does not assert that a particular missing language
|
||||||
|
exists. Dangling graph references, wrong-family targets, ineligible targets,
|
||||||
|
and nonreciprocal links fail validation. The rendered-output regression checks
|
||||||
|
also fail if an alternate target has no generated HTML file.
|
||||||
|
|
||||||
|
Indexing-enabled builds emit the same absolute hreflang links on every member,
|
||||||
|
including its own language. `x-default` points to the eligible English member
|
||||||
|
only; sets without one omit it. Staging suppresses hreflang while retaining the
|
||||||
|
eligible language menu and global `noindex,nofollow`. Unpaired/excluded pages
|
||||||
|
retain their current-language label without an empty interactive menu.
|
||||||
|
|
||||||
|
Run `npm run test:publication`, `npm run build`, and
|
||||||
|
`PUBLIC_ALLOW_INDEXING=true npm run build` to validate both modes. Finish with
|
||||||
|
`npm run build` to restore staging. See `reports/migration-summary.md` for
|
||||||
|
Phase 3B's exact route sets, evidence, and route-audit refresh commands.
|
||||||
|
|
||||||
|
Do not publish unreviewed machine translations. Do not invent translations;
|
||||||
|
substantive translation changes require human language review.
|
||||||
|
|
||||||
### Edit A Blog FAQ
|
### Edit A Blog FAQ
|
||||||
|
|
||||||
@@ -314,12 +536,49 @@ import FAQAccordion from '../../../components/FAQAccordion.astro';
|
|||||||
```
|
```
|
||||||
|
|
||||||
Edit the component's `label`, `heading`, and `items` data in the post. Keep
|
Edit the component's `label`, `heading`, and `items` data in the post. Keep
|
||||||
`answer` as plain text for JSON-LD and `answerHtml` as the matching visible
|
`answer` and `answerHtml` consistent. JSON-LD derives its answer text from the
|
||||||
answer. Shared FAQ markup, styling, interaction, and schema generation live in
|
actual visible `answerHtml` when supplied, otherwise from the rendered `answer`
|
||||||
`src/components/FAQAccordion.astro`.
|
fallback. Shared FAQ markup, styling, interaction, and schema generation remain
|
||||||
|
in `src/components/FAQAccordion.astro`, using `src/utils/structured-data.ts`.
|
||||||
|
|
||||||
|
The standalone FAQ page passes its rendered Markdown/MDX slot as `sourceHtml`
|
||||||
|
to the same component. Its server schema describes the direct H3 questions and
|
||||||
|
following answer nodes that the existing browser code turns into accordions.
|
||||||
|
Runtime-only sources without server content emit no invented FAQ schema. Do
|
||||||
|
not mix `items` with `sourceSelector`. Duplicate questions, multiple schema
|
||||||
|
producing accordions on one page, empty answers and conflicting canonical
|
||||||
|
props fail validation; consolidate questions into one accordion per page.
|
||||||
|
|
||||||
|
### Article and FAQ Structured Data
|
||||||
|
|
||||||
|
Article JSON-LD uses the existing SEO `title`, description, featured image,
|
||||||
|
language, `date`, optional `updatedDate`, and the exact locale/slug match in the
|
||||||
|
authors collection. Dates use calendar-day precision; article/card bylines
|
||||||
|
format that day in UTC to avoid shifting it on the build host. Missing
|
||||||
|
modification dates are omitted. Missing or ambiguous author references fail validation.
|
||||||
|
No author archive URL or publisher is invented. `displayH1` does not change
|
||||||
|
the schema headline. No new frontmatter fields are required.
|
||||||
|
|
||||||
|
BlogPosting and FAQPage emission reuse the manifest's `sitemapEligible` record
|
||||||
|
gate: drafts, noindex records and external-canonical records are excluded.
|
||||||
|
This gate is independent of the build's global indexing switch, so staging
|
||||||
|
can exercise schema while retaining its global noindex, empty sitemap and
|
||||||
|
absent hreflang. The existing site organization block remains unchanged.
|
||||||
|
|
||||||
|
These schemas describe the rendered local records; they do not certify that
|
||||||
|
older article dates or FAQ answers have been reconciled with production.
|
||||||
|
Phase 6C drift observations and validation results are recorded in
|
||||||
|
`reports/migration-summary.md`. Run `npm run test:seo` and
|
||||||
|
`npm run test:publication`, and validate both build modes before publication.
|
||||||
|
|
||||||
## Reports And Utilities
|
## Reports And Utilities
|
||||||
|
|
||||||
|
For the current migration checkpoint, next Codex phase, ratified decisions,
|
||||||
|
and outstanding cutover blockers, begin with the
|
||||||
|
**[living session handoff](reports/SESSION_HANDOFF.md)**. Update that short
|
||||||
|
handoff at each accepted milestone transition; detailed historical evidence
|
||||||
|
remains in `reports/migration-summary.md`.
|
||||||
|
|
||||||
Migration reports are stored in `reports/`.
|
Migration reports are stored in `reports/`.
|
||||||
|
|
||||||
Useful commands:
|
Useful commands:
|
||||||
@@ -333,14 +592,65 @@ npm run audit:links
|
|||||||
|
|
||||||
The live crawl is optional and may fail in restricted network environments.
|
The live crawl is optional and may fail in restricted network environments.
|
||||||
|
|
||||||
|
## Referral CTA
|
||||||
|
|
||||||
|
The public `/referrals` page preserves the existing site's **Refer a Client**
|
||||||
|
button, linking directly to https://form.jotform.com/231638510219149. The
|
||||||
|
site does **not** embed a referral form or require Form C. This destination is
|
||||||
|
separate from Form A's 16 allowlisted placements. Legacy-hosted-form privacy,
|
||||||
|
recipient, accessibility and operational acceptance remain the owner's release
|
||||||
|
responsibility.
|
||||||
|
|
||||||
## Forms
|
## 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.
|
Use `PUBLIC_AIA_FORMS_MODE=off npm run build` for an offline artifact, or
|
||||||
2. Connect the forms.
|
`PUBLIC_AIA_FORMS_MODE=mock npm run dev` for synthetic fixtures. Missing/empty
|
||||||
3. Add spam protection.
|
mode means live; obsolete `isolated-test` and other invalid values produce an
|
||||||
4. Test validation, confirmation, and failure states.
|
explicit configuration error. Remove old approval/environment variables from
|
||||||
|
local settings. Indexing and form mode remain independent of counter mode.
|
||||||
|
|
||||||
|
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 --counters=off`;
|
||||||
|
use `--mode=indexing` for indexing output and `--forms=off` or `--forms=mock`
|
||||||
|
for those explicit builds. Production counter artifacts require
|
||||||
|
`--counters=live`. No actual submissions or production counter writes run in
|
||||||
|
automated tests.
|
||||||
|
|
||||||
|
## Static releases and employee portal
|
||||||
|
|
||||||
|
The Contabo deployment interface is intentionally separate from NixOS changes.
|
||||||
|
Use [the release runbook](integrations/nixos/deploy.md) for `npm run deploy`,
|
||||||
|
dry-run, rollback, the encrypted production portal input and the separate
|
||||||
|
one-time employee-resource installer. The server-side installer is a root-only
|
||||||
|
POSIX shell script using NixOS base tools; it does not require Node.js on
|
||||||
|
Contabo. Ordinary releases never copy employee documents into `dist`;
|
||||||
|
protected staff and management resources remain under server-controlled Basic
|
||||||
|
Auth namespaces. After a successful unlock, the page keeps that role's code
|
||||||
|
only in memory and uses it for same-origin authenticated document fetches. The
|
||||||
|
response is downloaded as a local Blob, so employees do not receive a second
|
||||||
|
browser authentication prompt. Cross-role requests are stopped before
|
||||||
|
credentials are sent; direct resource URLs still require nginx authentication.
|
||||||
|
Codes are never put in URLs or browser storage. The accepted interim portal is
|
||||||
|
explicitly non-PHI.
|
||||||
|
|
||||||
|
### Google Ads consultation-form conversion handoff
|
||||||
|
|
||||||
|
The Google Ads conversion ID, label, and privacy-gated Astro integration
|
||||||
|
instructions are in
|
||||||
|
[`reports/google-ads-consultation-conversion.md`](reports/google-ads-consultation-conversion.md).
|
||||||
|
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. Any future measurement needs separately approved success and privacy semantics; the former API-success premise is historical and no tracking is active.
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,21 @@
|
|||||||
import { defineConfig } from 'astro/config';
|
import { defineConfig } from 'astro/config';
|
||||||
import mdx from '@astrojs/mdx';
|
import mdx from '@astrojs/mdx';
|
||||||
|
import { satteri } from '@astrojs/markdown-satteri';
|
||||||
|
import site from './src/data/site.json' with { type: 'json' };
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
site: 'https://www.azinstitute4autism.com',
|
site: site.url,
|
||||||
trailingSlash: 'never',
|
trailingSlash: 'never',
|
||||||
|
compressHTML: true,
|
||||||
integrations: [mdx()],
|
integrations: [mdx()],
|
||||||
markdown: {
|
markdown: {
|
||||||
|
processor: satteri({
|
||||||
|
features: {
|
||||||
|
headingAttributes: true,
|
||||||
|
// No directive consumers: parsing them drops literal ratios and times.
|
||||||
|
directive: false
|
||||||
|
}
|
||||||
|
}),
|
||||||
shikiConfig: { theme: 'github-light' }
|
shikiConfig: { theme: 'github-light' }
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
"pageBundle": false,
|
"pageBundle": false,
|
||||||
"fields": [
|
"fields": [
|
||||||
{ "title": "Title", "name": "title", "type": "string", "required": true },
|
{ "title": "Title", "name": "title", "type": "string", "required": true },
|
||||||
|
{ "title": "Display H1", "name": "displayH1", "type": "string" },
|
||||||
{ "title": "Description", "name": "description", "type": "string" },
|
{ "title": "Description", "name": "description", "type": "string" },
|
||||||
{ "title": "Slug", "name": "slug", "type": "string", "required": true },
|
{ "title": "Slug", "name": "slug", "type": "string", "required": true },
|
||||||
{ "title": "Language", "name": "lang", "type": "choice", "choices": ["en", "ar", "es"] },
|
{ "title": "Language", "name": "lang", "type": "choice", "choices": ["en", "ar", "es"] },
|
||||||
@@ -28,6 +29,7 @@
|
|||||||
"pageBundle": false,
|
"pageBundle": false,
|
||||||
"fields": [
|
"fields": [
|
||||||
{ "title": "Title", "name": "title", "type": "string", "required": true },
|
{ "title": "Title", "name": "title", "type": "string", "required": true },
|
||||||
|
{ "title": "Display H1", "name": "displayH1", "type": "string" },
|
||||||
{ "title": "Description", "name": "description", "type": "string" },
|
{ "title": "Description", "name": "description", "type": "string" },
|
||||||
{ "title": "Slug", "name": "slug", "type": "string", "required": true },
|
{ "title": "Slug", "name": "slug", "type": "string", "required": true },
|
||||||
{ "title": "Date", "name": "date", "type": "datetime", "required": true },
|
{ "title": "Date", "name": "date", "type": "datetime", "required": true },
|
||||||
@@ -47,6 +49,7 @@
|
|||||||
"pageBundle": false,
|
"pageBundle": false,
|
||||||
"fields": [
|
"fields": [
|
||||||
{ "title": "Name", "name": "name", "type": "string", "required": true },
|
{ "title": "Name", "name": "name", "type": "string", "required": true },
|
||||||
|
{ "title": "Display name (published heading/byline)", "name": "displayName", "type": "string" },
|
||||||
{ "title": "Slug", "name": "slug", "type": "string", "required": true },
|
{ "title": "Slug", "name": "slug", "type": "string", "required": true },
|
||||||
{ "title": "Description", "name": "description", "type": "string" },
|
{ "title": "Description", "name": "description", "type": "string" },
|
||||||
{ "title": "Avatar", "name": "avatar", "type": "image" },
|
{ "title": "Avatar", "name": "avatar", "type": "image" },
|
||||||
|
|||||||
@@ -0,0 +1,185 @@
|
|||||||
|
# Employee portal compatibility and private migration
|
||||||
|
|
||||||
|
Recorded 2026-11-04. The clinical director accepted the collected, non-PHI
|
||||||
|
staff and management portal content and the interim shared-code presentation.
|
||||||
|
Browser-side decryption remains access friction rather than individual
|
||||||
|
authentication, revocation, a secure session, or a HIPAA determination.
|
||||||
|
|
||||||
|
The same successfully validated code authorizes protected document downloads
|
||||||
|
for that role during the current page session. The browser keeps it only in a
|
||||||
|
closure, performs a same-origin authenticated fetch, and saves the returned
|
||||||
|
document without opening nginx's native Basic Auth dialog. Staff uses the
|
||||||
|
`staff` username and stream `b`; management uses the `management` username and
|
||||||
|
stream `a`. Direct URLs remain nginx-protected, cross-role fetches are rejected
|
||||||
|
before credentials are sent, and failed authenticated downloads show an inline
|
||||||
|
error without direct-navigation fallback. No code enters a URL, browser
|
||||||
|
storage, public artifact, or log. Downloads use a bounded safe form of the
|
||||||
|
approved link label and preserve the validated extension from the protected
|
||||||
|
SHA-256 server destination; server resources are not renamed.
|
||||||
|
|
||||||
|
## Approved production ciphertext
|
||||||
|
|
||||||
|
An indexing-enabled production build may include one owner-approved encrypted
|
||||||
|
two-stream payload when both of these non-public build inputs are set:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
AIA_PORTAL_PRODUCTION_APPROVED=true
|
||||||
|
AIA_PORTAL_PRODUCTION_CIPHERTEXT_FILE=/absolute/private/employee-portal/approved-production-ciphertext.json
|
||||||
|
```
|
||||||
|
|
||||||
|
The build rejects missing, malformed, symlinked, oversized, wrong-mode, or
|
||||||
|
simultaneous local-preview/production inputs. It never decrypts the payload at
|
||||||
|
build time. `/employee-portal` remains noindex, sitemap-excluded and
|
||||||
|
hreflang-excluded. See [the deployment runbook](../nixos/deploy.md) for the
|
||||||
|
approved release and protected-resource installation commands.
|
||||||
|
|
||||||
|
## Source and private collection
|
||||||
|
|
||||||
|
The 42 approved non-PHI resources have already been collected under the ignored
|
||||||
|
`private/employee-portal/hubfs/` workspace. Collection and clinical review are
|
||||||
|
complete. Do not run a new collection pass for production preparation.
|
||||||
|
|
||||||
|
Production preparation is an owner-only, hidden-prompt sequence. The first
|
||||||
|
command identifies the encrypted streams from the staff and management codes;
|
||||||
|
the codes are never accepted in arguments, environment variables, files or
|
||||||
|
output:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm run portal:prepare -- identify \
|
||||||
|
/home/alice/projects/wrk/aia/local-archives/aia-employee-portal-hubspot-footer-source.txt
|
||||||
|
npm run portal:prepare -- propose-mappings \
|
||||||
|
/home/alice/projects/wrk/aia/local-archives/aia-employee-portal-hubspot-footer-source.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
Review the private mapping summary. The role rule maps staff-only references to
|
||||||
|
`/staff-resources/`, management-only references to `/management-resources/`, and
|
||||||
|
duplicates a shared source into both protected namespaces. After the owner
|
||||||
|
approves that operational policy, run:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm run portal:prepare -- approve-mappings \
|
||||||
|
/home/alice/projects/wrk/aia/local-archives/aia-employee-portal-hubspot-footer-source.txt
|
||||||
|
npm run portal:prepare -- rewrite-production \
|
||||||
|
/home/alice/projects/wrk/aia/local-archives/aia-employee-portal-hubspot-footer-source.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
The rewrite command prompts for both codes again, rewrites every approved legacy
|
||||||
|
resource URL, re-encrypts with fresh salts and IVs, verifies each role privately,
|
||||||
|
and atomically installs `approved-production-ciphertext.json` plus a matching
|
||||||
|
private `production-readiness.json`. It refuses unresolved `/hubfs/` references.
|
||||||
|
Prior manifests and production ciphertext are retained as timestamped private
|
||||||
|
backups.
|
||||||
|
|
||||||
|
### Mapping approval versus server verification
|
||||||
|
|
||||||
|
`mappingApproved`, `accessPolicyApproved`, and `rewriteApproved` mean the
|
||||||
|
verified collected source has an approved role and safe protected destination
|
||||||
|
and may be prepared or installed. They do not claim the destination exists.
|
||||||
|
`destinationInstalled`, `destinationHashVerified`,
|
||||||
|
`destinationPermissionsVerified`, and `destinationAccessVerified` remain false
|
||||||
|
until an authorized VPS rehearsal actually installs the file and verifies its
|
||||||
|
bytes, `root:nginx` permissions, Basic Auth boundary and protected URL. Local
|
||||||
|
preparation and installation accept the first state; release acceptance must
|
||||||
|
still complete the second state before browser cutover.
|
||||||
|
|
||||||
|
Read-only legacy footer source:
|
||||||
|
`/home/alice/projects/wrk/aia/local-archives/aia-employee-portal-hubspot-footer-source.txt`.
|
||||||
|
The original stays outside Git as rollback evidence. The 42-file collection and
|
||||||
|
its accepted content are complete; no current command downloads resources.
|
||||||
|
|
||||||
|
Private output is `private/employee-portal/`: directories 0700, manifests and
|
||||||
|
binary resources 0600. This exact subtree is gitignored and outside Astro's
|
||||||
|
public directory. Filenames are SHA-256 hashes of source URLs, independently
|
||||||
|
verified by content hashes. The manifest retains original references, labels,
|
||||||
|
view membership, MIME, bytes, status and delivery/classification decisions.
|
||||||
|
The manifest preserves the original source URL, collection hash, size, reference
|
||||||
|
membership and accepted source evidence. Public legacy reachability did not
|
||||||
|
infer public approval.
|
||||||
|
|
||||||
|
Before every artifact transfer, verify that only `dist` is copied and that it
|
||||||
|
contains no private manifest, document or real ciphertext unless that ciphertext
|
||||||
|
has separately been authorized for the local preview. Never archive the whole
|
||||||
|
working directory as a deployable artifact.
|
||||||
|
|
||||||
|
## Historical collection and rewriting recovery notes
|
||||||
|
|
||||||
|
The original source, collection manifests, collected bytes and prior ciphertext
|
||||||
|
revisions remain recovery evidence. Do not change their classifications or
|
||||||
|
destination flags by hand; use the production-preparation sequence above so
|
||||||
|
stream identity, references, source hashes and protected destinations remain
|
||||||
|
consistent. CSS/srcset dependencies remain an explicit error rather than a
|
||||||
|
silent rewrite.
|
||||||
|
|
||||||
|
## Local preview and content safety
|
||||||
|
|
||||||
|
Use a retained private ciphertext revision:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
AIA_PORTAL_LOCAL_PREVIEW_APPROVED=true \
|
||||||
|
AIA_PORTAL_CIPHERTEXT_FILE=/absolute/private/ciphertext-TIMESTAMP.json \
|
||||||
|
PUBLIC_AIA_FORMS_MODE=off PUBLIC_ALLOW_INDEXING=false \
|
||||||
|
npm run dev -- --host 127.0.0.1
|
||||||
|
```
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
The passive DOM renderer preserves headings, lists, text, tables and safe
|
||||||
|
HTTPS/mailto/tel links, with no referrer on links. It rejects scripts, inline
|
||||||
|
handlers, styles, media, embedded forms and unknown tags. Real portal markup
|
||||||
|
has not been decrypted or reviewed; any removed behavior must be reviewed with
|
||||||
|
the owner before claiming fidelity. It must not silently become arbitrary
|
||||||
|
script execution. No real encrypted stream or plaintext is in Git.
|
||||||
|
|
||||||
|
### Scoped presentation correction, 2026-10-30
|
||||||
|
|
||||||
|
The renderer now maps only `hs-button`, `content-button`, or
|
||||||
|
`portal-resource-button` anchor tokens, or exact inline AIA orange background
|
||||||
|
colors (`#ffbd59` / `#ff914d`), to the local `portal-resource-button` class.
|
||||||
|
It does not copy the original style or arbitrary classes. These are narrow
|
||||||
|
compatibility candidates, not a claim that encrypted real views have been
|
||||||
|
inspected. HTTPS/mailto/tel links retain the existing safe URL checks; contact
|
||||||
|
links receive a local dark-orange accent for readable contrast. Table scope
|
||||||
|
and bounded numeric row/column spans are preserved. All other executable or
|
||||||
|
unapproved attributes remain removed.
|
||||||
|
|
||||||
|
The follow-up styling correction recognizes the live portal's `Daily Lineup
|
||||||
|
Report` and `Monthly Lineup Report` link labels, even when their original
|
||||||
|
HubSpot classes or inline fills are absent. It maps only those links to the
|
||||||
|
existing orange resource-button style; arbitrary anchors remain ordinary links.
|
||||||
|
Both unlocked views now use the site's orange accent for list-item markers.
|
||||||
|
The source classes and styles still do not reach the passive DOM.
|
||||||
|
|
||||||
|
### Staff resources and Management Templates, 2026-11-01
|
||||||
|
|
||||||
|
The owner observed that the non-management (general-staff) portal still lost
|
||||||
|
HubSpot's resource-button presentation. After **sanitizing** the decrypted DOM,
|
||||||
|
a headed `Management Templates` section identifies the general-staff resource
|
||||||
|
view. Valid HTTP(S) resource links in that view receive only the local
|
||||||
|
`portal-resource-button` class; `mailto:` and `tel:` retain contact-link
|
||||||
|
styling. Neither destination validation nor removed legacy classes/styles,
|
||||||
|
scripts, media or HTML attributes are relaxed.
|
||||||
|
|
||||||
|
The `Management Templates` unordered list receives a local
|
||||||
|
`portal-template-grid` class: two columns at desktop widths (768px+),
|
||||||
|
one column on smaller screens. Semantic list order and keyboard tab order
|
||||||
|
are retained, with responsive full-width buttons. This is a presentation
|
||||||
|
change only: it does not infer or approve employee resource access.
|
||||||
|
Synthetic staff/management browser fixtures check the distinction and
|
||||||
|
responsive columns. The actual decrypted staff source remains private;
|
||||||
|
owner should confirm layout and links in the local preview before merging.
|
||||||
|
|
||||||
|
Scoped typography, spacing, lists, table rules and keyboard focus apply to both
|
||||||
|
unlocked streams. Synthetic staff/management fixtures exercise these mappings
|
||||||
|
at 320/390/768/1440px. Owner must inspect the real views privately to confirm
|
||||||
|
legacy button recognition and source fidelity; if a different class is used,
|
||||||
|
provide sanitized class semantics rather than decrypted content or credentials.
|
||||||
|
|
||||||
|
Before owner acceptance: validate two real view codes privately, inspect every
|
||||||
|
resource/category, responsive directories, focus, link semantics and sanitization
|
||||||
|
impact. Check wrong-code feedback, keyboard unlock, no-JS explanation and refresh.
|
||||||
|
Production must use a separately reviewed runtime ciphertext delivery mechanism;
|
||||||
|
this batch intentionally provides only a gated local build input. Browser-delivered
|
||||||
|
ciphertext is publicly downloadable by anyone able to reach that preview.
|
||||||
@@ -0,0 +1,156 @@
|
|||||||
|
# AIA Form A Jotform styling and conditional-button guide
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
The selectors target Jotform Classic Forms identifiers such as `#form`, `.form-all`, `.form-line`, `.form-label`, `.form-sub-label`, `.form-required`, `.form-textbox`, `.form-dropdown`, `.form-textarea`, `.form-error-message`, and `.form-submit-button`. Jotform's final generated DOM must be checked in the account before relying on pixel-level parity. The stylesheet does not hide required indicators, error messages, honeypots, or focus outlines, and it does not request fonts or other external assets.
|
||||||
|
|
||||||
|
The current Builder theme reconciliation adds narrowly scoped `!important` declarations to the outer surface, labels, inputs, and submit-button treatments that Jotform's generated theme otherwise overrides. Error, required-indicator, and focus rules remain visible and are deliberately not reset. The account owner must still confirm the final generated DOM and rendered form after any Jotform theme or field change.
|
||||||
|
|
||||||
|
## 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. 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 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.
|
||||||
|
|
||||||
|
## Current Form A operation — superseding decision, 2026-10-30
|
||||||
|
|
||||||
|
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
|
||||||
|
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
|
||||||
|
```
|
||||||
|
|
||||||
|
`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.
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
|
| 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. No Form C is planned.
|
||||||
|
`/referrals` independently links to the existing hosted Jotform
|
||||||
|
`https://form.jotform.com/231638510219149`, not to Form A. That link is
|
||||||
|
owner-directed but its legacy form's runtime privacy/recipient acceptance remains
|
||||||
|
separate from Form A. 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
|
||||||
|
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.
|
||||||
|
```
|
||||||
|
|
||||||
|
Employee-portal ciphertext remains separately gated by its own approval, private
|
||||||
|
input and non-indexing preview requirement. Form A modes cannot authorize it.
|
||||||
|
|
||||||
|
## Existing professional referral destination (owner decision 2026-11-01)
|
||||||
|
|
||||||
|
`/referrals` has one `Refer a Client` link to
|
||||||
|
[the existing hosted Jotform](https://form.jotform.com/231638510219149). It does not embed Form A
|
||||||
|
or use Form C. No new form, question, Jotform integration, query parameter or
|
||||||
|
notification routing is introduced. Test the link and verify the separate
|
||||||
|
existing form's privacy, field necessity, recipients and confirmation with its
|
||||||
|
account owner before release.
|
||||||
|
|
||||||
|
## Form context and button labels
|
||||||
|
|
||||||
|
The current Form A design uses a hidden `formContext` value with fixed, approved values such as `contact` and `landing`. Jotform does not provide a native conditional rule that changes one Submit button's accessible label safely in every context. If owner-approved context-specific labels are required, use multiple native Jotform Submit buttons and Jotform's conditional visibility rules:
|
||||||
|
|
||||||
|
- Add one native Submit button for each approved context/language label.
|
||||||
|
- Show exactly one intended Submit button for the current, validated `formContext`.
|
||||||
|
- Keep every button a real Jotform Submit control; do not use CSS `::before`/`::after` text as a label.
|
||||||
|
- Verify that every visible variant submits through the same approved form and preserves the honeypot and validation behavior.
|
||||||
|
- Make the no-context and invalid-context states fail closed: no ambiguous extra button and no unintended submission path.
|
||||||
|
- Verify keyboard order, focus visibility, screen-reader names, English/Spanish labels, and mobile layout for every variant.
|
||||||
|
|
||||||
|
All five landing routes use Form A's fixed `landing` context. The nine consultation
|
||||||
|
placements use its fixed `consultation` context. Jotform owns native Submit labels
|
||||||
|
and conditions. Do not add an external Astro button that attempts to submit a
|
||||||
|
cross-origin iframe.
|
||||||
|
|
||||||
|
## Verification checklist
|
||||||
|
|
||||||
|
- [x] Direct English/Spanish Form A language handling, conditional email requirement, synthetic submission and native thank-you were owner-verified; this is not embedded-iframe acceptance.
|
||||||
|
- [x] Direct staff-notification/autoresponder delivery, generic no-answer/no-PDF content, fixed Reply-To, recipient access/retention, and absent webhooks/integrations were owner-verified for Form A.
|
||||||
|
- [ ] Exact remaining Form A consultation question properties, choices, conditional routing and availability, and consultation language/configuration, are approved.
|
||||||
|
- [ ] English and Spanish embedded-iframe labels, validation, confirmation, and button variants are reviewed by fluent-language owners.
|
||||||
|
- [ ] The hidden honeypot remains present, effective, and excluded from user-facing visual changes.
|
||||||
|
- [ ] Exactly one native Submit button is visible for every valid context.
|
||||||
|
- [ ] Invalid or missing context does not expose an unintended submission path.
|
||||||
|
- [ ] No PHI-bearing answer, PDF, recipient, redirect, webhook, or HTTP POST forwarding is inherited without privacy/security approval.
|
||||||
|
- [x] Owner-reported embedded synthetic submission and confirmation passed on English contact, Spanish contact and one ABA landing placement; record the exact ABA path in the owner test log before release.
|
||||||
|
- [ ] All sixteen placements have final responsive, keyboard, screen-reader and fluent-language acceptance, including timeout/fallback and error expansion.
|
||||||
|
- [ ] Jotform runtime requests, telemetry and cross-origin failure behavior are reviewed with privacy/security owners.
|
||||||
|
- [ ] No Jotform, Contabo, analytics, advertising, or production API request is made by off/mock builds.
|
||||||
|
|
||||||
|
Existing owner-verification scopes remain recorded in the contract/checklist. Outstanding consultation configuration acceptance, runtime/privacy, accessibility, fluent-language and site-release gates remain open. Default-live Form A is owner-authorized; this guide does not authorize Jotform account changes or site deployment.
|
||||||
@@ -0,0 +1,252 @@
|
|||||||
|
/* ==========================================================
|
||||||
|
AIA FORM A — JOTFORM CUSTOM CSS
|
||||||
|
Form ID: 262946078314059
|
||||||
|
Maximum form width: 640px
|
||||||
|
========================================================== */
|
||||||
|
|
||||||
|
/* Document and language selector */
|
||||||
|
|
||||||
|
html.supernova,
|
||||||
|
html.supernova body,
|
||||||
|
body.supernova {
|
||||||
|
background: #fff !important;
|
||||||
|
background-image: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Avoid horizontal overflow, including on the thank-you page */
|
||||||
|
body {
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Confirmation page styling */
|
||||||
|
body.thankyou,
|
||||||
|
body.thankyou #stage {
|
||||||
|
background: #fff !important;
|
||||||
|
background-image: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jfLangDd.jfLangDd--match-form {
|
||||||
|
padding: 12px 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Form container */
|
||||||
|
|
||||||
|
form[id="262946078314059"] {
|
||||||
|
width: 100% !important;
|
||||||
|
max-width: 640px !important;
|
||||||
|
margin: 8px auto !important;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-all {
|
||||||
|
width: 100% !important;
|
||||||
|
max-width: 100% !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
background: #fff !important;
|
||||||
|
border: 0 !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
color: #254080;
|
||||||
|
font-family: Rubik, Arial, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-all .form-section {
|
||||||
|
margin: 0 !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Field layout */
|
||||||
|
|
||||||
|
.form-all .form-line {
|
||||||
|
margin: 0 !important;
|
||||||
|
padding: 0 0 21px !important;
|
||||||
|
background: transparent !important;
|
||||||
|
border: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-all .form-input-wide {
|
||||||
|
margin-top: 0 !important;
|
||||||
|
padding-top: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Labels and sublabels */
|
||||||
|
|
||||||
|
.form-all .form-label,
|
||||||
|
.form-all .form-label-left,
|
||||||
|
.form-all .form-label-right,
|
||||||
|
.form-all .form-label-top {
|
||||||
|
color: #254080 !important;
|
||||||
|
font-size: .875rem;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1.35 !important;
|
||||||
|
margin: 0 0 6px !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-all .form-sub-label {
|
||||||
|
color: #254080;
|
||||||
|
font-size: .75rem;
|
||||||
|
line-height: 1.3 !important;
|
||||||
|
margin: 4px 0 0 !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-all .form-sub-label-container {
|
||||||
|
margin-top: 0 !important;
|
||||||
|
margin-bottom: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-all .form-required {
|
||||||
|
color: #a21c28 !important;
|
||||||
|
margin-left: .2rem;
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Inputs */
|
||||||
|
|
||||||
|
.form-all input.form-textbox,
|
||||||
|
.form-all select.form-dropdown,
|
||||||
|
.form-all textarea.form-textarea {
|
||||||
|
background: #fcf9f5 !important;
|
||||||
|
background-image: none !important;
|
||||||
|
border: 1px solid #edeef3 !important;
|
||||||
|
border-radius: 4px !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
box-sizing: border-box;
|
||||||
|
color: #254080 !important;
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 1.4;
|
||||||
|
min-height: 2.75rem;
|
||||||
|
padding: .55rem .7rem;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Preserve two-column name fields */
|
||||||
|
|
||||||
|
.form-all .form-sub-label-container input.form-textbox {
|
||||||
|
width: 100% !important;
|
||||||
|
max-width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Full-width phone and email fields */
|
||||||
|
|
||||||
|
.form-all
|
||||||
|
.form-line:is(
|
||||||
|
[data-type="control_phone"],
|
||||||
|
[data-type="control_email"]
|
||||||
|
)
|
||||||
|
:is(.form-input, .form-input-wide, input.form-textbox) {
|
||||||
|
width: 100% !important;
|
||||||
|
max-width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Message field */
|
||||||
|
|
||||||
|
.form-all textarea.form-textarea {
|
||||||
|
width: 100% !important;
|
||||||
|
min-height: 5.5rem !important;
|
||||||
|
resize: vertical;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Radio buttons and checkboxes */
|
||||||
|
|
||||||
|
.form-all .form-radio-item,
|
||||||
|
.form-all .form-checkbox-item {
|
||||||
|
color: #254080;
|
||||||
|
line-height: 1.4;
|
||||||
|
margin: 0 .75rem .2rem 0 !important;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-all .form-radio,
|
||||||
|
.form-all .form-checkbox {
|
||||||
|
accent-color: #254080;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Submit button and wrapper */
|
||||||
|
|
||||||
|
.form-all .jf-form-buttons,
|
||||||
|
.form-all .form-buttons-wrapper {
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 100% !important;
|
||||||
|
max-width: 100% !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
background: transparent !important;
|
||||||
|
border: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-all .form-submit-button,
|
||||||
|
.form-all button[type="submit"] {
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
min-height: 3rem;
|
||||||
|
padding: .65rem 1.2rem;
|
||||||
|
background: #ffbd59 !important;
|
||||||
|
background-image: none !important;
|
||||||
|
border: 2px solid #ffbd59 !important;
|
||||||
|
border-radius: 4px !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
color: #254080 !important;
|
||||||
|
cursor: pointer;
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 1.4;
|
||||||
|
text-shadow: none !important;
|
||||||
|
transition: background .3s linear, border-color .3s linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-all .form-submit-button:hover,
|
||||||
|
.form-all button[type="submit"]:hover {
|
||||||
|
background: transparent !important;
|
||||||
|
border-color: #ff914d !important;
|
||||||
|
color: #254080 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-all .form-submit-button:disabled,
|
||||||
|
.form-all button[type="submit"]:disabled {
|
||||||
|
cursor: not-allowed;
|
||||||
|
opacity: .65;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Keyboard focus */
|
||||||
|
|
||||||
|
.form-all input.form-textbox:focus-visible,
|
||||||
|
.form-all select.form-dropdown:focus-visible,
|
||||||
|
.form-all textarea.form-textarea:focus-visible,
|
||||||
|
.form-all input[type="radio"]:focus-visible,
|
||||||
|
.form-all input[type="checkbox"]:focus-visible,
|
||||||
|
.form-all .form-submit-button:focus-visible {
|
||||||
|
outline: 3px solid #115bbd !important;
|
||||||
|
outline-offset: -3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Validation */
|
||||||
|
|
||||||
|
.form-all .form-line-error input.form-textbox,
|
||||||
|
.form-all .form-line-error select.form-dropdown,
|
||||||
|
.form-all .form-line-error textarea.form-textarea,
|
||||||
|
.form-all input.form-validation-error {
|
||||||
|
border-color: #a21c28 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-all .form-error-message,
|
||||||
|
.form-all .form-line-error .form-error-message {
|
||||||
|
color: #a21c28 !important;
|
||||||
|
font-size: .8rem;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1.4;
|
||||||
|
margin: .3rem 0 0 !important;
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Accessibility: reduced motion */
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
.form-all .form-submit-button,
|
||||||
|
.form-all button[type="submit"] {
|
||||||
|
transition: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
# Inactive SOPS/age preparation, 2026-10-30
|
||||||
|
|
||||||
|
The owner selected SOPS, age and sops-nix. This directory is a template, not a
|
||||||
|
host configuration. The development flake remains unchanged. No real recipient,
|
||||||
|
key, encrypted secret or server user is supplied. No module is deployed.
|
||||||
|
|
||||||
|
Official references inspected for this pass:
|
||||||
|
- [SOPS documentation](https://getsops.io/docs/)
|
||||||
|
- [sops-nix installation and secret permissions](https://github.com/Mic92/sops-nix)
|
||||||
|
|
||||||
|
SOPS encrypts configuration at rest. sops-nix can supply decrypted values at
|
||||||
|
runtime under `/run/secrets` with explicit owners and modes. This does not make
|
||||||
|
browser ciphertext or publicly served documents private.
|
||||||
|
|
||||||
|
## Owner setup before activation
|
||||||
|
|
||||||
|
1. Supply the actual NixOS topology, host flake, deploy user, persisted key
|
||||||
|
location, backup owner, HTTPS termination and resource-service identity.
|
||||||
|
2. Pin a reviewed `github:Mic92/sops-nix` input in that host flake; import
|
||||||
|
`inputs.sops-nix.nixosModules.sops` and the reviewed template. Do not add the
|
||||||
|
input to the Astro development flake just to evaluate a deployment sketch.
|
||||||
|
3. The owner generates independent developer/recovery and VPS age identities in
|
||||||
|
private terminals. Record only public recipients in the reviewed SOPS
|
||||||
|
creation rule. Use distinct recipients, never a placeholder recipient. Keep
|
||||||
|
the VPS private identity on persistent root-controlled storage (0600), outside
|
||||||
|
`/nix/store`, Git, the public static root and CI artifacts.
|
||||||
|
4. Encrypt the approved credential material using SOPS with both recipients.
|
||||||
|
Review recipient access, least privilege and an offline recovery copy. SOPS
|
||||||
|
encrypted files may enter a deployment repository only after owner approval.
|
||||||
|
5. Set `aia.portalSecrets` options explicitly, then evaluate the complete host
|
||||||
|
configuration and test decryption on authorized nonproduction infrastructure.
|
||||||
|
Runtime consumers use the generated `.path`, not Nix evaluation of plaintext.
|
||||||
|
6. Decide which service reloads after rotation. Rotate application credentials
|
||||||
|
as well as SOPS recipients when revoking access: rewrapping alone does not
|
||||||
|
invalidate an already copied password. Test recovery and key restoration.
|
||||||
|
|
||||||
|
## Separate staff and management resource authorization
|
||||||
|
|
||||||
|
Keep original documents outside Astro `public`, `dist`, release archives and
|
||||||
|
CDN roots. Proposed delivery namespaces are `/staff-resources/` and
|
||||||
|
`/management-resources/`; neither is implemented or considered working here.
|
||||||
|
Use nginx `auth_request` to an approved authorization service or an equivalent
|
||||||
|
server-enforced policy with individually revocable identities and staff and
|
||||||
|
management roles. Staff credentials must not authorize management resources;
|
||||||
|
management access to staff resources must be an explicit policy. Backend file
|
||||||
|
locations must be internal, inaccessible through static aliases or alternate
|
||||||
|
paths. Never trust a browser-provided role header.
|
||||||
|
|
||||||
|
A separate shared Basic Auth credential file per namespace can be considered
|
||||||
|
only as an explicitly approved weaker interim model, not identity management or
|
||||||
|
automatic role inheritance. The template prepares separate secret inputs without
|
||||||
|
selecting that access model or installing an identity provider.
|
||||||
|
|
||||||
|
Use HTTPS, `Cache-Control: private, no-store`, no shared/CDN caching, and
|
||||||
|
`Referrer-Policy: no-referrer` for protected delivery. Avoid credentials and
|
||||||
|
sensitive resource paths in access/error logs; review monitoring and backups.
|
||||||
|
Authorization failures must fail closed, including at proxy/cache boundaries.
|
||||||
|
Test direct requests, alternate encodings, role crossover and rollback.
|
||||||
|
|
||||||
|
## Distinct boundaries and release checks
|
||||||
|
|
||||||
|
- SOPS: deployment secrets at rest and controlled runtime access.
|
||||||
|
- Portal HTML: shared-code browser decryption, offline-guessable access friction.
|
||||||
|
- Documents: require server authorization even if URLs are encrypted in the UI.
|
||||||
|
|
||||||
|
The approved production portal build uses a non-public encrypted two-stream
|
||||||
|
payload and retains the same browser-side decryption boundary. Approved non-PHI
|
||||||
|
documents install separately into the VPS-owned staff/management directories;
|
||||||
|
they are never copied into `dist`. Verify both protected namespaces, two-view
|
||||||
|
separation, artifact exclusions, code rotation, restore and rollback before
|
||||||
|
cutover. Revoking a static release cannot retract ciphertext or files already
|
||||||
|
downloaded by visitors. Site cutover remains separately authorized.
|
||||||
@@ -0,0 +1,135 @@
|
|||||||
|
# Contabo release operations
|
||||||
|
|
||||||
|
This site publishes static content through the merged Contabo release manager.
|
||||||
|
It does not run `nixos-rebuild`, reload nginx, change DNS, or write directly to
|
||||||
|
`/srv/www/azinstitute4autism.com/www/dist`.
|
||||||
|
|
||||||
|
## Required local tools and private inputs
|
||||||
|
|
||||||
|
- Node.js 22+, Git, tar, SSH and rsync.
|
||||||
|
- Either an OpenSSH host alias already configured locally, or a normal SSH
|
||||||
|
identity accepted by the existing root receiver.
|
||||||
|
- For environment-only invocations: `AIA_DEPLOY_HOST=administrator@host`,
|
||||||
|
`AIA_DEPLOY_SSH_IDENTITY=/absolute/path/to/identity`, and
|
||||||
|
`AIA_PORTAL_PRODUCTION_CIPHERTEXT_FILE=/absolute/private/employee-portal/approved-production-ciphertext.json`.
|
||||||
|
- For positional invocations, use either `SSH_HOST CIPHERTEXT` (OpenSSH resolves
|
||||||
|
the host alias and identity) or `SSH_HOST SSH_IDENTITY CIPHERTEXT` (the CLI
|
||||||
|
supplies `-i` and `IdentitiesOnly=yes`).
|
||||||
|
|
||||||
|
The payload remains outside Git and the source snapshot. It is browser ciphertext
|
||||||
|
only; neither access code nor decrypted portal HTML enters an Astro environment
|
||||||
|
variable, public resource directory, build log, or deployment manifest.
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
From `www/`:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm run deploy -- --dry-run
|
||||||
|
|
||||||
|
# Use a configured OpenSSH host alias and a private ciphertext path.
|
||||||
|
npm run deploy -- --dry-run aiar \
|
||||||
|
"$PWD/private/employee-portal/approved-production-ciphertext.json"
|
||||||
|
|
||||||
|
# Supply an explicit SSH identity; paths may contain spaces.
|
||||||
|
npm run deploy -- --dry-run 'root@66.94.121.180' \
|
||||||
|
"$HOME/.ssh/AIAMarketing" \
|
||||||
|
"$PWD/private/employee-portal/approved-production-ciphertext.json"
|
||||||
|
```
|
||||||
|
|
||||||
|
Dry-run performs the local production build, tests, artifact verification,
|
||||||
|
manifest creation and source-snapshot preparation. With no private production
|
||||||
|
payload it uses a generated synthetic two-stream fixture and explicitly reports
|
||||||
|
that the result is not production-ready. It never opens SSH or rsync.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
AIA_DEPLOY_HOST='root@approved-host' \
|
||||||
|
AIA_DEPLOY_SSH_IDENTITY="$HOME/.ssh/AIAMarketing" \
|
||||||
|
AIA_PORTAL_PRODUCTION_CIPHERTEXT_FILE="$PWD/private/employee-portal/approved-production-ciphertext.json" \
|
||||||
|
npm run deploy -- --confirm
|
||||||
|
```
|
||||||
|
|
||||||
|
The equivalent confirmed positional commands are:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm run deploy -- --confirm aiar \
|
||||||
|
"$PWD/private/employee-portal/approved-production-ciphertext.json"
|
||||||
|
|
||||||
|
npm run deploy -- --confirm 'root@66.94.121.180' \
|
||||||
|
"$HOME/.ssh/AIAMarketing" \
|
||||||
|
"$PWD/private/employee-portal/approved-production-ciphertext.json"
|
||||||
|
```
|
||||||
|
|
||||||
|
When positional values are present, they take precedence over all three
|
||||||
|
deployment environment variables. Two positional values deliberately omit
|
||||||
|
`-i`, allowing the local OpenSSH configuration to select the identity. Dry-run
|
||||||
|
never opens SSH or rsync, even when host and identity arguments are provided.
|
||||||
|
Invalid modes, mixed confirmation flags, incomplete positional sets, unsafe
|
||||||
|
hosts, relative positional paths, and missing ciphertext files fail before a
|
||||||
|
release can be promoted.
|
||||||
|
|
||||||
|
The confirmed command builds with `PUBLIC_ALLOW_INDEXING=true`, Form A live and
|
||||||
|
the approved live counters configuration, then uploads only fresh commit-specific `staging/source-<sha>` and
|
||||||
|
`staging/dist-<sha>` directories. It runs, in order:
|
||||||
|
|
||||||
|
```text
|
||||||
|
aia-website-release verify
|
||||||
|
aia-website-release sync-source
|
||||||
|
aia-website-release promote
|
||||||
|
```
|
||||||
|
|
||||||
|
The VPS verifies the manifest, promotes an immutable release by atomic symlink,
|
||||||
|
and retains the prior release. A successful rsync transfer alone is not success.
|
||||||
|
|
||||||
|
Rollback requires the reviewed manifest retained at the server’s fixed path:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
AIA_DEPLOY_HOST='root@approved-host' \
|
||||||
|
AIA_DEPLOY_SSH_IDENTITY="$HOME/.ssh/AIAMarketing" \
|
||||||
|
npm run deploy:rollback -- FULL_APPROVED_SHA --confirm
|
||||||
|
```
|
||||||
|
|
||||||
|
## Employee resources: separate one-time operation
|
||||||
|
|
||||||
|
Approved non-PHI employee files are never part of an ordinary release. After
|
||||||
|
the VPS SOPS-backed Basic Auth material is independently ready:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm run deploy:portal-resources -- --dry-run
|
||||||
|
|
||||||
|
AIA_DEPLOY_HOST='root@approved-host' \
|
||||||
|
AIA_DEPLOY_SSH_IDENTITY="$HOME/.ssh/AIAMarketing" \
|
||||||
|
npm run deploy:portal-resources -- --confirm
|
||||||
|
```
|
||||||
|
|
||||||
|
For the first install, the client extracts `portal-resource-install.sh` from the
|
||||||
|
current reviewed Git commit, uploads it into the root-controlled commit staging
|
||||||
|
directory, verifies its SHA-256 remotely, and invokes it through NixOS's base
|
||||||
|
`/bin/sh` and coreutils path. A prior public site release and a globally installed
|
||||||
|
Node.js runtime are not prerequisites. It reads only the private collection manifest,
|
||||||
|
accepts approved `STAFF-INTERNAL` and `MANAGEMENT-INTERNAL` mappings to
|
||||||
|
`/staff-resources/` and `/management-resources/`, verifies every local hash, rejects links/traversal and
|
||||||
|
uploads a root-controlled temporary tree. It never uses `--delete` for resource
|
||||||
|
directories and refuses to replace a different existing file. The VPS installs
|
||||||
|
regular files as `root:nginx` mode `0640` and reports metadata only.
|
||||||
|
|
||||||
|
Local mapping approval authorizes preparation and installation only. After the
|
||||||
|
authorized VPS rehearsal, verify installed hashes, ownership/mode, staff versus
|
||||||
|
management Basic Auth, and both protected URLs before deploying portal links.
|
||||||
|
|
||||||
|
Before public DNS cutover, test the site with approved host-header/SNI methods,
|
||||||
|
including the portal’s noindex response, valid ciphertext unlock, both protected
|
||||||
|
resource namespaces, denial cases, redirects, Form A, IPv4 and IPv6. Portal
|
||||||
|
shared-code rotation is coordinated: update VPS SOPS inputs and privately
|
||||||
|
re-encrypt the browser payload together. This interim portal is non-PHI and is
|
||||||
|
not an employee identity system.
|
||||||
|
|
||||||
|
The portal uses one code entry per page session. A successful decrypt retains
|
||||||
|
the code only in page memory and sends the matching fixed username (`staff` or
|
||||||
|
`management`) in an explicit same-origin Basic Authorization header when a
|
||||||
|
protected link is clicked. It downloads the authenticated response as a Blob
|
||||||
|
and never navigates directly to the protected URL after an error. Verify that
|
||||||
|
ordinary clicks download without a native credential dialog, inline errors
|
||||||
|
appear for denied or unavailable files, direct unauthenticated requests remain
|
||||||
|
401, and neither role can request the other namespace. Reloading, leaving the
|
||||||
|
page, or an Astro page swap discards the in-memory credential.
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
# INACTIVE TEMPLATE. Not imported by the development flake or any deployed host.
|
||||||
|
# Requires an owner-reviewed sops-nix NixOS module import in the host flake.
|
||||||
|
{ config, lib, ... }:
|
||||||
|
let cfg = config.aia.portalSecrets;
|
||||||
|
in {
|
||||||
|
options.aia.portalSecrets = {
|
||||||
|
enable = lib.mkEnableOption "owner-reviewed portal deployment secrets";
|
||||||
|
encryptedFile = lib.mkOption { type = lib.types.path; description = "SOPS-encrypted YAML only; never a plaintext file"; };
|
||||||
|
ageKeyFile = lib.mkOption { type = lib.types.str; description = "Private persisted host age key path outside the Nix store"; };
|
||||||
|
readerUser = lib.mkOption { type = lib.types.str; description = "Approved resource authorization service user"; };
|
||||||
|
};
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
assertions = [{ assertion = lib.hasPrefix "/" cfg.ageKeyFile && !(lib.hasPrefix "/nix/store/" cfg.ageKeyFile);
|
||||||
|
message = "The host age identity must be an absolute runtime path outside the Nix store."; }];
|
||||||
|
sops.defaultSopsFile = cfg.encryptedFile;
|
||||||
|
sops.age.keyFile = cfg.ageKeyFile;
|
||||||
|
sops.age.generateKey = false;
|
||||||
|
sops.age.sshKeyPaths = [];
|
||||||
|
sops.gnupg.sshKeyPaths = [];
|
||||||
|
sops.secrets."portal/staff-credentials" = { owner = cfg.readerUser; mode = "0400"; };
|
||||||
|
sops.secrets."portal/management-credentials" = { owner = cfg.readerUser; mode = "0400"; };
|
||||||
|
# Consumers reference config.sops.secrets.<name>.path at runtime.
|
||||||
|
# Do not use builtins.readFile on a decrypted secret, environment.etc.text,
|
||||||
|
# PUBLIC_* values, or Astro/Vite imports to transport secrets.
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -3,31 +3,48 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=20.19.0"
|
"node": ">=22.12.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "astro dev",
|
"dev": "astro dev",
|
||||||
"build": "astro build",
|
"check": "astro check",
|
||||||
"build:sandbox": "NODE_OPTIONS=--require=./tools/localhost-dns.cjs astro build",
|
"build": "astro check && astro build",
|
||||||
|
"build:sandbox": "NODE_OPTIONS=--require=./tools/localhost-dns.cjs astro check && NODE_OPTIONS=--require=./tools/localhost-dns.cjs astro build",
|
||||||
|
"deploy": "node tools/deploy.mjs",
|
||||||
|
"deploy:rollback": "node tools/deploy-rollback.mjs",
|
||||||
|
"deploy:portal-resources": "node tools/deploy-portal-resources.mjs",
|
||||||
|
"portal:prepare": "node tools/employee-portal-migrate.mjs",
|
||||||
"preview": "astro preview",
|
"preview": "astro preview",
|
||||||
"extract": "node tools/extract-fallback.mjs",
|
|
||||||
"extract:full": "node tools/extract-site.mjs",
|
|
||||||
"extract:blog-footers": "node tools/extract-blog-footers.mjs",
|
"extract:blog-footers": "node tools/extract-blog-footers.mjs",
|
||||||
"crawl:live": "node tools/crawl-live-site.mjs",
|
"crawl:live": "node tools/crawl-live-site.mjs",
|
||||||
"audit:links": "node tools/audit-links.mjs",
|
"audit:links": "node --experimental-strip-types tools/audit-links.mjs",
|
||||||
"audit:images": "node tools/audit-page-imagery.mjs",
|
"audit:images": "node tools/audit-page-imagery.mjs",
|
||||||
"audit:blog": "node tools/audit-blog-content.mjs",
|
"audit:blog": "node tools/audit-blog-content.mjs",
|
||||||
|
"audit:routes": "node --experimental-strip-types tools/audit-routes.mjs",
|
||||||
|
"test:routes": "node --experimental-strip-types --test tools/audit-routes.test.mjs",
|
||||||
|
"test:markdown": "node --test tools/markdown.test.mjs",
|
||||||
|
"test:publication": "node --experimental-strip-types --test tools/publication.test.mjs",
|
||||||
|
"test:seo": "node --experimental-strip-types --test tools/seo.test.mjs",
|
||||||
|
"test:library": "node --experimental-strip-types --test tools/library.test.mjs",
|
||||||
|
"test:campaign": "node --test tools/campaign.test.mjs",
|
||||||
|
"test:counters": "node --experimental-strip-types --test tools/counters.test.mjs",
|
||||||
|
"verify:counters": "node tools/counters-browser.mjs",
|
||||||
|
"verify:campaign": "node tools/campaign-browser.mjs",
|
||||||
"generate:sitemap": "node tools/generate-sitemap.mjs",
|
"generate:sitemap": "node tools/generate-sitemap.mjs",
|
||||||
"generate:redirects": "node tools/generate-redirects.mjs"
|
"generate:redirects": "node tools/generate-redirects.mjs"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astrojs/mdx": "^4.3.14",
|
"@astrojs/markdown-satteri": "^0.3.5",
|
||||||
"astro": "^5.10.0",
|
"@astrojs/mdx": "^7.0.5",
|
||||||
|
"astro": "^7.1.5",
|
||||||
"cheerio": "^1.1.0",
|
"cheerio": "^1.1.0",
|
||||||
"fast-glob": "^3.3.3",
|
"fast-glob": "^3.3.3",
|
||||||
"gray-matter": "^4.0.3",
|
"gray-matter": "^4.0.3",
|
||||||
"swiper": "^12.2.0",
|
"swiper": "^12.2.0",
|
||||||
"turndown": "^7.2.0",
|
"turndown": "^7.2.0"
|
||||||
"zod": "^3.25.0"
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@astrojs/check": "^0.9.10",
|
||||||
|
"typescript": "^6.0.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
Copyright 2017 The Playfair Display Project Authors (https://github.com/clauseggers/Playfair-Display), with Reserved Font Name "Playfair Display"
|
||||||
|
|
||||||
|
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||||
|
This license is copied below, and is also available with a FAQ at:
|
||||||
|
http://scripts.sil.org/OFL
|
||||||
|
|
||||||
|
|
||||||
|
-----------------------------------------------------------
|
||||||
|
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||||
|
-----------------------------------------------------------
|
||||||
|
|
||||||
|
PREAMBLE
|
||||||
|
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||||
|
development of collaborative font projects, to support the font creation
|
||||||
|
efforts of academic and linguistic communities, and to provide a free and
|
||||||
|
open framework in which fonts may be shared and improved in partnership
|
||||||
|
with others.
|
||||||
|
|
||||||
|
The OFL allows the licensed fonts to be used, studied, modified and
|
||||||
|
redistributed freely as long as they are not sold by themselves. The
|
||||||
|
fonts, including any derivative works, can be bundled, embedded,
|
||||||
|
redistributed and/or sold with any software provided that any reserved
|
||||||
|
names are not used by derivative works. The fonts and derivatives,
|
||||||
|
however, cannot be released under any other type of license. The
|
||||||
|
requirement for fonts to remain under this license does not apply
|
||||||
|
to any document created using the fonts or their derivatives.
|
||||||
|
|
||||||
|
DEFINITIONS
|
||||||
|
"Font Software" refers to the set of files released by the Copyright
|
||||||
|
Holder(s) under this license and clearly marked as such. This may
|
||||||
|
include source files, build scripts and documentation.
|
||||||
|
|
||||||
|
"Reserved Font Name" refers to any names specified as such after the
|
||||||
|
copyright statement(s).
|
||||||
|
|
||||||
|
"Original Version" refers to the collection of Font Software components as
|
||||||
|
distributed by the Copyright Holder(s).
|
||||||
|
|
||||||
|
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||||
|
or substituting -- in part or in whole -- any of the components of the
|
||||||
|
Original Version, by changing formats or by porting the Font Software to a
|
||||||
|
new environment.
|
||||||
|
|
||||||
|
"Author" refers to any designer, engineer, programmer, technical
|
||||||
|
writer or other person who contributed to the Font Software.
|
||||||
|
|
||||||
|
PERMISSION & CONDITIONS
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||||
|
redistribute, and sell modified and unmodified copies of the Font
|
||||||
|
Software, subject to the following conditions:
|
||||||
|
|
||||||
|
1) Neither the Font Software nor any of its individual components,
|
||||||
|
in Original or Modified Versions, may be sold by itself.
|
||||||
|
|
||||||
|
2) Original or Modified Versions of the Font Software may be bundled,
|
||||||
|
redistributed and/or sold with any software, provided that each copy
|
||||||
|
contains the above copyright notice and this license. These can be
|
||||||
|
included either as stand-alone text files, human-readable headers or
|
||||||
|
in the appropriate machine-readable metadata fields within text or
|
||||||
|
binary files as long as those fields can be easily viewed by the user.
|
||||||
|
|
||||||
|
3) No Modified Version of the Font Software may use the Reserved Font
|
||||||
|
Name(s) unless explicit written permission is granted by the corresponding
|
||||||
|
Copyright Holder. This restriction only applies to the primary font name as
|
||||||
|
presented to the users.
|
||||||
|
|
||||||
|
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||||
|
Software shall not be used to promote, endorse or advertise any
|
||||||
|
Modified Version, except to acknowledge the contribution(s) of the
|
||||||
|
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
5) The Font Software, modified or unmodified, in part or in whole,
|
||||||
|
must be distributed entirely under this license, and must not be
|
||||||
|
distributed under any other license. The requirement for fonts to
|
||||||
|
remain under this license does not apply to any document created
|
||||||
|
using the Font Software.
|
||||||
|
|
||||||
|
TERMINATION
|
||||||
|
This license becomes null and void if any of the above conditions are
|
||||||
|
not met.
|
||||||
|
|
||||||
|
DISCLAIMER
|
||||||
|
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||||
|
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||||
|
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||||
|
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
Copyright 2015 The Rubik Project Authors (https://github.com/googlefonts/rubik)
|
||||||
|
|
||||||
|
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||||
|
This license is copied below, and is also available with a FAQ at:
|
||||||
|
https://scripts.sil.org/OFL
|
||||||
|
|
||||||
|
|
||||||
|
-----------------------------------------------------------
|
||||||
|
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||||
|
-----------------------------------------------------------
|
||||||
|
|
||||||
|
PREAMBLE
|
||||||
|
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||||
|
development of collaborative font projects, to support the font creation
|
||||||
|
efforts of academic and linguistic communities, and to provide a free and
|
||||||
|
open framework in which fonts may be shared and improved in partnership
|
||||||
|
with others.
|
||||||
|
|
||||||
|
The OFL allows the licensed fonts to be used, studied, modified and
|
||||||
|
redistributed freely as long as they are not sold by themselves. The
|
||||||
|
fonts, including any derivative works, can be bundled, embedded,
|
||||||
|
redistributed and/or sold with any software provided that any reserved
|
||||||
|
names are not used by derivative works. The fonts and derivatives,
|
||||||
|
however, cannot be released under any other type of license. The
|
||||||
|
requirement for fonts to remain under this license does not apply
|
||||||
|
to any document created using the fonts or their derivatives.
|
||||||
|
|
||||||
|
DEFINITIONS
|
||||||
|
"Font Software" refers to the set of files released by the Copyright
|
||||||
|
Holder(s) under this license and clearly marked as such. This may
|
||||||
|
include source files, build scripts and documentation.
|
||||||
|
|
||||||
|
"Reserved Font Name" refers to any names specified as such after the
|
||||||
|
copyright statement(s).
|
||||||
|
|
||||||
|
"Original Version" refers to the collection of Font Software components as
|
||||||
|
distributed by the Copyright Holder(s).
|
||||||
|
|
||||||
|
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||||
|
or substituting -- in part or in whole -- any of the components of the
|
||||||
|
Original Version, by changing formats or by porting the Font Software to a
|
||||||
|
new environment.
|
||||||
|
|
||||||
|
"Author" refers to any designer, engineer, programmer, technical
|
||||||
|
writer or other person who contributed to the Font Software.
|
||||||
|
|
||||||
|
PERMISSION & CONDITIONS
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||||
|
redistribute, and sell modified and unmodified copies of the Font
|
||||||
|
Software, subject to the following conditions:
|
||||||
|
|
||||||
|
1) Neither the Font Software nor any of its individual components,
|
||||||
|
in Original or Modified Versions, may be sold by itself.
|
||||||
|
|
||||||
|
2) Original or Modified Versions of the Font Software may be bundled,
|
||||||
|
redistributed and/or sold with any software, provided that each copy
|
||||||
|
contains the above copyright notice and this license. These can be
|
||||||
|
included either as stand-alone text files, human-readable headers or
|
||||||
|
in the appropriate machine-readable metadata fields within text or
|
||||||
|
binary files as long as those fields can be easily viewed by the user.
|
||||||
|
|
||||||
|
3) No Modified Version of the Font Software may use the Reserved Font
|
||||||
|
Name(s) unless explicit written permission is granted by the corresponding
|
||||||
|
Copyright Holder. This restriction only applies to the primary font name as
|
||||||
|
presented to the users.
|
||||||
|
|
||||||
|
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||||
|
Software shall not be used to promote, endorse or advertise any
|
||||||
|
Modified Version, except to acknowledge the contribution(s) of the
|
||||||
|
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
5) The Font Software, modified or unmodified, in part or in whole,
|
||||||
|
must be distributed entirely under this license, and must not be
|
||||||
|
distributed under any other license. The requirement for fonts to
|
||||||
|
remain under this license does not apply to any document created
|
||||||
|
using the Font Software.
|
||||||
|
|
||||||
|
TERMINATION
|
||||||
|
This license becomes null and void if any of the above conditions are
|
||||||
|
not met.
|
||||||
|
|
||||||
|
DISCLAIMER
|
||||||
|
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||||
|
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||||
|
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||||
|
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||||
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 119 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 163 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 84 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 93 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 77 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 135 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 93 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 94 KiB |
@@ -0,0 +1 @@
|
|||||||
|
<svg viewBox="113.85996 134.2596 679.2 315.6" xmlns="http://www.w3.org/2000/svg" id="Layer_1" style="max-height: 500px" width="679.2" height="315.6"><defs><style>.cls-1,.cls-2,.cls-3,.cls-4,.cls-5,.cls-6{stroke-width:0px;}.cls-2{fill:#27417f;}.cls-3{fill:#554f62;}.cls-4{fill:#254080;}.cls-5{fill:#aea990;}.cls-6{fill:#f2b85b;}</style></defs><path d="m176.47,162.76l22.18,57.09c.85,2.24,1.83,3.76,2.95,4.54,1.12.79,2.17,1.21,3.14,1.27v1.82c-1.46-.12-3.17-.2-5.14-.22-1.97-.03-3.95-.05-5.95-.05-2.54,0-4.91.01-7.09.05-2.18.03-3.94.11-5.28.22v-1.82c3.09-.12,5.05-.65,5.87-1.59.82-.94.62-2.95-.59-6.04l-16.36-44.17,1.46-1.64-15.09,39.45c-1.09,2.73-1.74,5-1.95,6.82-.22,1.82-.06,3.24.45,4.27.52,1.03,1.41,1.76,2.68,2.18,1.27.43,2.85.67,4.73.73v1.82c-1.82-.12-3.65-.2-5.5-.22-1.85-.03-3.59-.05-5.23-.05-1.46,0-2.74.01-3.86.05-1.12.03-2.14.11-3.05.22v-1.82c1.27-.3,2.55-1.06,3.82-2.27,1.27-1.21,2.48-3.27,3.63-6.18l21.09-54.45h3.09Zm9.54,38.54v1.82h-27.08l.91-1.82h26.18Z" class="cls-2"/><path d="m235.82,179.3c1.76,0,3.26.37,4.5,1.09,1.24.73,2.18,1.65,2.82,2.77.64,1.12.96,2.38.96,3.77,0,1.76-.53,3.26-1.59,4.5-1.06,1.24-2.47,1.86-4.23,1.86-1.51,0-2.8-.46-3.86-1.36-1.06-.91-1.59-2.15-1.59-3.73,0-1.33.35-2.47,1.04-3.41.7-.94,1.5-1.68,2.41-2.22-.6-.49-1.33-.7-2.18-.64-1.64.06-3.15.59-4.55,1.59-1.39,1-2.58,2.27-3.54,3.82-.97,1.54-1.73,3.19-2.27,4.95-.54,1.76-.82,3.4-.82,4.91v20.91c0,2.97.82,4.96,2.46,5.95,1.63,1,3.91,1.5,6.81,1.5v1.91c-1.39-.06-3.38-.14-5.95-.22-2.58-.09-5.28-.14-8.14-.14-2.18,0-4.36.05-6.54.14-2.18.09-3.85.16-5,.22v-1.91c2.37,0,4.04-.45,5.05-1.36,1-.91,1.5-2.64,1.5-5.18v-28.54c0-2.73-.46-4.74-1.36-6.04-.91-1.3-2.64-1.95-5.18-1.95v-1.91c1.94.18,3.82.27,5.64.27,2.06,0,3.99-.11,5.77-.32,1.78-.22,3.44-.53,4.95-.96v10.46c.73-1.76,1.7-3.45,2.91-5.09,1.21-1.63,2.66-2.98,4.36-4.04,1.7-1.06,3.58-1.59,5.64-1.59Z" class="cls-2"/><path d="m264,179.57v39.45c0,2.54.5,4.27,1.5,5.18,1,.91,2.68,1.36,5.05,1.36v1.91c-1.03-.06-2.62-.14-4.77-.22-2.16-.09-4.35-.14-6.59-.14s-4.38.05-6.59.14c-2.21.09-3.86.16-4.96.22v-1.91c2.37,0,4.04-.45,5.05-1.36,1-.91,1.5-2.64,1.5-5.18v-28.54c0-2.73-.46-4.74-1.36-6.04-.91-1.3-2.64-1.95-5.18-1.95v-1.91c1.94.18,3.82.27,5.64.27,2.06,0,3.99-.11,5.77-.32,1.78-.22,3.44-.53,4.95-.96Zm-5.45-21.91c1.88,0,3.45.59,4.73,1.78,1.27,1.18,1.91,2.65,1.91,4.41s-.64,3.23-1.91,4.41c-1.27,1.18-2.85,1.77-4.73,1.77s-3.45-.59-4.73-1.77c-1.27-1.18-1.91-2.65-1.91-4.41s.64-3.23,1.91-4.41c1.27-1.18,2.85-1.78,4.73-1.78Z" class="cls-2"/><path d="m312.54,180.12l-25.09,45.99h8.18c2.42,0,4.58-.49,6.45-1.46,1.88-.97,3.42-2.57,4.64-4.81,1.21-2.24,1.94-5.21,2.18-8.91h2.09c0,4.06.03,7.45.09,10.18s.15,4.97.27,6.73c-2.72-.12-5.54-.22-8.45-.27-2.91-.06-5.79-.09-8.63-.09-3.09,0-6.23.05-9.41.14-3.18.09-6.23.2-9.14.32l25.09-45.99h-8.36c-2.6,0-4.85.5-6.73,1.5-1.88,1-3.35,2.61-4.41,4.82-1.06,2.21-1.74,5.17-2.05,8.86h-2c0-4.12-.03-7.51-.09-10.18-.06-2.66-.15-4.91-.27-6.73,2.67.12,5.45.22,8.36.27,2.91.06,5.82.09,8.73.09s6.14-.05,9.32-.14c3.18-.09,6.26-.2,9.23-.32Z" class="cls-2"/><path d="m340.81,179.3c4.06,0,7.66.85,10.82,2.55,3.15,1.7,5.66,4.36,7.55,8,1.88,3.64,2.81,8.39,2.81,14.27s-.94,10.62-2.81,14.23c-1.88,3.61-4.4,6.24-7.55,7.91-3.15,1.67-6.76,2.5-10.82,2.5s-7.6-.83-10.82-2.5c-3.21-1.67-5.74-4.3-7.59-7.91-1.85-3.61-2.77-8.35-2.77-14.23s.92-10.63,2.77-14.27c1.85-3.64,4.38-6.3,7.59-8,3.21-1.7,6.82-2.55,10.82-2.55Zm0,1.82c-3.15,0-5.73,1.8-7.73,5.41-2,3.61-3,9.47-3,17.59s1,13.95,3,17.5c2,3.55,4.58,5.32,7.73,5.32s5.65-1.77,7.68-5.32c2.03-3.55,3.05-9.38,3.05-17.5s-1.02-13.98-3.05-17.59c-2.03-3.61-4.59-5.41-7.68-5.41Z" class="cls-2"/><path d="m400.07,179.3c2.42,0,4.41.32,5.95.96,1.55.64,2.83,1.5,3.86,2.59,1.09,1.15,1.86,2.64,2.32,4.46.45,1.82.68,4.27.68,7.36v24.36c0,2.54.5,4.27,1.5,5.18,1,.91,2.68,1.36,5.05,1.36v1.91c-1.03-.06-2.64-.14-4.82-.22-2.18-.09-4.33-.14-6.45-.14s-4.11.05-6.14.14c-2.03.09-3.56.16-4.59.22v-1.91c2.06,0,3.51-.45,4.37-1.36.85-.91,1.27-2.64,1.27-5.18v-26.9c0-1.76-.15-3.35-.45-4.77-.31-1.42-.94-2.58-1.91-3.45-.97-.88-2.43-1.32-4.37-1.32-2.24,0-4.23.64-5.95,1.91-1.73,1.27-3.09,3.02-4.09,5.23-1,2.21-1.5,4.68-1.5,7.41v21.91c0,2.54.44,4.27,1.32,5.18.88.91,2.32,1.36,4.32,1.36v1.91c-.97-.06-2.44-.14-4.41-.22-1.97-.09-4.01-.14-6.14-.14s-4.21.05-6.45.14c-2.24.09-3.91.16-5,.22v-1.91c2.37,0,4.04-.45,5.05-1.36,1-.91,1.5-2.64,1.5-5.18v-28.54c0-2.73-.46-4.74-1.36-6.04-.91-1.3-2.64-1.95-5.18-1.95v-1.91c1.94.18,3.82.27,5.64.27,2.06,0,3.99-.11,5.77-.32,1.78-.22,3.44-.53,4.95-.96v9.91c1.57-3.76,3.74-6.39,6.5-7.91,2.75-1.51,5.68-2.27,8.77-2.27Z" class="cls-2"/><path d="m436.06,228.11c-2.54,0-4.73-.49-6.54-1.46-1.82-.97-3.18-2.3-4.09-4-.91-1.69-1.36-3.63-1.36-5.82,0-2.67.6-4.83,1.82-6.5,1.21-1.67,2.77-3.02,4.69-4.04,1.91-1.03,3.94-1.89,6.09-2.59,2.15-.7,4.18-1.36,6.09-2,1.91-.64,3.48-1.38,4.73-2.22,1.24-.85,1.86-1.97,1.86-3.36v-6.18c0-2.18-.35-3.93-1.05-5.23-.7-1.3-1.63-2.22-2.81-2.77-1.19-.55-2.59-.82-4.23-.82-1.4,0-2.88.2-4.46.59-1.57.39-2.81,1.17-3.72,2.32,1.33.37,2.44,1.08,3.32,2.14.88,1.06,1.32,2.38,1.32,3.95,0,1.7-.56,3.03-1.68,4s-2.53,1.45-4.Line truncated
|
||||||
|
After Width: | Height: | Size: 33 KiB |
@@ -0,0 +1,4 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 160" fill="none" stroke="#E5AE56" stroke-width="2">
|
||||||
|
<path d="m67 13 2-10h22l2 10 13 5 9-6 16 16-6 9 5 13 10 2v22l-10 2-5 13 6 9-16 16-9-6-13 5-2 10H69l-2-10-13-5-9 6-16-16 6-9-5-13-10-2V52l10-2 5-13-6-9 16-16 9 6Z" transform="translate(0 17)"/>
|
||||||
|
<circle cx="80" cy="80" r="26"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 346 B |
|
After Width: | Height: | Size: 109 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 63 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 42 KiB |
@@ -0,0 +1,24 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="800" height="450" viewBox="0 0 800 450">
|
||||||
|
<title>نموذج المقدمة والسلوك والنتيجة اللاحقة</title>
|
||||||
|
<image href="data:image/webp;base64,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 truncated
|
||||||
|
<rect width="800" height="64" fill="#fbf8ef" />
|
||||||
|
<g fill="#082f55" font-family="Arial, sans-serif" font-size="25" font-weight="700" text-anchor="middle" direction="rtl">
|
||||||
|
<text x="132" y="43">المُقدِّمة</text>
|
||||||
|
<text x="400" y="43">السلوك</text>
|
||||||
|
<text x="668" y="43">النتيجة اللاحقة</text>
|
||||||
|
</g>
|
||||||
|
<g fill="none" stroke="#082f55" stroke-linecap="round" stroke-linejoin="round" stroke-width="4">
|
||||||
|
<path d="M235 37h60m-12-11 12 11-12 11" />
|
||||||
|
<path d="M507 37h57m-12-11 12 11-12 11" />
|
||||||
|
</g>
|
||||||
|
<rect x="381" y="190" width="50" height="24" rx="3" fill="#fff" opacity=".98" />
|
||||||
|
<text x="406" y="206" fill="#1f2933" font-family="Arial, sans-serif" font-size="9" text-anchor="middle" direction="rtl">المزيد</text>
|
||||||
|
<rect x="611" y="190" width="65" height="24" rx="3" fill="#fff" opacity=".98" />
|
||||||
|
<text x="643" y="205" fill="#1f2933" font-family="Arial, sans-serif" font-size="7" text-anchor="middle" direction="rtl">دقيقتان إضافيتان</text>
|
||||||
|
<rect x="531" y="351" width="255" height="91" rx="12" fill="#e8efe8" />
|
||||||
|
<g fill="#082f55" font-family="Arial, sans-serif" font-size="14" direction="rtl" text-anchor="middle">
|
||||||
|
<text x="658" y="374">◷ حصلتَ على دقيقتين إضافيتين.</text>
|
||||||
|
<text x="658" y="399">← ثم ينتهي الوقت.</text>
|
||||||
|
<text x="658" y="424">▣ تستمر خطة «أولًا/ثم».</text>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 58 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 86 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 61 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 68 KiB |
|
After Width: | Height: | Size: 51 KiB |
|
After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 49 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 67 KiB |
|
After Width: | Height: | Size: 26 KiB |
@@ -0,0 +1,14 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="800" height="450" viewBox="0 0 800 450">
|
||||||
|
<title>طفل يعمل في مساحة هادئة تقل فيها المشتتات</title>
|
||||||
|
<image href="data:image/webp;base64,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 truncated
|
||||||
|
<g transform="translate(639 35) rotate(-1 71 87)">
|
||||||
|
<rect width="142" height="174" rx="3" fill="#eee9d8" stroke="#716b5d" stroke-width="2" />
|
||||||
|
<g fill="#304c39" font-family="Arial, sans-serif" direction="rtl" text-anchor="middle">
|
||||||
|
<text x="71" y="31" font-size="17" font-weight="700">ركن الهدوء</text>
|
||||||
|
<text x="71" y="65" font-size="12">♥ كن لطيفًا</text>
|
||||||
|
<text x="71" y="95" font-size="12">◯ خذ نفسًا عميقًا</text>
|
||||||
|
<text x="71" y="125" font-size="12">★ ابذل جهدك</text>
|
||||||
|
<text x="71" y="155" font-size="12">✓ أنت قادر</text>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 55 KiB |
@@ -0,0 +1,68 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="800" height="533" viewBox="0 0 800 533">
|
||||||
|
<title>مقارنة بين الهروب من مهمة صعبة واستخدام سلوك بديل لطلب المساعدة</title>
|
||||||
|
<image href="data:image/webp;base64,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 truncated
|
||||||
|
<style>
|
||||||
|
text { font-family: Arial, sans-serif; }
|
||||||
|
.heading { fill: #092f54; font-weight: 700; }
|
||||||
|
.body { fill: #202b31; }
|
||||||
|
</style>
|
||||||
|
<rect width="800" height="61" fill="#fbf8ef" />
|
||||||
|
<text class="heading" x="400" y="41" font-size="24" text-anchor="middle" direction="rtl">الموقف نفسه: المهمة صعبة</text>
|
||||||
|
|
||||||
|
<rect x="18" y="69" width="91" height="185" rx="12" fill="#c75f45" />
|
||||||
|
<g fill="#fff" text-anchor="middle" direction="rtl">
|
||||||
|
<text x="63" y="96" font-size="15" font-weight="700">المسار أ</text>
|
||||||
|
<text x="63" y="119" font-size="12" font-weight="700"><tspan x="63">استجابة</tspan><tspan x="63" dy="17">غير فعّالة</tspan></text>
|
||||||
|
<text x="63" y="187" font-size="10"><tspan x="63">تُلبّى الحاجة بطريقة</tspan><tspan x="63" dy="15">لا تساعد الطفل</tspan><tspan x="63" dy="15">على التعلّم.</tspan></text>
|
||||||
|
</g>
|
||||||
|
<rect x="111" y="59" width="550" height="29" fill="#fbf8ef" />
|
||||||
|
<g class="heading" font-size="12" text-anchor="middle" direction="rtl">
|
||||||
|
<text x="190" y="79">١. تقديم المهمة</text>
|
||||||
|
<text x="374" y="79">٢. سلوك يعيق المشاركة</text>
|
||||||
|
<text x="566" y="79">٣. النتيجة اللاحقة</text>
|
||||||
|
</g>
|
||||||
|
<rect x="111" y="190" width="550" height="66" fill="#fbf8ef" />
|
||||||
|
<g class="body" font-size="10" text-anchor="middle" direction="rtl">
|
||||||
|
<text x="190" y="211"><tspan x="190">تُقدَّم مهمة</tspan><tspan x="190" dy="15">صعبة.</tspan></text>
|
||||||
|
<text x="374" y="207"><tspan x="374">يدفع الطفل المواد بعيدًا</tspan><tspan x="374" dy="15">للهروب أو التجنب.</tspan></text>
|
||||||
|
<text x="566" y="203"><tspan x="566">تُزال المهمة أو تتوقف مؤقتًا،</tspan><tspan x="566" dy="14">فيتعزز الهروب ويزداد احتمال</tspan><tspan x="566" dy="14">تكرار السلوك.</tspan></text>
|
||||||
|
</g>
|
||||||
|
<rect x="679" y="70" width="103" height="184" rx="12" fill="#f7eadf" />
|
||||||
|
<g fill="#9c452e" text-anchor="middle" direction="rtl">
|
||||||
|
<text x="731" y="99" font-size="14" font-weight="700">النتيجة</text>
|
||||||
|
<text x="731" y="153" font-size="10"><tspan x="731">يلبّي السلوك الصعب</tspan><tspan x="731" dy="15">حاجة الطفل على المدى</tspan><tspan x="731" dy="15">القصير، لكن التعلّم</tspan><tspan x="731" dy="15">لا يتقدم.</tspan></text>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<rect x="18" y="271" width="91" height="194" rx="12" fill="#3f7a65" />
|
||||||
|
<g fill="#fff" text-anchor="middle" direction="rtl">
|
||||||
|
<text x="63" y="298" font-size="15" font-weight="700">المسار ب</text>
|
||||||
|
<text x="63" y="321" font-size="12" font-weight="700">بديل فعّال</text>
|
||||||
|
<text x="63" y="388" font-size="10"><tspan x="63">تُلبّى الحاجة نفسها</tspan><tspan x="63" dy="15">بطريقة آمنة وفعّالة</tspan><tspan x="63" dy="15">تدعم التعلّم.</tspan></text>
|
||||||
|
</g>
|
||||||
|
<rect x="109" y="245" width="566" height="44" fill="#fbf8ef" />
|
||||||
|
<g fill="#316b58" font-size="11" font-weight="700" text-anchor="middle" direction="rtl">
|
||||||
|
<text x="173" y="279">١. تقديم المهمة</text>
|
||||||
|
<text x="302" y="279">٢. السلوك البديل</text>
|
||||||
|
<text x="441" y="279">٣. استجابة مفيدة</text>
|
||||||
|
<text x="593" y="279">٤. النتيجة اللاحقة</text>
|
||||||
|
</g>
|
||||||
|
<rect x="110" y="405" width="565" height="68" fill="#fbf8ef" />
|
||||||
|
<g class="body" font-size="9.5" text-anchor="middle" direction="rtl">
|
||||||
|
<text x="173" y="427"><tspan x="173">تُقدَّم مهمة</tspan><tspan x="173" dy="14">صعبة.</tspan></text>
|
||||||
|
<text x="302" y="419"><tspan x="302">يطلب الطفل المساعدة</tspan><tspan x="302" dy="14">ببطاقة أو طلب</tspan><tspan x="302" dy="14">أو إشارة.</tspan></text>
|
||||||
|
<text x="441" y="415"><tspan x="441">يستجيب البالغ بطريقة داعمة،</tspan><tspan x="441" dy="14">فيقدم المساعدة أو استراحة</tspan><tspan x="441" dy="14">مناسبة حسب الخطة.</tspan></text>
|
||||||
|
<text x="593" y="415"><tspan x="593">تُلبّى الحاجة ويستطيع الطفل</tspan><tspan x="593" dy="14">المتابعة أو العودة إلى المهمة</tspan><tspan x="593" dy="14">بدعم.</tspan></text>
|
||||||
|
</g>
|
||||||
|
<rect x="680" y="272" width="102" height="193" rx="12" fill="#e7f0e8" />
|
||||||
|
<g fill="#316b58" text-anchor="middle" direction="rtl">
|
||||||
|
<text x="731" y="301" font-size="14" font-weight="700">النتيجة</text>
|
||||||
|
<text x="731" y="350" font-size="9.5"><tspan x="731">يساعد السلوك البديل</tspan><tspan x="731" dy="14">على تلبية حاجة الطفل،</tspan><tspan x="731" dy="14">فيزداد احتمال استخدامه</tspan><tspan x="731" dy="14">مجددًا ويتقدم التعلّم.</tspan></text>
|
||||||
|
</g>
|
||||||
|
<rect x="136" y="476" width="558" height="50" rx="12" fill="#e5edf3" />
|
||||||
|
<g fill="#173b5b" text-anchor="middle" direction="rtl">
|
||||||
|
<text x="415" y="497" font-size="13" font-weight="700">التعزيز الفعّال يجعل استخدام المهارة البديلة مجديًا.</text>
|
||||||
|
<text x="415" y="516" font-size="10">عندما يُعزَّز السلوك البديل، يصبح الخيار الأسهل والأكثر فاعلية.</text>
|
||||||
|
</g>
|
||||||
|
<rect x="305" y="347" width="49" height="25" rx="2" fill="#fff" />
|
||||||
|
<text x="329" y="364" fill="#253238" font-size="8" text-anchor="middle" direction="rtl">مساعدة</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 79 KiB |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 64 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 51 KiB |
|
After Width: | Height: | Size: 37 KiB |
@@ -1,3 +0,0 @@
|
|||||||
User-agent: *
|
|
||||||
Allow: /
|
|
||||||
Sitemap: https://www.azinstitute4autism.com/sitemap.xml
|
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/aba-therapy</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/aba-therapy-intake-process</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/about</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/ar</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/ar/library</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/ar/library/aba-school-readiness-guide</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/ar/library/autism-self-advocacy-skills-aba</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/ar/library/behavior-management-functions-guide</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/ar/library/executive-functioning-skills-autism</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/ar/library/first-then-cards-autism-transitions</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/ar/library/positive-reinforcement-techniques</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/ar/library/proactive-reactive-aba-strategies-guide</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/autism-evaluations</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/careers</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/client-consultation</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/client-forms</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/contact</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/donate-autism-giveback</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/employee-portal</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/es</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/es/aba-therapy</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/es/aba-therapy-intake-process</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/es/autism-evaluations</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/es/client-consultation</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/es/contact</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/es/learner-social-club</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/es/library</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/es/library/aba-school-readiness-arizona</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/es/library/autism-evaluation-diagnosis-arizona-parent-guide</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/es/library/autism-evaluation-what-to-expect</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/es/library/autism-family-self-care-tips</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/es/library/autism-self-advocacy-skills-aba</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/es/library/emotional-regulation-aba</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/es/library/enhancing-generalization-skills</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/es/library/executive-functioning-skills-autism</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/es/library/first-then-cards-autism-transitions</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/es/library/parents-guide-to-autism-and-aba</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/es/library/positive-reinforcement-techniques</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/es/library/social-pragmatic-communication-autism</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/es/services</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/faqs</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/insurance</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/learner-social-club</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/aac-visual-supports-autism</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/aba-school-readiness-arizona</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/aba-school-readiness-guide</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/aba-therapy-benefits</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/aba-therapy-dtt-net-guide</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/aba-therapy-prompting-parenting-benefits</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/aba-therapy-summer-routine-tips</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/aba-toilet-training-child-autism</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/aia-world-autism-community-day-celebration</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/asd-sensory-friendly-recipe-thanksgiving-pumpkin-cake</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/asd-sensory-friendly-recipes-pancakes</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/autism-evaluation-diagnosis-arizona-parent-guide</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/autism-evaluation-what-to-expect</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/autism-fall-break-routine-tips-halloween-thanksgiving</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/autism-family-self-care-tips</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/autism-friendships-social-play-support</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/autism-self-advocacy-skills-aba</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/autism-therapy-rapport-strategies</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/behavior-management-functions-guide</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/behavior-modification-techniques-reinforcement-theory</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/communication-social-skills-autistic-children-guide</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/community-highlight-meet-rula-diab</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/critical-thinking-skills</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/early-signs-autism-by-age</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/emotional-regulation-aba</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/enhancing-generalization-skills</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/executive-functioning-skills-autism</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/first-then-cards-autism-transitions</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/heart-full-of-gratitude</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/individualized-aba-therapy</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/integrated-aba-model-announcement</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/managing-aggressive-behavior-outbursts</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/meet-rula-diab-bcba</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/new-aia-scottsdale-office</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/new-year-2024-autism-holiday-tips</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/new-year-goals-2023</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/november-2022-aia-update</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/parents-guide-to-autism-and-aba</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/play-leisure-skills</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/positive-reinforcement-techniques</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/proactive-reactive-aba-strategies-guide</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/reduce-behavior-management</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/repetitive-behavior</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/sensory-processing</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/social-pragmatic-communication-autism</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/library/understanding-autism-support</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/privacy-policy</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/referrals</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/schedule-consultation</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/services</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/team</loc></url>
|
|
||||||
<url><loc>https://www.azinstitute4autism.com/tour</loc></url>
|
|
||||||
</urlset>
|
|
||||||
@@ -0,0 +1,533 @@
|
|||||||
|
# AIA Astro Migration — Living Session Handoff
|
||||||
|
|
||||||
|
## Deployment and employee-portal release preparation — 2026-11-04
|
||||||
|
|
||||||
|
The clinical director has accepted the collected non-PHI employee portal views,
|
||||||
|
their interim shared-code presentation and the approved employee resources.
|
||||||
|
This supersedes earlier collection/content-acceptance tasks. Deployment,
|
||||||
|
filesystem permissions, protected-resource authorization, DNS and cutover remain
|
||||||
|
separate technical gates.
|
||||||
|
|
||||||
|
The site-side deployment workflow builds an indexing-enabled release with an
|
||||||
|
explicit non-public approved portal ciphertext input, validates the artifact and
|
||||||
|
Contabo-compatible manifest, uploads only commit-specific staging trees, then
|
||||||
|
uses `aia-website-release verify`, `sync-source`, and `promote`. It does not
|
||||||
|
rebuild NixOS or alter nginx. Employee documents are a separate owner-run,
|
||||||
|
hash-verified resource-installation operation into the VPS-owned protected
|
||||||
|
namespaces. See [the release runbook](../integrations/nixos/deploy.md).
|
||||||
|
|
||||||
|
The browser payload remains ciphertext only; codes, plaintext portal content,
|
||||||
|
private manifests and resources must never enter Git, `dist`, source snapshots,
|
||||||
|
logs or deployment manifests. `/employee-portal` remains noindex and excluded
|
||||||
|
from sitemap/hreflang. Form A, referral and publication behavior are unchanged.
|
||||||
|
|
||||||
|
### Portal resource preparation correction — 2026-11-04
|
||||||
|
|
||||||
|
The resource schema now separates approved source-to-role mapping from actual
|
||||||
|
VPS installation evidence. An approved mapping may be prepared and installed
|
||||||
|
while all server-installed/hash/permission/authentication/URL verification flags
|
||||||
|
remain false. Shared resources can be installed from one verified source into
|
||||||
|
both protected namespaces without weakening management isolation. The owner-only
|
||||||
|
private workflow identifies the two encrypted streams via hidden prompts,
|
||||||
|
derives deterministic role mappings, rewrites all legacy employee `/hubfs/`
|
||||||
|
links, and creates a hash-bound private readiness record. A real production
|
||||||
|
ciphertext cannot pass `npm run deploy -- --dry-run` merely because it is
|
||||||
|
structurally valid.
|
||||||
|
|
||||||
|
The first resource install no longer depends on a previously promoted site
|
||||||
|
release: the reviewed POSIX installer is staged from the exact Git commit and
|
||||||
|
verified by SHA-256 before root execution. Server installation, SOPS-backed
|
||||||
|
Basic Auth and protected URL verification remain future VPS-rehearsal gates.
|
||||||
|
|
||||||
|
## Current referral decision — 2026-11-01 (supersedes Form C planning)
|
||||||
|
|
||||||
|
The owner directs `/referrals` to retain the current public-site workflow: one
|
||||||
|
button-styled **Refer a Client** link to
|
||||||
|
[the existing hosted Jotform](https://form.jotform.com/231638510219149). There is **no separate Form C**
|
||||||
|
to create, embed, configure or launch. The former Form C / proposed two-form
|
||||||
|
architecture is historical only. `/referrals` renders no local form or Form A
|
||||||
|
iframe; the original 16 approved Form A placements remain unchanged.
|
||||||
|
|
||||||
|
This is authorization to restore the existing destination in Astro, **not**
|
||||||
|
verification of that separate legacy Jotform's HIPAA configuration, notification
|
||||||
|
recipients, patient-data handling, accessibility or continued operational
|
||||||
|
suitability. Review the actual hosted form and its clinical/privacy claims before
|
||||||
|
production cutover. No account modification or submission occurred in this PR.
|
||||||
|
|
||||||
|
|
||||||
|
**Last updated:** November 1, 2026 (UTC)
|
||||||
|
**Repository:** `AIAMarketing/azinstitute4autism.com`
|
||||||
|
**Working branch:** `faithful-astro-migration`
|
||||||
|
**Last pushed checkpoint:** `55adb797051473c3067a0d454515153237e9b8d6` — completion handling and portal styling. The new commit containing this handoff simplifies Form A to default-live without rewriting that history.
|
||||||
|
**Previous accepted checkpoint:** P9-03 documentation, signed `537f9864a0a3d0806180cbeca909bf1d03200c6f`
|
||||||
|
**Implementation checkpoint:** the commit containing this handoff update; obtain its actual SHA from Git history after the signed checkpoint is created.
|
||||||
|
**Next milestone:** continue Phase 9 owner decisions and authorized integration batches; then Phase 10 — Final QA/Cutover Readiness.
|
||||||
|
|
||||||
|
The landing-page migration is technically completed for checkpoint purposes.
|
||||||
|
Editorial, accessibility, stakeholder and production-release approval remain
|
||||||
|
separate. This handoff does not authorize deployment or integration activation.
|
||||||
|
|
||||||
|
## Current decision — 2026-10-30: default-live Form A
|
||||||
|
|
||||||
|
The owner intentionally supersedes the earlier isolated-test and seven-route
|
||||||
|
production-gate architecture. `npm run dev` and `npm run build` now enable Form A
|
||||||
|
on exactly **16 approved placements**, including the publicly reachable
|
||||||
|
`aia.web3app.dev` environment. No additional approval flags or access restriction
|
||||||
|
are required. `PUBLIC_AIA_FORMS_MODE` is optional: absent/empty means `live`;
|
||||||
|
explicit `off` and `mock` remain available. Invalid/obsolete `isolated-test`
|
||||||
|
settings produce an actionable configuration error. The former approval flags
|
||||||
|
and form environment role are retired, not renamed.
|
||||||
|
|
||||||
|
Indexing and forms are independent. Both publication modes emit ten immediate
|
||||||
|
frames (two contact, five landing, three consultation) and six deferred bilingual
|
||||||
|
service-drawer frames. The bounded registry fixes ID `262946078314059`, HTTPS
|
||||||
|
origin, context and language. Form B is retired; Form C is canceled by the November 1 referral decision.
|
||||||
|
|
||||||
|
Live drawers retain four-second/50%-scroll opening, shared 30-day suppression,
|
||||||
|
manual CTA override, deferred loading, verified completion acknowledgment for
|
||||||
|
five seconds, animated dismissal and fresh-form reopening. Off mode does not
|
||||||
|
automatically show inactive drawers. All iframe security/fallback behavior is
|
||||||
|
preserved. Employee-portal preview remains independently gated by explicit local
|
||||||
|
approval, valid private ciphertext input and non-indexing output; Form A cannot
|
||||||
|
authorize private content. No portal private resources enter normal artifacts.
|
||||||
|
|
||||||
|
This owner authorization does not modify Jotform, authorize site cutover or
|
||||||
|
complete pending consultation-language, provider-event, accessibility, runtime
|
||||||
|
telemetry/privacy, recipient-routing or hosting acceptance. See the
|
||||||
|
[current operating guide](../integrations/jotform/README.md) and
|
||||||
|
[implementation and validation report](phase-9-form-a-default-live-2026-10-30.md).
|
||||||
|
Earlier dated decisions and test results below are historical evidence, not
|
||||||
|
current environment setup instructions.
|
||||||
|
|
||||||
|
## Latest verified validation — 2026-10-30 default-live revision
|
||||||
|
|
||||||
|
206 tests pass; Astro check has zero diagnostics. Normal default-live staging:
|
||||||
|
128 routes, empty sitemap, zero hreflang, ten immediate plus six deferred Form A
|
||||||
|
frames. Indexing-enabled: 127 routes, 109 sitemap URLs, 180 hreflang links, the
|
||||||
|
same 16 placements. Explicit off/mock artifacts contain no real Form A frames.
|
||||||
|
Guarded browser regressions preserve drawer completion/suppression and portal
|
||||||
|
fixture behavior; 128/128 staging routes open. Link/image/blog audits have zero
|
||||||
|
findings. See the current default-live report for exact overlapping check counts,
|
||||||
|
network interception evidence and remaining owner acceptance. No deployment,
|
||||||
|
Jotform mutation or new real submission was performed.
|
||||||
|
|
||||||
|
## Authority and checkpoint history
|
||||||
|
|
||||||
|
Read repository-root `AGENTS.md`, `MIGRATION_BRIEF.md` and `AUTONOMOUS-CODEX.md`,
|
||||||
|
then this handoff and the relevant [migration summary](migration-summary.md).
|
||||||
|
Later Phase 6A ratification controls conflicting original recommendations.
|
||||||
|
|
||||||
|
- Phase 5C Team: `34d5394b3ce765028a27b9cddd9952de3f09bfe7`.
|
||||||
|
- Phase 6A proposal: `76a035424dc5245443476b168d8c91ea62eed27b`.
|
||||||
|
- Phase 6B.1 search: `b20c253383440598c2d07bf6f852906ac00c42df`.
|
||||||
|
- Phase 6B.2 pagination: `6f5ac3c0d233cee5fbbb62be79bc6909e6bec183`.
|
||||||
|
- Phase 6B.3 author archives: `8646792d46a8a117ef617f5dd2582c2550b45d19`.
|
||||||
|
- Phase 6B.4 URL/SEO: `8192ea71c47a7163b40a7fad144ebbd2523282d1`.
|
||||||
|
- Phase 6B.5 multilingual navigation/RTL: the signed replacement checkpoint
|
||||||
|
`a699d467f19fafbfdda5fce1ce6226baa6e5fc3c`; do not use its superseded unsigned SHA.
|
||||||
|
|
||||||
|
- Phase 6C Library/multilingual parity: signed checkpoint
|
||||||
|
`b5bc95bc2b8e36c58e8b4d8ab4b11391374a7883`.
|
||||||
|
|
||||||
|
- Phase 7 multilingual reconciliation: signed checkpoint
|
||||||
|
`8e64d322092b1fa6e0f648ddf26a665c80588198`.
|
||||||
|
|
||||||
|
- Phase 8 visual/accessibility implementation: signed checkpoint
|
||||||
|
`59911eb929579af7bcd6c42de6476128dab62289`.
|
||||||
|
- P9-03 Jotform contract and complete owner inventory: signed checkpoint
|
||||||
|
`537f9864a0a3d0806180cbeca909bf1d03200c6f`.
|
||||||
|
- Phase 9 landing-page integration: the commit containing this handoff update;
|
||||||
|
obtain its actual SHA from Git history. It does not resolve P9-01 through P9-10.
|
||||||
|
|
||||||
|
Phase 6B.5 visitor navigation remains independent of SEO hreflang. Published
|
||||||
|
locale destinations, explicit fallback notices, native language disclosure,
|
||||||
|
Arabic contact bidi isolation and the two-line shared address remain intact.
|
||||||
|
`/ar` remains unpublished with an explicit English-home fallback.
|
||||||
|
ContactObfuscation is unchanged; reversed no-JavaScript strings are intentional.
|
||||||
|
The earlier Phase 6B.5 manual acceptance does not cover subsequent Phase 6C work.
|
||||||
|
|
||||||
|
## Completed Phase 6C technical sequence
|
||||||
|
|
||||||
|
- **6C:** restored nine missing English articles and source-backed self-hosted
|
||||||
|
media; derived English Library and author page 6 from the catalog.
|
||||||
|
- **6C.1:** restored source-supported Halloween contextual links in English
|
||||||
|
self-advocacy and AAC articles.
|
||||||
|
- **6C.2:** reconciled three materially outdated English articles and current
|
||||||
|
published Spanish school readiness; replaced the obsolete Arabic
|
||||||
|
antecedent/consequence body with a complete translation; audited all 19
|
||||||
|
established translation relationships.
|
||||||
|
- **6C.3:** reconciled featured-image alternatives, source-supported headings,
|
||||||
|
truncated descriptions and supported modification dates; retained the new
|
||||||
|
Arabic guide's intentional modification-date omission; localized three diagrams.
|
||||||
|
- **6C.4:** reconciled contextual and external links, previous/next/related
|
||||||
|
relationships, image links and fragments; added localized self-advocacy
|
||||||
|
Halloween references while preserving the landing-page ownership gate.
|
||||||
|
- **6C.5:** audited all 74 articles, corrected narrow structural/accessibility
|
||||||
|
regressions, and verified metadata, links, FAQs, translation relationships,
|
||||||
|
pagination, search and publication policies. Technical readiness has
|
||||||
|
documented nontechnical release gates.
|
||||||
|
|
||||||
|
Detailed evidence and reviewer checklists are in the
|
||||||
|
[final acceptance report](phase-6c5-final-library-acceptance-2026-10-13.md).
|
||||||
|
The [checkpoint manifest](phase-6c5-checkpoint-manifest-2026-10-13.md) lists 148
|
||||||
|
implementation/evidence paths; that checkpoint included its handoff as path 149.
|
||||||
|
Historical phase records retain their original context.
|
||||||
|
|
||||||
|
## Completed Phase 7 technical sequence
|
||||||
|
|
||||||
|
- Recovered Spanish privacy policy with February 19, 2025 revision date,
|
||||||
|
localized metadata and reciprocal English/Spanish policy navigation.
|
||||||
|
- Localized actual Spanish form labels, options, instructions, disabled notices
|
||||||
|
and Contact map text using explicitly passed publication locale; no backend enabled.
|
||||||
|
- Translated the Spanish reinforcement tip without changing article identity,
|
||||||
|
dates or surrounding content; fluent/clinical approval remains pending.
|
||||||
|
- Localized Spanish/Arabic author headings and isolated Arabic BCBA/LBA text;
|
||||||
|
biographies, identities and archive SEO unchanged.
|
||||||
|
- Prepared the [nonproduction verification plan](phase-7-nonproduction-verification-plan-2026-10-14.md)
|
||||||
|
and [Phase 9 decision register](phase-9-decision-register-2026-10-14.md).
|
||||||
|
P9-01 through P9-10 all remain **Pending decision**.
|
||||||
|
|
||||||
|
See the [Phase 7 reconciliation report](phase-7-multilingual-reconciliation-2026-10-14.md)
|
||||||
|
and [checkpoint manifest](phase-7-checkpoint-manifest-2026-10-14.md).
|
||||||
|
The non-Library matrix excludes all three Library-root content records:
|
||||||
|
20 EN / 8 ES / 1 unpublished AR draft → 20 EN / 9 ES / 1 unpublished AR draft;
|
||||||
|
28 → 29 eligible pages and 8 → 9 English–Spanish pairs. The final matrix has
|
||||||
|
30 records including the draft. Whole pages-collection counts (including roots)
|
||||||
|
are 21/9/2 → 21/10/2, with 9 → 10 English–Spanish pairs. Do not mix populations.
|
||||||
|
|
||||||
|
## Completed Phase 8 technical sequence
|
||||||
|
|
||||||
|
- Static checks and guarded Chromium smoke covered all 122 generated routes.
|
||||||
|
The original browser pass captured 50 desktop/50 mobile full pages, checked
|
||||||
|
50 routes without JavaScript, and passed 40 focused interactions, with one
|
||||||
|
native-dialog review finding subsequently compared against a native control.
|
||||||
|
- Corrected prose/FAQ/contact/form link contrast and underlines, navigation,
|
||||||
|
language-menu, skip-link, byline and diagram focus treatments; fixed the
|
||||||
|
scoped homepage director-grid overflow at 320px.
|
||||||
|
- Localized Arabic article controls and bidi counts without changing the API
|
||||||
|
script. Corrected DTT/NET peer sections and consultation heading semantics
|
||||||
|
while preserving text, fragments and appearance. Native dialogs remain intact;
|
||||||
|
Chromium's browser-chrome boundary did not establish application focus escape.
|
||||||
|
- Corrected Phase 7 carryovers: Spanish HSA/FSA section after ESA/before financial
|
||||||
|
help, Spanish alternative text and APROBADO artwork; Spanish privacy's missing
|
||||||
|
information-collection H2 (eleven sections/four items), with no legal-text change.
|
||||||
|
The final Spanish badge preserves the original alpha and every pixel outside
|
||||||
|
its lettering rectangle; the English artwork is unchanged.
|
||||||
|
- Replaced flattened Tour Markdown with one MDX publication, structured nine-photo
|
||||||
|
data and accessible carousel: captions, thumbnails, wraparound, keyboard/focus,
|
||||||
|
restrained announcements, no auto-rotation, full no-JavaScript fallback and
|
||||||
|
restored consultation link. No new dependency or production integration.
|
||||||
|
- Bounded follow-up: 30 grouped Chromium checks. Consolidated pass: 21 grouped
|
||||||
|
checks, two contrast/reduced-motion probes, five distinct routes, 20 full-page
|
||||||
|
captures, native 200% zoom on Tour/privacy (26 overlapping frames), four crops.
|
||||||
|
Earlier follow-up also tested seven routes at native 200% zoom. Badge correction:
|
||||||
|
eight EN/ES checks/crops at 320/390/768/1440px. These are distinct evidence
|
||||||
|
populations, not additional unique-site-route totals.
|
||||||
|
- Loopback-only contexts allowed only local GET/HEAD, blocked external traffic,
|
||||||
|
WebSockets and website service workers. Map-resource attempts and a synthetic
|
||||||
|
fixture POST were prevented; no production API/like/form/conversion request
|
||||||
|
was transmitted. Disabled controls/noindex remain insufficient API isolation.
|
||||||
|
|
||||||
|
See [consolidated findings](phase-8-consolidated-followup-2026-10-15.md),
|
||||||
|
[browser results](phase-8-browser-verification-2026-10-15.md),
|
||||||
|
[badge correction evidence](phase-8-badge-correction-evidence-2026-10-15.json),
|
||||||
|
and the [Phase 8 checkpoint manifest and validation](phase-8-checkpoint-manifest-2026-10-15.md).
|
||||||
|
Historical failed browser attempts remain recorded. System Playwright 1.61.0 /
|
||||||
|
Chromium 151.0.7922.75 now work; the optional Nix browser-shell realization is
|
||||||
|
not independently verified. No real screen-reader session or owner sign-off occurred.
|
||||||
|
|
||||||
|
Tour's public source passed normal TLS but was cache-qualified. Spanish privacy's
|
||||||
|
capture used a certificate-insecure fallback after validation failed. Neither
|
||||||
|
establishes current origin freshness; Spanish policy additionally requires a
|
||||||
|
trusted-source comparison. No insecure retrieval was repeated.
|
||||||
|
|
||||||
|
## Completed Phase 9 landing-page integration
|
||||||
|
|
||||||
|
- Imported four independently styled campaign routes from the sibling landing-page
|
||||||
|
repository: `/lp/aba-therapy`, `/lp/aba-insurance`, `/lp/aba-ahcccs` and
|
||||||
|
`/lp/aba-private-pay`. Their local fonts, images, components, metadata and
|
||||||
|
source noindex policy are isolated from ordinary site pages.
|
||||||
|
- Migrated the branded public `/lp/early-intervention` route with its compact
|
||||||
|
header/footer, source section order, existing byte-identical local imagery and
|
||||||
|
cache-qualified source evidence. It is self-canonical and adds one sitemap URL.
|
||||||
|
- Omitted the sibling project's API, tracking, success-state and attribution
|
||||||
|
runtime. Normal staging and indexing artifacts keep all five lead panels inactive,
|
||||||
|
with no native POST, live Jotform or conversion behavior. The later seven-route
|
||||||
|
Form A isolated-test adapter is separately gated and remains outside those artifacts.
|
||||||
|
P9-01, P9-03, P9-05 and P9-07 remain open.
|
||||||
|
- Added `/lp` as a temporary staging/testing index linking the five pages. It is
|
||||||
|
always `noindex,nofollow`, sitemap/hreflang-excluded and omitted entirely when
|
||||||
|
`PUBLIC_ALLOW_INDEXING=true`. This build gate is not access control.
|
||||||
|
- Detailed evidence is in the
|
||||||
|
[integration report](phase-9-campaign-page-integration-2026-10-20.md),
|
||||||
|
[sanitized evidence JSON](phase-9-campaign-integration-evidence-2026-10-20.json),
|
||||||
|
[early-intervention source record](phase-9-early-intervention-source-2026-10-20.json)
|
||||||
|
and [final offline reconciliation](route-reconciliation-2026-10-20-offline-18-37-43-828Z.json).
|
||||||
|
Earlier October 20 reconciliations remain superseded local evidence outside
|
||||||
|
the checkpoint.
|
||||||
|
|
||||||
|
### Current two-form status — 2026-10-29
|
||||||
|
|
||||||
|
- Form A uses one 16-placement live registry: two contact, five landing, three standalone consultation and six EN/ES service drawers. Mode defaults to live; off/mock are explicit options. `/referrals` independently links to the owner-approved existing hosted Jotform; Form C creation is canceled. See the November 1 decision above.
|
||||||
|
- Owner-confirmed direct-Jotform evidence covers synthetic EN/ES submission, native thank-you, conditional email/language, generic no-answer/no-PDF staff notification, autoresponder delivery, corrected fixed Reply-To, no webhooks/integrations, privacy scope, recipient access and retention. The owner also reports successful Astro-iframe synthetic submission and confirmation on English contact, Spanish contact and one ABA landing placement; record the exact third route before release. Functional submission acceptance is complete only for those owner-reported samples. All-sixteen-route accessibility, runtime-network/telemetry, deployment and site-release acceptance remain open.
|
||||||
|
- The adapter retains fixed URLs, responsive fixed heights, `no-referrer`, `allow-forms allow-scripts allow-same-origin`, no helper script, and a hosted fallback that is hidden without space until a 15-second missing-load timeout. A frame load only clears that timeout; it does not prove cross-origin application health or accepted submission. The official Jotform resizing handler is conditionally acceptable pending separately authorized source, origin, privilege, Firefox and error-state verification; it is not implemented. Fixed heights remain current.
|
||||||
|
- No additional Form A approval/environment flags remain. Indexing does not authorize or disable forms. Marketing-only notification routing remains a pre-cutover operational check. Rollback requires explicit mode `off`, rebuild and artifact verification; merely removing the mode restores live. No Form C is needed. Counters, analytics and API forwarding remain inactive.
|
||||||
|
|
||||||
|
The indexing-enabled build has 127 HTML routes/canonicals and 109 sitemap URLs.
|
||||||
|
Normal staging has 128 `noindex,nofollow` pages because it also contains `/lp`;
|
||||||
|
its sitemap and hreflang are empty. Existing 180 hreflang links across 55 routes,
|
||||||
|
25 translation sets, 74 Library articles, nine author archives and nine redirect
|
||||||
|
definitions are unchanged. Guarded Chromium covered the four campaign routes at
|
||||||
|
320/390/768/1440px, the branded route at those widths plus no-JavaScript checks,
|
||||||
|
and `/lp` at 320/1440px. Real screen-reader, non-Chromium and authorized visual,
|
||||||
|
clinical, privacy and organizational acceptance remain pending.
|
||||||
|
|
||||||
|
## Verified technical baseline
|
||||||
|
|
||||||
|
| Metric | Result |
|
||||||
|
|---|---:|
|
||||||
|
| Library articles / locale search records | 55 EN / 12 ES / 7 AR = 74 |
|
||||||
|
| Indexing-enabled HTML routes / unique canonical targets | 127 / 127 |
|
||||||
|
| Normal staging HTML routes, including temporary `/lp` | 128 |
|
||||||
|
| Author archive routes | 9 |
|
||||||
|
| Indexing-enabled sitemap URLs | 109 |
|
||||||
|
| Hreflang links / participating routes | 180 / 55 |
|
||||||
|
| Validated page/article translation sets | 25 |
|
||||||
|
| Repository redirect definitions | 9, not activated on deployed hosts |
|
||||||
|
| Visible/schema-aligned FAQ answers / articles | 182 / 30 |
|
||||||
|
|
||||||
|
English Library and author pagination is `10/10/10/10/10/5`; Spanish is `10/2`,
|
||||||
|
Arabic is one seven-article root. Page 6 is derived, with no page 7 or page-one
|
||||||
|
HTML alias. Search remains locale-scoped, metadata-only and demand-loaded.
|
||||||
|
Publication ordering uses original dates, not modification dates. Existing
|
||||||
|
syndicated external-canonical/noindex exceptions remain unchanged.
|
||||||
|
|
||||||
|
Normal staging output is **128 `noindex,nofollow` HTML pages, an empty sitemap
|
||||||
|
and no hreflang**. Indexing-enabled validation is local only. No deployment,
|
||||||
|
redirect activation, form submission or production integration is authorized.
|
||||||
|
|
||||||
|
Final source-matching offline evidence is the
|
||||||
|
[October 20 reconciliation](route-reconciliation-2026-10-20-offline-18-37-43-828Z.json):
|
||||||
|
138 dispositions, 128 local generated routes, 70 reused historical production
|
||||||
|
requests and schema 2. Use this explicit evidence path for read-only checks.
|
||||||
|
Earlier Phase 8 and October 20 reports remain historical evidence, not the
|
||||||
|
current source fingerprint. No fresh production crawl was performed.
|
||||||
|
|
||||||
|
The historical Phase 6C.5 parity classifications were 10 confirmed, 58 with accepted intentional
|
||||||
|
deviations, one minor discrepancy, five requiring human review, zero material
|
||||||
|
discrepancies and zero insufficient-verification records against the selected
|
||||||
|
evidence. Findings rely on dated, sometimes cached/prerendered public HubSpot
|
||||||
|
representations; they do not establish independent current origin freshness.
|
||||||
|
The newer Arabic antecedent/consequence translation intentionally supersedes
|
||||||
|
its outdated public Arabic body. Machine-assisted work is not professional approval.
|
||||||
|
|
||||||
|
Phase 8 checkpoint preparation revalidation on October 15 passed sequentially
|
||||||
|
with `TMPDIR=/tmp`: Astro check (101 files, zero diagnostics), Markdown 20,
|
||||||
|
publication 33, SEO 35, **Library 53**, routes 10 and Phase 8 5 tests: **156 total**.
|
||||||
|
Both build modes and link/image/blog audits pass. The final normal staging build
|
||||||
|
and explicit offline consistency check retain the publication safeguards above.
|
||||||
|
Git identity/signing remains the user’s host-terminal responsibility.
|
||||||
|
|
||||||
|
## Outstanding Stakeholder Review and Production Release Gates
|
||||||
|
|
||||||
|
- **Clinical/organizational — AIA:** approve eligibility and program-specific
|
||||||
|
ranges against general ABA eligibility of **18 months through eight years**;
|
||||||
|
resolve the summer-routine age discrepancy. Review Preparatory Academy ages
|
||||||
|
2–6 and 1:2 delivery ratio, ABA versus education, Arizona educational guidance,
|
||||||
|
functional assessment, behavior intervention, reinforcement, extinction,
|
||||||
|
aggression, self-injury, safety, treatment/outcome claims and author roles,
|
||||||
|
credentials and biographies, including Arabic physician-like wording versus
|
||||||
|
English “clinician.” Source publication alone is not clinical approval.
|
||||||
|
- **Fluent Spanish/Arabic and clinical review:** revised Spanish school readiness,
|
||||||
|
rewritten Arabic antecedent/consequence guidance and terminology, all three
|
||||||
|
localized Arabic diagrams, localized self-advocacy Halloween additions,
|
||||||
|
operational labels and cross-language notices remain pending.
|
||||||
|
- **Spanish tip review:** Phase 7 corrected the English tip at
|
||||||
|
`/es/library/positive-reinforcement-techniques`. Its fluent-Spanish and
|
||||||
|
clinical/editorial acceptance remains open; historical Phase 6C findings remain intact.
|
||||||
|
- **Privacy/legal and trusted-source approval — P9-07:** both policy claims need
|
||||||
|
AIA privacy/legal approval. Spanish privacy was recovered from a cache-qualified
|
||||||
|
response after standard TLS certificate validation failed; fallback disabled
|
||||||
|
certificate verification. Matching captured text does not prove authenticated
|
||||||
|
origin fidelity. Before production, compare against a certificate-validated
|
||||||
|
source or owner-supplied authoritative export with provenance; no trusted
|
||||||
|
comparison is available yet. Fluent Spanish approval remains mandatory.
|
||||||
|
Do not repeat insecure retrieval or rewrite policies to hide this limitation.
|
||||||
|
- **Browser/accessibility:** guarded Chromium automation now covers desktop/mobile,
|
||||||
|
keyboard, no-JavaScript, RTL/diagram scrolling and actual 200% zoom. Authorized
|
||||||
|
visual/source-fidelity acceptance, non-Chromium coverage, native-dialog AT
|
||||||
|
behavior, Arabic visual-language acceptance and real screen-reader testing
|
||||||
|
remain pending. Earlier failed attempts remain historical; browser automation
|
||||||
|
and DOM inspection do not constitute reviewer or assistive-technology approval.
|
||||||
|
- **Spanish HSA/FSA financial claims:** fluent-Spanish and organizational/financial
|
||||||
|
review of wording, account use, pre-tax and tuition claims remains pending.
|
||||||
|
Localized artwork is not financial eligibility or reimbursement approval.
|
||||||
|
- **Landing-page integration — Phase 9 owner gate:** presentation for the four
|
||||||
|
campaign routes and `/lp/early-intervention` is now imported under explicit
|
||||||
|
owner authorization. The Library CTA remains provisionally
|
||||||
|
`/client-consultation`; its equivalence to `/lp/early-intervention`, campaign
|
||||||
|
routing, redirects and live form behavior are not approved. Do not activate
|
||||||
|
submissions or production redirects without separate authorization.
|
||||||
|
- **Employee portal — P9-02:** staff/management access separation, authentication,
|
||||||
|
authorization and employee/clinical data security remain unresolved; current
|
||||||
|
metadata-only route is not a completed portal. See the
|
||||||
|
[portal brief](employee-portal-migration-brief-2026-10-08.md).
|
||||||
|
- **Likes/views API — P9-04:** the uncommitted local implementation now defaults
|
||||||
|
to explicit fail-closed `off`, with deterministic local `mock` behavior and
|
||||||
|
no live adapter. A future live adapter still requires separate API-origin,
|
||||||
|
credential, cookie, consent and production-approval evidence.
|
||||||
|
- **Author SEO:** keep archives self-canonical, `noindex,follow` in indexing-enabled
|
||||||
|
builds, sitemap-excluded and hreflang-excluded. Changes require explicit approval.
|
||||||
|
- **Forms/privacy/analytics/advertising:** approve form destinations and submission
|
||||||
|
APIs, HIPAA/privacy safeguards, consent/analytics, Google Ads conversion tracking
|
||||||
|
and each production integration's activation. No new PHI flow is authorized.
|
||||||
|
- **Hosting/release:** separately verify Contabo/NixOS deployment assumptions,
|
||||||
|
HTTPS, canonical host, slashless URLs, query preservation, redirect targets and
|
||||||
|
loops, real 404 responses, asset delivery, sitemap/robots, reproducible deployment,
|
||||||
|
rollback and organizational release approval. The temporary Docker/nginx
|
||||||
|
trailing-slash HTTPS-to-HTTP-to-HTTPS chain remains explicitly deferred.
|
||||||
|
Static-build success does not verify these deployed behaviors.
|
||||||
|
|
||||||
|
## Uncommitted extended Phase 10 technical QA — 2026-10-22
|
||||||
|
|
||||||
|
The signed baseline remains `e874b26bb9dc24beb6bce2e83a10e7800e7e12b9` on
|
||||||
|
`faithful-astro-migration`; this section records uncommitted verification and
|
||||||
|
must not be treated as an accepted checkpoint. The local Phase 9 batches for
|
||||||
|
counter isolation, off/mock form infrastructure and Contabo release planning
|
||||||
|
were revalidated. Two bounded responsive defects were corrected: mobile
|
||||||
|
PageHero headings now fit their available width, and the Library two-column
|
||||||
|
grid allows its primary track to shrink at tablet width.
|
||||||
|
|
||||||
|
The final guarded Chromium pass opened 128/128 staging routes. The responsive
|
||||||
|
matrix passed 110/110 checks across 22 routes at 320/390/768/1024/1440px.
|
||||||
|
Four Leaflet GET requests were intercepted before transmission; no production
|
||||||
|
API, Jotform, Contabo form, analytics, advertising or WebSocket request was
|
||||||
|
transmitted. The normal staging artifact has 128 noindex,nofollow pages, an
|
||||||
|
empty sitemap and zero hreflang; the indexing artifact has 127 pages, 109
|
||||||
|
sitemap URLs and 180 hreflang links, with the temporary `/lp` review index
|
||||||
|
excluded.
|
||||||
|
|
||||||
|
New local verification tools and reports are described in the Phase 10 audit,
|
||||||
|
browser, release-rehearsal and technical-readiness reports. A loopback Node
|
||||||
|
release rehearsal passed atomic switch and rollback. nginx, Contabo topology,
|
||||||
|
real screen-reader, non-Chromium, fluent-language, clinical, privacy/legal and
|
||||||
|
all P9 owner decisions remain pending. No checkpoint SHA is assigned to this
|
||||||
|
uncommitted work; the next signed SHA must come from the user's Git history.
|
||||||
|
|
||||||
|
## Next: Phase 9 — Human-Decision Gates
|
||||||
|
|
||||||
|
Begin from the commit containing this handoff update; obtain its actual SHA from
|
||||||
|
Git history and verify branch, history and working tree. Review
|
||||||
|
[P9-01 through P9-10](phase-9-decision-register-2026-10-14.md)
|
||||||
|
and gather evidence/owner decisions before proposing bounded implementation:
|
||||||
|
landing-page ownership; portal security/access; forms/APIs; likes/views isolation;
|
||||||
|
analytics/consent/Ads; clinical/organizational claims; policy/legal/provenance;
|
||||||
|
author SEO; hosting/rollback; production authorization. All ten remain **Pending decision**.
|
||||||
|
Do not infer approval from a technically feasible option or this checkpoint.
|
||||||
|
|
||||||
|
Use the [nonproduction plan](phase-7-nonproduction-verification-plan-2026-10-14.md)
|
||||||
|
and [reviewer procedure](phase-8-host-browser-verification-2026-10-14.md) for remaining
|
||||||
|
human acceptance. No hosted preview before approved fail-closed integration
|
||||||
|
isolation. Phase 10 retains final QA, deployed routing/integration tests,
|
||||||
|
rollback rehearsal and cutover readiness. Neither phase is authorized for live
|
||||||
|
changes by this handoff. The user separately authorizes each implementation scope.
|
||||||
|
|
||||||
|
## Working protocol and protected local files
|
||||||
|
|
||||||
|
Preserve the Markdown-first manifest-driven architecture, explicit translation
|
||||||
|
relationships and ratified publication policies. Implement only authorized scope;
|
||||||
|
report evidence and structural diffs before checkpoint actions. Follow
|
||||||
|
`AUTONOMOUS-CODEX.md`; do not repair identity/signing or bypass sandbox restrictions.
|
||||||
|
|
||||||
|
Do not read, modify, move, delete, stage or checksum root `merge-plan.md`.
|
||||||
|
|
||||||
|
### Reconciliation archive — 2026-10-28
|
||||||
|
|
||||||
|
The owner explicitly superseded the former local-preservation instruction for
|
||||||
|
the seven untracked reconciliation artifacts below. They were all confirmed
|
||||||
|
untracked and moved, without overwrite, to the local archive outside this Git
|
||||||
|
repository:
|
||||||
|
|
||||||
|
`/home/alice/projects/wrk/aia/local-archives/azinstitute4autism-route-reconciliation-2026-10-28`
|
||||||
|
|
||||||
|
- `route-reconciliation-2026-10-11-offline.json`
|
||||||
|
- `route-reconciliation-2026-10-12-offline.json`
|
||||||
|
- `route-reconciliation-2026-10-13-offline.json`
|
||||||
|
- `route-reconciliation-2026-10-13-offline-06-16-06-857Z.json`
|
||||||
|
- `route-reconciliation-2026-10-20-offline.json`
|
||||||
|
- `route-reconciliation-2026-10-20-offline-18-04-39-776Z.json`
|
||||||
|
- `route-reconciliation-2026-10-22-offline.json`
|
||||||
|
|
||||||
|
They remain excluded from Git because they are superseded intermediate or
|
||||||
|
local-only evidence. Filename-reference review found historical report links
|
||||||
|
only; no runtime, test, build or audit dependency. The tracked final evidence
|
||||||
|
remains `route-reconciliation-2026-10-20-offline-18-37-43-828Z.json` and
|
||||||
|
`route-reconciliation-2026-10-22-offline-05-10-47-827Z.json`. Historical
|
||||||
|
reports may retain filename references as their contemporaneous record; no
|
||||||
|
active dependency remains unresolved. The four October 11–13 files were moved
|
||||||
|
under this explicit authorization without parsing or checksumming their
|
||||||
|
contents.
|
||||||
|
|
||||||
|
Exclude root `merge-plan.md` and temporary `.phase8-stage-paths.nul` as well.
|
||||||
|
The old `.phase7-stage-paths.nul` is absent; do not recreate it.
|
||||||
|
The staging aid is for the user's host terminal only; never stage it or use a
|
||||||
|
broad Git add. The actual future checkpoint SHA comes from Git after the user
|
||||||
|
signs; do not amend merely to insert it here.
|
||||||
|
|
||||||
|
## Consolidated service drawers and portal checkpoint, 2026-10-30
|
||||||
|
|
||||||
|
This section supersedes earlier explicit-only drawer behavior. The checkpoint
|
||||||
|
containing this update adds four-second/50%-scroll consultation opening, one
|
||||||
|
shared 30-day localStorage expiry preference, manual override through the six
|
||||||
|
existing EN/ES service CTAs, and typed bilingual service introductions. The
|
||||||
|
Academy configuration is prepared without a new page. The fixed seven production
|
||||||
|
and separate nine consultation-test route lists remain unchanged. Consultation
|
||||||
|
indexing approval must explicitly be `false`.
|
||||||
|
|
||||||
|
The employee route now has a locked, local-decryption UI and a private owner-run
|
||||||
|
collection/rewrite utility. Real passphrases were unavailable: real portal
|
||||||
|
content/resource inventory and collection remain blocked pending the owner-run
|
||||||
|
step. Do not claim approximately 43 resources as a measured inventory. Do not
|
||||||
|
commit the original source, ciphertext, decrypted views or private resources.
|
||||||
|
`www/private/employee-portal/` is ignored and outside Astro public output.
|
||||||
|
The accepted Jotform CSS backup and reconciliation archives are unchanged.
|
||||||
|
|
||||||
|
SOPS/age/sops-nix preparation is inactive, with no generated production identity,
|
||||||
|
recipient, deployed module or server-access activation. Portal browser encryption
|
||||||
|
remains access friction; internal resources require separate server-enforced
|
||||||
|
staff/management authorization. See
|
||||||
|
[consolidated implementation and validation](phase-9-service-portal-consolidated-2026-10-30.md)
|
||||||
|
and [owner utility instructions](../integrations/employee-portal/README.md).
|
||||||
|
The actual checkpoint SHA is the commit containing this section; obtain it from
|
||||||
|
Git history. No push, deployment or cutover is authorized by this work.
|
||||||
|
|
||||||
|
## Focused completion, portal styling and Spanish diagnostic — 2026-10-30
|
||||||
|
|
||||||
|
Authorized consultation drawers now accept only the documented
|
||||||
|
`submission-completed` / `formID` envelope from their activated iframe window
|
||||||
|
at the exact configured Jotform origin while the drawer is open. Object and
|
||||||
|
bounded JSON-string envelopes are supported; other actions/messages are ignored.
|
||||||
|
Completion writes the existing global 30-day expiry immediately, reveals EN/ES
|
||||||
|
acknowledgment, then starts slide-out after five seconds. Manual dismissal or
|
||||||
|
navigation cancels the countdown. Duplicate completion cannot restart it.
|
||||||
|
The next deliberate opening replaces the completed iframe; incomplete forms
|
||||||
|
remain intact across ordinary close/reopen. Load remains fallback-only, never
|
||||||
|
submission evidence. Real provider-message acceptance requires one owner-run
|
||||||
|
synthetic submission; automated tests use intercepted local fixtures only.
|
||||||
|
|
||||||
|
Portal presentation now restores scoped blue headings, spacing, directories,
|
||||||
|
orange report buttons and accessible contact accents without retaining arbitrary
|
||||||
|
classes, styles or scripts. Two synthetic encrypted views are verified. Private
|
||||||
|
source exposed no plaintext class/CSS semantics, and real view codes were not
|
||||||
|
available; exact legacy button recognition and visual parity require owner review.
|
||||||
|
No private content/resource or ciphertext was added to Git or public output.
|
||||||
|
|
||||||
|
The reported seven-option Spanish consultation dropdown is an unresolved
|
||||||
|
Jotform configuration issue: generated EN/ES URLs have identical form ID and
|
||||||
|
`formContext=consultation`, differing only in `language`. Astro neither supplies
|
||||||
|
nor edits child dropdown options. Owner should compare the direct hosted Spanish
|
||||||
|
form and review multilingual option translations/Update Options conditions.
|
||||||
|
No account changes or real submissions were performed. Seven production and
|
||||||
|
nine isolated-test placements remain unchanged; production consultation, portal
|
||||||
|
cutover and site cutover remain unauthorized. See the
|
||||||
|
[focused correction evidence](phase-9-drawer-portal-corrections-2026-10-30.md).
|
||||||
@@ -1,5 +1,16 @@
|
|||||||
# Accessibility Audit
|
# Accessibility Audit
|
||||||
|
|
||||||
|
**Checkpoint preparation — 2026-10-15:** The [exact checkpoint manifest](phase-8-checkpoint-manifest-2026-10-15.md)
|
||||||
|
records final revalidation (156 tests, including Library 53), current publication
|
||||||
|
metrics, preserved release gates and the source-matching **18:21** offline report.
|
||||||
|
The [badge correction](phase-8-badge-correction-evidence-2026-10-15.json) supersedes
|
||||||
|
the earlier white-background derivative and its captures/hash. Current Spanish
|
||||||
|
artwork preserves original geometry/alpha outside the APROBADO lettering.
|
||||||
|
Earlier browser failures, capture results and file counts below are dated history;
|
||||||
|
they are not the latest technical state. Checkpoint preparation is now authorized;
|
||||||
|
no staging, commit, production activation or human approval has occurred.
|
||||||
|
|
||||||
|
|
||||||
## Implemented
|
## Implemented
|
||||||
|
|
||||||
- Semantic header, navigation, main, article, section, and footer landmarks.
|
- Semantic header, navigation, main, article, section, and footer landmarks.
|
||||||
@@ -7,19 +18,285 @@
|
|||||||
- Language and direction attributes for English, Spanish, and Arabic.
|
- Language and direction attributes for English, Spanish, and Arabic.
|
||||||
- Native `details` elements for mobile navigation and FAQ accordions.
|
- Native `details` elements for mobile navigation and FAQ accordions.
|
||||||
- Form labels, autocomplete hints, disabled submission state, and explanatory text.
|
- Form labels, autocomplete hints, disabled submission state, and explanatory text.
|
||||||
|
- Service inquiry drawers use native modal dialogs with focus containment,
|
||||||
|
Escape, backdrop, and labeled close-button dismissal plus reduced-motion
|
||||||
|
support.
|
||||||
- Reduced decorative image announcements through empty alt text where appropriate.
|
- Reduced decorative image announcements through empty alt text where appropriate.
|
||||||
- Responsive typography and layouts without fixed text sizing.
|
- Responsive typography and layouts without fixed text sizing.
|
||||||
- Language-switcher choices are limited to routes that actually exist.
|
- Language-switcher choices are limited to routes that actually exist.
|
||||||
|
- The language selector uses native `details`/`summary` disclosure semantics and
|
||||||
|
real links. Visitor navigation is resolved independently from SEO hreflang,
|
||||||
|
so validated noindex author roots remain reachable without adding them to the
|
||||||
|
hreflang graph.
|
||||||
|
- Desktop, mobile, and footer navigation resolve against eligible generated
|
||||||
|
routes. Cross-language fallbacks are explicitly identified rather than
|
||||||
|
silently linking visitors to another language.
|
||||||
|
- Arabic footer phone, email, and Latin-script address values use narrowly
|
||||||
|
scoped left-to-right bidi isolation while the surrounding footer remains RTL.
|
||||||
- Like buttons expose pressed and disabled state.
|
- Like buttons expose pressed and disabled state.
|
||||||
- Source-faithful colors, section hierarchy, and controls were retained while
|
- Source-faithful colors, section hierarchy, and controls were retained while
|
||||||
avoiding the source site's modal that obscures content on initial load.
|
avoiding the source site's modal that obscures content on initial load.
|
||||||
|
|
||||||
## Manual Review
|
## Manual Review
|
||||||
|
|
||||||
- Review extracted image alt text; source content frequently omitted or duplicated alt text.
|
- Have fluent Spanish/Arabic reviewers assess the newly localized article hero
|
||||||
|
descriptions and Arabic diagram alternatives in their full article context.
|
||||||
- Test keyboard and screen-reader behavior across all migrated pages.
|
- Test keyboard and screen-reader behavior across all migrated pages.
|
||||||
- Perform contrast testing against final approved brand colors.
|
- Perform contrast testing against final approved brand colors.
|
||||||
- Review extracted article heading hierarchy and any table markup.
|
- Review extracted article heading hierarchy and any table markup.
|
||||||
- Confirm Arabic content and RTL reading order with a fluent reviewer.
|
- Confirm Arabic content and RTL reading order with a fluent reviewer.
|
||||||
|
- Review Spanish and Arabic operational labels and fallback-language notices
|
||||||
|
with fluent reviewers. Phase 7 localizes the existing Spanish and Arabic
|
||||||
|
author-archive labels; fluent review remains pending.
|
||||||
|
- Test the native language disclosure, mobile navigation, search announcements,
|
||||||
|
contact links, and full-page RTL reading order with screen readers. Phase
|
||||||
|
6B.5 validated generated markup and keyboard semantics, but no screen-reader
|
||||||
|
executable was available in the implementation environment.
|
||||||
- Validate the rebuilt mobile navigation and all full-page responsive
|
- Validate the rebuilt mobile navigation and all full-page responsive
|
||||||
layouts in a browser outside the autonomous sandbox.
|
layouts in a browser outside the autonomous sandbox.
|
||||||
|
## Phase 6C.3 article-image update — 2026-10-12
|
||||||
|
|
||||||
|
The current 74-article Library corpus was re-audited after the Phase 6C.2
|
||||||
|
rewrites. All 74 featured images are informative in their present article
|
||||||
|
context. The 60 records that still lacked frontmatter descriptions now have
|
||||||
|
concise, locale-appropriate alt text based on direct visual inspection and the
|
||||||
|
corresponding public-page evidence. No current featured image is treated as an
|
||||||
|
accidental empty-alt fallback; this is a decision about the audited corpus, not
|
||||||
|
a rule that future decorative images must have nonempty alt text.
|
||||||
|
|
||||||
|
The three English-text diagrams in the revised Arabic antecedent/consequence
|
||||||
|
article now use separate self-hosted Arabic SVG counterparts. Each preserves
|
||||||
|
the source raster and its relationships while replacing the visible labels
|
||||||
|
with Arabic. The article also retains adjacent Arabic prose and semantic tables
|
||||||
|
that communicate the same information without relying on the images. The
|
||||||
|
causal panel order remains left-to-right where reversing it could obscure the
|
||||||
|
sequence, while Arabic labels render right-to-left within their panels.
|
||||||
|
At narrow widths, each detailed diagram sits in a keyboard-focusable,
|
||||||
|
explicitly named horizontal scroll region with a visible focus outline. This
|
||||||
|
keeps its labels at a readable minimum width without introducing page-level
|
||||||
|
horizontal overflow.
|
||||||
|
|
||||||
|
Generated-markup checks cover featured-image alt propagation to the article,
|
||||||
|
Open Graph, and Twitter metadata; localized Arabic asset references; and the
|
||||||
|
absence of the English diagram references from the Arabic body. The SVGs were
|
||||||
|
rendered locally for visual inspection at their native dimensions. A browser
|
||||||
|
was not available for desktop/390-pixel overflow checks, and no screen-reader
|
||||||
|
or fluent-Arabic review was performed. Those checks, plus clinical review of
|
||||||
|
the translated ABA terminology and diagram relationships, remain required
|
||||||
|
before cutover.
|
||||||
|
|
||||||
|
## Phase 6C.4 article-link update — 2026-10-13
|
||||||
|
|
||||||
|
Generated-HTML checks now cover every Library body link's published destination,
|
||||||
|
asset, and fragment, plus the rendered previous/next/related links. Spanish and
|
||||||
|
Arabic self-advocacy articles identify their Halloween-guide destination as
|
||||||
|
English; the two new localized sentences still require fluent-language review.
|
||||||
|
|
||||||
|
The play/leisure article retains two native image links to the full-size,
|
||||||
|
self-hosted infographics. Duplicate expanded images and orphaned lightbox close
|
||||||
|
symbols were removed. The ABC-data preview links to the existing full-size
|
||||||
|
worksheet. These static anchors do not require JavaScript; this is markup
|
||||||
|
verification, not a completed keyboard or no-JavaScript browser session.
|
||||||
|
|
||||||
|
Local Chromium failed its sandbox socket check; remote Playwright could not
|
||||||
|
reach the generated site and subsequently closed its transport. Desktop/mobile
|
||||||
|
visual checks, focus, image opening and browser Back behavior remain manual
|
||||||
|
acceptance items. No screen-reader or fluent Arabic/Spanish acceptance is
|
||||||
|
claimed. The three Phase 6C.3 Arabic diagrams still need visual-language review.
|
||||||
|
|
||||||
|
## Phase 6C.5 final verification — 2026-10-13
|
||||||
|
|
||||||
|
All 74 featured images retain the individually reviewed alternatives from Phase
|
||||||
|
6C.3. Final generated-output inspection found and corrected two flattened
|
||||||
|
screening/evaluation/diagnosis tables (English and Spanish), ten toilet-training
|
||||||
|
H3 labels that had absorbed adjacent list prose, and the opening headings in the
|
||||||
|
English/Spanish social-communication articles that had absorbed a quoted
|
||||||
|
paragraph. Words, article dates and clinical guidance were not changed. The
|
||||||
|
play/leisure closing CTA is now outside its last FAQ, matching the public page;
|
||||||
|
all 182 FAQ answers across 30 articles match their visible content and schema.
|
||||||
|
|
||||||
|
Actual raster inspection of the three Arabic SVGs found two bounded visual
|
||||||
|
issues: a replacement-behavior subtitle extended beyond its colored panel, and
|
||||||
|
a few original English calm-corner title pixels appeared above the overlay.
|
||||||
|
The subtitle now wraps and the calm-corner overlay starts 10 pixels higher.
|
||||||
|
Reinspection shows no exposed English labels or clipped Arabic text in the
|
||||||
|
inspection rasters. The previews used installed DejaVu fonts and losslessly
|
||||||
|
decoded PNG backing in temporary files because this environment's librsvg did
|
||||||
|
not render the SVGs' embedded WebP directly. Production SVGs retain their source
|
||||||
|
WebP artwork. This is raster evidence, not browser/font-fallback acceptance.
|
||||||
|
|
||||||
|
All three diagram wrappers retain a named, focusable region, narrow-screen
|
||||||
|
horizontal scrolling, a 720-pixel minimum image width and focus-outline CSS.
|
||||||
|
Browser transport remains unavailable; real desktop/390px overflow, keyboard
|
||||||
|
scrolling, no-JavaScript interactions, screen-reader and fluent Arabic checks
|
||||||
|
remain **pending**. The source-inherited English tip in the Spanish
|
||||||
|
positive-reinforcement article also remains a bounded language-review item.
|
||||||
|
See the final Phase 6C.5 report for the route-specific checklist and release gates.
|
||||||
|
|
||||||
|
## Phase 7 shared locale update — 2026-10-14
|
||||||
|
|
||||||
|
Spanish Contact and consultation forms now receive the publication locale
|
||||||
|
explicitly and render Spanish labels, service choices, instructions, submit
|
||||||
|
text and disabled-submission notices. Contact map landmark/tile alternatives
|
||||||
|
and zoom titles are localized from server-provided data. Provider/library and
|
||||||
|
contact values are unchanged. Empty form actions and disabled buttons remain;
|
||||||
|
these checks do not prove full Enter-key, scripted or no-JavaScript isolation.
|
||||||
|
|
||||||
|
Spanish and Arabic author archive eyebrows and list headings are localized.
|
||||||
|
Arabic BCBA/LBA abbreviations receive LTR isolation without changing identity,
|
||||||
|
biography or archive SEO. The Spanish reinforcement tip is now fully Spanish,
|
||||||
|
superseding the minor language finding recorded in Phase 6C.5. New wording is
|
||||||
|
still pending fluent-language and clinical/editorial acceptance. The Arabic
|
||||||
|
biography's physician-like wording versus English “clinician” is separately
|
||||||
|
flagged for organizational and fluent review; it was not silently rewritten.
|
||||||
|
|
||||||
|
The recovered Spanish privacy page preserves all ten source sections with
|
||||||
|
semantic headings, localized metadata and existing contact obfuscation.
|
||||||
|
Generated HTML tests verify labels, one H1, language, disabled form state and
|
||||||
|
translation navigation. Playwright opened about:blank, but its transport
|
||||||
|
closed on the subsequent isolated-local-preview attempt. No site browser,
|
||||||
|
keyboard, mobile, no-JavaScript or real screen-reader acceptance is claimed.
|
||||||
|
See [Phase 7 verification plan](phase-7-nonproduction-verification-plan-2026-10-14.md)
|
||||||
|
for reviewer fields and the API-isolation prerequisite for hosted review.
|
||||||
|
|
||||||
|
## Phase 8 bounded verification — 2026-10-14
|
||||||
|
|
||||||
|
Generated-HTML smoke checks now cover all 122 eligible routes: zero hard-rule
|
||||||
|
failures, two source-inherited H1→H3 review warnings (DTT/NET and schedule
|
||||||
|
consultation). These custom Cheerio rules check basic semantics, labels, alt
|
||||||
|
presence, fragments, assets and diagram regions; they are not a WCAG audit.
|
||||||
|
|
||||||
|
Two authored contrast defects were corrected without changing content or tokens:
|
||||||
|
inline prose/source-FAQ links now use primary blue and persistent underlines;
|
||||||
|
navigation/language/byline/diagram focus outlines now use primary blue. On white
|
||||||
|
and tint backgrounds the foreground contrast is 9.89:1 / 8.89:1, replacing
|
||||||
|
orange text at 2.23:1 / 2.01:1 and focus outlines at 1.66:1 / 1.49:1. Three focused
|
||||||
|
regression tests pass. Actual cascade/background/focus-clipping review remains
|
||||||
|
pending; other colors and controls have not received a complete rendered audit.
|
||||||
|
|
||||||
|
Three unchanged Arabic diagrams were rasterized and inspected again: no exposed
|
||||||
|
English labels or clipped Arabic detected in this DejaVu/librsvg rendering.
|
||||||
|
This is not browser/font-fallback or fluent-language acceptance. The earlier
|
||||||
|
statement that wrappers prevent page overflow describes CSS intent; actual
|
||||||
|
390px containment and keyboard scrolling remain unverified.
|
||||||
|
|
||||||
|
Remote browser transport closed before loading the site; only a same-execution
|
||||||
|
loopback HTTP fetch succeeded. Zero actual browser routes/screenshots, keyboard,
|
||||||
|
no-JS or real screen-reader sessions are claimed. Contact's external-map failure
|
||||||
|
fallback and all timed dialogs require actual browser checks. See the
|
||||||
|
[Phase 8 report](phase-8-visual-accessibility-acceptance-2026-10-14.md) and
|
||||||
|
[isolated host procedure](phase-8-host-browser-verification-2026-10-14.md).
|
||||||
|
All stakeholder/Phase 9 gates remain open. Phase 8 is partially verified, not
|
||||||
|
accepted, and the living handoff has not advanced.
|
||||||
|
|
||||||
|
## Phase 8 actual Chromium verification — 2026-10-15
|
||||||
|
|
||||||
|
The preceding unavailable-browser status is superseded for the system Chromium
|
||||||
|
151.0.7922.75 / Playwright 1.61.0 combination. See the
|
||||||
|
[browser report](phase-8-browser-verification-2026-10-15.md) and
|
||||||
|
[machine-readable evidence](phase-8-browser-evidence-2026-10-15.json).
|
||||||
|
All 122 routes loaded; 50 representative routes have full-page 1440/390 captures
|
||||||
|
and no-JavaScript content observations. The final source received another
|
||||||
|
122-route desktop check. Forty focused interaction checks pass; one modal focus
|
||||||
|
boundary remains Review required. No production API attempt was observed;
|
||||||
|
external map resources were blocked before transmission.
|
||||||
|
|
||||||
|
Two further bounded defects were corrected: low-contrast skip/contact/form
|
||||||
|
notice links now use primary blue and underlines; the homepage director grid
|
||||||
|
now follows the existing ≤760px single-column rule. Its scoped desktop rule had
|
||||||
|
caused 382px document width at a 320px viewport. Both homepages now pass actual
|
||||||
|
320/390/768/1440 reflow checks. Four CSS regression tests pass; full test suites
|
||||||
|
total 151 passing. These findings do not certify the rest of the palette.
|
||||||
|
|
||||||
|
All three unchanged Arabic SVGs rendered with their embedded artwork in Chromium;
|
||||||
|
inspected desktop captures showed no exposed English labels or clipped Arabic.
|
||||||
|
Named focusable regions scroll with arrow keys at 390px without page overflow.
|
||||||
|
Fluent Arabic and clinical review remain mandatory. Chromium AX-tree inspection
|
||||||
|
confirms Spanish form names/disabled state and Arabic named regions, but also
|
||||||
|
exposes inherited English “Like this article” and “Similar Blog Posts” labels.
|
||||||
|
Shared localized labels require a bounded follow-up and fluent review.
|
||||||
|
|
||||||
|
The service drawer focuses its heading, closes with Escape and restores prior
|
||||||
|
focus. Forward Tab reaches the native browser-chrome/BODY boundary before
|
||||||
|
returning to dialog controls; no background control received focus. Visible
|
||||||
|
browser/AT review remains pending, not a strict containment pass. A synthetic
|
||||||
|
fixture's scripted form submission was intercepted, demonstrating that disabled
|
||||||
|
buttons do not alone isolate submissions. No real form/server POST occurred;
|
||||||
|
P9-03 still owns the integration/isolation decision.
|
||||||
|
|
||||||
|
The two inherited heading skips, actual 200% browser zoom, broader rendered
|
||||||
|
contrast, complete source-qualified visual comparison, controlled live-map
|
||||||
|
behavior and real screen-reader acceptance remain open. Computed text resizing
|
||||||
|
and AX inspection are supplementary evidence, not substitutes. No human
|
||||||
|
sign-offs were received. All P9 decisions and the living handoff remain unchanged.
|
||||||
|
|
||||||
|
## Phase 8 bounded follow-up — 2026-10-15
|
||||||
|
|
||||||
|
[Follow-up results](phase-8-browser-verification-2026-10-15.md#bounded-follow-up--2026-10-15)
|
||||||
|
supersede the specific unresolved technical findings above. Arabic article and
|
||||||
|
archive counters/footer controls now receive publication locale explicitly;
|
||||||
|
Arabic names/views/navigation/related labels and isolated counts render correctly.
|
||||||
|
English/Spanish labels and the entire likes/views API script remain unchanged.
|
||||||
|
Fluent Arabic review is still pending.
|
||||||
|
|
||||||
|
The DTT/NET article's three primary peer sections and consultation's “Start Here”
|
||||||
|
now use H2 semantics, with identical heading text, IDs, appearance and searchable
|
||||||
|
text. Inspection established peer-section relationships; a numerical skip alone
|
||||||
|
was not treated as a WCAG violation. All-route generated audit: 122 pass, zero
|
||||||
|
hard failures or heading-review warnings.
|
||||||
|
|
||||||
|
Read More/eyebrow and selected nav/related-link states now use readable existing
|
||||||
|
primary colors. Card-author focus outlines also meet light-surface contrast.
|
||||||
|
Contact/skip links and focus clearance were rechecked. Native dialog Tab and
|
||||||
|
Shift+Tab, entry, Escape, keyboard Close and return pass at desktop/mobile.
|
||||||
|
The BODY/documentFocus=false boundary matches a minimal native control, with
|
||||||
|
background inertness preserved; no custom trap or application change was needed.
|
||||||
|
|
||||||
|
Real native tab zoom 200% passes seven high-risk pages: 1440px browser window,
|
||||||
|
720 CSS-pixel viewport, DPR 2, no page overflow. Overlapping actual viewport
|
||||||
|
captures replace an unreliable fullPage zoom capture. Both homepages pass
|
||||||
|
320/390/768/1440 and unchanged Arabic diagrams scroll/render correctly. Thirty
|
||||||
|
focused browser checks and 154 regression tests pass. This is technical
|
||||||
|
checkpoint-review readiness, not a complete WCAG audit. Human visual, fluent,
|
||||||
|
clinical/privacy, real screen-reader and source-fidelity gates remain pending;
|
||||||
|
all Phase 9 decisions remain unchanged. No production requests or activation.
|
||||||
|
|
||||||
|
|
||||||
|
## Phase 8 consolidated accessibility follow-up — 2026-10-15
|
||||||
|
|
||||||
|
See the [complete consolidated report](phase-8-consolidated-followup-2026-10-15.md)
|
||||||
|
and [evidence](phase-8-consolidated-evidence-2026-10-15.json).
|
||||||
|
|
||||||
|
- Phase 7 localization carryover: Spanish homepage now includes the faithful
|
||||||
|
HSA/FSA translation once after ESA/before Financial Help, with a separate
|
||||||
|
APROBADO graphic and Spanish alt. English content/artwork unchanged.
|
||||||
|
- Phase 7 structural carryover: Spanish privacy now has eleven H2 sections;
|
||||||
|
Información que recopilamos introduces the four existing collection items.
|
||||||
|
Policy wording/date/contact/metadata unchanged. Historical cache/insecure-TLS
|
||||||
|
provenance and trusted-source/legal review remain unresolved.
|
||||||
|
- Phase 8 Tour defect: replace flattened duplicated gallery with one enhanced
|
||||||
|
nine-slide carousel, caption, wraparound controls, named keyboard-operable
|
||||||
|
thumbnails, focus, restrained live announcements and full no-JS fallback.
|
||||||
|
Source is TLS-validated HTTP 200 but October 3 cached/prerendered content,
|
||||||
|
observed October 15. No live-page scripts executed or fresh-origin claim.
|
||||||
|
- Preserve prior Arabic UI, headings, contrast, responsive and native-dialog
|
||||||
|
findings. No changes to likes/views script, forms, publication architecture,
|
||||||
|
dependencies, hosting, SESSION_HANDOFF or pending Phase 9 decisions.
|
||||||
|
- Pass: 156 regression tests; 21 targeted Chromium checks and two actual-style/
|
||||||
|
reduced-motion probes; 122 generated-route static checks; link/image/blog
|
||||||
|
audits and both builds. Native 200% zoom on Tour/privacy adds 26 overlapping
|
||||||
|
frames, alongside 20 full-page captures and four crops (all outside Git).
|
||||||
|
- Counts unchanged: 122 routes/canonicals, 108 sitemap, 180 hreflang/55 routes,
|
||||||
|
25 sets, 74 Library records, 55/12/7 search, nine archives/redirects,
|
||||||
|
182 Library FAQ answers on 30 articles. Final staging 122 noindex,nofollow,
|
||||||
|
empty sitemap, zero hreflang. Raw all-site FAQ population is separately 254/32.
|
||||||
|
- Final explicit source-matching offline artifact:
|
||||||
|
[17-41-40-404Z](route-reconciliation-2026-10-15-offline-17-41-40-404Z.json),
|
||||||
|
133 dispositions/70 reused requests. Read-only consistency check passed.
|
||||||
|
|
||||||
|
**PHASE 8 TECHNICALLY READY FOR CHECKPOINT REVIEW**, not accepted by stakeholders.
|
||||||
|
Fluent Spanish/Arabic, HSA financial claims, clinical/organizational review,
|
||||||
|
privacy/legal/trusted-source comparison, real screen reader, native-dialog AT,
|
||||||
|
Arabic diagrams, source-design and non-Chromium acceptance remain open.
|
||||||
|
P9-01 through P9-10 all Pending decision; Phase 10 cutover remains unauthorized.
|
||||||
|
No staging, commit, checkpoint preparation, deployment or integration activation.
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
# Blog Content Audit
|
# Blog Content Audit
|
||||||
|
|
||||||
Checked 65 blog post bodies for layout content duplicated in Markdown.
|
Checked 74 blog post bodies for layout content duplicated in Markdown.
|
||||||
Verified 125 FAQ questions across 19 FAQ-bearing posts.
|
Verified 182 FAQ questions across 30 FAQ-bearing posts.
|
||||||
Detected 32 source-faithful blog blockquotes.
|
Detected 58 source-faithful blog blockquotes.
|
||||||
|
|
||||||
No duplicated article headers or invalid MDX FAQ components were detected.
|
No duplicated article headers or invalid MDX FAQ components were detected.
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
# Cleanup Log
|
# Cleanup Log
|
||||||
|
|
||||||
- Replaced HubSpot-generated wrappers, inline styles, scripts, analytics, and modules with reusable Astro components.
|
- Replaced HubSpot-generated wrappers, inline styles, scripts, analytics, and modules with reusable Astro components.
|
||||||
- Preserved canonical clean URLs while excluding local mirror query-string and AMP duplicates.
|
- Preserved canonical clean URLs while excluding HubSpot query-string and AMP duplicates.
|
||||||
- Consolidated responsive `hs-fs` image variants to canonical `hubfs` assets where available.
|
- Consolidated responsive `hs-fs` image variants to canonical `hubfs` assets where available.
|
||||||
- Excluded mirrored HubSpot CSS and JavaScript from the new public asset package.
|
- Excluded HubSpot CSS and JavaScript from the new public asset package.
|
||||||
- Self-hosted canonical images, SVGs, fonts, and PDFs from the mirror.
|
- Self-hosted canonical images, SVGs, fonts, and PDFs where practical.
|
||||||
- Recreated navigation and footer from structured JSON.
|
- Recreated navigation and footer from structured JSON.
|
||||||
- Recreated visible contact and consultation forms as static accessible HTML.
|
- Recreated visible contact and consultation forms as static accessible HTML.
|
||||||
- Used the source palette: AIA blue `#254080`, dark blue, straw yellow, orange, and teal.
|
- Used the source palette: AIA blue `#254080`, dark blue, straw yellow, orange, and teal.
|
||||||
- Used the live site's locally mirrored Playfair Display headings, Rubik body copy, and Caveat accent font.
|
- Used self-hosted Playfair Display headings, Rubik body copy, and Caveat accent font.
|
||||||
- Added multilingual collection and route structure with Arabic RTL support.
|
- Added multilingual collection and route structure with Arabic RTL support.
|
||||||
- Kept all extracted source content editable as Markdown.
|
- Kept all extracted source content editable as Markdown.
|
||||||
- Replaced the initial generic rounded-card visual system with live-derived
|
- Replaced the initial generic rounded-card visual system with live-derived
|
||||||
@@ -21,21 +21,26 @@
|
|||||||
- Reorganized the homepage source into named `home:` frontmatter blocks so the
|
- Reorganized the homepage source into named `home:` frontmatter blocks so the
|
||||||
content is easier to inspect and edit without changing the rendered layout.
|
content is easier to inspect and edit without changing the rendered layout.
|
||||||
- Replaced the extracted linear team article with a dedicated live-derived team grid.
|
- Replaced the extracted linear team article with a dedicated live-derived team grid.
|
||||||
- Repaired mirror-rewritten PDF, lightbox, CTA, and relative content links.
|
- Repaired rewritten PDF, lightbox, CTA, and relative content links.
|
||||||
- Limited language-switcher choices to translations that have generated routes.
|
- Limited language-switcher choices to translations that have generated routes.
|
||||||
- Verified and implemented the current production likes/views API contract.
|
- Verified and implemented the current production likes/views API contract.
|
||||||
- Recovered 18 live page-banner assets that the wget mirror missed because
|
- Recovered 18 live page-banner assets that HubSpot injected through malformed
|
||||||
HubSpot injected them through malformed inline `background-image` styles.
|
inline `background-image` styles.
|
||||||
- Restored the live library banner and consultation form section background.
|
- Restored the live library banner and consultation form section background.
|
||||||
- Added a mapped-page-imagery audit to prevent missing visual assets from
|
- Added a mapped-page-imagery audit to prevent missing visual assets from
|
||||||
silently passing the source link audit.
|
silently passing the source link audit.
|
||||||
- Removed duplicated article titles, author/date blocks, and featured images
|
- Removed duplicated article titles, author/date blocks, and featured images
|
||||||
from all 65 blog Markdown bodies; these elements are rendered by the shared
|
from all 65 blog Markdown bodies; these elements are rendered by the shared
|
||||||
blog-post layout. Updated both extractors and added a blog-content audit to
|
blog-post layout. Added a blog-content audit to prevent recurrence.
|
||||||
prevent recurrence.
|
|
||||||
- Converted 19 FAQ-bearing blog posts to MDX and restored a reusable
|
- Converted 19 FAQ-bearing blog posts to MDX and restored a reusable
|
||||||
`FAQAccordion.astro` component that owns the live-style accordion and
|
`FAQAccordion.astro` component that owns the live-style accordion and
|
||||||
matching `FAQPage` JSON-LD.
|
matching `FAQPage` JSON-LD.
|
||||||
|
- Converted the insurance content entry to MDX so its prose, carrier data, and
|
||||||
|
FAQ data have one editable source; reduced `InsurancePage.astro` to a
|
||||||
|
presentation-only wrapper that renders the content slot.
|
||||||
|
- Reconstructed the giveback page's four live-derived content bands and
|
||||||
|
restored its Amazon wishlist and GivingFountain actions without carrying
|
||||||
|
over HubSpot layout wrappers.
|
||||||
- Restored 32 blockquotes across 15 English and Spanish blog posts, including
|
- Restored 32 blockquotes across 15 English and Spanish blog posts, including
|
||||||
source emphasis, links, and the self-hosted quote-mark decoration; fixed
|
source emphasis, links, and the self-hosted quote-mark decoration; fixed
|
||||||
fallback extraction to preserve them.
|
fallback extraction to preserve them.
|
||||||
|
|||||||
@@ -0,0 +1,178 @@
|
|||||||
|
# AIA employee portal — migration brief and decision record
|
||||||
|
|
||||||
|
**Recorded:** 2026-10-08
|
||||||
|
**Project:** HubSpot to Astro migration, branch `faithful-astro-migration`
|
||||||
|
**Status:** Requirements clarified; implementation architecture and launch authorization still pending
|
||||||
|
**Related milestone:** Phase 9 human-decision gate, with implementation and verification required before cutover
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
|
||||||
|
Preserve the existing staff-facing `/employee-portal` experience during the move
|
||||||
|
from HubSpot to Astro on the AIA Contabo VPS. This is a small internal resource,
|
||||||
|
**not** an ordinary public marketing page. The owner describes its intended
|
||||||
|
protection as low-security, but that description is not a determination that the
|
||||||
|
underlying staff data or linked forms are safe to publish.
|
||||||
|
|
||||||
|
The current user-supplied requirements supersede earlier audit uncertainty
|
||||||
|
about the purpose of this route. They do **not** authorize a new authentication
|
||||||
|
implementation or relaxation of security/privacy checks.
|
||||||
|
|
||||||
|
## Confirmed legacy behavior (owner-supplied)
|
||||||
|
|
||||||
|
- The HubSpot employee portal contains **staff contact information** and links
|
||||||
|
or access to **day-to-day clinical-operations forms**.
|
||||||
|
- It has **two shared-password access levels**: general staff and management.
|
||||||
|
Preserve the separation and the intended content available to each group.
|
||||||
|
- The password handling and content are supplied in JavaScript/HTML through
|
||||||
|
the HubSpot page's **footer HTML field**.
|
||||||
|
- The supplied script embeds two independent encrypted HTML streams in a JSON
|
||||||
|
script element. The implementation labels them
|
||||||
|
`AES-256-CBC+HMAC-SHA256`, with PBKDF2-HMAC-SHA256 (200,000 iterations) used to
|
||||||
|
derive separate encryption and MAC keys from the entered passphrase.
|
||||||
|
- On password submission, the browser tries each stream; a matching MAC is
|
||||||
|
checked before decryption. On success, the script replaces the password
|
||||||
|
form with the decrypted HTML. Incorrect passwords leave the form visible.
|
||||||
|
- Decryption happens **entirely in the browser**, without an authenticated
|
||||||
|
server-side session. The encrypted data is downloadable with the page and
|
||||||
|
can be subjected to **offline password guesses**.
|
||||||
|
|
||||||
|
The supplied excerpt shows the encryption/decryption logic and encrypted
|
||||||
|
payload, but not the decrypted staff/management HTML or every surrounding
|
||||||
|
page element. The inventory of individual contacts, form destinations,
|
||||||
|
permissions, and client-side behavior therefore still requires a separate
|
||||||
|
owner-approved inspection.
|
||||||
|
|
||||||
|
**Sensitive material deliberately omitted:** the actual passphrases, encrypted
|
||||||
|
payload, decrypted HTML, contacts, staff details, and form-specific data are
|
||||||
|
not included in this document or any proposed Git commit. Do not paste,
|
||||||
|
log, or commit them. Rotate the shared passphrases before any migration
|
||||||
|
cutover; supply replacement secrets through an approved private mechanism.
|
||||||
|
|
||||||
|
## Current Astro state (repository-verified 2026-10-08)
|
||||||
|
|
||||||
|
- `www/src/content/pages/en/employee-portal.md` defines the
|
||||||
|
`/employee-portal` page route with metadata only; it has no portal body.
|
||||||
|
- It is `draft: false` and `noindex: true`.
|
||||||
|
- Phase 3A deliberately preserves the accessible local route while excluding
|
||||||
|
it from the production-policy sitemap. The staging build remains globally
|
||||||
|
`noindex,nofollow`.
|
||||||
|
- The existing migration audit listed employee portal replacement/access as
|
||||||
|
a human-decision gate. This brief clarifies the requirements without
|
||||||
|
treating the empty Astro route as a completed migration.
|
||||||
|
|
||||||
|
References:
|
||||||
|
- `www/reports/migration-audit-2026-10-06.md`
|
||||||
|
- `www/reports/migration-summary.md`
|
||||||
|
- `www/reports/migration-conversation-2026-10-07.txt`
|
||||||
|
- `www/src/content/pages/en/employee-portal.md`
|
||||||
|
|
||||||
|
## Desired migration behavior
|
||||||
|
|
||||||
|
1. Preserve the public-facing **route** `/employee-portal`, but do not expose
|
||||||
|
internal content to unauthenticated visitors.
|
||||||
|
2. Preserve **general staff** and **management** content separation.
|
||||||
|
3. Preserve the practical staff workflow: contact lookup, form links, and
|
||||||
|
day-to-day usability, including mobile layout.
|
||||||
|
4. Maintain the established `noindex` and sitemap-exclusion policy. Do not
|
||||||
|
add a translation alternate for this noindex route.
|
||||||
|
5. Audit each form link, embedded form, external provider, and asset before
|
||||||
|
migration. Identify whether any workflow collects, displays, or transmits
|
||||||
|
patient data or other sensitive information. Do not assume an internal
|
||||||
|
form's data handling is safe merely because the portal is gated.
|
||||||
|
6. Do not enable third-party advertising or general-purpose analytics tags
|
||||||
|
within the protected portal without an approved privacy review.
|
||||||
|
7. Preserve existing functionality without prematurely creating a user-account
|
||||||
|
database, integrating a full identity provider, or changing clinical forms.
|
||||||
|
Any such change requires a separate owner decision.
|
||||||
|
|
||||||
|
## Authentication/hosting decision — NOT YET RESOLVED
|
||||||
|
|
||||||
|
Two approaches are plausible. Do not select one implicitly.
|
||||||
|
|
||||||
|
**A. Reproduce the existing browser-side encrypted-content model.**
|
||||||
|
This offers closer functional compatibility and may remain entirely static,
|
||||||
|
but it is **obfuscation/access friction rather than robust access control**:
|
||||||
|
all ciphertext is publicly downloadable and shared passphrases can be tested
|
||||||
|
offline. It offers no individual account revocation or reliable per-user audit
|
||||||
|
trail. Use only after explicit owner acceptance of these limitations and
|
||||||
|
review of all included content.
|
||||||
|
|
||||||
|
**B. Protect staff and management resources at the Contabo server/edge.**
|
||||||
|
For example, separate protected URL/resource areas with nginx or another
|
||||||
|
server-side access control, while keeping `/employee-portal` as the entry
|
||||||
|
point. This avoids distributing readable internal content as public HTML and
|
||||||
|
can separate the two groups, but requires a design for two access levels,
|
||||||
|
credential distribution/revocation, and hosting operations. A single
|
||||||
|
undifferentiated HTTP Basic Auth gate is **not by itself** sufficient to enforce
|
||||||
|
different staff and management permissions.
|
||||||
|
|
||||||
|
**Security boundary:** `noindex` and omission from the sitemap are SEO
|
||||||
|
directives, **not** access controls. If server-side protection is selected,
|
||||||
|
protected plaintext must not be shipped as publicly retrievable assets in the
|
||||||
|
Astro `dist/` tree, public Git repository, or an unguarded CDN. Do not embed
|
||||||
|
passwords in browser JavaScript, frontmatter, static environment variables, or
|
||||||
|
committed web-server config.
|
||||||
|
|
||||||
|
## Decisions to obtain before implementation
|
||||||
|
|
||||||
|
- Confirm the exact resources visible to **staff** versus **management**
|
||||||
|
without storing them in public migration documentation.
|
||||||
|
- Classify staff contact details, form links, linked systems, and any clinical
|
||||||
|
or patient-related content; decide what is allowed in an externally reachable
|
||||||
|
portal.
|
||||||
|
- Select browser-side compatibility or server-side Contabo protection (and
|
||||||
|
whether existing URL/layout behavior should be retained verbatim).
|
||||||
|
- Decide how replacement credentials will be generated, distributed, rotated,
|
||||||
|
and revoked. Avoid reusing the old shared passphrases.
|
||||||
|
- Approve which portal forms/links are maintained, replaced, removed, or
|
||||||
|
re-hosted. Check destination URLs and privacy implications.
|
||||||
|
- Name the approver for both access-level mapping and launch acceptance.
|
||||||
|
|
||||||
|
## Future implementation milestone (separate from Phase 3B)
|
||||||
|
|
||||||
|
1. Perform a **read-only inventory** of the existing decrypted staff and
|
||||||
|
management views through owner-authorized access; record only non-sensitive
|
||||||
|
structure, required features, and form destinations in public reports.
|
||||||
|
2. Obtain the decisions above. Produce a short design and threat/operational
|
||||||
|
tradeoff review before implementing anything.
|
||||||
|
3. Implement in a scoped, reviewable milestone. Preserve the route and
|
||||||
|
publication policy; do not alter other migration page families.
|
||||||
|
4. Validate the access boundary: unauthenticated users cannot read protected
|
||||||
|
content; staff cannot read management-only content; management can access
|
||||||
|
its intended resources. Check direct URLs, page assets, and caching.
|
||||||
|
5. Validate UI and operations: wrong credentials, successful access, refresh,
|
||||||
|
mobile layout, keyboard access, link destinations, and form workflows.
|
||||||
|
6. Check `noindex`, sitemap omission, no hreflang, and absence of unintended
|
||||||
|
tracking/PHI leakage. Conduct an authorized privacy/security review.
|
||||||
|
7. Keep rollback instructions and credential-rotation procedures alongside
|
||||||
|
the Contabo cutover checklist. Do not activate until separately approved.
|
||||||
|
|
||||||
|
## Scope note
|
||||||
|
|
||||||
|
This is **documentation only**. It must not change Phase 3A publication policy,
|
||||||
|
Phase 3B hreflang implementation, Astro routing, production access, forms,
|
||||||
|
analytics, or server configuration. It does not claim authentication,
|
||||||
|
HIPAA compliance, or release readiness.
|
||||||
|
|
||||||
|
## 2026-10-30 owner authorization and implementation addendum
|
||||||
|
|
||||||
|
The owner explicitly authorized the two-stream browser-encrypted compatibility
|
||||||
|
model for development, superseding the earlier implementation hold for that
|
||||||
|
bounded scope. Production authorization and server-side resource protection are
|
||||||
|
still unresolved. The new scoped EmployeePortal component preserves the existing
|
||||||
|
route/SEO policy, local password entry, HMAC verification before decryption,
|
||||||
|
locked/unavailable default and passive content rendering.
|
||||||
|
|
||||||
|
The read-only source is at
|
||||||
|
`/home/alice/projects/wrk/aia/local-archives/aia-employee-portal-hubspot-footer-source.txt`.
|
||||||
|
Its two-stream structure and algorithm were inspected without exposing ciphertext
|
||||||
|
or plaintext. Legitimate codes were not available to the agent. Real-view
|
||||||
|
fidelity and exact resource counts remain blocked, not accepted. No real document
|
||||||
|
was fetched or published. The owner-run migration utility performs private
|
||||||
|
collection and approved link rewriting/re-encryption; see
|
||||||
|
[private workflow instructions](../integrations/employee-portal/README.md).
|
||||||
|
|
||||||
|
SOPS/age/sops-nix templates are prepared but inactive. Encryption of deployment
|
||||||
|
secrets does not authorize public delivery of staff/management documents. The
|
||||||
|
[consolidated report](phase-9-service-portal-consolidated-2026-10-30.md) records
|
||||||
|
synthetic tests and the separate remaining owner/cutover gates.
|
||||||
@@ -0,0 +1,156 @@
|
|||||||
|
# Google Ads consultation-form conversion: Astro implementation handoff
|
||||||
|
|
||||||
|
**Recorded:** 2026-10-08
|
||||||
|
**Repository branch:** `faithful-astro-migration`
|
||||||
|
**Status:** **Configuration documented only. NOT approved for production installation or activation.**
|
||||||
|
|
||||||
|
This document preserves the conversion action configured in the AIA Google Ads
|
||||||
|
organization account for the future Astro consultation/ABA-therapy landing pages.
|
||||||
|
It is a handoff to the site-migration and landing-page implementation work, **not**
|
||||||
|
authorization to install advertising tags. Follow the repository's
|
||||||
|
`AGENTS.md`/form-implementation constraints. As of this document, existing
|
||||||
|
migration forms are intentionally static; do not silently wire them to a backend
|
||||||
|
or add tracking while working on the visual migration.
|
||||||
|
|
||||||
|
## Google Ads configuration (verified in account UI)
|
||||||
|
|
||||||
|
| Field | Value |
|
||||||
|
| --- | --- |
|
||||||
|
| Google Ads customer/account | `515-940-4739` |
|
||||||
|
| Conversion action | `AIA | Consultation Form Submitted` |
|
||||||
|
| Goal/category | `Submit lead form` |
|
||||||
|
| Source | Website, **manual event** |
|
||||||
|
| Optimization | Primary; account-default goal (alongside Phone call lead) |
|
||||||
|
| Value | USD $1, fixed nominal reporting value (not actual revenue) |
|
||||||
|
| Count | One conversion per ad interaction |
|
||||||
|
| Click-through conversion window | 90 days |
|
||||||
|
| Engaged-view / view-through windows | 3 days / 1 day |
|
||||||
|
| Attribution | Data-driven |
|
||||||
|
| Enhanced conversions | **Not configured; do not enable** |
|
||||||
|
| Google tag setup | Not installed/verified for this new account |
|
||||||
|
| Conversion type ID (Google Ads UI reference only) | `7830657062` |
|
||||||
|
|
||||||
|
**Identifiers copied from the Google Ads “See event snippet” dialog:**
|
||||||
|
|
||||||
|
- **Google Ads destination / tag ID:** `AW-18494479353`
|
||||||
|
- **Conversion label:** `MzxbCKaw-ZUdEPm37fJE`
|
||||||
|
- **`send_to` value:** `AW-18494479353/MzxbCKaw-ZUdEPm37fJE`
|
||||||
|
|
||||||
|
The event snippet displayed in Google Ads is:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!-- REFERENCE ONLY. DO NOT DEPLOY WITHOUT PRIVACY APPROVAL. -->
|
||||||
|
<script>
|
||||||
|
gtag('event', 'conversion', {
|
||||||
|
'send_to': 'AW-18494479353/MzxbCKaw-ZUdEPm37fJE'
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
The `AW-` destination ID and conversion label are **not secrets**. Their
|
||||||
|
publication in source documentation does not imply permission to transmit data
|
||||||
|
to Google.
|
||||||
|
|
||||||
|
## Intended conversion semantics
|
||||||
|
|
||||||
|
One conversion represents **one consultation/ABA-therapy inquiry whose form
|
||||||
|
submission is accepted successfully by the approved API**, not a page visit,
|
||||||
|
form start, validation attempt, button click, or failed request.
|
||||||
|
|
||||||
|
The Google Ads dialog offered `Page load` and `Click` snippet options. The
|
||||||
|
`Page load` option was used to **retrieve the event syntax**, not as a mandate
|
||||||
|
to fire on arbitrary page loads. For the Astro/API flow, **prefer triggering
|
||||||
|
explicitly after the API returns a verified success response**, provided the
|
||||||
|
privacy review has approved the entire data flow.
|
||||||
|
|
||||||
|
Avoid a generic `/thank-you` page-load conversion: direct visits, refreshes,
|
||||||
|
or failed/subsequently redirected submissions can create false conversions
|
||||||
|
unless access and deduplication are robustly controlled. If confirmation-page
|
||||||
|
measurement is selected later, document and test how successful submissions
|
||||||
|
are authenticated and repeated visits are prevented from counting again.
|
||||||
|
|
||||||
|
## Integration requirements — gated, not yet authorized
|
||||||
|
|
||||||
|
1. **Privacy/HIPAA and Google Ads policy approval comes first.** Review with
|
||||||
|
AIA's responsible privacy/compliance team whether any Google tag may load
|
||||||
|
on the relevant pages, including the confirmation page. A health-service URL
|
||||||
|
and request metadata can disclose sensitive context even when no form fields
|
||||||
|
are sent. Review URL/path/query string, referrer, IP/device information,
|
||||||
|
cookies, network requests, automatic collection, consent, and applicable
|
||||||
|
Google terms/policies. **No tag loading at all** until that review is
|
||||||
|
completed and explicitly approved; a nominally sanitized `gtag` event is
|
||||||
|
not itself evidence of HIPAA compliance.
|
||||||
|
2. **Keep enhanced conversions and customer-data features off.** Do not send
|
||||||
|
names, emails, phone numbers, diagnoses, dates of birth, form contents,
|
||||||
|
hashed identifiers, `user_data`, or any patient-related values to Google.
|
||||||
|
Do not import sensitive customer lists or enable remarketing/health-audience
|
||||||
|
personalization. Don't append PII/PHI to redirect URLs, analytics events,
|
||||||
|
or advertising parameters.
|
||||||
|
3. **Do not add the base Google tag globally** to `src/layouts` or shared
|
||||||
|
head scripts as part of the ordinary site migration. If approved, provide
|
||||||
|
the minimum audited, route-specific implementation with explicit policy
|
||||||
|
controls. The Google Ads event requires a correctly initialized Google tag
|
||||||
|
(or a separately approved GTM implementation); the event snippet alone
|
||||||
|
cannot measure a conversion.
|
||||||
|
4. **Fire only after confirmed API success.** Use the real form endpoint's
|
||||||
|
documented response contract, not a presumed HTTP 200 or a click handler.
|
||||||
|
Fail closed on network error, invalid/partial responses, validation failure,
|
||||||
|
or spam rejection. Guard against duplicate calls from double-clicks,
|
||||||
|
retries, navigation, and refreshes.
|
||||||
|
5. **Keep the event minimal.** Once explicitly approved and initialized, the
|
||||||
|
only required conversion-event field in the recorded snippet is `send_to`.
|
||||||
|
Do not add `value`, `currency`, `transaction_id`, URL parameters, or
|
||||||
|
custom data without separate measurement/privacy review.
|
||||||
|
6. **Test safely.** First unit/integration-test form-success logic using a
|
||||||
|
mocked `gtag` and synthetic submissions. Test zero events on errors and
|
||||||
|
exactly one on verified success; inspect final URLs and outgoing requests.
|
||||||
|
Any real Google-network testing is itself tag deployment and requires the
|
||||||
|
same privacy approval. Verify the event in Google Ads/Tag diagnostics after
|
||||||
|
approval and deployment.
|
||||||
|
7. **Release gate.** Do not enable the paused campaign until the landing pages
|
||||||
|
are production-ready, successful forms are verified end to end, conversion
|
||||||
|
measurement is tested and approved, the healthcare/call-asset terms issue is
|
||||||
|
resolved, and the advertising-policy review is complete.
|
||||||
|
|
||||||
|
### Illustrative invocation — not production-ready code
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// Documentation-only. Run ONLY inside a privacy-approved implementation,
|
||||||
|
// after the approved API's actual success condition has been verified and
|
||||||
|
// the approved Google tag is initialized. Add submission-level deduplication.
|
||||||
|
gtag('event', 'conversion', {
|
||||||
|
send_to: 'AW-18494479353/MzxbCKaw-ZUdEPm37fJE',
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
Do **not** paste that example into a generic `submit` event handler or a
|
||||||
|
shared page layout: doing so before the asynchronous API response succeeds
|
||||||
|
would count attempted or failed inquiries.
|
||||||
|
|
||||||
|
## Related campaign and implementation notes
|
||||||
|
|
||||||
|
- The Search campaign in Google Ads account `515-940-4739` is intended to
|
||||||
|
remain **paused** during the Astro/Contabo migration and privacy audit.
|
||||||
|
- The other account-default Primary goal is `Phone call lead`, presently an
|
||||||
|
`AI-qualified call leads` action with a 60-second qualifying duration and
|
||||||
|
`Count = One`. Its Call and Messaging Ads Terms/HIPAA-exclusion question
|
||||||
|
is a separate launch blocker.
|
||||||
|
- The standalone advertising landing pages and associated form API work may
|
||||||
|
have their own repository or implementation handoff. Reconcile this document
|
||||||
|
with that source before making changes; do not assume the migration repo's
|
||||||
|
static forms already implement those endpoints.
|
||||||
|
- For privacy, keep identifiers limited to the public Ads destination ID and
|
||||||
|
conversion label; **no API credentials, patient examples, or submitted lead
|
||||||
|
data belong in this documentation**.
|
||||||
|
|
||||||
|
## Implementation checklist
|
||||||
|
|
||||||
|
- [x] Create the Google Ads manual Website conversion action and record IDs.
|
||||||
|
- [x] Configure Primary, One, $1, data-driven attribution; enhanced conversions off.
|
||||||
|
- [ ] Approve the exact third-party tag/data-flow design through AIA privacy review.
|
||||||
|
- [ ] Confirm form API success contract and documented submission deduplication.
|
||||||
|
- [ ] Implement a strictly gated, audited event only on verified form success.
|
||||||
|
- [ ] Verify outgoing network payloads and URLs contain no sensitive information.
|
||||||
|
- [ ] Complete approved end-to-end tracking tests and inspect Google Ads diagnostics.
|
||||||
|
- [ ] Confirm Google call-assets terms/HIPAA exclusion and other launch gates.
|
||||||
|
- [ ] Unpause campaign only after written go-live approval.
|
||||||
@@ -0,0 +1,326 @@
|
|||||||
|
# Migration audit — accepted baseline and Phase 1 evidence
|
||||||
|
|
||||||
|
Report date: **2026-10-06**, as requested. Application baseline: commit
|
||||||
|
`147b55c586f1a176050551003af98903901833eb` on `faithful-astro-migration`.
|
||||||
|
|
||||||
|
## Evidence dates and interpretation
|
||||||
|
|
||||||
|
- **Inherited accepted findings:** the audit accepted in the migration planning
|
||||||
|
conversation. Its observations span October 5–6, 2026. The temporary JSON/HTML
|
||||||
|
did not retain exact request timestamps; these remain `null` in the durable
|
||||||
|
baseline. File modification times were not substituted for observation times.
|
||||||
|
- **Fresh verified observations:** the shell's UTC clock recorded production
|
||||||
|
requests on **2026-10-07, 00:56:33–00:57:25 UTC**. This differs from the report's
|
||||||
|
requested date and is intentionally not backdated.
|
||||||
|
- **Inferences and uncertainty:** route presence does not establish content,
|
||||||
|
visual, accessibility, or functional equivalence. Unrequested routes remain
|
||||||
|
HTTP-unverified. Sitemap `lastmod` is a discovery hint, not a verified edit date.
|
||||||
|
|
||||||
|
Durable evidence:
|
||||||
|
|
||||||
|
- [Accepted route baseline](route-baseline-2026-10-06.json): compact extraction of
|
||||||
|
the saved inventories and selected HTML metadata/link references; no HTML,
|
||||||
|
article bodies, form payloads, or scripts are committed.
|
||||||
|
- [Current route reconciliation](route-reconciliation-2026-10-07-offline.json):
|
||||||
|
fresh production observations reconciled with generated/local routes. Its
|
||||||
|
final derivation was validated offline; the original production request times
|
||||||
|
and complete request ledger are retained. `mode: offline-reconciliation` does
|
||||||
|
not mean the production observations were invented or newly requested offline.
|
||||||
|
- [Historical migration summary](migration-summary.md): preserved unchanged;
|
||||||
|
its earlier completion claims are not current acceptance evidence.
|
||||||
|
|
||||||
|
The `/tmp` paths recorded in baseline provenance are historical origins only.
|
||||||
|
The tool and offline checks do not depend on those files still existing.
|
||||||
|
|
||||||
|
## Executive summary
|
||||||
|
|
||||||
|
**Inherited finding:** this is a substantial, buildable full-site migration,
|
||||||
|
not a new scaffold. Most page families exist, but route coverage overstates
|
||||||
|
readiness. Rendering, factual content, conversion behavior, and SEO need work.
|
||||||
|
|
||||||
|
**Fresh route verification:** the core inventory is unchanged: 97 generated
|
||||||
|
HTML pages, 102 production sitemap URLs, and 92 overlapping routes. Ten
|
||||||
|
sitemap-listed pages are missing locally. Five generated routes are absent
|
||||||
|
from the production sitemap; four remain live and one is the `/ar` placeholder.
|
||||||
|
|
||||||
|
Phase 1 adds evidence and tooling only. It does not repair rendering, alter
|
||||||
|
content, activate forms, change indexing, or implement redirects.
|
||||||
|
|
||||||
|
## Last known project state
|
||||||
|
|
||||||
|
**Inherited, corroborated by unchanged HEAD:** initial migration work landed in
|
||||||
|
June 2026. The newest local English article publication date was June 1, 2026.
|
||||||
|
Subsequent work concentrated on fidelity, page-specific layouts, FAQ behavior,
|
||||||
|
static inquiry drawers, and authoring infrastructure. Astro upgrades occurred
|
||||||
|
in July. The final August 28 commits enabled Sätteri features, restored Giveback
|
||||||
|
layout, and included MDX routes in sitemap generation.
|
||||||
|
|
||||||
|
Phase 0 fetched both remotes successfully. The migration branch was ahead of
|
||||||
|
`origin/faithful-astro-migration` by 14 commits and its `github` counterpart by
|
||||||
|
16; no remote-only commits were found. Local `main` and the reference foundation
|
||||||
|
branch matched their corresponding remote branches. The pre-existing untracked
|
||||||
|
`merge-plan.md` remains separate, unapproved merger planning, not migration
|
||||||
|
implementation authority.
|
||||||
|
|
||||||
|
## Current architecture
|
||||||
|
|
||||||
|
**Inherited inspection:** Astro 7.1.5, TypeScript, npm, static output, Zod content
|
||||||
|
collections, Markdown/MDX, plain CSS, and self-hosted fonts remain a suitable
|
||||||
|
foundation. English/Spanish/Arabic routing and RTL support exist. Some page copy
|
||||||
|
is rendered from dedicated components rather than its Markdown record.
|
||||||
|
|
||||||
|
The source contains 21 English, nine Spanish, and two Arabic page records;
|
||||||
|
46 English, 12 Spanish, and seven Arabic posts; and one author record per
|
||||||
|
language. Assets comprise 172 image files, 20 font files, and two PDFs.
|
||||||
|
|
||||||
|
**Inherited blocker, deliberately unchanged:** directive parsing removes the
|
||||||
|
`:1` and `:2` portions of ordinary therapy ratios. The accepted audit reproduced
|
||||||
|
this despite a passing build. Phase 2 must inspect intentional directive use
|
||||||
|
before changing the parser and preserve explicit heading IDs.
|
||||||
|
|
||||||
|
## Migration coverage
|
||||||
|
|
||||||
|
| Area | Accepted assessment | Remaining work |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| Service/conversion pages | Implemented, materially stale in places | Ages, eligibility, program naming, CTA destinations, consultation/referral copy |
|
||||||
|
| Homepages | Substantial implementation | English HSA/FSA section and metadata; source-specific Spanish reconciliation |
|
||||||
|
| About, careers, intake, insurance | Sampled substantive copy appeared aligned | Full visual/functional acceptance remains incomplete |
|
||||||
|
| Team | Implemented but stale | Reconcile names, roles, ordering, images |
|
||||||
|
| Employee portal | Effectively an empty page body | Human decision on replacement/access behavior |
|
||||||
|
| Library | 65 local posts; partial index behavior | Nine missing English posts, rewritten articles, search, pagination, authors |
|
||||||
|
| Spanish | Partial page coverage; 12 Library routes | Privacy page, updated source-supported translations, human language review |
|
||||||
|
| Arabic | Seven Library posts plus index and homepage placeholder | RTL/content review; intended unpublished homepage policy not implemented |
|
||||||
|
| SEO | Shared metadata, organization schema, selected FAQs | Publication rules, canonicals, hreflang, article/FAQ schema, social gaps |
|
||||||
|
| Forms/integrations | Static forms; selected external dependencies | Explicit activation and ownership decisions before launch |
|
||||||
|
|
||||||
|
These are inherited content assessments. Phase 1's fresh requests recheck route
|
||||||
|
and selected metadata evidence, not every paragraph or page layout.
|
||||||
|
|
||||||
|
## Route reconciliation
|
||||||
|
|
||||||
|
| Measure | Accepted core count | Fresh result |
|
||||||
|
| --- | ---: | ---: |
|
||||||
|
| Generated HTML pages | 97 | 97 |
|
||||||
|
| Production sitemap URLs | 102 | 102 |
|
||||||
|
| Sitemap/local overlap | 92 | 92 |
|
||||||
|
| Sitemap URLs missing locally | 10 | 10 |
|
||||||
|
| Local generated routes absent from sitemap | 5 | 5 |
|
||||||
|
| Production sitemap additions/removals | — | 0 / 0 |
|
||||||
|
|
||||||
|
The final machine inventory has **129 normalized route keys**, including
|
||||||
|
aliases, utility/archive routes, and the local placeholder. This is not 129
|
||||||
|
verified production pages. `robots.txt` and `sitemap.xml` are recorded separately
|
||||||
|
as two generated utilities, not counted among the 97 HTML pages.
|
||||||
|
|
||||||
|
Ten sitemap-listed missing routes, all freshly verified HTTP 200:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/es/privacy-policy
|
||||||
|
/library/does-aba-therapy-replace-school
|
||||||
|
/library/autism-daily-living-skills-challenges
|
||||||
|
/library/how-many-hours-aba-child-need
|
||||||
|
/library/autism-after-school-meltdowns
|
||||||
|
/library/autism-back-to-school-transition
|
||||||
|
/library/autism-social-skills-by-age
|
||||||
|
/library/sleep-issues-autistic-children
|
||||||
|
/library/halloween-and-autism
|
||||||
|
/library/picky-eating-autism-parent-guide
|
||||||
|
```
|
||||||
|
|
||||||
|
Fresh checks preserve these sitemap-absent local routes as live:
|
||||||
|
|
||||||
|
- `/employee-portal`: HTTP 200.
|
||||||
|
- `/schedule-consultation`: HTTP 200, source `noindex`.
|
||||||
|
- `/library/community-highlight-meet-rula-diab`: HTTP 200, external canonical.
|
||||||
|
- `/library/new-aia-scottsdale-office`: HTTP 200, external canonical.
|
||||||
|
|
||||||
|
`/ar` remains HTTP 404 in production. Locally it is **generated, `draft:false`,
|
||||||
|
and identifiable as placeholder content**. Its intended nonpublication is an
|
||||||
|
accepted future policy, not current implemented behavior.
|
||||||
|
|
||||||
|
All three short aliases remain 301 redirects to their hyphenated service URLs:
|
||||||
|
`/aba`, `/autismevaluations`, and `/learnersocialclub`.
|
||||||
|
|
||||||
|
### Additional discoveries and checking-method differences
|
||||||
|
|
||||||
|
- Six author-pagination links were recovered from archived HTML beyond the
|
||||||
|
earlier narrative: English `/library/author/rula-diab/page/2` through `/6`, and
|
||||||
|
Spanish `/es/library/author/rula-diab/page/2`. They are historical discoveries,
|
||||||
|
not evidence of six new publications. All now return 200 in fresh checks.
|
||||||
|
- English Library pagination pages 3–6, previously only discovered, now return
|
||||||
|
200. Search, the campaign page, three author indexes, and both languages'
|
||||||
|
page-2 listings also remain verified live.
|
||||||
|
- Two links were first inventoried in the fresh pass:
|
||||||
|
`/library/page/1` and `/library/author/rula-diab/page/1`. They were discovered
|
||||||
|
during the final bounded pagination pass and were **not requested**. Do not
|
||||||
|
assume either is absent, a 200, or a redirect.
|
||||||
|
- `/es` returns 301 to `/es/` without redirect following. The original audit
|
||||||
|
followed redirects and recorded the final 200. This is a transport observation
|
||||||
|
difference, **not established evidence that production changed**. The tool
|
||||||
|
records the Location and does not compare unavailable redirect-body metadata
|
||||||
|
as if title/canonical fields had been deleted.
|
||||||
|
|
||||||
|
There are 21 verified HTTP-200 routes outside the sitemap, including the four
|
||||||
|
already represented locally. The route report distinguishes these from 59
|
||||||
|
overlapping sitemap-listed routes not individually HTTP-verified in this pass.
|
||||||
|
|
||||||
|
## Significant content changes preserved from the accepted audit
|
||||||
|
|
||||||
|
These findings remain historical evidence pending page-specific reconciliation:
|
||||||
|
|
||||||
|
1. [ABA](https://www.azinstitute4autism.com/aba-therapy) and
|
||||||
|
[referrals](https://www.azinstitute4autism.com/referrals) differed from local
|
||||||
|
ages/eligibility copy; the individual ABA program described 18 months–8 years.
|
||||||
|
2. English/Spanish [school readiness](https://www.azinstitute4autism.com/library/aba-school-readiness-arizona)
|
||||||
|
changed from academy promotion to a broader guide; the fall-break article
|
||||||
|
also changed materially.
|
||||||
|
3. The [English homepage](https://www.azinstitute4autism.com/) added HSA/FSA
|
||||||
|
information absent locally. That does not itself justify new JSON-LD.
|
||||||
|
4. The [team listing](https://www.azinstitute4autism.com/team) differed from
|
||||||
|
local names; website differences do not prove employment status.
|
||||||
|
5. Spanish privacy content and nine English articles were absent locally.
|
||||||
|
6. `/lp/early-intervention` existed with an API-backed form; its ownership remains
|
||||||
|
a separate decision from full-site migration.
|
||||||
|
|
||||||
|
## SEO / URL risks
|
||||||
|
|
||||||
|
**Inherited findings, not repaired:** syndicated articles self-canonicalize
|
||||||
|
locally despite external production canonicals; hreflang is absent; BlogPosting
|
||||||
|
and standalone FAQPage schema are missing; display H1 is conflated with SEO
|
||||||
|
title; publication exceptions are not modeled; and the separate sitemap
|
||||||
|
generator extracts canonical strings without adequate publication exclusions.
|
||||||
|
|
||||||
|
Global staging noindex currently protects all generated pages. Turning indexing
|
||||||
|
on would not implement the intended `/ar` or `/schedule-consultation` exceptions.
|
||||||
|
Archive/search routes lack implementations or explicit redirect dispositions.
|
||||||
|
Existing nginx rewrites are report artifacts, not deployed routing behavior.
|
||||||
|
|
||||||
|
The route audit does not enforce these future policies or label overlaps as
|
||||||
|
content-aligned. It records observed behavior for subsequent milestones.
|
||||||
|
|
||||||
|
## Forms / analytics / external integrations
|
||||||
|
|
||||||
|
**Inherited findings:** production uses Jotform, HubSpot forms, a campaign API,
|
||||||
|
Google Analytics/consent setup, and Ahrefs analytics. Astro has disabled static
|
||||||
|
forms, configurable counters, payment links, video, and Leaflet/OpenStreetMap.
|
||||||
|
Form and tracking parity is incomplete. No legal compliance conclusion is made.
|
||||||
|
|
||||||
|
Phase 1 used raw GET requests only. It did not execute production JavaScript,
|
||||||
|
submit forms, contact form/counter APIs, unlock the portal, or fetch external
|
||||||
|
canonical publishers. Same-origin GET form actions were recorded as discovery
|
||||||
|
references (for example `/search`); no field values were submitted.
|
||||||
|
|
||||||
|
## Technical debt, sequence, and human gates
|
||||||
|
|
||||||
|
Keep the existing foundation. Resume through individually reviewed milestones:
|
||||||
|
Markdown rendering; route/publication policy; genuine translation relationships;
|
||||||
|
display/social/article/FAQ metadata; high-impact service and homepage facts;
|
||||||
|
Library capability design and content batches; source-supported multilingual
|
||||||
|
work; detailed visual/accessibility QA; and eventual cutover preparation.
|
||||||
|
|
||||||
|
Library search, pagination, and author routes are required capabilities. Inspect
|
||||||
|
the Astro architecture before selecting search technology; do not copy HubSpot
|
||||||
|
implementation details by default. Correct material service facts before
|
||||||
|
extensive pixel-level matching. Substantive translation changes finish ready
|
||||||
|
for human language review, not self-approved fluency.
|
||||||
|
|
||||||
|
Human decisions remain required for employee access, campaign ownership,
|
||||||
|
production form activation, analytics/consent architecture, and conflicting
|
||||||
|
public eligibility claims. None is authorized as implementation by this report.
|
||||||
|
|
||||||
|
## Reproducing the route reconciliation
|
||||||
|
|
||||||
|
Run from `www/`, using the already installed project dependencies:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm run build
|
||||||
|
npm run test:routes
|
||||||
|
npm run audit:routes
|
||||||
|
npm run audit:routes -- --check
|
||||||
|
```
|
||||||
|
|
||||||
|
- `audit:routes` requires existing build output. It reads source page/post
|
||||||
|
records and generated HTML; discovers through robots.txt, sitemap(s), five
|
||||||
|
locale/index seeds, links, and targeted checks; then writes a new dated JSON.
|
||||||
|
- It uses sequential same-origin GET requests, at least 750 ms between starts
|
||||||
|
(or the applicable robots crawl-delay), 15-second timeouts, ten sitemap and
|
||||||
|
80-request limits. It records redirects without following them and stops
|
||||||
|
network work on 429, 5xx, or a network failure. Incomplete discovery exits
|
||||||
|
nonzero with evidence where available; inability to establish robots policy
|
||||||
|
stops before page discovery.
|
||||||
|
- Known tracking parameters and trailing slashes are normalized. Unknown and
|
||||||
|
semantic query parameters, their ordering, and fragments are preserved.
|
||||||
|
Fragment references share one HTTP route and are not fetched separately.
|
||||||
|
Arbitrary query variants are not automatically crawled.
|
||||||
|
- Only 404/410 establish verified absence. Sitemap omission, redirects, blocked
|
||||||
|
requests, and network failures never do. Locale and canonical come from HTML
|
||||||
|
where actually inspected; unrequested metadata is not invented.
|
||||||
|
- Normalized route rows retain local counterparts, discovery sources/times,
|
||||||
|
request statuses/times, metadata where collected, and a route-level
|
||||||
|
disposition. The request ledger separately dates each discovery document.
|
||||||
|
- Subsequent runs create new files; they do not overwrite the accepted baseline
|
||||||
|
or prior snapshots. Baseline hashes protect the inherited evidence identity.
|
||||||
|
|
||||||
|
Offline validation of this exact snapshot, with no network or writes:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm run audit:routes -- --check --evidence reports/route-reconciliation-2026-10-07-offline.json
|
||||||
|
```
|
||||||
|
|
||||||
|
After intentional local changes, rebuild and reconcile against the same saved
|
||||||
|
production evidence without making production requests:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm run build
|
||||||
|
npm run audit:routes -- --offline --evidence reports/route-reconciliation-2026-10-07-offline.json
|
||||||
|
npm run audit:routes -- --check
|
||||||
|
```
|
||||||
|
|
||||||
|
`--check` defaults to the snapshot with the latest `generatedAt`. It verifies
|
||||||
|
the application source/asset fingerprint and recomputes route rows, totals, and
|
||||||
|
baseline comparisons. It fails on mismatches or saved discovery warnings. It
|
||||||
|
does **not** certify that production has remained unchanged since observation.
|
||||||
|
Build before capture when application files changed: the tool requires `dist`
|
||||||
|
but cannot prove that an arbitrary pre-existing build was produced from the
|
||||||
|
current source. Application fingerprints exclude this audit tooling and reports.
|
||||||
|
|
||||||
|
## Phase 1 validation and remaining uncertainty
|
||||||
|
|
||||||
|
- Focused offline tests cover normalization, meaningful queries/fragments,
|
||||||
|
deduplication, classification, placeholders, redirects, external canonicals,
|
||||||
|
inherited comparisons, and robots handling.
|
||||||
|
- Fresh discovery performed 70 requests: one robots, one sitemap, 68 pages.
|
||||||
|
Responses: 65 HTTP 200, four 301, one 404. No failures or discovery warnings.
|
||||||
|
One additional preflight `robots.txt` GET preceded the tool run and is not
|
||||||
|
counted in its request ledger; no other production requests were made in Phase 1.
|
||||||
|
- The sitemap membership and ten missing content routes match the accepted
|
||||||
|
baseline. Known gaps remain findings; they do not make a consistent inventory
|
||||||
|
fail its offline check.
|
||||||
|
- Per-page content/layout parity, full accessibility testing, linguistic review,
|
||||||
|
external integrations, and the two newly discovered `/page/1` behaviors remain
|
||||||
|
outside this milestone's verification.
|
||||||
|
- `npm run test:routes`: **9/9 passed**, entirely offline.
|
||||||
|
- `npm run audit:routes`: **passed**, with the fresh observations above.
|
||||||
|
- `npm run audit:routes -- --offline --evidence ...`: **passed**, retaining the
|
||||||
|
same production observations while validating final comparison logic. The
|
||||||
|
superseded preliminary generated artifact was not retained in the repository.
|
||||||
|
- `npm run audit:routes -- --check`: **passed** against the final saved snapshot,
|
||||||
|
including after the final build; no network requests or file writes.
|
||||||
|
- `npm run build`: **passed**, 97 pages, zero errors/warnings/hints.
|
||||||
|
- `npm run audit:links`: **passed**, zero broken internal links; the existing
|
||||||
|
broken-links report remained byte-for-byte unchanged.
|
||||||
|
- `git diff --check`: **passed**. Application source, assets, Astro configuration,
|
||||||
|
dependency declarations, lockfile, and existing migration reports are unchanged.
|
||||||
|
The package manifest adds only the two audit/test commands.
|
||||||
|
- All 97 generated pages retain the saved baseline titles, descriptions,
|
||||||
|
canonicals, headings, JSON-LD, and main-content text after normalizing existing
|
||||||
|
randomly generated contact-obfuscation IDs. Whole-output hashes differ because
|
||||||
|
`ContactObfuscation.astro` already uses `Math.random()` for those IDs; byte
|
||||||
|
identity is not claimed. No application behavior change was introduced.
|
||||||
|
- `merge-plan.md` remains untracked and unchanged. Before/after SHA-256:
|
||||||
|
`015db80cdbaf7d68799265d2070db760155c342b432ce6795f17ebc2218c641c`.
|
||||||
|
|
||||||
|
**Recommendation:** Phase 2 is the next useful milestone, subject to approval.
|
||||||
|
The ratio defect remains unchanged. Search the complete Markdown/MDX corpus and
|
||||||
|
directive consumers before altering parsing; retain explicit heading IDs and
|
||||||
|
add rendered Markdown/MDX regression coverage. No Phase 2 work was performed.
|
||||||
@@ -1,3 +1,77 @@
|
|||||||
|
## Include these directives inside the public HTTPS server block, before the
|
||||||
|
## generic static `location /` handler. Root (`/`) is the only trailing-slash
|
||||||
|
## public URL; every other terminal slash receives a query-preserving 308.
|
||||||
|
location ~ ^(.+?)/+$ {
|
||||||
|
return 308 $1$is_args$args;
|
||||||
|
}
|
||||||
|
|
||||||
|
## The static handler must serve the generated directory artifact at its
|
||||||
|
## slashless public path. Do not use `$uri/`, which permits nginx's automatic
|
||||||
|
## directory-slash redirect before `$uri/index.html` can be served.
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/index.html $uri.html =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
## HubSpot redirect export imported from repository-root `url-redirects.csv`
|
||||||
|
## on 2026-11-01. The export contains 45 STANDARD 301 rules. The three aliases
|
||||||
|
## already generated below (`/aba`, `/autismevaluations`, and
|
||||||
|
## `/learnersocialclub`) are intentionally not duplicated here.
|
||||||
|
##
|
||||||
|
## The IndexNow verification-file redirect retains HubSpot's original external
|
||||||
|
## target. Before cutover, confirm that target remains reachable after this
|
||||||
|
## hostname points at nginx; serving the required verification file locally may
|
||||||
|
## be necessary instead.
|
||||||
|
rewrite ^/abaportal$ /employee-portal permanent;
|
||||||
|
rewrite ^/aiaportal$ /employee-portal permanent;
|
||||||
|
rewrite ^/giveback$ /donate-autism-giveback permanent;
|
||||||
|
rewrite ^/blog$ /library permanent;
|
||||||
|
rewrite ^/donate$ /donate-autism-giveback permanent;
|
||||||
|
rewrite ^/contactus$ /contact permanent;
|
||||||
|
rewrite ^/post/4waysonhowtoreducebehaviormanagement$ /library/reduce-behavior-management permanent;
|
||||||
|
rewrite ^/post/playandleisureskillsforchildrenwithautism$ /library/play-leisure-skills permanent;
|
||||||
|
rewrite ^/post/managing-aggressive-behavior-outbursts-and-proper-communication-with-your-child-during-those-moments$ /library/managing-aggressive-behavior-outbursts permanent;
|
||||||
|
rewrite ^/post/critical-thinking-skills-for-children-with-autism$ /library/critical-thinking-skills permanent;
|
||||||
|
rewrite ^/post/new-year-goals-for-our-children-with-autism$ /library/new-year-goals-2023 permanent;
|
||||||
|
rewrite ^/post/aia-world-autism-month-celebration$ /library/aia-world-autism-community-day-celebration permanent;
|
||||||
|
rewrite ^/forms$ /client-forms permanent;
|
||||||
|
rewrite ^/post/november-aia-update$ /library/november-2022-aia-update permanent;
|
||||||
|
rewrite ^/post/behavior-modification-techniques-reinforcement-theory$ /library/behavior-modification-techniques-reinforcement-theory permanent;
|
||||||
|
rewrite ^/post/navigating-the-autism-journey-understanding-and-supporting-our-children-with-autism$ /library/understanding-autism-support permanent;
|
||||||
|
rewrite ^/post/arizona-institute-for-autism-is-thrilled-to-announce-its-transformation-into-an-integrated-aba-model$ /library/integrated-aba-model-announcement permanent;
|
||||||
|
rewrite ^/post/repetitive-behaviors-with-children-diagnosed-with-autism$ /library/repetitive-behavior permanent;
|
||||||
|
rewrite ^/post/asd-sensory-friendly-thanksgiving-recipe$ /library/asd-sensory-friendly-recipe-thanksgiving-pumpkin-cake permanent;
|
||||||
|
rewrite ^/post/toilet-training-for-a-child-with-autism-using-applied-behavior-analysis-aba$ /library/aba-toilet-training-child-autism permanent;
|
||||||
|
rewrite ^/post/new-year-2024-holiday-and-autism$ /library/new-year-2024-autism-holiday-tips permanent;
|
||||||
|
rewrite ^/post/understanding-sensory-processing-in-the-context-of-aba-therapy$ /library/sensory-processing permanent;
|
||||||
|
rewrite ^/post/enhancing-generalization-for-broader-impact$ /library/enhancing-generalization-skills permanent;
|
||||||
|
rewrite ^/post/asd-sensory-friendly-recipes-pancakes$ /library/asd-sensory-friendly-recipes-pancakes permanent;
|
||||||
|
rewrite ^/post/the-benefits-of-aba-therapy-for-children-with-autism$ /library/aba-therapy-benefits permanent;
|
||||||
|
rewrite ^/post/meet-rula-diab-board-certified-behavior-analyst-bcba$ /library/meet-rula-diab-bcba permanent;
|
||||||
|
rewrite ^/post/integrity-empowerment-and-excellence-arizona-institute-for-autism-expands-to-new-office$ /library/new-aia-scottsdale-office permanent;
|
||||||
|
rewrite ^/post/community-highlights-meet-rula-diab-of-arizona-institute-for-autism$ /library/community-highlight-meet-rula-diab permanent;
|
||||||
|
rewrite ^/post/navigating-dtt-and-net-in-aba-therapy$ /library/aba-therapy-dtt-net-guide permanent;
|
||||||
|
rewrite ^/post/benefits-of-prompting-and-parenting-in-aba-therapy$ /library/aba-therapy-prompting-parenting-benefits permanent;
|
||||||
|
rewrite ^/post/building-rapport-with-a-child-in-aba-therapy-the-key-to-fun-engaging-and-effective-sessions$ /library/autism-therapy-rapport-strategies permanent;
|
||||||
|
rewrite ^/post/exploring-behavior-management-and-understanding-the-functions-of-behavior$ /library/behavior-management-functions-guide permanent;
|
||||||
|
rewrite ^/post/navigating-back-to-school-understanding-antecedent-and-consequence-interventions-for-families-with$ /library/aba-school-readiness-guide permanent;
|
||||||
|
rewrite ^/post/proactive-and-reactive-strategies-in-aba$ /library/proactive-reactive-aba-strategies-guide permanent;
|
||||||
|
rewrite ^/post/individualized-aba-therapy$ /library/individualized-aba-therapy permanent;
|
||||||
|
rewrite ^/post/parental-self-care-for-autism-families$ /library/autism-family-self-care-tips permanent;
|
||||||
|
rewrite ^/post/teaching-self-advocacy-through-aba-empowering-children-to-express-their-needs$ /library/autism-self-advocacy-skills-aba permanent;
|
||||||
|
rewrite ^/ar/library/author/rula-diab-ar$ https://www.azinstitute4autism.com/ar/library/author/rula-diab permanent;
|
||||||
|
rewrite ^/locations$ /contact permanent;
|
||||||
|
rewrite ^/schedule/consultation$ /schedule-consultation permanent;
|
||||||
|
rewrite ^/e2ae5722f9ae40e89a9ebb8d53200e66\.txt$ https://www.azinstitute4autism.com/hubfs/e2ae5722f9ae40e89a9ebb8d53200e66.txt permanent;
|
||||||
|
rewrite ^/parent-guide$ /library/parents-guide-to-autism-and-aba permanent;
|
||||||
|
|
||||||
|
## Existing generated migration redirects follow. They include the remaining
|
||||||
|
## three rules from the HubSpot export, plus current page-one aliases.
|
||||||
rewrite ^/aba$ /aba-therapy permanent;
|
rewrite ^/aba$ /aba-therapy permanent;
|
||||||
rewrite ^/autismevaluations$ /autism-evaluations permanent;
|
rewrite ^/autismevaluations$ /autism-evaluations permanent;
|
||||||
rewrite ^/learnersocialclub$ /learner-social-club permanent;
|
rewrite ^/learnersocialclub$ /learner-social-club permanent;
|
||||||
|
rewrite ^/library/page/1$ /library permanent;
|
||||||
|
rewrite ^/es/library/page/1$ /es/library permanent;
|
||||||
|
rewrite ^/ar/library/page/1$ /ar/library permanent;
|
||||||
|
rewrite ^/library/author/rula-diab/page/1$ /library/author/rula-diab permanent;
|
||||||
|
rewrite ^/es/library/author/rula-diab/page/1$ /es/library/author/rula-diab permanent;
|
||||||
|
rewrite ^/ar/library/author/rula-diab/page/1$ /ar/library/author/rula-diab permanent;
|
||||||