Files
aia-website/www/integrations/employee-portal/README.md
T

9.3 KiB

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.

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:

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 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:

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:

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:

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.