84 lines
5 KiB
Markdown
84 lines
5 KiB
Markdown
|
|
# Railiance Clock lifecycle-consumer review
|
||
|
|
|
||
|
|
SECRETS-IN-0003, reviewed 2026-09-27. This completes the requested consumer
|
||
|
|
review. It does not admit a new authority, key, deployment or execution window.
|
||
|
|
|
||
|
|
Reviewed inputs: railiance-clock `61e86a6e01c2e93a9af923a46772a41d080a5743`,
|
||
|
|
`specs/sample-profile-v0.1.md`, `docs/implementation-review-2026-09-15.md`,
|
||
|
|
`src/railiance_clock/{protocol,client,admission}.py`, and this repository's
|
||
|
|
`application_time.py`, approval validators and consume guard. The earlier
|
||
|
|
intake describes a proposal, but consumer implementation and scoped native
|
||
|
|
acceptance already exist in [the approval contract](approval-consumption.md)
|
||
|
|
and [the September 16 receipt](evidence/2026-09-16-t03-completion.json).
|
||
|
|
|
||
|
|
## Signing compatibility and custody
|
||
|
|
|
||
|
|
The reviewed implementation delegates ES256 to PyJWT/cryptography, pinned by
|
||
|
|
railiance-clock's dependency range (`PyJWT[crypto]>=2.10,<3`). It verifies the
|
||
|
|
original compact envelope, restricts the algorithm to ES256, and requires an
|
||
|
|
admitted P-256 public key and exact key ID. Closed headers, 64-byte signatures,
|
||
|
|
canonical base64url, strict JSON, nonce and authority/environment/epoch/policy
|
||
|
|
checks accompany signature verification. Secrets-engine uses that library;
|
||
|
|
it has no independent signing or verification implementation.
|
||
|
|
|
||
|
|
The signing private key belongs to the platform's admitted custody and the
|
||
|
|
clock authority runtime. It must not share an approval, KeyCape, SSH or engine
|
||
|
|
credential. No signing key is delivered to this engine: its input is a public
|
||
|
|
trust binding. The clock's explicit private-file deployment interface is not
|
||
|
|
proof of OpenBao custody, renewal or fleet-wide admission. Those owner proofs
|
||
|
|
remain in existing RCLK-WP-0002/0004/0005; no new custody task or lane is created.
|
||
|
|
|
||
|
|
## Bootstrap, rotation and revocation
|
||
|
|
|
||
|
|
Admit the authority, environment, public-key fingerprint, key ID, epoch, policy,
|
||
|
|
transport and finite lifetime over an independently authenticated owner path.
|
||
|
|
The sample under verification cannot establish its own trust. HTTPS verification
|
||
|
|
must work already; the reviewed alternative is explicitly admitted SSH-backed
|
||
|
|
loopback transport. Neither permits disabling TLS checks or adjusting OS time.
|
||
|
|
|
||
|
|
The current trust admission is client-boot-bound, with a maximum 15-minute
|
||
|
|
BOOTTIME deadline. Every read obtains a fresh sample and checks the trust file
|
||
|
|
before and after exchange; cached usable-time holdover is absent. Missing or
|
||
|
|
changed trust, expiration, an unknown epoch, rollback-state failure or excessive
|
||
|
|
uncertainty must refuse. The engine's cached client intentionally remains refused
|
||
|
|
after its trust file changes; restart/reacquisition requires a separately admitted
|
||
|
|
replacement, not automatic trust discovery.
|
||
|
|
|
||
|
|
For rotation, platform/clock owners admit the replacement key and invalidate old
|
||
|
|
client trust bindings, then consumers reacquire under the new binding. For
|
||
|
|
revocation, invalidate every affected binding and stop the old authority before
|
||
|
|
accepting further samples. File-change detection is local enforcement, not an
|
||
|
|
automatic estate-wide revocation distribution system. A consumer whose old file
|
||
|
|
is not invalidated can retain trust until its bounded deadline. Native rotation,
|
||
|
|
revocation propagation and snapshot/recovery acceptance must be proved by the
|
||
|
|
owners before claiming those operational guarantees. The library does not grant
|
||
|
|
permission to reset the persisted rollback floor.
|
||
|
|
|
||
|
|
## Consumer acceptance and limits
|
||
|
|
|
||
|
|
`SECRETS_ENGINE_CLOCK_TRUST_FILE` remains explicit opt-in. When configured,
|
||
|
|
unavailable or untrusted time refuses; it never falls back to workstation time.
|
||
|
|
An unconfigured engine retains its existing OS-clock path. Claim validity and
|
||
|
|
freshness and PDP decision lifetime must contain the whole interval: the lower
|
||
|
|
bound reaches not-before and the upper bound remains strictly before expiry.
|
||
|
|
Nanosecond-to-microsecond conversion rounds outward. Decision validity is checked
|
||
|
|
before and after CAS consume, with the existing actor/tenant/action/field/digest
|
||
|
|
and policy checks unchanged. A refusal after consume prevents backend access,
|
||
|
|
although the approval may already be consumed and needs a new request.
|
||
|
|
|
||
|
|
This is a check at the engine's consume boundary, not an atomic transaction
|
||
|
|
spanning OpenBao or a proof that a long-running child remains within the decision
|
||
|
|
lifetime. The library provides bounded time evidence, not authorization, spend
|
||
|
|
admission, complete audit custody or provider-session revocation. Server-side
|
||
|
|
issuers/approval storage retain their own validity enforcement.
|
||
|
|
|
||
|
|
The September 16 native receipt records three bounded samples, wrong-key-ID
|
||
|
|
refusal, independent host cross-checks and a 900-second trust admission during
|
||
|
|
one exact OpenRouter acceptance. It does not prove universal UTC accuracy,
|
||
|
|
all-platform suspend behavior or a rotation/revocation exercise. Existing
|
||
|
|
RCLK-WP-0002-T04 and RCLK-WP-0004 retain those owner acceptance boundaries.
|
||
|
|
`tests/test_application_time.py` covers interval boundaries, missing trust,
|
||
|
|
no shifted-time mixing and consume expiry refusal. This review accepts the
|
||
|
|
explicit bounded-time consumer contract within those stated limits; it grants
|
||
|
|
no new production use.
|