ProjectKILN
Sheet1 OF 7
Rev78e0a2a

A request goes in.A hardened resource comes out.

A developer's request is policy-checked, provisioned, canary-delivered and chaos-tested without a ticket, and every step lands on a hash-chained audit log.

Provisioning a standard Postgres: 11s p50, 16s p95, n=10. The status quo, a Terraform pull request with human review, waits hours to a day.

Subsystems

Pick a block. Each sheet shows the stack it runs on, the problem it had to solve, the custom resource or contract it owns, the decision record that settles it, and the number it produced in the validation week.

GitOps and policy

Turns a claim into real resources, after the org's rules have said yes.

  • Crossplane v2
  • ArgoCD
  • Kyverno
  • CEL
  • Terraform
  • A developer asks for a standard Postgres and never names an instance class, backup retention or network placement. Those are platform defaults, with a custom tier as the escape hatch.
  • Rules are fail-closed validating policies at admission. A denied claim leaves nothing on the cluster and a POLICY_DENY row in the audit log.
  • ArgoCD heals drift on anything stateless and only flags it on anything stateful, so a live database is never reverted without a human.

In the validation week

32 ms

to deny a claim over the storage ceiling. Nothing reached the cluster.

DatabaseClaim and the rule that denied one

apiVersion: platform.internal/v1alpha1kind: DatabaseClaimmetadata:  name: checkout-db  namespace: team-checkoutspec:  parameters:    tier: standard          # standard | custom    storageGB: 500          # the validation week's injected violation    tags:      team: checkout      costCenter: eng-platform# gitops/policies/databaseclaim-org-rules.yaml- expression: object.spec.parameters.storageGB <= 100  message: "POLICY_DENIED rule=storage-ceiling: spec.parameters.storageGB must be at most 100"
ProjectKILN
TitleSubsystems
Sheet2 OF 7
Drawn byGo, Java, Crossplane

Mechanisms

Not animations of the idea. The hash rule, the scoring rule and the blast-radius rule below are the platform's own, running in this page.

Test sheet: break the audit chain

Every row's hash covers its content and the previous row's hash. Change a field and the row fails verification. Rewrite its stored hash too, the way a careful intruder would, and the next row fails instead.

Edit any actor or outcome. Every hash is recomputed here, with the service's rule.

  1. seq 1PROVISION_REQUESTDatabaseClaim/dev03/dev03-db
    prev…stored…recomputed…
  2. seq 2PROVISIONTenantDatabase/dev03/dev03-db
    prev…stored…recomputed…
  3. seq 3SCHEDULEPod/dev03/dev03-db-0
    prev…stored…recomputed…
  4. seq 4DEPLOYCanaryRollout/dev03/dev03-svc
    prev…stored…recomputed…
  5. seq 5ROLLBACKCanaryRollout/dev03/dev03-svc
    prev…stored…recomputed…

GET /v1/audit/verify

computing…

Calc sheet: score a placement

50 × cost + 30 × fragmentation + 20 × preemption, on four nodes carrying the placement contract. A latency-sensitive pod never sees the spot nodes: they are filtered before scoring runs.

kiln.platform.internal/workload-class

cpu request 1.0

  1. worker-aon-demand, $0.096/h, 1.2/4 cpu
    50 × cost1.00
    30 × fragmentation0.55
    20 × preemption1.00

    86.5

  2. worker-bspot, $0.037/h, 0.4/4 cpu, risk 0.05

    filtered before scoring: workload-class filter

  3. worker-con-demand, $0.170/h, 5.6/8 cpu
    50 × cost0.00
    30 × fragmentation0.82
    20 × preemption1.00

    44.8

  4. worker-dspot, $0.065/h, 4.4/8 cpu, risk 0.12

    filtered before scoring: workload-class filter

the SCHEDULE event this placement publishes

{"action":"SCHEDULE","details":{"outcome":"Bound","node":"worker-a","workloadClass":"latency-sensitive"}}

Plan: cap the blast radius

The agent floors the percentage to whole pods from its own read of the cluster, and rejects a cap that floors to zero rather than rounding up. Faulted pods are hatched, as a section cut would be.

pods matching app=checkout-service: 7

maxReplicaPercentage: 30

floor(7 × 30%) = 2 pods faulted, deterministically, from the agent's own read of the cluster. The other 5 keep serving.

ProjectKILN
TitleMechanisms
Sheet3 OF 7
Drawn byThe platform's rules

Injected failures

During the validation week one identity claimed too much storage, one shipped a bad version, and one ran a full network partition. Each guardrail fired, and each timing was read from audit rows and cross-checked on the cluster in run 34085396203.
  1. Oversized claim

    500 GB against a 100 GB ceiling. Denied at admission; the claim never reached the cluster.

    0 ms25 ms50 ms75 ms100 msdenied at 32 ms
  2. Bad deploy

    A version answering 30% of requests with 500. Rolled back on the mesh, measured from the first traffic split.

    0 s15 s30 s45 s60 srolled back at 50 s
  3. SLO breach under chaos

    A full network partition against a 20% error bound. Aborted, and the iptables rule was gone from the node one second later.

    0 s10 s20 s30 saborted at 25 sfault gone at 26 s
ProjectKILN
TitleInjected failures
Sheet4 OF 7
Drawn byTestPhase7Validation

Invariants

Guarantees that hold structurally, not by convention. Each one is settled by an accepted decision record; records are immutable, and a change means a new record that supersedes it.
  • Org rules are fail-closed Kyverno policies evaluated at admission, before anything is provisioned.

    Decision record 0006
  • Every resource the operator creates carries an owner reference to its custom resource, so nothing outlives it.

    Decision record 0004
  • The chaos agent re-derives the blast radius from its own cluster read, and a fault reverts on a lease dead-man switch if the controller disappears.

    Decision record 0015
  • A resilience score is SLO headroom plus recovery, reported only for a fault confirmed to have landed. A run that tested nothing never reads as a pass.

    Decision record 0016
  • Audit publishing never blocks a reconcile. A Kafka outage stalls no provisioning, rollout or revert, and a dropped publish is counted, not lost.

    Decision record 0017
  • The audit service alone computes the hash chain, under a single write credential no other subsystem holds.

    Decision record 0018
  • The operator holds create-only access to secrets.

    Decision record 0019

The platform does not know, and does not need to know, whether a person or an AI agent submitted the request. An agent gets the same JSON contract, the same bearer token, the same policy gate before anything is provisioned and the same hash-chained audit row as a developer at a keyboard. That is what makes agent-submitted infrastructure safe to allow: the guardrails are in the structure of the platform, not in the judgement of the requester.

ProjectKILN
TitleInvariants
Sheet5 OF 7
Drawn bydocs/decisions

Validation

Ten developer identities, one simulated week compressed into twenty minutes, three injected failures. The table is the run's own artifact, verbatim; this page fails its build if the two ever differ.
Request typeBaseline (status quo)p50p95nError rateGuardrail
Provisioning (standard Postgres)Manual Terraform PR with human review: hours to a day before merge and apply.11s16s100.0% (0/10)
Scaling (storage growth)Manual Terraform PR with human review: hours to a day before merge and apply.49 ms140 ms200.0% (0/20)
Healthy deploy (canary promoted)Manual on-call detection of a bad deploy (minutes to tens of minutes), manual rollback.2m14s2m30s290.0% (0/29)
Bad deploy (injected regression)Manual on-call detection of a bad deploy (minutes to tens of minutes), manual rollback.50s50s10.0% (0/1)auto-rollback fired 1/1
Chaos test (pod-kill, completed)Zero pre-production resilience coverage; failure modes discovered during real incidents.46s52s190.0% (0/19)
Chaos test (injected SLO breach)Zero pre-production resilience coverage; failure modes discovered during real incidents.25s25s10.0% (0/1)auto-abort, fault removed on the node fired 1/1
Policy violation (storage over the ceiling)Manual Terraform PR with human review: hours to a day before merge and apply.32 ms32 ms10.0% (0/1)policy denial fired 1/1
Audit query (actor, time range)Manual compliance log reconstruction across disparate systems, commonly a multi-day effort at audit time.10 ms108 ms100.0% (0/10)

201 audit rows in 23m13s of wall clock, 176 events acknowledged by Kafka, 0 publish failures, chain intact. Run 34085396203 on commit 78e0a2a.

ProjectKILN
TitleValidation
Sheet6 OF 7
Drawn bydocs/METRICS.md

Second pass

The validation week is one run on one cluster. A second pass put the two headline claims against a public workload, the scheduler binary, traffic the decision rule had never seen and a thousand concurrent rollouts, and wrote down where each holds and where it does not. Every figure here is read from METRICS.md the same way the table above is; the commands that reproduce them are in the README.

Calc sheet: the scheduler on a public workload

The first 93.5 minutes of the Google 2011 cluster trace: 12,477 machines, 57,012 placements, synthetic spot labels on half the machines. Once through the plugin's scoring function as a model, once through kube-scheduler itself on an envtest API server, with the default profile and the kiln profile as the config declares them. An empty cluster, so every idle machine can be released.

PlacementBilled $, model / binaryvs default, model / binaryLatency-class on spot, model / binaryMachines touched, model / binary
default profile723.06 / 713.29249 / 25712,403 / 12,466
kiln profile59.56 / 65.51-91.8% / -90.8%0 / 02,104 / 2,253

The binary agrees with the model on the bill to within a few percent and on the class guarantee exactly. On the cluster as the trace found it, already 92.3% requested and carrying 132,982 tasks, the model bills $1329.75 for both profiles: no machine ever empties, so placement alone saves nothing. What holds in both scenarios is the guarantee, 0 production-priority tasks on reclaimable capacity against 263 for an economics-blind placement. The binary did not finish the full cluster, so that row stands as the model's only; the full tables say so.

Test sheet: the canary decision against two other rules

The sequential test at its defaults, a consecutive-breach threshold (the shape Flagger and Argo Rollouts ship) and a multi-window burn-rate alert (the shape the SRE Workbook gives), on the same seeded traffic, the alternatives tuned to the same false-rollback ceiling. Each cell is detection from onset, p50 / p95, and the share of regressions that promoted anyway.

DetectorWorst false rollbackStep to 30%Step to 2x the limitRamp over 8 windowsLatency tail
sequential test + CUSUM (this controller)ADR-0014 defaults2.8%30s / 30s, 0.0%1m15s / 2m30s, 0.0%1m45s / 2m0s, 0.0%30s / 45s, 0.0%
threshold, N consecutive breacheslimit x1.5, 4 consecutive2.0%45s / 45s, 0.0%1m15s / 2m45s, 6.6%1m45s / 2m30s, 0.0%45s / 45s, 0.0%
multi-window multi-burn-rateburn x1.25 (18.0/7.5/1.2)1.8%15s / 15s, 0.0%3m0s / 3m0s, 2.0%3m0s / 3m0s, 0.0%3m0s / 3m0s, 0.0%

Then 21 traffic classes, 12 of them new, split in two: each alternative tuned on one half and scored on the other, the sequential test untuned. Where it loses:

  • 99.3% false rollbacks at 5 rps, every one as Inconclusive. The 500-request sample gate outlasts the step deadline at that rate, and the controller does not derive either field from the traffic it sees. A spec mismatch, named as one.

  • 7.5% false rollbacks on retry storms, against the 5% it promises. Correlated bursts break the independence the likelihood ratio assumes.

  • 27.9% of heavy-tailed regressions missed, against the 10% it promises. The burn-rate alert misses 42.4% and the threshold 97%: everyone loses on that traffic, the sequential test least.

  • 15 s against 30 s on a flagrant step, the burn-rate alert's win, one window against the three the evidence cap needs.

Every tuning point, with intervals, and the trade-off plot: held-out evaluation.

Load sheet: a thousand rollouts at once

N concurrent CanaryRollouts through the reconciler on an envtest API server. As shipped, the manager had controller-runtime's default client budget, 20 requests per second with a burst of 30, and one worker, because nothing had set either. The fix is three flags: the client budget and the reconcile concurrency.

RolloutsConfigEvery rollout promoted inPromotedReconcile p50 / p99Analysis tick late, p50 / p99 / maxController writes/s
500as shipped1 worker, 20/30 qps/burst9m21s500 of 50098ms / 155ms35s / 35s / 36s33.8
1,000as shipped1 worker, 20/30 qps/burst12m39s, timed out0 of 1,000100ms / 135ms85s / 85s / 86s33.3
500fixed8 workers, 100/200 qps/burst2m39s500 of 50014ms / 122ms0s / 1s / 2s151.7
1,000fixed8 workers, 100/200 qps/burst3m58s1,000 of 1,00081ms / 160ms5s / 10s / 10s193.2

Lateness in a canary controller is risk: a regression that should roll back in 30 s rolls back while the queue drains. The fix moves the wall rather than removing it; at a thousand rollouts the status patches alone reach the new budget. Next in line, measured: one live read of the VirtualService per reconcile, because unstructured reads bypass the cache, and Events at a quarter of the budget. Per-verb request rates.

Revision note: the proof that never ran

The durable-outbox proof kills every controller, repeatedly and without grace, through a burst of requests, and requires each transition to land exactly one audit row with the chain intact.

It failed on every nightly for 29 days after it was pushed, on a precondition the harness asserted instead of waiting for, and nothing alerted. An audit of every claimed number found the streak, the harness now waits for its own precondition, a red nightly opens an issue, and the proof passed in run 38176386056 on 2026-10-11. The postmortem is blameless and names its action items; the audit itself and the second pass are methods in TESTING.md.

ProjectKILN
TitleSecond pass
Sheet7 OF 7
Drawn byGoogle trace, envtest