186 lines
10 KiB
Markdown
186 lines
10 KiB
Markdown
# 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.
|