signet-protocol 0.1.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 (156) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +112 -0
  3. package/dist/anomaly.d.ts +42 -0
  4. package/dist/anomaly.d.ts.map +1 -0
  5. package/dist/anomaly.js +209 -0
  6. package/dist/anomaly.js.map +1 -0
  7. package/dist/badge.d.ts +56 -0
  8. package/dist/badge.d.ts.map +1 -0
  9. package/dist/badge.js +171 -0
  10. package/dist/badge.js.map +1 -0
  11. package/dist/bonds.d.ts +39 -0
  12. package/dist/bonds.d.ts.map +1 -0
  13. package/dist/bonds.js +149 -0
  14. package/dist/bonds.js.map +1 -0
  15. package/dist/challenges.d.ts +18 -0
  16. package/dist/challenges.d.ts.map +1 -0
  17. package/dist/challenges.js +145 -0
  18. package/dist/challenges.js.map +1 -0
  19. package/dist/cold-call.d.ts +74 -0
  20. package/dist/cold-call.d.ts.map +1 -0
  21. package/dist/cold-call.js +176 -0
  22. package/dist/cold-call.js.map +1 -0
  23. package/dist/compliance.d.ts +82 -0
  24. package/dist/compliance.d.ts.map +1 -0
  25. package/dist/compliance.js +478 -0
  26. package/dist/compliance.js.map +1 -0
  27. package/dist/connections.d.ts +63 -0
  28. package/dist/connections.d.ts.map +1 -0
  29. package/dist/connections.js +170 -0
  30. package/dist/connections.js.map +1 -0
  31. package/dist/constants.d.ts +86 -0
  32. package/dist/constants.d.ts.map +1 -0
  33. package/dist/constants.js +124 -0
  34. package/dist/constants.js.map +1 -0
  35. package/dist/credentials.d.ts +190 -0
  36. package/dist/credentials.d.ts.map +1 -0
  37. package/dist/credentials.js +686 -0
  38. package/dist/credentials.js.map +1 -0
  39. package/dist/crypto.d.ts +27 -0
  40. package/dist/crypto.d.ts.map +1 -0
  41. package/dist/crypto.js +75 -0
  42. package/dist/crypto.js.map +1 -0
  43. package/dist/errors.d.ts +17 -0
  44. package/dist/errors.d.ts.map +1 -0
  45. package/dist/errors.js +29 -0
  46. package/dist/errors.js.map +1 -0
  47. package/dist/i18n.d.ts +98 -0
  48. package/dist/i18n.d.ts.map +1 -0
  49. package/dist/i18n.js +1118 -0
  50. package/dist/i18n.js.map +1 -0
  51. package/dist/identity-bridge.d.ts +52 -0
  52. package/dist/identity-bridge.d.ts.map +1 -0
  53. package/dist/identity-bridge.js +228 -0
  54. package/dist/identity-bridge.js.map +1 -0
  55. package/dist/identity-tree.d.ts +47 -0
  56. package/dist/identity-tree.d.ts.map +1 -0
  57. package/dist/identity-tree.js +69 -0
  58. package/dist/identity-tree.js.map +1 -0
  59. package/dist/index.d.ts +55 -0
  60. package/dist/index.d.ts.map +1 -0
  61. package/dist/index.js +86 -0
  62. package/dist/index.js.map +1 -0
  63. package/dist/key-derivation.d.ts +43 -0
  64. package/dist/key-derivation.d.ts.map +1 -0
  65. package/dist/key-derivation.js +212 -0
  66. package/dist/key-derivation.js.map +1 -0
  67. package/dist/lsag.d.ts +23 -0
  68. package/dist/lsag.d.ts.map +1 -0
  69. package/dist/lsag.js +35 -0
  70. package/dist/lsag.js.map +1 -0
  71. package/dist/merkle.d.ts +19 -0
  72. package/dist/merkle.d.ts.map +1 -0
  73. package/dist/merkle.js +155 -0
  74. package/dist/merkle.js.map +1 -0
  75. package/dist/policies.d.ts +22 -0
  76. package/dist/policies.d.ts.map +1 -0
  77. package/dist/policies.js +123 -0
  78. package/dist/policies.js.map +1 -0
  79. package/dist/range-proof.d.ts +6 -0
  80. package/dist/range-proof.d.ts.map +1 -0
  81. package/dist/range-proof.js +45 -0
  82. package/dist/range-proof.js.map +1 -0
  83. package/dist/relay.d.ts +106 -0
  84. package/dist/relay.d.ts.map +1 -0
  85. package/dist/relay.js +336 -0
  86. package/dist/relay.js.map +1 -0
  87. package/dist/ring-signature.d.ts +35 -0
  88. package/dist/ring-signature.d.ts.map +1 -0
  89. package/dist/ring-signature.js +56 -0
  90. package/dist/ring-signature.js.map +1 -0
  91. package/dist/shamir.d.ts +55 -0
  92. package/dist/shamir.d.ts.map +1 -0
  93. package/dist/shamir.js +253 -0
  94. package/dist/shamir.js.map +1 -0
  95. package/dist/signet-words.d.ts +42 -0
  96. package/dist/signet-words.d.ts.map +1 -0
  97. package/dist/signet-words.js +82 -0
  98. package/dist/signet-words.js.map +1 -0
  99. package/dist/store.d.ts +65 -0
  100. package/dist/store.d.ts.map +1 -0
  101. package/dist/store.js +290 -0
  102. package/dist/store.js.map +1 -0
  103. package/dist/trust-score.d.ts +9 -0
  104. package/dist/trust-score.d.ts.map +1 -0
  105. package/dist/trust-score.js +186 -0
  106. package/dist/trust-score.js.map +1 -0
  107. package/dist/types.d.ts +358 -0
  108. package/dist/types.d.ts.map +1 -0
  109. package/dist/types.js +15 -0
  110. package/dist/types.js.map +1 -0
  111. package/dist/utils.d.ts +11 -0
  112. package/dist/utils.d.ts.map +1 -0
  113. package/dist/utils.js +21 -0
  114. package/dist/utils.js.map +1 -0
  115. package/dist/validation.d.ts +33 -0
  116. package/dist/validation.d.ts.map +1 -0
  117. package/dist/validation.js +312 -0
  118. package/dist/validation.js.map +1 -0
  119. package/dist/verifiers.d.ts +18 -0
  120. package/dist/verifiers.d.ts.map +1 -0
  121. package/dist/verifiers.js +118 -0
  122. package/dist/verifiers.js.map +1 -0
  123. package/dist/vouches.d.ts +14 -0
  124. package/dist/vouches.d.ts.map +1 -0
  125. package/dist/vouches.js +103 -0
  126. package/dist/vouches.js.map +1 -0
  127. package/package.json +76 -0
  128. package/src/anomaly.ts +307 -0
  129. package/src/badge.ts +208 -0
  130. package/src/bonds.ts +203 -0
  131. package/src/challenges.ts +187 -0
  132. package/src/cold-call.ts +238 -0
  133. package/src/compliance.ts +612 -0
  134. package/src/connections.ts +216 -0
  135. package/src/constants.ts +146 -0
  136. package/src/credentials.ts +908 -0
  137. package/src/crypto.ts +85 -0
  138. package/src/errors.ts +31 -0
  139. package/src/i18n.ts +1347 -0
  140. package/src/identity-bridge.ts +262 -0
  141. package/src/identity-tree.ts +90 -0
  142. package/src/index.ts +452 -0
  143. package/src/lsag.ts +53 -0
  144. package/src/merkle.ts +176 -0
  145. package/src/policies.ts +154 -0
  146. package/src/range-proof.ts +66 -0
  147. package/src/relay.ts +433 -0
  148. package/src/ring-signature.ts +76 -0
  149. package/src/signet-words.ts +122 -0
  150. package/src/store.ts +336 -0
  151. package/src/trust-score.ts +208 -0
  152. package/src/types.ts +482 -0
  153. package/src/utils.ts +20 -0
  154. package/src/validation.ts +391 -0
  155. package/src/verifiers.ts +156 -0
  156. package/src/vouches.ts +141 -0
package/dist/store.js ADDED
@@ -0,0 +1,290 @@
1
+ // Signet Event Store
2
+ // In-memory event storage with query support and JSON serialization
3
+ import { ATTESTATION_KIND, ATTESTATION_TYPES, APP_DATA_KIND } from './constants.js';
4
+ import { getTagValue, validateFieldSizeBounds } from './validation.js';
5
+ import { SignetValidationError } from './errors.js';
6
+ import { parseCredential } from './credentials.js';
7
+ /**
8
+ * In-memory Signet event store.
9
+ * Stores events indexed by kind, author, and subject for fast queries.
10
+ * Handles replaceable event semantics (kind 30xxx: newer replaces older for same d-tag).
11
+ */
12
+ export class SignetStore {
13
+ events = new Map();
14
+ // Indexes for fast queries
15
+ byKind = new Map();
16
+ byAuthor = new Map();
17
+ bySubject = new Map();
18
+ /** Add an event to the store. Returns true if added (not a duplicate/older). */
19
+ add(event) {
20
+ // Check if this is a replaceable event (kind 30000-39999)
21
+ if (event.kind >= 30000 && event.kind < 40000) {
22
+ const dTag = getTagValue(event, 'd');
23
+ // Find existing event with same replace key
24
+ for (const [id, existing] of this.events) {
25
+ if (existing.kind === event.kind && existing.pubkey === event.pubkey) {
26
+ const existingD = getTagValue(existing, 'd');
27
+ if (existingD === dTag) {
28
+ if (existing.created_at >= event.created_at) {
29
+ return false; // existing is newer or same
30
+ }
31
+ // Remove older event
32
+ this.remove(id);
33
+ break;
34
+ }
35
+ }
36
+ }
37
+ }
38
+ // Deduplicate by event ID
39
+ if (this.events.has(event.id))
40
+ return false;
41
+ this.events.set(event.id, event);
42
+ this.indexEvent(event);
43
+ return true;
44
+ }
45
+ /** Remove an event by ID */
46
+ remove(id) {
47
+ const event = this.events.get(id);
48
+ if (!event)
49
+ return false;
50
+ this.events.delete(id);
51
+ this.deindexEvent(event);
52
+ return true;
53
+ }
54
+ /** Get an event by ID */
55
+ get(id) {
56
+ return this.events.get(id);
57
+ }
58
+ /** Check if an event exists */
59
+ has(id) {
60
+ return this.events.has(id);
61
+ }
62
+ /** Total number of events */
63
+ get size() {
64
+ return this.events.size;
65
+ }
66
+ /** Query events with filters */
67
+ query(q = {}) {
68
+ let candidateIds = null;
69
+ // Narrow by kind
70
+ if (q.kinds?.length) {
71
+ const kindIds = new Set();
72
+ for (const kind of q.kinds) {
73
+ const ids = this.byKind.get(kind);
74
+ if (ids)
75
+ ids.forEach((id) => kindIds.add(id));
76
+ }
77
+ candidateIds = kindIds;
78
+ }
79
+ // Narrow by author
80
+ if (q.authors?.length) {
81
+ const authorIds = new Set();
82
+ for (const author of q.authors) {
83
+ const ids = this.byAuthor.get(author);
84
+ if (ids)
85
+ ids.forEach((id) => authorIds.add(id));
86
+ }
87
+ candidateIds = candidateIds
88
+ ? intersect(candidateIds, authorIds)
89
+ : authorIds;
90
+ }
91
+ // Narrow by subject
92
+ if (q.subjects?.length) {
93
+ const subjectIds = new Set();
94
+ for (const subject of q.subjects) {
95
+ const ids = this.bySubject.get(subject);
96
+ if (ids)
97
+ ids.forEach((id) => subjectIds.add(id));
98
+ }
99
+ candidateIds = candidateIds
100
+ ? intersect(candidateIds, subjectIds)
101
+ : subjectIds;
102
+ }
103
+ // Collect events
104
+ const ids = candidateIds ?? new Set(this.events.keys());
105
+ let results = [];
106
+ for (const id of ids) {
107
+ const event = this.events.get(id);
108
+ if (!event)
109
+ continue;
110
+ if (q.since && event.created_at < q.since)
111
+ continue;
112
+ if (q.until && event.created_at > q.until)
113
+ continue;
114
+ results.push(event);
115
+ }
116
+ // Sort by created_at descending (newest first)
117
+ results.sort((a, b) => b.created_at - a.created_at);
118
+ if (q.limit && results.length > q.limit) {
119
+ results = results.slice(0, q.limit);
120
+ }
121
+ return results;
122
+ }
123
+ // --- Convenience query methods ---
124
+ /** Get all credentials for a subject */
125
+ getCredentials(subjectPubkey) {
126
+ return this.query({ kinds: [ATTESTATION_KIND], subjects: [`credential:${subjectPubkey}`, subjectPubkey] })
127
+ .filter((e) => getTagValue(e, 'type') === ATTESTATION_TYPES.CREDENTIAL);
128
+ }
129
+ /** Get the highest-tier credential for a subject */
130
+ getHighestCredential(subjectPubkey) {
131
+ const creds = this.getCredentials(subjectPubkey);
132
+ let highest = null;
133
+ for (const cred of creds) {
134
+ const parsed = parseCredential(cred);
135
+ if (parsed && (!highest || parsed.tier > highest.tier)) {
136
+ highest = parsed;
137
+ }
138
+ }
139
+ return highest;
140
+ }
141
+ /** Get all vouches for a subject */
142
+ getVouches(subjectPubkey) {
143
+ return this.query({ kinds: [ATTESTATION_KIND], subjects: [`vouch:${subjectPubkey}`, subjectPubkey] })
144
+ .filter((e) => getTagValue(e, 'type') === ATTESTATION_TYPES.VOUCH);
145
+ }
146
+ /** Get the community policy for a community */
147
+ getPolicy(communityId) {
148
+ const policies = this.query({ kinds: [APP_DATA_KIND] });
149
+ return policies.find((p) => {
150
+ const dTag = getTagValue(p, 'd') || '';
151
+ return dTag === `signet:policy:${communityId}`;
152
+ });
153
+ }
154
+ /** Get a verifier credential */
155
+ getVerifierCredential(verifierPubkey) {
156
+ const creds = this.query({ kinds: [ATTESTATION_KIND], authors: [verifierPubkey] })
157
+ .filter((e) => getTagValue(e, 'type') === ATTESTATION_TYPES.VERIFIER);
158
+ return creds[0];
159
+ }
160
+ /** Get all challenges against a verifier */
161
+ getChallenges(verifierPubkey) {
162
+ return this.query({ kinds: [ATTESTATION_KIND], subjects: [`challenge:${verifierPubkey}`, verifierPubkey] })
163
+ .filter((e) => getTagValue(e, 'type') === ATTESTATION_TYPES.CHALLENGE);
164
+ }
165
+ /** Get all revocations for a verifier */
166
+ getRevocations(verifierPubkey) {
167
+ return this.query({ kinds: [ATTESTATION_KIND], subjects: [`revocation:${verifierPubkey}`, verifierPubkey] })
168
+ .filter((e) => getTagValue(e, 'type') === ATTESTATION_TYPES.REVOCATION);
169
+ }
170
+ /** Check if a verifier is revoked */
171
+ isRevoked(verifierPubkey) {
172
+ return this.getRevocations(verifierPubkey).length > 0;
173
+ }
174
+ /** Get all credentials issued by a verifier */
175
+ getCredentialsByIssuer(issuerPubkey) {
176
+ return this.query({ kinds: [ATTESTATION_KIND], authors: [issuerPubkey] })
177
+ .filter((e) => getTagValue(e, 'type') === ATTESTATION_TYPES.CREDENTIAL);
178
+ }
179
+ // --- Serialization ---
180
+ /** Export all events as JSON */
181
+ export() {
182
+ return JSON.stringify(Array.from(this.events.values()));
183
+ }
184
+ /** Import events from JSON.
185
+ *
186
+ * WARNING: This method validates structural shape and field-size bounds but does
187
+ * NOT verify event signatures. Callers are responsible for verifying cryptographic
188
+ * validity before importing untrusted data. The RelayClient verifies signatures
189
+ * by default — this gap only affects direct callers of store.import(). */
190
+ import(json) {
191
+ let parsed;
192
+ try {
193
+ parsed = JSON.parse(json);
194
+ }
195
+ catch {
196
+ throw new SignetValidationError('Import data is not valid JSON');
197
+ }
198
+ if (!Array.isArray(parsed)) {
199
+ throw new SignetValidationError('Import data must be a JSON array');
200
+ }
201
+ const MAX_IMPORT_SIZE = 10_000;
202
+ if (parsed.length > MAX_IMPORT_SIZE) {
203
+ throw new SignetValidationError(`Import array too large: ${parsed.length} items (max ${MAX_IMPORT_SIZE})`);
204
+ }
205
+ const events = [];
206
+ for (const item of parsed) {
207
+ if (typeof item !== 'object' || item === null ||
208
+ typeof item.id !== 'string' ||
209
+ typeof item.pubkey !== 'string' ||
210
+ typeof item.kind !== 'number' ||
211
+ typeof item.created_at !== 'number' ||
212
+ !Array.isArray(item.tags) ||
213
+ typeof item.content !== 'string' ||
214
+ typeof item.sig !== 'string' ||
215
+ !item.tags.every((t) => Array.isArray(t) && t.every((v) => typeof v === 'string'))) {
216
+ continue; // skip malformed entries
217
+ }
218
+ // Validate hex format of id, pubkey, sig
219
+ if (!/^[0-9a-f]{64}$/.test(item.id) || !/^[0-9a-f]{64}$/.test(item.pubkey) || !/^[0-9a-f]{128}$/.test(item.sig)) {
220
+ continue;
221
+ }
222
+ // Validate field-size bounds on imported events
223
+ const boundsErrors = [];
224
+ validateFieldSizeBounds(item, boundsErrors);
225
+ if (boundsErrors.length > 0)
226
+ continue;
227
+ events.push(item);
228
+ }
229
+ let added = 0;
230
+ for (const event of events) {
231
+ if (this.add(event))
232
+ added++;
233
+ }
234
+ return added;
235
+ }
236
+ /** Clear all events */
237
+ clear() {
238
+ this.events.clear();
239
+ this.byKind.clear();
240
+ this.byAuthor.clear();
241
+ this.bySubject.clear();
242
+ }
243
+ // --- Index management ---
244
+ indexEvent(event) {
245
+ // Index by kind
246
+ if (!this.byKind.has(event.kind))
247
+ this.byKind.set(event.kind, new Set());
248
+ this.byKind.get(event.kind).add(event.id);
249
+ // Index by author
250
+ if (!this.byAuthor.has(event.pubkey))
251
+ this.byAuthor.set(event.pubkey, new Set());
252
+ this.byAuthor.get(event.pubkey).add(event.id);
253
+ // Index by subject (d tag)
254
+ const subject = getTagValue(event, 'd');
255
+ if (subject) {
256
+ if (!this.bySubject.has(subject))
257
+ this.bySubject.set(subject, new Set());
258
+ this.bySubject.get(subject).add(event.id);
259
+ }
260
+ // Also index by p tag (many events reference subjects via p tag)
261
+ const pTags = event.tags.filter((t) => t[0] === 'p').map((t) => t[1]);
262
+ for (const p of pTags) {
263
+ if (!this.bySubject.has(p))
264
+ this.bySubject.set(p, new Set());
265
+ this.bySubject.get(p).add(event.id);
266
+ }
267
+ }
268
+ deindexEvent(event) {
269
+ this.byKind.get(event.kind)?.delete(event.id);
270
+ this.byAuthor.get(event.pubkey)?.delete(event.id);
271
+ const subject = getTagValue(event, 'd');
272
+ if (subject)
273
+ this.bySubject.get(subject)?.delete(event.id);
274
+ const pTags = event.tags.filter((t) => t[0] === 'p').map((t) => t[1]);
275
+ for (const p of pTags) {
276
+ this.bySubject.get(p)?.delete(event.id);
277
+ }
278
+ }
279
+ }
280
+ /** Set intersection */
281
+ function intersect(a, b) {
282
+ const result = new Set();
283
+ const [smaller, larger] = a.size <= b.size ? [a, b] : [b, a];
284
+ for (const item of smaller) {
285
+ if (larger.has(item))
286
+ result.add(item);
287
+ }
288
+ return result;
289
+ }
290
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { NostrEvent, TrustSignal, TrustScoreBreakdown } from './types.js';
2
+ /** Compute Signet Score for a subject from their credentials, vouches, and bridges */
3
+ export declare function computeTrustScore(subjectPubkey: string, credentials: NostrEvent[], vouches: NostrEvent[], accountCreatedAt?: number, bridges?: NostrEvent[]): TrustScoreBreakdown;
4
+ /** Get a human-readable Signet Score display */
5
+ export declare function formatTrustDisplay(breakdown: TrustScoreBreakdown): string;
6
+ /** Verify the signal ordering invariant:
7
+ * professional verification > identity bridge > in-person vouch > online vouch > account age */
8
+ export declare function verifySignalOrdering(signals: TrustSignal[]): boolean;
9
+ //# sourceMappingURL=trust-score.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trust-score.d.ts","sourceRoot":"","sources":["../src/trust-score.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,mBAAmB,EAEpB,MAAM,YAAY,CAAC;AAEpB,sFAAsF;AACtF,wBAAgB,iBAAiB,CAC/B,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,UAAU,EAAE,EACzB,OAAO,EAAE,UAAU,EAAE,EACrB,gBAAgB,CAAC,EAAE,MAAM,EACzB,OAAO,CAAC,EAAE,UAAU,EAAE,GACrB,mBAAmB,CAyIrB;AAED,gDAAgD;AAChD,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,mBAAmB,GAAG,MAAM,CAwBzE;AAED;iGACiG;AACjG,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,OAAO,CAoBpE"}
@@ -0,0 +1,186 @@
1
+ // Signet Score Computation
2
+ // Continuous 0-200 Signet Score from weighted signals
3
+ import { TRUST_WEIGHTS, MAX_TRUST_SCORE, ATTESTATION_KIND, ATTESTATION_TYPES } from './constants.js';
4
+ import { getTagValue } from './validation.js';
5
+ /** Compute Signet Score for a subject from their credentials, vouches, and bridges */
6
+ export function computeTrustScore(subjectPubkey, credentials, vouches, accountCreatedAt, bridges) {
7
+ const signals = [];
8
+ let rawScore = 0;
9
+ let highestTier = 1;
10
+ let professionalVerifications = 0;
11
+ let inPersonVouches = 0;
12
+ let onlineVouches = 0;
13
+ // Process credentials
14
+ const now = Math.floor(Date.now() / 1000);
15
+ for (const cred of credentials) {
16
+ if (cred.kind !== ATTESTATION_KIND)
17
+ continue;
18
+ if (getTagValue(cred, 'type') !== ATTESTATION_TYPES.CREDENTIAL)
19
+ continue;
20
+ const dTag = getTagValue(cred, 'd') || '';
21
+ const pTag = getTagValue(cred, 'p');
22
+ let subject;
23
+ if (dTag.startsWith('assertion:') && pTag) {
24
+ subject = pTag;
25
+ }
26
+ else {
27
+ subject = dTag.startsWith('credential:') ? dTag.slice('credential:'.length) : dTag;
28
+ }
29
+ if (subject !== subjectPubkey)
30
+ continue;
31
+ // Skip expired credentials — NaN must be treated as expired (not perpetually valid)
32
+ const expires = getTagValue(cred, 'expiration');
33
+ if (expires) {
34
+ const exp = parseInt(expires, 10);
35
+ if (isNaN(exp) || exp < now)
36
+ continue;
37
+ }
38
+ const rawTier = parseInt(getTagValue(cred, 'tier') || '1', 10);
39
+ const tier = (!isNaN(rawTier) && rawTier >= 1 && rawTier <= 4 ? rawTier : 1);
40
+ if (tier > highestTier)
41
+ highestTier = tier;
42
+ const verificationType = getTagValue(cred, 'verification-type');
43
+ if (verificationType === 'professional') {
44
+ professionalVerifications++;
45
+ const weight = TRUST_WEIGHTS.PROFESSIONAL_VERIFICATION;
46
+ rawScore += weight;
47
+ signals.push({
48
+ type: 'professional-verification',
49
+ weight,
50
+ source: cred.pubkey,
51
+ });
52
+ }
53
+ }
54
+ // Process vouches
55
+ const vouchersSeen = new Set();
56
+ for (const vouch of vouches) {
57
+ if (vouch.kind !== ATTESTATION_KIND)
58
+ continue;
59
+ if (getTagValue(vouch, 'type') !== ATTESTATION_TYPES.VOUCH)
60
+ continue;
61
+ const dTag = getTagValue(vouch, 'd') || '';
62
+ const subject = dTag.startsWith('vouch:') ? dTag.slice('vouch:'.length) : dTag;
63
+ if (subject !== subjectPubkey)
64
+ continue;
65
+ // One vouch per voucher
66
+ if (vouchersSeen.has(vouch.pubkey))
67
+ continue;
68
+ vouchersSeen.add(vouch.pubkey);
69
+ const method = getTagValue(vouch, 'method');
70
+ const rawVoucherScore = parseInt(getTagValue(vouch, 'voucher-score') || '50', 10);
71
+ const voucherScore = isNaN(rawVoucherScore) ? 50 : Math.max(0, Math.min(rawVoucherScore, MAX_TRUST_SCORE));
72
+ const scoreMultiplier = voucherScore / MAX_TRUST_SCORE;
73
+ if (method === 'in-person') {
74
+ inPersonVouches++;
75
+ const weight = TRUST_WEIGHTS.IN_PERSON_VOUCH * scoreMultiplier;
76
+ rawScore += weight;
77
+ signals.push({
78
+ type: 'in-person-vouch',
79
+ weight,
80
+ source: vouch.pubkey,
81
+ score: voucherScore,
82
+ });
83
+ }
84
+ else {
85
+ onlineVouches++;
86
+ const weight = TRUST_WEIGHTS.ONLINE_VOUCH * scoreMultiplier;
87
+ rawScore += weight;
88
+ signals.push({
89
+ type: 'online-vouch',
90
+ weight,
91
+ source: vouch.pubkey,
92
+ score: voucherScore,
93
+ });
94
+ }
95
+ }
96
+ // Process identity bridges
97
+ if (bridges) {
98
+ for (const bridge of bridges) {
99
+ if (bridge.kind !== ATTESTATION_KIND)
100
+ continue;
101
+ if (getTagValue(bridge, 'type') !== ATTESTATION_TYPES.IDENTITY_BRIDGE)
102
+ continue;
103
+ if (bridge.pubkey !== subjectPubkey)
104
+ continue;
105
+ const rawRingMinTier = parseInt(getTagValue(bridge, 'ring-min-tier') || '1', 10);
106
+ const ringMinTier = (!isNaN(rawRingMinTier) && rawRingMinTier >= 1 && rawRingMinTier <= 4 ? rawRingMinTier : 1);
107
+ const weight = TRUST_WEIGHTS.IDENTITY_BRIDGE * (ringMinTier / 4);
108
+ rawScore += weight;
109
+ signals.push({
110
+ type: 'identity-bridge',
111
+ weight,
112
+ source: bridge.pubkey,
113
+ });
114
+ // Only count one bridge per account
115
+ break;
116
+ }
117
+ }
118
+ // Account age
119
+ let accountAgeDays = 0;
120
+ if (accountCreatedAt) {
121
+ accountAgeDays = Math.max(0, Math.floor((now - accountCreatedAt) / (24 * 60 * 60)));
122
+ const years = accountAgeDays / 365;
123
+ const ageWeight = Math.min(years * TRUST_WEIGHTS.ACCOUNT_AGE_PER_YEAR, TRUST_WEIGHTS.ACCOUNT_AGE_MAX);
124
+ rawScore += ageWeight;
125
+ signals.push({
126
+ type: 'account-age',
127
+ weight: ageWeight,
128
+ });
129
+ }
130
+ // Cap at MAX_TRUST_SCORE
131
+ const score = Math.min(Math.round(rawScore), MAX_TRUST_SCORE);
132
+ return {
133
+ score,
134
+ tier: highestTier,
135
+ professionalVerifications,
136
+ inPersonVouches,
137
+ onlineVouches,
138
+ accountAgeDays,
139
+ signals,
140
+ };
141
+ }
142
+ /** Get a human-readable Signet Score display */
143
+ export function formatTrustDisplay(breakdown) {
144
+ const checkmarks = breakdown.tier >= 2 ? '✓'.repeat(breakdown.tier - 1) : '';
145
+ const tierLabel = ['', 'Self-declared', 'Web-of-trust', 'Verified', 'Verified (Child Safety)'][breakdown.tier];
146
+ const lines = [
147
+ `${checkmarks} Tier ${breakdown.tier} (${tierLabel})`,
148
+ `Signet Score: ${breakdown.score}`,
149
+ ];
150
+ if (breakdown.professionalVerifications > 0) {
151
+ lines.push(` Prof verified: ${breakdown.professionalVerifications}`);
152
+ }
153
+ if (breakdown.inPersonVouches > 0) {
154
+ lines.push(` In-person vouches: ${breakdown.inPersonVouches}`);
155
+ }
156
+ if (breakdown.onlineVouches > 0) {
157
+ lines.push(` Online vouches: ${breakdown.onlineVouches}`);
158
+ }
159
+ if (breakdown.accountAgeDays > 0) {
160
+ const years = (breakdown.accountAgeDays / 365).toFixed(1);
161
+ lines.push(` Account age: ${years} years`);
162
+ }
163
+ return lines.join('\n');
164
+ }
165
+ /** Verify the signal ordering invariant:
166
+ * professional verification > identity bridge > in-person vouch > online vouch > account age */
167
+ export function verifySignalOrdering(signals) {
168
+ const maxWeight = (type) => {
169
+ const weights = signals.filter((s) => s.type === type).map((s) => s.weight);
170
+ return weights.length > 0 ? Math.max(...weights) : 0;
171
+ };
172
+ const profMax = maxWeight('professional-verification');
173
+ const bridgeMax = maxWeight('identity-bridge');
174
+ const inPersonMax = maxWeight('in-person-vouch');
175
+ // Professional verification must exceed identity bridge
176
+ if (profMax > 0 && bridgeMax > 0 && profMax <= bridgeMax)
177
+ return false;
178
+ // Identity bridge must exceed in-person vouch
179
+ if (bridgeMax > 0 && inPersonMax > 0 && bridgeMax <= inPersonMax)
180
+ return false;
181
+ // Professional verification must exceed in-person vouch
182
+ if (profMax > 0 && inPersonMax > 0 && profMax <= inPersonMax)
183
+ return false;
184
+ return true;
185
+ }
186
+ //# sourceMappingURL=trust-score.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trust-score.js","sourceRoot":"","sources":["../src/trust-score.ts"],"names":[],"mappings":"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"}