From 21ebb185cf49945dbbac322246c3045251e4187e Mon Sep 17 00:00:00 2001 From: kairunedev Date: Thu, 27 Aug 2026 23:44:05 +0700 Subject: [PATCH 1/8] showcase: Kairune - proven wallets + self-serve spend permissions Wallet proof via EIP-191 personal_sign (chain 4663, 600s TTL) and self-serve spend permissions gated by trust tier instead of a platform admin key. Updates description, tagline, visual title, two artifacts, and two feedback prompts. Validator passes; all referenced URLs return 200. --- showcase/kairune-verifiable-trust/README.md | 18 ++++++++++++++- .../kairune-verifiable-trust/showcase.json | 22 ++++++++++++++----- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/showcase/kairune-verifiable-trust/README.md b/showcase/kairune-verifiable-trust/README.md index 5248328..bfd0db1 100644 --- a/showcase/kairune-verifiable-trust/README.md +++ b/showcase/kairune-verifiable-trust/README.md @@ -10,12 +10,28 @@ engine weights verified attestations fully and discounts unsigned ones (0.25×). Backward compatible — existing unsigned submissions still work, recorded as `unverified`. +**Since first submission — proven wallets and self-serve spend:** + +- **Wallet proof (EIP-191).** An agent proves it controls the wallet it claims + by signing a server-issued challenge with `personal_sign` (chain `4663`, + domain-bound, 600s TTL). The private key never leaves the wallet, and proof + status is a public read — a payer deciding whether to release funds needs to + know whether the address it is about to pay was ever proven. Scope is + deliberately narrow: this proves wallet control, not trustworthiness. +- **Self-serve permissions.** Granting a budget, spending, scoping payees, + setting expiry and revoking no longer need a platform admin key. The trust + tier is the access control: below EMERGING (score 250) a grant is refused + with `409 tier_too_low`. An agent earns its budget rather than being handed + one, and the API is usable by agents that are not us. + ## Proof - Animated demo: `assets/kairune-verify-demo.mp4` - Live console: https://kairune.online/app -- API meta (shows `signature_algorithm: ed25519`): https://kairune.online/api/meta +- API meta (`wallet_proof: eip191-personal-sign`, `signature_algorithm: ed25519`): https://kairune.online/api/meta - Example trust card: https://kairune.online/a/voyager-07 +- API docs: https://kairune.online/docs - Source: https://github.com/kairunedev/Kairune +- Wallet proof + self-serve PR: https://github.com/kairunedev/Kairune/pull/7 ## EconomyOS primitives ACP job (4 paid offerings on Robinhood Chain via Virtuals), Agent Token diff --git a/showcase/kairune-verifiable-trust/showcase.json b/showcase/kairune-verifiable-trust/showcase.json index fe8010a..c7dc041 100644 --- a/showcase/kairune-verifiable-trust/showcase.json +++ b/showcase/kairune-verifiable-trust/showcase.json @@ -1,8 +1,8 @@ { "slug": "kairune-verifiable-trust", "title": "Kairune — Verifiable Agent Trust Layer", - "tagline": "Every agent gets a verifiable, cryptographically-signed trust score — then scoped spend by tier.", - "description": "Kairune is the trust layer for AI agents that spend. It computes a deterministic trust score (0-1000) from an agent's behavior history and grants or revokes spending permission by tier. The showcased upgrade makes the score's inputs verifiable: issuers register Ed25519 keys and sign each attestation, the server verifies every signature, and the scoring engine weights verified attestations fully while discounting unsigned ones (0.25x). Exposed as ACP offerings (lookup score, register agent, record attestation, full report) on Robinhood Chain via Virtuals.", + "tagline": "An agent earns its budget instead of being handed one: verifiable trust score, proven wallet, scoped spend it cannot cross.", + "description": "Kairune is the trust layer for AI agents that spend, and it is now self-serve end to end: an agent registers, earns attestations, crosses a tier threshold, grants itself a scoped budget, spends against it, and revokes — with no platform admin key anywhere in that path. Authorisation comes from the trust tier instead: an agent below EMERGING (score 250) is refused a budget with 409 tier_too_low, because there is no behavioural basis to extend it credit yet. Both sides of the record are verifiable. Attestation issuers register Ed25519 keys and sign each attestation; the server verifies every signature and weights verified attestations fully while discounting unsigned ones (0.25x). The wallet an agent claims can be proven with an EIP-191 personal_sign challenge (chain 4663, 600s TTL) without the private key ever leaving the wallet. Spend enforcement is live — over-ceiling charges are blocked with 409 ceiling_exceeded and every decision fires an HMAC-SHA256 signed webhook. Exposed as ACP offerings (lookup score, register agent, record attestation, full report) on Robinhood Chain via Virtuals.", "status": "live", "topic": "commerce", "topics": ["identity", "commerce", "acp"], @@ -22,7 +22,7 @@ "visual": { "kind": "animated demo", "eyebrow": "live api + acp", - "title": "verifiable attestations", + "title": "verifiable attestations, proven wallets, self-serve spend", "posterUrl": "https://raw.githubusercontent.com/Virtual-Protocol/acp-cli-demos/main/showcase/kairune-verifiable-trust/assets/poster.png", "videoUrl": "https://raw.githubusercontent.com/Virtual-Protocol/acp-cli-demos/main/showcase/kairune-verifiable-trust/assets/kairune-verify-demo.mp4", "videoLabel": "Watch the 0:06 demo on X" @@ -58,7 +58,7 @@ "kind": "proof" }, { - "label": "API meta (signature_algorithm: ed25519, unverified_weight_factor: 0.25)", + "label": "API meta — wallet_proof: eip191-personal-sign, signature_algorithm: ed25519, unverified_weight_factor: 0.25", "href": "https://kairune.online/api/meta", "kind": "proof" }, @@ -67,6 +67,11 @@ "href": "https://kairune.online/a/voyager-07", "kind": "proof" }, + { + "label": "API docs — wallet proof, self-serve permissions, spend enforcement, signed webhooks", + "href": "https://kairune.online/docs", + "kind": "docs" + }, { "label": "Public repo", "href": "https://github.com/kairunedev/Kairune", @@ -76,11 +81,16 @@ "label": "Verifiable attestations PR", "href": "https://github.com/kairunedev/Kairune/pull/1", "kind": "proof" + }, + { + "label": "Wallet proof + self-serve permissions PR — EIP-191 challenge, tier gate replaces the admin key", + "href": "https://github.com/kairunedev/Kairune/pull/7", + "kind": "proof" } ], "feedbackPrompts": [ "Should issuer identities be verified on-chain rather than by API key?", - "What attestation kinds matter most for agent-to-agent commerce?", - "Would a replay-protection window on signed submissions be worth the added friction?" + "Is EMERGING (score 250) the right floor before an agent may hold any budget, or should tier 0 get a probationary micro-ceiling?", + "Should a proven wallet (EIP-191) be required before an agent can receive a budget, not just recorded alongside it?" ] } From a203aa7be0580991f1e5e128d145fe94392c3ba5 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 28 Aug 2026 00:45:27 +0700 Subject: [PATCH 2/8] showcase(kairune): lead the card with the refusal, not the happy path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Swaps the inline video for a 0:13 film of the full arc: the agent registers itself, is refused a permission at 409 tier_too_low while UNRATED, earns attestations until the score crosses 250, then gets a ceiling it cannot cross. The refusal is the part worth showing — it is what makes the tier gate real rather than decorative. Hosted on kairune.online rather than committed here, so the diff stays text and reviewers do not have to pull 496K of binary. The previous 0:06 demo is kept as an artifact. --- showcase/kairune-verifiable-trust/README.md | 5 +++++ showcase/kairune-verifiable-trust/showcase.json | 11 ++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/showcase/kairune-verifiable-trust/README.md b/showcase/kairune-verifiable-trust/README.md index bfd0db1..a80f91d 100644 --- a/showcase/kairune-verifiable-trust/README.md +++ b/showcase/kairune-verifiable-trust/README.md @@ -23,8 +23,13 @@ Backward compatible — existing unsigned submissions still work, recorded as tier is the access control: below EMERGING (score 250) a grant is refused with `409 tier_too_low`. An agent earns its budget rather than being handed one, and the API is usable by agents that are not us. +- **A film of the refusal.** The 0:13 demo walks the whole arc, including the + part most demos leave out: the agent asks for a budget while UNRATED and is + turned down. It earns attestations, crosses 250, asks again, and gets a + ceiling it cannot exceed. No admin key appears anywhere in that path. ## Proof +- Self-serve film (0:13): https://kairune.online/assets/video/kairune-self-serve.mp4 - Animated demo: `assets/kairune-verify-demo.mp4` - Live console: https://kairune.online/app - API meta (`wallet_proof: eip191-personal-sign`, `signature_algorithm: ed25519`): https://kairune.online/api/meta diff --git a/showcase/kairune-verifiable-trust/showcase.json b/showcase/kairune-verifiable-trust/showcase.json index c7dc041..3f65a1a 100644 --- a/showcase/kairune-verifiable-trust/showcase.json +++ b/showcase/kairune-verifiable-trust/showcase.json @@ -22,9 +22,9 @@ "visual": { "kind": "animated demo", "eyebrow": "live api + acp", - "title": "verifiable attestations, proven wallets, self-serve spend", - "posterUrl": "https://raw.githubusercontent.com/Virtual-Protocol/acp-cli-demos/main/showcase/kairune-verifiable-trust/assets/poster.png", - "videoUrl": "https://raw.githubusercontent.com/Virtual-Protocol/acp-cli-demos/main/showcase/kairune-verifiable-trust/assets/kairune-verify-demo.mp4", + "title": "refused at tier 0, then it earns the budget", + "posterUrl": "https://kairune.online/assets/video/kairune-self-serve.jpg", + "videoUrl": "https://kairune.online/assets/video/kairune-self-serve.mp4", "videoLabel": "Watch the 0:06 demo on X" }, "skills": [ @@ -47,6 +47,11 @@ "href": "https://github.com/Virtual-Protocol/acp-cli-demos/tree/main/showcase/kairune-verifiable-trust/skills/kairune-verify-agent-trust", "kind": "skill" }, + { + "label": "Self-serve film (0:13) — grant refused at 409 tier_too_low, then earned", + "href": "https://kairune.online/assets/video/kairune-self-serve.mp4", + "kind": "video" + }, { "label": "Animated demo (mp4)", "href": "https://raw.githubusercontent.com/Virtual-Protocol/acp-cli-demos/main/showcase/kairune-verifiable-trust/assets/kairune-verify-demo.mp4", From 475cdb43c0ca7aba0402e64f8b1978e5ac59395f Mon Sep 17 00:00:00 2001 From: root Date: Fri, 28 Aug 2026 18:49:20 +0700 Subject: [PATCH 3/8] showcase(kairune): add ERC-8126 derived adapter proof (explicitly not compliant) Adds a verifiable artifact pointing at the new derived adapter GET /api/agents/:id/erc8126 (alias /api/erc8126/agents/:id), which exposes Kairune's behavioural score as an inverted 0..100 risk (100 - Math.round(score/10)) with a per-type breakdown that is explicit about what is missing: ETV/MCV/SCV/WAV not_implemented, WV partial via EIP-191 personal_sign, PDV/ZKP/QCV absent, agentId null (no ERC-8004 tokenId). Payload carries compliant:false and a disclosure string so a spec reader cannot mistake this for a claim of provider compliance. Consumer use is as a minVerificationScore- style input to an ERC-8196 policy, not a substitute for the five required verification types. Validated 59 manifests. Artifacts: 11 -> 12. Live: https://kairune.online/api/agents/voyager-07/erc8126 --- showcase/kairune-verifiable-trust/README.md | 1 + showcase/kairune-verifiable-trust/showcase.json | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/showcase/kairune-verifiable-trust/README.md b/showcase/kairune-verifiable-trust/README.md index a80f91d..8bb31d9 100644 --- a/showcase/kairune-verifiable-trust/README.md +++ b/showcase/kairune-verifiable-trust/README.md @@ -33,6 +33,7 @@ Backward compatible — existing unsigned submissions still work, recorded as - Animated demo: `assets/kairune-verify-demo.mp4` - Live console: https://kairune.online/app - API meta (`wallet_proof: eip191-personal-sign`, `signature_algorithm: ed25519`): https://kairune.online/api/meta +- ERC-8126 derived adapter (explicitly not compliant, `compliant: false`, `agentId: null`, ETV/MCV/SCV/WAV not implemented, WV partial via EIP-191): https://kairune.online/api/agents/voyager-07/erc8126 — also at https://kairune.online/api/erc8126/agents/voyager-07 - Example trust card: https://kairune.online/a/voyager-07 - API docs: https://kairune.online/docs - Source: https://github.com/kairunedev/Kairune diff --git a/showcase/kairune-verifiable-trust/showcase.json b/showcase/kairune-verifiable-trust/showcase.json index 3f65a1a..3a26454 100644 --- a/showcase/kairune-verifiable-trust/showcase.json +++ b/showcase/kairune-verifiable-trust/showcase.json @@ -67,6 +67,11 @@ "href": "https://kairune.online/api/meta", "kind": "proof" }, + { + "label": "ERC-8126 derived adapter (not compliant) — 0-100 risk + per-type breakdown, EIP-191 WV partial", + "href": "https://kairune.online/api/agents/voyager-07/erc8126", + "kind": "proof" + }, { "label": "Example public trust card", "href": "https://kairune.online/a/voyager-07", From c97e701c2ed69513c2b3596463e98eeed3977db6 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 28 Aug 2026 19:30:50 +0700 Subject: [PATCH 4/8] showcase(kairune): align tagline/topics/feedback with contributor guide Tagline without trailing period, topics to agents/commerce/security, feedback prefill synced to current feedbackPrompts. No content change. Co-Authored-By: internal-model --- showcase/kairune-verifiable-trust/showcase.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/showcase/kairune-verifiable-trust/showcase.json b/showcase/kairune-verifiable-trust/showcase.json index 3a26454..f01421a 100644 --- a/showcase/kairune-verifiable-trust/showcase.json +++ b/showcase/kairune-verifiable-trust/showcase.json @@ -1,11 +1,11 @@ { "slug": "kairune-verifiable-trust", "title": "Kairune — Verifiable Agent Trust Layer", - "tagline": "An agent earns its budget instead of being handed one: verifiable trust score, proven wallet, scoped spend it cannot cross.", + "tagline": "An agent earns its budget instead of being handed one: verifiable trust score, proven wallet, scoped spend it cannot cross", "description": "Kairune is the trust layer for AI agents that spend, and it is now self-serve end to end: an agent registers, earns attestations, crosses a tier threshold, grants itself a scoped budget, spends against it, and revokes — with no platform admin key anywhere in that path. Authorisation comes from the trust tier instead: an agent below EMERGING (score 250) is refused a budget with 409 tier_too_low, because there is no behavioural basis to extend it credit yet. Both sides of the record are verifiable. Attestation issuers register Ed25519 keys and sign each attestation; the server verifies every signature and weights verified attestations fully while discounting unsigned ones (0.25x). The wallet an agent claims can be proven with an EIP-191 personal_sign challenge (chain 4663, 600s TTL) without the private key ever leaving the wallet. Spend enforcement is live — over-ceiling charges are blocked with 409 ceiling_exceeded and every decision fires an HMAC-SHA256 signed webhook. Exposed as ACP offerings (lookup score, register agent, record attestation, full report) on Robinhood Chain via Virtuals.", "status": "live", "topic": "commerce", - "topics": ["identity", "commerce", "acp"], + "topics": ["agents", "commerce", "security"], "hidden": false, "builder": { "name": "Kairune", @@ -16,7 +16,7 @@ "demo": "https://kairune.online/app", "video": "https://x.com/usekairune/status/2075911860516528241", "share": "https://x.com/usekairune/status/2075911860516528241", - "feedback": "https://github.com/Virtual-Protocol/acp-cli-demos/issues/new?title=Feedback%3A%20Kairune%20Verifiable%20Agent%20Trust%20Layer&body=Which%20feedback%20prompt%20fits%3F%0A%0A-%20Issuer%20identity%20should%20be%20verified%20on-chain%0A-%20Attestation%20kinds%20for%20agent-to-agent%20commerce%0A-%20Replay-protection%20window%20worth%20the%20friction%3F%0A%0ANotes%3A%0A" + "feedback": "https://github.com/Virtual-Protocol/acp-cli-demos/issues/new?title=Feedback%3A%20Kairune%20Verifiable%20Agent%20Trust%20Layer&body=Which%20feedback%20prompt%20fits%3F%0A%0A-%20Should%20issuer%20identities%20be%20verified%20on-chain%20rather%20than%20by%20API%20key%3F%0A-%20Is%20EMERGING%20(score%20250)%20the%20right%20floor%20before%20an%20agent%20may%20hold%20any%20budget%2C%20or%20should%20tier%200%20get%20a%20probationary%20micro-ceiling%3F%0A-%20Should%20a%20proven%20wallet%20(EIP-191)%20be%20required%20before%20an%20agent%20can%20receive%20a%20budget%2C%20not%20just%20recorded%20alongside%20it%3F%0A%0ANotes%3A%0A" }, "primitives": ["acp", "token", "wallet"], "visual": { From 0621e5158dfc37183e03288bb8a34e1d83a191ed Mon Sep 17 00:00:00 2001 From: root Date: Sun, 30 Aug 2026 22:28:08 +0700 Subject: [PATCH 5/8] docs(kairune): replace invented example numbers with live values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The worked example claimed score 512 with 18 verified and 3 unverified attestations, and returned decision "allow". None of those numbers came from the endpoint. voyager-07 actually reports 668 with 0 verified and 2327 unverified, which means the example's own stated policy — tier >= 2 AND mostly-verified backing — should have produced "review", not a grant. A skill whose worked example approves spend on evidence that does not exist is worse than one with no example. The example now reads from the live endpoint and ends in "review" with granted_ceiling 0, explaining that the tier gate passed while the verified-backing requirement failed. Also surfaces breakdown.integrityFactor and breakdown.boundBy, added upstream today. When boundBy is "misconduct-ratio" the score was reduced in proportion to the share of disputes and chargebacks in the agent's record; voyager-07 sits at 0.668, so roughly a third was withheld. A consumer reading only score and tier cannot see that, so it is now a documented rule and a stop condition. Validator: 59 showcase project manifest(s) pass. --- .../kairune-verify-agent-trust/SKILL.md | 22 ++++++++---- .../examples/result-redacted.md | 35 +++++++++++++------ 2 files changed, 40 insertions(+), 17 deletions(-) diff --git a/showcase/kairune-verifiable-trust/skills/kairune-verify-agent-trust/SKILL.md b/showcase/kairune-verifiable-trust/skills/kairune-verify-agent-trust/SKILL.md index 7b89151..7d306d9 100644 --- a/showcase/kairune-verifiable-trust/skills/kairune-verify-agent-trust/SKILL.md +++ b/showcase/kairune-verifiable-trust/skills/kairune-verify-agent-trust/SKILL.md @@ -54,6 +54,11 @@ clear the bar. - Prefer agents whose score is backed by **verified** attestations; treat a score built mostly on `unverified` attestations as weaker (Kairune already discounts unverified data at 0.25×). +- Read `breakdown.boundBy`. When it is `misconduct-ratio`, disputes and + chargebacks are a large enough share of the agent's record that the score was + reduced proportionally, and `breakdown.integrityFactor` is how much survived + (1 = a spotless record, 0.6 = roughly 40% withheld). A tier alone will not tell + you this. - Re-check just before granting; scores change as behavior is attested. - Never fabricate or infer a score that was not returned by Kairune. @@ -66,6 +71,8 @@ Stop and defer to the caller (return `review` or `deny`) when: - The intended amount exceeds the tier's `suggested_daily_ceiling`. - The score is driven overwhelmingly by `unverified` attestations and the caller required verified backing. +- `breakdown.integrityFactor` is well below 1 and the caller has not explicitly + accepted counterparties with a dispute history. - Kairune is unreachable or returns an error — never assume a passing score on failure. @@ -146,20 +153,21 @@ Return a single JSON object: ```json { "handle": "voyager-07", - "score": 512, + "score": 668, "tier": 2, "label": "ESTABLISHED", "suggested_daily_ceiling": 150, - "verified_count": 18, - "unverified_count": 3, - "decision": "allow", - "granted_ceiling": 100, - "reason": "Tier 2 >= min tier 2; amount 100 <= ceiling 150; mostly verified." + "verified_count": 0, + "unverified_count": 2327, + "decision": "review", + "granted_ceiling": 0, + "reason": "Tier 2 >= min tier 2, but 0 of 2327 attestations are signed and the caller required verified backing." } ``` `decision` is one of `allow`, `review`, `deny`. `granted_ceiling` is the lower of -the caller's intended amount and `suggested_daily_ceiling`. +the caller's intended amount and `suggested_daily_ceiling`, and is `0` when the +decision is not `allow`. ## References diff --git a/showcase/kairune-verifiable-trust/skills/kairune-verify-agent-trust/examples/result-redacted.md b/showcase/kairune-verifiable-trust/skills/kairune-verify-agent-trust/examples/result-redacted.md index 2321cab..4350f07 100644 --- a/showcase/kairune-verifiable-trust/skills/kairune-verify-agent-trust/examples/result-redacted.md +++ b/showcase/kairune-verifiable-trust/skills/kairune-verify-agent-trust/examples/result-redacted.md @@ -3,6 +3,10 @@ **Request:** grant `voyager-07` a $100/day compute permission; require tier ≥ 2 and mostly-verified backing; cap at Kairune's suggested ceiling. +This example is deliberately one that does **not** end in a clean `allow`. The +agent clears the tier gate but fails the caller's verified-backing requirement, +which is the case worth showing: the tier alone is not the whole policy. + **Live API call (free, public):** ``` @@ -16,11 +20,16 @@ GET https://kairune.online/api/agents/voyager-07 "agent": { "handle": "voyager-07", "status": "active", - "score": 512, + "score": 668, "tier": 2, "label": "ESTABLISHED", "suggested_daily_ceiling": 150, - "breakdown": { "verifiedCount": 18, "unverifiedCount": 3 } + "breakdown": { + "verifiedCount": 0, + "unverifiedCount": 2327, + "integrityFactor": 0.668, + "boundBy": "misconduct-ratio" + } } } ``` @@ -30,18 +39,24 @@ GET https://kairune.online/api/agents/voyager-07 ```json { "handle": "voyager-07", - "score": 512, + "score": 668, "tier": 2, "label": "ESTABLISHED", "suggested_daily_ceiling": 150, - "verified_count": 18, - "unverified_count": 3, - "decision": "allow", - "granted_ceiling": 100, - "reason": "Tier 2 >= min tier 2; amount 100 <= ceiling 150; 18 verified vs 3 unverified." + "verified_count": 0, + "unverified_count": 2327, + "decision": "review", + "granted_ceiling": 0, + "reason": "Tier 2 >= min tier 2 and amount 100 <= ceiling 150, but the caller required mostly-verified backing and 0 of 2327 attestations are signed. Escalate rather than grant." } ``` **Notes:** No credentials were used (reads are public). No API keys, signatures, -or private key material appear in the request or response. Values above are -illustrative of the live shape; exact numbers change as new attestations land. +or private key material appear in the request or response. + +The numbers above were read from the live endpoint, so they show something an +invented example would have hidden: this agent's score is bound by +`misconduct-ratio`, not by the plain additive path. `integrityFactor: 0.668` +means roughly a third of the score was withheld because disputes and chargebacks +make up a measurable share of its record. Re-read the endpoint before relying on +any specific value — scores move as attestations land. From ce3a7c9ce17842fedafa272539c7548b43e0e553 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 1 Sep 2026 19:17:35 +0700 Subject: [PATCH 6/8] showcase(kairune): fix video length, tighten tagline, add owner lock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addresses the auto-review feedback on #116. The 0:06 videoLabel was wrong. The file is 13.00s exactly (390 frames at 30fps, confirmed against the mvhd atom), and every other reference in the card already said 0:13 — including line 51 of this same manifest, pointing at the same URL. Corrected to 0:13 so all four mentions agree. Took the suggested verb-led tagline, with one change: it kept "verifiable trust score" from the old copy, and that overclaims. The score is derived from attestations, not cryptographically verified — only wallet control is (EIP-191). Says "signed attestations" instead, which is the part that actually carries a signature. Also added the owner lock shipped today, because it is a direct correction to the self-serve bullet above it. Cutting the admin key out of the permission path also meant those routes accepted no credential at all, and a permission id is a public read. Locking binds an agent to its wallet: mutating permission routes then require a fresh single-use X-Owner-Proof or return 401. Noted that it is opt-in and therefore does not protect agents that never lock — making it mandatory would strand every agent registered before the feature existed. Reads and the spend dry-run stay open so a payment rail can still get a go/no-go signal without holding the owner wallet. validate-showcase.mjs passes (59 manifests). Diff touches only the two files inside showcase/kairune-verifiable-trust/. --- showcase/kairune-verifiable-trust/README.md | 8 ++++++++ showcase/kairune-verifiable-trust/showcase.json | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/showcase/kairune-verifiable-trust/README.md b/showcase/kairune-verifiable-trust/README.md index 8bb31d9..9da4bd1 100644 --- a/showcase/kairune-verifiable-trust/README.md +++ b/showcase/kairune-verifiable-trust/README.md @@ -23,6 +23,14 @@ Backward compatible — existing unsigned submissions still work, recorded as tier is the access control: below EMERGING (score 250) a grant is refused with `409 tier_too_low`. An agent earns its budget rather than being handed one, and the API is usable by agents that are not us. +- **Owner lock on spend authority.** Self-serve cut the admin key out of the + path, which also meant those routes accepted no credential at all — and a + permission id is public. An operator can now bind an agent to its wallet with + the same EIP-191 proof: once locked, every mutating permission route requires + a fresh single-use proof in `X-Owner-Proof` and refuses with `401` without + one. Reads and the spend dry-run stay open so a payment rail still gets a + go/no-go signal. It is opt-in, so an agent that never locks is still open — + making it mandatory would strand every agent registered before the feature. - **A film of the refusal.** The 0:13 demo walks the whole arc, including the part most demos leave out: the agent asks for a budget while UNRATED and is turned down. It earns attestations, crosses 250, asks again, and gets a diff --git a/showcase/kairune-verifiable-trust/showcase.json b/showcase/kairune-verifiable-trust/showcase.json index f01421a..74d6f8d 100644 --- a/showcase/kairune-verifiable-trust/showcase.json +++ b/showcase/kairune-verifiable-trust/showcase.json @@ -1,7 +1,7 @@ { "slug": "kairune-verifiable-trust", "title": "Kairune — Verifiable Agent Trust Layer", - "tagline": "An agent earns its budget instead of being handed one: verifiable trust score, proven wallet, scoped spend it cannot cross", + "tagline": "Earn a budget with signed attestations, a proven wallet, and a spend ceiling it can't cross", "description": "Kairune is the trust layer for AI agents that spend, and it is now self-serve end to end: an agent registers, earns attestations, crosses a tier threshold, grants itself a scoped budget, spends against it, and revokes — with no platform admin key anywhere in that path. Authorisation comes from the trust tier instead: an agent below EMERGING (score 250) is refused a budget with 409 tier_too_low, because there is no behavioural basis to extend it credit yet. Both sides of the record are verifiable. Attestation issuers register Ed25519 keys and sign each attestation; the server verifies every signature and weights verified attestations fully while discounting unsigned ones (0.25x). The wallet an agent claims can be proven with an EIP-191 personal_sign challenge (chain 4663, 600s TTL) without the private key ever leaving the wallet. Spend enforcement is live — over-ceiling charges are blocked with 409 ceiling_exceeded and every decision fires an HMAC-SHA256 signed webhook. Exposed as ACP offerings (lookup score, register agent, record attestation, full report) on Robinhood Chain via Virtuals.", "status": "live", "topic": "commerce", @@ -25,7 +25,7 @@ "title": "refused at tier 0, then it earns the budget", "posterUrl": "https://kairune.online/assets/video/kairune-self-serve.jpg", "videoUrl": "https://kairune.online/assets/video/kairune-self-serve.mp4", - "videoLabel": "Watch the 0:06 demo on X" + "videoLabel": "Watch the 0:13 demo on X" }, "skills": [ { From 1aed09b4ababb1bf68200ca37013964ed22c90a8 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 3 Sep 2026 20:44:24 +0700 Subject: [PATCH 7/8] showcase(kairune): tighten description, add the published SDK MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two things, both from the review on this PR. Took the suggested shorter description. The reviewer was right that it ran long for the card format — 1109 characters down to 662. Kept every claim that carries a number (the 250 floor, 409 tier_too_low, the HMAC webhook) and cut the restatement around them. One addition rather than a pure trim: the owner lock is named in the description now, not just the README, because a reader deciding whether the self-serve path is safe should not have to open the README to find out the permission routes can be bound to a wallet. Second, the SDK is published: @kairune/sdk@0.4.0 on npm, zero dependencies, native fetch. It is the piece that makes the lock usable rather than merely documented — pass a signOwnerMessage signer once and any mutating call that comes back 401 because the agent turned out to be locked is signed and retried exactly once. An unlocked agent pays nothing for it; no extra round trip happens unless the server actually refuses. Added as an artifact and a README bullet. Deliberately not claimed: the SDK does not make the trust score verifiable. It only automates the wallet-control proof, which is the one part that carries a signature. validate-showcase.mjs passes (59 manifests). Diff touches only the two files inside showcase/kairune-verifiable-trust/. --- showcase/kairune-verifiable-trust/README.md | 7 +++++++ showcase/kairune-verifiable-trust/showcase.json | 7 ++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/showcase/kairune-verifiable-trust/README.md b/showcase/kairune-verifiable-trust/README.md index 9da4bd1..e78fe07 100644 --- a/showcase/kairune-verifiable-trust/README.md +++ b/showcase/kairune-verifiable-trust/README.md @@ -31,6 +31,12 @@ Backward compatible — existing unsigned submissions still work, recorded as one. Reads and the spend dry-run stay open so a payment rail still gets a go/no-go signal. It is opt-in, so an agent that never locks is still open — making it mandatory would strand every agent registered before the feature. +- **A published SDK.** `@kairune/sdk@0.4.0` on npm, zero dependencies, native + `fetch`. Pass a `signOwnerMessage` signer once and `lockAgent()`, + `unlockAgent()` and `getOwnerLock()` are available; every mutating call that + comes back `401` because the agent turned out to be locked is signed and + retried exactly once. An unlocked agent pays nothing for this — no extra + round trip is made unless the server actually refuses. - **A film of the refusal.** The 0:13 demo walks the whole arc, including the part most demos leave out: the agent asks for a budget while UNRATED and is turned down. It earns attestations, crosses 250, asks again, and gets a @@ -38,6 +44,7 @@ Backward compatible — existing unsigned submissions still work, recorded as ## Proof - Self-serve film (0:13): https://kairune.online/assets/video/kairune-self-serve.mp4 +- SDK on npm (`@kairune/sdk@0.4.0`): https://www.npmjs.com/package/@kairune/sdk - Animated demo: `assets/kairune-verify-demo.mp4` - Live console: https://kairune.online/app - API meta (`wallet_proof: eip191-personal-sign`, `signature_algorithm: ed25519`): https://kairune.online/api/meta diff --git a/showcase/kairune-verifiable-trust/showcase.json b/showcase/kairune-verifiable-trust/showcase.json index 74d6f8d..90dcdfa 100644 --- a/showcase/kairune-verifiable-trust/showcase.json +++ b/showcase/kairune-verifiable-trust/showcase.json @@ -2,7 +2,7 @@ "slug": "kairune-verifiable-trust", "title": "Kairune — Verifiable Agent Trust Layer", "tagline": "Earn a budget with signed attestations, a proven wallet, and a spend ceiling it can't cross", - "description": "Kairune is the trust layer for AI agents that spend, and it is now self-serve end to end: an agent registers, earns attestations, crosses a tier threshold, grants itself a scoped budget, spends against it, and revokes — with no platform admin key anywhere in that path. Authorisation comes from the trust tier instead: an agent below EMERGING (score 250) is refused a budget with 409 tier_too_low, because there is no behavioural basis to extend it credit yet. Both sides of the record are verifiable. Attestation issuers register Ed25519 keys and sign each attestation; the server verifies every signature and weights verified attestations fully while discounting unsigned ones (0.25x). The wallet an agent claims can be proven with an EIP-191 personal_sign challenge (chain 4663, 600s TTL) without the private key ever leaving the wallet. Spend enforcement is live — over-ceiling charges are blocked with 409 ceiling_exceeded and every decision fires an HMAC-SHA256 signed webhook. Exposed as ACP offerings (lookup score, register agent, record attestation, full report) on Robinhood Chain via Virtuals.", + "description": "Kairune is a trust layer for AI agents that spend. It's self-serve end to end: an agent earns a trust score from signed attestations, proves wallet control via EIP-191, and is granted a spend budget based on its tier — no admin key required. Below EMERGING the grant is refused (409 tier_too_low); over-ceiling charges are blocked and every decision fires an HMAC-SHA256 signed webhook. An operator can lock an agent to its wallet: mutating routes then demand a fresh single-use X-Owner-Proof and return 401 without one, which @kairune/sdk@0.4.0 mints on the caller's behalf. Exposed as live APIs, paid ACP offerings on Robinhood Chain via Virtuals, and the SDK.", "status": "live", "topic": "commerce", "topics": ["agents", "commerce", "security"], @@ -82,6 +82,11 @@ "href": "https://kairune.online/docs", "kind": "docs" }, + { + "label": "SDK on npm — @kairune/sdk@0.4.0, zero dependencies, lockAgent() plus auto-proof retry on 401", + "href": "https://www.npmjs.com/package/@kairune/sdk", + "kind": "docs" + }, { "label": "Public repo", "href": "https://github.com/kairunedev/Kairune", From dd185c85ca3f55e664f808dc118738183a1d2b0d Mon Sep 17 00:00:00 2001 From: root Date: Fri, 4 Sep 2026 17:59:52 +0700 Subject: [PATCH 8/8] docs(kairune): teach the skill the corroboration ceiling The trust engine gained a third rule that can decide a score, so an agent reading this skill could see boundBy: "corroboration-ceiling" with no idea how to interpret it. Documented all three boundBy values, plus the trust-sources endpoint that explains the cap and what lifts it. The redacted example went stale in a useful way. It quoted voyager-07 at 668 bound by misconduct-ratio; live it now reads 600 bound by corroboration-ceiling, with 668 surviving as earnedScore. Refreshed against the live endpoint rather than invented, and the note now explains that two rules are pushing the score down while only the stricter one is reported. The substance: 2328 attestations bought that agent no more standing than a few hundred would have, because it wrote them about itself. Volume is not evidence when the subject authors its own record. The skill already advised treating unverified-heavy scores as weaker; that is now enforced by the engine instead of left to the caller's judgment. --- .../kairune-verify-agent-trust/SKILL.md | 57 +++++++++++++----- .../examples/result-redacted.md | 58 +++++++++++++++---- 2 files changed, 89 insertions(+), 26 deletions(-) diff --git a/showcase/kairune-verifiable-trust/skills/kairune-verify-agent-trust/SKILL.md b/showcase/kairune-verifiable-trust/skills/kairune-verify-agent-trust/SKILL.md index 7d306d9..24d5046 100644 --- a/showcase/kairune-verifiable-trust/skills/kairune-verify-agent-trust/SKILL.md +++ b/showcase/kairune-verifiable-trust/skills/kairune-verify-agent-trust/SKILL.md @@ -54,11 +54,23 @@ clear the bar. - Prefer agents whose score is backed by **verified** attestations; treat a score built mostly on `unverified` attestations as weaker (Kairune already discounts unverified data at 0.25×). -- Read `breakdown.boundBy`. When it is `misconduct-ratio`, disputes and - chargebacks are a large enough share of the agent's record that the score was - reduced proportionally, and `breakdown.integrityFactor` is how much survived - (1 = a spotless record, 0.6 = roughly 40% withheld). A tier alone will not tell - you this. +- Read `breakdown.boundBy`. It names which rule actually decided the score: + - `additive` — the score is what the agent's history earned. + - `misconduct-ratio` — disputes and chargebacks are a large enough share of the + record that the score was reduced proportionally, and + `breakdown.integrityFactor` is how much survived (1 = a spotless record, + 0.6 = roughly 40% withheld). + - `corroboration-ceiling` — the agent earned more than it can prove. Nobody + independent has attested to it, so its score is capped regardless of volume. + Compare `breakdown.earnedScore` against `breakdown.corroborationCeiling` to + see the gap. A large gap means a long history that no third party will vouch + for; treat that as weaker than a shorter, corroborated one. + A tier alone will not tell you any of this. +- Volume is not evidence. An agent can post attestations about itself, so with + zero verified issuers a score cannot exceed 600 and cannot present as TRUSTED + or PRIME no matter how many rows exist. Each independent verified issuer lifts + that cap by 100. Read `distinct_issuers` from the trust-sources endpoint before + reading a high score as a track record. - Re-check just before granting; scores change as behavior is attested. - Never fabricate or infer a score that was not returned by Kairune. @@ -73,6 +85,8 @@ Stop and defer to the caller (return `review` or `deny`) when: required verified backing. - `breakdown.integrityFactor` is well below 1 and the caller has not explicitly accepted counterparties with a dispute history. +- `breakdown.boundBy` is `corroboration-ceiling` and the caller expected the + agent's standing to be independently attested. - Kairune is unreachable or returns an error — never assume a passing score on failure. @@ -84,6 +98,9 @@ Reads are free and unauthenticated: # Score, tier, breakdown (verified/unverified counts), suggested ceiling curl -s https://kairune.online/api/agents/ +# Who vouched for this agent, and the score ceiling that breadth earns +curl -s https://kairune.online/api/agents//trust-sources + # Scoring metadata (tier thresholds, unverified_weight_factor, algorithm) curl -s https://kairune.online/api/meta @@ -92,8 +109,13 @@ curl -s https://kairune.online/api/meta ``` Relevant fields on the agent detail: `score`, `tier`, `label`, -`suggested_daily_ceiling`, `status`, and `breakdown.verifiedCount` / -`breakdown.unverifiedCount`. +`suggested_daily_ceiling`, `status`, `breakdown.verifiedCount` / +`breakdown.unverifiedCount`, and `breakdown.boundBy` with its companions +`breakdown.earnedScore` / `breakdown.corroborationCeiling`. + +On trust-sources: `distinct_issuers`, `score_ceiling`, +`score_ceiling_next_issuer`, and `issuers_to_remove_ceiling` (how many +independent issuers it would take before the cap stops applying at all). ## ACP Command Pattern @@ -114,10 +136,12 @@ Provider agent: https://app.virtuals.io/virtuals/100623 2. Resolve the counterparty by handle or id (live API mode) or open the matching ACP offering (ACP mode). 3. Fetch the agent detail; confirm `status` is `active`. -4. Read `score`, `tier`, `label`, `suggested_daily_ceiling`, and the - verified/unverified attestation counts. +4. Read `score`, `tier`, `label`, `suggested_daily_ceiling`, the + verified/unverified attestation counts, and `breakdown.boundBy`. 5. Apply the caller's policy: tier ≥ minimum, amount ≤ `suggested_daily_ceiling`, - and verified-backing requirement if set. + and verified-backing requirement if set. When `boundBy` is + `corroboration-ceiling`, the history is self-reported — weigh it accordingly + rather than reading the raw score as earned standing. 6. Return a decision: `allow`, `review`, or `deny`, with the capped amount and a one-line reason. 7. If `allow`, grant only up to the capped amount and re-check before any future @@ -143,6 +167,8 @@ Provider agent: https://app.virtuals.io/virtuals/100623 - [ ] Tier ≥ caller's minimum acceptable tier. - [ ] Intended amount ≤ `suggested_daily_ceiling` (else capped). - [ ] Verified-backing requirement satisfied if the caller set one. +- [ ] `breakdown.boundBy` read, and a `corroboration-ceiling` result treated as + self-reported history rather than earned standing. - [ ] Decision, capped amount, and reason returned. - [ ] No secrets in output. @@ -153,21 +179,24 @@ Return a single JSON object: ```json { "handle": "voyager-07", - "score": 668, + "score": 600, "tier": 2, "label": "ESTABLISHED", "suggested_daily_ceiling": 150, "verified_count": 0, - "unverified_count": 2327, + "unverified_count": 2328, + "distinct_issuers": 0, + "bound_by": "corroboration-ceiling", "decision": "review", "granted_ceiling": 0, - "reason": "Tier 2 >= min tier 2, but 0 of 2327 attestations are signed and the caller required verified backing." + "reason": "Tier 2 >= min tier 2, but 0 of 2328 attestations are signed and no independent issuer has attested, so the score is capped rather than earned." } ``` `decision` is one of `allow`, `review`, `deny`. `granted_ceiling` is the lower of the caller's intended amount and `suggested_daily_ceiling`, and is `0` when the -decision is not `allow`. +decision is not `allow`. `bound_by` carries `breakdown.boundBy` through so the +caller can see which rule decided the score. ## References diff --git a/showcase/kairune-verifiable-trust/skills/kairune-verify-agent-trust/examples/result-redacted.md b/showcase/kairune-verifiable-trust/skills/kairune-verify-agent-trust/examples/result-redacted.md index 4350f07..3d49d6d 100644 --- a/showcase/kairune-verifiable-trust/skills/kairune-verify-agent-trust/examples/result-redacted.md +++ b/showcase/kairune-verifiable-trust/skills/kairune-verify-agent-trust/examples/result-redacted.md @@ -20,43 +20,77 @@ GET https://kairune.online/api/agents/voyager-07 "agent": { "handle": "voyager-07", "status": "active", - "score": 668, + "score": 600, "tier": 2, "label": "ESTABLISHED", "suggested_daily_ceiling": 150, "breakdown": { "verifiedCount": 0, - "unverifiedCount": 2327, + "unverifiedCount": 2328, "integrityFactor": 0.668, - "boundBy": "misconduct-ratio" + "earnedScore": 668, + "corroborationCeiling": 600, + "corroborationCapped": true, + "boundBy": "corroboration-ceiling" } } } ``` +And the companion read, which explains *why* the score stops where it does: + +``` +GET https://kairune.online/api/agents/voyager-07/trust-sources +``` + +```json +{ + "verified_count": 0, + "unverified_count": 2328, + "distinct_issuers": 0, + "score_ceiling": 600, + "score_ceiling_next_issuer": 700, + "issuers_to_remove_ceiling": 4 +} +``` + **Decision:** ```json { "handle": "voyager-07", - "score": 668, + "score": 600, "tier": 2, "label": "ESTABLISHED", "suggested_daily_ceiling": 150, "verified_count": 0, - "unverified_count": 2327, + "unverified_count": 2328, + "distinct_issuers": 0, + "bound_by": "corroboration-ceiling", "decision": "review", "granted_ceiling": 0, - "reason": "Tier 2 >= min tier 2 and amount 100 <= ceiling 150, but the caller required mostly-verified backing and 0 of 2327 attestations are signed. Escalate rather than grant." + "reason": "Tier 2 >= min tier 2 and amount 100 <= ceiling 150, but 0 of 2328 attestations are signed and no independent issuer has attested, so the score is capped at 600 rather than earned. Escalate rather than grant." } ``` **Notes:** No credentials were used (reads are public). No API keys, signatures, or private key material appear in the request or response. -The numbers above were read from the live endpoint, so they show something an -invented example would have hidden: this agent's score is bound by -`misconduct-ratio`, not by the plain additive path. `integrityFactor: 0.668` -means roughly a third of the score was withheld because disputes and chargebacks -make up a measurable share of its record. Re-read the endpoint before relying on -any specific value — scores move as attestations land. +The numbers above were read from the live endpoint, so they show two things an +invented example would have hidden. + +First, two separate rules are pushing this score down and only the stricter one +is reported. `integrityFactor: 0.668` means roughly a third was withheld because +disputes and chargebacks make up a measurable share of the record — that alone +put the agent at 668. But `distinct_issuers` is 0, so the corroboration ceiling +caps it at 600 and `boundBy` names that instead. `earnedScore` is where the +history would have landed; `score` is what it can actually prove. + +Second, 2328 attestations produced no more standing than a few hundred would +have. Volume is not evidence when the subject can write its own record. This is +the case the skill exists to catch: a big number that looks like a track record +and isn't. + +Re-read the endpoint before relying on any specific value — scores move as +attestations land, and this agent's will move the moment someone independent +vouches for it.