kairos-chain 2.6.0 → 2.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +35 -0
- data/lib/kairos_mcp/http_server.rb +11 -0
- data/lib/kairos_mcp/meeting_router.rb +3 -0
- data/lib/kairos_mcp/version.rb +1 -1
- data/templates/knowledge/synoptis_attestation/synoptis_attestation.md +157 -0
- data/templates/knowledge/synoptis_attestation_jp/synoptis_attestation_jp.md +157 -0
- data/templates/skillsets/mmp/config/meeting.yml +1 -1
- data/templates/skillsets/mmp/lib/mmp/peer_manager.rb +6 -2
- data/templates/skillsets/mmp/lib/mmp/protocol.rb +63 -8
- data/templates/skillsets/synoptis/config/synoptis.yml +31 -0
- data/templates/skillsets/synoptis/knowledge/synoptis_protocol/synoptis_protocol.md +84 -0
- data/templates/skillsets/synoptis/lib/synoptis/attestation_engine.rb +81 -0
- data/templates/skillsets/synoptis/lib/synoptis/challenge_manager.rb +90 -0
- data/templates/skillsets/synoptis/lib/synoptis/proof_envelope.rb +92 -0
- data/templates/skillsets/synoptis/lib/synoptis/registry/file_registry.rb +148 -0
- data/templates/skillsets/synoptis/lib/synoptis/revocation_manager.rb +37 -0
- data/templates/skillsets/synoptis/lib/synoptis/tool_helpers.rb +85 -0
- data/templates/skillsets/synoptis/lib/synoptis/transport/base_transport.rb +31 -0
- data/templates/skillsets/synoptis/lib/synoptis/transport/hestia_transport.rb +46 -0
- data/templates/skillsets/synoptis/lib/synoptis/transport/local_transport.rb +45 -0
- data/templates/skillsets/synoptis/lib/synoptis/transport/mmp_transport.rb +104 -0
- data/templates/skillsets/synoptis/lib/synoptis/trust_scorer.rb +100 -0
- data/templates/skillsets/synoptis/lib/synoptis/verifier.rb +50 -0
- data/templates/skillsets/synoptis/lib/synoptis.rb +93 -0
- data/templates/skillsets/synoptis/skillset.json +22 -0
- data/templates/skillsets/synoptis/test/test_synoptis.rb +457 -0
- data/templates/skillsets/synoptis/tools/attestation_issue.rb +65 -0
- data/templates/skillsets/synoptis/tools/attestation_list.rb +61 -0
- data/templates/skillsets/synoptis/tools/attestation_revoke.rb +58 -0
- data/templates/skillsets/synoptis/tools/attestation_verify.rb +55 -0
- data/templates/skillsets/synoptis/tools/challenge_create.rb +61 -0
- data/templates/skillsets/synoptis/tools/challenge_respond.rb +60 -0
- data/templates/skillsets/synoptis/tools/trust_query.rb +54 -0
- metadata +29 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ffb5f6c69245852c1c1f9991cac0098bf630f460a35bc72d5cda24eef290218f
|
|
4
|
+
data.tar.gz: 60a22caeaf0abcd7433a9f518aac3b4553d48f395f5e8ea70dca69fff3c735f5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6121a1dded568c8035a6c4a89c2aaded921d42559b7ae491c898a0648dffa52bc66f784fc08d9de04b8304db2c303a75727fb8b90a28e35007455055a8cfaf68
|
|
7
|
+
data.tar.gz: '0892de4a22da8c86df601b1b6c4523207adee72988eeb3d982ddeae625181fa04ac7322b4d698d18c8b76684e5693931c2cacf4950933b61f808ead59937a6e0'
|
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,40 @@ All notable changes to the `kairos-chain` gem will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
This project follows [Semantic Versioning](https://semver.org/).
|
|
6
6
|
|
|
7
|
+
## [2.7.0] - 2026-03-06
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **Synoptis Mutual Attestation SkillSet**: New opt-in SkillSet for cross-agent trust verification through cryptographically signed proof envelopes
|
|
12
|
+
- `ProofEnvelope`: Signed attestation data structure with Merkle root and content hash
|
|
13
|
+
- `Verifier`: Structural + cryptographic verification with mandatory signature checks
|
|
14
|
+
- `AttestationEngine`: Attestation lifecycle (create, verify, list) with re-issuance prevention
|
|
15
|
+
- `RevocationManager`: Authorization-checked revocation (original attester or admin only)
|
|
16
|
+
- `ChallengeManager`: Challenge/response lifecycle (validity, evidence_request, re_verification)
|
|
17
|
+
- `TrustScorer`: Weighted composite trust score (quality, freshness, diversity, velocity, revocation penalty)
|
|
18
|
+
- `Registry::FileRegistry`: Append-only JSONL storage with hash-chain integrity (`_prev_entry_hash`) implementing constitutive recording (Proposition 5)
|
|
19
|
+
- `Transport`: Abstraction layer for MMP, Hestia, and Local transport mechanisms
|
|
20
|
+
- 7 MCP tools: `attestation_issue`, `attestation_verify`, `attestation_revoke`, `attestation_list`, `trust_query`, `challenge_create`, `challenge_respond`
|
|
21
|
+
- 88 unit tests
|
|
22
|
+
|
|
23
|
+
- **MMP Handler Extension Mechanism**: `MMP::Protocol.register_handler` allows SkillSets to register custom MMP actions without modifying core protocol code. Thread-safe with Mutex, built-in action override prevention.
|
|
24
|
+
|
|
25
|
+
- **MMP Bearer Token Authentication**: `MMP::PeerManager` now includes `session_token` in Peer struct, extracted during `introduce_to` handshake and sent as `Authorization: Bearer` header on all subsequent messages.
|
|
26
|
+
|
|
27
|
+
- **MeetingRouter Authenticated Peer Injection**: `MeetingRouter#handle_message` injects `_authenticated_peer_id` into message body, enabling receiving handlers to verify sender identity.
|
|
28
|
+
|
|
29
|
+
- **SkillSet Eager Loading in HTTP Mode**: `HttpServer` now calls `eager_load_skillsets` during initialization, ensuring SkillSet MMP handlers are registered before the first HTTP request.
|
|
30
|
+
|
|
31
|
+
- **L1 Knowledge**: Synoptis attestation knowledge (EN/JP) with `readme_order: 4.7` for auto-generated README inclusion.
|
|
32
|
+
|
|
33
|
+
- **Self-Development Workflow v1.2**: Added SkillSet Release Checklist to `kairoschain_self_development` knowledge (EN/JP) — covers L1 knowledge creation for README, `rake build_readme`, version/changelog updates, and gem build/publish.
|
|
34
|
+
|
|
35
|
+
### Changed
|
|
36
|
+
|
|
37
|
+
- **MMP SkillSet**: `meeting.yml` default changed from `enabled: false` to `enabled: true`
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
7
41
|
## [2.6.0] - 2026-03-05
|
|
8
42
|
|
|
9
43
|
### Added
|
|
@@ -315,6 +349,7 @@ This project follows [Semantic Versioning](https://semver.org/).
|
|
|
315
349
|
- Skill promotion with Persona Assembly
|
|
316
350
|
- Tool guide and metadata system
|
|
317
351
|
|
|
352
|
+
[2.7.0]: https://github.com/masaomi/KairosChain_2026/compare/v2.6.0...v2.7.0
|
|
318
353
|
[2.6.0]: https://github.com/masaomi/KairosChain_2026/compare/v2.5.0...v2.6.0
|
|
319
354
|
[2.5.0]: https://github.com/masaomi/KairosChain_2026/compare/v2.4.0...v2.5.0
|
|
320
355
|
[2.4.0]: https://github.com/masaomi/KairosChain_2026/compare/v2.3.1...v2.4.0
|
|
@@ -54,6 +54,17 @@ module KairosMcp
|
|
|
54
54
|
@admin_router = Admin::Router.new(token_store: @token_store, authenticator: @authenticator)
|
|
55
55
|
@meeting_router = MeetingRouter.new
|
|
56
56
|
@place_router = nil # Initialized lazily via meeting_place_start tool
|
|
57
|
+
|
|
58
|
+
eager_load_skillsets
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Load SkillSets at startup so /meeting/* endpoints work immediately.
|
|
62
|
+
# Without this, MMP module is not defined until the first MCP request.
|
|
63
|
+
def eager_load_skillsets
|
|
64
|
+
require_relative 'skillset_manager'
|
|
65
|
+
SkillSetManager.new.enabled_skillsets.each(&:load!)
|
|
66
|
+
rescue StandardError => e
|
|
67
|
+
$stderr.puts "[HttpServer] SkillSet eager load: #{e.message}"
|
|
57
68
|
end
|
|
58
69
|
|
|
59
70
|
# Start the HTTP server with Puma
|
|
@@ -206,8 +206,10 @@ module KairosMcp
|
|
|
206
206
|
end
|
|
207
207
|
|
|
208
208
|
# POST /meeting/v1/message - Generic MMP message handler
|
|
209
|
+
# Injects authenticated peer_id to prevent from: spoofing in extended handlers.
|
|
209
210
|
def handle_message(env)
|
|
210
211
|
body = parse_body(env)
|
|
212
|
+
body['_authenticated_peer_id'] = env['meeting.authenticated_peer_id']
|
|
211
213
|
result = protocol.process_message(body)
|
|
212
214
|
json_response(200, result)
|
|
213
215
|
end
|
|
@@ -453,6 +455,7 @@ module KairosMcp
|
|
|
453
455
|
})
|
|
454
456
|
end
|
|
455
457
|
|
|
458
|
+
env['meeting.authenticated_peer_id'] = peer_id
|
|
456
459
|
nil # Authentication passed
|
|
457
460
|
end
|
|
458
461
|
|
data/lib/kairos_mcp/version.rb
CHANGED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: synoptis_attestation
|
|
3
|
+
description: "Synoptis Mutual Attestation — cross-agent trust verification through cryptographic proof envelopes"
|
|
4
|
+
version: 1.0
|
|
5
|
+
layer: L1
|
|
6
|
+
tags: [documentation, readme, synoptis, attestation, trust, p2p, audit, challenge]
|
|
7
|
+
readme_order: 4.7
|
|
8
|
+
readme_lang: en
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Synoptis: Mutual Attestation Protocol (v2.7.0)
|
|
12
|
+
|
|
13
|
+
### What is Synoptis?
|
|
14
|
+
|
|
15
|
+
Synoptis is an opt-in SkillSet for cross-agent trust verification through cryptographically signed attestation proofs. It enables agents to attest to facts about any subject (knowledge entries, skill hashes, chain blocks, pipeline outputs, etc.), and provides mechanisms to verify, revoke, and challenge those attestations.
|
|
16
|
+
|
|
17
|
+
Synoptis is implemented entirely as a SkillSet, preserving KairosChain's principle that new capabilities are expressed as SkillSets rather than core modifications.
|
|
18
|
+
|
|
19
|
+
### Architecture
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
KairosChain (MCP Server)
|
|
23
|
+
├── [core] L0/L1/L2 + private blockchain
|
|
24
|
+
├── [SkillSet: mmp] P2P direct mode, /meeting/v1/*
|
|
25
|
+
├── [SkillSet: hestia] Meeting Place + trust anchor
|
|
26
|
+
└── [SkillSet: synoptis] Mutual attestation protocol
|
|
27
|
+
├── ProofEnvelope ← Signed attestation data structure
|
|
28
|
+
├── Verifier ← Structural + cryptographic verification
|
|
29
|
+
├── AttestationEngine ← Attestation lifecycle (create, verify, list)
|
|
30
|
+
├── RevocationManager ← Revocation with authorization checks
|
|
31
|
+
├── ChallengeManager ← Challenge/response lifecycle
|
|
32
|
+
├── TrustScorer ← Weighted trust score calculation
|
|
33
|
+
├── Registry::FileRegistry ← Append-only JSONL with hash-chain integrity
|
|
34
|
+
├── Transport ← MMP / Hestia / Local transport abstraction
|
|
35
|
+
└── tools/ ← 7 MCP tools
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Quick Start
|
|
39
|
+
|
|
40
|
+
#### 1. Install the synoptis SkillSet
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# Synoptis depends on MMP. Install both:
|
|
44
|
+
kairos-chain skillset install templates/skillsets/mmp
|
|
45
|
+
kairos-chain skillset install templates/skillsets/synoptis
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
#### 2. Issue an attestation
|
|
49
|
+
|
|
50
|
+
In Claude Code / Cursor:
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
"Attest that knowledge/my_skill has been integrity_verified"
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
This calls `attestation_issue(subject_ref: "knowledge/my_skill", claim: "integrity_verified")`.
|
|
57
|
+
|
|
58
|
+
#### 3. Verify and query trust
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
"What is the trust score for knowledge/my_skill?"
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
This calls `trust_query(subject_ref: "knowledge/my_skill")`.
|
|
65
|
+
|
|
66
|
+
### MCP Tools
|
|
67
|
+
|
|
68
|
+
| Tool | Description |
|
|
69
|
+
|------|-------------|
|
|
70
|
+
| `attestation_issue` | Issue a signed attestation proof for a subject |
|
|
71
|
+
| `attestation_verify` | Verify proof validity (structure, signature, expiry, revocation) |
|
|
72
|
+
| `attestation_revoke` | Revoke an attestation (original attester or admin only) |
|
|
73
|
+
| `attestation_list` | List attestations with optional filters (subject_ref, attester_id) |
|
|
74
|
+
| `trust_query` | Calculate trust score based on attestation history |
|
|
75
|
+
| `challenge_create` | Challenge an existing attestation (validity, evidence_request, re_verification) |
|
|
76
|
+
| `challenge_respond` | Respond to a challenge with additional evidence |
|
|
77
|
+
|
|
78
|
+
### MMP Integration
|
|
79
|
+
|
|
80
|
+
Synoptis registers 5 MMP actions via `MMP::Protocol.register_handler`, enabling P2P attestation exchange:
|
|
81
|
+
|
|
82
|
+
| MMP Action | Description |
|
|
83
|
+
|------------|-------------|
|
|
84
|
+
| `attestation_request` | Request an attestation from a peer |
|
|
85
|
+
| `attestation_response` | Respond with a signed ProofEnvelope |
|
|
86
|
+
| `attestation_revoke` | Broadcast a revocation |
|
|
87
|
+
| `challenge_create` | Send a challenge to the original attester |
|
|
88
|
+
| `challenge_respond` | Respond to a challenge over MMP |
|
|
89
|
+
|
|
90
|
+
All P2P messages use Bearer token authentication via `MMP::PeerManager`. The authenticated peer ID is injected by `MeetingRouter` as `_authenticated_peer_id`.
|
|
91
|
+
|
|
92
|
+
### Trust Scoring
|
|
93
|
+
|
|
94
|
+
Trust scores are calculated as a weighted composite:
|
|
95
|
+
|
|
96
|
+
| Factor | Weight | Description |
|
|
97
|
+
|--------|--------|-------------|
|
|
98
|
+
| Quality | 0.30 | Ratio of valid (non-revoked, non-expired) attestations |
|
|
99
|
+
| Freshness | 0.25 | Recency of latest attestation (exponential decay, 24h half-life) |
|
|
100
|
+
| Diversity | 0.25 | Number of unique attesters (capped at 5) |
|
|
101
|
+
| Velocity | 0.10 | Attestation rate in the last 7 days |
|
|
102
|
+
| Revocation penalty | −0.10 | Penalty for revoked attestations |
|
|
103
|
+
|
|
104
|
+
### Registry and Constitutive Recording
|
|
105
|
+
|
|
106
|
+
All attestation data is stored in append-only JSONL files with hash-chain linking (`_prev_entry_hash`). This implements constitutive recording (Proposition 5): each record irreversibly extends the system's history.
|
|
107
|
+
|
|
108
|
+
Registry types:
|
|
109
|
+
- `proofs.jsonl` — Attestation proof envelopes
|
|
110
|
+
- `revocations.jsonl` — Revocation records
|
|
111
|
+
- `challenges.jsonl` — Challenge and response records
|
|
112
|
+
|
|
113
|
+
Use `trust_query` to verify registry integrity — it includes a `registry_integrity.valid` field in its response.
|
|
114
|
+
|
|
115
|
+
### ProofEnvelope Structure
|
|
116
|
+
|
|
117
|
+
```json
|
|
118
|
+
{
|
|
119
|
+
"proof_id": "uuid",
|
|
120
|
+
"attester_id": "agent_instance_id",
|
|
121
|
+
"subject_ref": "knowledge/my_skill",
|
|
122
|
+
"claim": "integrity_verified",
|
|
123
|
+
"evidence": "manual review of hash chain",
|
|
124
|
+
"merkle_root": "sha256_of_content",
|
|
125
|
+
"content_hash": "sha256_of_canonical_json",
|
|
126
|
+
"signature": "rsa_sha256_signature",
|
|
127
|
+
"timestamp": "2026-03-06T12:00:00Z",
|
|
128
|
+
"ttl": 86400,
|
|
129
|
+
"version": "1.0.0"
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Challenge Workflow
|
|
134
|
+
|
|
135
|
+
1. Any agent can call `challenge_create(proof_id, challenge_type, details)` to challenge an attestation
|
|
136
|
+
2. The original attester receives the challenge (via MMP or local notification)
|
|
137
|
+
3. The attester calls `challenge_respond(challenge_id, response, evidence)` with additional evidence
|
|
138
|
+
4. Challenge types: `validity` (proof may be incorrect), `evidence_request` (more evidence needed), `re_verification` (conditions may have changed)
|
|
139
|
+
|
|
140
|
+
### Transport Layer
|
|
141
|
+
|
|
142
|
+
Synoptis supports multiple transport mechanisms:
|
|
143
|
+
|
|
144
|
+
| Transport | Backend | Use Case |
|
|
145
|
+
|-----------|---------|----------|
|
|
146
|
+
| MMP | `MMP::PeerManager` | P2P direct attestation exchange |
|
|
147
|
+
| Hestia | `Hestia::PlaceRouter` | Via Meeting Place (future) |
|
|
148
|
+
| Local | Direct registry access | Single-instance and Multiuser mode |
|
|
149
|
+
|
|
150
|
+
Transport selection is automatic based on available SkillSets.
|
|
151
|
+
|
|
152
|
+
### Dependencies
|
|
153
|
+
|
|
154
|
+
- **Required**: MMP SkillSet (>= 1.0.0)
|
|
155
|
+
- **Optional**: Hestia SkillSet (for Meeting Place transport)
|
|
156
|
+
|
|
157
|
+
For the full protocol specification, install the synoptis SkillSet and refer to its bundled knowledge (`synoptis_protocol`).
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: synoptis_attestation_jp
|
|
3
|
+
description: "Synoptis 相互証明 — 暗号署名付き証明エンベロープによるクロスエージェント信頼検証"
|
|
4
|
+
version: 1.0
|
|
5
|
+
layer: L1
|
|
6
|
+
tags: [documentation, readme, synoptis, attestation, trust, p2p, audit, challenge]
|
|
7
|
+
readme_order: 4.7
|
|
8
|
+
readme_lang: jp
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Synoptis:相互証明プロトコル (v2.7.0)
|
|
12
|
+
|
|
13
|
+
### Synoptis とは
|
|
14
|
+
|
|
15
|
+
Synoptis は、暗号署名付き証明プルーフによるクロスエージェント信頼検証のためのオプトイン SkillSet です。エージェントはあらゆるサブジェクト(知識エントリ、スキルハッシュ、チェーンブロック、パイプライン出力など)に対して事実を証明でき、その証明を検証・取り消し・チャレンジする仕組みを提供します。
|
|
16
|
+
|
|
17
|
+
Synoptis は完全に SkillSet として実装されており、新機能をコアではなく SkillSet として表現するという KairosChain の設計原則を保持しています。
|
|
18
|
+
|
|
19
|
+
### アーキテクチャ
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
KairosChain (MCP Server)
|
|
23
|
+
├── [core] L0/L1/L2 + private blockchain
|
|
24
|
+
├── [SkillSet: mmp] P2P direct mode, /meeting/v1/*
|
|
25
|
+
├── [SkillSet: hestia] Meeting Place + 信頼アンカー
|
|
26
|
+
└── [SkillSet: synoptis] 相互証明プロトコル
|
|
27
|
+
├── ProofEnvelope ← 署名付き証明データ構造
|
|
28
|
+
├── Verifier ← 構造的 + 暗号学的検証
|
|
29
|
+
├── AttestationEngine ← 証明ライフサイクル(作成・検証・一覧)
|
|
30
|
+
├── RevocationManager ← 認可チェック付き取り消し
|
|
31
|
+
├── ChallengeManager ← チャレンジ/応答ライフサイクル
|
|
32
|
+
├── TrustScorer ← 加重信頼スコア計算
|
|
33
|
+
├── Registry::FileRegistry ← ハッシュチェーン付き追記専用 JSONL
|
|
34
|
+
├── Transport ← MMP / Hestia / Local トランスポート抽象
|
|
35
|
+
└── tools/ ← 7 MCP ツール
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### クイックスタート
|
|
39
|
+
|
|
40
|
+
#### 1. synoptis SkillSet のインストール
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# Synoptis は MMP に依存します。両方をインストール:
|
|
44
|
+
kairos-chain skillset install templates/skillsets/mmp
|
|
45
|
+
kairos-chain skillset install templates/skillsets/synoptis
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
#### 2. 証明の発行
|
|
49
|
+
|
|
50
|
+
Claude Code / Cursor で:
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
「knowledge/my_skill の整合性を検証済みとして証明して」
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
これは `attestation_issue(subject_ref: "knowledge/my_skill", claim: "integrity_verified")` を呼び出します。
|
|
57
|
+
|
|
58
|
+
#### 3. 検証と信頼クエリ
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
「knowledge/my_skill の信頼スコアは?」
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
これは `trust_query(subject_ref: "knowledge/my_skill")` を呼び出します。
|
|
65
|
+
|
|
66
|
+
### MCP ツール
|
|
67
|
+
|
|
68
|
+
| ツール | 説明 |
|
|
69
|
+
|--------|------|
|
|
70
|
+
| `attestation_issue` | サブジェクトに対する署名付き証明プルーフを発行 |
|
|
71
|
+
| `attestation_verify` | プルーフの有効性を検証(構造、署名、有効期限、取り消し) |
|
|
72
|
+
| `attestation_revoke` | 証明を取り消し(元の証明者または管理者のみ) |
|
|
73
|
+
| `attestation_list` | 証明一覧を表示(subject_ref、attester_id でフィルタ可能) |
|
|
74
|
+
| `trust_query` | 証明履歴に基づく信頼スコアを計算 |
|
|
75
|
+
| `challenge_create` | 既存の証明にチャレンジ(validity、evidence_request、re_verification) |
|
|
76
|
+
| `challenge_respond` | チャレンジに追加証拠で応答 |
|
|
77
|
+
|
|
78
|
+
### MMP 統合
|
|
79
|
+
|
|
80
|
+
Synoptis は `MMP::Protocol.register_handler` 経由で5つの MMP アクションを登録し、P2P 証明交換を可能にします:
|
|
81
|
+
|
|
82
|
+
| MMP アクション | 説明 |
|
|
83
|
+
|---------------|------|
|
|
84
|
+
| `attestation_request` | ピアに証明をリクエスト |
|
|
85
|
+
| `attestation_response` | 署名付き ProofEnvelope で応答 |
|
|
86
|
+
| `attestation_revoke` | 取り消しをブロードキャスト |
|
|
87
|
+
| `challenge_create` | 元の証明者にチャレンジを送信 |
|
|
88
|
+
| `challenge_respond` | MMP 経由でチャレンジに応答 |
|
|
89
|
+
|
|
90
|
+
すべての P2P メッセージは `MMP::PeerManager` 経由の Bearer トークン認証を使用します。認証済みピア ID は `MeetingRouter` が `_authenticated_peer_id` として注入します。
|
|
91
|
+
|
|
92
|
+
### 信頼スコアリング
|
|
93
|
+
|
|
94
|
+
信頼スコアは加重複合値として計算されます:
|
|
95
|
+
|
|
96
|
+
| 要素 | 重み | 説明 |
|
|
97
|
+
|------|------|------|
|
|
98
|
+
| 品質 (Quality) | 0.30 | 有効な(未取消・未期限切れ)証明の比率 |
|
|
99
|
+
| 鮮度 (Freshness) | 0.25 | 最新証明の新しさ(指数減衰、24時間半減期) |
|
|
100
|
+
| 多様性 (Diversity) | 0.25 | ユニーク証明者の数(上限5) |
|
|
101
|
+
| 速度 (Velocity) | 0.10 | 過去7日間の証明レート |
|
|
102
|
+
| 取消ペナルティ | −0.10 | 取り消された証明に対するペナルティ |
|
|
103
|
+
|
|
104
|
+
### レジストリと構成的記録
|
|
105
|
+
|
|
106
|
+
すべての証明データはハッシュチェーン連結(`_prev_entry_hash`)付きの追記専用 JSONL ファイルに保存されます。これは構成的記録(命題5)を実装しています:各レコードはシステムの履歴を不可逆的に拡張します。
|
|
107
|
+
|
|
108
|
+
レジストリ種別:
|
|
109
|
+
- `proofs.jsonl` — 証明プルーフエンベロープ
|
|
110
|
+
- `revocations.jsonl` — 取り消しレコード
|
|
111
|
+
- `challenges.jsonl` — チャレンジと応答レコード
|
|
112
|
+
|
|
113
|
+
`trust_query` でレジストリの整合性を検証できます — 応答に `registry_integrity.valid` フィールドが含まれます。
|
|
114
|
+
|
|
115
|
+
### ProofEnvelope 構造
|
|
116
|
+
|
|
117
|
+
```json
|
|
118
|
+
{
|
|
119
|
+
"proof_id": "uuid",
|
|
120
|
+
"attester_id": "agent_instance_id",
|
|
121
|
+
"subject_ref": "knowledge/my_skill",
|
|
122
|
+
"claim": "integrity_verified",
|
|
123
|
+
"evidence": "ハッシュチェーンの手動レビュー",
|
|
124
|
+
"merkle_root": "sha256_of_content",
|
|
125
|
+
"content_hash": "sha256_of_canonical_json",
|
|
126
|
+
"signature": "rsa_sha256_signature",
|
|
127
|
+
"timestamp": "2026-03-06T12:00:00Z",
|
|
128
|
+
"ttl": 86400,
|
|
129
|
+
"version": "1.0.0"
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### チャレンジワークフロー
|
|
134
|
+
|
|
135
|
+
1. 任意のエージェントが `challenge_create(proof_id, challenge_type, details)` で証明にチャレンジ
|
|
136
|
+
2. 元の証明者がチャレンジを受信(MMP またはローカル通知)
|
|
137
|
+
3. 証明者が `challenge_respond(challenge_id, response, evidence)` で追加証拠とともに応答
|
|
138
|
+
4. チャレンジ種別:`validity`(プルーフが正しくない可能性)、`evidence_request`(追加証拠が必要)、`re_verification`(条件が変化した可能性)
|
|
139
|
+
|
|
140
|
+
### トランスポート層
|
|
141
|
+
|
|
142
|
+
Synoptis は複数のトランスポート機構をサポートします:
|
|
143
|
+
|
|
144
|
+
| トランスポート | バックエンド | 用途 |
|
|
145
|
+
|--------------|------------|------|
|
|
146
|
+
| MMP | `MMP::PeerManager` | P2P 直接証明交換 |
|
|
147
|
+
| Hestia | `Hestia::PlaceRouter` | Meeting Place 経由(将来) |
|
|
148
|
+
| Local | レジストリ直接アクセス | シングルインスタンスおよび Multiuser モード |
|
|
149
|
+
|
|
150
|
+
トランスポート選択は利用可能な SkillSet に基づいて自動的に行われます。
|
|
151
|
+
|
|
152
|
+
### 依存関係
|
|
153
|
+
|
|
154
|
+
- **必須**: MMP SkillSet (>= 1.0.0)
|
|
155
|
+
- **オプション**: Hestia SkillSet(Meeting Place トランスポート用)
|
|
156
|
+
|
|
157
|
+
プロトコルの完全な仕様については、synoptis SkillSet をインストールし、同梱の knowledge(`synoptis_protocol`)を参照してください。
|
|
@@ -13,6 +13,7 @@ module MMP
|
|
|
13
13
|
|
|
14
14
|
Peer = Struct.new(:id, :name, :url, :status, :last_seen, :introduction,
|
|
15
15
|
:extensions, :added_at, :public_key, :verified,
|
|
16
|
+
:session_token,
|
|
16
17
|
keyword_init: true)
|
|
17
18
|
|
|
18
19
|
def initialize(identity:, config: {}, data_dir: nil)
|
|
@@ -110,6 +111,7 @@ module MMP
|
|
|
110
111
|
response = http_post("#{peer.url}/meeting/v1/introduce", my_intro)
|
|
111
112
|
if response && response[:status] == 'received'
|
|
112
113
|
peer.introduction = response[:peer_identity] if response[:peer_identity]
|
|
114
|
+
peer.session_token = response[:session_token] if response[:session_token]
|
|
113
115
|
peer.last_seen = Time.now.utc
|
|
114
116
|
save_peers
|
|
115
117
|
end
|
|
@@ -119,7 +121,8 @@ module MMP
|
|
|
119
121
|
def send_message(peer_id, message)
|
|
120
122
|
peer = @peers[peer_id]
|
|
121
123
|
return nil unless peer
|
|
122
|
-
|
|
124
|
+
auth = peer.session_token ? { 'Authorization' => "Bearer #{peer.session_token}" } : {}
|
|
125
|
+
response = http_post("#{peer.url}/meeting/v1/message", message, headers: auth)
|
|
123
126
|
peer.last_seen = Time.now.utc if response
|
|
124
127
|
response
|
|
125
128
|
end
|
|
@@ -224,7 +227,7 @@ module MMP
|
|
|
224
227
|
nil
|
|
225
228
|
end
|
|
226
229
|
|
|
227
|
-
def http_post(url, data)
|
|
230
|
+
def http_post(url, data, headers: {})
|
|
228
231
|
uri = URI.parse(url)
|
|
229
232
|
http = Net::HTTP.new(uri.host, uri.port)
|
|
230
233
|
http.open_timeout = @timeout
|
|
@@ -232,6 +235,7 @@ module MMP
|
|
|
232
235
|
request = Net::HTTP::Post.new(uri.request_uri)
|
|
233
236
|
request['Content-Type'] = 'application/json'
|
|
234
237
|
request['Accept'] = 'application/json'
|
|
238
|
+
headers.each { |k, v| request[k] = v }
|
|
235
239
|
request.body = JSON.generate(data)
|
|
236
240
|
response = http.request(request)
|
|
237
241
|
return nil unless response.is_a?(Net::HTTPSuccess)
|
|
@@ -16,6 +16,49 @@ module MMP
|
|
|
16
16
|
propose_extension evaluate_extension adopt_extension share_extension
|
|
17
17
|
].freeze
|
|
18
18
|
|
|
19
|
+
# Generic handler extension mechanism for other SkillSets.
|
|
20
|
+
# Completes the ProtocolLoader design: action names + handlers in one step.
|
|
21
|
+
class << self
|
|
22
|
+
def handler_mutex
|
|
23
|
+
@handler_mutex ||= Mutex.new
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def register_handler(action, &block)
|
|
27
|
+
handler_mutex.synchronize do
|
|
28
|
+
action_str = action.to_s
|
|
29
|
+
raise ArgumentError, "Cannot override built-in action: #{action_str}" if ACTIONS.include?(action_str)
|
|
30
|
+
|
|
31
|
+
@extended_handlers ||= {}
|
|
32
|
+
@extended_actions ||= []
|
|
33
|
+
@extended_handlers[action_str] = block
|
|
34
|
+
@extended_actions << action_str unless @extended_actions.include?(action_str)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def unregister_handler(action)
|
|
39
|
+
handler_mutex.synchronize do
|
|
40
|
+
action_str = action.to_s
|
|
41
|
+
@extended_handlers&.delete(action_str)
|
|
42
|
+
@extended_actions&.delete(action_str)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def extended_handler(action)
|
|
47
|
+
handler_mutex.synchronize { @extended_handlers&.dig(action.to_s) }
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def extended_actions
|
|
51
|
+
handler_mutex.synchronize { (@extended_actions || []).dup }
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def clear_extended_handlers!
|
|
55
|
+
handler_mutex.synchronize do
|
|
56
|
+
@extended_handlers = {}
|
|
57
|
+
@extended_actions = []
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
19
62
|
attr_reader :protocol_loader, :supported_extensions, :evolution, :compatibility
|
|
20
63
|
|
|
21
64
|
Message = Struct.new(:id, :action, :from, :to, :timestamp, :payload, :in_reply_to, :protocol_version, keyword_init: true) do
|
|
@@ -56,11 +99,13 @@ module MMP
|
|
|
56
99
|
end
|
|
57
100
|
|
|
58
101
|
def supported_actions
|
|
59
|
-
if @protocol_loader&.available_actions&.any?
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
102
|
+
base = if @protocol_loader&.available_actions&.any?
|
|
103
|
+
@protocol_loader.available_actions
|
|
104
|
+
else
|
|
105
|
+
ACTIONS
|
|
106
|
+
end
|
|
107
|
+
ext = self.class.extended_actions
|
|
108
|
+
ext.empty? ? base : (base + ext).uniq
|
|
64
109
|
end
|
|
65
110
|
|
|
66
111
|
def action_supported?(action) = supported_actions.include?(action)
|
|
@@ -138,9 +183,19 @@ module MMP
|
|
|
138
183
|
when 'skill_content' then process_skill_content(msg_data)
|
|
139
184
|
when 'reflect' then process_reflect(msg_data)
|
|
140
185
|
else
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
186
|
+
handler = self.class.extended_handler(action)
|
|
187
|
+
if handler
|
|
188
|
+
begin
|
|
189
|
+
handler.call(msg_data, self)
|
|
190
|
+
rescue StandardError => e
|
|
191
|
+
warn "[MMP::Protocol] Handler error for '#{action}': #{e.message}"
|
|
192
|
+
{ status: 'error', action: action, message: 'Handler execution failed' }
|
|
193
|
+
end
|
|
194
|
+
else
|
|
195
|
+
{ status: 'action_not_supported', action: action,
|
|
196
|
+
message: "Action '#{action}' is recognized but has no handler.",
|
|
197
|
+
available_actions: supported_actions }
|
|
198
|
+
end
|
|
144
199
|
end
|
|
145
200
|
end
|
|
146
201
|
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
enabled: true
|
|
2
|
+
|
|
3
|
+
attestation:
|
|
4
|
+
default_ttl: 86400 # 24 hours
|
|
5
|
+
max_evidence_size: 65536 # 64KB
|
|
6
|
+
require_signature: true
|
|
7
|
+
|
|
8
|
+
trust:
|
|
9
|
+
score_weights:
|
|
10
|
+
quality: 0.3
|
|
11
|
+
freshness: 0.25
|
|
12
|
+
diversity: 0.25
|
|
13
|
+
velocity: 0.1
|
|
14
|
+
revocation_penalty: 0.1
|
|
15
|
+
min_trust_score: 0.0
|
|
16
|
+
max_trust_score: 1.0
|
|
17
|
+
|
|
18
|
+
challenge:
|
|
19
|
+
response_timeout: 3600 # 1 hour
|
|
20
|
+
max_active_per_subject: 5
|
|
21
|
+
|
|
22
|
+
registry:
|
|
23
|
+
backend: file # file | sqlite (future)
|
|
24
|
+
data_dir: synoptis_data
|
|
25
|
+
|
|
26
|
+
transport:
|
|
27
|
+
preferred: mmp # mmp | hestia | local
|
|
28
|
+
fallback_order:
|
|
29
|
+
- mmp
|
|
30
|
+
- hestia
|
|
31
|
+
- local
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: synoptis_attestation_protocol
|
|
3
|
+
version: "1.0.0"
|
|
4
|
+
actions:
|
|
5
|
+
- attestation_request
|
|
6
|
+
- attestation_response
|
|
7
|
+
- attestation_revoke
|
|
8
|
+
- challenge_create
|
|
9
|
+
- challenge_respond
|
|
10
|
+
tags:
|
|
11
|
+
- synoptis
|
|
12
|
+
- attestation
|
|
13
|
+
- trust
|
|
14
|
+
- audit
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# Synoptis Mutual Attestation Protocol
|
|
18
|
+
|
|
19
|
+
## Overview
|
|
20
|
+
|
|
21
|
+
Synoptis is an opt-in SkillSet for KairosChain that provides mutual attestation
|
|
22
|
+
between agents. It enables cross-agent trust verification through cryptographically
|
|
23
|
+
signed proof envelopes, stored in append-only registries with hash-chain integrity.
|
|
24
|
+
|
|
25
|
+
## MMP Actions
|
|
26
|
+
|
|
27
|
+
### attestation_request
|
|
28
|
+
|
|
29
|
+
Sent to request an attestation from a peer agent.
|
|
30
|
+
|
|
31
|
+
**Payload:**
|
|
32
|
+
- `subject_ref` (string): Reference to the subject being attested
|
|
33
|
+
- `claim` (string): The type of attestation requested
|
|
34
|
+
- `evidence_hints` (array, optional): Hints about what evidence to examine
|
|
35
|
+
|
|
36
|
+
### attestation_response
|
|
37
|
+
|
|
38
|
+
Sent in response to an attestation request, containing the signed proof envelope.
|
|
39
|
+
|
|
40
|
+
**Payload:**
|
|
41
|
+
- ProofEnvelope fields (proof_id, attester_id, subject_ref, claim, evidence, merkle_root, signature, timestamp, ttl)
|
|
42
|
+
|
|
43
|
+
### attestation_revoke
|
|
44
|
+
|
|
45
|
+
Broadcast when an attestation is revoked.
|
|
46
|
+
|
|
47
|
+
**Payload:**
|
|
48
|
+
- `proof_id` (string): The revoked proof ID
|
|
49
|
+
- `revoker_id` (string): Who revoked it
|
|
50
|
+
- `reason` (string): Reason for revocation
|
|
51
|
+
|
|
52
|
+
### challenge_create
|
|
53
|
+
|
|
54
|
+
Sent to challenge an existing attestation.
|
|
55
|
+
|
|
56
|
+
**Payload:**
|
|
57
|
+
- `challenge_id` (string): Unique challenge identifier
|
|
58
|
+
- `proof_id` (string): The challenged proof
|
|
59
|
+
- `challenge_type` (string): validity | evidence_request | re_verification
|
|
60
|
+
- `details` (string, optional): Challenge details
|
|
61
|
+
|
|
62
|
+
### challenge_respond
|
|
63
|
+
|
|
64
|
+
Sent by the original attester in response to a challenge.
|
|
65
|
+
|
|
66
|
+
**Payload:**
|
|
67
|
+
- `challenge_id` (string): The challenge being responded to
|
|
68
|
+
- `response` (string): Response text
|
|
69
|
+
- `evidence` (string, optional): Additional evidence
|
|
70
|
+
|
|
71
|
+
## Transport
|
|
72
|
+
|
|
73
|
+
Messages are delivered via MMP PeerManager with Bearer token authentication.
|
|
74
|
+
Handlers are registered via `MMP::Protocol.register_handler` during `Synoptis.load!`.
|
|
75
|
+
|
|
76
|
+
## Registry
|
|
77
|
+
|
|
78
|
+
All attestation data is stored in append-only JSONL files with hash-chain linking
|
|
79
|
+
(`_prev_entry_hash`), implementing constitutive recording (Proposition 5).
|
|
80
|
+
|
|
81
|
+
## Trust Scoring
|
|
82
|
+
|
|
83
|
+
Trust scores are calculated from: quality (0.3), freshness (0.25), diversity (0.25),
|
|
84
|
+
velocity (0.1), minus revocation penalty (0.1).
|