triage-ows 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.
Files changed (91) hide show
  1. package/README.md +786 -0
  2. package/bin/triage-ows.js +218 -0
  3. package/bin/triage-policy.js +66 -0
  4. package/bin/triage-server.js +4 -0
  5. package/dashboard-dist/assets/index-Dnhi_dJQ.css +2 -0
  6. package/dashboard-dist/assets/index-g_2MwC-o.js +9 -0
  7. package/dashboard-dist/favicon.svg +7 -0
  8. package/dashboard-dist/index.html +16 -0
  9. package/dist/config.d.ts +32 -0
  10. package/dist/config.d.ts.map +1 -0
  11. package/dist/config.js +61 -0
  12. package/dist/config.js.map +1 -0
  13. package/dist/emitter.d.ts +7 -0
  14. package/dist/emitter.d.ts.map +1 -0
  15. package/dist/emitter.js +41 -0
  16. package/dist/emitter.js.map +1 -0
  17. package/dist/index.d.ts +17 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +55 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/scoring/behavior.d.ts +3 -0
  22. package/dist/scoring/behavior.d.ts.map +1 -0
  23. package/dist/scoring/behavior.js +13 -0
  24. package/dist/scoring/behavior.js.map +1 -0
  25. package/dist/scoring/compliance.d.ts +3 -0
  26. package/dist/scoring/compliance.d.ts.map +1 -0
  27. package/dist/scoring/compliance.js +11 -0
  28. package/dist/scoring/compliance.js.map +1 -0
  29. package/dist/scoring/identity.d.ts +3 -0
  30. package/dist/scoring/identity.d.ts.map +1 -0
  31. package/dist/scoring/identity.js +16 -0
  32. package/dist/scoring/identity.js.map +1 -0
  33. package/dist/scoring/index.d.ts +10 -0
  34. package/dist/scoring/index.d.ts.map +1 -0
  35. package/dist/scoring/index.js +35 -0
  36. package/dist/scoring/index.js.map +1 -0
  37. package/dist/scoring/limits.d.ts +7 -0
  38. package/dist/scoring/limits.d.ts.map +1 -0
  39. package/dist/scoring/limits.js +9 -0
  40. package/dist/scoring/limits.js.map +1 -0
  41. package/dist/scoring/network.d.ts +3 -0
  42. package/dist/scoring/network.d.ts.map +1 -0
  43. package/dist/scoring/network.js +16 -0
  44. package/dist/scoring/network.js.map +1 -0
  45. package/dist/scoring/onchain.d.ts +4 -0
  46. package/dist/scoring/onchain.d.ts.map +1 -0
  47. package/dist/scoring/onchain.js +35 -0
  48. package/dist/scoring/onchain.js.map +1 -0
  49. package/dist/scoring/risk.d.ts +3 -0
  50. package/dist/scoring/risk.d.ts.map +1 -0
  51. package/dist/scoring/risk.js +22 -0
  52. package/dist/scoring/risk.js.map +1 -0
  53. package/dist/server.d.ts +6 -0
  54. package/dist/server.d.ts.map +1 -0
  55. package/dist/server.js +405 -0
  56. package/dist/server.js.map +1 -0
  57. package/dist/store.d.ts +13 -0
  58. package/dist/store.d.ts.map +1 -0
  59. package/dist/store.js +177 -0
  60. package/dist/store.js.map +1 -0
  61. package/dist/types.d.ts +107 -0
  62. package/dist/types.d.ts.map +1 -0
  63. package/dist/types.js +26 -0
  64. package/dist/types.js.map +1 -0
  65. package/dist/webbotauth.d.ts +38 -0
  66. package/dist/webbotauth.d.ts.map +1 -0
  67. package/dist/webbotauth.js +120 -0
  68. package/dist/webbotauth.js.map +1 -0
  69. package/dist/xmtp.d.ts +6 -0
  70. package/dist/xmtp.d.ts.map +1 -0
  71. package/dist/xmtp.js +161 -0
  72. package/dist/xmtp.js.map +1 -0
  73. package/package.json +58 -0
  74. package/policy-template.json +14 -0
  75. package/src/config.ts +86 -0
  76. package/src/emitter.ts +40 -0
  77. package/src/index.ts +18 -0
  78. package/src/scoring/behavior.ts +15 -0
  79. package/src/scoring/compliance.ts +12 -0
  80. package/src/scoring/identity.ts +12 -0
  81. package/src/scoring/index.ts +31 -0
  82. package/src/scoring/limits.ts +10 -0
  83. package/src/scoring/network.ts +18 -0
  84. package/src/scoring/onchain.ts +44 -0
  85. package/src/scoring/risk.ts +25 -0
  86. package/src/server.ts +410 -0
  87. package/src/store.ts +197 -0
  88. package/src/types.ts +137 -0
  89. package/src/webbotauth.ts +128 -0
  90. package/src/xmtp.ts +188 -0
  91. package/triage.config.example.json +22 -0
@@ -0,0 +1,107 @@
1
+ export interface PolicyContext {
2
+ chain_id: string;
3
+ wallet_id: string;
4
+ api_key_id: string;
5
+ transaction: {
6
+ to: string;
7
+ value: string;
8
+ raw_hex: string;
9
+ data: string;
10
+ };
11
+ spending: {
12
+ daily_total: string;
13
+ date: string;
14
+ };
15
+ timestamp: string;
16
+ policy_config?: Record<string, unknown>;
17
+ }
18
+ export interface PolicyResult {
19
+ allow: boolean;
20
+ reason?: string;
21
+ }
22
+ export interface TrustBreakdown {
23
+ identity: number;
24
+ onChain: number;
25
+ behavior: number;
26
+ compliance: number;
27
+ network: number;
28
+ risk: number;
29
+ total: number;
30
+ }
31
+ export interface SpendingTier {
32
+ name: 'Sovereign' | 'Trusted' | 'Building' | 'Cautious' | 'Restricted' | 'Frozen';
33
+ color: string;
34
+ dailyLimit: number;
35
+ perTxLimit: number;
36
+ minScore: number;
37
+ }
38
+ export interface AgentProfile {
39
+ address: string;
40
+ walletId?: string;
41
+ apiKeyId?: string;
42
+ chainId?: string;
43
+ isOWSWallet: boolean;
44
+ worldIdVerified: boolean;
45
+ webBotAuthVerified: boolean;
46
+ nullifierHash?: string;
47
+ trustScore: number;
48
+ breakdown: TrustBreakdown;
49
+ tier: string;
50
+ totalRequests: number;
51
+ successfulRequests: number;
52
+ failedRequests: number;
53
+ dailySpent: number;
54
+ dailyDate: string;
55
+ consecutiveApprovals: number;
56
+ consecutiveDenials: number;
57
+ totalApproved: number;
58
+ totalDenied: number;
59
+ humanOverrides: number;
60
+ counterparties: string[];
61
+ pendingOverride?: {
62
+ tx: PolicyContext['transaction'];
63
+ amount: number;
64
+ createdAt: number;
65
+ };
66
+ lastOnChainRefresh?: number;
67
+ requestTimestamps: number[];
68
+ lastActive: number;
69
+ consecutiveCleanDays: number;
70
+ cleanDayDate: string;
71
+ createdAt: number;
72
+ }
73
+ export interface PolicyDecisionEvent {
74
+ type: 'POLICY_DECISION';
75
+ agent: string;
76
+ amount: number;
77
+ trustScore: number;
78
+ tier: string;
79
+ decision: 'APPROVE' | 'DENY' | 'OVERRIDE';
80
+ reason: string;
81
+ dailyLimit: number;
82
+ dailySpent: number;
83
+ timestamp: number;
84
+ }
85
+ export interface TrustChangeEvent {
86
+ type: 'TRUST_CHANGE';
87
+ agent: string;
88
+ oldScore: number;
89
+ newScore: number;
90
+ oldTier: string;
91
+ newTier: string;
92
+ reason: string;
93
+ timestamp: number;
94
+ }
95
+ export interface BudgetWarningEvent {
96
+ type: 'BUDGET_WARNING';
97
+ agent: string;
98
+ spent: number;
99
+ limit: number;
100
+ percentage: number;
101
+ timestamp: number;
102
+ }
103
+ export type TriageEvent = PolicyDecisionEvent | TrustChangeEvent | BudgetWarningEvent;
104
+ export declare let SPENDING_TIERS: SpendingTier[];
105
+ export declare function updateSpendingTiers(tiers: SpendingTier[]): void;
106
+ export declare function getTierForScore(score: number): SpendingTier;
107
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ // --- OWS Policy Types ---
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.SPENDING_TIERS = void 0;
5
+ exports.updateSpendingTiers = updateSpendingTiers;
6
+ exports.getTierForScore = getTierForScore;
7
+ // --- Spending Tiers ---
8
+ exports.SPENDING_TIERS = [
9
+ { name: 'Sovereign', color: '#fff8e1', dailyLimit: 1000, perTxLimit: 500, minScore: 80 },
10
+ { name: 'Trusted', color: '#ffd700', dailyLimit: 200, perTxLimit: 100, minScore: 60 },
11
+ { name: 'Building', color: '#4caf50', dailyLimit: 50, perTxLimit: 25, minScore: 40 },
12
+ { name: 'Cautious', color: '#00bcd4', dailyLimit: 10, perTxLimit: 5, minScore: 20 },
13
+ { name: 'Restricted', color: '#2196f3', dailyLimit: 2, perTxLimit: 1, minScore: 1 },
14
+ { name: 'Frozen', color: '#1a1a4e', dailyLimit: 0, perTxLimit: 0, minScore: 0 },
15
+ ];
16
+ function updateSpendingTiers(tiers) {
17
+ exports.SPENDING_TIERS = tiers;
18
+ }
19
+ function getTierForScore(score) {
20
+ for (const tier of exports.SPENDING_TIERS) {
21
+ if (score >= tier.minScore)
22
+ return tier;
23
+ }
24
+ return exports.SPENDING_TIERS[exports.SPENDING_TIERS.length - 1];
25
+ }
26
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA,2BAA2B;;;AA+H3B,kDAEC;AAED,0CAKC;AApBD,yBAAyB;AAEd,QAAA,cAAc,GAAmB;IAC1C,EAAE,IAAI,EAAE,WAAW,EAAI,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,QAAQ,EAAE,EAAE,EAAE;IAC1F,EAAE,IAAI,EAAE,SAAS,EAAM,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,EAAG,UAAU,EAAE,GAAG,EAAE,QAAQ,EAAE,EAAE,EAAE;IAC1F,EAAE,IAAI,EAAE,UAAU,EAAK,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,EAAE,EAAI,UAAU,EAAE,EAAE,EAAG,QAAQ,EAAE,EAAE,EAAE;IAC1F,EAAE,IAAI,EAAE,UAAU,EAAK,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,EAAE,EAAI,UAAU,EAAE,CAAC,EAAI,QAAQ,EAAE,EAAE,EAAE;IAC1F,EAAE,IAAI,EAAE,YAAY,EAAG,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC,EAAK,UAAU,EAAE,CAAC,EAAI,QAAQ,EAAE,CAAC,EAAG;IAC1F,EAAE,IAAI,EAAE,QAAQ,EAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC,EAAK,UAAU,EAAE,CAAC,EAAI,QAAQ,EAAE,CAAC,EAAG;CAC3F,CAAA;AAED,SAAgB,mBAAmB,CAAC,KAAqB;IACvD,sBAAc,GAAG,KAAK,CAAA;AACxB,CAAC;AAED,SAAgB,eAAe,CAAC,KAAa;IAC3C,KAAK,MAAM,IAAI,IAAI,sBAAc,EAAE,CAAC;QAClC,IAAI,KAAK,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAO,IAAI,CAAA;IACzC,CAAC;IACD,OAAO,sBAAc,CAAC,sBAAc,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;AAClD,CAAC"}
@@ -0,0 +1,38 @@
1
+ export interface SignatureComponents {
2
+ signatureInput: string;
3
+ signature: string;
4
+ }
5
+ /**
6
+ * Parse RFC 9421 Signature-Input header.
7
+ * Format: sig1=("@method" "@authority" "@path"); keyid="agent-key"; alg="ed25519"; created=1234567890
8
+ */
9
+ export declare function parseSignatureInput(input: string): {
10
+ label: string;
11
+ components: string[];
12
+ params: Record<string, string>;
13
+ } | null;
14
+ /**
15
+ * Build the RFC 9421 signature base string from request components.
16
+ */
17
+ export declare function buildSignatureBase(components: string[], request: {
18
+ method: string;
19
+ url: string;
20
+ headers: Record<string, string>;
21
+ }, signatureInputValue: string, label: string): string;
22
+ /**
23
+ * Verify an Ed25519 signature.
24
+ * Returns true if the signature is valid for the given public key and data.
25
+ */
26
+ export declare function verifyEd25519Signature(publicKeyBase64: string, signatureBase64: string, data: string): boolean;
27
+ export declare function registerAgentPublicKey(agentKey: string, publicKeyBase64: string): void;
28
+ export declare function getAgentPublicKey(agentKey: string): string | undefined;
29
+ /**
30
+ * Full Web Bot Auth verification.
31
+ * Checks Signature-Input + Signature headers against agent's registered public key.
32
+ */
33
+ export declare function verifyWebBotAuth(headers: Record<string, string>, request: {
34
+ method: string;
35
+ url: string;
36
+ headers: Record<string, string>;
37
+ }, agentKey: string): boolean;
38
+ //# sourceMappingURL=webbotauth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webbotauth.d.ts","sourceRoot":"","sources":["../src/webbotauth.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,mBAAmB;IAClC,cAAc,EAAE,MAAM,CAAA;IACtB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG;IAClD,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAC/B,GAAG,IAAI,CAeP;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,MAAM,EAAE,EACpB,OAAO,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,EACzE,mBAAmB,EAAE,MAAM,EAC3B,KAAK,EAAE,MAAM,GACZ,MAAM,CAaR;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,eAAe,EAAE,MAAM,EACvB,eAAe,EAAE,MAAM,EACvB,IAAI,EAAE,MAAM,GACX,OAAO,CAiBT;AAKD,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,IAAI,CAEtF;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEtE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,OAAO,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,EACzE,QAAQ,EAAE,MAAM,GACf,OAAO,CA0BT"}
@@ -0,0 +1,120 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.parseSignatureInput = parseSignatureInput;
7
+ exports.buildSignatureBase = buildSignatureBase;
8
+ exports.verifyEd25519Signature = verifyEd25519Signature;
9
+ exports.registerAgentPublicKey = registerAgentPublicKey;
10
+ exports.getAgentPublicKey = getAgentPublicKey;
11
+ exports.verifyWebBotAuth = verifyWebBotAuth;
12
+ const crypto_1 = __importDefault(require("crypto"));
13
+ /**
14
+ * Parse RFC 9421 Signature-Input header.
15
+ * Format: sig1=("@method" "@authority" "@path"); keyid="agent-key"; alg="ed25519"; created=1234567890
16
+ */
17
+ function parseSignatureInput(input) {
18
+ try {
19
+ const match = input.match(/^(\w+)=\(([^)]*)\);\s*(.+)$/);
20
+ if (!match)
21
+ return null;
22
+ const [, label, componentStr, paramStr] = match;
23
+ const components = componentStr.match(/"([^"]+)"/g)?.map(s => s.replace(/"/g, '')) ?? [];
24
+ const params = {};
25
+ for (const part of paramStr.split(';')) {
26
+ const [k, v] = part.trim().split('=');
27
+ if (k && v)
28
+ params[k.trim()] = v.replace(/"/g, '').trim();
29
+ }
30
+ return { label, components, params };
31
+ }
32
+ catch {
33
+ return null;
34
+ }
35
+ }
36
+ /**
37
+ * Build the RFC 9421 signature base string from request components.
38
+ */
39
+ function buildSignatureBase(components, request, signatureInputValue, label) {
40
+ const lines = [];
41
+ const url = new URL(request.url, 'http://localhost');
42
+ for (const comp of components) {
43
+ if (comp === '@method')
44
+ lines.push(`"@method": ${request.method.toUpperCase()}`);
45
+ else if (comp === '@authority')
46
+ lines.push(`"@authority": ${url.host}`);
47
+ else if (comp === '@path')
48
+ lines.push(`"@path": ${url.pathname}`);
49
+ else if (comp === '@query')
50
+ lines.push(`"@query": ?${url.search.slice(1)}`);
51
+ else if (comp.startsWith('@'))
52
+ lines.push(`"${comp}": `);
53
+ else
54
+ lines.push(`"${comp}": ${request.headers[comp.toLowerCase()] ?? ''}`);
55
+ }
56
+ lines.push(`"@signature-params": ${signatureInputValue.split('=').slice(1).join('=')}`);
57
+ return lines.join('\n');
58
+ }
59
+ /**
60
+ * Verify an Ed25519 signature.
61
+ * Returns true if the signature is valid for the given public key and data.
62
+ */
63
+ function verifyEd25519Signature(publicKeyBase64, signatureBase64, data) {
64
+ try {
65
+ const pubKeyBuffer = Buffer.from(publicKeyBase64, 'base64');
66
+ const sigBuffer = Buffer.from(signatureBase64, 'base64');
67
+ const key = crypto_1.default.createPublicKey({
68
+ key: Buffer.concat([
69
+ // Ed25519 DER prefix
70
+ Buffer.from('302a300506032b6570032100', 'hex'),
71
+ pubKeyBuffer
72
+ ]),
73
+ format: 'der',
74
+ type: 'spki'
75
+ });
76
+ return crypto_1.default.verify(null, Buffer.from(data), key, sigBuffer);
77
+ }
78
+ catch {
79
+ return false;
80
+ }
81
+ }
82
+ // Public key cache: agentKey -> base64 public key
83
+ const keyCache = new Map();
84
+ function registerAgentPublicKey(agentKey, publicKeyBase64) {
85
+ keyCache.set(agentKey, publicKeyBase64);
86
+ }
87
+ function getAgentPublicKey(agentKey) {
88
+ return keyCache.get(agentKey);
89
+ }
90
+ /**
91
+ * Full Web Bot Auth verification.
92
+ * Checks Signature-Input + Signature headers against agent's registered public key.
93
+ */
94
+ function verifyWebBotAuth(headers, request, agentKey) {
95
+ const signatureInput = headers['signature-input'];
96
+ const signature = headers['signature'];
97
+ if (!signatureInput || !signature)
98
+ return false;
99
+ const parsed = parseSignatureInput(signatureInput);
100
+ if (!parsed)
101
+ return false;
102
+ // Check algorithm is ed25519
103
+ if (parsed.params.alg && parsed.params.alg !== 'ed25519')
104
+ return false;
105
+ // Check expiry
106
+ if (parsed.params.expires && Number(parsed.params.expires) < Date.now() / 1000)
107
+ return false;
108
+ // Get public key
109
+ const pubKey = getAgentPublicKey(agentKey) || getAgentPublicKey(parsed.params.keyid);
110
+ if (!pubKey)
111
+ return false;
112
+ // Build signature base and verify
113
+ const base = buildSignatureBase(parsed.components, request, signatureInput, parsed.label);
114
+ // Extract signature value (format: sig1=:base64:)
115
+ const sigMatch = signature.match(new RegExp(`${parsed.label}=:([^:]+):`));
116
+ if (!sigMatch)
117
+ return false;
118
+ return verifyEd25519Signature(pubKey, sigMatch[1], base);
119
+ }
120
+ //# sourceMappingURL=webbotauth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webbotauth.js","sourceRoot":"","sources":["../src/webbotauth.ts"],"names":[],"mappings":"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"}
package/dist/xmtp.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ export declare function initXMTP(): Promise<void>;
2
+ export declare function notifyDenial(agent: string, amount: number, trustScore: number, tier: string, dailyLimit: number, dailySpent: number, reason: string, txTo: string): Promise<void>;
3
+ export declare function notifyTrustChange(agent: string, oldScore: number, newScore: number, oldTier: string, newTier: string, reason: string): Promise<void>;
4
+ export declare function notifyBudgetWarning(agent: string, spent: number, limit: number): Promise<void>;
5
+ export declare function notifyAnomaly(agent: string, pattern: string, action: string, riskPenalty: number, oldScore: number, newScore: number): Promise<void>;
6
+ //# sourceMappingURL=xmtp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xmtp.d.ts","sourceRoot":"","sources":["../src/xmtp.ts"],"names":[],"mappings":"AAoEA,wBAAsB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CA0C9C;AAED,wBAAsB,YAAY,CAChC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CAcf;AAED,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAQf;AAED,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CAUf;AAED,wBAAsB,aAAa,CACjC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAUf"}
package/dist/xmtp.js ADDED
@@ -0,0 +1,161 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.initXMTP = initXMTP;
4
+ exports.notifyDenial = notifyDenial;
5
+ exports.notifyTrustChange = notifyTrustChange;
6
+ exports.notifyBudgetWarning = notifyBudgetWarning;
7
+ exports.notifyAnomaly = notifyAnomaly;
8
+ const node_sdk_1 = require("@xmtp/node-sdk");
9
+ const accounts_1 = require("viem/accounts");
10
+ const viem_1 = require("viem");
11
+ const config_1 = require("./config");
12
+ const HUMAN_ADDRESS = process.env.HUMAN_XMTP_ADDRESS || '';
13
+ // Module-level state
14
+ let xmtpClient = null;
15
+ let humanDm = null;
16
+ let lastDeniedAgent = '';
17
+ function humanIdentifier() {
18
+ return {
19
+ identifier: HUMAN_ADDRESS.toLowerCase(),
20
+ identifierKind: 0 /* IdentifierKind.Ethereum */,
21
+ };
22
+ }
23
+ // ----------------------------------------------------------------
24
+ // Incoming message listener — detects "override" replies
25
+ // ----------------------------------------------------------------
26
+ async function startMessageListener() {
27
+ if (!xmtpClient)
28
+ return;
29
+ try {
30
+ const stream = await xmtpClient.conversations.streamAllMessages();
31
+ for await (const message of stream) {
32
+ try {
33
+ const text = typeof message.content === 'string' ? message.content.trim().toLowerCase() : '';
34
+ if (text.startsWith('override') && lastDeniedAgent) {
35
+ const port = process.env.PORT || '4021';
36
+ const agentToOverride = lastDeniedAgent;
37
+ lastDeniedAgent = '';
38
+ const res = await fetch(`http://localhost:${port}/api/override/${agentToOverride}`, { method: 'POST' });
39
+ if (res.ok) {
40
+ console.log(`[XMTP] Override accepted for agent: ${agentToOverride}`);
41
+ }
42
+ }
43
+ }
44
+ catch (err) {
45
+ console.error('[XMTP] Error processing message:', err);
46
+ }
47
+ }
48
+ }
49
+ catch (err) {
50
+ console.error('[XMTP] Message stream error:', err);
51
+ }
52
+ }
53
+ // ----------------------------------------------------------------
54
+ // Send helper — finds or creates DM with human, caches it
55
+ // ----------------------------------------------------------------
56
+ async function sendToHuman(text) {
57
+ if (!xmtpClient)
58
+ return;
59
+ try {
60
+ if (!humanDm) {
61
+ humanDm = await xmtpClient.conversations.createDmWithIdentifier(humanIdentifier());
62
+ }
63
+ await humanDm.sendText(text);
64
+ }
65
+ catch (err) {
66
+ console.error('[XMTP] Send error:', err);
67
+ humanDm = null; // reset so next call retries
68
+ }
69
+ }
70
+ // ----------------------------------------------------------------
71
+ // Exported functions
72
+ // ----------------------------------------------------------------
73
+ async function initXMTP() {
74
+ if (!(0, config_1.getConfig)().xmtp?.enabled) {
75
+ console.log('[XMTP] Disabled by config');
76
+ return;
77
+ }
78
+ const privateKey = process.env.XMTP_PRIVATE_KEY;
79
+ if (!privateKey || !HUMAN_ADDRESS) {
80
+ console.log('[XMTP] Not configured — notifications disabled');
81
+ return;
82
+ }
83
+ try {
84
+ const account = (0, accounts_1.privateKeyToAccount)(privateKey);
85
+ const signer = {
86
+ type: 'EOA',
87
+ getIdentifier: () => ({
88
+ identifier: account.address.toLowerCase(),
89
+ identifierKind: 0 /* IdentifierKind.Ethereum */,
90
+ }),
91
+ signMessage: async (message) => {
92
+ const sig = await account.signMessage({ message });
93
+ return (0, viem_1.hexToBytes)(sig);
94
+ },
95
+ };
96
+ // `as any` required: ClientOptions is a union type that doesn't survive
97
+ // Omit<> in Client.create's signature — SDK types collapse the union.
98
+ xmtpClient = await node_sdk_1.Client.create(signer, { env: 'production' });
99
+ // Warm up the DM channel
100
+ humanDm = await xmtpClient.conversations.createDmWithIdentifier(humanIdentifier());
101
+ // Start listening for override replies (fire and forget)
102
+ startMessageListener().catch((err) => {
103
+ console.error('[XMTP] Listener startup error:', err);
104
+ });
105
+ console.log('[XMTP] Initialized — notifications enabled');
106
+ }
107
+ catch (err) {
108
+ console.error('[XMTP] Init failed:', err);
109
+ }
110
+ }
111
+ async function notifyDenial(agent, amount, trustScore, tier, dailyLimit, dailySpent, reason, txTo) {
112
+ if (!xmtpClient)
113
+ return;
114
+ lastDeniedAgent = agent;
115
+ const msg = [
116
+ `⚠️ Transaction denied`,
117
+ `Agent: ${agent}`,
118
+ `Amount: $${amount.toFixed(2)} USDC → ${txTo}`,
119
+ `Trust score: ${trustScore} (${tier} tier)`,
120
+ `Daily limit: $${dailyLimit} | Spent today: $${dailySpent.toFixed(2)}`,
121
+ `Reason: ${reason}`,
122
+ ``,
123
+ `Reply "override" to approve this transaction.`,
124
+ ].join('\n');
125
+ await sendToHuman(msg);
126
+ }
127
+ async function notifyTrustChange(agent, oldScore, newScore, oldTier, newTier, reason) {
128
+ if (!xmtpClient)
129
+ return;
130
+ const msg = [
131
+ `📊 Trust update: ${agent}`,
132
+ `Score: ${oldScore} → ${newScore} | Tier: ${oldTier} → ${newTier}`,
133
+ `Reason: ${reason}`,
134
+ ].join('\n');
135
+ await sendToHuman(msg);
136
+ }
137
+ async function notifyBudgetWarning(agent, spent, limit) {
138
+ if (!xmtpClient)
139
+ return;
140
+ const percentage = Math.round((spent / limit) * 100);
141
+ const remaining = limit - spent;
142
+ const msg = [
143
+ `💰 Budget alert: ${agent}`,
144
+ `Daily spend: $${spent.toFixed(2)} / $${limit} (${percentage}%)`,
145
+ `Remaining: $${remaining.toFixed(2)}`,
146
+ ].join('\n');
147
+ await sendToHuman(msg);
148
+ }
149
+ async function notifyAnomaly(agent, pattern, action, riskPenalty, oldScore, newScore) {
150
+ if (!xmtpClient)
151
+ return;
152
+ const msg = [
153
+ `🚨 Anomaly: ${agent}`,
154
+ `Pattern: ${pattern}`,
155
+ `Action: ${action}`,
156
+ `Risk penalty: -${riskPenalty}`,
157
+ `Trust score: ${oldScore} → ${newScore}`,
158
+ ].join('\n');
159
+ await sendToHuman(msg);
160
+ }
161
+ //# sourceMappingURL=xmtp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xmtp.js","sourceRoot":"","sources":["../src/xmtp.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "triage-ows",
3
+ "version": "1.0.0",
4
+ "description": "Reputation-gated spending policies for OWS agent wallets",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "bin": {
8
+ "triage-ows": "./bin/triage-ows.js",
9
+ "triage-policy": "./bin/triage-policy.js"
10
+ },
11
+ "files": [
12
+ "bin/",
13
+ "src/",
14
+ "dist/",
15
+ "dashboard-dist/",
16
+ "triage.config.example.json",
17
+ "policy-template.json",
18
+ "README.md"
19
+ ],
20
+ "scripts": {
21
+ "build": "tsc",
22
+ "prepublishOnly": "npm run build",
23
+ "seed": "npx tsx scripts/seed-demo.ts",
24
+ "simulate": "npx tsx scripts/simulate.ts"
25
+ },
26
+ "peerDependencies": {
27
+ "hono": ">=4.0.0"
28
+ },
29
+ "dependencies": {
30
+ "@hono/node-server": "^1.19.12",
31
+ "@worldcoin/idkit-server": "^1.0.0",
32
+ "@xmtp/node-sdk": "^6.0.0",
33
+ "viem": "^2.47.6",
34
+ "ws": "^8.0.0"
35
+ },
36
+ "devDependencies": {
37
+ "@types/node": "^22.0.0",
38
+ "@types/ws": "^8.0.0",
39
+ "hono": "^4.12.0",
40
+ "typescript": "^5.0.0"
41
+ },
42
+ "keywords": [
43
+ "ows",
44
+ "open-wallet-standard",
45
+ "policy",
46
+ "trust",
47
+ "reputation",
48
+ "agent",
49
+ "spending-governance",
50
+ "hono"
51
+ ],
52
+ "license": "MIT",
53
+ "repository": {
54
+ "type": "git",
55
+ "url": "https://github.com/ioannisCC/triage-hackathon"
56
+ },
57
+ "homepage": "https://github.com/ioannisCC/triage-hackathon#readme"
58
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "id": "triage-trust",
3
+ "name": "Triage Reputation-Gated Policy",
4
+ "version": 1,
5
+ "created_at": "2026-04-04T00:00:00Z",
6
+ "rules": [
7
+ { "type": "allowed_chains", "chain_ids": ["eip155:84532"] }
8
+ ],
9
+ "executable": "./node_modules/.bin/triage-policy",
10
+ "config": {
11
+ "scoring_server": "http://localhost:4021"
12
+ },
13
+ "action": "deny"
14
+ }
package/src/config.ts ADDED
@@ -0,0 +1,86 @@
1
+ import { readFileSync } from 'fs'
2
+ import { join } from 'path'
3
+ import type { SpendingTier } from './types'
4
+ import { updateSpendingTiers } from './types'
5
+
6
+ export interface TriageConfig {
7
+ scoreBands?: Array<{
8
+ name: string
9
+ min: number
10
+ dailyLimit: number
11
+ perTxLimit: number
12
+ color?: string
13
+ }>
14
+
15
+ warningThreshold?: number
16
+
17
+ xmtp?: { enabled: boolean }
18
+ worldId?: { enabled: boolean }
19
+ webBotAuth?: { enabled: boolean }
20
+ networkScore?: { enabled: boolean }
21
+
22
+ scoring?: {
23
+ overrideBoost?: number
24
+ maxFrequencyPenalty?: number
25
+ inactivityDecayRate?: number
26
+ }
27
+
28
+ port?: number
29
+ dashboardEnabled?: boolean
30
+ }
31
+
32
+ const DEFAULT_CONFIG: Required<TriageConfig> = {
33
+ scoreBands: [
34
+ { name: 'Sovereign', min: 80, dailyLimit: 1000, perTxLimit: 500, color: '#fff8e1' },
35
+ { name: 'Trusted', min: 60, dailyLimit: 200, perTxLimit: 100, color: '#ffd700' },
36
+ { name: 'Building', min: 40, dailyLimit: 50, perTxLimit: 25, color: '#4caf50' },
37
+ { name: 'Cautious', min: 20, dailyLimit: 10, perTxLimit: 5, color: '#00bcd4' },
38
+ { name: 'Restricted', min: 1, dailyLimit: 2, perTxLimit: 1, color: '#2196f3' },
39
+ { name: 'Frozen', min: 0, dailyLimit: 0, perTxLimit: 0, color: '#1a1a4e' },
40
+ ],
41
+ warningThreshold: 0.8,
42
+ xmtp: { enabled: true },
43
+ worldId: { enabled: true },
44
+ webBotAuth: { enabled: true },
45
+ networkScore: { enabled: true },
46
+ scoring: { overrideBoost: 3, maxFrequencyPenalty: 10, inactivityDecayRate: 0.5 },
47
+ port: 4021,
48
+ dashboardEnabled: true,
49
+ }
50
+
51
+ let _config: Required<TriageConfig> = { ...DEFAULT_CONFIG }
52
+
53
+ export function loadConfig(configPath?: string): Required<TriageConfig> {
54
+ const path = configPath || process.env.TRIAGE_CONFIG_PATH || join(process.cwd(), 'triage.config.json')
55
+ try {
56
+ const raw = readFileSync(path, 'utf-8')
57
+ const parsed = JSON.parse(raw) as TriageConfig
58
+ _config = {
59
+ ...DEFAULT_CONFIG,
60
+ ...parsed,
61
+ xmtp: { ...DEFAULT_CONFIG.xmtp, ...parsed.xmtp },
62
+ worldId: { ...DEFAULT_CONFIG.worldId, ...parsed.worldId },
63
+ webBotAuth: { ...DEFAULT_CONFIG.webBotAuth, ...parsed.webBotAuth },
64
+ networkScore: { ...DEFAULT_CONFIG.networkScore, ...parsed.networkScore },
65
+ scoring: { ...DEFAULT_CONFIG.scoring, ...parsed.scoring },
66
+ }
67
+ if (parsed.scoreBands) {
68
+ _config.scoreBands = parsed.scoreBands
69
+ updateSpendingTiers(parsed.scoreBands.map(b => ({
70
+ name: b.name as SpendingTier['name'],
71
+ color: b.color || '#666',
72
+ dailyLimit: b.dailyLimit,
73
+ perTxLimit: b.perTxLimit,
74
+ minScore: b.min,
75
+ })))
76
+ }
77
+ console.log(`[Config] Loaded from ${path}`)
78
+ } catch {
79
+ console.log('[Config] No triage.config.json found — using defaults')
80
+ }
81
+ return _config
82
+ }
83
+
84
+ export function getConfig(): Required<TriageConfig> {
85
+ return _config
86
+ }