@svrnsec/pulse 0.8.0 → 0.9.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.
package/index.d.ts CHANGED
@@ -893,3 +893,57 @@ export declare function decodeToken(compact: string): object;
893
893
  * For logging/debugging only — use verifyEngagementToken for security checks.
894
894
  */
895
895
  export declare function decodeTokenUnsafe(compact: string): object & { _verified: false };
896
+
897
+ // =============================================================================
898
+ // Structured Error Codes
899
+ // =============================================================================
900
+
901
+ export declare const PulseErrorCode: Readonly<{
902
+ // Structural
903
+ INVALID_PAYLOAD_STRUCTURE: 'INVALID_PAYLOAD_STRUCTURE';
904
+ PROTOTYPE_POLLUTION_ATTEMPT: 'PROTOTYPE_POLLUTION_ATTEMPT';
905
+ MISSING_REQUIRED_FIELD: 'MISSING_REQUIRED_FIELD';
906
+ INVALID_TYPE: 'INVALID_TYPE';
907
+ TIMESTAMP_OUT_OF_RANGE: 'TIMESTAMP_OUT_OF_RANGE';
908
+ UNSUPPORTED_PROOF_VERSION: 'UNSUPPORTED_PROOF_VERSION';
909
+
910
+ // Hash integrity
911
+ INVALID_HASH_FORMAT: 'INVALID_HASH_FORMAT';
912
+ HASH_MISMATCH_PAYLOAD_TAMPERED: 'HASH_MISMATCH_PAYLOAD_TAMPERED';
913
+
914
+ // Timestamp / freshness
915
+ PROOF_EXPIRED: 'PROOF_EXPIRED';
916
+ PROOF_FROM_FUTURE: 'PROOF_FROM_FUTURE';
917
+ NONCE_INVALID_OR_REPLAYED: 'NONCE_INVALID_OR_REPLAYED';
918
+
919
+ // Jitter / scoring
920
+ JITTER_SCORE_TOO_LOW: 'JITTER_SCORE_TOO_LOW';
921
+ DYNAMIC_THRESHOLD_NOT_MET: 'DYNAMIC_THRESHOLD_NOT_MET';
922
+
923
+ // Heuristic / coherence overrides
924
+ HEURISTIC_HARD_OVERRIDE: 'HEURISTIC_HARD_OVERRIDE';
925
+ COHERENCE_HARD_OVERRIDE: 'COHERENCE_HARD_OVERRIDE';
926
+
927
+ // Renderer
928
+ SOFTWARE_RENDERER_DETECTED: 'SOFTWARE_RENDERER_DETECTED';
929
+ BLOCKLISTED_RENDERER: 'BLOCKLISTED_RENDERER';
930
+
931
+ // Bio activity
932
+ NO_BIO_ACTIVITY_DETECTED: 'NO_BIO_ACTIVITY_DETECTED';
933
+
934
+ // Cross-signal forgery detection
935
+ FORGED_SIGNAL_CV_SCORE_IMPOSSIBLE: 'FORGED_SIGNAL:CV_SCORE_IMPOSSIBLE';
936
+ FORGED_SIGNAL_AUTOCORR_SCORE_IMPOSSIBLE: 'FORGED_SIGNAL:AUTOCORR_SCORE_IMPOSSIBLE';
937
+ FORGED_SIGNAL_QE_SCORE_IMPOSSIBLE: 'FORGED_SIGNAL:QE_SCORE_IMPOSSIBLE';
938
+
939
+ // Risk flags (informational)
940
+ NONCE_FRESHNESS_NOT_CHECKED: 'NONCE_FRESHNESS_NOT_CHECKED';
941
+ CANVAS_UNAVAILABLE: 'CANVAS_UNAVAILABLE';
942
+ ZERO_BIO_SAMPLES: 'ZERO_BIO_SAMPLES';
943
+ NEGATIVE_INTERFERENCE_COEFFICIENT: 'NEGATIVE_INTERFERENCE_COEFFICIENT';
944
+ INCONSISTENCY_LOW_CV_BUT_HIGH_SCORE: 'INCONSISTENCY:LOW_CV_BUT_HIGH_SCORE';
945
+ SUSPICIOUS_ZERO_TIMER_GRANULARITY: 'SUSPICIOUS_ZERO_TIMER_GRANULARITY';
946
+ INCONSISTENCY_FLAT_THERMAL_BUT_HIGH_SCORE: 'INCONSISTENCY:FLAT_THERMAL_BUT_HIGH_SCORE';
947
+ EXTREME_HURST: 'EXTREME_HURST';
948
+ AUDIO_JITTER_TOO_FLAT: 'AUDIO_JITTER_TOO_FLAT';
949
+ }>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@svrnsec/pulse",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "Physical Turing Test — Idle attestation, population-level Sybil detection, and engagement tokens that defeat click farms at the physics layer.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -96,6 +96,10 @@
96
96
  "./coordination": {
97
97
  "import": "./src/analysis/coordinatedBehavior.js",
98
98
  "node": "./src/analysis/coordinatedBehavior.js"
99
+ },
100
+ "./errors": {
101
+ "import": "./src/errors.js",
102
+ "node": "./src/errors.js"
99
103
  }
100
104
  },
101
105
  "main": "dist/pulse.cjs",
package/src/errors.js ADDED
@@ -0,0 +1,54 @@
1
+ /**
2
+ * @svrnsec/pulse — Structured Error Codes
3
+ *
4
+ * Use these constants instead of string matching for type-safe error handling.
5
+ */
6
+ export const PulseErrorCode = Object.freeze({
7
+ // Structural
8
+ INVALID_PAYLOAD_STRUCTURE: 'INVALID_PAYLOAD_STRUCTURE',
9
+ PROTOTYPE_POLLUTION_ATTEMPT: 'PROTOTYPE_POLLUTION_ATTEMPT',
10
+ MISSING_REQUIRED_FIELD: 'MISSING_REQUIRED_FIELD',
11
+ INVALID_TYPE: 'INVALID_TYPE',
12
+ TIMESTAMP_OUT_OF_RANGE: 'TIMESTAMP_OUT_OF_RANGE',
13
+ UNSUPPORTED_PROOF_VERSION: 'UNSUPPORTED_PROOF_VERSION',
14
+
15
+ // Hash integrity
16
+ INVALID_HASH_FORMAT: 'INVALID_HASH_FORMAT',
17
+ HASH_MISMATCH_PAYLOAD_TAMPERED: 'HASH_MISMATCH_PAYLOAD_TAMPERED',
18
+
19
+ // Timestamp / freshness
20
+ PROOF_EXPIRED: 'PROOF_EXPIRED',
21
+ PROOF_FROM_FUTURE: 'PROOF_FROM_FUTURE',
22
+ NONCE_INVALID_OR_REPLAYED: 'NONCE_INVALID_OR_REPLAYED',
23
+
24
+ // Jitter / scoring
25
+ JITTER_SCORE_TOO_LOW: 'JITTER_SCORE_TOO_LOW',
26
+ DYNAMIC_THRESHOLD_NOT_MET: 'DYNAMIC_THRESHOLD_NOT_MET',
27
+
28
+ // Heuristic / coherence overrides
29
+ HEURISTIC_HARD_OVERRIDE: 'HEURISTIC_HARD_OVERRIDE',
30
+ COHERENCE_HARD_OVERRIDE: 'COHERENCE_HARD_OVERRIDE',
31
+
32
+ // Renderer
33
+ SOFTWARE_RENDERER_DETECTED: 'SOFTWARE_RENDERER_DETECTED',
34
+ BLOCKLISTED_RENDERER: 'BLOCKLISTED_RENDERER',
35
+
36
+ // Bio activity
37
+ NO_BIO_ACTIVITY_DETECTED: 'NO_BIO_ACTIVITY_DETECTED',
38
+
39
+ // Cross-signal forgery detection
40
+ FORGED_SIGNAL_CV_SCORE_IMPOSSIBLE: 'FORGED_SIGNAL:CV_SCORE_IMPOSSIBLE',
41
+ FORGED_SIGNAL_AUTOCORR_SCORE_IMPOSSIBLE: 'FORGED_SIGNAL:AUTOCORR_SCORE_IMPOSSIBLE',
42
+ FORGED_SIGNAL_QE_SCORE_IMPOSSIBLE: 'FORGED_SIGNAL:QE_SCORE_IMPOSSIBLE',
43
+
44
+ // Risk flags (informational, not rejection reasons)
45
+ NONCE_FRESHNESS_NOT_CHECKED: 'NONCE_FRESHNESS_NOT_CHECKED',
46
+ CANVAS_UNAVAILABLE: 'CANVAS_UNAVAILABLE',
47
+ ZERO_BIO_SAMPLES: 'ZERO_BIO_SAMPLES',
48
+ NEGATIVE_INTERFERENCE_COEFFICIENT: 'NEGATIVE_INTERFERENCE_COEFFICIENT',
49
+ INCONSISTENCY_LOW_CV_BUT_HIGH_SCORE: 'INCONSISTENCY:LOW_CV_BUT_HIGH_SCORE',
50
+ SUSPICIOUS_ZERO_TIMER_GRANULARITY: 'SUSPICIOUS_ZERO_TIMER_GRANULARITY',
51
+ INCONSISTENCY_FLAT_THERMAL_BUT_HIGH_SCORE: 'INCONSISTENCY:FLAT_THERMAL_BUT_HIGH_SCORE',
52
+ EXTREME_HURST: 'EXTREME_HURST',
53
+ AUDIO_JITTER_TOO_FLAT: 'AUDIO_JITTER_TOO_FLAT',
54
+ });
package/src/index.js CHANGED
@@ -317,6 +317,9 @@ export { detectLlmAgent } from './analysis/llm.js';
317
317
  // Terminal utilities — pretty probe results in Node.js server contexts
318
318
  export { renderProbeResult, renderError, renderInlineUpdateHint } from './terminal.js';
319
319
 
320
+ // Structured error codes
321
+ export { PulseErrorCode } from './errors.js';
322
+
320
323
  // Version introspection
321
324
  export { CURRENT_VERSION, checkForUpdate } from './update-notifier.js';
322
325