@sempdev/semp 0.5.1 → 0.5.5

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 (227) hide show
  1. package/dist/brief/address.d.ts +1 -1
  2. package/dist/brief/address.js +1 -1
  3. package/dist/brief/brief.d.ts +1 -1
  4. package/dist/brief/brief.js +1 -1
  5. package/dist/canonical/marshal.d.ts +2 -2
  6. package/dist/canonical/marshal.js +2 -2
  7. package/dist/closure/driver.d.ts +2 -2
  8. package/dist/closure/driver.js +1 -1
  9. package/dist/crypto/aead.d.ts +2 -2
  10. package/dist/crypto/aead.js +2 -2
  11. package/dist/crypto/kdf.d.ts +1 -1
  12. package/dist/crypto/kdf.js +1 -1
  13. package/dist/crypto/mac.d.ts +1 -1
  14. package/dist/crypto/mac.js +1 -1
  15. package/dist/delivery/ack.d.ts +5 -5
  16. package/dist/delivery/ack.js +6 -6
  17. package/dist/delivery/blocklist.d.ts +1 -1
  18. package/dist/delivery/blocklist.js +2 -2
  19. package/dist/delivery/device_sync.d.ts +26 -0
  20. package/dist/delivery/device_sync.d.ts.map +1 -0
  21. package/dist/delivery/device_sync.js +18 -0
  22. package/dist/delivery/device_sync.js.map +1 -0
  23. package/dist/delivery/disposition.d.ts +1 -1
  24. package/dist/delivery/fetch.d.ts +1 -1
  25. package/dist/delivery/fetch.js +1 -1
  26. package/dist/delivery/inbox.d.ts +2 -2
  27. package/dist/delivery/inbox.js +2 -2
  28. package/dist/delivery/index.d.ts +4 -0
  29. package/dist/delivery/index.d.ts.map +1 -1
  30. package/dist/delivery/index.js +4 -0
  31. package/dist/delivery/index.js.map +1 -1
  32. package/dist/delivery/persistent_silent.d.ts +70 -0
  33. package/dist/delivery/persistent_silent.d.ts.map +1 -0
  34. package/dist/delivery/persistent_silent.js +117 -0
  35. package/dist/delivery/persistent_silent.js.map +1 -0
  36. package/dist/delivery/pipeline.d.ts +4 -4
  37. package/dist/delivery/pipeline.js +2 -2
  38. package/dist/delivery/policy_state.d.ts +2 -2
  39. package/dist/delivery/policy_state.js +4 -4
  40. package/dist/delivery/receipt.d.ts +3 -3
  41. package/dist/delivery/receipt.js +3 -3
  42. package/dist/delivery/receipt_store.d.ts +1 -1
  43. package/dist/delivery/receipt_store.js +1 -1
  44. package/dist/delivery/retry.d.ts +2 -2
  45. package/dist/delivery/retry.js +2 -2
  46. package/dist/delivery/scheduler.d.ts +1 -1
  47. package/dist/delivery/scheduler.js +1 -1
  48. package/dist/delivery/stage_partition.d.ts +1 -1
  49. package/dist/delivery/stage_partition.js +1 -1
  50. package/dist/delivery/staged_runner.d.ts +1 -1
  51. package/dist/delivery/staged_runner.js +2 -2
  52. package/dist/delivery/status_message.d.ts +75 -0
  53. package/dist/delivery/status_message.d.ts.map +1 -0
  54. package/dist/delivery/status_message.js +109 -0
  55. package/dist/delivery/status_message.js.map +1 -0
  56. package/dist/delivery/upgrade_signal.d.ts +48 -0
  57. package/dist/delivery/upgrade_signal.d.ts.map +1 -0
  58. package/dist/delivery/upgrade_signal.js +48 -0
  59. package/dist/delivery/upgrade_signal.js.map +1 -0
  60. package/dist/discovery/configuration.d.ts +20 -1
  61. package/dist/discovery/configuration.d.ts.map +1 -1
  62. package/dist/discovery/configuration.js.map +1 -1
  63. package/dist/discovery/dns.d.ts +27 -1
  64. package/dist/discovery/dns.d.ts.map +1 -1
  65. package/dist/discovery/dns.js +37 -0
  66. package/dist/discovery/dns.js.map +1 -1
  67. package/dist/discovery/index.d.ts +2 -2
  68. package/dist/discovery/index.d.ts.map +1 -1
  69. package/dist/discovery/index.js +1 -1
  70. package/dist/discovery/index.js.map +1 -1
  71. package/dist/discovery/partition.d.ts +1 -1
  72. package/dist/discovery/partition.js +1 -1
  73. package/dist/discovery/resolver.d.ts +5 -5
  74. package/dist/discovery/resolver.js +5 -5
  75. package/dist/discovery/txt.d.ts +1 -1
  76. package/dist/discovery/txt.js +1 -1
  77. package/dist/enclosure/forwarding.d.ts +1 -1
  78. package/dist/enclosure/forwarding.js +1 -1
  79. package/dist/envelope/buckets.d.ts +2 -2
  80. package/dist/envelope/buckets.js +2 -2
  81. package/dist/envelope/compose.d.ts +17 -2
  82. package/dist/envelope/compose.d.ts.map +1 -1
  83. package/dist/envelope/compose.js +29 -11
  84. package/dist/envelope/compose.js.map +1 -1
  85. package/dist/envelope/encode.d.ts +2 -2
  86. package/dist/envelope/encode.js +3 -3
  87. package/dist/envelope/index.d.ts +1 -1
  88. package/dist/envelope/index.d.ts.map +1 -1
  89. package/dist/envelope/index.js +1 -1
  90. package/dist/envelope/index.js.map +1 -1
  91. package/dist/envelope/open_any.d.ts.map +1 -1
  92. package/dist/envelope/open_any.js +5 -5
  93. package/dist/envelope/open_any.js.map +1 -1
  94. package/dist/envelope/open_verified.d.ts +1 -1
  95. package/dist/envelope/open_verified.js +1 -1
  96. package/dist/envelope/padding.d.ts +2 -2
  97. package/dist/envelope/padding.js +3 -3
  98. package/dist/envelope/verify.d.ts +1 -1
  99. package/dist/envelope/verify.js +1 -1
  100. package/dist/extensions/index.d.ts +1 -0
  101. package/dist/extensions/index.d.ts.map +1 -1
  102. package/dist/extensions/index.js +1 -0
  103. package/dist/extensions/index.js.map +1 -1
  104. package/dist/extensions/limits.d.ts +2 -2
  105. package/dist/extensions/limits.js +2 -2
  106. package/dist/extensions/validation_failure.d.ts +48 -0
  107. package/dist/extensions/validation_failure.d.ts.map +1 -0
  108. package/dist/extensions/validation_failure.js +25 -0
  109. package/dist/extensions/validation_failure.js.map +1 -0
  110. package/dist/handshake/abort.d.ts +1 -1
  111. package/dist/handshake/abort.js +1 -1
  112. package/dist/handshake/client_state.d.ts +5 -5
  113. package/dist/handshake/client_state.js +5 -5
  114. package/dist/handshake/confirm.d.ts +2 -2
  115. package/dist/handshake/confirm.js +2 -2
  116. package/dist/handshake/driver.d.ts +2 -2
  117. package/dist/handshake/driver.js +1 -1
  118. package/dist/handshake/federation.d.ts +6 -6
  119. package/dist/handshake/federation.js +5 -5
  120. package/dist/handshake/first_contact.d.ts +1 -1
  121. package/dist/handshake/first_contact.js +1 -1
  122. package/dist/handshake/identity.d.ts +1 -1
  123. package/dist/handshake/identity.js +1 -1
  124. package/dist/handshake/pow.js +1 -1
  125. package/dist/handshake/server_state.d.ts +3 -3
  126. package/dist/handshake/server_state.js +3 -3
  127. package/dist/index.d.ts +1 -1
  128. package/dist/index.js +1 -1
  129. package/dist/keys/compromise.d.ts +2 -2
  130. package/dist/keys/compromise.js +1 -1
  131. package/dist/keys/device_certificate.d.ts +3 -3
  132. package/dist/keys/device_certificate.js +4 -4
  133. package/dist/keys/key_revocation.d.ts +2 -2
  134. package/dist/keys/key_revocation.js +1 -1
  135. package/dist/keys/request.d.ts +17 -3
  136. package/dist/keys/request.d.ts.map +1 -1
  137. package/dist/keys/request.js.map +1 -1
  138. package/dist/keys/sign.d.ts +1 -1
  139. package/dist/keys/sign.js +1 -1
  140. package/dist/keys/signed.d.ts +3 -3
  141. package/dist/keys/signed.js +3 -3
  142. package/dist/keys/store.js +1 -1
  143. package/dist/largeattachment/crypto.d.ts +1 -1
  144. package/dist/largeattachment/crypto.js +2 -2
  145. package/dist/largeattachment/upload.d.ts +3 -3
  146. package/dist/largeattachment/upload.js +1 -1
  147. package/dist/migration/index.d.ts +1 -1
  148. package/dist/migration/index.d.ts.map +1 -1
  149. package/dist/migration/index.js +1 -1
  150. package/dist/migration/index.js.map +1 -1
  151. package/dist/migration/lockout.d.ts +2 -2
  152. package/dist/migration/lockout.js +2 -2
  153. package/dist/migration/migration.d.ts +6 -4
  154. package/dist/migration/migration.d.ts.map +1 -1
  155. package/dist/migration/migration.js +3 -3
  156. package/dist/migration/migration.js.map +1 -1
  157. package/dist/migration/notice.d.ts +31 -19
  158. package/dist/migration/notice.d.ts.map +1 -1
  159. package/dist/migration/notice.js +37 -71
  160. package/dist/migration/notice.js.map +1 -1
  161. package/dist/migration/orchestrate.d.ts +10 -10
  162. package/dist/migration/orchestrate.d.ts.map +1 -1
  163. package/dist/migration/orchestrate.js +23 -23
  164. package/dist/migration/orchestrate.js.map +1 -1
  165. package/dist/migration/sign.js +9 -9
  166. package/dist/migration/sign.js.map +1 -1
  167. package/dist/migration/types.d.ts +35 -29
  168. package/dist/migration/types.d.ts.map +1 -1
  169. package/dist/migration/types.js +5 -7
  170. package/dist/migration/types.js.map +1 -1
  171. package/dist/recovery/bundle_store.js +1 -1
  172. package/dist/recovery/sign.js +3 -3
  173. package/dist/recovery/types.d.ts +3 -3
  174. package/dist/reputation/abuse_report.d.ts +3 -3
  175. package/dist/reputation/abuse_report.js +2 -2
  176. package/dist/reputation/eligibility.d.ts +44 -0
  177. package/dist/reputation/eligibility.d.ts.map +1 -0
  178. package/dist/reputation/eligibility.js +58 -0
  179. package/dist/reputation/eligibility.js.map +1 -0
  180. package/dist/reputation/evidence.d.ts +47 -0
  181. package/dist/reputation/evidence.d.ts.map +1 -0
  182. package/dist/reputation/evidence.js +117 -0
  183. package/dist/reputation/evidence.js.map +1 -0
  184. package/dist/reputation/gossip_fetch.d.ts +2 -2
  185. package/dist/reputation/gossip_fetch.js +1 -1
  186. package/dist/reputation/index.d.ts +4 -1
  187. package/dist/reputation/index.d.ts.map +1 -1
  188. package/dist/reputation/index.js +4 -1
  189. package/dist/reputation/index.js.map +1 -1
  190. package/dist/reputation/pow.d.ts +1 -1
  191. package/dist/reputation/pow.js +1 -1
  192. package/dist/reputation/references.d.ts +51 -0
  193. package/dist/reputation/references.d.ts.map +1 -0
  194. package/dist/reputation/references.js +95 -0
  195. package/dist/reputation/references.js.map +1 -0
  196. package/dist/reputation/sign.d.ts +1 -1
  197. package/dist/reputation/sign.js +2 -2
  198. package/dist/reputation/types.d.ts +46 -2
  199. package/dist/reputation/types.d.ts.map +1 -1
  200. package/dist/reputation/types.js +14 -0
  201. package/dist/reputation/types.js.map +1 -1
  202. package/dist/reputation/whois.d.ts +1 -1
  203. package/dist/reputation/whois.js +1 -1
  204. package/dist/seal/wrap.d.ts +2 -2
  205. package/dist/seal/wrap.js +4 -4
  206. package/dist/session/dispatcher.d.ts +3 -3
  207. package/dist/session/dispatcher.js +1 -1
  208. package/dist/session/rekey_seal.d.ts +3 -3
  209. package/dist/session/rekey_seal.js +3 -3
  210. package/dist/session/session.d.ts +3 -3
  211. package/dist/session/session.js +3 -3
  212. package/dist/transparency/log.d.ts +1 -1
  213. package/dist/transparency/log.js +2 -2
  214. package/dist/transparency/types.d.ts +2 -2
  215. package/dist/transparency/types.js +1 -1
  216. package/dist/transport/h2.d.ts +33 -12
  217. package/dist/transport/h2.d.ts.map +1 -1
  218. package/dist/transport/h2.js +40 -13
  219. package/dist/transport/h2.js.map +1 -1
  220. package/dist/transport/index.d.ts +1 -1
  221. package/dist/transport/index.d.ts.map +1 -1
  222. package/dist/transport/index.js +1 -1
  223. package/dist/transport/index.js.map +1 -1
  224. package/dist/transport/memory.js +1 -1
  225. package/dist/transport/ws.d.ts +1 -1
  226. package/dist/transport/ws.js +1 -1
  227. package/package.json +1 -1
@@ -9,7 +9,7 @@ import { sign as ed25519Sign, verify as ed25519Verify } from "../keys/index.js";
9
9
  import { signSignedDoc, verifySignedDoc } from "../keys/index.js";
10
10
  import { RecoveryManifestPrefix, RecoveryShareSignaturePrefix, SignatureAlgorithmEd25519, SuccessorRecordPrefix, } from "./types.js";
11
11
  // ---------------------------------------------------------------------------
12
- // SuccessorRecord three-signature record per §7.3
12
+ // SuccessorRecord - three-signature record per §7.3
13
13
  /**
14
14
  * Pre-populate the algorithm + key_id fields on all three signature
15
15
  * blocks so the canonical bytes are stable across the three signing
@@ -148,7 +148,7 @@ function canonicalSuccessorBytesElidingThreeSignatures(r) {
148
148
  return canonicalMarshal(clone);
149
149
  }
150
150
  // ---------------------------------------------------------------------------
151
- // RecoverySetManifest single user-identity signature per §5.2
151
+ // RecoverySetManifest - single user-identity signature per §5.2
152
152
  /**
153
153
  * Sign `m.signature` with the user's identity private key per §5.2.
154
154
  * Pre-populates algorithm + key_id so the canonical bytes cover them.
@@ -240,7 +240,7 @@ export function validateManifest(m, opts = {}) {
240
240
  }
241
241
  }
242
242
  // ---------------------------------------------------------------------------
243
- // RecoveryShareRecord single device-identity signature per §5.3
243
+ // RecoveryShareRecord - single device-identity signature per §5.3
244
244
  /** Sign `s.device_signature` with the device's identity private key per §5.3. */
245
245
  export function signShareRecord(s, devicePriv, deviceKeyId) {
246
246
  if (deviceKeyId === "") {
@@ -35,7 +35,7 @@ export interface RecoverySignatureBlock {
35
35
  value: string;
36
36
  }
37
37
  /**
38
- * SEMP_SUCCESSOR per §7.2 links a prior identity key to a new one
38
+ * SEMP_SUCCESSOR per §7.2 - links a prior identity key to a new one
39
39
  * after recovery or rotation. Carries three independent signatures
40
40
  * so third-party domains can verify continuity without needing the
41
41
  * prior identity private key.
@@ -68,7 +68,7 @@ export interface RecoveryContributor {
68
68
  device_identity_pubkey: DeviceIdentityPubkey;
69
69
  }
70
70
  /**
71
- * SEMP_RECOVERY_SET_MANIFEST per §5.2 binds each Shamir share
71
+ * SEMP_RECOVERY_SET_MANIFEST per §5.2 - binds each Shamir share
72
72
  * index to a specific device's identity public key.
73
73
  */
74
74
  export interface RecoverySetManifest {
@@ -83,7 +83,7 @@ export interface RecoverySetManifest {
83
83
  signature: RecoverySignatureBlock;
84
84
  }
85
85
  /**
86
- * SEMP_RECOVERY_SHARE per §5.3 one device's holding of a Shamir
86
+ * SEMP_RECOVERY_SHARE per §5.3 - one device's holding of a Shamir
87
87
  * share, authenticated by the device's identity-key signature.
88
88
  */
89
89
  export interface RecoveryShareRecord {
@@ -3,7 +3,7 @@
3
3
  * §3.7.
4
4
  *
5
5
  * Abuse reports flow user → home-server over an authenticated
6
- * session the handshake identifies the reporting user so the
6
+ * session - the handshake identifies the reporting user so the
7
7
  * report itself does NOT carry its own signature. The report's
8
8
  * evidence MAY include decrypted envelope fragments, in which case
9
9
  * an embedded {@link DisclosureAuthorization} signed by the
@@ -35,7 +35,7 @@ export interface AbuseReportInput {
35
35
  export declare function newAbuseReport(input: AbuseReportInput): AbuseReport;
36
36
  /**
37
37
  * Lookup hook used by {@link validateEvidence} to resolve a user's
38
- * identity public key. Returning `null` means "unknown user"
38
+ * identity public key. Returning `null` means "unknown user" -
39
39
  * callers MUST treat that as a §3.7 verification failure.
40
40
  */
41
41
  export type UserKeyLookup = (user: string) => Promise<Uint8Array | null>;
@@ -44,7 +44,7 @@ export type UserKeyLookup = (user: string) => Promise<Uint8Array | null>;
44
44
  * content requires a valid {@link DisclosureAuthorization} signed
45
45
  * by the affected user.
46
46
  *
47
- * Metadata-only evidence is always acceptable postmark + seal
47
+ * Metadata-only evidence is always acceptable - postmark + seal
48
48
  * data is verifiable from the sender's published domain key without
49
49
  * disclosing user content.
50
50
  *
@@ -3,7 +3,7 @@
3
3
  * §3.7.
4
4
  *
5
5
  * Abuse reports flow user → home-server over an authenticated
6
- * session the handshake identifies the reporting user so the
6
+ * session - the handshake identifies the reporting user so the
7
7
  * report itself does NOT carry its own signature. The report's
8
8
  * evidence MAY include decrypted envelope fragments, in which case
9
9
  * an embedded {@link DisclosureAuthorization} signed by the
@@ -56,7 +56,7 @@ export function newAbuseReport(input) {
56
56
  * content requires a valid {@link DisclosureAuthorization} signed
57
57
  * by the affected user.
58
58
  *
59
- * Metadata-only evidence is always acceptable postmark + seal
59
+ * Metadata-only evidence is always acceptable - postmark + seal
60
60
  * data is verifiable from the sender's published domain key without
61
61
  * disclosing user content.
62
62
  *
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Publication eligibility helpers per REPUTATION.md §4.6.2 /
3
+ * draft-gokce-semp-delivery §11.7.
4
+ *
5
+ * A server SHOULD NOT publish an observation about a subject
6
+ * domain unless it has directly observed enough interaction with
7
+ * the subject to back the metrics. The two publisher-side gates:
8
+ *
9
+ * - At least {@link MinPublishVolumeEnvelopes} envelopes (or
10
+ * equivalent handshake attempts) observed during the window.
11
+ * - At least one metrics field non-zero. Records with uniformly
12
+ * zero metrics MUST NOT be published.
13
+ *
14
+ * A consumer that receives an observation violating either rule
15
+ * SHOULD treat the publishing observer as a candidate for
16
+ * `observation_record_abuse` reporting per §3.4.
17
+ *
18
+ * @module
19
+ */
20
+ import type { Metrics } from "./types.js";
21
+ /**
22
+ * §4.6.2 RECOMMENDED minimum number of envelopes (or handshake
23
+ * attempts) the observer should have observed during the window
24
+ * before publishing an observation about a subject domain.
25
+ */
26
+ export declare const MinPublishVolumeEnvelopes = 16;
27
+ /**
28
+ * Reports whether the metrics carry at least
29
+ * {@link MinPublishVolumeEnvelopes} envelopes or handshake
30
+ * attempts (post-bucketing).
31
+ */
32
+ export declare function meetsPublishVolume(m: Metrics): boolean;
33
+ /**
34
+ * Reports whether every metric field is zero and
35
+ * `abuse_categories` is empty.
36
+ */
37
+ export declare function allMetricsZero(m: Metrics): boolean;
38
+ /**
39
+ * Convenience predicate: true when the metrics satisfy both the
40
+ * volume threshold and the non-all-zero rule. Publishers SHOULD
41
+ * gate every outgoing observation on this check.
42
+ */
43
+ export declare function eligibleForPublication(m: Metrics): boolean;
44
+ //# sourceMappingURL=eligibility.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eligibility.d.ts","sourceRoot":"","sources":["../../src/reputation/eligibility.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,KAAK,CAAC;AAE5C;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAMtD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAUlD;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAE1D"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Publication eligibility helpers per REPUTATION.md §4.6.2 /
3
+ * draft-gokce-semp-delivery §11.7.
4
+ *
5
+ * A server SHOULD NOT publish an observation about a subject
6
+ * domain unless it has directly observed enough interaction with
7
+ * the subject to back the metrics. The two publisher-side gates:
8
+ *
9
+ * - At least {@link MinPublishVolumeEnvelopes} envelopes (or
10
+ * equivalent handshake attempts) observed during the window.
11
+ * - At least one metrics field non-zero. Records with uniformly
12
+ * zero metrics MUST NOT be published.
13
+ *
14
+ * A consumer that receives an observation violating either rule
15
+ * SHOULD treat the publishing observer as a candidate for
16
+ * `observation_record_abuse` reporting per §3.4.
17
+ *
18
+ * @module
19
+ */
20
+ /**
21
+ * §4.6.2 RECOMMENDED minimum number of envelopes (or handshake
22
+ * attempts) the observer should have observed during the window
23
+ * before publishing an observation about a subject domain.
24
+ */
25
+ export const MinPublishVolumeEnvelopes = 16;
26
+ /**
27
+ * Reports whether the metrics carry at least
28
+ * {@link MinPublishVolumeEnvelopes} envelopes or handshake
29
+ * attempts (post-bucketing).
30
+ */
31
+ export function meetsPublishVolume(m) {
32
+ const total = (m.envelopes_received ?? 0) +
33
+ (m.handshakes_completed ?? 0) +
34
+ (m.handshakes_rejected ?? 0);
35
+ return total >= MinPublishVolumeEnvelopes;
36
+ }
37
+ /**
38
+ * Reports whether every metric field is zero and
39
+ * `abuse_categories` is empty.
40
+ */
41
+ export function allMetricsZero(m) {
42
+ return ((m.envelopes_received ?? 0) === 0 &&
43
+ (m.envelopes_rejected ?? 0) === 0 &&
44
+ (m.abuse_reports ?? 0) === 0 &&
45
+ (m.unique_senders_observed ?? 0) === 0 &&
46
+ (m.handshakes_completed ?? 0) === 0 &&
47
+ (m.handshakes_rejected ?? 0) === 0 &&
48
+ (m.abuse_categories === undefined || m.abuse_categories.length === 0));
49
+ }
50
+ /**
51
+ * Convenience predicate: true when the metrics satisfy both the
52
+ * volume threshold and the non-all-zero rule. Publishers SHOULD
53
+ * gate every outgoing observation on this check.
54
+ */
55
+ export function eligibleForPublication(m) {
56
+ return meetsPublishVolume(m) && !allMetricsZero(m);
57
+ }
58
+ //# sourceMappingURL=eligibility.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eligibility.js","sourceRoot":"","sources":["../../src/reputation/eligibility.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH;;;;GAIG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,EAAE,CAAC;AAE5C;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,CAAU;IAC3C,MAAM,KAAK,GACT,CAAC,CAAC,CAAC,kBAAkB,IAAI,CAAC,CAAC;QAC3B,CAAC,CAAC,CAAC,oBAAoB,IAAI,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC,mBAAmB,IAAI,CAAC,CAAC,CAAC;IAC/B,OAAO,KAAK,IAAI,yBAAyB,CAAC;AAC5C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,CAAU;IACvC,OAAO,CACL,CAAC,CAAC,CAAC,kBAAkB,IAAI,CAAC,CAAC,KAAK,CAAC;QACjC,CAAC,CAAC,CAAC,kBAAkB,IAAI,CAAC,CAAC,KAAK,CAAC;QACjC,CAAC,CAAC,CAAC,aAAa,IAAI,CAAC,CAAC,KAAK,CAAC;QAC5B,CAAC,CAAC,CAAC,uBAAuB,IAAI,CAAC,CAAC,KAAK,CAAC;QACtC,CAAC,CAAC,CAAC,oBAAoB,IAAI,CAAC,CAAC,KAAK,CAAC;QACnC,CAAC,CAAC,CAAC,mBAAmB,IAAI,CAAC,CAAC,KAAK,CAAC;QAClC,CAAC,CAAC,CAAC,gBAAgB,KAAK,SAAS,IAAI,CAAC,CAAC,gBAAgB,CAAC,MAAM,KAAK,CAAC,CAAC,CACtE,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CAAC,CAAU;IAC/C,OAAO,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;AACrD,CAAC"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Evidence-hash binding helpers per REPUTATION.md §5.5.1.
3
+ *
4
+ * A SEMP_TRUST_OBSERVATION that claims `evidence_available: true`
5
+ * carries an `evidence_hash` over the bytes returned by
6
+ * `evidence_uri`. A consumer MUST verify the fetched bytes against
7
+ * the hash before treating the evidence as authoritative; a
8
+ * mismatch is equivalent to a signature failure.
9
+ *
10
+ * @module
11
+ */
12
+ import { type Observation } from "./types.js";
13
+ /** Sentinel error class returned on any evidence-hash divergence. */
14
+ export declare class EvidenceHashMismatchError extends Error {
15
+ constructor(message: string);
16
+ }
17
+ /** Sentinel error class returned on observation size violations. */
18
+ export declare class ObservationOversizedError extends Error {
19
+ constructor(message: string);
20
+ }
21
+ /**
22
+ * Enforce the §4.2 rules linking `evidence_available`,
23
+ * `evidence_uri`, and `evidence_hash`:
24
+ *
25
+ * - true -> both `evidence_uri` and `evidence_hash` MUST be present.
26
+ * - false -> both `evidence_uri` and `evidence_hash` MUST be absent.
27
+ *
28
+ * Throws with a descriptive message on any violation.
29
+ */
30
+ export declare function validateEvidenceFields(observation: Observation): void;
31
+ /**
32
+ * Verify that `evidence` hashes to the observation's
33
+ * `evidence_hash.value` under `evidence_hash.algorithm`. Throws
34
+ * {@link EvidenceHashMismatchError} on any divergence (algorithm
35
+ * unsupported, base64 decode failure, digest mismatch).
36
+ *
37
+ * Currently the only defined algorithm is "sha-256".
38
+ */
39
+ export declare function verifyEvidenceBytes(observation: Observation, evidence: Uint8Array): void;
40
+ /**
41
+ * Throw {@link ObservationOversizedError} when the canonical UTF-8
42
+ * JSON form of an observation exceeds {@link MaxObservationBytes}.
43
+ * Servers MUST run this before propagating a received observation
44
+ * per §4.6.1.
45
+ */
46
+ export declare function checkObservationSize(canonicalBytes: Uint8Array): void;
47
+ //# sourceMappingURL=evidence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evidence.d.ts","sourceRoot":"","sources":["../../src/reputation/evidence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,EAAE,KAAK,WAAW,EAAuB,MAAM,YAAY,CAAC;AAEnE,qEAAqE;AACrE,qBAAa,yBAA0B,SAAQ,KAAK;gBACtC,OAAO,EAAE,MAAM;CAI5B;AAED,oEAAoE;AACpE,qBAAa,yBAA0B,SAAQ,KAAK;gBACtC,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI,CAmCrE;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,UAAU,GACnB,IAAI,CAoCN;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,cAAc,EAAE,UAAU,GAAG,IAAI,CAMrE"}
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Evidence-hash binding helpers per REPUTATION.md §5.5.1.
3
+ *
4
+ * A SEMP_TRUST_OBSERVATION that claims `evidence_available: true`
5
+ * carries an `evidence_hash` over the bytes returned by
6
+ * `evidence_uri`. A consumer MUST verify the fetched bytes against
7
+ * the hash before treating the evidence as authoritative; a
8
+ * mismatch is equivalent to a signature failure.
9
+ *
10
+ * @module
11
+ */
12
+ import { sha256 } from "@noble/hashes/sha2.js";
13
+ import { MaxObservationBytes } from "./types.js";
14
+ /** Sentinel error class returned on any evidence-hash divergence. */
15
+ export class EvidenceHashMismatchError extends Error {
16
+ constructor(message) {
17
+ super(message);
18
+ this.name = "EvidenceHashMismatchError";
19
+ }
20
+ }
21
+ /** Sentinel error class returned on observation size violations. */
22
+ export class ObservationOversizedError extends Error {
23
+ constructor(message) {
24
+ super(message);
25
+ this.name = "ObservationOversizedError";
26
+ }
27
+ }
28
+ /**
29
+ * Enforce the §4.2 rules linking `evidence_available`,
30
+ * `evidence_uri`, and `evidence_hash`:
31
+ *
32
+ * - true -> both `evidence_uri` and `evidence_hash` MUST be present.
33
+ * - false -> both `evidence_uri` and `evidence_hash` MUST be absent.
34
+ *
35
+ * Throws with a descriptive message on any violation.
36
+ */
37
+ export function validateEvidenceFields(observation) {
38
+ if (observation.evidence_available) {
39
+ if (observation.evidence_uri === undefined ||
40
+ observation.evidence_uri === "") {
41
+ throw new Error("reputation: evidence_available=true requires evidence_uri");
42
+ }
43
+ if (observation.evidence_hash === undefined) {
44
+ throw new Error("reputation: evidence_available=true requires evidence_hash");
45
+ }
46
+ if (observation.evidence_hash.algorithm === "" ||
47
+ observation.evidence_hash.value === "") {
48
+ throw new Error("reputation: evidence_hash requires algorithm and value");
49
+ }
50
+ return;
51
+ }
52
+ if (observation.evidence_uri !== undefined) {
53
+ throw new Error("reputation: evidence_available=false MUST NOT carry evidence_uri");
54
+ }
55
+ if (observation.evidence_hash !== undefined) {
56
+ throw new Error("reputation: evidence_available=false MUST NOT carry evidence_hash");
57
+ }
58
+ }
59
+ /**
60
+ * Verify that `evidence` hashes to the observation's
61
+ * `evidence_hash.value` under `evidence_hash.algorithm`. Throws
62
+ * {@link EvidenceHashMismatchError} on any divergence (algorithm
63
+ * unsupported, base64 decode failure, digest mismatch).
64
+ *
65
+ * Currently the only defined algorithm is "sha-256".
66
+ */
67
+ export function verifyEvidenceBytes(observation, evidence) {
68
+ if (observation.evidence_hash === undefined) {
69
+ throw new EvidenceHashMismatchError("reputation: observation has no evidence_hash");
70
+ }
71
+ let want;
72
+ try {
73
+ want = decodeBase64(observation.evidence_hash.value);
74
+ }
75
+ catch (err) {
76
+ throw new EvidenceHashMismatchError(`reputation: evidence_hash.value not base64: ${err instanceof Error ? err.message : String(err)}`);
77
+ }
78
+ let got;
79
+ switch (observation.evidence_hash.algorithm) {
80
+ case "sha-256":
81
+ got = sha256(evidence);
82
+ break;
83
+ default:
84
+ throw new EvidenceHashMismatchError(`reputation: unsupported evidence_hash algorithm "${observation.evidence_hash.algorithm}"`);
85
+ }
86
+ if (got.length !== want.length) {
87
+ throw new EvidenceHashMismatchError("reputation: evidence_hash length mismatch");
88
+ }
89
+ for (let i = 0; i < got.length; i++) {
90
+ if (got[i] !== want[i]) {
91
+ throw new EvidenceHashMismatchError("reputation: evidence_hash digest does not match fetched bytes");
92
+ }
93
+ }
94
+ }
95
+ /**
96
+ * Throw {@link ObservationOversizedError} when the canonical UTF-8
97
+ * JSON form of an observation exceeds {@link MaxObservationBytes}.
98
+ * Servers MUST run this before propagating a received observation
99
+ * per §4.6.1.
100
+ */
101
+ export function checkObservationSize(canonicalBytes) {
102
+ if (canonicalBytes.length > MaxObservationBytes) {
103
+ throw new ObservationOversizedError(`reputation: observation ${canonicalBytes.length} bytes exceeds 16 KiB cap`);
104
+ }
105
+ }
106
+ function decodeBase64(s) {
107
+ if (typeof Buffer !== "undefined") {
108
+ return new Uint8Array(Buffer.from(s, "base64"));
109
+ }
110
+ const bin = atob(s);
111
+ const out = new Uint8Array(bin.length);
112
+ for (let i = 0; i < bin.length; i++) {
113
+ out[i] = bin.charCodeAt(i);
114
+ }
115
+ return out;
116
+ }
117
+ //# sourceMappingURL=evidence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evidence.js","sourceRoot":"","sources":["../../src/reputation/evidence.ts"],"names":[],"mappings":"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"}
@@ -31,7 +31,7 @@ export interface FetchTrustObservationsOptions {
31
31
  /** Optional cancellation signal. */
32
32
  signal?: AbortSignal;
33
33
  /**
34
- * Per-request timeout in milliseconds. Defaults to 10 seconds
34
+ * Per-request timeout in milliseconds. Defaults to 10 seconds -
35
35
  * matches `discovery.fetchConfiguration`.
36
36
  */
37
37
  timeoutMs?: number;
@@ -52,7 +52,7 @@ export interface FetchTrustObservationsOptions {
52
52
  * return the parsed envelope.
53
53
  *
54
54
  * Per-observation signatures inside `result.observations` are NOT
55
- * verified callers walk those and call
55
+ * verified - callers walk those and call
56
56
  * {@link "./sign".verifyObservation} on each, because different
57
57
  * observations in the same envelope MAY be signed under different
58
58
  * key_ids (e.g. after a key rotation).
@@ -31,7 +31,7 @@ export const TrustGossipMaxBytes = 1 * 1024 * 1024;
31
31
  * return the parsed envelope.
32
32
  *
33
33
  * Per-observation signatures inside `result.observations` are NOT
34
- * verified callers walk those and call
34
+ * verified - callers walk those and call
35
35
  * {@link "./sign".verifyObservation} on each, because different
36
36
  * observations in the same envelope MAY be signed under different
37
37
  * key_ids (e.g. after a key rotation).
@@ -8,7 +8,10 @@
8
8
  *
9
9
  * @module
10
10
  */
11
- export { type AbuseCategory, type AbuseReport, type Assessment, type DisclosureAuthorization, type DisclosureScope, type Evidence, type GossipHash, type Metrics, type Observation, type ReputationSignature, type SealedEnvelopeEvidence, type TrustObservations, type Window, AbuseReportType, MaxMetricBucket, ObservationType, ObservationsEnvelopeType, PublicationPath, Version, isKnownAbuseCategory, } from "./types.js";
11
+ export { type AbuseCategory, type AbuseReport, type Assessment, type DisclosureAuthorization, type DisclosureScope, type Evidence, type EvidenceHash, type GossipHash, type Metrics, type Observation, type ReputationSignature, type SealedEnvelopeEvidence, type TrustObservations, type Window, AbuseReportType, MaxEvidenceBytes, MaxMetricBucket, MaxObservationBytes, ObservationType, ObservationsEnvelopeType, PublicationPath, Version, isKnownAbuseCategory, } from "./types.js";
12
+ export { EvidenceHashMismatchError, ObservationOversizedError, checkObservationSize, validateEvidenceFields, verifyEvidenceBytes, } from "./evidence.js";
13
+ export { MinPublishVolumeEnvelopes, allMetricsZero, eligibleForPublication, meetsPublishVolume, } from "./eligibility.js";
14
+ export { type ReferenceEntry, type References, ReferencesPrefix, ReferencesType, ReferencesVersion, signReferences, validateReferences, verifyReferences, } from "./references.js";
12
15
  export { applyBucketing, bucketize, dedupeAbuseCategories, } from "./bucketize.js";
13
16
  export { SignatureAlgorithmEd25519, authAllowsBrief, authAllowsEnclosure, signDisclosureAuthorization, signObservation, signTrustObservations, validateAbuseReport, verifyDisclosureAuthorization, verifyObservation, verifyTrustObservations, } from "./sign.js";
14
17
  export { type Score, ObservationStore, classifyScore, } from "./observation_store.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/reputation/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,uBAAuB,EAC5B,KAAK,eAAe,EACpB,KAAK,QAAQ,EACb,KAAK,UAAU,EACf,KAAK,OAAO,EACZ,KAAK,WAAW,EAChB,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,iBAAiB,EACtB,KAAK,MAAM,EACX,eAAe,EACf,eAAe,EACf,eAAe,EACf,wBAAwB,EACxB,eAAe,EACf,OAAO,EACP,oBAAoB,GACrB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,cAAc,EACd,SAAS,EACT,qBAAqB,GACtB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,yBAAyB,EACzB,eAAe,EACf,mBAAmB,EACnB,2BAA2B,EAC3B,eAAe,EACf,qBAAqB,EACrB,mBAAmB,EACnB,6BAA6B,EAC7B,iBAAiB,EACjB,uBAAuB,GACxB,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,KAAK,KAAK,EACV,gBAAgB,EAChB,aAAa,GACd,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,EACL,KAAK,YAAY,EACjB,eAAe,EACf,qBAAqB,EACrB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,iBAAiB,EACjB,cAAc,EACd,YAAY,EACZ,qBAAqB,EACrB,gBAAgB,EAChB,uBAAuB,EACvB,cAAc,GACf,MAAM,UAAU,CAAC;AAElB,OAAO,EACL,KAAK,KAAK,EACV,cAAc,EACd,WAAW,GACZ,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,cAAc,EACd,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,KAAK,6BAA6B,EAClC,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/reputation/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,uBAAuB,EAC5B,KAAK,eAAe,EACpB,KAAK,QAAQ,EACb,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,OAAO,EACZ,KAAK,WAAW,EAChB,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,iBAAiB,EACtB,KAAK,MAAM,EACX,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,mBAAmB,EACnB,eAAe,EACf,wBAAwB,EACxB,eAAe,EACf,OAAO,EACP,oBAAoB,GACrB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,yBAAyB,EACzB,yBAAyB,EACzB,oBAAoB,EACpB,sBAAsB,EACtB,mBAAmB,GACpB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,yBAAyB,EACzB,cAAc,EACd,sBAAsB,EACtB,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,cAAc,EACd,SAAS,EACT,qBAAqB,GACtB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,yBAAyB,EACzB,eAAe,EACf,mBAAmB,EACnB,2BAA2B,EAC3B,eAAe,EACf,qBAAqB,EACrB,mBAAmB,EACnB,6BAA6B,EAC7B,iBAAiB,EACjB,uBAAuB,GACxB,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,KAAK,KAAK,EACV,gBAAgB,EAChB,aAAa,GACd,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,EACL,KAAK,YAAY,EACjB,eAAe,EACf,qBAAqB,EACrB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,iBAAiB,EACjB,cAAc,EACd,YAAY,EACZ,qBAAqB,EACrB,gBAAgB,EAChB,uBAAuB,EACvB,cAAc,GACf,MAAM,UAAU,CAAC;AAElB,OAAO,EACL,KAAK,KAAK,EACV,cAAc,EACd,WAAW,GACZ,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,cAAc,EACd,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,KAAK,6BAA6B,EAClC,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,mBAAmB,CAAC"}
@@ -8,7 +8,10 @@
8
8
  *
9
9
  * @module
10
10
  */
11
- export { AbuseReportType, MaxMetricBucket, ObservationType, ObservationsEnvelopeType, PublicationPath, Version, isKnownAbuseCategory, } from "./types.js";
11
+ export { AbuseReportType, MaxEvidenceBytes, MaxMetricBucket, MaxObservationBytes, ObservationType, ObservationsEnvelopeType, PublicationPath, Version, isKnownAbuseCategory, } from "./types.js";
12
+ export { EvidenceHashMismatchError, ObservationOversizedError, checkObservationSize, validateEvidenceFields, verifyEvidenceBytes, } from "./evidence.js";
13
+ export { MinPublishVolumeEnvelopes, allMetricsZero, eligibleForPublication, meetsPublishVolume, } from "./eligibility.js";
14
+ export { ReferencesPrefix, ReferencesType, ReferencesVersion, signReferences, validateReferences, verifyReferences, } from "./references.js";
12
15
  export { applyBucketing, bucketize, dedupeAbuseCategories, } from "./bucketize.js";
13
16
  export { SignatureAlgorithmEd25519, authAllowsBrief, authAllowsEnclosure, signDisclosureAuthorization, signObservation, signTrustObservations, validateAbuseReport, verifyDisclosureAuthorization, verifyObservation, verifyTrustObservations, } from "./sign.js";
14
17
  export { ObservationStore, classifyScore, } from "./observation_store.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/reputation/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAcL,eAAe,EACf,eAAe,EACf,eAAe,EACf,wBAAwB,EACxB,eAAe,EACf,OAAO,EACP,oBAAoB,GACrB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,cAAc,EACd,SAAS,EACT,qBAAqB,GACtB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,yBAAyB,EACzB,eAAe,EACf,mBAAmB,EACnB,2BAA2B,EAC3B,eAAe,EACf,qBAAqB,EACrB,mBAAmB,EACnB,6BAA6B,EAC7B,iBAAiB,EACjB,uBAAuB,GACxB,MAAM,WAAW,CAAC;AAEnB,OAAO,EAEL,gBAAgB,EAChB,aAAa,GACd,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,EAEL,eAAe,EACf,qBAAqB,EACrB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,iBAAiB,EACjB,cAAc,EACd,YAAY,EACZ,qBAAqB,EACrB,gBAAgB,EAChB,uBAAuB,EACvB,cAAc,GACf,MAAM,UAAU,CAAC;AAElB,OAAO,EAEL,cAAc,EACd,WAAW,GACZ,MAAM,YAAY,CAAC;AAEpB,OAAO,EAGL,cAAc,EACd,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAEL,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/reputation/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAeL,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,mBAAmB,EACnB,eAAe,EACf,wBAAwB,EACxB,eAAe,EACf,OAAO,EACP,oBAAoB,GACrB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,yBAAyB,EACzB,yBAAyB,EACzB,oBAAoB,EACpB,sBAAsB,EACtB,mBAAmB,GACpB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,yBAAyB,EACzB,cAAc,EACd,sBAAsB,EACtB,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAGL,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,cAAc,EACd,SAAS,EACT,qBAAqB,GACtB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,yBAAyB,EACzB,eAAe,EACf,mBAAmB,EACnB,2BAA2B,EAC3B,eAAe,EACf,qBAAqB,EACrB,mBAAmB,EACnB,6BAA6B,EAC7B,iBAAiB,EACjB,uBAAuB,GACxB,MAAM,WAAW,CAAC;AAEnB,OAAO,EAEL,gBAAgB,EAChB,aAAa,GACd,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,EAEL,eAAe,EACf,qBAAqB,EACrB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,iBAAiB,EACjB,cAAc,EACd,YAAY,EACZ,qBAAqB,EACrB,gBAAgB,EAChB,uBAAuB,EACvB,cAAc,GACf,MAAM,UAAU,CAAC;AAElB,OAAO,EAEL,cAAc,EACd,WAAW,GACZ,MAAM,YAAY,CAAC;AAEpB,OAAO,EAGL,cAAc,EACd,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAEL,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,mBAAmB,CAAC"}
@@ -58,7 +58,7 @@ export declare function difficultyForAssessment(a: Assessment | ""): number;
58
58
  * `ttlMs <= 0` is replaced with {@link DefaultChallengeTTLMs}.
59
59
  */
60
60
  export declare function issueChallenge(difficulty: number, ttlMs?: number, rand?: (n: number) => Uint8Array): PoWChallenge;
61
- /** Base64-encoded challenge prefix what the wire carries. */
61
+ /** Base64-encoded challenge prefix - what the wire carries. */
62
62
  export declare function challengePrefixBase64(c: PoWChallenge): string;
63
63
  /**
64
64
  * Tracks issued + redeemed challenges; prevents replay per §8.3.4.
@@ -75,7 +75,7 @@ export function issueChallenge(difficulty, ttlMs, rand = defaultRand) {
75
75
  expires: new Date(Date.now() + ttl),
76
76
  };
77
77
  }
78
- /** Base64-encoded challenge prefix what the wire carries. */
78
+ /** Base64-encoded challenge prefix - what the wire carries. */
79
79
  export function challengePrefixBase64(c) {
80
80
  if (typeof Buffer !== "undefined") {
81
81
  return Buffer.from(c.prefix).toString("base64");
@@ -0,0 +1,51 @@
1
+ /**
2
+ * SEMP_REPUTATION_REFERENCES document per
3
+ * draft-gokce-semp-delivery §12.2.
4
+ *
5
+ * Lists third-party observers a subject domain points peers at
6
+ * when they want to cross-check the subject's reputation. The
7
+ * subject domain signs the document with its domain signing key
8
+ * under the SEMP-REPUTATION-REFERENCES: prefix; consumers verify
9
+ * against the published domain key.
10
+ *
11
+ * @module
12
+ */
13
+ import type { Assessment, ReputationSignature } from "./types.js";
14
+ /** Wire-level type discriminator. */
15
+ export declare const ReferencesType = "SEMP_REPUTATION_REFERENCES";
16
+ /** Wire-level version. */
17
+ export declare const ReferencesVersion = "1.0.0";
18
+ /** Domain-separation prefix for SEMP_REPUTATION_REFERENCES signatures. */
19
+ export declare const ReferencesPrefix = "SEMP-REPUTATION-REFERENCES:";
20
+ /** Single observer reference. */
21
+ export interface ReferenceEntry {
22
+ observer: string;
23
+ uri: string;
24
+ /** ISO 8601 UTC. */
25
+ fetched_at: string;
26
+ /** Optional cached classification hint; informational. */
27
+ assessment?: Assessment;
28
+ }
29
+ /** SEMP_REPUTATION_REFERENCES record per §12.2. */
30
+ export interface References {
31
+ type: typeof ReferencesType;
32
+ version: string;
33
+ domain: string;
34
+ references: ReferenceEntry[];
35
+ /** ISO 8601 UTC. */
36
+ timestamp: string;
37
+ signature: ReputationSignature;
38
+ }
39
+ /**
40
+ * Sign `r.signature` with the subject domain's signing key under
41
+ * the SEMP-REPUTATION-REFERENCES: prefix. Mutates r in place and
42
+ * returns the base64 signature value.
43
+ */
44
+ export declare function signReferences(r: References, domainPriv: Uint8Array, domainKeyId: string): string;
45
+ /** Verify `r.signature` against the subject domain's public key. */
46
+ export declare function verifyReferences(r: References, domainPub: Uint8Array): boolean;
47
+ /** Structural validation per §12.2. */
48
+ export declare function validateReferences(r: References, opts?: {
49
+ skipSignatureCheck?: boolean;
50
+ }): void;
51
+ //# sourceMappingURL=references.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"references.d.ts","sourceRoot":"","sources":["../../src/reputation/references.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAElE,qCAAqC;AACrC,eAAO,MAAM,cAAc,+BAA+B,CAAC;AAE3D,0BAA0B;AAC1B,eAAO,MAAM,iBAAiB,UAAU,CAAC;AAEzC,0EAA0E;AAC1E,eAAO,MAAM,gBAAgB,gCAAgC,CAAC;AAE9D,iCAAiC;AACjC,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,oBAAoB;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB;AAED,mDAAmD;AACnD,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,OAAO,cAAc,CAAC;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B,oBAAoB;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,mBAAmB,CAAC;CAChC;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,CAAC,EAAE,UAAU,EACb,UAAU,EAAE,UAAU,EACtB,WAAW,EAAE,MAAM,GAClB,MAAM,CAsBR;AAED,oEAAoE;AACpE,wBAAgB,gBAAgB,CAC9B,CAAC,EAAE,UAAU,EACb,SAAS,EAAE,UAAU,GACpB,OAAO,CAYT;AAED,uCAAuC;AACvC,wBAAgB,kBAAkB,CAChC,CAAC,EAAE,UAAU,EACb,IAAI,GAAE;IAAE,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAAO,GAC1C,IAAI,CAiCN"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * SEMP_REPUTATION_REFERENCES document per
3
+ * draft-gokce-semp-delivery §12.2.
4
+ *
5
+ * Lists third-party observers a subject domain points peers at
6
+ * when they want to cross-check the subject's reputation. The
7
+ * subject domain signs the document with its domain signing key
8
+ * under the SEMP-REPUTATION-REFERENCES: prefix; consumers verify
9
+ * against the published domain key.
10
+ *
11
+ * @module
12
+ */
13
+ import { signSignedDoc, verifySignedDoc } from "../keys/index.js";
14
+ /** Wire-level type discriminator. */
15
+ export const ReferencesType = "SEMP_REPUTATION_REFERENCES";
16
+ /** Wire-level version. */
17
+ export const ReferencesVersion = "1.0.0";
18
+ /** Domain-separation prefix for SEMP_REPUTATION_REFERENCES signatures. */
19
+ export const ReferencesPrefix = "SEMP-REPUTATION-REFERENCES:";
20
+ /**
21
+ * Sign `r.signature` with the subject domain's signing key under
22
+ * the SEMP-REPUTATION-REFERENCES: prefix. Mutates r in place and
23
+ * returns the base64 signature value.
24
+ */
25
+ export function signReferences(r, domainPriv, domainKeyId) {
26
+ if (domainKeyId === "") {
27
+ throw new Error("reputation: empty domain key_id");
28
+ }
29
+ if (r.type === "") {
30
+ r.type = ReferencesType;
31
+ }
32
+ if (r.version === "") {
33
+ r.version = ReferencesVersion;
34
+ }
35
+ validateReferences(r, { skipSignatureCheck: true });
36
+ r.signature.algorithm = "ed25519";
37
+ r.signature.key_id = domainKeyId;
38
+ r.signature.value = "";
39
+ const { signedJSON, signatureB64 } = signSignedDoc({
40
+ preSignJSON: r,
41
+ seed: domainPriv,
42
+ signaturePath: "signature.value",
43
+ prefix: ReferencesPrefix,
44
+ });
45
+ r.signature.value = signedJSON.signature.value;
46
+ return signatureB64;
47
+ }
48
+ /** Verify `r.signature` against the subject domain's public key. */
49
+ export function verifyReferences(r, domainPub) {
50
+ validateReferences(r);
51
+ if (r.signature.value === "") {
52
+ return false;
53
+ }
54
+ const { ok } = verifySignedDoc({
55
+ signedJSON: r,
56
+ publicKey: domainPub,
57
+ signaturePath: "signature.value",
58
+ prefix: ReferencesPrefix,
59
+ });
60
+ return ok;
61
+ }
62
+ /** Structural validation per §12.2. */
63
+ export function validateReferences(r, opts = {}) {
64
+ if (r.type !== ReferencesType) {
65
+ throw new Error(`reputation: references type ${JSON.stringify(r.type)}, want ${ReferencesType}`);
66
+ }
67
+ if (r.version === "") {
68
+ throw new Error("reputation: references missing version");
69
+ }
70
+ if (r.domain === "") {
71
+ throw new Error("reputation: references missing domain");
72
+ }
73
+ if (r.timestamp === "") {
74
+ throw new Error("reputation: references missing timestamp");
75
+ }
76
+ for (let i = 0; i < r.references.length; i++) {
77
+ const e = r.references[i];
78
+ if (e === undefined) {
79
+ continue;
80
+ }
81
+ if (e.observer === "") {
82
+ throw new Error(`reputation: references[${i}] missing observer`);
83
+ }
84
+ if (e.uri === "") {
85
+ throw new Error(`reputation: references[${i}] missing uri`);
86
+ }
87
+ if (e.fetched_at === "") {
88
+ throw new Error(`reputation: references[${i}] missing fetched_at`);
89
+ }
90
+ }
91
+ if (!opts.skipSignatureCheck && r.signature === undefined) {
92
+ throw new Error("reputation: references missing signature");
93
+ }
94
+ }
95
+ //# sourceMappingURL=references.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"references.js","sourceRoot":"","sources":["../../src/reputation/references.ts"],"names":[],"mappings":"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"}