Assistant: codex Assistant-Model: gpt-6.1-sol Assistant-Session: 01a126e1-76f8-7643-8cf3-e93336539ade
217 lines
13 KiB
Markdown
217 lines
13 KiB
Markdown
# KEY39 node-local OpenBao route prerequisite
|
|
|
|
Source-only successor `KEY-WP-0039-T02/attended-lifecycle-v9-ready-input` of frozen
|
|
v5. No native preflight, port-forward, login, Secret access or execution has run.
|
|
Previous v5 source and every review remain unchanged. The new executor and
|
|
health endpoint need fresh exact source-owner acknowledgments and a founder
|
|
native decision; previous v5 agreement is historical compatibility only.
|
|
|
|
The child runs on railiance01 and uses the explicit node k3s kubeconfig.
|
|
The environment orientation's port 18200 is a **workstation** address. The
|
|
installed `openbao-ui-railiance01` routing metadata is `direction: local`, local
|
|
port 18200, node destination `10.43.5.152:8080`. OpsBridge's supported local
|
|
forward builds `-L 127.0.0.1:18200:10.43.5.152:8080`; its listener belongs to the
|
|
machine invoking Bridge. It does not establish a node-local listener. No current
|
|
node DNS evidence establishes that `openbao.openbao.svc` resolves there. Do not
|
|
infer node reachability from workstation role observations or Bridge status.
|
|
|
|
OpsBridge supports named `up`, `down`, `status`, `check`, and local/reverse
|
|
configurations. There is no existing named KEY39 node-local reverse route in the
|
|
inspected routing metadata. Do not invent `bridge forward`, silently modify the
|
|
shared workstation tunnel, repurpose its port, or request a new SSH certificate
|
|
for this preparation. A new Bridge-managed route needs its own owner-reviewed
|
|
configuration and authority; this source does not create one.
|
|
|
|
## Proposed founder-held route on the child node
|
|
|
|
The Platform source publishes Service `openbao/openbao-ui-gateway`, port 8080,
|
|
which proxies the OpenBao API. The proposed attended route uses this existing
|
|
service and node loopback; it requires no pod DNS or hardcoded ClusterIP:
|
|
|
|
```bash
|
|
# Proposed only: run in a dedicated founder terminal ON railiance01, after exact
|
|
# route/session authority and current cluster/service identity are confirmed.
|
|
# Lifetime is capped at 25 minutes, including preparation/action/cleanup.
|
|
timeout --foreground 1500s kubectl --kubeconfig=/etc/rancher/k3s/k3s.yaml --request-timeout=20s -n openbao port-forward --address=127.0.0.1 --pod-running-timeout=20s service/openbao-ui-gateway 18200:8080 >/dev/null 2>&1
|
|
```
|
|
|
|
Keep that exact foreground process alive through issuer restoration, removed
|
|
client refusal and Secret absence verification. Stop only the new process with
|
|
Ctrl-C when those obligations are verified; timeout also stops it. Do not kill
|
|
an arbitrary existing listener, run `bridge down` against shared tunnels, or
|
|
restart a shared gateway. Port conflict, unavailable service, route loss or
|
|
non-ready OpenBao means stop and retain any pending custody for separately
|
|
approved recovery. Recovery requires re-establishing the same admitted node
|
|
route under its own founder recovery decision; no automatic tunnel is opened.
|
|
The lifetime estimate is a finite preparation ceiling, not an authority grant.
|
|
|
|
## Public preflight and exact envelope pin
|
|
|
|
The separate diagnostic command reads only the exact unauthenticated health
|
|
endpoint, never Kubernetes, Secrets, a token producer or a credential. Run from
|
|
the same founder-owned node execution context as the intended child:
|
|
|
|
```bash
|
|
python3 /OWNER-PINNED-PATH/openbao-negative-session.py route-preflight --bao-addr http://127.0.0.1:18200 --receipt /OWNER-PRIVATE-PATH/key39-node-route.json
|
|
```
|
|
|
|
The receipt is exclusive and mode 0600. It records only booleans and SHA256 of
|
|
public `cluster_id`; `probe_location=current_process_only` expressly avoids
|
|
claiming that an arbitrary workstation run proves node readiness. It accepts
|
|
only HTTP 200 with strictly boolean initialized=true, sealed=false,
|
|
standby=false, performance_standby=false when supplied, and a nonempty bounded
|
|
cluster identity. The official endpoint defines these health states:
|
|
[OpenBao health API](https://openbao.org/api-docs/system/health/).
|
|
|
|
Then run the existing founder preflight with the explicit same Bao origin:
|
|
|
|
```bash
|
|
python3 /OWNER-PINNED-PATH/openbao-negative-session.py founder-preflight --confirm 'FOUNDER ATTENDED KEY39 PREFLIGHT' --bao-addr http://127.0.0.1:18200 --receipt /OWNER-PRIVATE-PATH/key39-preflight.json
|
|
```
|
|
|
|
This retains all previous runtime/registry/headroom/quiet-window obligations.
|
|
Copy its `bao_health_identity_sha256` into the exact reviewed execute/recovery
|
|
envelope. The attending founder/Platform owner must verify the route target and
|
|
provider identity against their authoritative facts. Public health is not
|
|
cryptographic service authentication, role/policy proof or execution admission;
|
|
its hash detects accidental provider changes and does not replace that review.
|
|
|
|
Execute probes this pinned health identity before protected token input/native
|
|
object reads, then again after dry-runs immediately before the first temporary
|
|
Secret create. Recovery probes it before native object/Secret reads. A missing
|
|
pin, changed identity, redirect, unreachable/oversized/malformed response or
|
|
inactive provider refuses. The existing no-proxy/no-redirect/byte/total-elapsed
|
|
bounds and exception abort obligations apply to this new GET too. No local
|
|
helper opens or repairs the route. Loss after the first mutation still invokes
|
|
the existing bounded owner cleanup path; unproved cleanup stays pending.
|
|
|
|
The admitted human/coding-agent private stdin producer and all Platform/Mason/
|
|
Secrets Engine native acceptance prerequisites remain unresolved separately.
|
|
This preflight never fetches or produces those tokens and closes no owner task.
|
|
|
|
## V7 actual entrypoint sequencing correction
|
|
|
|
V6's statement that health preceded private token input was too broad: its
|
|
`main` read private stdin before calling `execute`, though health still preceded
|
|
all native reads/mutations. Platform identified that exact source/documentation
|
|
mismatch. V6 and its reviews remain immutable history.
|
|
|
|
V7 `main` verifies the exact approval/source envelope, starts the bounded action
|
|
window and checks the approved public health identity before reading private
|
|
stdin. On route failure, stdin is never read and no native access occurs. After
|
|
input arrives, `execute` revalidates source/authority and expiry, preserving the
|
|
original pre-input monotonic deadline rather than restarting it; its existing
|
|
health checks before native access and immediately before mutation remain.
|
|
Recovery never reads private stdin and still checks the same public health pin
|
|
before native Secret/config/deployment reads. Public route-preflight likewise
|
|
consumes no private input. These are separately tested through the actual `main`
|
|
entrypoint, with synthetic data and zero native/network calls.
|
|
|
|
## V8 bounded private JSON receive correction
|
|
|
|
V7 health preceded private stdin but `stdin.read()` had no byte or elapsed bound.
|
|
That issuer-owner finding remains history; exporter write bounds do not bound a
|
|
consumer read. V8 reads binary chunks of at most 4096 bytes, at most 65536 total
|
|
bytes, and requires actual EOF before decoding the exact two-token JSON object.
|
|
Each token is capped at 16384 UTF-8 bytes. The entire receive has a Linux main-
|
|
thread total timer capped at 15 seconds and clipped to the original remaining
|
|
wall-clock/monotonic action window; waiting never renews that window. Expiry is
|
|
checked before receiving, after EOF, and after decoding. Empty, oversized,
|
|
incomplete, invalid, stalled or late input cannot reach native execution.
|
|
Receipts contain only fixed failure codes/booleans, never bytes or parser errors.
|
|
|
|
This child-side read gate still does not establish producer-side readiness.
|
|
Before ANY token bytes enter a pipe/SSH transport, a separately reviewed trusted
|
|
launcher/exporter must receive an exact-child source/approval/public-health ready
|
|
acknowledgment bound to that pipe session and window. The current producer v1
|
|
has no such protocol; the producer consumer review requests it. V8 supplies no
|
|
handshake, launcher admission or native readiness and must not be piped to the
|
|
old exporter as though its health-before-read check prevents early transmission.
|
|
|
|
## V9 private ready protocol and concrete node wrapper
|
|
|
|
The old producer v1 refusal remains history: a child checking health before
|
|
reading stdin cannot prevent an exporter from buffering or transmitting tokens
|
|
earlier. V9 execute therefore requires `--ready-fd`, `--session-nonce` and
|
|
`--ready-envelope-sha256` before it will read private input. The ready FD is a
|
|
locally inherited writable FIFO >=3 whose inode/device differs from every stdio
|
|
endpoint; stdout/stderr aliases, regular files and missing FDs refuse.
|
|
|
|
After source/approval validation, original-window start and approved public
|
|
health, the child emits one <=4096-byte newline JSON marker to that private FD
|
|
and closes it. Emission has a total two-second cap clipped to the original
|
|
action window. Child stdout and stderr remain quiet. Exact marker fields are:
|
|
|
|
```json
|
|
{
|
|
"schema": "key39-private-input-ready/v1",
|
|
"session_nonce": "<fresh 64 lowercase hex characters from trusted launcher>",
|
|
"proposal_id": "KEY-WP-0039-T02/attended-lifecycle-v9-ready-input",
|
|
"target": "sso/keycape",
|
|
"executor_sha256": "<exact reviewed child source hash>",
|
|
"envelope_sha256": "<exact approved raw envelope byte hash>",
|
|
"bao_health_identity_sha256": "<exact owner provider identity pin>",
|
|
"valid_until_epoch": 0,
|
|
"receive_budget_seconds": 0
|
|
}
|
|
```
|
|
|
|
Zeros/placeholders illustrate keys only and are never a valid marker. Epoch is
|
|
the exact finite nonboolean approved envelope expiry, still future; receive
|
|
budget is finite positive <=15 and clipped at emission to the original action
|
|
window. The exporter clips its already-running deadline to the advertised
|
|
budget and *current* approval remainder. It must not reset a deadline or demand
|
|
that a budget measured at emission equal the smaller remainder after transport.
|
|
|
|
`openbao-negative-node-wrapper.py` is the concrete node-local relay. The trusted
|
|
launcher supplies nonsecret exact child/envelope paths and SHA256 pins, a new
|
|
nonce and exclusive receipt destination. Wrapper envelope must be owner UID,
|
|
mode0600, single-link regular file, stable bounded bytes; its child/wrapper
|
|
source paths must be included in the exact envelope's native source hash map.
|
|
This is reconstruction of the caller's review context, not authenticated human
|
|
approval: assertions in JSON cannot create a grant. The founder must separately
|
|
admit the exact source/profile, target and SSH peer under the applicable lane.
|
|
|
|
The wrapper creates an **ordinary local pipe on the node**, starts the pinned
|
|
Python child with that write endpoint passed locally, and reads its bounded
|
|
marker plus EOF. The child's private stdin is inherited directly from the SSH
|
|
input stream: wrapper never reads, copies, logs or writes token bytes. No extra
|
|
file descriptor is forwarded by SSH or OpsBridge. Within one five-second total
|
|
preparation deadline, the wrapper validates all marker keys/nonce/pins/window and
|
|
forwards exactly one value-free marker line on its own stdout control pipe.
|
|
The admitted workstation launcher must own/capture that SSH stdout separately
|
|
from its private stdin data pipe, never display/tee/log it, validate the exact
|
|
marker and then allow the KeyCape adapter to load/consume caller files or write
|
|
ANY token bytes. The control stream stays open while the child runs; the
|
|
exporter stops marker reception at newline, not SSH EOF. Missing, partial,
|
|
wrong-nonce, stale, oversized or pin-mismatched markers mean zero token file
|
|
reads/writes and retained caller files. The old v1 adapter is incompatible.
|
|
|
|
This wrapper emits control stdout and therefore **cannot run inside the
|
|
warden attended command lane that rejects all child output**. It requires a
|
|
separately admitted founder-owned direct SSH profile with no PTY, captured
|
|
stdin/stdout/stderr, pinned peer/host identity, exact wrapper/source/receipt paths
|
|
and no agent credential access. No such runtime admission is supplied here.
|
|
A bare marker, caller boolean or downloaded ready file cannot authenticate a
|
|
peer, source execution or founder decision. A trusted reviewed launcher owning
|
|
that transport and verifying the context is a prerequisite.
|
|
|
|
The wrapper waits only through the original approval remainder plus 300 seconds
|
|
cleanup. Any child stdout/stderr is captured with bounded reads and refused,
|
|
never forwarded. Failure terminates the exact launched child with bounded five-
|
|
second TERM then two-second kill/wait fallback; capture closes have 20 ms caps.
|
|
No retry or replay occurs. Interruption, partial private delivery, emitted ready
|
|
followed by child death, unconfirmed revoke or interrupted native cleanup remains
|
|
unknown/pending owner reconciliation using the separately approved recovery
|
|
path. Wrapper exit zero is not owner/native acceptance; the child receipt still
|
|
requires actual owner acceptance. No persistent file/copy on the node is added
|
|
for token material, and Unix/Python memory cleanup is not secure zeroization.
|
|
|
|
Human browser issuance and admitted coding-agent custody remain distinct owner
|
|
choices. Any new files must be produced by the pinned verified owner CLI under
|
|
continuous exclusive tmpfs custody after the separately admitted route preflight.
|
|
They must be prepared before launching this short-lived private receive window;
|
|
the child cannot wait for a five-minute browser login after emitting ready.
|
|
Fresh registered-client/MFA/custody evidence, exact independent KeyCape/Platform
|
|
reviews and the founder's complete route/transport/private-file/native decision
|
|
remain required. No native handshake, SSH, credential or route was exercised.
|