@antseed/cli 0.1.158 → 0.1.159
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 +23 -0
- package/dist/cli/commands/buyer/start.d.ts.map +1 -1
- package/dist/cli/commands/buyer/start.js +7 -1
- package/dist/cli/commands/buyer/start.js.map +1 -1
- package/dist/cli/commands/network/browse.d.ts.map +1 -1
- package/dist/cli/commands/network/browse.js +12 -3
- package/dist/cli/commands/network/browse.js.map +1 -1
- package/dist/cli/commands/network/chain-config-helper.d.ts +3 -1
- package/dist/cli/commands/network/chain-config-helper.d.ts.map +1 -1
- package/dist/cli/commands/network/chain-config-helper.js +6 -1
- package/dist/cli/commands/network/chain-config-helper.js.map +1 -1
- package/dist/cli/commands/network/peer.d.ts.map +1 -1
- package/dist/cli/commands/network/peer.js +21 -1
- package/dist/cli/commands/network/peer.js.map +1 -1
- package/dist/cli/commands/seller/contract-clients.test.js +5 -4
- package/dist/cli/commands/seller/contract-clients.test.js.map +1 -1
- package/dist/plugins/verifier-evidence.test.d.ts +2 -0
- package/dist/plugins/verifier-evidence.test.d.ts.map +1 -0
- package/dist/plugins/verifier-evidence.test.js +41 -0
- package/dist/plugins/verifier-evidence.test.js.map +1 -0
- package/dist/plugins/verifier.d.ts +8 -10
- package/dist/plugins/verifier.d.ts.map +1 -1
- package/dist/plugins/verifier.js +23 -51
- package/dist/plugins/verifier.js.map +1 -1
- package/dist/plugins/verifier.test.js +1 -37
- package/dist/plugins/verifier.test.js.map +1 -1
- package/dist/proxy/buyer-proxy.d.ts +2 -1
- package/dist/proxy/buyer-proxy.d.ts.map +1 -1
- package/dist/proxy/buyer-proxy.js +104 -28
- package/dist/proxy/buyer-proxy.js.map +1 -1
- package/dist/proxy/buyer-proxy.test.js +177 -19
- package/dist/proxy/buyer-proxy.test.js.map +1 -1
- package/dist/proxy/network-models.d.ts +1 -2
- package/dist/proxy/network-models.d.ts.map +1 -1
- package/dist/proxy/network-models.js +10 -23
- package/dist/proxy/network-models.js.map +1 -1
- package/dist/proxy/network-models.test.js +56 -27
- package/dist/proxy/network-models.test.js.map +1 -1
- package/dist/proxy/tee-control.d.ts +14 -0
- package/dist/proxy/tee-control.d.ts.map +1 -0
- package/dist/proxy/tee-control.js +100 -0
- package/dist/proxy/tee-control.js.map +1 -0
- package/dist/proxy/tee-control.test.d.ts +2 -0
- package/dist/proxy/tee-control.test.d.ts.map +1 -0
- package/dist/proxy/tee-control.test.js +56 -0
- package/dist/proxy/tee-control.test.js.map +1 -0
- package/dist/proxy/tee-verification.d.ts +24 -0
- package/dist/proxy/tee-verification.d.ts.map +1 -0
- package/dist/proxy/tee-verification.js +128 -0
- package/dist/proxy/tee-verification.js.map +1 -0
- package/dist/proxy/tee-verification.test.d.ts +2 -0
- package/dist/proxy/tee-verification.test.d.ts.map +1 -0
- package/dist/proxy/tee-verification.test.js +241 -0
- package/dist/proxy/tee-verification.test.js.map +1 -0
- package/package.json +7 -6
|
@@ -5,8 +5,9 @@ import { tmpdir } from 'node:os';
|
|
|
5
5
|
import { join } from 'node:path';
|
|
6
6
|
import { Readable } from 'node:stream';
|
|
7
7
|
import test from 'node:test';
|
|
8
|
-
import { ANTSEED_BUYER_FAULT_ERROR_CODE, ANTSEED_FAULT_ATTRIBUTION_HEADER, CONNECTION_CAPABILITY_COOPERATIVE_CLOSE_V1, CONNECTION_CAPABILITY_RELAYS_SWEEPS_V1, adaptPeerFaultErrorResponse, buyerFault,
|
|
8
|
+
import { ANTSEED_BUYER_FAULT_ERROR_CODE, ANTSEED_FAULT_ATTRIBUTION_HEADER, CONNECTION_CAPABILITY_COOPERATIVE_CLOSE_V1, CONNECTION_CAPABILITY_RELAYS_SWEEPS_V1, adaptPeerFaultErrorResponse, buyerFault, computeTrustScore, } from '@antseed/node';
|
|
9
9
|
import { DEFAULT_BUYER_PEER_REFRESH_INTERVAL_MS } from '../config/defaults.js';
|
|
10
|
+
import { TeeVerification } from './tee-verification.js';
|
|
10
11
|
import { BuyerProxy, isModelNotFoundResponse, makeVerifierReach, mergeJsonStateFile, parsePeerPinnedService, parsePersistedPeers, rewritePeerPinnedServiceInBody, sanitizePeerBuyerFaultMarker, selectCandidatePeersForRouting, substituteRoutedModelAlias, sweepStaleStateTmpFiles, } from './buyer-proxy.js';
|
|
11
12
|
import { extractRequestedService, overrideRoutedModelInBody, SYSTEM_ROUTED_MODEL_HEADER, } from './request-utils.js';
|
|
12
13
|
function makePeer(seed, providers) {
|
|
@@ -17,6 +18,40 @@ function makePeer(seed, providers) {
|
|
|
17
18
|
providers,
|
|
18
19
|
};
|
|
19
20
|
}
|
|
21
|
+
test('existing required CLI verification rejects a failed pin without payment/inference and auto falls back to a verified seller', async () => {
|
|
22
|
+
const rejected = makePeer('a', ['openai']);
|
|
23
|
+
const accepted = makePeer('b', ['openai']);
|
|
24
|
+
for (const peer of [rejected, accepted]) {
|
|
25
|
+
peer.capabilities = ['verifier.antseed-verifier'];
|
|
26
|
+
peer.providerServiceApiProtocols = { openai: { services: { 'gpt-4o': ['openai-chat-completions'] } } };
|
|
27
|
+
}
|
|
28
|
+
rejected.reputationScore = 99;
|
|
29
|
+
accepted.reputationScore = 90;
|
|
30
|
+
const peers = [rejected, accepted];
|
|
31
|
+
const proxy = makeBuyerProxyWithPeers(peers, peers, permissiveRouter());
|
|
32
|
+
const policy = { require: true, prefer: ['antseed-verifier'] };
|
|
33
|
+
const verification = new TeeVerification(policy);
|
|
34
|
+
proxy._verifier = policy;
|
|
35
|
+
proxy._teeVerification = verification;
|
|
36
|
+
proxy._cachedPeers = peers;
|
|
37
|
+
await verification.verify(rejected, policy, async () => ({ ok: false, verified: false, reason: 'Seller binding failed' }));
|
|
38
|
+
await verification.verify(accepted, policy, async () => ({ ok: true, verified: true, sellerNodeVerified: true }));
|
|
39
|
+
const dispatches = [];
|
|
40
|
+
proxy._node.sendRequest = async (peer, request) => {
|
|
41
|
+
dispatches.push(peer.peerId);
|
|
42
|
+
return { requestId: request.requestId, statusCode: 200, headers: { 'content-type': 'application/json' }, body: Buffer.from('{}') };
|
|
43
|
+
};
|
|
44
|
+
const pinned = await invokeProxy(proxy, makeProxyRequest({ headers: { 'x-antseed-pin-peer': rejected.peerId } }));
|
|
45
|
+
assert.equal(pinned.statusCode, 502);
|
|
46
|
+
assert.match(pinned.body, /failed required verification/);
|
|
47
|
+
assert.deepEqual(dispatches, []);
|
|
48
|
+
const automatic = await invokeProxy(proxy, makeProxyRequest({}));
|
|
49
|
+
assert.equal(automatic.statusCode, 200);
|
|
50
|
+
assert.deepEqual(dispatches, [accepted.peerId]);
|
|
51
|
+
const explicit = await invokeProxy(proxy, makeProxyRequest({ headers: { 'x-antseed-pin-peer': accepted.peerId } }));
|
|
52
|
+
assert.equal(explicit.statusCode, 200);
|
|
53
|
+
assert.deepEqual(dispatches, [accepted.peerId, accepted.peerId]);
|
|
54
|
+
});
|
|
20
55
|
function makeProxyRequest(options) {
|
|
21
56
|
const body = JSON.stringify(options.body ?? { model: 'gpt-4o', messages: [] });
|
|
22
57
|
const req = Readable.from([Buffer.from(body)]);
|
|
@@ -425,12 +460,12 @@ test('selectCandidatePeersForRouting can still include peers without service pro
|
|
|
425
460
|
});
|
|
426
461
|
test('model-only request routes to the highest-ranked canonical service match', async () => {
|
|
427
462
|
const lower = makePeer('a', ['anthropic']);
|
|
428
|
-
lower.
|
|
463
|
+
lower.onChainReputationScore = 40;
|
|
429
464
|
lower.providerServiceApiProtocols = {
|
|
430
465
|
anthropic: { services: { 'Claude Opus 5': ['anthropic-messages'] } },
|
|
431
466
|
};
|
|
432
467
|
const higher = makePeer('b', ['anthropic']);
|
|
433
|
-
higher.
|
|
468
|
+
higher.onChainReputationScore = 90;
|
|
434
469
|
higher.providerServiceApiProtocols = {
|
|
435
470
|
anthropic: { services: { 'opus-5': ['anthropic-messages'] } },
|
|
436
471
|
};
|
|
@@ -647,7 +682,7 @@ test('model-only request applies a cached-input pricing reputation penalty', asy
|
|
|
647
682
|
});
|
|
648
683
|
test('model-only cached-input pricing penalty does not bury a substantially stronger peer', async () => {
|
|
649
684
|
const priced = makePeer('a', ['openai']);
|
|
650
|
-
priced.
|
|
685
|
+
priced.onChainReputationScore = 20;
|
|
651
686
|
priced.providerPricing = {
|
|
652
687
|
openai: {
|
|
653
688
|
defaults: { inputUsdPerMillion: 2, outputUsdPerMillion: 4 },
|
|
@@ -660,7 +695,7 @@ test('model-only cached-input pricing penalty does not bury a substantially stro
|
|
|
660
695
|
openai: { services: { 'cache-model': ['openai-chat-completions'] } },
|
|
661
696
|
};
|
|
662
697
|
const unpriced = makePeer('b', ['openai']);
|
|
663
|
-
unpriced.
|
|
698
|
+
unpriced.onChainReputationScore = 100;
|
|
664
699
|
unpriced.providerServiceApiProtocols = {
|
|
665
700
|
openai: { services: { 'cache-model': ['openai-chat-completions'] } },
|
|
666
701
|
};
|
|
@@ -681,12 +716,12 @@ test('model-only cached-input pricing penalty does not bury a substantially stro
|
|
|
681
716
|
});
|
|
682
717
|
test('model-only request keeps reputation ordering when cached-input pricing is absent for all peers', async () => {
|
|
683
718
|
const lower = makePeer('a', ['openai']);
|
|
684
|
-
lower.
|
|
719
|
+
lower.onChainReputationScore = 20;
|
|
685
720
|
lower.providerServiceApiProtocols = {
|
|
686
721
|
openai: { services: { 'no-cache-model': ['openai-chat-completions'] } },
|
|
687
722
|
};
|
|
688
723
|
const higher = makePeer('b', ['openai']);
|
|
689
|
-
higher.
|
|
724
|
+
higher.onChainReputationScore = 100;
|
|
690
725
|
higher.providerServiceApiProtocols = {
|
|
691
726
|
openai: { services: { 'no-cache-model': ['openai-chat-completions'] } },
|
|
692
727
|
};
|
|
@@ -789,12 +824,12 @@ test('model-only request uses the cheapest duplicate service advertised by one p
|
|
|
789
824
|
});
|
|
790
825
|
test('antseed alias with a model-only default route uses automatic peer selection', async () => {
|
|
791
826
|
const lower = makePeer('a', ['openai']);
|
|
792
|
-
lower.
|
|
827
|
+
lower.onChainReputationScore = 40;
|
|
793
828
|
lower.providerServiceApiProtocols = {
|
|
794
829
|
openai: { services: { 'gpt-56-sol': ['openai-chat-completions'] } },
|
|
795
830
|
};
|
|
796
831
|
const higher = makePeer('b', ['openai']);
|
|
797
|
-
higher.
|
|
832
|
+
higher.onChainReputationScore = 90;
|
|
798
833
|
higher.providerServiceApiProtocols = {
|
|
799
834
|
openai: { services: { 'openai-gpt-56-sol': ['openai-chat-completions'] } },
|
|
800
835
|
};
|
|
@@ -849,7 +884,7 @@ test('model-only routing skips higher-reputation peers rejected by buyer policy'
|
|
|
849
884
|
});
|
|
850
885
|
test('/models order and model-only dispatch use the same Price + Trust ranking', async () => {
|
|
851
886
|
const cobaltRelay = makePeer('a', ['openai']);
|
|
852
|
-
cobaltRelay.
|
|
887
|
+
cobaltRelay.onChainReputationScore = 99;
|
|
853
888
|
cobaltRelay.providerPricing = {
|
|
854
889
|
openai: { defaults: { inputUsdPerMillion: 1.88, outputUsdPerMillion: 9.38 } },
|
|
855
890
|
};
|
|
@@ -857,7 +892,7 @@ test('/models order and model-only dispatch use the same Price + Trust ranking',
|
|
|
857
892
|
openai: { services: { 'kimi-k3': ['openai-chat-completions'] } },
|
|
858
893
|
};
|
|
859
894
|
const emberRoute = makePeer('b', ['openai']);
|
|
860
|
-
emberRoute.
|
|
895
|
+
emberRoute.onChainReputationScore = 96;
|
|
861
896
|
emberRoute.providerPricing = {
|
|
862
897
|
openai: { defaults: { inputUsdPerMillion: 0.9, outputUsdPerMillion: 2.7 } },
|
|
863
898
|
};
|
|
@@ -886,7 +921,7 @@ test('/models order and model-only dispatch use the same Price + Trust ranking',
|
|
|
886
921
|
});
|
|
887
922
|
test('Price + Trust routing falls back after the preferred cheaper peer fails', async () => {
|
|
888
923
|
const cobaltRelay = makePeer('a', ['openai']);
|
|
889
|
-
cobaltRelay.
|
|
924
|
+
cobaltRelay.onChainReputationScore = 99;
|
|
890
925
|
cobaltRelay.providerPricing = {
|
|
891
926
|
openai: { defaults: { inputUsdPerMillion: 1.88, outputUsdPerMillion: 9.38 } },
|
|
892
927
|
};
|
|
@@ -894,7 +929,7 @@ test('Price + Trust routing falls back after the preferred cheaper peer fails',
|
|
|
894
929
|
openai: { services: { 'kimi-k3': ['openai-chat-completions'] } },
|
|
895
930
|
};
|
|
896
931
|
const emberRoute = makePeer('b', ['openai']);
|
|
897
|
-
emberRoute.
|
|
932
|
+
emberRoute.onChainReputationScore = 96;
|
|
898
933
|
emberRoute.providerPricing = {
|
|
899
934
|
openai: { defaults: { inputUsdPerMillion: 0.9, outputUsdPerMillion: 2.7 } },
|
|
900
935
|
};
|
|
@@ -1321,7 +1356,7 @@ test('a pinned seller failure explains the peer boundary and preserves the selle
|
|
|
1321
1356
|
assert.equal(parsed.error.peer_status, 503);
|
|
1322
1357
|
assert.equal(parsed.error.message, [
|
|
1323
1358
|
'Oops, pinned peer could not complete the request.',
|
|
1324
|
-
'
|
|
1359
|
+
'Antseed is a peer-to-peer network. Try another peer or use Auto routing.',
|
|
1325
1360
|
'Original Response: {"message":"No billing tier matches this request.","status":503}',
|
|
1326
1361
|
].join('\n'));
|
|
1327
1362
|
});
|
|
@@ -1955,6 +1990,19 @@ test('parsePersistedPeers drops entries with non-array providers', () => {
|
|
|
1955
1990
|
}, NOW);
|
|
1956
1991
|
assert.equal(result.length, 0);
|
|
1957
1992
|
});
|
|
1993
|
+
test('parsePersistedPeers removes decorative icons from legacy display names', () => {
|
|
1994
|
+
const result = parsePersistedPeers({
|
|
1995
|
+
discoveredPeers: [
|
|
1996
|
+
{
|
|
1997
|
+
peerId: validPeerId,
|
|
1998
|
+
displayName: '▲ Example Seller ✅ 🌐',
|
|
1999
|
+
providers: ['openai'],
|
|
2000
|
+
lastSeen: NOW,
|
|
2001
|
+
},
|
|
2002
|
+
],
|
|
2003
|
+
}, NOW);
|
|
2004
|
+
assert.equal(result[0]?.displayName, 'Example Seller');
|
|
2005
|
+
});
|
|
1958
2006
|
test('parsePersistedPeers drops entries with stale or missing freshness anchors', () => {
|
|
1959
2007
|
const result = parsePersistedPeers({
|
|
1960
2008
|
discoveredPeers: [
|
|
@@ -2072,26 +2120,90 @@ test('parsePersistedPeers preserves provider metadata so routing filters still w
|
|
|
2072
2120
|
assert.equal(result.candidatePeers[0]?.peerId, validPeerId);
|
|
2073
2121
|
assert.equal(result.routePlanByPeerId.get(validPeerId)?.provider, 'claude-oauth');
|
|
2074
2122
|
});
|
|
2075
|
-
test('parsePersistedPeers re-derives
|
|
2123
|
+
test('parsePersistedPeers re-derives the trust score from persisted on-chain signals', () => {
|
|
2076
2124
|
const persisted = {
|
|
2077
2125
|
discoveredPeers: [
|
|
2078
2126
|
{
|
|
2079
2127
|
peerId: validPeerId,
|
|
2080
2128
|
providers: ['claude-oauth'],
|
|
2081
2129
|
lastSeen: NOW - 5_000,
|
|
2082
|
-
|
|
2130
|
+
// A stale cached score and breakdown must never win over the signals.
|
|
2131
|
+
onChainReputationScore: 3,
|
|
2132
|
+
trust: { score: 3, history: null, usage: null, power: null, identity: null, washFlagged: null },
|
|
2083
2133
|
onChainChannelCount: 20,
|
|
2084
2134
|
onChainGhostCount: 0,
|
|
2085
2135
|
onChainTotalVolumeUsdcMicros: 100_000_000,
|
|
2086
2136
|
onChainLastSettledAtSec: Math.floor((NOW - 60_000) / 1000),
|
|
2087
2137
|
onChainStakedAtSec: Math.floor((NOW - 40 * 86_400_000) / 1000),
|
|
2138
|
+
onChainUsageEpoch: 22,
|
|
2139
|
+
onChainUsageShareBps: 1_000,
|
|
2140
|
+
onChainUsageLastEpochUsdcMicros: 500_000_000,
|
|
2141
|
+
onChainPoolStakeAnts: 1_250.5,
|
|
2142
|
+
onChainPoolPowerShareBps: 1_000,
|
|
2143
|
+
onChainWashFlagged: false,
|
|
2144
|
+
onChainWashShareBps: 0,
|
|
2088
2145
|
},
|
|
2089
2146
|
],
|
|
2090
2147
|
};
|
|
2091
2148
|
const [peer] = parsePersistedPeers(persisted, NOW);
|
|
2092
2149
|
assert.ok(peer);
|
|
2093
|
-
assert.equal(peer.
|
|
2094
|
-
assert.
|
|
2150
|
+
assert.equal(peer.onChainUsageEpoch, 22);
|
|
2151
|
+
assert.equal(peer.onChainUsageShareBps, 1_000);
|
|
2152
|
+
assert.equal(peer.onChainUsageLastEpochUsdcMicros, 500_000_000);
|
|
2153
|
+
assert.equal(peer.onChainPoolStakeAnts, 1_250.5);
|
|
2154
|
+
assert.equal(peer.onChainPoolPowerShareBps, 1_000);
|
|
2155
|
+
assert.equal(peer.onChainWashFlagged, false);
|
|
2156
|
+
assert.equal(peer.onChainWashShareBps, 0);
|
|
2157
|
+
assert.equal(peer.onChainStakedAtSec, Math.floor((NOW - 40 * 86_400_000) / 1000));
|
|
2158
|
+
assert.ok(!('onChainStakeUsdcMicros' in peer));
|
|
2159
|
+
assert.ok(!('onChainTrustScore' in peer));
|
|
2160
|
+
assert.deepEqual(peer.trust, computeTrustScore(peer, NOW));
|
|
2161
|
+
assert.equal(peer.onChainReputationScore, peer.trust?.score);
|
|
2162
|
+
// Twenty settled sessions and 100 USDC of volume contribute about 49 history
|
|
2163
|
+
// points; a 10% usage share adds about 10 and a 10% power share about 3 more.
|
|
2164
|
+
assert.equal(Math.round(peer.onChainReputationScore ?? 0), 63);
|
|
2165
|
+
assert.equal(peer.trust?.history?.channelCount, 20);
|
|
2166
|
+
assert.equal(peer.trust?.history?.totalVolumeUsdcMicros, 100_000_000);
|
|
2167
|
+
assert.equal(peer.trust?.usage?.epoch, 21);
|
|
2168
|
+
assert.equal(peer.trust?.usage?.shareBps, 1_000);
|
|
2169
|
+
assert.equal(peer.trust?.power?.shareBps, 1_000);
|
|
2170
|
+
assert.equal(peer.trust?.washFlagged, false);
|
|
2171
|
+
});
|
|
2172
|
+
test('parsePersistedPeers scores a proven wash trader at zero regardless of usage', () => {
|
|
2173
|
+
const [peer] = parsePersistedPeers({
|
|
2174
|
+
discoveredPeers: [{
|
|
2175
|
+
peerId: validPeerId,
|
|
2176
|
+
providers: ['openai'],
|
|
2177
|
+
lastSeen: NOW - 5_000,
|
|
2178
|
+
onChainReputationScore: 95,
|
|
2179
|
+
onChainUsageEpoch: 22,
|
|
2180
|
+
onChainUsageShareBps: 10_000,
|
|
2181
|
+
onChainPoolPowerShareBps: 10_000,
|
|
2182
|
+
onChainWashFlagged: true,
|
|
2183
|
+
onChainWashShareBps: 9_800,
|
|
2184
|
+
}],
|
|
2185
|
+
}, NOW);
|
|
2186
|
+
assert.ok(peer);
|
|
2187
|
+
assert.equal(peer.onChainWashFlagged, true);
|
|
2188
|
+
assert.equal(peer.onChainWashShareBps, 9_800);
|
|
2189
|
+
assert.equal(peer.onChainReputationScore, 0);
|
|
2190
|
+
assert.equal(peer.trust?.washFlagged, true);
|
|
2191
|
+
assert.equal(peer.trust?.score, 0);
|
|
2192
|
+
});
|
|
2193
|
+
test('parsePersistedPeers keeps the persisted score when nothing scoreable was stored', () => {
|
|
2194
|
+
const [peer] = parsePersistedPeers({
|
|
2195
|
+
discoveredPeers: [{
|
|
2196
|
+
peerId: validPeerId,
|
|
2197
|
+
providers: ['openai'],
|
|
2198
|
+
lastSeen: NOW - 5_000,
|
|
2199
|
+
onChainReputationScore: 42,
|
|
2200
|
+
onChainChannelCount: 3,
|
|
2201
|
+
}],
|
|
2202
|
+
}, NOW);
|
|
2203
|
+
assert.ok(peer);
|
|
2204
|
+
assert.equal(computeTrustScore(peer, NOW), null);
|
|
2205
|
+
assert.equal(peer.onChainReputationScore, 42);
|
|
2206
|
+
assert.equal(peer.trust, undefined);
|
|
2095
2207
|
});
|
|
2096
2208
|
test('parsePersistedPeers restores sellerContract into peer.metadata', () => {
|
|
2097
2209
|
// Regression: dropping sellerContract through the persistence layer caused
|
|
@@ -2115,6 +2227,8 @@ test('parsePersistedPeers restores sellerContract into peer.metadata', () => {
|
|
|
2115
2227
|
});
|
|
2116
2228
|
test('parsePersistedPeers restores external verification claims and results', () => {
|
|
2117
2229
|
const verificationResults = {
|
|
2230
|
+
identityHistory: { version: 1, identities: [{ kind: 'domain', claim: 'example.com', identityId: 'domain:example.com',
|
|
2231
|
+
status: 'available', fetchedAtMs: NOW - 500, createdAtMs: NOW - 10 * 365.25 * 86_400_000 }] },
|
|
2118
2232
|
verified: true,
|
|
2119
2233
|
checkedAtMs: NOW - 500,
|
|
2120
2234
|
domains: [
|
|
@@ -2147,6 +2261,50 @@ test('parsePersistedPeers restores external verification claims and results', ()
|
|
|
2147
2261
|
domains: [{ domain: 'example.com', methods: ['dns-txt'] }],
|
|
2148
2262
|
});
|
|
2149
2263
|
assert.deepEqual(peer.verificationResults, verificationResults);
|
|
2264
|
+
// A ten-year-old verified domain earns the full 12 identity points, worth 20 * 12 / 70 trust.
|
|
2265
|
+
assert.equal(peer.onChainReputationScore, 20 * 12 / 70);
|
|
2266
|
+
assert.deepEqual(peer.trust?.identity, { score: 20 * 12 / 70, kind: 'domain', claim: 'example.com' });
|
|
2267
|
+
assert.equal(peer.trust?.history, null);
|
|
2268
|
+
assert.equal(peer.trust?.usage, null);
|
|
2269
|
+
assert.equal(peer.trust?.washFlagged, null);
|
|
2270
|
+
// Ownership proofs and identity evidence expire after seven days: once
|
|
2271
|
+
// stale the peer is unscored again rather than keeping the cached score.
|
|
2272
|
+
const [stale] = parsePersistedPeers({ discoveredPeers: [{ peerId: validPeerId, providers: ['openai'], lastSeen: NOW + 8 * 86_400_000 - 1_000,
|
|
2273
|
+
verifications: { domains: [{ domain: 'example.com', methods: ['dns-txt'] }] }, verificationResults }] }, NOW + 8 * 86_400_000);
|
|
2274
|
+
assert.ok(stale);
|
|
2275
|
+
assert.equal(computeTrustScore(stale, NOW + 8 * 86_400_000), null);
|
|
2276
|
+
assert.equal(stale.onChainReputationScore, undefined);
|
|
2277
|
+
assert.equal(stale.trust, undefined);
|
|
2278
|
+
});
|
|
2279
|
+
test('parsePersistedPeers restores GitHub identity history but never trusts persisted score breakdowns', () => {
|
|
2280
|
+
const stored = { discoveredPeers: [{ peerId: validPeerId, providers: ['openai'], lastSeen: NOW - 1_000,
|
|
2281
|
+
verifications: { github: [{ username: 'portfolio', repository: 'proof' }] },
|
|
2282
|
+
onChainReputationScore: 100,
|
|
2283
|
+
trust: { score: 100, history: { score: 60, channelCount: 100, totalVolumeUsdcMicros: 100_000_000 }, usage: { score: 15, shareBps: 10_000, epoch: 1 }, power: { score: 5, shareBps: 10_000, epoch: 1 }, identity: { score: 20, kind: 'github', claim: 'portfolio' }, washFlagged: false },
|
|
2284
|
+
verificationResults: { verified: true, checkedAtMs: NOW - 500, domains: [],
|
|
2285
|
+
github: [{ username: 'portfolio', repository: 'proof', peerId: validPeerId, verified: true, checkedAtMs: NOW - 500 }],
|
|
2286
|
+
identityHistory: { version: 1, identities: [{ kind: 'github', claim: 'portfolio', identityId: 'github:42', status: 'available',
|
|
2287
|
+
fetchedAtMs: NOW - 500, createdAtMs: NOW - 2 * 365.25 * 86_400_000,
|
|
2288
|
+
projects: [
|
|
2289
|
+
{ id: 1, name: 'alpha', createdAtMs: NOW - 365.25 * 86_400_000, stars: 31, archived: false },
|
|
2290
|
+
// The ownership-proof repository never counts, however popular.
|
|
2291
|
+
{ id: 2, name: 'proof', createdAtMs: NOW - 365.25 * 86_400_000, stars: 5_000, archived: false },
|
|
2292
|
+
] }] } },
|
|
2293
|
+
}] };
|
|
2294
|
+
const [peer] = parsePersistedPeers(JSON.parse(JSON.stringify(stored)), NOW);
|
|
2295
|
+
assert.ok(peer);
|
|
2296
|
+
assert.equal(peer.verificationResults?.identityHistory?.version, 1);
|
|
2297
|
+
assert.equal(peer.verificationResults?.identityHistory?.identities[0]?.projects?.length, 2);
|
|
2298
|
+
const trust = computeTrustScore(peer, NOW);
|
|
2299
|
+
assert.ok(trust);
|
|
2300
|
+
assert.deepEqual(peer.trust, trust);
|
|
2301
|
+
assert.equal(peer.onChainReputationScore, trust.score);
|
|
2302
|
+
assert.equal(trust.identity?.kind, 'github');
|
|
2303
|
+
assert.equal(trust.identity?.claim, 'portfolio');
|
|
2304
|
+
assert.equal(trust.usage, null);
|
|
2305
|
+
assert.ok(trust.score > 0 && trust.score < 20, `expected a modest identity-only score, got ${trust.score}`);
|
|
2306
|
+
const [stale] = parsePersistedPeers(JSON.parse(JSON.stringify(stored)), NOW + 8 * 86_400_000);
|
|
2307
|
+
assert.equal(stale, undefined);
|
|
2150
2308
|
});
|
|
2151
2309
|
test('parsePersistedPeers leaves metadata undefined when sellerContract is absent', () => {
|
|
2152
2310
|
const [peer] = parsePersistedPeers({
|
|
@@ -2888,7 +3046,7 @@ test('adaptPeerFaultErrorResponse upgrades a generic wrapper for a pinned route'
|
|
|
2888
3046
|
assert.equal(parsed.error.peer_status, 429);
|
|
2889
3047
|
assert.equal(parsed.error.message, [
|
|
2890
3048
|
'Oops, pinned peer could not complete the request.',
|
|
2891
|
-
'
|
|
3049
|
+
'Antseed is a peer-to-peer network. Try another peer or use Auto routing.',
|
|
2892
3050
|
'Original Response: {"message":"Insufficient balance or no resource package. Please recharge.","status":429}',
|
|
2893
3051
|
].join('\n'));
|
|
2894
3052
|
});
|