# External witness onboarding

No Finality credentials, application DB or private API is needed. This package is
seller built; there are zero evidenced outside witness operators. Use Node 24 for
source operation. Resource estimates (not measured production requirements): one
CPU, 512 MiB RAM and persistent disk sized for retained journals; public HTTPS
checkpoint feed plus consistency endpoint. Outbound HTTPS and operator-managed
alerts are required; bind health to loopback unless deliberately protected.

Prepare witness.json: feed, witness_id, key_id, operator, authenticated anchor,
policy with logId/epoch/keys/maxAgeMs/maxFutureMs. Public log keys include id,
publicKey, status, notBefore/notAfter. Authenticate anchor and keys separately;
do not copy a feed's offered root into trust automatically. In an extracted kit:

```
node research/operations/witness-up.mjs STATE-DIRECTORY witness.json
```

The command initializes an operator-owned key once and runs the witness. Register
witness-public.pem with relying parties through their real approval process.
The private key and writable state directory stay operator owned (mode0600/0700).
Separate instances need separate keys, directories, configuration and processes.
A different key or operator label is not evidence of independent organizations.

The OCI builder accepts a digest-pinned public Node index and explicitly copies
only public code. It emits a real OCI archive and IMAGE.json with all hashes:

```
node research/operations/build-witness-oci.mjs EMPTY-OUTPUT sha256:a9f5f7c91a432850b2a8a7797adf5eadb6c733ceed61167806cee7ea7fbc29df
```

Load the archive with an eligible OCI runtime, then run its image digest with a
read-only root filesystem, /config/witness.json read-only, writable /state owned by
UID65534, and a tmpfs /tmp. The image entrypoint is witness-up.mjs. Container boot
and clean-host setup time are not measured here; namespaces/runtime are unavailable.
An archive hash proves packaged bytes, not successful execution or external operation.

Observe /health, signed observation JSON, retained state, journal and alert files.
Forks, shrinking trees, missing proofs, stale checkpoints and incomplete commits
halt. Validate the alert behavior by serving incompatible same-size roots under
test-only keys. Seller-operated local HTTP tests cover two distinct keys/stores;
the permanent tests include fork/shrinkage and restore refusal.

Upgrade: pin and verify the new source/image digest, stop safely, back up state and
key, retain the latest authenticated checkpoint outside the recoverable host, then
start the reviewed release on the same state volume. Never reinitialize or wipe a
floor to get past a rejection. A crash between journal and state commit must be
reconciled against the independently retained checkpoint before resuming.

Recovery: restore the encrypted key/state backup and compare to the separate floor;
if behind or divergent, refuse observations until authenticated consistency and
review reconcile it. Restoring all state and all external floors together defeats
local rollback detection. Registry/log key rotation and globally protected floor
operations require additional reviewed deployment engineering. Outside operator
onboarding and installation timing remain real-world tasks, never fabricated passes.
