instar 0.26.11 → 0.27.2
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/README.md +1 -1
- package/dist/commands/init.d.ts +5 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +46 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +228 -36
- package/dist/commands/server.js.map +1 -1
- package/dist/commands/slack-cli.d.ts +6 -0
- package/dist/commands/slack-cli.d.ts.map +1 -1
- package/dist/commands/slack-cli.js +99 -1
- package/dist/commands/slack-cli.js.map +1 -1
- package/dist/core/GitSync.d.ts.map +1 -1
- package/dist/core/GitSync.js +47 -5
- package/dist/core/GitSync.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts +7 -1
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +19 -1
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/types.d.ts +9 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/identity/IdentityManager.d.ts +70 -0
- package/dist/identity/IdentityManager.d.ts.map +1 -0
- package/dist/identity/IdentityManager.js +179 -0
- package/dist/identity/IdentityManager.js.map +1 -0
- package/dist/identity/KeyEncryption.d.ts +40 -0
- package/dist/identity/KeyEncryption.d.ts.map +1 -0
- package/dist/identity/KeyEncryption.js +93 -0
- package/dist/identity/KeyEncryption.js.map +1 -0
- package/dist/identity/KeyRevocation.d.ts +68 -0
- package/dist/identity/KeyRevocation.d.ts.map +1 -0
- package/dist/identity/KeyRevocation.js +171 -0
- package/dist/identity/KeyRevocation.js.map +1 -0
- package/dist/identity/KeyRotation.d.ts +43 -0
- package/dist/identity/KeyRotation.d.ts.map +1 -0
- package/dist/identity/KeyRotation.js +81 -0
- package/dist/identity/KeyRotation.js.map +1 -0
- package/dist/identity/Migration.d.ts +50 -0
- package/dist/identity/Migration.d.ts.map +1 -0
- package/dist/identity/Migration.js +125 -0
- package/dist/identity/Migration.js.map +1 -0
- package/dist/identity/RecoveryPhrase.d.ts +43 -0
- package/dist/identity/RecoveryPhrase.d.ts.map +1 -0
- package/dist/identity/RecoveryPhrase.js +93 -0
- package/dist/identity/RecoveryPhrase.js.map +1 -0
- package/dist/identity/index.d.ts +13 -0
- package/dist/identity/index.d.ts.map +1 -0
- package/dist/identity/index.js +20 -0
- package/dist/identity/index.js.map +1 -0
- package/dist/identity/types.d.ts +101 -0
- package/dist/identity/types.d.ts.map +1 -0
- package/dist/identity/types.js +55 -0
- package/dist/identity/types.js.map +1 -0
- package/dist/knowledge/TreeTriage.d.ts.map +1 -1
- package/dist/knowledge/TreeTriage.js +9 -0
- package/dist/knowledge/TreeTriage.js.map +1 -1
- package/dist/memory/TopicMemory.d.ts +2 -0
- package/dist/memory/TopicMemory.d.ts.map +1 -1
- package/dist/memory/TopicMemory.js +55 -0
- package/dist/memory/TopicMemory.js.map +1 -1
- package/dist/messaging/slack/SlackAdapter.d.ts +15 -4
- package/dist/messaging/slack/SlackAdapter.d.ts.map +1 -1
- package/dist/messaging/slack/SlackAdapter.js +131 -14
- package/dist/messaging/slack/SlackAdapter.js.map +1 -1
- package/dist/messaging/slack/SocketModeClient.d.ts +2 -0
- package/dist/messaging/slack/SocketModeClient.d.ts.map +1 -1
- package/dist/messaging/slack/SocketModeClient.js +31 -1
- package/dist/messaging/slack/SocketModeClient.js.map +1 -1
- package/dist/moltbridge/MoltBridgeClient.d.ts +124 -0
- package/dist/moltbridge/MoltBridgeClient.d.ts.map +1 -0
- package/dist/moltbridge/MoltBridgeClient.js +321 -0
- package/dist/moltbridge/MoltBridgeClient.js.map +1 -0
- package/dist/moltbridge/ProfileCompiler.d.ts +68 -0
- package/dist/moltbridge/ProfileCompiler.d.ts.map +1 -0
- package/dist/moltbridge/ProfileCompiler.js +317 -0
- package/dist/moltbridge/ProfileCompiler.js.map +1 -0
- package/dist/moltbridge/index.d.ts +12 -0
- package/dist/moltbridge/index.d.ts.map +1 -0
- package/dist/moltbridge/index.js +11 -0
- package/dist/moltbridge/index.js.map +1 -0
- package/dist/moltbridge/routes.d.ts +21 -0
- package/dist/moltbridge/routes.d.ts.map +1 -0
- package/dist/moltbridge/routes.js +224 -0
- package/dist/moltbridge/routes.js.map +1 -0
- package/dist/moltbridge/types.d.ts +93 -0
- package/dist/moltbridge/types.d.ts.map +1 -0
- package/dist/moltbridge/types.js +20 -0
- package/dist/moltbridge/types.js.map +1 -0
- package/dist/monitoring/PresenceProxy.d.ts +3 -0
- package/dist/monitoring/PresenceProxy.d.ts.map +1 -1
- package/dist/monitoring/PresenceProxy.js +80 -3
- package/dist/monitoring/PresenceProxy.js.map +1 -1
- package/dist/monitoring/SessionMonitor.d.ts +7 -0
- package/dist/monitoring/SessionMonitor.d.ts.map +1 -1
- package/dist/monitoring/SessionMonitor.js +47 -22
- package/dist/monitoring/SessionMonitor.js.map +1 -1
- package/dist/monitoring/TriageOrchestrator.d.ts.map +1 -1
- package/dist/monitoring/TriageOrchestrator.js +25 -1
- package/dist/monitoring/TriageOrchestrator.js.map +1 -1
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +29 -1
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/server/AgentServer.d.ts +1 -0
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +1 -0
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/routes.d.ts +2 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +21 -0
- package/dist/server/routes.js.map +1 -1
- package/dist/threadline/AuthorizationPolicy.d.ts +110 -0
- package/dist/threadline/AuthorizationPolicy.d.ts.map +1 -0
- package/dist/threadline/AuthorizationPolicy.js +226 -0
- package/dist/threadline/AuthorizationPolicy.js.map +1 -0
- package/dist/threadline/DiscoveryWaterfall.d.ts +73 -0
- package/dist/threadline/DiscoveryWaterfall.d.ts.map +1 -0
- package/dist/threadline/DiscoveryWaterfall.js +113 -0
- package/dist/threadline/DiscoveryWaterfall.js.map +1 -0
- package/dist/threadline/ListenerSessionManager.d.ts.map +1 -1
- package/dist/threadline/ListenerSessionManager.js +2 -0
- package/dist/threadline/ListenerSessionManager.js.map +1 -1
- package/dist/threadline/MessageSecurity.d.ts +49 -0
- package/dist/threadline/MessageSecurity.d.ts.map +1 -0
- package/dist/threadline/MessageSecurity.js +93 -0
- package/dist/threadline/MessageSecurity.js.map +1 -0
- package/dist/threadline/SecureInvitation.d.ts +79 -0
- package/dist/threadline/SecureInvitation.d.ts.map +1 -0
- package/dist/threadline/SecureInvitation.js +164 -0
- package/dist/threadline/SecureInvitation.js.map +1 -0
- package/dist/threadline/TrustAuditLog.d.ts +49 -0
- package/dist/threadline/TrustAuditLog.d.ts.map +1 -0
- package/dist/threadline/TrustAuditLog.js +111 -0
- package/dist/threadline/TrustAuditLog.js.map +1 -0
- package/dist/threadline/TrustEvaluator.d.ts +69 -0
- package/dist/threadline/TrustEvaluator.d.ts.map +1 -0
- package/dist/threadline/TrustEvaluator.js +93 -0
- package/dist/threadline/TrustEvaluator.js.map +1 -0
- package/dist/threadline/UnifiedTrustWiring.d.ts +66 -0
- package/dist/threadline/UnifiedTrustWiring.d.ts.map +1 -0
- package/dist/threadline/UnifiedTrustWiring.js +192 -0
- package/dist/threadline/UnifiedTrustWiring.js.map +1 -0
- package/dist/threadline/client/IdentityManager.d.ts +27 -6
- package/dist/threadline/client/IdentityManager.d.ts.map +1 -1
- package/dist/threadline/client/IdentityManager.js +64 -18
- package/dist/threadline/client/IdentityManager.js.map +1 -1
- package/dist/threadline/relay/SybilProtection.d.ts +78 -0
- package/dist/threadline/relay/SybilProtection.d.ts.map +1 -0
- package/dist/threadline/relay/SybilProtection.js +187 -0
- package/dist/threadline/relay/SybilProtection.js.map +1 -0
- package/package.json +9 -3
- package/playbook-scripts/build-state.py +529 -0
- package/scripts/check-contract-evidence.js +103 -0
- package/scripts/pre-push-gate.js +53 -0
- package/scripts/run-contract-tests.js +75 -0
- package/src/data/builtin-manifest.json +87 -63
- package/src/templates/hooks/build-stop-hook.sh +79 -0
- package/upgrades/0.26.10.md +36 -0
- package/upgrades/0.27.1.md +101 -0
- package/upgrades/0.27.2.md +36 -0
- package/upgrades/NEXT.md +0 -27
- /package/.claude/skills/secret-setup/{SKILL.md → skill.md} +0 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SybilProtection — Relay-side protection against identity flooding.
|
|
3
|
+
*
|
|
4
|
+
* Spec Section 3.12:
|
|
5
|
+
* - Proof-of-Work at connection (Hashcash-style, ~1s commodity hardware)
|
|
6
|
+
* - Dynamic difficulty (3x spike → scale up, 10x ceiling)
|
|
7
|
+
* - Fast-solver throttling (<100ms = suspicious)
|
|
8
|
+
* - Identity aging (new identities hidden from directory for 1h)
|
|
9
|
+
* - IP rate limiting (10 new connections/min, 50 total/IP)
|
|
10
|
+
* - Identity-level limits (5 identities per IP per hour)
|
|
11
|
+
*/
|
|
12
|
+
/** Identity aging: new identities hidden for 1 hour */
|
|
13
|
+
export declare const IDENTITY_AGING_MS: number;
|
|
14
|
+
/** IP rate limits */
|
|
15
|
+
export declare const IP_LIMITS: {
|
|
16
|
+
readonly newConnectionsPerMinute: 10;
|
|
17
|
+
readonly totalConnectionsPerIP: 50;
|
|
18
|
+
readonly identitiesPerIPPerHour: 5;
|
|
19
|
+
};
|
|
20
|
+
export interface PoWChallenge {
|
|
21
|
+
epoch: string;
|
|
22
|
+
difficulty: number;
|
|
23
|
+
issuedAt: number;
|
|
24
|
+
}
|
|
25
|
+
export interface PoWSolution {
|
|
26
|
+
challenge: PoWChallenge;
|
|
27
|
+
nonce: string;
|
|
28
|
+
solveTimeMs: number;
|
|
29
|
+
}
|
|
30
|
+
export interface IPConnectionState {
|
|
31
|
+
recentConnections: number[];
|
|
32
|
+
identities: Set<string>;
|
|
33
|
+
identityTimestamps: number[];
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Generate a PoW challenge for a connecting agent.
|
|
37
|
+
*/
|
|
38
|
+
export declare function generateChallenge(clientIP: string, currentDifficulty?: number): PoWChallenge;
|
|
39
|
+
/**
|
|
40
|
+
* Verify a PoW solution.
|
|
41
|
+
*
|
|
42
|
+
* Checks:
|
|
43
|
+
* 1. SHA-256(epoch || clientIP || nonce) has enough leading zero bits
|
|
44
|
+
* 2. Epoch is current (within tolerance)
|
|
45
|
+
* 3. Not solved suspiciously fast
|
|
46
|
+
*/
|
|
47
|
+
export declare function verifySolution(solution: PoWSolution, clientIP: string): {
|
|
48
|
+
valid: boolean;
|
|
49
|
+
suspicious: boolean;
|
|
50
|
+
reason?: string;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Solve a PoW challenge (for client-side use / testing).
|
|
54
|
+
*/
|
|
55
|
+
export declare function solveChallenge(challenge: PoWChallenge, clientIP: string): PoWSolution;
|
|
56
|
+
/**
|
|
57
|
+
* Compute dynamic difficulty based on connection rate.
|
|
58
|
+
*
|
|
59
|
+
* Attack condition: >3x rolling 10-minute average = spike.
|
|
60
|
+
* Difficulty scales linearly from 1x to ceiling proportional to spike magnitude.
|
|
61
|
+
*/
|
|
62
|
+
export declare function computeDynamicDifficulty(recentConnectionRate: number, baselineRate: number): number;
|
|
63
|
+
export declare class IPRateLimiter {
|
|
64
|
+
private ipStates;
|
|
65
|
+
/**
|
|
66
|
+
* Check if a new connection from an IP is allowed.
|
|
67
|
+
*/
|
|
68
|
+
checkConnection(ip: string, fingerprint: string): {
|
|
69
|
+
allowed: boolean;
|
|
70
|
+
reason?: string;
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* Check if an identity is old enough to appear in directory.
|
|
74
|
+
*/
|
|
75
|
+
isIdentityAged(firstSeenTimestamp: number, now?: number): boolean;
|
|
76
|
+
private getOrCreateState;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=SybilProtection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SybilProtection.d.ts","sourceRoot":"","sources":["../../../src/threadline/relay/SybilProtection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAkBH,uDAAuD;AACvD,eAAO,MAAM,iBAAiB,QAAiB,CAAC;AAEhD,qBAAqB;AACrB,eAAO,MAAM,SAAS;;;;CAIZ,CAAC;AAIX,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,YAAY,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACxB,kBAAkB,EAAE,MAAM,EAAE,CAAC;CAC9B;AAID;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,iBAAiB,CAAC,EAAE,MAAM,GACzB,YAAY,CAOd;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,WAAW,EACrB,QAAQ,EAAE,MAAM,GACf;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAoB1D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,GAAG,WAAW,CAgBrF;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,oBAAoB,EAAE,MAAM,EAC5B,YAAY,EAAE,MAAM,GACnB,MAAM,CAUR;AAID,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAA6C;IAE7D;;OAEG;IACH,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE;IAoCvF;;OAEG;IACH,cAAc,CAAC,kBAAkB,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO;IAIjE,OAAO,CAAC,gBAAgB;CAQzB"}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SybilProtection — Relay-side protection against identity flooding.
|
|
3
|
+
*
|
|
4
|
+
* Spec Section 3.12:
|
|
5
|
+
* - Proof-of-Work at connection (Hashcash-style, ~1s commodity hardware)
|
|
6
|
+
* - Dynamic difficulty (3x spike → scale up, 10x ceiling)
|
|
7
|
+
* - Fast-solver throttling (<100ms = suspicious)
|
|
8
|
+
* - Identity aging (new identities hidden from directory for 1h)
|
|
9
|
+
* - IP rate limiting (10 new connections/min, 50 total/IP)
|
|
10
|
+
* - Identity-level limits (5 identities per IP per hour)
|
|
11
|
+
*/
|
|
12
|
+
import crypto from 'node:crypto';
|
|
13
|
+
// ── Constants ────────────────────────────────────────────────────────
|
|
14
|
+
/** Default PoW difficulty: 20 leading zero bits (~1s on commodity hardware) */
|
|
15
|
+
const DEFAULT_DIFFICULTY = 20;
|
|
16
|
+
/** Max difficulty ceiling: 10x baseline = ~10s on commodity hardware */
|
|
17
|
+
const MAX_DIFFICULTY_BITS = DEFAULT_DIFFICULTY + 4; // ~16x baseline, capped
|
|
18
|
+
/** Epoch rotation interval (10 minutes) */
|
|
19
|
+
const EPOCH_INTERVAL_MS = 10 * 60 * 1000;
|
|
20
|
+
/** Fast-solver threshold: solutions under 100ms are suspicious */
|
|
21
|
+
const FAST_SOLVER_THRESHOLD_MS = 100;
|
|
22
|
+
/** Identity aging: new identities hidden for 1 hour */
|
|
23
|
+
export const IDENTITY_AGING_MS = 60 * 60 * 1000;
|
|
24
|
+
/** IP rate limits */
|
|
25
|
+
export const IP_LIMITS = {
|
|
26
|
+
newConnectionsPerMinute: 10,
|
|
27
|
+
totalConnectionsPerIP: 50,
|
|
28
|
+
identitiesPerIPPerHour: 5,
|
|
29
|
+
};
|
|
30
|
+
// ── PoW Functions ────────────────────────────────────────────────────
|
|
31
|
+
/**
|
|
32
|
+
* Generate a PoW challenge for a connecting agent.
|
|
33
|
+
*/
|
|
34
|
+
export function generateChallenge(clientIP, currentDifficulty) {
|
|
35
|
+
const epoch = getCurrentEpoch();
|
|
36
|
+
return {
|
|
37
|
+
epoch,
|
|
38
|
+
difficulty: currentDifficulty ?? DEFAULT_DIFFICULTY,
|
|
39
|
+
issuedAt: Date.now(),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Verify a PoW solution.
|
|
44
|
+
*
|
|
45
|
+
* Checks:
|
|
46
|
+
* 1. SHA-256(epoch || clientIP || nonce) has enough leading zero bits
|
|
47
|
+
* 2. Epoch is current (within tolerance)
|
|
48
|
+
* 3. Not solved suspiciously fast
|
|
49
|
+
*/
|
|
50
|
+
export function verifySolution(solution, clientIP) {
|
|
51
|
+
// Check epoch freshness (allow previous + current epoch)
|
|
52
|
+
const currentEpoch = getCurrentEpoch();
|
|
53
|
+
const previousEpoch = getEpoch(Date.now() - EPOCH_INTERVAL_MS);
|
|
54
|
+
if (solution.challenge.epoch !== currentEpoch && solution.challenge.epoch !== previousEpoch) {
|
|
55
|
+
return { valid: false, suspicious: false, reason: 'Stale epoch — challenge expired' };
|
|
56
|
+
}
|
|
57
|
+
// Verify hash
|
|
58
|
+
const hash = computePoWHash(solution.challenge.epoch, clientIP, solution.nonce);
|
|
59
|
+
const leadingZeros = countLeadingZeroBits(hash);
|
|
60
|
+
if (leadingZeros < solution.challenge.difficulty) {
|
|
61
|
+
return { valid: false, suspicious: false, reason: `Insufficient work: ${leadingZeros} < ${solution.challenge.difficulty} bits` };
|
|
62
|
+
}
|
|
63
|
+
// Fast-solver detection
|
|
64
|
+
const elapsedMs = Date.now() - solution.challenge.issuedAt;
|
|
65
|
+
const suspicious = elapsedMs < FAST_SOLVER_THRESHOLD_MS;
|
|
66
|
+
return { valid: true, suspicious };
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Solve a PoW challenge (for client-side use / testing).
|
|
70
|
+
*/
|
|
71
|
+
export function solveChallenge(challenge, clientIP) {
|
|
72
|
+
const startTime = Date.now();
|
|
73
|
+
let nonce = 0;
|
|
74
|
+
while (true) {
|
|
75
|
+
const nonceHex = nonce.toString(16).padStart(16, '0');
|
|
76
|
+
const hash = computePoWHash(challenge.epoch, clientIP, nonceHex);
|
|
77
|
+
if (countLeadingZeroBits(hash) >= challenge.difficulty) {
|
|
78
|
+
return {
|
|
79
|
+
challenge,
|
|
80
|
+
nonce: nonceHex,
|
|
81
|
+
solveTimeMs: Date.now() - startTime,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
nonce++;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Compute dynamic difficulty based on connection rate.
|
|
89
|
+
*
|
|
90
|
+
* Attack condition: >3x rolling 10-minute average = spike.
|
|
91
|
+
* Difficulty scales linearly from 1x to ceiling proportional to spike magnitude.
|
|
92
|
+
*/
|
|
93
|
+
export function computeDynamicDifficulty(recentConnectionRate, baselineRate) {
|
|
94
|
+
if (baselineRate <= 0)
|
|
95
|
+
return DEFAULT_DIFFICULTY;
|
|
96
|
+
const ratio = recentConnectionRate / baselineRate;
|
|
97
|
+
if (ratio <= 3)
|
|
98
|
+
return DEFAULT_DIFFICULTY;
|
|
99
|
+
// Linear scale from baseline to 10x ceiling
|
|
100
|
+
const scaleFactor = Math.min((ratio - 3) / 7, 1); // 0 at 3x, 1 at 10x
|
|
101
|
+
const extraBits = Math.floor(scaleFactor * (MAX_DIFFICULTY_BITS - DEFAULT_DIFFICULTY));
|
|
102
|
+
return Math.min(DEFAULT_DIFFICULTY + extraBits, MAX_DIFFICULTY_BITS);
|
|
103
|
+
}
|
|
104
|
+
// ── IP Rate Limiter ──────────────────────────────────────────────────
|
|
105
|
+
export class IPRateLimiter {
|
|
106
|
+
ipStates = new Map();
|
|
107
|
+
/**
|
|
108
|
+
* Check if a new connection from an IP is allowed.
|
|
109
|
+
*/
|
|
110
|
+
checkConnection(ip, fingerprint) {
|
|
111
|
+
const now = Date.now();
|
|
112
|
+
const state = this.getOrCreateState(ip);
|
|
113
|
+
// Prune old entries
|
|
114
|
+
const oneMinuteAgo = now - 60 * 1000;
|
|
115
|
+
const oneHourAgo = now - 60 * 60 * 1000;
|
|
116
|
+
state.recentConnections = state.recentConnections.filter(t => t > oneMinuteAgo);
|
|
117
|
+
state.identityTimestamps = state.identityTimestamps.filter(t => t > oneHourAgo);
|
|
118
|
+
// Check connections per minute
|
|
119
|
+
if (state.recentConnections.length >= IP_LIMITS.newConnectionsPerMinute) {
|
|
120
|
+
return { allowed: false, reason: `IP rate limit: ${IP_LIMITS.newConnectionsPerMinute} connections/min` };
|
|
121
|
+
}
|
|
122
|
+
// Check total connections per IP
|
|
123
|
+
if (state.recentConnections.length >= IP_LIMITS.totalConnectionsPerIP) {
|
|
124
|
+
return { allowed: false, reason: `IP total limit: ${IP_LIMITS.totalConnectionsPerIP} connections` };
|
|
125
|
+
}
|
|
126
|
+
// Check identities per IP per hour
|
|
127
|
+
if (!state.identities.has(fingerprint) &&
|
|
128
|
+
state.identityTimestamps.length >= IP_LIMITS.identitiesPerIPPerHour) {
|
|
129
|
+
return { allowed: false, reason: `IP identity limit: ${IP_LIMITS.identitiesPerIPPerHour} identities/hour` };
|
|
130
|
+
}
|
|
131
|
+
// Record
|
|
132
|
+
state.recentConnections.push(now);
|
|
133
|
+
if (!state.identities.has(fingerprint)) {
|
|
134
|
+
state.identities.add(fingerprint);
|
|
135
|
+
state.identityTimestamps.push(now);
|
|
136
|
+
}
|
|
137
|
+
return { allowed: true };
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Check if an identity is old enough to appear in directory.
|
|
141
|
+
*/
|
|
142
|
+
isIdentityAged(firstSeenTimestamp, now) {
|
|
143
|
+
return ((now ?? Date.now()) - firstSeenTimestamp) >= IDENTITY_AGING_MS;
|
|
144
|
+
}
|
|
145
|
+
getOrCreateState(ip) {
|
|
146
|
+
let state = this.ipStates.get(ip);
|
|
147
|
+
if (!state) {
|
|
148
|
+
state = { recentConnections: [], identities: new Set(), identityTimestamps: [] };
|
|
149
|
+
this.ipStates.set(ip, state);
|
|
150
|
+
}
|
|
151
|
+
return state;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
// ── Helpers ──────────────────────────────────────────────────────────
|
|
155
|
+
function getCurrentEpoch() {
|
|
156
|
+
return getEpoch(Date.now());
|
|
157
|
+
}
|
|
158
|
+
function getEpoch(timestamp) {
|
|
159
|
+
const epochNum = Math.floor(timestamp / EPOCH_INTERVAL_MS);
|
|
160
|
+
return epochNum.toString(16);
|
|
161
|
+
}
|
|
162
|
+
function computePoWHash(epoch, clientIP, nonce) {
|
|
163
|
+
return crypto.createHash('sha256')
|
|
164
|
+
.update(epoch)
|
|
165
|
+
.update(clientIP)
|
|
166
|
+
.update(nonce)
|
|
167
|
+
.digest();
|
|
168
|
+
}
|
|
169
|
+
function countLeadingZeroBits(hash) {
|
|
170
|
+
let bits = 0;
|
|
171
|
+
for (const byte of hash) {
|
|
172
|
+
if (byte === 0) {
|
|
173
|
+
bits += 8;
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
// Count leading zeros in this byte
|
|
177
|
+
let mask = 0x80;
|
|
178
|
+
while (mask > 0 && (byte & mask) === 0) {
|
|
179
|
+
bits++;
|
|
180
|
+
mask >>= 1;
|
|
181
|
+
}
|
|
182
|
+
break;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return bits;
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=SybilProtection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SybilProtection.js","sourceRoot":"","sources":["../../../src/threadline/relay/SybilProtection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,MAAM,MAAM,aAAa,CAAC;AAEjC,wEAAwE;AAExE,+EAA+E;AAC/E,MAAM,kBAAkB,GAAG,EAAE,CAAC;AAE9B,wEAAwE;AACxE,MAAM,mBAAmB,GAAG,kBAAkB,GAAG,CAAC,CAAC,CAAC,wBAAwB;AAE5E,2CAA2C;AAC3C,MAAM,iBAAiB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAEzC,kEAAkE;AAClE,MAAM,wBAAwB,GAAG,GAAG,CAAC;AAErC,uDAAuD;AACvD,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAEhD,qBAAqB;AACrB,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,uBAAuB,EAAE,EAAE;IAC3B,qBAAqB,EAAE,EAAE;IACzB,sBAAsB,EAAE,CAAC;CACjB,CAAC;AAsBX,wEAAwE;AAExE;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAC/B,QAAgB,EAChB,iBAA0B;IAE1B,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;IAChC,OAAO;QACL,KAAK;QACL,UAAU,EAAE,iBAAiB,IAAI,kBAAkB;QACnD,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE;KACrB,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAC5B,QAAqB,EACrB,QAAgB;IAEhB,yDAAyD;IACzD,MAAM,YAAY,GAAG,eAAe,EAAE,CAAC;IACvC,MAAM,aAAa,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,iBAAiB,CAAC,CAAC;IAC/D,IAAI,QAAQ,CAAC,SAAS,CAAC,KAAK,KAAK,YAAY,IAAI,QAAQ,CAAC,SAAS,CAAC,KAAK,KAAK,aAAa,EAAE,CAAC;QAC5F,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,iCAAiC,EAAE,CAAC;IACxF,CAAC;IAED,cAAc;IACd,MAAM,IAAI,GAAG,cAAc,CAAC,QAAQ,CAAC,SAAS,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;IAChF,MAAM,YAAY,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;IAChD,IAAI,YAAY,GAAG,QAAQ,CAAC,SAAS,CAAC,UAAU,EAAE,CAAC;QACjD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,sBAAsB,YAAY,MAAM,QAAQ,CAAC,SAAS,CAAC,UAAU,OAAO,EAAE,CAAC;IACnI,CAAC;IAED,wBAAwB;IACxB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC,SAAS,CAAC,QAAQ,CAAC;IAC3D,MAAM,UAAU,GAAG,SAAS,GAAG,wBAAwB,CAAC;IAExD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;AACrC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,SAAuB,EAAE,QAAgB;IACtE,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,IAAI,KAAK,GAAG,CAAC,CAAC;IAEd,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QACtD,MAAM,IAAI,GAAG,cAAc,CAAC,SAAS,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACjE,IAAI,oBAAoB,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC,UAAU,EAAE,CAAC;YACvD,OAAO;gBACL,SAAS;gBACT,KAAK,EAAE,QAAQ;gBACf,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;aACpC,CAAC;QACJ,CAAC;QACD,KAAK,EAAE,CAAC;IACV,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,wBAAwB,CACtC,oBAA4B,EAC5B,YAAoB;IAEpB,IAAI,YAAY,IAAI,CAAC;QAAE,OAAO,kBAAkB,CAAC;IAEjD,MAAM,KAAK,GAAG,oBAAoB,GAAG,YAAY,CAAC;IAClD,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,kBAAkB,CAAC;IAE1C,4CAA4C;IAC5C,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,oBAAoB;IACtE,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,CAAC,mBAAmB,GAAG,kBAAkB,CAAC,CAAC,CAAC;IACvF,OAAO,IAAI,CAAC,GAAG,CAAC,kBAAkB,GAAG,SAAS,EAAE,mBAAmB,CAAC,CAAC;AACvE,CAAC;AAED,wEAAwE;AAExE,MAAM,OAAO,aAAa;IAChB,QAAQ,GAAmC,IAAI,GAAG,EAAE,CAAC;IAE7D;;OAEG;IACH,eAAe,CAAC,EAAU,EAAE,WAAmB;QAC7C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC;QAExC,oBAAoB;QACpB,MAAM,YAAY,GAAG,GAAG,GAAG,EAAE,GAAG,IAAI,CAAC;QACrC,MAAM,UAAU,GAAG,GAAG,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;QACxC,KAAK,CAAC,iBAAiB,GAAG,KAAK,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC;QAChF,KAAK,CAAC,kBAAkB,GAAG,KAAK,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC;QAEhF,+BAA+B;QAC/B,IAAI,KAAK,CAAC,iBAAiB,CAAC,MAAM,IAAI,SAAS,CAAC,uBAAuB,EAAE,CAAC;YACxE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,kBAAkB,SAAS,CAAC,uBAAuB,kBAAkB,EAAE,CAAC;QAC3G,CAAC;QAED,iCAAiC;QACjC,IAAI,KAAK,CAAC,iBAAiB,CAAC,MAAM,IAAI,SAAS,CAAC,qBAAqB,EAAE,CAAC;YACtE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,mBAAmB,SAAS,CAAC,qBAAqB,cAAc,EAAE,CAAC;QACtG,CAAC;QAED,mCAAmC;QACnC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,WAAW,CAAC;YAClC,KAAK,CAAC,kBAAkB,CAAC,MAAM,IAAI,SAAS,CAAC,sBAAsB,EAAE,CAAC;YACxE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,sBAAsB,SAAS,CAAC,sBAAsB,kBAAkB,EAAE,CAAC;QAC9G,CAAC;QAED,SAAS;QACT,KAAK,CAAC,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;YACvC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YAClC,KAAK,CAAC,kBAAkB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACrC,CAAC;QAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,cAAc,CAAC,kBAA0B,EAAE,GAAY;QACrD,OAAO,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,GAAG,kBAAkB,CAAC,IAAI,iBAAiB,CAAC;IACzE,CAAC;IAEO,gBAAgB,CAAC,EAAU;QACjC,IAAI,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,KAAK,GAAG,EAAE,iBAAiB,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,GAAG,EAAE,EAAE,kBAAkB,EAAE,EAAE,EAAE,CAAC;YACjF,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;QAC/B,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;CACF;AAED,wEAAwE;AAExE,SAAS,eAAe;IACtB,OAAO,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;AAC9B,CAAC;AAED,SAAS,QAAQ,CAAC,SAAiB;IACjC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,iBAAiB,CAAC,CAAC;IAC3D,OAAO,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC/B,CAAC;AAED,SAAS,cAAc,CAAC,KAAa,EAAE,QAAgB,EAAE,KAAa;IACpE,OAAO,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC;SAC/B,MAAM,CAAC,KAAK,CAAC;SACb,MAAM,CAAC,QAAQ,CAAC;SAChB,MAAM,CAAC,KAAK,CAAC;SACb,MAAM,EAAE,CAAC;AACd,CAAC;AAED,SAAS,oBAAoB,CAAC,IAAY;IACxC,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;QACxB,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;YACf,IAAI,IAAI,CAAC,CAAC;QACZ,CAAC;aAAM,CAAC;YACN,mCAAmC;YACnC,IAAI,IAAI,GAAG,IAAI,CAAC;YAChB,OAAO,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBACvC,IAAI,EAAE,CAAC;gBACP,IAAI,KAAK,CAAC,CAAC;YACb,CAAC;YACD,MAAM;QACR,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "instar",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.27.2",
|
|
4
4
|
"description": "Persistent autonomy infrastructure for AI agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -24,13 +24,16 @@
|
|
|
24
24
|
"test:watch": "vitest",
|
|
25
25
|
"test:integration": "vitest run --config vitest.integration.config.ts",
|
|
26
26
|
"test:e2e": "vitest run --config vitest.e2e.config.ts",
|
|
27
|
+
"test:contract": "node scripts/run-contract-tests.js",
|
|
28
|
+
"test:contract:raw": "vitest run --config vitest.contract.config.ts",
|
|
27
29
|
"test:all": "vitest run && vitest run --config vitest.integration.config.ts && vitest run --config vitest.e2e.config.ts",
|
|
28
30
|
"lint": "tsc --noEmit",
|
|
29
31
|
"clean": "rm -rf dist",
|
|
30
32
|
"check:upgrade-guide": "node scripts/check-upgrade-guide.js",
|
|
31
33
|
"check:pre-push-gate": "node scripts/pre-push-gate.js",
|
|
32
34
|
"check:release": "node scripts/analyze-release.js",
|
|
33
|
-
"
|
|
35
|
+
"check:contract-evidence": "node scripts/check-contract-evidence.js",
|
|
36
|
+
"prepublishOnly": "npm run build && npm run check:upgrade-guide && npm run check:contract-evidence",
|
|
34
37
|
"postinstall": "node scripts/fix-better-sqlite3.cjs",
|
|
35
38
|
"prepare": "husky"
|
|
36
39
|
},
|
|
@@ -83,12 +86,15 @@
|
|
|
83
86
|
"@inquirer/prompts": "^8.2.1",
|
|
84
87
|
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
85
88
|
"@noble/ciphers": "^2.1.1",
|
|
89
|
+
"@noble/hashes": "^2.0.1",
|
|
90
|
+
"@scure/bip39": "^2.0.1",
|
|
86
91
|
"better-sqlite3": "^12.8.0",
|
|
87
92
|
"cloudflared": "^0.7.1",
|
|
88
93
|
"commander": "^12.0.0",
|
|
89
94
|
"croner": "^8.0.0",
|
|
90
95
|
"express": "^4.18.0",
|
|
91
96
|
"marked": "^17.0.5",
|
|
97
|
+
"moltbridge": "^0.1.6",
|
|
92
98
|
"picocolors": "^1.0.0",
|
|
93
99
|
"proper-lockfile": "^4.1.2",
|
|
94
100
|
"ws": "^8.19.0",
|
|
@@ -108,6 +114,6 @@
|
|
|
108
114
|
"husky": "^9.1.7",
|
|
109
115
|
"supertest": "^7.2.2",
|
|
110
116
|
"typescript": "^5.9.3",
|
|
111
|
-
"vitest": "^2.
|
|
117
|
+
"vitest": "^2.1.9"
|
|
112
118
|
}
|
|
113
119
|
}
|