# Certificates / TLS Backlog

Bounded implementation slice chain for the certificates/TLS track. It
decomposes [certificates-and-tls-proposal.md](../proposals/certificates-and-tls-proposal.md)
into dispatchable slices and is owned by the **Certificates / TLS** track in
[`docs/tasks/README.md`](../tasks/README.md). The dispatchable records live under
`docs/tasks/`; this file is the long-form decomposition and sequencing rationale.

## Grounding

- [certificates-and-tls-proposal.md](../proposals/certificates-and-tls-proposal.md)
  -- the schema surface and Phase 1-9 ordering. Phases 1-2 are the near-term
  target; Phase 1 is `Certificate` / `CertificateChain` / `TrustStore` /
  `CertVerifier` over a RAM-only `webpki-roots` store and a `rustls-webpki`
  verifier. The Phase 2 client-only local proof now completes a TLS 1.3
  handshake over a userspace-served `TcpSocket` cap with `embedded-tls`; the
  server/config service surface remains future Phase 2 work.
- [cryptography-and-key-management-proposal.md](../proposals/cryptography-and-key-management-proposal.md)
  -- partial implementation. The minimal `SymmetricKey`, `PrivateKey`, and
  `PublicKey` ABI, RAM-only XChaCha20+HMAC/P-256 key cores, RAM-only
  `KeyVault` handle custody, and development-only software `KeySource`
  bootstrap exist for local proofs. There is still **no** persistence or
  production custody source, so production/public TLS and ACME remain blocked on
  a reviewed source that can mint key handles without exposing raw private-key
  material.
- [time-and-clock-proposal.md](../proposals/time-and-clock-proposal.md)
  -- `WallClock` Phase 1 landed (`88cf4b5d`): a read cap with `wallTime` and a
  `ClockProvenance` label, but the fixed-boot-base source reports `Untrusted`.
  Cert-validity (`notBefore`/`notAfter`) and OIDC `exp`/`iat` compare against it.
  Host-tested verify logic passes an explicit `atEpochSeconds` and needs no live
  clock; security-grade validity against an adversarial clock wants the
  trusted-provenance upgrade (WallClock Phase 2). Recorded as a sequencing
  dependency on the *live* consumer slices, not on the host verifier slice.
- [phase-c-userspace-nic-driver-relocation.md](../proposals/phase-c-userspace-nic-driver-relocation.md)
  -- the userspace `TcpSocket` cap the TLS stack wraps arrives via Phase C
  slice-7 ([`cloud-prod-userspace-network-stack-smoltcp-local-proof`](../tasks/done/2026-06-07/cloud-prod-userspace-network-stack-smoltcp-local-proof.md)).
  The TLS stack is a **userspace** consumer of that cap and must not move into
  the kernel.

## Sequencing Rationale

The proposal's suggested shape (library -> handshake -> cert caps -> consumer) is
reordered to land the lowest-risk real logic first, grounded in what exists:

- The **verifier** path (TrustStore + CertVerifier over webpki-roots) needs
  **no socket and no private key** -- it is pure `no_std + alloc` host-testable
  logic. It lands before the handshake.
- A TLS **client** handshake needs a `TcpSocket` cap but **no** private key.
- A TLS **server** (the Web UI consumer) needs a `KeyVault`-issued
  `PrivateKey` handle and a server cert source, so it remains the most-blocked
  terminal slice.

## Slice Chain

| # | Task | Proposal phase | Status | Depends on |
|---|------|----------------|--------|------------|
| 1 | [`cloud-tls-vendor-rustls-webpki-roots-no-std-provenance`](../tasks/done/2026-06-03/cloud-tls-vendor-rustls-webpki-roots-no-std-provenance.md) | Phase 1 deps | done | -- |
| 2 | [`cloud-tls-cert-truststore-certverifier-phase1-host-proof`](../tasks/done/2026-06-03/cloud-tls-cert-truststore-certverifier-phase1-host-proof.md) | Phase 1 | done | slice 1 |
| 3 | [`cloud-tls-client-handshake-over-tcpsocket-local-proof`](../tasks/done/2026-06-08/cloud-tls-client-handshake-over-tcpsocket-local-proof.md) | Phase 2 (client) | done | slice 2 + Phase C slice-7 socket cap |
| 4 | [`cloud-tls-self-hosted-webui-terminated-endpoint`](../tasks/cloud-tls-self-hosted-webui-terminated-endpoint.md) | Phase 2 (server) consumer | blocked | slice 3 + key-cap surface + provider-terminated GCE Web UI proof |
| K0 | [`crypto-key-custody-tls-acme-decomposition`](../tasks/done/2026-06-04/crypto-key-custody-tls-acme-decomposition.md) | key-management precursor | done | -- |
| K1 | [`crypto-privatekey-publickey-ram-signing-local-proof`](../tasks/done/2026-06-04/crypto-privatekey-publickey-ram-signing-local-proof.md) | key Phase 1 subset | done | slice 2 |
| K2 | [`crypto-keyvault-ram-privatekey-custody-local-proof`](../tasks/done/2026-06-05/crypto-keyvault-ram-privatekey-custody-local-proof.md) | key Phase 2 subset | done | K1 |
| K3 | [`crypto-development-keysource-tls-acme-bootstrap-local-proof`](../tasks/done/2026-06-05/crypto-development-keysource-tls-acme-bootstrap-local-proof.md) | key source local bootstrap | done | K2 |
| 5 | [`cloud-tls-acme-account-order-local-proof`](../tasks/done/2026-06-08/cloud-tls-acme-account-order-local-proof.md) | Phase 3 (ACME core) | done | slice 3 + K3 |
| 6 | [`cloud-tls-acme-http01-challenge-solver-local-proof`](../tasks/done/2026-06-09/cloud-tls-acme-http01-challenge-solver-local-proof.md) | Phase 3 (`http-01`) | done | slice 5 + Web UI L4 path |
| 7 | [`cloud-tls-acme-renewal-certstore-rotation-local-proof`](../tasks/cloud-tls-acme-renewal-certstore-rotation-local-proof.md) | Phase 3 (renewal) | blocked | slices 4-6 |
| 8 | [`cloud-gce-public-webui-letsencrypt-direct-termination-proof`](../tasks/on-hold/cloud-gce-public-webui-letsencrypt-direct-termination-proof.md) | public GCE successor | blocked | provider proof + slice 7 + public DNS/authorization |

1. **Vendor the Phase-1 verifier crates.** `rustls-webpki` + `webpki-roots` as
   static-pinned no_std+alloc snapshots with `VENDORED_FROM.md` provenance,
   recorded under `docs/trusted-build-inputs.md`, proved to build for the
   bare-metal target. Slice 3 later selected `embedded-tls` for the local
   client proof's no_std TLS state machine; the broader server/config service
   stack remains future work.
2. **`Certificate` / `TrustStore` / `CertVerifier` (Phase 1).** Schema additions
   plus host-tested verify logic over `rustls-webpki` seeded by `webpki-roots`,
   with chain verification proved against committed good/bad vectors and explicit
   `atEpochSeconds`. No running cap service, no socket, no key -- the lowest-risk
   real cert logic.
3. **Client TLS handshake over `TcpSocket` (Phase 2, client-only).** Done
   2026-06-08. A userspace process completes one TLS 1.3 client handshake over
   the Phase C userspace `TcpSocket` cap, validating the peer chain with the
   slice-2 verifier, with an observable local QEMU proof. The no_std
   determination selected a vendored `embedded-tls 0.19.0` client state machine
   for this local proof rather than full `rustls`.
4. **capOS-terminated Web UI endpoint (terminal consumer).** Serves the Web UI
   over capOS-held TLS as a direct-termination successor after the first GCE
   public Web UI proof closes through provider-terminated HTTPS. Deeply blocked:
   needs a `KeyVault`-issued `PrivateKey` cap and a server cert source (ACME /
   provisioned).
5. **Minimal key-custody decomposition.** Done. It decomposes the missing
   `PrivateKey` / `KeyVault` / `KeySource` subset into the three implementation
   records below, keeping production hardware/cloud custody out of the local
   TLS/ACME bootstrap.
6. **`PrivateKey` / `PublicKey` RAM signing proof.** Done 2026-06-04. Adds the
   minimal asymmetric-key ABI and host-tested RAM signing core:
   sign/public/info, public verify/export/info, purpose metadata, and no raw
   private-key export.
7. **RAM `KeyVault` custody.** Done 2026-06-05. Adds handle-based key
   generation/open/list/destroy and a local QEMU proof for TLS and ACME account
   key handles, still RAM-only and not production custody.
8. **Development-only `KeySource` bootstrap.** Done 2026-06-05. Grants local proofs a
   development software key source that mints key handles without putting raw
   private keys in manifests, images, logs, task records, or evidence, and is
   rejected for production/public profiles.
9. **ACME account/order local proof.** Done 2026-06-08. `capos-tls` now has a
   no_std+alloc ACME account/new-order/CSR-finalize/certificate-retrieval core,
   with ES256 JWS signing through `AcmeAccount` `PrivateKey` caps and CSR
   signing through a separate TLS-purpose `PrivateKey` cap. Challenge
   validation stays fake or pre-authorized here; the proof does not call Let's
   Encrypt staging or production.
10. **Scoped `http-01` solver.** Done 2026-06-09. `capos-tls` adds a bounded,
   token-scoped `Http01ChallengeSolver` and the RFC 8555 `http-01` authorization
   flow (pending order, authorization fetch, key-authorization derivation via the
   RFC 7638 account-key thumbprint, challenge response, out-of-band validation,
   and cleanup). `remote-session-web-ui` serves only
   `/.well-known/acme-challenge/<token>` for currently-published tokens through
   that same solver; retired, unknown, sub-path, and traversal tokens fail closed
   (404). The host ACME `http-01` test proves the protocol and cleanup; the Web UI
   L4 QEMU proof fetches the challenge through the served origin. It grants no
   generic route, static-file, DNS, or Web UI authority and adds no public CA
   call.
11. **`CertificateStore.watch` renewal and rotation.** Proves local renewal with
   short-lived test certificates, storing the fresh chain under a stable handle
   and rotating the Web UI TLS server without restart.
12. **Public GCE Let's Encrypt direct-termination proof.** A separately reviewed
   successor after the provider-managed first public proof. It requires a public
   DNS name controlled for the run, explicit billable/public-ingress
   authorization, and explicit authorization before any Let's Encrypt production
   call; staging remains the default external CA target.

## Let's Encrypt / ACME Public TLS Decomposition

Let's Encrypt support is implementable for the public TLS milestone only as the
capability-native, capOS-terminated successor path. It is not the already
selected closeout path for the first public GCE Web UI proof. That first proof
continues to terminate HTTPS at the GCP external load balancer with a
provider-managed certificate, no capOS private-key custody, and no raw public
HTTP closeout.

The missing prerequisites are represented as named task records:

- Minimal `PrivateKey` / `PublicKey` ABI and RAM signing proof for TLS server
  keys and ACME account keys
  ([`crypto-privatekey-publickey-ram-signing-local-proof`](../tasks/done/2026-06-04/crypto-privatekey-publickey-ram-signing-local-proof.md)).
- RAM-only `KeyVault` custody for TLS and ACME private-key handles
  ([`crypto-keyvault-ram-privatekey-custody-local-proof`](../tasks/done/2026-06-05/crypto-keyvault-ram-privatekey-custody-local-proof.md)).
- Development-only software `KeySource` bootstrap for local TLS/ACME proofs,
  rejected for production/public profiles
  ([`crypto-development-keysource-tls-acme-bootstrap-local-proof`](../tasks/done/2026-06-05/crypto-development-keysource-tls-acme-bootstrap-local-proof.md)).
- A TLS client over the userspace `TcpSocket` cap
  ([`cloud-tls-client-handshake-over-tcpsocket-local-proof`](../tasks/done/2026-06-08/cloud-tls-client-handshake-over-tcpsocket-local-proof.md)).
- Server-side TLS and `TlsServerConfig` for `remote-session-web-ui`
  ([`cloud-tls-self-hosted-webui-terminated-endpoint`](../tasks/cloud-tls-self-hosted-webui-terminated-endpoint.md)).
- An RFC 8555 `AcmeClient` account/order/finalize path against a local
  Let's Encrypt-compatible directory
  ([`cloud-tls-acme-account-order-local-proof`](../tasks/done/2026-06-08/cloud-tls-acme-account-order-local-proof.md)).
- A scoped `http-01` challenge solver under the Web UI service boundary
  ([`cloud-tls-acme-http01-challenge-solver-local-proof`](../tasks/done/2026-06-09/cloud-tls-acme-http01-challenge-solver-local-proof.md)).
- `CertificateStore.watch` renewal and TLS-chain rotation without a Web UI
  restart
  ([`cloud-tls-acme-renewal-certstore-rotation-local-proof`](../tasks/cloud-tls-acme-renewal-certstore-rotation-local-proof.md)).
- Public DNS/name control plus explicit billable/public-ingress authorization
  before a real GCE run, and explicit CA authorization before any Let's Encrypt
  staging or production request
  ([`cloud-gce-public-webui-letsencrypt-direct-termination-proof`](../tasks/on-hold/cloud-gce-public-webui-letsencrypt-direct-termination-proof.md)).

Local proofs and public CA/cloud proofs stay distinct. The ACME account/order,
challenge, and renewal slices use a local RFC 8555-compatible directory and local
QEMU/cloudboot paths. A public GCE/Let's Encrypt run requires a separately
authorized harness mode, a controlled public DNS name, public-ingress teardown
evidence, and no private key material in manifests, images, logs, task records,
or evidence directories.

## Next Gap

Slices 1 and 2 landed on 2026-06-03: `rustls-webpki` and `webpki-roots` are
vendored as static-pinned no_std+alloc snapshots, and `capos-tls` contains the
Phase 1 `Certificate` / `TrustStore` / `CertVerifier` host verifier proof over
those crates. K1 landed on 2026-06-04: `capos-tls` also contains the minimal
RAM-only P-256 `PrivateKey` / `PublicKey` signing core. K2 landed on
2026-06-05: RAM-only `KeyVault` generation/open/list/destroy handle custody for
those keys. K3 landed on 2026-06-05: local development software `KeySource`
bootstrap now mints TLS and ACME account key handles without raw private-key
material in manifests or evidence and rejects production/public profiles.
Capability-infrastructure key-cap reconciliation landed on 2026-06-06: the
minimal RAM-only `SymmetricKey` ABI and local AEAD/MAC proof now exist. Slice 3
landed on 2026-06-08: the local QEMU proof now completes one TLS 1.3 client
handshake over a userspace-served `TcpSocket` cap and validates the peer chain
with `capos-tls`. ACME slice 5 landed on 2026-06-08: `capos-tls` now proves
account registration, order creation, CSR finalize, and returned-chain parsing
against a local RFC 8555-style directory using purpose-scoped key caps. ACME
slice 6 (proposal item 10) landed on 2026-06-09: the scoped `http-01` solver now serves bounded
`/.well-known/acme-challenge/<token>` responses through `remote-session-web-ui`,
with the `http-01` authorization/validation/cleanup flow proven host-side and the
served route proven in the Web UI L4 QEMU proof. The next ACME gap is renewal and
certificate-store rotation (slice 11). The next server-side TLS behavior gap
remains the Web UI consumer, still blocked on reviewed server key custody and a
certificate source. The behavior chain then
advances slice-by-slice -- each kernel/lib-first with a local proof -- until the
Web UI consumer slice can add a separately reviewed direct-termination successor after
[`cloud-gce-public-self-hosted-webui-ingress-tls`](../tasks/on-hold/cloud-gce-public-self-hosted-webui-ingress-tls.md)
closes with provider-terminated HTTPS. The key-custody local-proof precursor is
now complete for `PrivateKey` / `PublicKey`, RAM `KeyVault`, and development
`KeySource`; production custody remains future.
