Provider docs: generic contract, spec template and appendix on the existing providers #7
@@ -4,7 +4,7 @@ Plan: [docs/plans/2026-09-16-1108-provider-docs-split.md](../plans/2026-09-16-11
|
|||||||
|
|
||||||
- [x] Step 0 — Save and commit the plan
|
- [x] Step 0 — Save and commit the plan
|
||||||
- [x] Step 1 — Write `docs/provider-contract.md`
|
- [x] Step 1 — Write `docs/provider-contract.md`
|
||||||
- [ ] Step 2 — Write `docs/provider-spec-template.md`
|
- [x] Step 2 — Write `docs/provider-spec-template.md`
|
||||||
- [ ] Step 3 — Write `docs/providers-existing.md`
|
- [ ] Step 3 — Write `docs/providers-existing.md`
|
||||||
- [ ] Step 4 — Rewrite `docs/providers.md` as the index; link edits
|
- [ ] Step 4 — Rewrite `docs/providers.md` as the index; link edits
|
||||||
- [ ] Step 5 — Verification sweep
|
- [ ] Step 5 — Verification sweep
|
||||||
@@ -63,3 +63,27 @@ own API" rather than naming the platform, so that the abstractness grep stays
|
|||||||
meaningful. The `hack/providers-dev.yaml` rule is phrased as "only if the type
|
meaningful. The `hack/providers-dev.yaml` rule is phrased as "only if the type
|
||||||
needs no credentials" because that file exists for `make run-dev` without any
|
needs no credentials" because that file exists for `make run-dev` without any
|
||||||
Secret.
|
Secret.
|
||||||
|
|
||||||
|
## Step 2 — Write `docs/provider-spec-template.md`
|
||||||
|
|
||||||
|
2026-09-16 11:28. Twenty-four entries in a fixed shape (Question, Allowed
|
||||||
|
answers, Obligations, Answer, Evidence). Thirteen of them carry an axis code
|
||||||
|
and their numbers are the ones the contract's §4.20 table points at; the
|
||||||
|
other eleven (identity, placement, image, cloud-init, machine type, config
|
||||||
|
block, Checker, concurrency, deployment, docs, accepted limits) are decisions
|
||||||
|
the contract leaves open without being a profile axis. Entries 9, 13 and 15
|
||||||
|
carry an empty table to fill in (state mapping, error classification, config
|
||||||
|
fields); entry 21 carries the contract §11 test list as checkboxes so a
|
||||||
|
filled spec doubles as the test plan.
|
||||||
|
|
||||||
|
Check that every axis code appears in the template:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
for c in $(grep -oE '^### 4\.[0-9]+ `[a-z-]+`' docs/provider-contract.md | grep -oE '`[a-z-]+`' | tr -d '`'); do
|
||||||
|
grep -q "\`$c\`" docs/provider-spec-template.md || echo "template missing $c"
|
||||||
|
done
|
||||||
|
```
|
||||||
|
|
||||||
|
Clean. Worth noting: the preamble allows "verify against the target version"
|
||||||
|
only on an Evidence line, never as an Answer, because the whole point of the
|
||||||
|
file is that the implementer does not guess.
|
||||||
|
|||||||
@@ -0,0 +1,455 @@
|
|||||||
|
# Provider spec template
|
||||||
|
|
||||||
|
Copy this file to `docs/<type>-provider-spec.md`, fill in every **Answer**
|
||||||
|
line, and hand the result to whoever implements the provider together with
|
||||||
|
[provider-contract.md](provider-contract.md) and
|
||||||
|
[providers-existing.md](providers-existing.md). An unanswered entry blocks
|
||||||
|
implementation: it is a decision the contract leaves to the provider, and the
|
||||||
|
implementer must not guess it.
|
||||||
|
|
||||||
|
Where an entry names an axis in backticks, the allowed answers are the
|
||||||
|
profiles of that axis in contract §4, and the entry number matches the last
|
||||||
|
column of the contract's §4.20 table. **Evidence** is where the answer was
|
||||||
|
confirmed: a link into the backend's API documentation, or the experiment
|
||||||
|
that was run. "Verify against the target version" is a valid interim
|
||||||
|
answer only for the Evidence line, never for the Answer.
|
||||||
|
|
||||||
|
## Header
|
||||||
|
|
||||||
|
- **Type** (the `type:` value in the providers config, lowercase):
|
||||||
|
- **Example configured name**:
|
||||||
|
- **Backend and API version this spec was written against**:
|
||||||
|
- **Client** (`vendor-sdk` with the module path, or `thin-client`):
|
||||||
|
- **Author and date**:
|
||||||
|
|
||||||
|
## 1. Identity and providerID
|
||||||
|
|
||||||
|
**Question.** What is the providerID's shape, which location parts does it
|
||||||
|
embed, and what validates the config values pasted into it?
|
||||||
|
|
||||||
|
**Allowed answers.** `<location>/<name>`, `<location>/<allocated-key>`, or a
|
||||||
|
location-free `<allocated-key>` (contract §6; required when instances can
|
||||||
|
migrate, see entry 2).
|
||||||
|
|
||||||
|
**Obligations.** Strict parsing; `ErrPermanent` for a malformed ID from `Get`
|
||||||
|
and `Delete`; a regexp on every config value that becomes an ID segment, in
|
||||||
|
`config_<type>.go`.
|
||||||
|
|
||||||
|
**Answer:**
|
||||||
|
|
||||||
|
**Evidence:**
|
||||||
|
|
||||||
|
## 2. Primary key (`primary-key`)
|
||||||
|
|
||||||
|
**Question.** Is `req.Name` the backend's key, or does the backend allocate an
|
||||||
|
identifier?
|
||||||
|
|
||||||
|
**Allowed answers.** `name-is-key`; `allocated-id`.
|
||||||
|
|
||||||
|
**Obligations.** `allocated-id`: `Create` finds an existing instance by name
|
||||||
|
before allocating; allocation is safe against a concurrent `Create` for
|
||||||
|
another Proxy (deterministic from `req.UID`, or allocate-then-verify); `Get`
|
||||||
|
and `Delete` use the allocated key; state how a collision with an instance
|
||||||
|
the operator does not own is detected and reported.
|
||||||
|
|
||||||
|
**Answer:**
|
||||||
|
|
||||||
|
**Evidence:**
|
||||||
|
|
||||||
|
## 3. Placement mapping
|
||||||
|
|
||||||
|
**Question.** What do `Placement.Region`, `Zone`, `MachineType` and `Image`
|
||||||
|
mean for this backend, which are required, which are ignored, and what
|
||||||
|
happens when a value is unknown?
|
||||||
|
|
||||||
|
**Allowed answers.** Per field: a config catalogue key, a backend identifier
|
||||||
|
passed through, or ignored (contract §2.1, MAY ignore with documentation).
|
||||||
|
|
||||||
|
**Obligations.** Unknown values are rejected with `ErrPermanent` naming the
|
||||||
|
field and value before any backend call; ignored fields are listed in the
|
||||||
|
provider's guide because they are still in the spec hash; an empty value with
|
||||||
|
a single-choice catalogue may default, and the guide says so.
|
||||||
|
|
||||||
|
**Answer:**
|
||||||
|
|
||||||
|
**Evidence:**
|
||||||
|
|
||||||
|
## 4. Image source
|
||||||
|
|
||||||
|
**Question.** Where does the boot image come from, and what does a catalogue
|
||||||
|
edit do to running instances?
|
||||||
|
|
||||||
|
**Allowed answers.** A catalogue in the config block (key to URL or backend
|
||||||
|
image ID); a backend template or image referenced directly by
|
||||||
|
`Placement.Image`; a URL fetched by the provider into the backend on first
|
||||||
|
use.
|
||||||
|
|
||||||
|
**Obligations.** If the provider fetches or converts images: streaming, no
|
||||||
|
buffering (contract §1.4), a completeness marker so a cut-off fetch is redone,
|
||||||
|
concurrency control so two Creates fetch once, and a written warning that
|
||||||
|
replacing an image in use may corrupt instances that depend on it. If the
|
||||||
|
backend owns the image: the prerequisite is documented in the guide.
|
||||||
|
|
||||||
|
**Answer:**
|
||||||
|
|
||||||
|
**Evidence:**
|
||||||
|
|
||||||
|
## 5. Cloud-init delivery
|
||||||
|
|
||||||
|
**Question.** How does `CreateRequest.CloudInit` reach the guest, byte for
|
||||||
|
byte?
|
||||||
|
|
||||||
|
**Allowed answers.** User-data metadata on the instance; a NoCloud seed
|
||||||
|
built in-process and attached as media; a file placed on the backend and
|
||||||
|
referenced from the instance config; not delivered (documented, with how the
|
||||||
|
proxy gets configured instead).
|
||||||
|
|
||||||
|
**Obligations.** Size limits of the channel stated; whether vendor-data or a
|
||||||
|
second document can ride along; the sentinel test (contract §11); the channel
|
||||||
|
must be fully reachable through the API the provider uses (no step that needs
|
||||||
|
shell access on the backend unless the spec says the provider has it).
|
||||||
|
|
||||||
|
**Answer:**
|
||||||
|
|
||||||
|
**Evidence:**
|
||||||
|
|
||||||
|
## 6. Machine type mapping
|
||||||
|
|
||||||
|
**Question.** How does `Placement.MachineType` become CPU, memory and disk?
|
||||||
|
|
||||||
|
**Allowed answers.** A catalogue of named profiles in the config block; a
|
||||||
|
backend size name passed through.
|
||||||
|
|
||||||
|
**Obligations.** A catalogue needs validation of each profile; disk size
|
||||||
|
default and its config field named.
|
||||||
|
|
||||||
|
**Answer:**
|
||||||
|
|
||||||
|
**Evidence:**
|
||||||
|
|
||||||
|
## 7. Network and IP discovery (`readiness`, `ip-source`)
|
||||||
|
|
||||||
|
**Question.** Which network does the instance attach to, where does its
|
||||||
|
address come from, how long until it is usable, and what makes it reachable
|
||||||
|
from the operator pod and from clients on `spec.port`?
|
||||||
|
|
||||||
|
**Allowed answers.** `readiness`: `immediate`; `provisioning-window`.
|
||||||
|
`ip-source`: `assigned-at-create`; `discovered` (name the mechanism: guest
|
||||||
|
agent, DHCP lease, neighbour table, and the order if several).
|
||||||
|
|
||||||
|
**Obligations.** `discovered`: what the guest must run, how it gets
|
||||||
|
installed, what happens without it; discovery failure is Provisioning, not an
|
||||||
|
error; only routable IPv4 is reported (state the filter). Reachability:
|
||||||
|
firewall or routing steps the provider performs, or the prerequisite the
|
||||||
|
guide states. Whether `Port` is used by the provider at all.
|
||||||
|
|
||||||
|
**Answer:**
|
||||||
|
|
||||||
|
**Evidence:**
|
||||||
|
|
||||||
|
## 8. GC marks and CreatedAt (`gc-mark`, `created-at`)
|
||||||
|
|
||||||
|
**Question.** Where do `LabelManaged` and `LabelUID` live, where does
|
||||||
|
`CreatedAt` come from, and which secondary resources are marked?
|
||||||
|
|
||||||
|
**Allowed answers.** `gc-mark`: `native-labels`; `written-metadata`;
|
||||||
|
`mark-window`. `created-at`: `backend-timestamp`; `written-at-create`.
|
||||||
|
|
||||||
|
**Obligations.** `mark-window`: the window's length in seconds, why it is
|
||||||
|
far below `MinAge`, and how the same Proxy's next reconcile cleans an
|
||||||
|
unmarked instance. Any value-format constraint of the backend's labels
|
||||||
|
(allowed characters, length) and how a Proxy UID fits it.
|
||||||
|
|
||||||
|
**Answer:**
|
||||||
|
|
||||||
|
**Evidence:**
|
||||||
|
|
||||||
|
## 9. State mapping (`provisioning-state`)
|
||||||
|
|
||||||
|
**Question.** How does every backend state map to `StateProvisioning`,
|
||||||
|
`StateRunning`, `StateStopped`, `StateTerminated`, and how does `Get` tell
|
||||||
|
"defined but never started" from "stopped"?
|
||||||
|
|
||||||
|
**Allowed answers.** A table of backend state (plus lock or task flags) to
|
||||||
|
provider state, with the unknown-state row mapping to `StateStopped`.
|
||||||
|
`provisioning-state`: `native`; `create-blocks`; `marker`.
|
||||||
|
|
||||||
|
**Obligations.** Running requires an IP; `marker` names what is recorded at
|
||||||
|
creation and how `Get` reads it; `create-blocks` names the cap on the wait.
|
||||||
|
|
||||||
|
**Answer:**
|
||||||
|
|
||||||
|
| Backend state | Lock or task | Provider state |
|
||||||
|
|---|---|---|
|
||||||
|
| | | |
|
||||||
|
|
||||||
|
**Evidence:**
|
||||||
|
|
||||||
|
## 10. Create: blocking and task tracking (`create-return`, `async-ops`)
|
||||||
|
|
||||||
|
**Question.** What does `Create` wait for before returning, and how are
|
||||||
|
asynchronous backend tasks tracked?
|
||||||
|
|
||||||
|
**Allowed answers.** `create-return`: `submit`; `blocking`. `async-ops`:
|
||||||
|
`none`; `task-handle`; `backend-lock`.
|
||||||
|
|
||||||
|
**Obligations.** `task-handle`: where the handle is kept and how a failed
|
||||||
|
task surfaces (in `Get`, as which class, with which message). `backend-lock`:
|
||||||
|
what `Get` and `Delete` return while locked. Every step of `Create` is
|
||||||
|
idempotent so a cut-off attempt resumes; list the steps and what each finds
|
||||||
|
on a retry.
|
||||||
|
|
||||||
|
**Answer:**
|
||||||
|
|
||||||
|
**Evidence:**
|
||||||
|
|
||||||
|
## 11. Delete and secondary resources (`delete-return`, `secondary-resources`)
|
||||||
|
|
||||||
|
**Question.** In what order does `Delete` tear things down, what does it do
|
||||||
|
when called again mid-delete, and what does `Get` return meanwhile?
|
||||||
|
|
||||||
|
**Allowed answers.** `delete-return`: `returns-early`; `waits`.
|
||||||
|
`secondary-resources`: `none`; `cascade` (name the flags set at create);
|
||||||
|
`explicit` (name each resource and how it is found by name).
|
||||||
|
|
||||||
|
**Obligations.** Idempotent at every step; "already deleting" is success and
|
||||||
|
cheap; a location no longer in the config is a logged no-op success; any
|
||||||
|
resource that can outlive the instance without being listable is a documented
|
||||||
|
GC blind spot.
|
||||||
|
|
||||||
|
**Answer:**
|
||||||
|
|
||||||
|
**Evidence:**
|
||||||
|
|
||||||
|
## 12. ListByTag scope and partial failure (`list-partial`)
|
||||||
|
|
||||||
|
**Question.** What is the full scope `ListByTag` enumerates, and what happens
|
||||||
|
when part of it is unreachable?
|
||||||
|
|
||||||
|
**Allowed answers.** `fail-whole`; `omit-unreachable`.
|
||||||
|
|
||||||
|
**Obligations.** The scope covers everything the provider can create in;
|
||||||
|
server-side filtering on the mark where the backend allows it; a single
|
||||||
|
unreadable instance may be skipped with a log line; the cost of one list at
|
||||||
|
fleet size.
|
||||||
|
|
||||||
|
**Answer:**
|
||||||
|
|
||||||
|
**Evidence:**
|
||||||
|
|
||||||
|
## 13. Error classification (`not-found`, `quota`)
|
||||||
|
|
||||||
|
**Question.** Which backend responses map to which of the four classes, and
|
||||||
|
which signal means "does not exist"?
|
||||||
|
|
||||||
|
**Allowed answers.** A table of backend status or code (with message pattern
|
||||||
|
where needed) to class. `not-found`: `status-404`; `error-code`;
|
||||||
|
`list-and-miss`. `quota`: `detected`; `absent`.
|
||||||
|
|
||||||
|
**Obligations.** One `classify`, a table test with captured real responses
|
||||||
|
for every matched message; the permission-denied-versus-quota case decided;
|
||||||
|
authentication failures, host-key or certificate failures, and cancellation
|
||||||
|
each assigned a class with a reason.
|
||||||
|
|
||||||
|
**Answer:**
|
||||||
|
|
||||||
|
| Backend response | Class | Why |
|
||||||
|
|---|---|---|
|
||||||
|
| | | |
|
||||||
|
|
||||||
|
**Evidence:**
|
||||||
|
|
||||||
|
## 14. Credentials and TLS (`credentials`)
|
||||||
|
|
||||||
|
**Question.** What credential does the operator use, where does it come from,
|
||||||
|
when is it read, and how is the backend's TLS certificate trusted?
|
||||||
|
|
||||||
|
**Allowed answers.** `mounted-files` (Secret name, mount path, file names,
|
||||||
|
`optional: true`); `environment`; `workload-identity`. TLS: `system-roots`;
|
||||||
|
`ca-file`; `insecure` (the flag's exact name).
|
||||||
|
|
||||||
|
**Obligations.** The minimum privilege set the credential needs, listed;
|
||||||
|
rotation behaviour (free, or restart needed); the sentinel test for the
|
||||||
|
credential (contract §7); the constructor never dials.
|
||||||
|
|
||||||
|
**Answer:**
|
||||||
|
|
||||||
|
**Evidence:**
|
||||||
|
|
||||||
|
## 15. Config block
|
||||||
|
|
||||||
|
**Question.** What are the fields of `<Type>Config`, their defaults, and their
|
||||||
|
validation?
|
||||||
|
|
||||||
|
**Allowed answers.** A table: field, required, default, validation, and which
|
||||||
|
identifier or path the value ends up in.
|
||||||
|
|
||||||
|
**Obligations.** Contract §10: `setBlocks`, the type allow-list in
|
||||||
|
`Config.validate` and the constructor map in `cmd/main.go`, `config_<type>.go`
|
||||||
|
with its tests, regexps for values pasted into IDs or file names.
|
||||||
|
|
||||||
|
**Answer:**
|
||||||
|
|
||||||
|
| Field | Required | Default | Validation | Ends up in |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| | | | | |
|
||||||
|
|
||||||
|
**Evidence:**
|
||||||
|
|
||||||
|
## 16. Checker
|
||||||
|
|
||||||
|
**Question.** What are the check targets, what does one check do, which
|
||||||
|
reasons can it report, and what goes into `Details`?
|
||||||
|
|
||||||
|
**Allowed answers.** One target per thing that fails independently; the
|
||||||
|
shared reasons from `internal/provider/check.go` first, provider-specific
|
||||||
|
reasons only with a stated "what the admin does differently"; `Details` keys
|
||||||
|
listed.
|
||||||
|
|
||||||
|
**Obligations.** Same credential, verb and scope as `ListByTag` and `Create`;
|
||||||
|
cheap (one page, one object); never disrupts a reconcile that shares a
|
||||||
|
connection; returns promptly on `ctx`; the `status.type` comment in
|
||||||
|
`api/v1alpha1/providerhealth_types.go` updated.
|
||||||
|
|
||||||
|
**Answer:**
|
||||||
|
|
||||||
|
**Evidence:**
|
||||||
|
|
||||||
|
## 17. Client and child spans (`client-kind`, `child-spans`)
|
||||||
|
|
||||||
|
**Question.** What talks to the backend, and how do its calls appear under the
|
||||||
|
operation span?
|
||||||
|
|
||||||
|
**Allowed answers.** `client-kind`: `vendor-sdk` (module path, and whether it
|
||||||
|
is maintained); `thin-client`; `rpc-over-ssh`. `child-spans`:
|
||||||
|
`sdk-instrumentation`; `transport-wrapper`; `span-decorator`; `none`.
|
||||||
|
|
||||||
|
**Obligations.** The seam interface's name and the fake that implements it;
|
||||||
|
`thin-client`: one error type carrying status and body, transport timeouts,
|
||||||
|
parent-gated `otelhttp`; `none` is a documented gap; the span recorder test
|
||||||
|
(contract §11).
|
||||||
|
|
||||||
|
**Answer:**
|
||||||
|
|
||||||
|
**Evidence:**
|
||||||
|
|
||||||
|
## 18. Timeouts (`timeouts`)
|
||||||
|
|
||||||
|
**Question.** What bounds each backend call, the dial, and any long step such
|
||||||
|
as a download or a wait loop, and what does a cancelled `ctx` do to a shared
|
||||||
|
connection?
|
||||||
|
|
||||||
|
**Allowed answers.** `per-call` (the budgets, per operation); `ctx-only`
|
||||||
|
(cite the client's own timeout).
|
||||||
|
|
||||||
|
**Obligations.** Contract §1.5: no caller sets a deadline; a hung call pins a
|
||||||
|
worker or stalls GC. Cancellation behaviour on a shared connection stated
|
||||||
|
(abandon the call, or close the connection).
|
||||||
|
|
||||||
|
**Answer:**
|
||||||
|
|
||||||
|
**Evidence:**
|
||||||
|
|
||||||
|
## 19. Concurrency
|
||||||
|
|
||||||
|
**Question.** What is shared between concurrent calls (connections, caches,
|
||||||
|
locks), and what happens when two calls for the same instance name overlap?
|
||||||
|
|
||||||
|
**Allowed answers.** A description of the shared state and its locking.
|
||||||
|
|
||||||
|
**Obligations.** Safe for 3 reconciles, a GC sweep and a check round at once;
|
||||||
|
two `Delete` calls for one instance overlap safely; one fetch per image per
|
||||||
|
location when several Creates race.
|
||||||
|
|
||||||
|
**Answer:**
|
||||||
|
|
||||||
|
**Evidence:**
|
||||||
|
|
||||||
|
## 20. Logging (`logging`)
|
||||||
|
|
||||||
|
**Question.** Which tiers does the provider log, with which keys on every
|
||||||
|
line?
|
||||||
|
|
||||||
|
**Allowed answers.** `tiered`; `outcome-only`; `none` (cite the client's own
|
||||||
|
logging).
|
||||||
|
|
||||||
|
**Obligations.** Logger from `logf.FromContext(ctx)` on every call; never
|
||||||
|
`CloudInit` or credentials; `provider` and the instance name on every line
|
||||||
|
that concerns an instance.
|
||||||
|
|
||||||
|
**Answer:**
|
||||||
|
|
||||||
|
**Evidence:**
|
||||||
|
|
||||||
|
## 21. Tests (`backend-test`)
|
||||||
|
|
||||||
|
**Question.** What is the fake, which contract tests exist, and how is the
|
||||||
|
provider proven against the real backend?
|
||||||
|
|
||||||
|
**Allowed answers.** `backend-test`: `cluster-e2e`; `integration-tag` (the
|
||||||
|
`<TYPE>_TEST_*` variables, the `make test-integration-<type>` target); `manual-runbook`.
|
||||||
|
|
||||||
|
**Obligations.** Every item of the contract §11 list, ticked here:
|
||||||
|
|
||||||
|
- [ ] repeat `Create`
|
||||||
|
- [ ] `Get` after `Delete`
|
||||||
|
- [ ] `Delete` twice
|
||||||
|
- [ ] malformed ID
|
||||||
|
- [ ] unknown state maps to `StateStopped`
|
||||||
|
- [ ] `StateRunning` requires an IP
|
||||||
|
- [ ] `UID` and `CreatedAt` read back
|
||||||
|
- [ ] `ListByTag` excludes unmarked instances
|
||||||
|
- [ ] `Get` during an in-progress delete
|
||||||
|
- [ ] `Get` during an asynchronous operation or lock
|
||||||
|
- [ ] never started is never `StateStopped`
|
||||||
|
- [ ] cancelled `ctx` returns promptly
|
||||||
|
- [ ] `classify` table with captured responses
|
||||||
|
- [ ] Checker reasons, expired `ctx`, stable order
|
||||||
|
- [ ] sentinel tests for `CloudInit` and the credential
|
||||||
|
- [ ] child spans under the operation span
|
||||||
|
- [ ] real-backend lifecycle test
|
||||||
|
|
||||||
|
**Answer:**
|
||||||
|
|
||||||
|
**Evidence:**
|
||||||
|
|
||||||
|
## 22. Deployment
|
||||||
|
|
||||||
|
**Question.** What changes in `config/` and the Makefile?
|
||||||
|
|
||||||
|
**Allowed answers.** The list: the `optional: true` mount in
|
||||||
|
`config/manager/manager.yaml`; the commented entries in
|
||||||
|
`config/manager/providers_config.yaml` and
|
||||||
|
`config/samples/providers-config.yaml`; `config/samples/proxy_<type>.yaml`
|
||||||
|
with a cloud-init that installs a proxy on the sample image; a Makefile
|
||||||
|
helper for the Secret; RBAC markers if the provider talks to the cluster's
|
||||||
|
own API; whether `hack/providers-dev.yaml` gets an entry.
|
||||||
|
|
||||||
|
**Answer:**
|
||||||
|
|
||||||
|
**Evidence:**
|
||||||
|
|
||||||
|
## 23. Docs
|
||||||
|
|
||||||
|
**Question.** Which documents are written or updated?
|
||||||
|
|
||||||
|
**Allowed answers.** `docs/<type>-provider.md` with its section list; the row
|
||||||
|
and section in `providers-existing.md`; the `architecture.md` rows (components
|
||||||
|
table, §5, §11, and §10 if spans are added); the README row; the
|
||||||
|
`docs/testing.md` section; the `CHANGELOG.md` entry after confirmation.
|
||||||
|
|
||||||
|
**Answer:**
|
||||||
|
|
||||||
|
**Evidence:**
|
||||||
|
|
||||||
|
## 24. Known limits accepted at design time
|
||||||
|
|
||||||
|
**Question.** Which of the contract's §13 limits bite this provider in
|
||||||
|
practice, and which new gaps does this design accept?
|
||||||
|
|
||||||
|
**Allowed answers.** A list, each with the consequence for an operator and
|
||||||
|
the workaround.
|
||||||
|
|
||||||
|
**Answer:**
|
||||||
|
|
||||||
|
**Evidence:**
|
||||||
Reference in New Issue
Block a user