fix(portal): prepare approved resource mappings safely
This commit is contained in:
1 parent
36d417a422
commit
81492125f4
11 files changed
+427
-153
No files matched your search
@@ -23,71 +23,84 @@ approved release and protected-resource installation commands.
|
||||
|
||||
## 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.
|
||||
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.
|
||||
|
||||
From `www`, in the owner's private interactive terminal:
|
||||
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
|
||||
node tools/employee-portal-migrate.mjs collect \
|
||||
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
|
||||
```
|
||||
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
|
||||
## Approved rewriting
|
||||
## Historical collection and rewriting recovery notes
|
||||
|
||||
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.
|
||||
|
||||
```sh
|
||||
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.
|
||||
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 private ciphertext file generated by `collect` or `rewrite`:
|
||||
Use a retained private ciphertext revision:
|
||||
|
||||
```sh
|
||||
AIA_PORTAL_LOCAL_PREVIEW_APPROVED=true \
|
||||
|
||||
@@ -61,7 +61,6 @@ 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 website release that contains `portal-resource-install.sh` is promoted and
|
||||
the VPS SOPS-backed Basic Auth material is independently ready:
|
||||
|
||||
```sh
|
||||
@@ -72,15 +71,21 @@ AIA_DEPLOY_SSH_IDENTITY="$HOME/.ssh/AIAMarketing" \
|
||||
npm run deploy:portal-resources -- --confirm
|
||||
```
|
||||
|
||||
The installer invokes the promoted root-only `portal-resource-install.sh` through
|
||||
NixOS's base `/bin/sh` and coreutils path; it does not depend on a globally
|
||||
installed Node.js runtime. It reads only the private collection manifest,
|
||||
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
|
||||
|
||||
Reference in new issue
Block a user