@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/SECURITY.md +91 -86
- package/dist/pulse.cjs +56 -0
- package/dist/pulse.cjs.map +1 -1
- package/dist/pulse.esm.js +56 -1
- package/dist/pulse.esm.js.map +1 -1
- package/index.d.ts +54 -0
- package/package.json +5 -1
- package/src/errors.js +54 -0
- package/src/index.js +3 -0
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.
|
|
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
|
|