openclaw-core 1.0.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.
package/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ ISC License (ISC)
2
+
3
+ Copyright (c) 2026, James
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any
6
+ purpose with or without fee is hereby granted, provided that the above
7
+ copyright notice and this permission notice appear in all copies.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,122 @@
1
+ # @lobster/openclaw-core
2
+
3
+ > Open-source AI Agent OS primitive layer — P2P federation, sovereign protocols, and plugin-ready base store.
4
+ > **Apache 2.0 Licensed. Built on the Lobster Civilization architecture.**
5
+
6
+ [![Status: Preview](https://img.shields.io/badge/status-Preview-blue)](https://github.com/lobster-civilization/openclaw)
7
+
8
+ ---
9
+
10
+ ## 什么是 OpenClaw Core?
11
+
12
+ `@lobster/openclaw-core` 是龙虾文明(Lobster Civilization)Agent OS 的**开源物理底座**。它提供:
13
+
14
+ - 🌐 **真实 P2P 通信骨干**:Ed25519 签名验证,WebSocket 物理传输,没有任何日志模拟
15
+ - 📜 **SAML 主权协议**:Agent-to-Agent 语义消息语言,内置防重放攻击
16
+ - 🧠 **Vector DB 记忆引擎**:事件溯源(Event Sourcing)只写架构,强制向量持久化
17
+ - 🔌 **插件热插拔架构**:`store.usePlugin()` 一行激活任意商业引擎
18
+ - 📡 **SignalManager**:HMAC/Ed25519 双模签名,支持 E2EE 加密信道和群组通信
19
+
20
+ > ⚡ **600% Real 原则**:本包所有代码均运行在物理与密码学意义上的"真实"之上。网络不通就是不通,签名不对包就丢。
21
+
22
+ ---
23
+
24
+ ## 快速开始
25
+
26
+ ```bash
27
+ npm install @lobster/openclaw-core
28
+ # or
29
+ pnpm add @lobster/openclaw-core
30
+ ```
31
+
32
+ ### 最小化 Agent 节点
33
+
34
+ ```typescript
35
+ import { BaseStateStore, SignalManager } from '@lobster/openclaw-core';
36
+
37
+ const store = new BaseStateStore();
38
+ await store.updateIdentity({ did: 'did:lobster:my-agent', name: 'MyAgent' });
39
+
40
+ // 连接数据库(SurrealDB)
41
+ const db = await Surreal.connect('ws://localhost:8000');
42
+ await store.setDB(db);
43
+
44
+ // 发送经过签名的信号
45
+ await store.signalManager.sendTo('did:lobster:peer', 'HELLO', { greeting: 'World' });
46
+ ```
47
+
48
+ ### 安装商业插件(可选)
49
+
50
+ ```typescript
51
+ // 开源版默认是"裸奔"模式(Null 实现)
52
+ // 安装 @lobster/openclaw-enterprise 后:
53
+ import { activateEnterprisePlugins } from '@lobster/openclaw-enterprise';
54
+ await activateEnterprisePlugins(store);
55
+ // → 激活 DLP / 经济结算 / 保险库 / 进化矩阵
56
+ ```
57
+
58
+ ---
59
+
60
+ ## 模块结构
61
+
62
+ ```
63
+ src/
64
+ ├── store/BaseStore.ts # 骨架状态机(含 usePlugin 热插拔)
65
+ ├── resonance/SignalManager.ts # 加密信号路由(Ed25519 + E2EE)
66
+ ├── brain/MemoryManager.ts # Vector DB 记忆引擎(Event Sourcing)
67
+ ├── interfaces/index.ts # 插件契约 + Null 裸奔实现
68
+ └── common/protocols/SAML.ts # SAML 主权通信协议
69
+ ```
70
+
71
+ ---
72
+
73
+ ## 插件槽位(Plugin Slots)
74
+
75
+ 商业引擎通过接口契约热插拔,不影响开源骨架:
76
+
77
+ | 插件槽 | 接口 | 开源裸奔 | 商业实现 |
78
+ |---|---|---|---|
79
+ | `dlp` | `IDLPManager` | `NullDLPManager` | `EnterpriseDLPPlugin` |
80
+ | `ledger` | `ILedgerPlugin` | `NullLedgerPlugin` | `EnterpriseLedgerPlugin` |
81
+ | `vault` | `IVaultPlugin` | `NullVaultPlugin` | `EnterpriseVaultPlugin` |
82
+ | `evolution` | `IEvolutionPlugin` | `NullEvolutionPlugin` | `EnterpriseEvolutionPlugin` |
83
+
84
+ ```typescript
85
+ // 自定义插件接入示例
86
+ import type { IDLPManager } from '@lobster/openclaw-core';
87
+
88
+ class MyDLPImpl implements IDLPManager {
89
+ async check(content: string) { /* your logic */ }
90
+ // ...
91
+ }
92
+
93
+ store.usePlugin('dlp', new MyDLPImpl());
94
+ ```
95
+
96
+ ---
97
+
98
+ ## 技术规格
99
+
100
+ - **协议**:SAML/1.0 (Sovereign Agent Message Language)
101
+ - **签名**:Ed25519 / HMAC-SHA256 Durable Mode
102
+ - **加密**:AES-256-GCM (E2EE)
103
+ - **存储**:SurrealDB 3.0(HNSW 向量索引 + Event Sourcing)
104
+ - **传输**:WebSocket / WebRTC Data Channel
105
+
106
+ ---
107
+
108
+ ## 商业套件
109
+
110
+ 需要完整能力(DLP / 经济结算 / 硬件级保险库 / 群智进化)?
111
+
112
+ ```bash
113
+ claws plugin install @lobster/shield-pro
114
+ claws plugin install @lobster/economy-engine
115
+ claws plugin install @lobster/evolution-matrix
116
+ ```
117
+
118
+ ---
119
+
120
+ ## License
121
+
122
+ Apache 2.0 — See [LICENSE](../../LICENSE)
@@ -0,0 +1,25 @@
1
+ export interface MemoryFragment {
2
+ id?: string;
3
+ agent_id: string;
4
+ content: string;
5
+ embedding?: number[];
6
+ importance: number;
7
+ tags: string[];
8
+ type: 'TRANSACTION' | 'PATTERN' | 'RELATION' | 'SKILL';
9
+ linked_ids: string[];
10
+ created_at?: string;
11
+ }
12
+ export interface MemoryQuery {
13
+ agent_id: string;
14
+ query?: string;
15
+ tags?: string[];
16
+ type?: string;
17
+ limit?: number;
18
+ minImportance?: number;
19
+ }
20
+ export declare class MemoryManager {
21
+ db: any;
22
+ sedimentate(db: any, fragment: MemoryFragment): Promise<void>;
23
+ retrieve(db: any, query: MemoryQuery): Promise<MemoryFragment[]>;
24
+ initSchema(db: any): Promise<void>;
25
+ }
@@ -0,0 +1,53 @@
1
+ export class MemoryManager {
2
+ db = null;
3
+ async sedimentate(db, fragment) {
4
+ const store = db || this.db;
5
+ if (!store) {
6
+ console.warn("[MemoryManager] ⚠️ No DB connected. Memory fragment DROPPED. Connect SurrealDB to enable persistence.");
7
+ return;
8
+ }
9
+ await store.query(`INSERT INTO memory_fragments {
10
+ agent_id: $agent_id,
11
+ content: $content,
12
+ importance: $importance,
13
+ tags: $tags,
14
+ type: $type,
15
+ linked_ids: $linked_ids,
16
+ created_at: time::now()
17
+ }`, { ...fragment }).catch((e) => console.error("[MemoryManager] DB write failed:", e));
18
+ }
19
+ async retrieve(db, query) {
20
+ const store = db || this.db;
21
+ if (!store)
22
+ return [];
23
+ const { agent_id, tags, type, limit = 20, minImportance = 0 } = query;
24
+ let sql = `SELECT * FROM memory_fragments WHERE agent_id = $agent_id AND importance >= $minImportance`;
25
+ const params = { agent_id, minImportance, limit };
26
+ if (tags?.length) {
27
+ sql += ` AND tags CONTAINSANY $tags`;
28
+ params.tags = tags;
29
+ }
30
+ if (type) {
31
+ sql += ` AND type = $type`;
32
+ params.type = type;
33
+ }
34
+ sql += ` ORDER BY importance DESC LIMIT $limit`;
35
+ const result = await store.query(sql, params).catch(() => []);
36
+ return result[0]?.result || result[0] || [];
37
+ }
38
+ async initSchema(db) {
39
+ if (!db)
40
+ return;
41
+ const queries = [
42
+ `DEFINE TABLE memory_fragments SCHEMALESS
43
+ PERMISSIONS FOR select FULL, FOR create FULL, FOR update, delete NONE;`,
44
+ `DEFINE INDEX memory_vector_idx ON memory_fragments
45
+ FIELDS embedding MTREE DIMENSION 1536 DIST EUCLIDEAN;`,
46
+ `DEFINE INDEX memory_importance ON memory_fragments FIELDS importance;`,
47
+ `DEFINE INDEX memory_agent_tag ON memory_fragments FIELDS agent_id, tags;`,
48
+ ];
49
+ for (const q of queries) {
50
+ await db.query(q).catch(() => { });
51
+ }
52
+ }
53
+ }
@@ -0,0 +1,18 @@
1
+ interface BoundaryViolation {
2
+ file: string;
3
+ line: number;
4
+ importPath: string;
5
+ fromDomain: string;
6
+ toDomain: string;
7
+ severity: 'ERROR' | 'WARNING';
8
+ }
9
+ export declare class BoundaryChecker {
10
+ private violations;
11
+ private srcRoot;
12
+ constructor(srcRoot: string);
13
+ scan(): BoundaryViolation[];
14
+ private walkDir;
15
+ private checkFile;
16
+ static formatReport(violations: BoundaryViolation[]): string;
17
+ }
18
+ export {};
@@ -0,0 +1,87 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ const ISOLATION_MATRIX = {
4
+ 'shield': ['finance', 'resonance', 'brain', 'economy', 'social'],
5
+ 'finance': ['shield', 'resonance', 'brain', 'social'],
6
+ 'resonance': ['shield', 'finance', 'social'],
7
+ 'brain': ['shield', 'finance', 'social'],
8
+ 'economy': ['shield', 'resonance', 'brain', 'social'],
9
+ 'social': ['shield', 'brain'],
10
+ };
11
+ const EXEMPT_DIRS = ['api', 'tests', 'common', 'services', 'skills', 'cli'];
12
+ export class BoundaryChecker {
13
+ violations = [];
14
+ srcRoot;
15
+ constructor(srcRoot) {
16
+ this.srcRoot = srcRoot;
17
+ }
18
+ scan() {
19
+ this.violations = [];
20
+ this.walkDir(this.srcRoot);
21
+ return this.violations;
22
+ }
23
+ walkDir(dir) {
24
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
25
+ for (const entry of entries) {
26
+ const fullPath = path.join(dir, entry.name);
27
+ if (entry.isDirectory()) {
28
+ if (entry.name === 'node_modules')
29
+ continue;
30
+ this.walkDir(fullPath);
31
+ }
32
+ else if (entry.name.endsWith('.ts') && !entry.name.endsWith('.d.ts')) {
33
+ this.checkFile(fullPath);
34
+ }
35
+ }
36
+ }
37
+ checkFile(filePath) {
38
+ const relativePath = path.relative(this.srcRoot, filePath).replace(/\\/g, '/');
39
+ const fromDomain = relativePath.split('/')[0];
40
+ if (EXEMPT_DIRS.includes(fromDomain))
41
+ return;
42
+ if (!ISOLATION_MATRIX[fromDomain])
43
+ return;
44
+ const content = fs.readFileSync(filePath, 'utf8');
45
+ const lines = content.split('\n');
46
+ for (let i = 0; i < lines.length; i++) {
47
+ const line = lines[i];
48
+ const importMatch = line.match(/(?:import|export)\s+.*from\s+['"](\.\.\/?([^'"\/]+))/);
49
+ if (importMatch) {
50
+ const toDomain = importMatch[2];
51
+ const forbidden = ISOLATION_MATRIX[fromDomain];
52
+ if (forbidden && forbidden.includes(toDomain)) {
53
+ this.violations.push({
54
+ file: relativePath,
55
+ line: i + 1,
56
+ importPath: importMatch[1],
57
+ fromDomain,
58
+ toDomain,
59
+ severity: 'ERROR',
60
+ });
61
+ }
62
+ }
63
+ }
64
+ }
65
+ static formatReport(violations) {
66
+ if (violations.length === 0) {
67
+ return '✅ [BoundaryAST] 编译级黑洞断崖检查通过:零隔离违规。';
68
+ }
69
+ let report = `🚨 [BoundaryAST] 发现 ${violations.length} 处跨域隔离违规:\n\n`;
70
+ const grouped = {};
71
+ for (const v of violations) {
72
+ const key = `${v.fromDomain} → ${v.toDomain}`;
73
+ if (!grouped[key])
74
+ grouped[key] = [];
75
+ grouped[key].push(v);
76
+ }
77
+ for (const [pair, items] of Object.entries(grouped)) {
78
+ report += ` ⛔ ${pair} (${items.length} 处):\n`;
79
+ for (const item of items) {
80
+ report += ` ${item.file}:${item.line} → ${item.importPath}\n`;
81
+ }
82
+ report += '\n';
83
+ }
84
+ report += `💡 修复方案:将跨域类型移至 common/types/,将跨域调用改为通过 FederatedProxy 或 common/interfaces/ 中的抽象接口。\n`;
85
+ return report;
86
+ }
87
+ }
@@ -0,0 +1,25 @@
1
+ export interface IEmbeddingProvider {
2
+ generate(text: string): Promise<number[]>;
3
+ }
4
+ export declare class DevEmbeddingProvider implements IEmbeddingProvider {
5
+ private dimensions;
6
+ constructor(dimensions?: number);
7
+ generate(text: string): Promise<number[]>;
8
+ }
9
+ export declare class OpenAIEmbeddingProvider implements IEmbeddingProvider {
10
+ private apiKey;
11
+ private model;
12
+ constructor(apiKey: string, model?: string);
13
+ generate(text: string): Promise<number[]>;
14
+ }
15
+ export declare class OllamaEmbeddingProvider implements IEmbeddingProvider {
16
+ private endpoint;
17
+ private model;
18
+ constructor(endpoint?: string, model?: string);
19
+ generate(text: string): Promise<number[]>;
20
+ }
21
+ export declare class EmbeddingService {
22
+ private provider;
23
+ constructor(provider?: IEmbeddingProvider);
24
+ getVector(text: string): Promise<number[]>;
25
+ }
@@ -0,0 +1,77 @@
1
+ export class DevEmbeddingProvider {
2
+ dimensions;
3
+ constructor(dimensions = 128) {
4
+ this.dimensions = dimensions;
5
+ }
6
+ async generate(text) {
7
+ const vector = new Array(this.dimensions).fill(0);
8
+ const seed = text.split('').reduce((acc, char) => acc + char.charCodeAt(0), 0);
9
+ for (let i = 0; i < this.dimensions; i++) {
10
+ vector[i] = Math.sin(seed + i) * Math.cos((seed * 0.5) + i);
11
+ }
12
+ return vector;
13
+ }
14
+ }
15
+ export class OpenAIEmbeddingProvider {
16
+ apiKey;
17
+ model;
18
+ constructor(apiKey, model = "text-embedding-3-small") {
19
+ this.apiKey = apiKey;
20
+ this.model = model;
21
+ }
22
+ async generate(text) {
23
+ const response = await fetch("https://api.openai.com/v1/embeddings", {
24
+ method: "POST",
25
+ headers: {
26
+ "Content-Type": "application/json",
27
+ "Authorization": `Bearer ${this.apiKey}`
28
+ },
29
+ body: JSON.stringify({ input: text, model: this.model })
30
+ });
31
+ if (!response.ok)
32
+ throw new Error(`OpenAI_Embedding_Error: ${response.status}`);
33
+ const json = await response.json();
34
+ return json.data[0].embedding;
35
+ }
36
+ }
37
+ export class OllamaEmbeddingProvider {
38
+ endpoint;
39
+ model;
40
+ constructor(endpoint = "http://localhost:11434", model = "mxbai-embed-large") {
41
+ this.endpoint = endpoint;
42
+ this.model = model;
43
+ }
44
+ async generate(text) {
45
+ const response = await fetch(`${this.endpoint}/api/embeddings`, {
46
+ method: "POST",
47
+ body: JSON.stringify({ model: this.model, prompt: text })
48
+ });
49
+ if (!response.ok)
50
+ throw new Error(`Ollama_Embedding_Error: ${response.status}`);
51
+ const json = await response.json();
52
+ return json.embedding;
53
+ }
54
+ }
55
+ export class EmbeddingService {
56
+ provider;
57
+ constructor(provider) {
58
+ if (provider) {
59
+ this.provider = provider;
60
+ }
61
+ else {
62
+ const type = process.env.EMBEDDING_PROVIDER || "dev";
63
+ if (type === "openai" && process.env.OPENAI_API_KEY) {
64
+ this.provider = new OpenAIEmbeddingProvider(process.env.OPENAI_API_KEY);
65
+ }
66
+ else if (type === "ollama") {
67
+ this.provider = new OllamaEmbeddingProvider(process.env.OLLAMA_ENDPOINT);
68
+ }
69
+ else {
70
+ this.provider = new DevEmbeddingProvider(1536);
71
+ }
72
+ }
73
+ }
74
+ async getVector(text) {
75
+ return this.provider.generate(text);
76
+ }
77
+ }
@@ -0,0 +1,16 @@
1
+ export interface VectorEntry {
2
+ id: string;
3
+ vector: number[];
4
+ metadata: any;
5
+ }
6
+ export declare class VectorStore {
7
+ private entries;
8
+ constructor();
9
+ upsert(id: string, vector: number[], metadata?: any): void;
10
+ private cosineSimilarity;
11
+ search(queryVector: number[], k?: number): Array<{
12
+ entry: VectorEntry;
13
+ score: number;
14
+ }>;
15
+ clear(): void;
16
+ }
@@ -0,0 +1,42 @@
1
+ export class VectorStore {
2
+ entries = [];
3
+ constructor() { }
4
+ upsert(id, vector, metadata = {}) {
5
+ const index = this.entries.findIndex(e => e.id === id);
6
+ if (index !== -1) {
7
+ this.entries[index] = { id, vector, metadata };
8
+ }
9
+ else {
10
+ this.entries.push({ id, vector, metadata });
11
+ }
12
+ }
13
+ cosineSimilarity(v1, v2) {
14
+ if (v1.length !== v2.length)
15
+ return 0;
16
+ let dotProduct = 0;
17
+ let norm1 = 0;
18
+ let norm2 = 0;
19
+ for (let i = 0; i < v1.length; i++) {
20
+ dotProduct += v1[i] * v2[i];
21
+ norm1 += v1[i] * v1[i];
22
+ norm2 += v2[i] * v2[i];
23
+ }
24
+ if (norm1 === 0 || norm2 === 0)
25
+ return 0;
26
+ return dotProduct / (Math.sqrt(norm1) * Math.sqrt(norm2));
27
+ }
28
+ search(queryVector, k = 5) {
29
+ if (this.entries.length === 0)
30
+ return [];
31
+ const results = this.entries.map(entry => ({
32
+ entry,
33
+ score: this.cosineSimilarity(queryVector, entry.vector)
34
+ }));
35
+ return results
36
+ .sort((a, b) => b.score - a.score)
37
+ .slice(0, k);
38
+ }
39
+ clear() {
40
+ this.entries = [];
41
+ }
42
+ }
@@ -0,0 +1,32 @@
1
+ export interface SAMLVector {
2
+ intent: SAMLIntent;
3
+ budget_ceiling: number;
4
+ deadline_ts: number;
5
+ slash_ratio: number;
6
+ }
7
+ export declare enum SAMLIntent {
8
+ BUY = "BUY",
9
+ SELL = "SELL",
10
+ RENT = "RENT",
11
+ QUERY = "QUERY",
12
+ ADVERTISE = "ADVERTISE",
13
+ ESCROW = "ESCROW",
14
+ ARBITRATE = "ARBITRATE"
15
+ }
16
+ export interface SAMLEnvelope {
17
+ version: string;
18
+ sender_did: string;
19
+ recipient_did: string;
20
+ vector: SAMLVector;
21
+ payload: Record<string, unknown>;
22
+ signature: string;
23
+ nonce: string;
24
+ timestamp: number;
25
+ }
26
+ export interface SAMLDatabase {
27
+ query(sql: string, vars?: Record<string, unknown>): Promise<unknown[]>;
28
+ }
29
+ export declare function signSAML(envelope: Omit<SAMLEnvelope, "signature">): string;
30
+ export declare function verifySAML(envelope: SAMLEnvelope, db?: SAMLDatabase): Promise<boolean>;
31
+ export declare function parseSAML(raw: Record<string, unknown>, db?: SAMLDatabase): Promise<SAMLEnvelope>;
32
+ export declare function buildSAMLEnvelope(senderDid: string, recipientDid: string, intent: SAMLIntent, budgetCeiling: number, deadlineTs: number, slashRatio: number, payload?: Record<string, unknown>): SAMLEnvelope;
@@ -0,0 +1,107 @@
1
+ import crypto from "node:crypto";
2
+ export var SAMLIntent;
3
+ (function (SAMLIntent) {
4
+ SAMLIntent["BUY"] = "BUY";
5
+ SAMLIntent["SELL"] = "SELL";
6
+ SAMLIntent["RENT"] = "RENT";
7
+ SAMLIntent["QUERY"] = "QUERY";
8
+ SAMLIntent["ADVERTISE"] = "ADVERTISE";
9
+ SAMLIntent["ESCROW"] = "ESCROW";
10
+ SAMLIntent["ARBITRATE"] = "ARBITRATE";
11
+ })(SAMLIntent || (SAMLIntent = {}));
12
+ const SAML_SECRET = process.env.SAML_HMAC_SECRET;
13
+ export function signSAML(envelope) {
14
+ if (!SAML_SECRET) {
15
+ throw new Error("CRITICAL_SECURITY_ERROR: SAML_HMAC_SECRET is not defined in environment.");
16
+ }
17
+ const canonical = JSON.stringify({
18
+ v: envelope.version,
19
+ s: envelope.sender_did,
20
+ r: envelope.recipient_did,
21
+ vec: envelope.vector,
22
+ n: envelope.nonce,
23
+ t: envelope.timestamp,
24
+ });
25
+ return crypto.createHmac("sha256", SAML_SECRET).update(canonical).digest("hex");
26
+ }
27
+ export async function verifySAML(envelope, db) {
28
+ const expected = signSAML(envelope);
29
+ const signatureOk = crypto.timingSafeEqual(Buffer.from(expected, "hex"), Buffer.from(envelope.signature, "hex"));
30
+ if (!signatureOk)
31
+ return false;
32
+ if (db) {
33
+ const nonceKey = `nonce_registry:${envelope.sender_did}:${envelope.nonce}`;
34
+ try {
35
+ await db.query(`INSERT INTO nonce_registry {
36
+ id: $id,
37
+ created_at: time::now(),
38
+ expires_at: time::now() + 24h
39
+ }`, { id: nonceKey });
40
+ }
41
+ catch (e) {
42
+ const errMessage = e instanceof Error ? e.message : String(e);
43
+ const isReplay = /already exists|conflict|409|Duplicate/i.test(errMessage);
44
+ if (isReplay) {
45
+ console.error(`🚨 [SAML] Replay detected for DID ${envelope.sender_did} with nonce ${envelope.nonce}`);
46
+ return false;
47
+ }
48
+ console.error("❌ [SAML] Security critical failure: Nonce registry inaccessible.", errMessage);
49
+ throw new Error(`SECURITY_INFRASTRUCTURE_FAILURE: Nonce registry check failed. ${errMessage}`);
50
+ }
51
+ }
52
+ return true;
53
+ }
54
+ export async function parseSAML(raw, db) {
55
+ const version = String(raw.saml_version || raw.version || "");
56
+ if (!version || !version.startsWith("SAML/1")) {
57
+ throw new Error("SAML_PARSE_ERROR: Unsupported or missing SAML version header.");
58
+ }
59
+ const vec = (raw.vector || raw.v);
60
+ if (!vec || typeof vec.intent !== "string") {
61
+ throw new Error("SAML_PARSE_ERROR: Missing or invalid intent vector. All A2A requests must declare intent.");
62
+ }
63
+ const intentKey = vec.intent;
64
+ const intent = SAMLIntent[intentKey];
65
+ if (!intent) {
66
+ throw new Error(`SAML_PARSE_ERROR: Unknown intent '${vec.intent}'. Valid: ${Object.keys(SAMLIntent).join(", ")}`);
67
+ }
68
+ const vector = {
69
+ intent,
70
+ budget_ceiling: Number(vec.budget_ceiling ?? vec.budget ?? 0),
71
+ deadline_ts: Number(vec.deadline_ts ?? vec.deadline ?? Date.now() + 86400000),
72
+ slash_ratio: Math.min(1, Math.max(0, Number(vec.slash_ratio ?? vec.slash ?? 0.5))),
73
+ };
74
+ const envelope = {
75
+ version,
76
+ sender_did: String(raw.sender_did || raw.from || "UNKNOWN"),
77
+ recipient_did: String(raw.recipient_did || raw.to || "BROADCAST"),
78
+ vector,
79
+ payload: raw.payload || {},
80
+ signature: String(raw.signature || ""),
81
+ nonce: String(raw.nonce || crypto.randomBytes(8).toString("hex")),
82
+ timestamp: Number(raw.timestamp || Date.now()),
83
+ };
84
+ if (!envelope.signature) {
85
+ throw new Error("SAML_AUTH_FAILED: Missing mandatory signature. Insecure A2A communication is blocked.");
86
+ }
87
+ const isVerified = await verifySAML(envelope, db);
88
+ if (!isVerified) {
89
+ throw new Error("SAML_AUTH_FAILED: Signature mismatch or replay attack.");
90
+ }
91
+ return envelope;
92
+ }
93
+ export function buildSAMLEnvelope(senderDid, recipientDid, intent, budgetCeiling, deadlineTs, slashRatio, payload = {}) {
94
+ const nonce = crypto.randomBytes(8).toString("hex");
95
+ const timestamp = Date.now();
96
+ const partial = {
97
+ version: "SAML/1.0",
98
+ sender_did: senderDid,
99
+ recipient_did: recipientDid,
100
+ vector: { intent, budget_ceiling: budgetCeiling, deadline_ts: deadlineTs, slash_ratio: slashRatio },
101
+ payload,
102
+ nonce,
103
+ timestamp,
104
+ };
105
+ const signature = signSAML(partial);
106
+ return { ...partial, signature };
107
+ }
@@ -0,0 +1,18 @@
1
+ import { AgenticHarness } from "./AgenticHarness.js";
2
+ export interface CodeAuditRequest {
3
+ specHash: string;
4
+ generatedCode: string;
5
+ harness?: AgenticHarness;
6
+ tools?: Record<string, unknown>;
7
+ testResults?: {
8
+ pass: boolean;
9
+ coverage: number;
10
+ };
11
+ }
12
+ export declare class ByzantineFaultError extends Error {
13
+ constructor(message: string);
14
+ }
15
+ export declare class AgentEvaluator {
16
+ constructor();
17
+ audit(request: CodeAuditRequest, enforceBoundary?: boolean): Promise<boolean>;
18
+ }