@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 +10 -3
- package/dist/index.d.ts +10 -3
- package/dist/index.js +117 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +114 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -1
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 "
|
|
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
|
-
* `
|
|
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 "
|
|
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
|
-
* `
|
|
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: "
|
|
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,
|