An illustrative flow based on the Platform Mesh showroom — a provider publishes an API through kcp, a subscriber binds to it and orders a capability — written down as the business facts each of the three parties records at each step. The 32 synthetic sample events below were replayed into four NEO edge instances in our lab. They were not captured from a SAP installation.
The existing sample files are preserved. For complete teardown, failed provisioning and metering differences, use the extended lifecycle explorer. Its 30 new fixture events are separate from this 32-event historical run.
Sample objects are illustrative, not deployable manifests. They contain synthetic identifiers, abbreviated hashes and selected status fields. Use the pinned upstream showroom installation for runnable resources.
kcp holds technical resource facts: an APIExport makes an API available; an APIBinding enables access in a workspace; an instance expresses a request and Ready reports resource readiness. Commercial terms, delivery acceptance and billing are separate business records. Each party records every fact it took part in, in its own book at its own site — and a fact with two parties leaves two records that carry the same digest. In a connected deployment, each nonempty period produces a 32-byte commitment payload. A verifier needs the disclosed record and its independently verified inclusion proof to compare statements without opening the entire book. This historical replay did not include a real rail.
root
Proposed collection point: kcp's API-server audit backend (a webhook) → an adapter → the audit SDK.
root:providers:private-llm
Proposed collection point: the provider's operator emits at each reconcile outcome (the audit SDK).
root:providers:chat-ui
Proposed collection point: the provider's operator emits at each reconcile outcome (the audit SDK).
root:orgs:demo:tutorial
Proposed collection point: a read-only watcher in the subscriber's own workspace (its bindings and instances).
The objects and names are the showroom's (the local Platform Mesh MSP demo): the exports llm.privatellms.msp and ui.privatellms.msp, the org demo with the account tutorial, the bindings llm-binding and chat-ui-binding. Uids, cluster names and identity hashes are sample values.
| step · what happens in kcp | service provider's book | platform provider's book | subscriber's book |
|---|---|---|---|
| 1 · A service is publishedThe provider's API becomes an offering: its schemas and an APIExport in the provider's workspace; kcp gives the export its identity.APIResourceSchema, APIExport (provider workspace) | audit.service.publish (Private LLM)audit.service.publish (Chat UI) | audit.catalog.listaudit.catalog.list | — |
| 2 · A subscriber joinsAn organisation and an account are created; the account is a workspace of its own.Account ×2 → workspace root:orgs:demo:tutorial | — | audit.account.createaudit.account.create | audit.account.create |
| 3 · The subscriptionThe subscriber binds to the export and accepts the provider's permission claims; kcp authorises the bind and marks the binding Bound. This is technical API access; commercial terms require a separate agreement.APIBinding llm-binding (subscriber workspace) | audit.contract.agreement (Private LLM) | audit.door.decision | audit.contract.agreement |
| 4 · A capability is orderedThe subscriber creates an instance of the bound API; the provider's operator provisions it on the provider's own cluster and reports Ready.LLMInstance demo-llm | audit.workload.start (Private LLM) | audit.door.decision | audit.instance.create |
| 5 · A credential is issuedThe subscriber asks for a token; the provider writes a Secret into the subscriber's workspace under the accepted claim.APITokenRequest → Secret demo-llm-token-token | audit.token.issue (Private LLM) | audit.claim.use | audit.token.request |
| 6 · A second provider joins the chainThe subscriber binds to the Chat UI export and orders a chat front-end that uses the first provider's credential; the second provider reads that Secret under its own claim.APIBinding chat-ui-binding, ChatUIInstance demo-chat | audit.contract.agreement (Chat UI)audit.workload.start (Chat UI) | audit.door.decisionaudit.claim.use | audit.contract.agreementaudit.chatui.create |
| 7 · A day of operationThe provider measures what it delivered; the subscriber measures what it received; the subscriber scales the instance.LLMInstance replicas 1 → 2; the day's SLA and usage | audit.workload.scale (Private LLM)audit.contract.sla (Private LLM) | — | audit.instance.scaleaudit.contract.sla |
| 8 · The endThe instance is deleted, the binding removed, and each side states the week from its own records.delete LLMInstance, delete APIBinding | audit.workload.end (Private LLM)audit.contract.end (Private LLM)audit.contract.week (Private LLM) | — | audit.instance.deleteaudit.contract.endaudit.contract.week |
Highlighted: the records that carry the subscription's digest — the same 32 bytes in the three books. The event names follow the audit-logging signal's form (audit.*, with the actor, the action, the outcome and the target as attributes). Six of them have their own code at the edge today (audit.contract.agreement, audit.door.decision, audit.workload.start / .end, audit.contract.sla, audit.contract.week); the others are filed as general audit events — their names are local proposed conventions, not a claim of standardised KCP business events.
When the binding becomes Bound, both sides see the same facts in kcp: the export and its identity, the subscriber's workspace, the claims it accepted, the resources bound. Written in one canonical form, their SHA-256 is the 32 bytes each party's record carries.
{
"kind": "platform-mesh.subscription.v1",
"export": {"path": "root:providers:private-llm", "name": "llm.privatellms.msp", "identityHash": "6aedce73259b9202790d4f502a37577673d4e7f830fe22782e1a277e99eb3ea0"},
"consumer": {"workspace": "root:orgs:demo:tutorial", "cluster": "5t8r3p1y6u2i7o4w"},
"binding": {"name": "llm-binding", "uid": "36adc41e-a627-5047-9bdd-5ec8ca6f6904"},
"permissionClaims": [
{"group": "", "resource": "secrets", "verbs": ["*"], "selector": {"matchAll": true}, "state": "Accepted"},
{"group": "", "resource": "namespaces", "verbs": ["*"], "selector": {"matchAll": true}, "state": "Accepted"},
{"group": "", "resource": "events", "verbs": ["*"], "selector": {"matchAll": true}, "state": "Accepted"}
],
"boundResources": [
{"group": "llm.privatellms.msp", "resource": "llminstances", "schema": "v1a2b3c4d.llminstances.llm.privatellms.msp"},
{"group": "llm.privatellms.msp", "resource": "apitokenrequests", "schema": "v1a2b3c4d.apitokenrequests.llm.privatellms.msp"}
],
"boundAt": "2026-09-30T09:03:12Z"
}
sha256(canonical form) = 66ba9ca6470b7f3566447b84cf13a3599cd61570f15f0fc0efbf736466c49e41| book | event | actor | record id | booked as | record hash |
|---|---|---|---|---|---|
| Subscriber | audit.contract.agreement | user:tutorial@example.com | binding:36adc41e-a627-5047-9bdd-5ec8ca6f6904 | record 2, code 21 | 81b9e4627ac35e4e… |
| Platform provider | audit.door.decision | system:kcp:authorizer | binding:36adc41e-a627-5047-9bdd-5ec8ca6f6904:admit | record 5, code 20 | 709ce5932a7263c3… |
| Service provider A | audit.contract.agreement | system:private-llm:controller | binding:36adc41e-a627-5047-9bdd-5ec8ca6f6904 | record 2, code 21 | a8fb2e69280093f0… |
Three generated records carry the same technical subscription digest. This replay checks local recording and digest consistency; it does not demonstrate source authentication or rail finality. In a connected installation, source signatures and verified inclusion proofs support comparison of the disclosed records. Matching digests establish matching content, not truthful metering, commercial acceptance or a dispute ruling. Later events refer to the subscription digest; a separate signed terms document supplies the business agreement.
apiexports, apibindings, accounts, the providers' resources, the claimed secrets — to a small adapter that emits them through the audit SDK.The commitment payload is 32 bytes; the existing light33 message adds one flag byte. Transport, retries and proof traffic are additional. A collection adapter must preserve actor identity and exclude Secret values. These taps were not exercised by this replay.
37790d2bd518c393de5d53a85138d82a75e02687ddcbbef04134d192d4bd757d91fe2567ef3657f6d007e70fc374e289c86a299fa0b6eb0b437f45b0a2fc72b5745c77fa8b07b201a2376cf2bdc758dfd701feabdfd234cfa6265bf5efee1b0e85f54e6d8db4081b500b01a6dcbffe053abcc0d050168d260a4c3d022e7ea54dThe 32 events of this page were sent to four NEO edges in our lab on 2026-10-01 14:13:05 UTC (one edge per party, the edge core of the pilot). Every record's hash at the edge is the one computed from the event beforehand (all 32 as predicted); each edge closed its minute and offered one commitment to a test double; a retry of the first event was answered 200 and made no second record. The lab had no real rail behind it; these commitments are not sealed. Event timestamps span 30 September to 7 October, but all events were replayed on 1 October. This is not a week-long run. No end-to-end finality latency is established by this replay.
In root:providers:private-llm — Service provider A:
apiVersion: apis.kcp.io/v1alpha2
kind: APIExport
metadata:
name: llm.privatellms.msp
spec:
resources:
- {group: llm.privatellms.msp, name: llminstances, schema: v1a2b3c4d.llminstances.llm.privatellms.msp, storage: {crd: {}}}
- {group: llm.privatellms.msp, name: apitokenrequests, schema: v1a2b3c4d.apitokenrequests.llm.privatellms.msp, storage: {crd: {}}}
permissionClaims:
- {group: "", resource: secrets, verbs: ["*"]}
- {group: "", resource: namespaces, verbs: ["*"]}
- {group: "", resource: events, verbs: ["*"]}
status:
identityHash: 6aedce73259b9202790d4f502a37577673d4e7f830fe22782e1a277e99eb3ea0In root:orgs and root:orgs:demo — Platform provider / the subscriber:
apiVersion: core.platform-mesh.io/v1alpha1 kind: Account metadata: name: demo spec: type: org displayName: Demo Org --- apiVersion: core.platform-mesh.io/v1alpha1 kind: Account metadata: name: tutorial spec: type: account displayName: Tutorial Account
In root:orgs:demo:tutorial — Subscriber:
apiVersion: apis.kcp.io/v1alpha2
kind: APIBinding
metadata:
name: llm-binding
uid: 36adc41e-a627-5047-9bdd-5ec8ca6f6904
spec:
reference:
export:
path: root:providers:private-llm
name: llm.privatellms.msp
permissionClaims:
- {group: "", resource: secrets, verbs: ["*"], selector: {matchAll: true}, state: Accepted}
- {group: "", resource: namespaces, verbs: ["*"], selector: {matchAll: true}, state: Accepted}
- {group: "", resource: events, verbs: ["*"], selector: {matchAll: true}, state: Accepted}
status:
phase: Bound
boundResources:
- {group: llm.privatellms.msp, resource: llminstances, schema: {name: v1a2b3c4d.llminstances.llm.privatellms.msp, identityHash: 6aedce73259b9202…}}
- {group: llm.privatellms.msp, resource: apitokenrequests, schema: {name: v1a2b3c4d.apitokenrequests.llm.privatellms.msp, identityHash: 6aedce73259b9202…}}In root:orgs:demo:tutorial — Subscriber:
apiVersion: llm.privatellms.msp/v1alpha1
kind: LLMInstance
metadata:
name: demo-llm
namespace: default
uid: 7e2d83de-e0f5-5874-9510-ce2f1ce6edb0
spec:
model: gemma-3-1b-it
replicas: 1
status:
conditions:
- {type: Ready, status: "True"}In root:orgs:demo:tutorial — Subscriber:
apiVersion: llm.privatellms.msp/v1alpha1 kind: APITokenRequest metadata: name: demo-llm-token namespace: default uid: 9bbe05b5-ffc8-5367-9923-f209cff1c2c2 spec: instanceName: demo-llm description: Chat UI access token
In root:orgs:demo:tutorial — Subscriber:
apiVersion: ui.privatellms.msp/v1alpha1
kind: ChatUIInstance
metadata:
name: demo-chat
namespace: default
uid: eb3cc4a8-cdcc-5a20-96ec-ad64c5461e47
spec:
credentialsSecretRef:
name: demo-llm-token-token{
"resource": {
"neo.provider.id": "demo-tutorial"
},
"event_name": "audit.contract.agreement",
"time": "2026-09-30T09:03:12Z",
"attributes": {
"audit.record.id": "binding:36adc41e-a627-5047-9bdd-5ec8ca6f6904",
"audit.actor.id": "user:tutorial@example.com",
"audit.actor.type": "user",
"audit.action": "BIND",
"audit.outcome": "success",
"audit.target.id": "apis.kcp.io/APIExport:root:providers:private-llm/llm.privatellms.msp",
"neo.country": "DE",
"kcp.workspace": "root:orgs:demo:tutorial",
"kcp.binding": "llm-binding",
"neo.agreement.digest": "66ba9ca6470b7f3566447b84cf13a3599cd61570f15f0fc0efbf736466c49e41",
"neo.market.role": "subscriber"
},
"body": {
"sha256_of": "D1",
"bytes_hex": "66ba9ca6470b7f3566447b84cf13a3599cd61570f15f0fc0efbf736466c49e41"
}
}The record's body is the 32-byte digest of the agreement; the attributes are the audit signal's (who, what, on what, with what outcome) plus the kcp coordinates. At the edge it became record 2 of the subscriber's book, event code 21, hash 81b9e4627ac35e4e03b24f53da302d1c5f0e18c76e9441c98ecca04849735972.
| step | time (UTC) | book | event | actor | action | target | record at the edge |
|---|---|---|---|---|---|---|---|
| 1 | 09-30 08:40 | Private LLM | audit.service.publish | serviceaccount:private-llm-pm | PUBLISH | private-llm/llm.privatellms.msp | #1 · 6e5d4201f588… |
| 1 | 09-30 08:40 | the Platform Mesh operator | audit.catalog.list | system:platform-mesh:marketplace | CREATE | private-llm/llm.privatellms.msp | #1 · eeee6f55985d… |
| 1 | 09-30 08:44 | Chat UI | audit.service.publish | serviceaccount:chat-ui-pm | PUBLISH | chat-ui/ui.privatellms.msp | #1 · b849214efe3e… |
| 1 | 09-30 08:44 | the Platform Mesh operator | audit.catalog.list | system:platform-mesh:marketplace | CREATE | chat-ui/ui.privatellms.msp | #2 · b0126e45c90c… |
| 2 | 09-30 08:58 | the Platform Mesh operator | audit.account.create | user:platform-admin@example.com | CREATE | orgs/demo | #3 · b9b4636716ee… |
| 2 | 09-30 09:00 | the Platform Mesh operator | audit.account.create | user:tutorial@example.com | CREATE | demo/tutorial | #4 · 0f776f15292f… |
| 2 | 09-30 09:00 | org demo, account tutorial | audit.account.create | user:tutorial@example.com | CREATE | demo/tutorial | #1 · 6977d0799b18… |
| 3 | 09-30 09:03 | org demo, account tutorial | audit.contract.agreement | user:tutorial@example.com | BIND | private-llm/llm.privatellms.msp | #2 · 81b9e4627ac3… |
| 3 | 09-30 09:03 | the Platform Mesh operator | audit.door.decision | system:kcp:authorizer | AUTHORIZE | tutorial/llm-binding | #5 · 709ce5932a72… |
| 3 | 09-30 09:03 | Private LLM | audit.contract.agreement | system:private-llm:controller | ACCEPT | kcp:cluster:5t8r3p1y6u2i7o4w | #2 · a8fb2e692800… |
| 4 | 09-30 09:05 | org demo, account tutorial | audit.instance.create | user:tutorial@example.com | CREATE | tutorial/default/demo-llm | #3 · 0bba02b8c84c… |
| 4 | 09-30 09:05 | the Platform Mesh operator | audit.door.decision | system:kcp:authorizer | AUTHORIZE | tutorial/default/demo-llm | #6 · 2ac5c7b47e76… |
| 4 | 09-30 09:08 | Private LLM | audit.workload.start | system:private-llm:operator | PROVISION | tutorial/default/demo-llm | #3 · 4646c6fc135d… |
| 5 | 09-30 09:09 | org demo, account tutorial | audit.token.request | user:tutorial@example.com | CREATE | tutorial/default/demo-llm-token | #4 · c4ef602390f5… |
| 5 | 09-30 09:09 | Private LLM | audit.token.issue | system:private-llm:operator | ISSUE | tutorial/default/demo-llm-token-token | #4 · d8e8fd41bc99… |
| 5 | 09-30 09:09 | the Platform Mesh operator | audit.claim.use | system:private-llm:controller | CREATE | tutorial/default/demo-llm-token-token | #7 · 4d62051a3d30… |
| 6 | 09-30 09:11 | org demo, account tutorial | audit.contract.agreement | user:tutorial@example.com | BIND | chat-ui/ui.privatellms.msp | #5 · 23d44b987dd3… |
| 6 | 09-30 09:11 | the Platform Mesh operator | audit.door.decision | system:kcp:authorizer | AUTHORIZE | tutorial/chat-ui-binding | #8 · 40a7998c66db… |
| 6 | 09-30 09:11 | Chat UI | audit.contract.agreement | system:chat-ui:controller | ACCEPT | kcp:cluster:5t8r3p1y6u2i7o4w | #2 · 238aa5b2a31d… |
| 6 | 09-30 09:12 | org demo, account tutorial | audit.chatui.create | user:tutorial@example.com | CREATE | tutorial/default/demo-chat | #6 · db29ee67e6e2… |
| 6 | 09-30 09:12 | the Platform Mesh operator | audit.claim.use | system:chat-ui:controller | READ | tutorial/default/demo-llm-token-token | #9 · 08ad06d82d08… |
| 6 | 09-30 09:14 | Chat UI | audit.workload.start | system:chat-ui:operator | PROVISION | tutorial/default/demo-chat | #3 · 50a38ceb816c… |
| 7 | 09-30 15:30 | org demo, account tutorial | audit.instance.scale | user:tutorial@example.com | UPDATE | tutorial/default/demo-llm | #7 · 65143b265ef9… |
| 7 | 09-30 15:31 | Private LLM | audit.workload.scale | system:private-llm:operator | UPDATE | tutorial/default/demo-llm | #5 · ee840dd08bb8… |
| 7 | 09-30 23:59 | Private LLM | audit.contract.sla | system:private-llm:operator | MEASURE | tutorial/default/demo-llm | #6 · 427c67890ff0… |
| 7 | 09-30 23:59 | org demo, account tutorial | audit.contract.sla | serviceaccount:demo-probe | MEASURE | tutorial/default/demo-llm | #8 · 8a84ae6f0b10… |
| 8 | 10-07 10:00 | org demo, account tutorial | audit.instance.delete | user:tutorial@example.com | DELETE | tutorial/default/demo-llm | #9 · 1ae8bef34906… |
| 8 | 10-07 10:00 | Private LLM | audit.workload.end | system:private-llm:operator | DEPROVISION | tutorial/default/demo-llm | #7 · 09e4ec6afb37… |
| 8 | 10-07 10:02 | org demo, account tutorial | audit.contract.end | user:tutorial@example.com | UNBIND | private-llm/llm.privatellms.msp | #10 · 7e8a2b03cf80… |
| 8 | 10-07 10:02 | Private LLM | audit.contract.end | system:private-llm:controller | RELEASE | kcp:cluster:5t8r3p1y6u2i7o4w | #8 · b8d6b9ebf7b0… |
| 8 | 10-07 10:05 | Private LLM | audit.contract.week | system:private-llm:operator | STATE | kcp:cluster:5t8r3p1y6u2i7o4w | #9 · 73a13c610972… |
| 8 | 10-07 10:05 | org demo, account tutorial | audit.contract.week | serviceaccount:demo-probe | STATE | private-llm/llm.privatellms.msp | #11 · 01c9ea4038bb… |
events.jsonl objects.yaml agreements.json booked.json
events.jsonl: one readable projection per generated event and its recorded edge hash. The actual client sends OTLP protobuf; this JSONL is not the wire request. agreements.json: the two subscriptions in canonical form with their digests. booked.json: the lab's output, per edge and per event.
APIBinding shown here, and does the provider's controller see its consumers' bindings through the export's virtual workspace in your version?