Files

8.1 KiB

Employee portal compatibility and private migration

Recorded 2026-10-30. Browser-side shared-code decryption is approved only for local compatibility development. It is not authentication, individual revocation, a secure session or a HIPAA compliance determination. Resources need separate server authorization before cutover.

Source and private collection

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. No access code was available to the agent. The exact resource count and real content compatibility remain unverified. Do not infer the earlier approximate 43 links as a measured count.

From www, in the owner's private interactive terminal:

node tools/employee-portal-migrate.mjs collect \
  /home/alice/projects/wrk/aia/local-archives/aia-employee-portal-hubspot-footer-source.txt

Enter each legitimate view code at its hidden prompt. Never place codes in arguments, environment variables, shell history or reports. The utility checks both streams, keeps plaintext in memory, and collects only referenced /hubfs/ resources from the verified source origin. Other origins require explicit review/code allowlisting; redirects are bounded and never inherit credentials. No Jotform, Google or other vendor forms are fetched.

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. All new resources default to UNRESOLVED. Publicly reachable does not mean public approved. Resuming verifies an existing file's content hash; mismatches are not overwritten. HTML error documents, executable responses, invalid known signatures, redirects outside approved destinations and resources over 50 MiB are rejected. The first pass allows only the verified site origin. If a legitimate /hubfs/ response redirects to a HubSpot CDN, inspect that exact HTTPS origin first, then add its origin to the private manifest's approvedOrigins list and rerun. Never approve a redirect based only on a failed download or a broadly shared vendor domain. Failures remain private review items. The utility prints counts only.

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.

Approved rewriting

The owner classifies records as PUBLIC-APPROVED, STAFF-INTERNAL, MANAGEMENT-INTERNAL or UNRESOLVED in the private manifest. Set deliveryPath, rewriteApproved, destinationImplemented, destinationVerified, and (for internal documents) destinationAccessControlled only with actual evidence. The utility does not create those destinations or infer their approval.

node tools/employee-portal-migrate.mjs rewrite \
  /home/alice/projects/wrk/aia/local-archives/aia-employee-portal-hubspot-footer-source.txt

It reauthenticates both views, changes approved quoted href/src attributes only, preserves unrelated HTML/labels, and re-encrypts with fresh salts and IVs. It verifies round-trip decryption and distinct codes before writing new ciphertext with exclusive filenames. The original source is untouched. CSS/srcset mappings require separate review and are rejected rather than silently rewritten. Unresolved links retain their original destination as a recorded dependency, not a claim of verified destination health. A changed manifest alone never changes links in the encrypted stream.

Local preview and content safety

Use a private ciphertext file generated by collect or rewrite:

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.