@entros/pulse-sdk 1.0.1 → 1.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.
package/dist/index.d.mts CHANGED
@@ -95,6 +95,13 @@ interface VerificationResult {
95
95
  }
96
96
 
97
97
  type ResolvedConfig = Required<Pick<PulseConfig, "cluster" | "threshold">> & PulseConfig;
98
+ /**
99
+ * Shared pipeline: features → simhash → TBH → proof → submit.
100
+ * Used by both PulseSDK.verify() and PulseSession.complete().
101
+ */
102
+ declare const MIN_AUDIO_SAMPLES = 16000;
103
+ declare const MIN_MOTION_SAMPLES = 10;
104
+ declare const MIN_TOUCH_SAMPLES = 10;
98
105
  /**
99
106
  * PulseSession — event-driven staged capture session.
100
107
  *
@@ -512,7 +519,7 @@ declare function attestAgentOperator(agentAsset: string, options: {
512
519
  /**
513
520
  * Query whether an AI agent has a verified human operator via Entros.
514
521
  *
515
- * Reads the "iam:human-operator" metadata from the agent's on-chain record
522
+ * Reads the "entros:human-operator" metadata from the agent's on-chain record
516
523
  * and returns the operator's Entros Anchor details.
517
524
  *
518
525
  * @param agentAsset - Base58 pubkey of the agent's Metaplex Core NFT
@@ -618,7 +625,7 @@ declare function generateLissajousSequence(count?: number): {
618
625
  * The executor's `/challenge` endpoint returns a fresh nonce + 5-word phrase
619
626
  * bound to the wallet for a short TTL (default 60s). The phrase is drawn from
620
627
  * a curated English-word dictionary (source of truth at
621
- * `iam-validation/src/word_dict.rs`); shown to the user as the voice challenge
628
+ * `entros-validation/src/word_dict.rs`); shown to the user as the voice challenge
622
629
  * and looked up server-side at `/validate-features` to verify the audio
623
630
  * matches the issued phrase (master-list #89, phrase content binding).
624
631
  *
@@ -668,4 +675,4 @@ declare function fetchChallenge(executorUrl: string, walletAddress: string, apiK
668
675
  */
669
676
  declare function encodeAudioAsBase64(samples: Float32Array): string;
670
677
 
671
- export { type AgentHumanOperator, type AudioCapture, type CaptureOptions, type CaptureStage, type ChallengeResponse, type CircuitInput, DEFAULT_CAPTURE_MS, DEFAULT_MIN_DISTANCE, DEFAULT_THRESHOLD, type EntrosAttestation, FINGERPRINT_BITS, type FeatureVector, type FusedFeatureVector, type IdentityState, type LissajousParams, MAX_CAPTURE_MS, MIN_CAPTURE_MS, type MotionSample, PROGRAM_IDS, type PackedFingerprint, type Point2D, type ProofResult, type PulseConfig, PulseSDK, PulseSession, SPEAKER_FEATURE_COUNT, type SensorData, type SolanaProof, type StageState, type StatsSummary, type StoredVerificationData, type SubmissionResult, type TBH, type TemporalFingerprint, type TouchSample, type VerificationResult, attestAgentOperator, autocorrelation, bigintToBytes32, computeCommitment, condense, encodeAudioAsBase64, entropy, extractAccelerationMagnitude, extractMotionFeatures, extractMouseDynamics, extractSpeakerFeatures, extractSpeakerFeaturesDetailed, extractTouchFeatures, fetchChallenge, fetchIdentityState, fuseFeatures, fuseRawFeatures, generateLissajousPoints, generateLissajousSequence, generatePhrase, generatePhraseSequence, generateProof, generateSalt, generateSolanaProof, generateTBH, getAgentHumanOperator, hammingDistance, kurtosis, loadVerificationData, mean, packBits, prepareCircuitInput, randomLissajousParams, serializeProof, simhash, skewness, storeVerificationData, submitResetViaWallet, submitViaRelayer, submitViaWallet, toBigEndian32, variance, verifyEntrosAttestation };
678
+ export { type AgentHumanOperator, type AudioCapture, type CaptureOptions, type CaptureStage, type ChallengeResponse, type CircuitInput, DEFAULT_CAPTURE_MS, DEFAULT_MIN_DISTANCE, DEFAULT_THRESHOLD, type EntrosAttestation, FINGERPRINT_BITS, type FeatureVector, type FusedFeatureVector, type IdentityState, type LissajousParams, MAX_CAPTURE_MS, MIN_AUDIO_SAMPLES, MIN_CAPTURE_MS, MIN_MOTION_SAMPLES, MIN_TOUCH_SAMPLES, type MotionSample, PROGRAM_IDS, type PackedFingerprint, type Point2D, type ProofResult, type PulseConfig, PulseSDK, PulseSession, SPEAKER_FEATURE_COUNT, type SensorData, type SolanaProof, type StageState, type StatsSummary, type StoredVerificationData, type SubmissionResult, type TBH, type TemporalFingerprint, type TouchSample, type VerificationResult, attestAgentOperator, autocorrelation, bigintToBytes32, computeCommitment, condense, encodeAudioAsBase64, entropy, extractAccelerationMagnitude, extractMotionFeatures, extractMouseDynamics, extractSpeakerFeatures, extractSpeakerFeaturesDetailed, extractTouchFeatures, fetchChallenge, fetchIdentityState, fuseFeatures, fuseRawFeatures, generateLissajousPoints, generateLissajousSequence, generatePhrase, generatePhraseSequence, generateProof, generateSalt, generateSolanaProof, generateTBH, getAgentHumanOperator, hammingDistance, kurtosis, loadVerificationData, mean, packBits, prepareCircuitInput, randomLissajousParams, serializeProof, simhash, skewness, storeVerificationData, submitResetViaWallet, submitViaRelayer, submitViaWallet, toBigEndian32, variance, verifyEntrosAttestation };
package/dist/index.d.ts CHANGED
@@ -95,6 +95,13 @@ interface VerificationResult {
95
95
  }
96
96
 
97
97
  type ResolvedConfig = Required<Pick<PulseConfig, "cluster" | "threshold">> & PulseConfig;
98
+ /**
99
+ * Shared pipeline: features → simhash → TBH → proof → submit.
100
+ * Used by both PulseSDK.verify() and PulseSession.complete().
101
+ */
102
+ declare const MIN_AUDIO_SAMPLES = 16000;
103
+ declare const MIN_MOTION_SAMPLES = 10;
104
+ declare const MIN_TOUCH_SAMPLES = 10;
98
105
  /**
99
106
  * PulseSession — event-driven staged capture session.
100
107
  *
@@ -512,7 +519,7 @@ declare function attestAgentOperator(agentAsset: string, options: {
512
519
  /**
513
520
  * Query whether an AI agent has a verified human operator via Entros.
514
521
  *
515
- * Reads the "iam:human-operator" metadata from the agent's on-chain record
522
+ * Reads the "entros:human-operator" metadata from the agent's on-chain record
516
523
  * and returns the operator's Entros Anchor details.
517
524
  *
518
525
  * @param agentAsset - Base58 pubkey of the agent's Metaplex Core NFT
@@ -618,7 +625,7 @@ declare function generateLissajousSequence(count?: number): {
618
625
  * The executor's `/challenge` endpoint returns a fresh nonce + 5-word phrase
619
626
  * bound to the wallet for a short TTL (default 60s). The phrase is drawn from
620
627
  * a curated English-word dictionary (source of truth at
621
- * `iam-validation/src/word_dict.rs`); shown to the user as the voice challenge
628
+ * `entros-validation/src/word_dict.rs`); shown to the user as the voice challenge
622
629
  * and looked up server-side at `/validate-features` to verify the audio
623
630
  * matches the issued phrase (master-list #89, phrase content binding).
624
631
  *
@@ -668,4 +675,4 @@ declare function fetchChallenge(executorUrl: string, walletAddress: string, apiK
668
675
  */
669
676
  declare function encodeAudioAsBase64(samples: Float32Array): string;
670
677
 
671
- export { type AgentHumanOperator, type AudioCapture, type CaptureOptions, type CaptureStage, type ChallengeResponse, type CircuitInput, DEFAULT_CAPTURE_MS, DEFAULT_MIN_DISTANCE, DEFAULT_THRESHOLD, type EntrosAttestation, FINGERPRINT_BITS, type FeatureVector, type FusedFeatureVector, type IdentityState, type LissajousParams, MAX_CAPTURE_MS, MIN_CAPTURE_MS, type MotionSample, PROGRAM_IDS, type PackedFingerprint, type Point2D, type ProofResult, type PulseConfig, PulseSDK, PulseSession, SPEAKER_FEATURE_COUNT, type SensorData, type SolanaProof, type StageState, type StatsSummary, type StoredVerificationData, type SubmissionResult, type TBH, type TemporalFingerprint, type TouchSample, type VerificationResult, attestAgentOperator, autocorrelation, bigintToBytes32, computeCommitment, condense, encodeAudioAsBase64, entropy, extractAccelerationMagnitude, extractMotionFeatures, extractMouseDynamics, extractSpeakerFeatures, extractSpeakerFeaturesDetailed, extractTouchFeatures, fetchChallenge, fetchIdentityState, fuseFeatures, fuseRawFeatures, generateLissajousPoints, generateLissajousSequence, generatePhrase, generatePhraseSequence, generateProof, generateSalt, generateSolanaProof, generateTBH, getAgentHumanOperator, hammingDistance, kurtosis, loadVerificationData, mean, packBits, prepareCircuitInput, randomLissajousParams, serializeProof, simhash, skewness, storeVerificationData, submitResetViaWallet, submitViaRelayer, submitViaWallet, toBigEndian32, variance, verifyEntrosAttestation };
678
+ export { type AgentHumanOperator, type AudioCapture, type CaptureOptions, type CaptureStage, type ChallengeResponse, type CircuitInput, DEFAULT_CAPTURE_MS, DEFAULT_MIN_DISTANCE, DEFAULT_THRESHOLD, type EntrosAttestation, FINGERPRINT_BITS, type FeatureVector, type FusedFeatureVector, type IdentityState, type LissajousParams, MAX_CAPTURE_MS, MIN_AUDIO_SAMPLES, MIN_CAPTURE_MS, MIN_MOTION_SAMPLES, MIN_TOUCH_SAMPLES, type MotionSample, PROGRAM_IDS, type PackedFingerprint, type Point2D, type ProofResult, type PulseConfig, PulseSDK, PulseSession, SPEAKER_FEATURE_COUNT, type SensorData, type SolanaProof, type StageState, type StatsSummary, type StoredVerificationData, type SubmissionResult, type TBH, type TemporalFingerprint, type TouchSample, type VerificationResult, attestAgentOperator, autocorrelation, bigintToBytes32, computeCommitment, condense, encodeAudioAsBase64, entropy, extractAccelerationMagnitude, extractMotionFeatures, extractMouseDynamics, extractSpeakerFeatures, extractSpeakerFeaturesDetailed, extractTouchFeatures, fetchChallenge, fetchIdentityState, fuseFeatures, fuseRawFeatures, generateLissajousPoints, generateLissajousSequence, generatePhrase, generatePhraseSequence, generateProof, generateSalt, generateSolanaProof, generateTBH, getAgentHumanOperator, hammingDistance, kurtosis, loadVerificationData, mean, packBits, prepareCircuitInput, randomLissajousParams, serializeProof, simhash, skewness, storeVerificationData, submitResetViaWallet, submitViaRelayer, submitViaWallet, toBigEndian32, variance, verifyEntrosAttestation };
package/dist/index.js CHANGED
@@ -35,7 +35,10 @@ __export(index_exports, {
35
35
  DEFAULT_THRESHOLD: () => DEFAULT_THRESHOLD,
36
36
  FINGERPRINT_BITS: () => FINGERPRINT_BITS,
37
37
  MAX_CAPTURE_MS: () => MAX_CAPTURE_MS,
38
+ MIN_AUDIO_SAMPLES: () => MIN_AUDIO_SAMPLES,
38
39
  MIN_CAPTURE_MS: () => MIN_CAPTURE_MS,
40
+ MIN_MOTION_SAMPLES: () => MIN_MOTION_SAMPLES,
41
+ MIN_TOUCH_SAMPLES: () => MIN_TOUCH_SAMPLES,
39
42
  PROGRAM_IDS: () => PROGRAM_IDS,
40
43
  PulseSDK: () => PulseSDK,
41
44
  PulseSession: () => PulseSession,
@@ -113,7 +116,7 @@ var PROGRAM_IDS = {
113
116
  var AGENT_REGISTRY_CONFIG = {
114
117
  programIdDevnet: "8oo4J9tBB3Hna1jRQ3rWvJjojqM5DYTDJo5cejUuJy3C",
115
118
  programIdMainnet: "8oo4dC4JvBLwy5tGgiH3WwK4B9PWxL9Z4XjA2jzkQMbQ",
116
- metadataKey: "iam:human-operator"
119
+ metadataKey: "entros:human-operator"
117
120
  };
118
121
  var SAS_CONFIG = {
119
122
  programId: "22zoJMtdu4tQc2PzL74ZUT7FrwgB1Udec8DdW4yw4BdG",
@@ -2403,6 +2406,116 @@ var PulseSession = class {
2403
2406
  );
2404
2407
  this.touchStageState = "skipped";
2405
2408
  }
2409
+ // --- Test hooks (internal builds only) ---
2410
+ /**
2411
+ * @internal Test-only. Primes the session with pre-captured sensor data,
2412
+ * bypassing browser capture APIs. Throws unless built with IAM_INTERNAL_TEST=1.
2413
+ * Stripped from the published .d.ts so npm consumers never see it. Used by the
2414
+ * red team harness to drive the real verification pipeline (extraction →
2415
+ * SimHash → TBH → proof → submit) against synthetic sensor data — never
2416
+ * available to npm consumers.
2417
+ */
2418
+ __injectSensorData(data) {
2419
+ if (true) {
2420
+ throw new Error(
2421
+ "PulseSession.__injectSensorData is only available in internal test builds. Set IAM_INTERNAL_TEST=1 when building pulse-sdk from source."
2422
+ );
2423
+ }
2424
+ const conflicts = [];
2425
+ if (this.audioStageState === "capturing") conflicts.push("audio");
2426
+ if (this.motionStageState === "capturing") conflicts.push("motion");
2427
+ if (this.touchStageState === "capturing") conflicts.push("touch");
2428
+ if (conflicts.length > 0) {
2429
+ throw new Error(
2430
+ `__injectSensorData: cannot inject while stages are capturing: ${conflicts.join(", ")}. Create a fresh session via sdk.createSession() and inject before any startAudio/startMotion/startTouch call.`
2431
+ );
2432
+ }
2433
+ if (!data.audio || data.audio.samples.length < MIN_AUDIO_SAMPLES) {
2434
+ throw new Error(
2435
+ `__injectSensorData: audio required, minimum ${MIN_AUDIO_SAMPLES} samples (got ${data.audio?.samples.length ?? 0}).`
2436
+ );
2437
+ }
2438
+ if (data.motion.length < MIN_MOTION_SAMPLES) {
2439
+ throw new Error(
2440
+ `__injectSensorData: motion required, minimum ${MIN_MOTION_SAMPLES} samples (got ${data.motion.length}).`
2441
+ );
2442
+ }
2443
+ if (data.touch.length < MIN_TOUCH_SAMPLES) {
2444
+ throw new Error(
2445
+ `__injectSensorData: touch required, minimum ${MIN_TOUCH_SAMPLES} samples (got ${data.touch.length}).`
2446
+ );
2447
+ }
2448
+ this.audioData = data.audio;
2449
+ this.motionData = data.motion;
2450
+ this.touchData = data.touch;
2451
+ this.audioStageState = "captured";
2452
+ this.motionStageState = "captured";
2453
+ this.touchStageState = "captured";
2454
+ }
2455
+ /**
2456
+ * @internal
2457
+ *
2458
+ * Run the validation step of the verify pipeline only: feature extraction
2459
+ * + `/validate-features` POST. Returns the validation outcome without ever
2460
+ * touching the on-chain submission path. Mirrors the production user
2461
+ * flow's pre-payment gate — the validation server runs without requiring
2462
+ * the wallet to have SOL, just like a real user gets a validation result
2463
+ * before being prompted to sign the on-chain mint.
2464
+ *
2465
+ * Note: this is a strict subset of `complete()`. It skips the data-quality
2466
+ * gates and re-verification check that `processSensorData` performs. The
2467
+ * validation server still runs its full pipeline (Tier 1 + Tier 2 +
2468
+ * phrase binding); only the client-side pre-flight checks differ.
2469
+ *
2470
+ * Use case: red team campaigns measuring server-side validation at scale
2471
+ * without per-attempt SOL funding. Build-time gated identically to
2472
+ * `__injectSensorData`; throws in production builds.
2473
+ */
2474
+ async __validateOnly(walletAddress) {
2475
+ if (true) {
2476
+ throw new Error(
2477
+ "PulseSession.__validateOnly is only available in internal test builds. Set IAM_INTERNAL_TEST=1 when building pulse-sdk from source."
2478
+ );
2479
+ }
2480
+ if (typeof walletAddress !== "string" || walletAddress.length === 0) {
2481
+ throw new Error(
2482
+ "__validateOnly requires a non-empty walletAddress string (used as wallet_id in the /validate-features payload)."
2483
+ );
2484
+ }
2485
+ const active = [];
2486
+ if (this.audioStageState === "capturing") active.push("audio");
2487
+ if (this.motionStageState === "capturing") active.push("motion");
2488
+ if (this.touchStageState === "capturing") active.push("touch");
2489
+ if (active.length > 0) {
2490
+ throw new Error(
2491
+ `Cannot validate: stages still capturing: ${active.join(", ")}`
2492
+ );
2493
+ }
2494
+ if (!this.audioData || this.motionData.length === 0 || this.touchData.length === 0) {
2495
+ throw new Error(
2496
+ "__validateOnly requires sensor data first \u2014 call __injectSensorData() before this."
2497
+ );
2498
+ }
2499
+ const sensorData = {
2500
+ audio: this.audioData,
2501
+ motion: this.motionData,
2502
+ touch: this.touchData,
2503
+ modalities: {
2504
+ audio: true,
2505
+ motion: true,
2506
+ touch: true
2507
+ }
2508
+ };
2509
+ const extraction = await extractFingerprintAndValidate(
2510
+ sensorData,
2511
+ this.config,
2512
+ walletAddress
2513
+ );
2514
+ if (!extraction.ok) {
2515
+ return { validated: false, error: extraction.error };
2516
+ }
2517
+ return { validated: true };
2518
+ }
2406
2519
  // --- Complete ---
2407
2520
  // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Solana types are optional peer deps
2408
2521
  async complete(wallet, connection, onProgress) {
@@ -3078,7 +3191,10 @@ async function fetchChallenge(executorUrl, walletAddress, apiKey) {
3078
3191
  DEFAULT_THRESHOLD,
3079
3192
  FINGERPRINT_BITS,
3080
3193
  MAX_CAPTURE_MS,
3194
+ MIN_AUDIO_SAMPLES,
3081
3195
  MIN_CAPTURE_MS,
3196
+ MIN_MOTION_SAMPLES,
3197
+ MIN_TOUCH_SAMPLES,
3082
3198
  PROGRAM_IDS,
3083
3199
  PulseSDK,
3084
3200
  PulseSession,