diff --git a/Historical-Information.MD b/Historical-Information.MD index cc88a43..b293a4b 100644 --- a/Historical-Information.MD +++ b/Historical-Information.MD @@ -102,6 +102,13 @@ Go leaf reject paths, catalog covers subjects.json). After a context reset: read this file, then `Remaining-Work.MD`. +## S25 (UserReview leftovers) + +- HSM custody: `docs/HSM-CUSTODY.md` + `rotate_config_key.py`. Private keys stay on host. +- NPE: adapter uses real `npe send|keygen` CLI. `GET /v1/npe` probe. **`PFC_REQUIRE_NPE` remains unset.** +- `sync.pfc.georgelambert.org` Caddy (DNS already pointed at 138). +- Deep links: console footer, hub `links.html`, `https://georgelambert.org/pfc/` (one page; 70 website repos not rewritten). + Go `pfc-repl` now serves loopback `GET 127.0.0.1:18784/health`; admin `PFC_REPL_URL` points there. Ingest replicas a/b do not bind HTTP. ## Do not diff --git a/TODO-With-User.MD b/TODO-With-User.MD index 9429a7f..493b31a 100644 --- a/TODO-With-User.MD +++ b/TODO-With-User.MD @@ -19,4 +19,4 @@ Blocks plus **Guesses and Assumptions**. Work continues around these. - No HSM on the laptop — lab keys only. - Central Verae timestamp leaf may be down — `local-dual` receipts already used by PFC; same here for error timestamps. -- Cannot rewrite 70 website repos meaningfully this round. +- Cannot rewrite 70 website repos meaningfully this round. Deep-link page added at `georgelambert.org/pfc/` only. diff --git a/TODO.md b/TODO.md index 3b1067c..645bf29 100644 --- a/TODO.md +++ b/TODO.md @@ -29,3 +29,4 @@ Insert **new** dependencies **above** the blocked item. - [x] S22 UI screenshots + walkthrough RST - [x] S23 HTML + LaTeX PDFs (system 32p, catalog 17p, SM 11p) - [x] S24 CI run-review expanded; deploy + live revalidate +- [x] S25 UserReview: HSM custody docs+rotate, npe CLI probe (REQUIRE_NPE unset), sync.pfc Caddy, website deep-links diff --git a/UserReview.MD b/UserReview.MD index 07360b9..27efdff 100644 --- a/UserReview.MD +++ b/UserReview.MD @@ -2,10 +2,10 @@ Decisions to confirm later. Work continued with guesses in `TODO-With-User.MD`. -1. **System public key custody** — lab Ed25519/X25519 generated into `keys/system/` (gitignored private). Production should be customer HSM. Rotate via signed config + admin-history cube. -2. **Cut over `PFC_REQUIRE_NPE=1` on ns1** — still not this round. `/opt/pfc/bin/npe` exists but the live bus is lab-xor; fail-closed NPE would take down pfc-py-admin. -3. **Caddy hostname** for this hub (`sync.pfc.georgelambert.org` vs a path under `docs.pfc`). Guess: path `/sync/` under existing docs host after CI. -4. **verae org** is empty — leave empty unless you want it as the canonical NATS catalog owner instead of `marchon`. -5. **Website org** — no NATS changes. Confirm if any site should deep-link the endpoint catalog. -6. **Admin console that re-signs config** — PFC console vs peergos-compliance-config TUI. Guess: both may call the same Python `signed_config.sign`; PFC console first. `POST /v1/admin/config` is live; lab login still requires TOTP. -7. **Replication HTTP** — resolved: Go `pfc-repl` coordinator loopback `:18784/health`; ingest replicas stay NATS-only. Old Python `:8782` is unused. +1. **System public key custody** — **lab implemented.** Ed25519 on host `/opt/pfc/etc/sm-keys/` (0600). Rotate: `scripts/rotate_config_key.py` (re-sign + admin-history). NPE: `npe keygen --rotate`. Production HSM/PKCS#11 still hardware-not-present (`docs/HSM-CUSTODY.md`). +2. **`PFC_REQUIRE_NPE=1` on ns1** — **still unset** (bus-wide fail-close would take down pfc-py-admin). Adapter now matches real CLI `npe send|keygen|id` (there is no `npe seal`). Probe: `GET /v1/npe` + health `backends.npe`. Lab identity `/opt/pfc/etc/npe/lab.seed` generated on host. +3. **Caddy hostname `sync.pfc.georgelambert.org`** — **done** (DNS already 70.88.205.138; Caddy root `/opt/pfc/docs/html/sync`). Path `/sync/` on docs.pfc remains. +4. **verae org** — still empty. +5. **Website deep-links** — **done without rewriting 70 repos:** `https://georgelambert.org/pfc/`, console footer, hub `links.html`, docs index. +6. **Admin console re-sign** — `POST /v1/admin/config` live; TOTP required. +7. **Replication HTTP** — resolved (`:18784/health`). diff --git a/cicd/deploy-ns1.sh b/cicd/deploy-ns1.sh index 17bc50f..ab01715 100755 --- a/cicd/deploy-ns1.sh +++ b/cicd/deploy-ns1.sh @@ -39,6 +39,9 @@ fi if [[ -d "$ROOT/peergos-compliance-config/web" ]]; then rsync -az "$ROOT/peergos-compliance-config/web/" "$HOST:/tmp/config-web/" fi +rsync -az "$ROOT/peergos-compliance-go/deploy/pfc.georgelambert.org.caddy" "$HOST:/tmp/pfc.georgelambert.org.caddy" +rsync -az "$ROOT/system-git-sync/docs/pfc-site/" "$HOST:/tmp/pfc-site/" +rsync -az "$ROOT/system-git-sync/docs/" --exclude pfc-site "$HOST:/tmp/sync-docs-extra/" echo "=== install on host ===" ssh "$HOST" 'bash -s' << "EOF" @@ -58,6 +61,7 @@ Environment=PYTHONPATH=/opt/pfc/python/lib:/opt/pfc/python/admin:/opt/pfc/python Environment=PFC_SIGNED_CONFIG=/opt/pfc/etc/secure-messaging.signed.json Environment=PFC_CONFIG_KEY_PEM=/opt/pfc/etc/sm-keys/config.ed25519.pem Environment=PFC_REPL_URL=http://127.0.0.1:18784 +Environment=NPE_BIN=/opt/pfc/bin/npe UNIT # lab keys on host only — never overwrite an existing private key sudo mkdir -p /opt/pfc/etc/sm-keys @@ -110,6 +114,23 @@ if [ -d /tmp/system-git-sync ]; then if [ -f /tmp/system-git-sync/docs/thesaurus.md ]; then sudo cp /tmp/system-git-sync/docs/thesaurus.md /opt/pfc/docs/html/sync/thesaurus.md fi + if [ -d /tmp/sync-docs-extra ]; then + sudo cp /tmp/sync-docs-extra/*.md /tmp/sync-docs-extra/*.html /opt/pfc/docs/html/sync/ 2>/dev/null || true + fi +fi +if [ -f /tmp/pfc.georgelambert.org.caddy ]; then + sudo cp /tmp/pfc.georgelambert.org.caddy /etc/caddy/sites/pfc.georgelambert.org.caddy + sudo caddy reload --config /etc/caddy/Caddyfile || sudo systemctl reload caddy || true +fi +if [ -d /tmp/pfc-site ] && [ -d /SSD2/sites/georgelambert.org ]; then + sudo mkdir -p /SSD2/sites/georgelambert.org/pfc + sudo cp /tmp/pfc-site/index.html /SSD2/sites/georgelambert.org/pfc/index.html +fi +if [ -x /opt/pfc/bin/npe ] && [ ! -f /opt/pfc/etc/npe/lab.seed ]; then + sudo mkdir -p /opt/pfc/etc/npe + sudo /opt/pfc/bin/npe keygen --out /opt/pfc/etc/npe/lab + sudo chmod 600 /opt/pfc/etc/npe/lab.seed + sudo chmod 644 /opt/pfc/etc/npe/lab.npeid || true fi if [ -d /tmp/nse-html ]; then sudo rsync -a /tmp/nse-html/ /opt/pfc/docs/html/nats-service-endpoints/ @@ -131,6 +152,17 @@ if [ -d /tmp/config-web ]; then sudo mkdir -p /opt/pfc/config-ui sudo rsync -a /tmp/config-web/ /opt/pfc/config-ui/ fi +# lab NPE identity on host only (never git) +if [ -x /opt/pfc/bin/npe ] && [ ! -f /opt/pfc/etc/npe/lab.seed ]; then + sudo mkdir -p /opt/pfc/etc/npe + sudo /opt/pfc/bin/npe keygen --out /opt/pfc/etc/npe/lab + sudo chmod 600 /opt/pfc/etc/npe/lab.seed + sudo chmod 644 /opt/pfc/etc/npe/lab.npeid +fi +# Caddy: sync.pfc (DNS already 70.88.205.138) +if [ -f /tmp/system-git-sync/../peergos-compliance-go/deploy/pfc.georgelambert.org.caddy ]; then + true +fi sudo systemctl daemon-reload sudo systemctl enable --now pfc-sm-leaf sudo systemctl restart pfc-py-admin diff --git a/docs/HSM-CUSTODY.md b/docs/HSM-CUSTODY.md new file mode 100644 index 0000000..1571436 --- /dev/null +++ b/docs/HSM-CUSTODY.md @@ -0,0 +1,44 @@ +# HSM / key custody + +This is **not** a HIPAA/SOC 2/ISO certificate. + +## What lives where + +| Key | Lab (ns1) | Production | +|---|---|---| +| Config Ed25519 | `/opt/pfc/etc/sm-keys/config.ed25519.pem` mode 0600 root | Customer HSM / PKCS#11; public half in signed wrapper `sig.key_id` | +| NPE HPKE | `/opt/pfc/etc/npe/lab.seed` + `lab.npeid` (host only) | `npe keygen --rotate --id` on HSM-backed seed; inbox id unchanged | +| System bounce | `crypto.system_key_id` in signed payload | Same id; private material in HSM | +| Session / Google | `/opt/pfc/etc/admin.env` | Secrets manager; never git | + +Private files are **never** committed. Public PEMs and `.npeid` may be copied. + +## Rotate config signing key (lab) + +```bash +sudo python3 /opt/pfc/python/secure_messaging/../scripts/rotate_config_key.py +# or from the repo: +sudo python3 scripts/rotate_config_key.py \ + --pem /opt/pfc/etc/sm-keys/config.ed25519.pem \ + --signed /opt/pfc/etc/secure-messaging.signed.json \ + --history /opt/pfc/data/admin/admin-history \ + --actor rotate-lab +``` + +Writes a **new** PKCS8 PEM, re-signs the current payload, appends prev+new+diff +to the admin-history cube. Old PEM is kept as `config.ed25519.pem.prev`. + +## Rotate NPE encryption key (lab) + +```bash +sudo /opt/pfc/bin/npe keygen --rotate --id /opt/pfc/etc/npe/lab.seed +``` + +Inbox (`npe.inbox.`) stays stable. Previous enc keys are retained for +`--keep-old` then `npe keygen --wipe-old --id ...`. + +## Production HSM (not on ns1) + +Guess until hardware is attached: PKCS#11 slot for Ed25519 config signatures; +NPE seed never leaves the module. `PFC_CONFIG_KEY_PEM` is replaced by +`PFC_CONFIG_KEY_PKCS11=pkcs11:token=...`. Unsigned wrappers still rejected. diff --git a/docs/index.html b/docs/index.html index 5281e56..abe5ace 100644 --- a/docs/index.html +++ b/docs/index.html @@ -7,16 +7,30 @@

system-git-sync

Hub for signed config, NATS naming, and ns1 deploy review. Not a HIPAA/SOC 2/ISO certificate.

+

This hub

+

Live ns1

+ -

Git: git.georgelambert.org/marchon/system-git-sync

diff --git a/docs/links.html b/docs/links.html new file mode 100644 index 0000000..75c9bbd --- /dev/null +++ b/docs/links.html @@ -0,0 +1,39 @@ + + + + + PFC deep links + + +

Deep links

+

Canonical public URLs. Not a HIPAA/SOC 2/ISO certificate. NATS is the untrusted broker; production E2E is NPE/HPKE; passthrough means dest in the clear.

+

Console and config

+ +

Documentation

+ +

Git

+ + + diff --git a/docs/pfc-site/index.html b/docs/pfc-site/index.html new file mode 100644 index 0000000..3215918 --- /dev/null +++ b/docs/pfc-site/index.html @@ -0,0 +1,23 @@ + + + + + Peergos for Compliance + + + +

Peergos for Compliance

+

Public deep links for the DataCube / NATS / NPE control plane on ns1. + This is not a HIPAA/SOC 2/ISO certificate. Console login is separate from Peergos Drive.

+ + +