@svrnsec/pulse 0.3.0 → 0.3.1

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
@@ -586,3 +586,131 @@ export interface SignatureComparison {
586
586
  profileMatch: boolean;
587
587
  providerMatch: boolean;
588
588
  }
589
+
590
+ // =============================================================================
591
+ // Extended Signal Layer Types
592
+ // =============================================================================
593
+
594
+ // ── ENF (Electrical Network Frequency) ───────────────────────────────────────
595
+
596
+ export interface EnfResult {
597
+ enfAvailable: boolean;
598
+ ripplePresent: boolean;
599
+ gridFrequency: 50 | 60 | null;
600
+ gridRegion: 'americas' | 'emea_apac' | 'unknown';
601
+ ripplePower: number;
602
+ snr50hz: number;
603
+ snr60hz: number;
604
+ enfDeviation: number | null;
605
+ sampleRateHz: number;
606
+ resolutionUs: number;
607
+ verdict: 'grid_60hz' | 'grid_50hz' | 'no_grid_signal' | 'grid_detected_region_unknown' | 'unavailable';
608
+ isVmIndicator: boolean;
609
+ temporalAnchor: {
610
+ nominalHz: number;
611
+ measuredRippleHz: number;
612
+ capturedAt: number;
613
+ gridHz: number;
614
+ } | null;
615
+ reason?: string;
616
+ }
617
+
618
+ export declare function collectEnfTimings(opts?: { iterations?: number }): Promise<EnfResult>;
619
+
620
+ // ── WebGPU Thermal Variance ───────────────────────────────────────────────────
621
+
622
+ export interface GpuEntropyResult {
623
+ gpuPresent: boolean;
624
+ isSoftware: boolean;
625
+ vendorString: string | null;
626
+ dispatchCV: number;
627
+ thermalGrowth: number;
628
+ verdict: 'real_gpu' | 'software_renderer' | 'no_webgpu' | 'ambiguous';
629
+ }
630
+
631
+ export declare function collectGpuEntropy(opts?: object): Promise<GpuEntropyResult>;
632
+
633
+ // ── DRAM Refresh Cycle ────────────────────────────────────────────────────────
634
+
635
+ export interface DramResult {
636
+ timings: number[];
637
+ refreshPeriodMs: number | null;
638
+ refreshPresent: boolean;
639
+ peakLag: number;
640
+ peakPower: number;
641
+ verdict: 'dram' | 'virtual' | 'ambiguous';
642
+ }
643
+
644
+ export declare function collectDramTimings(opts?: { iterations?: number; bufferMb?: number }): DramResult;
645
+
646
+ // ── LLM / AI Agent Behavioral Fingerprint ─────────────────────────────────────
647
+
648
+ export interface LlmResult {
649
+ aiConf: number;
650
+ thinkTimePattern: 'llm_latency_peak' | 'human_pareto' | 'unknown';
651
+ correctionRate: number;
652
+ rhythmicity: number;
653
+ pauseDistribution: 'uniform' | 'pareto' | 'unknown';
654
+ verdict: 'ai_agent' | 'human' | 'insufficient_data';
655
+ matchedModel: string | null;
656
+ }
657
+
658
+ export declare function detectLlmAgent(bioSnapshot: object): LlmResult;
659
+
660
+ // ── SAB Microsecond Timer ─────────────────────────────────────────────────────
661
+
662
+ export interface SabTimerResult {
663
+ isClamped: boolean;
664
+ clampAmountUs: number;
665
+ resolutionUs: number;
666
+ }
667
+
668
+ export declare function isSabAvailable(): boolean;
669
+ export declare function collectHighResTimings(opts?: { iterations?: number; matrixSize?: number }): {
670
+ timings: number[];
671
+ resolutionUs: number;
672
+ };
673
+
674
+ // =============================================================================
675
+ // Terminal / DX Utilities
676
+ // =============================================================================
677
+
678
+ export declare function renderProbeResult(opts: {
679
+ payload: ProofPayload;
680
+ hash: string;
681
+ result?: ValidationResult;
682
+ enf?: EnfResult | null;
683
+ gpu?: GpuEntropyResult | null;
684
+ dram?: DramResult | null;
685
+ llm?: LlmResult | null;
686
+ elapsedMs?: number;
687
+ }): void;
688
+
689
+ export declare function renderError(err: Error | string): void;
690
+ export declare function renderInlineUpdateHint(latest: string): void;
691
+
692
+ // =============================================================================
693
+ // Version / Update Notifier
694
+ // =============================================================================
695
+
696
+ export declare const CURRENT_VERSION: string;
697
+
698
+ export declare function checkForUpdate(opts?: {
699
+ silent?: boolean;
700
+ pkg?: string;
701
+ }): Promise<{ current: string; latest: string | null; updateAvailable: boolean }>;
702
+
703
+ export declare function notifyOnExit(opts?: { pkg?: string }): void;
704
+
705
+ // =============================================================================
706
+ // Extended PulseCommitment (includes extended signal layer results)
707
+ // =============================================================================
708
+
709
+ export interface ExtendedPulseCommitment extends PulseCommitment {
710
+ extended: {
711
+ enf: EnfResult | null;
712
+ gpu: GpuEntropyResult | null;
713
+ dram: DramResult | null;
714
+ llm: LlmResult | null;
715
+ };
716
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@svrnsec/pulse",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "Physical Turing Test — Hardware-Biological Symmetry Protocol distinguishing real consumer devices from sanitised datacenter VMs.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -54,9 +54,9 @@ export function blake3HexStr(str) {
54
54
  * @param {string} p.nonce – server-issued challenge nonce (hex)
55
55
  * @returns {ProofPayload}
56
56
  */
57
- export function buildProof({ entropy, jitter, bio, canvas, audio, nonce }) {
57
+ export function buildProof({ entropy, jitter, bio, canvas, audio, enf, gpu, dram, llm, nonce }) {
58
58
  if (!nonce || typeof nonce !== 'string') {
59
- throw new Error('@sovereign/pulse: nonce is required for anti-replay protection');
59
+ throw new Error('@svrnsec/pulse: nonce is required for anti-replay protection');
60
60
  }
61
61
 
62
62
  // Hash the raw timing arrays IN-BROWSER so we can prove their integrity
@@ -138,12 +138,68 @@ export function buildProof({ entropy, jitter, bio, canvas, audio, nonce }) {
138
138
  jitterMeanMs: _round(audio.jitterMeanMs, 4),
139
139
  jitterP95Ms: _round(audio.jitterP95Ms, 4),
140
140
  },
141
+
142
+ // ── Electrical Network Frequency ─────────────────────────────────────
143
+ enf: enf ? {
144
+ available: enf.enfAvailable,
145
+ ripplePresent: enf.ripplePresent,
146
+ gridFrequency: enf.gridFrequency,
147
+ gridRegion: enf.gridRegion,
148
+ ripplePower: _round(enf.ripplePower, 4),
149
+ enfDeviation: _round(enf.enfDeviation, 3),
150
+ snr50hz: _round(enf.snr50hz, 2),
151
+ snr60hz: _round(enf.snr60hz, 2),
152
+ sampleRateHz: _round(enf.sampleRateHz, 1),
153
+ verdict: enf.verdict,
154
+ isVmIndicator: enf.isVmIndicator,
155
+ capturedAt: enf.temporalAnchor?.capturedAt ?? null,
156
+ } : null,
157
+
158
+ // ── WebGPU thermal variance ───────────────────────────────────────────
159
+ gpu: gpu ? {
160
+ available: gpu.gpuPresent,
161
+ isSoftware: gpu.isSoftware,
162
+ vendorString: gpu.vendorString,
163
+ dispatchCV: _round(gpu.dispatchCV, 4),
164
+ thermalGrowth: _round(gpu.thermalGrowth, 4),
165
+ verdict: gpu.verdict,
166
+ } : null,
167
+
168
+ // ── DRAM refresh cycle ────────────────────────────────────────────────
169
+ dram: dram ? {
170
+ refreshPresent: dram.refreshPresent,
171
+ refreshPeriodMs: _round(dram.refreshPeriodMs, 2),
172
+ peakPower: _round(dram.peakPower, 4),
173
+ verdict: dram.verdict,
174
+ } : null,
175
+
176
+ // ── LLM / AI agent behavioral fingerprint ────────────────────────────
177
+ llm: llm ? {
178
+ aiConf: _round(llm.aiConf, 3),
179
+ thinkTimePattern: llm.thinkTimePattern,
180
+ correctionRate: _round(llm.correctionRate, 3),
181
+ rhythmicity: _round(llm.rhythmicity, 3),
182
+ pauseDistribution: llm.pauseDistribution,
183
+ verdict: llm.verdict,
184
+ matchedModel: llm.matchedModel ?? null,
185
+ } : null,
141
186
  },
142
187
 
143
- // Top-level classification summary
188
+ // Top-level classification summary — all signal layers combined
144
189
  classification: {
145
- jitterScore: _round(jitter.score, 4),
146
- flags: jitter.flags ?? [],
190
+ jitterScore: _round(jitter.score, 4),
191
+ flags: jitter.flags ?? [],
192
+ enfVerdict: enf?.verdict ?? 'unavailable',
193
+ gpuVerdict: gpu?.verdict ?? 'unavailable',
194
+ dramVerdict: dram?.verdict ?? 'unavailable',
195
+ llmVerdict: llm?.verdict ?? 'unavailable',
196
+ // Combined VM confidence: any hard signal raises this
197
+ vmIndicators: [
198
+ enf?.isVmIndicator ? 'enf_no_grid' : null,
199
+ gpu?.isSoftware ? 'gpu_software' : null,
200
+ dram?.verdict === 'virtual' ? 'dram_no_refresh' : null,
201
+ llm?.aiConf > 0.7 ? 'llm_agent' : null,
202
+ ].filter(Boolean),
147
203
  },
148
204
  };
149
205