Use case documentation¶
Situation¶
The kerbside docs are reference-heavy: installation.md,
configuration.md, and console-sources.md document the
knobs, and the spice/ tree documents the protocol. What
is missing is use case documentation — a clear page per
deployment permutation that says "this is the value
proposition for this type of deployment, this is how it
works, this is how to set it up". The value-proposition
material that exists today is scattered through
docs/index.md's introduction (the broker model, the
OpenStack spice-direct story, the Bumblebee comparison)
rather than organised by the decision a prospective
operator is actually making.
Identified during two-tier CI planning (PLAN-two-tier-ci.md, 2026-08-02); tracked here as a standalone plan because the suite is broader than that plan's mission.
Mission¶
One page per deployment permutation, each following the same structure:
- Value proposition — who this deployment is for and what kerbside adds over the platform's native console story.
- How it works — the broker/token/connection flow for this platform, with a diagram.
- How to set it up — platform-side configuration, kerbside-side configuration, network prerequisites, and a pointer to a worked deployment (CI ansible or kerbside-patches) where one exists.
- Status and limitations — what is proven, what is experimental, what is not yet implemented.
Proposed pages:
| Page | Notes |
|---|---|
| Shaken Fist VDI | Broker embedded in SF; Ed25519 VDI console tokens (PLAN-kerbside-vdi-tokens.md); the sf-e2e lane is the worked example |
| OpenStack | Nova 2025.1 spice-direct; Kolla-Ansible deployment via kerbside-patches; much of docs/index.md's OpenStack section moves here |
| oVirt | Front-door architecture per PLAN-two-tier-ci.md; written by that plan's phase 4 as the FIRST page, establishing the format |
| Multi-cloud aggregation | One kerbside brokering several sources at once — the distinctive value proposition. Resurveyed 2026-09-22 and corrected: it is no longer one sentence. It is the docs/index.md Use Cases row plus a "One entry point across clouds" bullet on each of the three cloud pages — ovirt.md:40, shakenfist.md:63 and openstack.md:65 — and the last of those has grown to nine lines carrying the substantive material phase 2 found: several OpenStack clouds may be configured at once, a presented token is offered to each in sources.yaml order until one validates it, and the coupling that follows. The page therefore decides which of four places owns each fact rather than writing on a blank sheet. Covers the consequences: users keep one console entry point while workloads move between providers (cloud migration without retraining or re-plumbing client access), and multiple clouds in different regions present as a single VDI estate |
| Placement topologies | The inverse of aggregation: kerbside instances placed by user population rather than by cloud — e.g. a kerbside per regional office, close to its users, so SPICE over the WAN is exactly the kerbside-to-hypervisor backend leg: firewall-inspected, audited, a single controllable egress point at the office edge, and — conditionally — TLS'd. Corrected 2026-09-22, having said "TLS'd (with host-subject pinning)" unconditionally: rust/kerbside-proxy/src/backend.rs:92 dials the insecure port first and escalates only when the hypervisor rejects plaintext with NEED_SECURED and a secure port is configured, and :198-211 maps an empty host_subject or ca_cert to None, so pinning happens only when the source supplied a subject. OpenStack never does — kerbside/api.py:665-671 is the only add_console() on that path and passes neither field. Multiple kerbsides against one cloud is natural for scraped sources (SF, oVirt); the OpenStack flow assumes one kerbside URL per Nova deployment, so per-group placement there needs the broker to route — document as a caveat |
| Standalone / static source | The static driver (kerbside/sources/static.py) for labs, demos, and direct-qemu style fleets. docs/installation.md owns the demo mechanics — the commands, in order, with their real output — per PLAN-demo-install.md decision 2, delivered 2026-08-22 as that plan's phase 5 (docs/installation.md "Try it: the demo stack"). This page owns the framing: why you would run a static source, how it works, what it cannot do, linking to the installation demo rather than restating it |
| Proxmox | Deferred until the source exists; the design record is PLAN-proxmox-source.md, whose phase 6 is this page |
docs/index.md's introduction slims down to the generic
broker model and links to these pages; the pages join the
Operator Documentation section of the index. README.md is
only touched if the curated doc links change (per the
readme-discipline policy).
Status¶
All six writable pages exist. The oVirt page landed
2026-08-10 as PLAN-two-tier-ci.md phase 4's deliverable, and
settles the format; shakenfist.md followed 2026-09-18 as
phase 1 (2f0e526), openstack.md 2026-09-20 as phase 2
(a7df5e5), standalone.md 2026-09-21 as phase 3
(28efa6c), and multi-cloud.md with placement.md
2026-09-22 as phase 4 (8c5c042). All six carry identical
section headings, so the format is a convention rather than
a coincidence. Phase 5, the index slim-down and closeout,
landed 2026-09-24 (073603b), and phase 6, the push audit,
completed on 2026-09-26. The plan is complete. Proxmox
is still blocked and still has no source driver
(kerbside/sources/ holds base.py, ovirt.py,
shakenfist.py and static.py and nothing else, rechecked
2026-09-26); it was never a phase of this plan and does not
hold it open.
One fact about the backend leg cost four phases to settle
and is now guarded rather than remembered. Phases 1, 2 and 3
each stated backend TLS or host-subject pinning more
strongly than rust/kerbside-proxy/src/backend.rs supports,
and each was corrected at review. Phase 4 stopped correcting
instances and swept the class: six pages had it wrong, the
sixth (docs/proxy-architecture.md) is filed as #472, and
tools/check-backend-tls-claims.py now fails CI on an
unconditional claim in docs/use-cases/ or the Use Cases
table. A page in this plan may not say the leg is encrypted
or pinned without saying when.
A third thing landed since this plan was written, and the
plan did not know it: the index scaffolding already
exists. docs/index.md carries a ### Use Cases heading
with a seven-row table — every proposed page including
Proxmox — each with a description and a "Tested in Kerbside
CI" column, and the note that scenarios without a link are
planned rather than written. Each page phase therefore
links an existing row rather than adding one, and must
agree with that row's description and CI claim or change
it.
Two things it decided that the rest should follow:
- The pages live in
docs/use-cases/, not flat indocs/. Seven pages would have buried the reference material;docs/spice/anddocs/plans/set the subdirectory precedent. - They are indexed under their own "Use Cases" heading
in
docs/index.md, listed before Operator Documentation, rather than joining the Operator section as this plan originally proposed. A prospective operator reads "is this for me?" before "what are the config keys?".
One thing worth imitating: the oVirt page's "Status and limitations" section is a table of what is not proven, each row naming why. That is more useful than a prose paragraph and much harder to let quietly rot, because a row either still applies or gets deleted.
Execution¶
Promoted from a standalone plan on 2026-09-18, when phase 1
was planned: six remaining pages cannot be tracked by a
single status cell. Promotion brings the
plan-push-audit-phase obligation from PLAN-TEMPLATE.md
with it, which is phase 6 and is not optional. Because that
audit runs over the accumulated diff of every phase, each
row records the merge commit that landed it as it lands —
the range is not reliably reconstructable afterwards.
| Phase | Plan | Status | Merged |
|---|---|---|---|
| 1. Shaken Fist | PLAN-use-case-docs-phase-01-shaken-fist.md | Complete | 2f0e526 |
| 2. OpenStack | PLAN-use-case-docs-phase-02-openstack.md | Complete | a7df5e5 |
| 3. Standalone / static source | PLAN-use-case-docs-phase-03-standalone.md | Complete | 28efa6c |
| 4. Multi-cloud aggregation and placement topologies | PLAN-use-case-docs-phase-04-multi-cloud.md | Complete | 8c5c042 |
| 5. Index slim-down and closeout | PLAN-use-case-docs-phase-05-index-slimdown.md | Complete | 073603b |
| 6. Push audit | PLAN-use-case-docs-phase-06-push-audit.md | Complete |
The oVirt page is not a phase: it landed 2026-08-10 as
PLAN-two-tier-ci-phase-04-docs.md's deliverable. That plan
predates the plan-push-audit-phase shared block, carries
neither the phase nor a Merged column, and is already
Complete; by the block's own rule such a plan is not
reopened to acquire one. The page's creation is therefore
push-audited nowhere, which the block permits rather than
forbids. What phases 1 to 5 changed in the page is in this
plan's audit range, and is audited here.
Proxmox is not a phase either. It stays deferred until a source driver exists, and acquires a phase then.
Phases 2 to 4 group the remaining five pages. OpenStack
and the static source each get their own phase because
each has a reference page and a worked example to reconcile
with; multi-cloud aggregation and placement topologies
share one because they are the same architectural argument
read forwards and backwards, neither has CI coverage, and
writing them apart would duplicate the reasoning. Phase 5
is the index work the Mission describes — slimming the
introduction once the OpenStack page exists to receive
### Implementation in OpenStack and ### What About
Bumblebee? — plus the README collapse that phase 1's risk
table flags: one link to the Use Cases section rather than
a bullet per page.
Phase 6 — push audit. Work through PUSH-AUDIT.md over
the accumulated diff of phases 1 to 5, deriving the range
from the merge commits above with
tools/audit/plan-range.sh, which gives
2f0e526^1..073603b over 31 paths. The diff is not
documentation-only, and the audit is not vacuous: it carries
758 lines of Python that did not exist before this plan, the
docs_checks CI job, and a change to
kerbside/sources/static.py, so every judgment agent in the
runbook has material.
Phase 6 findings¶
Run 2026-09-26. No blocking findings, and no security finding above LOW. Wave 1 failed once on a real defect and passed after it was fixed; all five judgment agents ran and each reported a result for every class in its brief.
Five items were fixed in the audit's own pull request. Two
were substantive. Phase 4 shipped two reporting CLIs
(tools/check-backend-tls-claims.py,
tools/mutate-backend-tls-claims.py) without the
audit-allow-print marker that tools/check-pypi-storage.py
already establishes for exactly that shape, which is what
made wave 1 fail. And the mutation tester rewrites the
tracked guard in the working tree for the whole of its run,
where its restore covered KeyboardInterrupt but not
SIGTERM — a kill or a closed terminal left a weakened CI
guard behind. Both are fixed. The other three were a missing
containment comment the path-traversal-review block asks
for by name, nine double-quoted literals, and three lines
over 80 columns.
Three findings were out of this plan's range and were filed
rather than fixed: #488, the wave 1 flake8 gate ignoring
AUDIT_RANGE and passing vacuously; #490, nothing in CI
validating the docs/index.md#use-cases anchor that
README.md and ARCHITECTURE.md both now depend on; and
#491, plan-range.sh sweeping unrelated commits into an
audit. One finding was declined in writing — the guard's
mutation coverage is partial, and the reason it is
proportionate rather than a gap is recorded in the phase
plan's Outcome.
The durable result is #491, and it is the kind of thing only
an accumulated audit finds. Because plan-range.sh unions
the files each merge touched and then diffs one contiguous
range across them, the issue #132 secret-redaction commits —
in none of this plan's pull requests — added 188 lines to
kerbside/tests/unit/test_db.py that the audit read as this
plan's work. Three judgment agents reviewed them as such;
one noticed and said so. The full account is in the phase
plan.