@validpay/node-sdk
Advanced tools
| import { type ValidPayClientOptions, type CreateIntentParams, type BatchIntentItem, type SelectiveIntentParams, type CreateIntentResult, type VerifyIntentResult, type RevocationResult, type RevocationEvent } from "./types.js"; | ||
| export declare class ValidPayClient { | ||
| private readonly apiKey; | ||
| private readonly baseUrl; | ||
| private readonly timeout; | ||
| private readonly fetchImpl; | ||
| constructor(options: ValidPayClientOptions); | ||
| createIntent(params: CreateIntentParams): Promise<CreateIntentResult>; | ||
| createIntentBatch(items: BatchIntentItem[]): Promise<CreateIntentResult[]>; | ||
| verifyIntent<T = unknown>(retrievalId: string, key: string): Promise<VerifyIntentResult<T>>; | ||
| createSplitKeyIntent(params: CreateIntentParams): Promise<CreateIntentResult>; | ||
| verifySplitKeyIntent<T = unknown>(retrievalId: string, shareA: string): Promise<VerifyIntentResult<T>>; | ||
| createSelectiveIntent(params: SelectiveIntentParams): Promise<CreateIntentResult>; | ||
| verifySelectiveIntent(retrievalId: string, key: string, role?: string): Promise<VerifyIntentResult<Record<string, unknown>>>; | ||
| revokeIntent(retrievalId: string, reason?: string): Promise<RevocationResult>; | ||
| reinstateIntent(retrievalId: string, reason?: string): Promise<RevocationResult>; | ||
| getRevocationHistory(retrievalId: string): Promise<RevocationEvent[]>; | ||
| health(): Promise<{ | ||
| status: string; | ||
| version?: string; | ||
| }>; | ||
| private request; | ||
| } | ||
| //# sourceMappingURL=client.d.ts.map |
| {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAWA,OAAO,EAEL,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EAEvB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EAMrB,MAAM,YAAY,CAAC;AAYpB,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;gBAE7B,OAAO,EAAE,qBAAqB;IAYpC,YAAY,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAgCrE,iBAAiB,CAAC,KAAK,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAoE1E,YAAY,CAAC,CAAC,GAAG,OAAO,EAC5B,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC;IAmE3B,oBAAoB,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAoC7E,oBAAoB,CAAC,CAAC,GAAG,OAAO,EACpC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC;IAiE3B,qBAAqB,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAyEjF,qBAAqB,CACzB,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,MAAM,EACX,IAAI,SAAS,GACZ,OAAO,CAAC,kBAAkB,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IA4GjD,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAoB7E,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAoBhF,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IAoBrE,MAAM,IAAI,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;YAQ/C,OAAO;CAgDtB"} |
+498
| import { generateKey, encrypt, decrypt, commitmentHash, splitKey as splitKeyFn, combineKeyShares, encryptFields, buildKeyMap, decryptFields, } from "./crypto.js"; | ||
| import { ValidPayError, } from "./types.js"; | ||
| const DEFAULT_BASE_URL = "https://api.validpay.io"; | ||
| const DEFAULT_TIMEOUT_MS = 30_000; | ||
| export class ValidPayClient { | ||
| apiKey; | ||
| baseUrl; | ||
| timeout; | ||
| fetchImpl; | ||
| constructor(options) { | ||
| if (!options.apiKey) { | ||
| throw new ValidPayError("invalid_config", "apiKey is required"); | ||
| } | ||
| this.apiKey = options.apiKey; | ||
| this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, ""); | ||
| this.timeout = options.timeout ?? DEFAULT_TIMEOUT_MS; | ||
| this.fetchImpl = options.fetch ?? fetch; | ||
| } | ||
| // === Core === | ||
| async createIntent(params) { | ||
| if (!params.documentType) { | ||
| throw new ValidPayError("invalid_argument", "documentType is required"); | ||
| } | ||
| validateTimeLock(params.validFrom, params.validUntil); | ||
| const key = generateKey(); | ||
| const plaintext = JSON.stringify(params.payload); | ||
| const encrypted_payload = encrypt(plaintext, key); | ||
| const commitment_hash = commitmentHash(plaintext); | ||
| const body = { | ||
| document_type: params.documentType, | ||
| encrypted_payload, | ||
| commitment_hash, | ||
| }; | ||
| if (params.validFrom !== undefined) | ||
| body["valid_from"] = params.validFrom; | ||
| if (params.validUntil !== undefined) | ||
| body["valid_until"] = params.validUntil; | ||
| const data = await this.request("POST", "/v1/intent", { | ||
| body, | ||
| auth: true, | ||
| }); | ||
| if (!data?.retrieval_id) { | ||
| throw new ValidPayError("invalid_response", "API response missing retrieval_id", { | ||
| details: data, | ||
| }); | ||
| } | ||
| return { retrievalId: data.retrieval_id, key }; | ||
| } | ||
| async createIntentBatch(items) { | ||
| if (!Array.isArray(items) || items.length === 0) { | ||
| throw new ValidPayError("invalid_argument", "items must contain at least 1 item"); | ||
| } | ||
| if (items.length > 100) { | ||
| throw new ValidPayError("invalid_argument", `items must contain at most 100 items (got ${items.length})`); | ||
| } | ||
| const keys = []; | ||
| const requestItems = []; | ||
| items.forEach((item, idx) => { | ||
| if (!item.documentType) { | ||
| throw new ValidPayError("invalid_argument", `items[${idx}].documentType is required`); | ||
| } | ||
| if (!("payload" in item)) { | ||
| throw new ValidPayError("invalid_argument", `items[${idx}].payload is required`); | ||
| } | ||
| try { | ||
| validateTimeLock(item.validFrom, item.validUntil); | ||
| } | ||
| catch (e) { | ||
| if (e instanceof ValidPayError) { | ||
| throw new ValidPayError("invalid_argument", `items[${idx}]: ${e.message}`); | ||
| } | ||
| throw e; | ||
| } | ||
| const k = generateKey(); | ||
| keys.push(k); | ||
| const plaintext = JSON.stringify(item.payload); | ||
| const req = { | ||
| document_type: item.documentType, | ||
| encrypted_payload: encrypt(plaintext, k), | ||
| commitment_hash: commitmentHash(plaintext), | ||
| }; | ||
| if (item.validFrom !== undefined) | ||
| req["valid_from"] = item.validFrom; | ||
| if (item.validUntil !== undefined) | ||
| req["valid_until"] = item.validUntil; | ||
| requestItems.push(req); | ||
| }); | ||
| const data = await this.request("POST", "/v1/intent/batch", { | ||
| body: { intents: requestItems }, | ||
| auth: true, | ||
| }); | ||
| if (!Array.isArray(data?.results) || data.results.length !== keys.length) { | ||
| throw new ValidPayError("invalid_response", "API response missing results array of expected length", { details: data }); | ||
| } | ||
| return data.results.map((row, i) => { | ||
| if (!row?.retrieval_id) { | ||
| throw new ValidPayError("invalid_response", `results[${i}] missing retrieval_id`, { | ||
| details: data, | ||
| }); | ||
| } | ||
| return { retrievalId: row.retrieval_id, key: keys[i] }; | ||
| }); | ||
| } | ||
| async verifyIntent(retrievalId, key) { | ||
| if (!retrievalId) { | ||
| throw new ValidPayError("invalid_argument", "retrievalId is required"); | ||
| } | ||
| if (!key) { | ||
| throw new ValidPayError("invalid_argument", "key is required"); | ||
| } | ||
| const data = await this.request("GET", `/v1/intent/${encodeURIComponent(retrievalId)}`, { auth: false }); | ||
| if (!data || typeof data !== "object") { | ||
| throw new ValidPayError("invalid_response", "API response missing intent body", { | ||
| details: data, | ||
| }); | ||
| } | ||
| if (data.status === "revoked" || !data.encrypted_payload) { | ||
| const reasonSuffix = data.revocation_reason ? `: ${data.revocation_reason}` : ""; | ||
| throw new ValidPayError("intent_revoked", `Intent ${retrievalId} has been revoked${reasonSuffix}`, { | ||
| details: { | ||
| intent_id: data.intent_id, | ||
| status: data.status, | ||
| revoked_at: data.revoked_at, | ||
| revocation_reason: data.revocation_reason, | ||
| }, | ||
| }); | ||
| } | ||
| if (data.selective_disclosure) { | ||
| throw new ValidPayError("selective_disclosure_required", "This intent uses selective field disclosure. Use verifySelectiveIntent(retrievalId, key, role) instead."); | ||
| } | ||
| if (data.split_key) { | ||
| throw new ValidPayError("split_key_required", `Intent ${retrievalId} uses split-key protection. Use verifySplitKeyIntent(retrievalId, shareA) instead.`); | ||
| } | ||
| const decrypted = decrypt(data.encrypted_payload, key); | ||
| const integrityVerified = checkCommitment(data.commitment_hash, decrypted); | ||
| let payload; | ||
| try { | ||
| payload = JSON.parse(decrypted); | ||
| } | ||
| catch (cause) { | ||
| throw new ValidPayError("invalid_payload", "Decrypted payload is not valid JSON", { | ||
| cause, | ||
| }); | ||
| } | ||
| return buildVerifyResult(data, payload, integrityVerified); | ||
| } | ||
| // === Split-key (Patent C) === | ||
| async createSplitKeyIntent(params) { | ||
| if (!params.documentType) { | ||
| throw new ValidPayError("invalid_argument", "documentType is required"); | ||
| } | ||
| validateTimeLock(params.validFrom, params.validUntil); | ||
| const fullKey = generateKey(); | ||
| const [shareA, shareB] = splitKeyFn(fullKey); | ||
| const plaintext = JSON.stringify(params.payload); | ||
| const encrypted_payload = encrypt(plaintext, fullKey); | ||
| const commitment_hash = commitmentHash(plaintext); | ||
| const body = { | ||
| document_type: params.documentType, | ||
| encrypted_payload, | ||
| commitment_hash, | ||
| split_key: true, | ||
| key_fragment_b: shareB, | ||
| }; | ||
| if (params.validFrom !== undefined) | ||
| body["valid_from"] = params.validFrom; | ||
| if (params.validUntil !== undefined) | ||
| body["valid_until"] = params.validUntil; | ||
| const data = await this.request("POST", "/v1/intent", { | ||
| body, | ||
| auth: true, | ||
| }); | ||
| if (!data?.retrieval_id) { | ||
| throw new ValidPayError("invalid_response", "API response missing retrieval_id", { | ||
| details: data, | ||
| }); | ||
| } | ||
| return { retrievalId: data.retrieval_id, key: shareA }; | ||
| } | ||
| async verifySplitKeyIntent(retrievalId, shareA) { | ||
| if (!retrievalId) { | ||
| throw new ValidPayError("invalid_argument", "retrievalId is required"); | ||
| } | ||
| if (!shareA) { | ||
| throw new ValidPayError("invalid_argument", "shareA is required"); | ||
| } | ||
| const data = await this.request("GET", `/v1/intent/${encodeURIComponent(retrievalId)}`, { auth: false }); | ||
| if (data.status === "revoked" || !data.encrypted_payload) { | ||
| const reasonSuffix = data.revocation_reason ? `: ${data.revocation_reason}` : ""; | ||
| throw new ValidPayError("intent_revoked", `Intent ${retrievalId} has been revoked${reasonSuffix}`, { | ||
| details: { | ||
| intent_id: data.intent_id, | ||
| status: data.status, | ||
| revoked_at: data.revoked_at, | ||
| revocation_reason: data.revocation_reason, | ||
| }, | ||
| }); | ||
| } | ||
| const frag = await this.request("GET", `/v1/intent/${encodeURIComponent(retrievalId)}/fragment`, { auth: false }); | ||
| if (frag?.error) { | ||
| throw new ValidPayError(frag.error, `Fragment retrieval failed: ${frag.error}`, { | ||
| details: frag, | ||
| }); | ||
| } | ||
| if (!frag?.fragment_b) { | ||
| throw new ValidPayError("missing_fragment", "Server did not return key fragment", { | ||
| details: frag, | ||
| }); | ||
| } | ||
| const fullKey = combineKeyShares(shareA, frag.fragment_b); | ||
| const decrypted = decrypt(data.encrypted_payload, fullKey); | ||
| const integrityVerified = checkCommitment(data.commitment_hash, decrypted); | ||
| let payload; | ||
| try { | ||
| payload = JSON.parse(decrypted); | ||
| } | ||
| catch (cause) { | ||
| throw new ValidPayError("invalid_payload", "Decrypted payload is not valid JSON", { | ||
| cause, | ||
| }); | ||
| } | ||
| return buildVerifyResult(data, payload, integrityVerified); | ||
| } | ||
| // === Selective disclosure (Patent E) === | ||
| async createSelectiveIntent(params) { | ||
| if (!params.documentType) { | ||
| throw new ValidPayError("invalid_argument", "documentType is required"); | ||
| } | ||
| if (!params.payload || Object.keys(params.payload).length === 0) { | ||
| throw new ValidPayError("invalid_argument", "payload must be a non-empty object"); | ||
| } | ||
| if (!params.disclosurePolicy || Object.keys(params.disclosurePolicy).length === 0) { | ||
| throw new ValidPayError("invalid_argument", "disclosurePolicy must be a non-empty object"); | ||
| } | ||
| validateTimeLock(params.validFrom, params.validUntil); | ||
| for (const [role, fields] of Object.entries(params.disclosurePolicy)) { | ||
| if (!Array.isArray(fields)) { | ||
| throw new ValidPayError("invalid_argument", `disclosurePolicy['${role}'] must be an array`); | ||
| } | ||
| for (const f of fields) { | ||
| if (!(f in params.payload)) { | ||
| throw new ValidPayError("invalid_argument", `Field '${f}' in role '${role}' not found in payload`); | ||
| } | ||
| } | ||
| } | ||
| const masterKey = generateKey(); | ||
| const { encryptedFields, fieldKeys } = encryptFields(params.payload); | ||
| const keyMap = buildKeyMap(fieldKeys, params.disclosurePolicy); | ||
| const encrypted_key_map = encrypt(JSON.stringify(keyMap), masterKey); | ||
| const fullPlaintext = JSON.stringify(params.payload); | ||
| const commitment_hash = commitmentHash(fullPlaintext); | ||
| let qrKey = masterKey; | ||
| let key_fragment_b; | ||
| if (params.splitKey) { | ||
| const [shareA, shareB] = splitKeyFn(masterKey); | ||
| qrKey = shareA; | ||
| key_fragment_b = shareB; | ||
| } | ||
| const body = { | ||
| document_type: params.documentType, | ||
| encrypted_payload: JSON.stringify(encryptedFields), | ||
| commitment_hash, | ||
| selective_disclosure: true, | ||
| disclosure_policy: JSON.stringify(params.disclosurePolicy), | ||
| encrypted_key_map, | ||
| split_key: !!params.splitKey, | ||
| }; | ||
| if (key_fragment_b !== undefined) | ||
| body["key_fragment_b"] = key_fragment_b; | ||
| if (params.validFrom !== undefined) | ||
| body["valid_from"] = params.validFrom; | ||
| if (params.validUntil !== undefined) | ||
| body["valid_until"] = params.validUntil; | ||
| const data = await this.request("POST", "/v1/intent", { | ||
| body, | ||
| auth: true, | ||
| }); | ||
| if (!data?.retrieval_id) { | ||
| throw new ValidPayError("invalid_response", "API response missing retrieval_id", { | ||
| details: data, | ||
| }); | ||
| } | ||
| return { retrievalId: data.retrieval_id, key: qrKey }; | ||
| } | ||
| async verifySelectiveIntent(retrievalId, key, role = "full") { | ||
| if (!retrievalId) { | ||
| throw new ValidPayError("invalid_argument", "retrievalId is required"); | ||
| } | ||
| if (!key) { | ||
| throw new ValidPayError("invalid_argument", "key is required"); | ||
| } | ||
| const data = await this.request("GET", `/v1/intent/${encodeURIComponent(retrievalId)}`, { auth: false }); | ||
| if (data.status === "revoked" || !data.encrypted_payload) { | ||
| const reasonSuffix = data.revocation_reason ? `: ${data.revocation_reason}` : ""; | ||
| throw new ValidPayError("intent_revoked", `Intent ${retrievalId} has been revoked${reasonSuffix}`, { | ||
| details: { | ||
| intent_id: data.intent_id, | ||
| status: data.status, | ||
| revoked_at: data.revoked_at, | ||
| revocation_reason: data.revocation_reason, | ||
| }, | ||
| }); | ||
| } | ||
| let masterKey = key; | ||
| if (data.split_key) { | ||
| const frag = await this.request("GET", `/v1/intent/${encodeURIComponent(retrievalId)}/fragment`, { auth: false }); | ||
| if (frag?.error) { | ||
| throw new ValidPayError(frag.error, `Fragment retrieval failed: ${frag.error}`, { | ||
| details: frag, | ||
| }); | ||
| } | ||
| if (!frag?.fragment_b) { | ||
| throw new ValidPayError("missing_fragment", "Server did not return key fragment", { | ||
| details: frag, | ||
| }); | ||
| } | ||
| masterKey = combineKeyShares(key, frag.fragment_b); | ||
| } | ||
| if (!data.encrypted_key_map) { | ||
| throw new ValidPayError("invalid_response", "Selective disclosure intent missing encrypted_key_map"); | ||
| } | ||
| const keyMapJson = decrypt(data.encrypted_key_map, masterKey); | ||
| let keyMap; | ||
| try { | ||
| keyMap = JSON.parse(keyMapJson); | ||
| } | ||
| catch (cause) { | ||
| throw new ValidPayError("invalid_payload", "Decrypted key map is not valid JSON", { | ||
| cause, | ||
| }); | ||
| } | ||
| if (!(role in keyMap)) { | ||
| const available = Object.keys(keyMap).sort().join(", "); | ||
| throw new ValidPayError("invalid_role", `Role '${role}' is not defined in this document's disclosure policy. Available roles: ${available}`); | ||
| } | ||
| const fieldKeys = keyMap[role]; | ||
| let encryptedFields; | ||
| try { | ||
| encryptedFields = JSON.parse(data.encrypted_payload); | ||
| } | ||
| catch (cause) { | ||
| throw new ValidPayError("invalid_payload", "Encrypted payload is not a valid JSON envelope", { cause }); | ||
| } | ||
| const payload = decryptFields(encryptedFields, fieldKeys); | ||
| let integrityVerified = false; | ||
| if (data.commitment_hash && role === "full") { | ||
| const allKeys = keyMap["full"] ?? {}; | ||
| const fullPayload = decryptFields(encryptedFields, allKeys); | ||
| const actual = commitmentHash(JSON.stringify(fullPayload)); | ||
| if (actual !== data.commitment_hash) { | ||
| throw new ValidPayError("integrity_failure", "INTEGRITY VERIFICATION FAILED — the decrypted payload does not match the commitment hash stored at issuance."); | ||
| } | ||
| integrityVerified = true; | ||
| } | ||
| return buildVerifyResult(data, payload, integrityVerified); | ||
| } | ||
| // === Revocation (Patent H) === | ||
| async revokeIntent(retrievalId, reason) { | ||
| if (!retrievalId) { | ||
| throw new ValidPayError("invalid_argument", "retrievalId is required"); | ||
| } | ||
| const data = await this.request("PATCH", `/v1/intent/${encodeURIComponent(retrievalId)}/revoke`, { body: reason ? { reason } : {}, auth: true }); | ||
| return { | ||
| intentId: data?.intent_id ?? retrievalId, | ||
| status: data?.status ?? "revoked", | ||
| revokedAt: data?.revoked_at, | ||
| }; | ||
| } | ||
| async reinstateIntent(retrievalId, reason) { | ||
| if (!retrievalId) { | ||
| throw new ValidPayError("invalid_argument", "retrievalId is required"); | ||
| } | ||
| const data = await this.request("PATCH", `/v1/intent/${encodeURIComponent(retrievalId)}/reinstate`, { body: reason ? { reason } : {}, auth: true }); | ||
| return { | ||
| intentId: data?.intent_id ?? retrievalId, | ||
| status: data?.status ?? "active", | ||
| reinstatedAt: data?.reinstated_at, | ||
| }; | ||
| } | ||
| async getRevocationHistory(retrievalId) { | ||
| if (!retrievalId) { | ||
| throw new ValidPayError("invalid_argument", "retrievalId is required"); | ||
| } | ||
| const data = await this.request("GET", `/v1/intent/${encodeURIComponent(retrievalId)}/revocations`, { auth: true }); | ||
| if (!Array.isArray(data?.events)) | ||
| return []; | ||
| return data.events.map((e) => ({ | ||
| id: e.id, | ||
| action: e.action, | ||
| reason: e.reason, | ||
| performedAt: e.performed_at, | ||
| })); | ||
| } | ||
| // === Health === | ||
| async health() { | ||
| return this.request("GET", "/health", { | ||
| auth: false, | ||
| }); | ||
| } | ||
| // === HTTP === | ||
| async request(method, path, opts) { | ||
| const url = `${this.baseUrl}${path}`; | ||
| const headers = { Accept: "application/json" }; | ||
| if (opts.auth) | ||
| headers["Authorization"] = `Bearer ${this.apiKey}`; | ||
| if (opts.body !== undefined) | ||
| headers["Content-Type"] = "application/json"; | ||
| const controller = new AbortController(); | ||
| const timer = setTimeout(() => controller.abort(), this.timeout); | ||
| let response; | ||
| try { | ||
| response = await this.fetchImpl(url, { | ||
| method, | ||
| headers, | ||
| body: opts.body !== undefined ? JSON.stringify(opts.body) : undefined, | ||
| signal: controller.signal, | ||
| }); | ||
| } | ||
| catch (cause) { | ||
| throw new ValidPayError("network_error", `Request to ${url} failed`, { cause }); | ||
| } | ||
| finally { | ||
| clearTimeout(timer); | ||
| } | ||
| const text = await response.text(); | ||
| let json = undefined; | ||
| if (text) { | ||
| try { | ||
| json = JSON.parse(text); | ||
| } | ||
| catch { | ||
| // leave undefined | ||
| } | ||
| } | ||
| if (!response.ok) { | ||
| const errBody = (json ?? text); | ||
| const code = typeof errBody === "object" && errBody && typeof errBody.error === "string" | ||
| ? errBody.error | ||
| : "http_error"; | ||
| throw new ValidPayError(code, `ValidPay API ${method} ${path} failed: ${response.status}`, { status: response.status, details: errBody }); | ||
| } | ||
| return json; | ||
| } | ||
| } | ||
| // === Helpers === | ||
| function checkCommitment(expected, plaintext) { | ||
| if (!expected) | ||
| return false; | ||
| const actual = commitmentHash(plaintext); | ||
| if (actual !== expected) { | ||
| throw new ValidPayError("integrity_failure", "INTEGRITY VERIFICATION FAILED — the decrypted payload does not match the commitment hash stored at issuance."); | ||
| } | ||
| return true; | ||
| } | ||
| function computeTimeLockStatus(validFrom, validUntil) { | ||
| if (!validFrom && !validUntil) | ||
| return null; | ||
| const now = Date.now(); | ||
| if (validFrom) { | ||
| const t = Date.parse(validFrom); | ||
| if (!Number.isNaN(t) && now < t) | ||
| return "not_yet_valid"; | ||
| } | ||
| if (validUntil) { | ||
| const t = Date.parse(validUntil); | ||
| if (!Number.isNaN(t) && now > t) | ||
| return "expired"; | ||
| } | ||
| return "valid"; | ||
| } | ||
| function validateTimeLock(validFrom, validUntil) { | ||
| if (validFrom !== undefined && Number.isNaN(Date.parse(validFrom))) { | ||
| throw new ValidPayError("invalid_argument", `validFrom is not a valid ISO-8601: ${validFrom}`); | ||
| } | ||
| if (validUntil !== undefined && Number.isNaN(Date.parse(validUntil))) { | ||
| throw new ValidPayError("invalid_argument", `validUntil is not a valid ISO-8601: ${validUntil}`); | ||
| } | ||
| if (validFrom !== undefined && validUntil !== undefined) { | ||
| if (Date.parse(validFrom) >= Date.parse(validUntil)) { | ||
| throw new ValidPayError("invalid_argument", "validFrom must be before validUntil"); | ||
| } | ||
| } | ||
| } | ||
| function buildVerifyResult(data, payload, integrityVerified) { | ||
| return { | ||
| intentId: data.intent_id, | ||
| payload, | ||
| issuer: data.issuer, | ||
| issuerVerified: data.issuer_verified, | ||
| registeredAt: data.registered_at, | ||
| status: data.status, | ||
| integrityVerified, | ||
| validFrom: data.valid_from ?? null, | ||
| validUntil: data.valid_until ?? null, | ||
| timeLockStatus: computeTimeLockStatus(data.valid_from, data.valid_until), | ||
| }; | ||
| } | ||
| //# sourceMappingURL=client.js.map |
| {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"} |
| /** | ||
| * Wire format (matches the Python SDK so blobs are interoperable): | ||
| * base64(iv[12] || authTag[16] || ciphertext) | ||
| */ | ||
| export declare function generateKey(): string; | ||
| export declare function encrypt(plaintext: string, key: string): string; | ||
| export declare function decrypt(blob: string, key: string): string; | ||
| export declare function commitmentHash(plaintext: string): string; | ||
| export declare function splitKey(key: string): [string, string]; | ||
| export declare function combineKeyShares(shareA: string, shareB: string): string; | ||
| /** Encrypt each field of payload with its own AES key (Selective Disclosure). */ | ||
| export declare function encryptFields(payload: Record<string, unknown>): { | ||
| encryptedFields: Record<string, string>; | ||
| fieldKeys: Record<string, string>; | ||
| }; | ||
| /** Build per-role key map; "full" role always added with all keys. */ | ||
| export declare function buildKeyMap(fieldKeys: Record<string, string>, disclosurePolicy: Record<string, string[]>): Record<string, Record<string, string>>; | ||
| /** Decrypt only fields with keys; others become "[REDACTED]". */ | ||
| export declare function decryptFields(encryptedFields: Record<string, string>, fieldKeys: Record<string, string>): Record<string, unknown>; | ||
| //# sourceMappingURL=crypto.d.ts.map |
| {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"AAQA;;;GAGG;AAEH,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAkBD,wBAAgB,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAO9D;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAkCzD;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAQtD;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAQvE;AAED,iFAAiF;AACjF,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B;IAAE,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAUhF;AAED,sEAAsE;AACtE,wBAAgB,WAAW,CACzB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACjC,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GACzC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAWxC;AAED,iEAAiE;AACjE,wBAAgB,aAAa,CAC3B,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACvC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAChC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAezB"} |
+126
| import { randomBytes, createCipheriv, createDecipheriv, createHash } from "node:crypto"; | ||
| import { ValidPayError } from "./types.js"; | ||
| const ALGORITHM = "aes-256-gcm"; | ||
| const KEY_BYTES = 32; | ||
| const IV_BYTES = 12; | ||
| const TAG_BYTES = 16; | ||
| /** | ||
| * Wire format (matches the Python SDK so blobs are interoperable): | ||
| * base64(iv[12] || authTag[16] || ciphertext) | ||
| */ | ||
| export function generateKey() { | ||
| return randomBytes(KEY_BYTES).toString("base64"); | ||
| } | ||
| function decodeKey(key) { | ||
| let buf; | ||
| try { | ||
| buf = Buffer.from(key, "base64"); | ||
| } | ||
| catch (cause) { | ||
| throw new ValidPayError("invalid_key", "Key is not valid base64", { cause }); | ||
| } | ||
| if (buf.length !== KEY_BYTES) { | ||
| throw new ValidPayError("invalid_key", `Key must decode to ${KEY_BYTES} bytes (got ${buf.length})`); | ||
| } | ||
| return buf; | ||
| } | ||
| export function encrypt(plaintext, key) { | ||
| const keyBuf = decodeKey(key); | ||
| const iv = randomBytes(IV_BYTES); | ||
| const cipher = createCipheriv(ALGORITHM, keyBuf, iv); | ||
| const ciphertext = Buffer.concat([cipher.update(plaintext, "utf8"), cipher.final()]); | ||
| const authTag = cipher.getAuthTag(); | ||
| return Buffer.concat([iv, authTag, ciphertext]).toString("base64"); | ||
| } | ||
| export function decrypt(blob, key) { | ||
| const keyBuf = decodeKey(key); | ||
| let buf; | ||
| try { | ||
| buf = Buffer.from(blob, "base64"); | ||
| } | ||
| catch (cause) { | ||
| throw new ValidPayError("invalid_blob", "Blob is not valid base64", { cause }); | ||
| } | ||
| if (buf.length < IV_BYTES + TAG_BYTES + 1) { | ||
| throw new ValidPayError("invalid_blob", `Blob too short: expected at least ${IV_BYTES + TAG_BYTES + 1} bytes`); | ||
| } | ||
| const iv = buf.subarray(0, IV_BYTES); | ||
| const authTag = buf.subarray(IV_BYTES, IV_BYTES + TAG_BYTES); | ||
| const ciphertext = buf.subarray(IV_BYTES + TAG_BYTES); | ||
| const decipher = createDecipheriv(ALGORITHM, keyBuf, iv); | ||
| decipher.setAuthTag(authTag); | ||
| try { | ||
| const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]); | ||
| return plaintext.toString("utf8"); | ||
| } | ||
| catch (cause) { | ||
| throw new ValidPayError("decryption_failed", "Decryption failed — wrong key or tampered blob", { cause }); | ||
| } | ||
| } | ||
| export function commitmentHash(plaintext) { | ||
| return createHash("sha256").update(plaintext, "utf8").digest("hex"); | ||
| } | ||
| export function splitKey(key) { | ||
| const keyBuf = decodeKey(key); | ||
| const shareA = randomBytes(KEY_BYTES); | ||
| const shareB = Buffer.alloc(KEY_BYTES); | ||
| for (let i = 0; i < KEY_BYTES; i++) { | ||
| shareB[i] = keyBuf[i] ^ shareA[i]; | ||
| } | ||
| return [shareA.toString("base64"), shareB.toString("base64")]; | ||
| } | ||
| export function combineKeyShares(shareA, shareB) { | ||
| const a = decodeKey(shareA); | ||
| const b = decodeKey(shareB); | ||
| const combined = Buffer.alloc(KEY_BYTES); | ||
| for (let i = 0; i < KEY_BYTES; i++) { | ||
| combined[i] = a[i] ^ b[i]; | ||
| } | ||
| return combined.toString("base64"); | ||
| } | ||
| /** Encrypt each field of payload with its own AES key (Selective Disclosure). */ | ||
| export function encryptFields(payload) { | ||
| const encryptedFields = {}; | ||
| const fieldKeys = {}; | ||
| for (const [name, value] of Object.entries(payload)) { | ||
| const k = generateKey(); | ||
| const plaintext = typeof value === "string" ? value : JSON.stringify(value); | ||
| encryptedFields[name] = encrypt(plaintext, k); | ||
| fieldKeys[name] = k; | ||
| } | ||
| return { encryptedFields, fieldKeys }; | ||
| } | ||
| /** Build per-role key map; "full" role always added with all keys. */ | ||
| export function buildKeyMap(fieldKeys, disclosurePolicy) { | ||
| const map = {}; | ||
| for (const [role, fields] of Object.entries(disclosurePolicy)) { | ||
| const roleKeys = {}; | ||
| for (const f of fields) { | ||
| if (fieldKeys[f] !== undefined) | ||
| roleKeys[f] = fieldKeys[f]; | ||
| } | ||
| map[role] = roleKeys; | ||
| } | ||
| map["full"] = { ...fieldKeys }; | ||
| return map; | ||
| } | ||
| /** Decrypt only fields with keys; others become "[REDACTED]". */ | ||
| export function decryptFields(encryptedFields, fieldKeys) { | ||
| const out = {}; | ||
| for (const [name, blob] of Object.entries(encryptedFields)) { | ||
| if (fieldKeys[name] !== undefined) { | ||
| const plaintext = decrypt(blob, fieldKeys[name]); | ||
| try { | ||
| out[name] = JSON.parse(plaintext); | ||
| } | ||
| catch { | ||
| out[name] = plaintext; | ||
| } | ||
| } | ||
| else { | ||
| out[name] = "[REDACTED]"; | ||
| } | ||
| } | ||
| return out; | ||
| } | ||
| //# sourceMappingURL=crypto.js.map |
| {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACxF,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,MAAM,SAAS,GAAG,aAAa,CAAC;AAChC,MAAM,SAAS,GAAG,EAAE,CAAC;AACrB,MAAM,QAAQ,GAAG,EAAE,CAAC;AACpB,MAAM,SAAS,GAAG,EAAE,CAAC;AAErB;;;GAGG;AAEH,MAAM,UAAU,WAAW;IACzB,OAAO,WAAW,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACnD,CAAC;AAED,SAAS,SAAS,CAAC,GAAW;IAC5B,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IACnC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,aAAa,CAAC,aAAa,EAAE,yBAAyB,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/E,CAAC;IACD,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC7B,MAAM,IAAI,aAAa,CACrB,aAAa,EACb,sBAAsB,SAAS,eAAe,GAAG,CAAC,MAAM,GAAG,CAC5D,CAAC;IACJ,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,SAAiB,EAAE,GAAW;IACpD,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;IAC9B,MAAM,EAAE,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;IACjC,MAAM,MAAM,GAAG,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;IACrD,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACrF,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;IACpC,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,IAAY,EAAE,GAAW;IAC/C,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;IAE9B,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,aAAa,CAAC,cAAc,EAAE,0BAA0B,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IACjF,CAAC;IAED,IAAI,GAAG,CAAC,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,aAAa,CACrB,cAAc,EACd,qCAAqC,QAAQ,GAAG,SAAS,GAAG,CAAC,QAAQ,CACtE,CAAC;IACJ,CAAC;IAED,MAAM,EAAE,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;IACrC,MAAM,OAAO,GAAG,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,SAAS,CAAC,CAAC;IAC7D,MAAM,UAAU,GAAG,GAAG,CAAC,QAAQ,CAAC,QAAQ,GAAG,SAAS,CAAC,CAAC;IAEtD,MAAM,QAAQ,GAAG,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;IACzD,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;IAE7B,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QACjF,OAAO,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,aAAa,CACrB,mBAAmB,EACnB,gDAAgD,EAChD,EAAE,KAAK,EAAE,CACV,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,SAAiB;IAC9C,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACtE,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,GAAW;IAClC,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;IAC9B,MAAM,MAAM,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC;IACtC,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACvC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,EAAE,CAAC,EAAE,EAAE,CAAC;QACnC,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAE,GAAG,MAAM,CAAC,CAAC,CAAE,CAAC;IACtC,CAAC;IACD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAc,EAAE,MAAc;IAC7D,MAAM,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;IAC5B,MAAM,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;IAC5B,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACzC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,EAAE,CAAC,EAAE,EAAE,CAAC;QACnC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC;IAC9B,CAAC;IACD,OAAO,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACrC,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,aAAa,CAC3B,OAAgC;IAEhC,MAAM,eAAe,GAA2B,EAAE,CAAC;IACnD,MAAM,SAAS,GAA2B,EAAE,CAAC;IAC7C,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACpD,MAAM,CAAC,GAAG,WAAW,EAAE,CAAC;QACxB,MAAM,SAAS,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAC5E,eAAe,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;QAC9C,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACtB,CAAC;IACD,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,CAAC;AACxC,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,WAAW,CACzB,SAAiC,EACjC,gBAA0C;IAE1C,MAAM,GAAG,GAA2C,EAAE,CAAC;IACvD,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAC9D,MAAM,QAAQ,GAA2B,EAAE,CAAC;QAC5C,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;YACvB,IAAI,SAAS,CAAC,CAAC,CAAC,KAAK,SAAS;gBAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;QAC7D,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC;IACvB,CAAC;IACD,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,SAAS,EAAE,CAAC;IAC/B,OAAO,GAAG,CAAC;AACb,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,aAAa,CAC3B,eAAuC,EACvC,SAAiC;IAEjC,MAAM,GAAG,GAA4B,EAAE,CAAC;IACxC,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,CAAC;QAC3D,IAAI,SAAS,CAAC,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;YAClC,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;YACjD,IAAI,CAAC;gBACH,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;YACpC,CAAC;YAAC,MAAM,CAAC;gBACP,GAAG,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC;YACxB,CAAC;QACH,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC;QAC3B,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"} |
| {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EACL,WAAW,EACX,OAAO,EACP,OAAO,EACP,cAAc,EACd,QAAQ,EACR,gBAAgB,EAChB,aAAa,EACb,WAAW,EACX,aAAa,GACd,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,aAAa,EACb,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,uBAAuB,GAC7B,MAAM,YAAY,CAAC"} |
| {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EACL,WAAW,EACX,OAAO,EACP,OAAO,EACP,cAAc,EACd,QAAQ,EACR,gBAAgB,EAChB,aAAa,EACb,WAAW,EACX,aAAa,GACd,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,aAAa,GAYd,MAAM,YAAY,CAAC"} |
+104
| export interface ValidPayClientOptions { | ||
| apiKey: string; | ||
| baseUrl?: string; | ||
| timeout?: number; | ||
| fetch?: typeof fetch; | ||
| } | ||
| export interface CreateIntentParams { | ||
| documentType: string; | ||
| payload: unknown; | ||
| validFrom?: string; | ||
| validUntil?: string; | ||
| } | ||
| export interface BatchIntentItem { | ||
| documentType: string; | ||
| payload: unknown; | ||
| validFrom?: string; | ||
| validUntil?: string; | ||
| } | ||
| export interface SelectiveIntentParams { | ||
| documentType: string; | ||
| payload: Record<string, unknown>; | ||
| disclosurePolicy: Record<string, string[]>; | ||
| splitKey?: boolean; | ||
| validFrom?: string; | ||
| validUntil?: string; | ||
| } | ||
| export interface CreateIntentResult { | ||
| retrievalId: string; | ||
| key: string; | ||
| } | ||
| export type TimeLockStatus = "valid" | "not_yet_valid" | "expired"; | ||
| export interface VerifyIntentResult<T = unknown> { | ||
| intentId: string; | ||
| payload: T; | ||
| issuer: string; | ||
| issuerVerified: boolean; | ||
| registeredAt: string; | ||
| status: string; | ||
| integrityVerified: boolean; | ||
| validFrom?: string | null; | ||
| validUntil?: string | null; | ||
| timeLockStatus?: TimeLockStatus | null; | ||
| } | ||
| export interface RevocationResult { | ||
| intentId: string; | ||
| status: string; | ||
| revokedAt?: string; | ||
| reinstatedAt?: string; | ||
| } | ||
| export interface RevocationEvent { | ||
| id: string; | ||
| action: "revoked" | "reinstated"; | ||
| reason?: string; | ||
| performedAt: string; | ||
| } | ||
| export interface RawIntentResponse { | ||
| intent_id: string; | ||
| encrypted_payload: string | null; | ||
| issuer: string; | ||
| issuer_verified: boolean; | ||
| registered_at: string; | ||
| status: string; | ||
| commitment_hash?: string; | ||
| valid_from?: string | null; | ||
| valid_until?: string | null; | ||
| selective_disclosure?: boolean; | ||
| encrypted_key_map?: string; | ||
| split_key?: boolean; | ||
| revocation_reason?: string; | ||
| revoked_at?: string; | ||
| } | ||
| export interface RawCreateIntentResponse { | ||
| retrieval_id: string; | ||
| status: string; | ||
| } | ||
| export interface RawBatchCreateResponse { | ||
| results: Array<{ | ||
| retrieval_id: string; | ||
| status?: string; | ||
| }>; | ||
| } | ||
| export interface RawFragmentResponse { | ||
| fragment_b?: string; | ||
| error?: string; | ||
| } | ||
| export interface RawRevocationHistoryResponse { | ||
| events?: Array<{ | ||
| id: string; | ||
| action: "revoked" | "reinstated"; | ||
| reason?: string; | ||
| performed_at: string; | ||
| }>; | ||
| } | ||
| export declare class ValidPayError extends Error { | ||
| readonly code: string; | ||
| readonly status?: number; | ||
| readonly details?: unknown; | ||
| constructor(code: string, message: string, options?: { | ||
| status?: number; | ||
| details?: unknown; | ||
| cause?: unknown; | ||
| }); | ||
| } | ||
| //# sourceMappingURL=types.d.ts.map |
| {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"} |
| export class ValidPayError extends Error { | ||
| code; | ||
| status; | ||
| details; | ||
| constructor(code, message, options = {}) { | ||
| super(message, options.cause !== undefined ? { cause: options.cause } : undefined); | ||
| this.name = "ValidPayError"; | ||
| this.code = code; | ||
| this.status = options.status; | ||
| this.details = options.details; | ||
| } | ||
| } | ||
| //# sourceMappingURL=types.js.map |
| {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAwGA,MAAM,OAAO,aAAc,SAAQ,KAAK;IAC7B,IAAI,CAAS;IACb,MAAM,CAAU;IAChB,OAAO,CAAW;IAE3B,YACE,IAAY,EACZ,OAAe,EACf,UAAmE,EAAE;QAErE,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QACnF,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;QAC5B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAC7B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IACjC,CAAC;CACF"} |
+21
| MIT License | ||
| Copyright (c) 2026 ValidPay | ||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| of this software and associated documentation files (the "Software"), to deal | ||
| in the Software without restriction, including without limitation the rights | ||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| copies of the Software, and to permit persons to whom the Software is | ||
| furnished to do so, subject to the following conditions: | ||
| The above copyright notice and this permission notice shall be included in all | ||
| copies or substantial portions of the Software. | ||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| SOFTWARE. |
+4
-24
@@ -1,24 +0,4 @@ | ||
| export interface ValidPayClientOptions { | ||
| apiKey: string; | ||
| baseUrl?: string; | ||
| } | ||
| export interface CreateIntentParams { | ||
| documentType: 'check' | 'invoice' | 'receipt' | 'document'; | ||
| payload: Record<string, unknown>; | ||
| } | ||
| export interface Intent { | ||
| id: string; | ||
| verifyUrl: string; | ||
| createdAt: string; | ||
| expiresAt: string; | ||
| } | ||
| export declare class ValidPayClient { | ||
| constructor(options: ValidPayClientOptions); | ||
| createIntent(params: CreateIntentParams): Promise<Intent>; | ||
| getIntent(id: string): Promise<Intent>; | ||
| } | ||
| export default ValidPayClient; | ||
| export { ValidPayClient } from "./client.js"; | ||
| export { generateKey, encrypt, decrypt, commitmentHash, splitKey, combineKeyShares, encryptFields, buildKeyMap, decryptFields, } from "./crypto.js"; | ||
| export { ValidPayError, type ValidPayClientOptions, type CreateIntentParams, type BatchIntentItem, type SelectiveIntentParams, type CreateIntentResult, type VerifyIntentResult, type TimeLockStatus, type RevocationResult, type RevocationEvent, type RawIntentResponse, type RawCreateIntentResponse, } from "./types.js"; | ||
| //# sourceMappingURL=index.d.ts.map |
+4
-33
@@ -1,33 +0,4 @@ | ||
| /** | ||
| * @validpay/node-sdk | ||
| * Official Node.js SDK for the ValidPay document verification API. | ||
| * | ||
| * Status: Private Beta — Contact mike@validpay.io for API access. | ||
| * Docs: https://validpay.io/docs | ||
| */ | ||
| export class ValidPayClient { | ||
| constructor(options = {}) { | ||
| if (!options.apiKey) { | ||
| throw new Error( | ||
| 'ValidPay: API key required. Get yours at https://validpay.io' | ||
| ); | ||
| } | ||
| this.apiKey = options.apiKey; | ||
| this.baseUrl = options.baseUrl || 'https://api.validpay.io'; | ||
| } | ||
| async createIntent(params) { | ||
| throw new Error( | ||
| 'ValidPay SDK is in private beta. Contact mike@validpay.io for access.' | ||
| ); | ||
| } | ||
| async getIntent(id) { | ||
| throw new Error( | ||
| 'ValidPay SDK is in private beta. Contact mike@validpay.io for access.' | ||
| ); | ||
| } | ||
| } | ||
| export default ValidPayClient; | ||
| export { ValidPayClient } from "./client.js"; | ||
| export { generateKey, encrypt, decrypt, commitmentHash, splitKey, combineKeyShares, encryptFields, buildKeyMap, decryptFields, } from "./crypto.js"; | ||
| export { ValidPayError, } from "./types.js"; | ||
| //# sourceMappingURL=index.js.map |
+43
-14
| { | ||
| "name": "@validpay/node-sdk", | ||
| "version": "0.1.0", | ||
| "description": "ValidPay Node.js SDK — Document verification and authentication API client", | ||
| "main": "dist/index.js", | ||
| "types": "dist/index.d.ts", | ||
| "version": "0.2.0", | ||
| "description": "Official ValidPay Node.js SDK — client-side AES-256-GCM encryption + commitment hashing + split-key + selective disclosure + revocation. Zero production dependencies.", | ||
| "type": "module", | ||
| "main": "./dist/index.js", | ||
| "types": "./dist/index.d.ts", | ||
| "exports": { | ||
| ".": { | ||
| "import": "./dist/index.js", | ||
| "types": "./dist/index.d.ts" | ||
| "types": "./dist/index.d.ts", | ||
| "import": "./dist/index.js" | ||
| } | ||
| }, | ||
| "files": ["dist", "README.md"], | ||
| "keywords": ["validpay", "document-verification", "authentication", "check-verification", "anti-fraud", "encryption"], | ||
| "author": "MiLu Technologies LLC <mike@validpay.io>", | ||
| "license": "MIT", | ||
| "homepage": "https://validpay.io", | ||
| "files": [ | ||
| "dist", | ||
| "README.md", | ||
| "LICENSE" | ||
| ], | ||
| "scripts": { | ||
| "build": "tsc -p tsconfig.build.json", | ||
| "test": "vitest run", | ||
| "test:watch": "vitest", | ||
| "typecheck": "tsc --noEmit", | ||
| "prepublishOnly": "npm run build" | ||
| }, | ||
| "engines": { | ||
| "node": ">=20" | ||
| }, | ||
| "keywords": [ | ||
| "validpay", | ||
| "encryption", | ||
| "aes-256-gcm", | ||
| "document-verification", | ||
| "check-fraud", | ||
| "authentication", | ||
| "selective-disclosure", | ||
| "split-key", | ||
| "blind-escrow" | ||
| ], | ||
| "homepage": "https://github.com/ValidPay-io/validpay-node-sdk", | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "https://github.com/ValidPay-io/validpay-node-sdk" | ||
| "url": "git+https://github.com/ValidPay-io/validpay-node-sdk.git" | ||
| }, | ||
| "engines": { | ||
| "node": ">=20.0.0" | ||
| "bugs": { | ||
| "url": "https://github.com/ValidPay-io/validpay-node-sdk/issues" | ||
| }, | ||
| "license": "MIT", | ||
| "author": "ValidPay", | ||
| "devDependencies": { | ||
| "@types/node": "^20.11.0", | ||
| "typescript": "^5.4.0", | ||
| "vitest": "^1.6.0" | ||
| } | ||
| } |
+189
-27
| # @validpay/node-sdk | ||
| Official Node.js SDK for the [ValidPay](https://validpay.io) document verification API. | ||
| Official Node.js SDK for [ValidPay](https://validpay.io) — document verification API with **client-side AES-256-GCM encryption**. Sensitive payloads are encrypted on your server before they ever leave the box; ValidPay stores the ciphertext, and only your verifier (with the key you hand them) can read the contents. | ||
| ## Overview | ||
| - **Zero production dependencies** — Node.js built-in `crypto` + native `fetch` only | ||
| - **AES-256-GCM** authenticated encryption (tampering is detected on decrypt) | ||
| - **Hybrid commitment scheme** — SHA-256 commitment hash detects server-side tampering | ||
| - **Split-key verification** (Patent C) — XOR-share the key so neither party alone can decrypt | ||
| - **Selective field disclosure** (Patent E) — encrypt fields independently, gate per role | ||
| - **Blind revocation** (Patent H) — revoke / reinstate / inspect audit history | ||
| - **Time-locked verification** (Patent D) — validFrom / validUntil windows | ||
| - **TypeScript-first**, ESM-only, requires Node `>= 20` | ||
| - The encryption key is **never** sent to the ValidPay API | ||
| ValidPay provides cryptographic document verification infrastructure. This SDK enables issuers (banks, fintechs, check printers) to create tamper-proof verification intents and allows verifiers to authenticate documents in real-time. | ||
| ## Install | ||
| ## Installation | ||
| ```bash | ||
@@ -15,39 +21,195 @@ npm install @validpay/node-sdk | ||
| ## Quick Start | ||
| ## Quick start | ||
| ```typescript | ||
| import { ValidPayClient } from '@validpay/node-sdk'; | ||
| ```ts | ||
| import { ValidPayClient } from "@validpay/node-sdk"; | ||
| const client = new ValidPayClient({ | ||
| apiKey: process.env.VALIDPAY_API_KEY, | ||
| const client = new ValidPayClient({ apiKey: process.env.VALIDPAY_API_KEY! }); | ||
| // 1. Issuer side — register an intent with sensitive payload | ||
| const { retrievalId, key } = await client.createIntent({ | ||
| documentType: "ssn_card", | ||
| payload: { ssn: "123-45-6789", name: "Jane Doe" }, | ||
| }); | ||
| // Create a verification intent | ||
| const intent = await client.createIntent({ | ||
| documentType: 'check', | ||
| payload: { payee: 'Jane Doe', amount: 1500.00 }, | ||
| // retrievalId is public (e.g. "vp_abc123def456") — embed in a QR code. | ||
| // key is secret — deliver it ONLY to the intended verifier, out-of-band. | ||
| // 2. Verifier side — fetch and decrypt (no API key needed) | ||
| const result = await client.verifyIntent<{ ssn: string; name: string }>(retrievalId, key); | ||
| console.log(result.payload); // { ssn: "123-45-6789", name: "Jane Doe" } | ||
| console.log(result.integrityVerified); // true — commitment hash matched | ||
| console.log(result.issuer); // "Acme Bank" | ||
| console.log(result.issuerVerified); // true | ||
| ``` | ||
| ## How it works | ||
| 1. `createIntent` generates a fresh 256-bit key, encrypts your payload locally with AES-256-GCM, computes a SHA-256 commitment hash of the plaintext, and POSTs only the ciphertext + hash to `POST /v1/intent`. | ||
| 2. The API returns a public `retrieval_id` and stores the ciphertext + commitment hash. | ||
| 3. You hand the verifier the `retrievalId` and the `key` through your own secure channel. | ||
| 4. The verifier calls `verifyIntent`, which fetches `GET /v1/intent/:id`, decrypts the ciphertext locally, then recomputes the commitment hash and compares — any server-side tampering would change the hash. | ||
| The key is generated client-side, used client-side, and transmitted client-side. ValidPay can never read the payload. | ||
| ## API reference | ||
| ### `new ValidPayClient(options)` | ||
| | Option | Type | Default | Notes | | ||
| | --------- | ------------------- | --------------------------- | ------------------------------------------- | | ||
| | `apiKey` | `string` (required) | — | Your ValidPay issuer API key. | | ||
| | `baseUrl` | `string` | `"https://api.validpay.io"` | Override for staging or self-hosted setups. | | ||
| | `timeout` | `number` | `30000` | Request timeout (ms). | | ||
| | `fetch` | `typeof fetch` | global `fetch` | Inject a custom fetch (useful for testing). | | ||
| ### Core | ||
| #### `client.createIntent({ documentType, payload, validFrom?, validUntil? }) → { retrievalId, key }` | ||
| Generates a key, encrypts `JSON.stringify(payload)`, posts ciphertext + commitment hash to `/v1/intent`. **The key is never sent to the API.** | ||
| #### `client.createIntentBatch(items[]) → { retrievalId, key }[]` | ||
| Same as `createIntent` for up to 100 intents in a single request. Each item gets a unique AES key; results match the input order. | ||
| #### `client.verifyIntent<T>(retrievalId, key) → VerifyIntentResult<T>` | ||
| Fetches the intent and decrypts the payload locally. Verifies the commitment hash. Throws `ValidPayError`: | ||
| - `decryption_failed` — wrong key or tampered ciphertext (GCM auth-tag failure) | ||
| - `integrity_failure` — commitment hash mismatch (server-side tampering detected) | ||
| - `intent_revoked` — the intent has been revoked | ||
| - `split_key_required` / `selective_disclosure_required` — use the specialised verify method | ||
| ```ts | ||
| interface VerifyIntentResult<T> { | ||
| intentId: string; | ||
| payload: T; | ||
| issuer: string; | ||
| issuerVerified: boolean; | ||
| registeredAt: string; // ISO 8601 | ||
| status: string; | ||
| integrityVerified: boolean; | ||
| validFrom?: string | null; | ||
| validUntil?: string | null; | ||
| timeLockStatus?: "valid" | "not_yet_valid" | "expired" | null; | ||
| } | ||
| ``` | ||
| ### Split-key (Patent C) | ||
| ```ts | ||
| const { retrievalId, key: shareA } = await client.createSplitKeyIntent({ | ||
| documentType: "ssn_card", | ||
| payload: { ssn: "123-45-6789" }, | ||
| }); | ||
| // shareA goes in the QR; shareB stays at the API. | ||
| // intent.id → embed in QR code | ||
| // intent.verifyUrl → direct verification link | ||
| const result = await client.verifySplitKeyIntent(retrievalId, shareA); | ||
| // SDK fetches shareB from /v1/intent/:id/fragment, XOR-combines, decrypts. | ||
| ``` | ||
| ## Features | ||
| ### Selective disclosure (Patent E) | ||
| - Zero production dependencies (Node built-in crypto + native fetch) | ||
| - ESM-only, TypeScript-first | ||
| - AES-256-GCM encryption with client-side key generation | ||
| - XOR key splitting for multi-party verification | ||
| - Automatic retry with exponential backoff | ||
| ```ts | ||
| const { retrievalId, key } = await client.createSelectiveIntent({ | ||
| documentType: "check", | ||
| payload: { amount: 1500, payee: "Alice", memo: "rent" }, | ||
| disclosurePolicy: { | ||
| bank: ["amount"], | ||
| auditor: ["amount", "payee"], | ||
| }, | ||
| }); | ||
| ## Documentation | ||
| const bankView = await client.verifySelectiveIntent(retrievalId, key, "bank"); | ||
| // { amount: 1500, payee: "[REDACTED]", memo: "[REDACTED]" } | ||
| Full API documentation: [https://validpay.io/docs](https://validpay.io/docs) | ||
| const fullView = await client.verifySelectiveIntent(retrievalId, key, "full"); | ||
| // { amount: 1500, payee: "Alice", memo: "rent" } | ||
| ``` | ||
| ## Status | ||
| ### Revocation (Patent H) | ||
| **Private Beta** — Contact mike@validpay.io for API access. | ||
| ```ts | ||
| await client.revokeIntent(retrievalId, "stop payment requested"); | ||
| await client.reinstateIntent(retrievalId, "false alarm"); | ||
| const history = await client.getRevocationHistory(retrievalId); | ||
| ``` | ||
| ### Health | ||
| ```ts | ||
| const { status, version } = await client.health(); | ||
| ``` | ||
| ### Low-level crypto helpers | ||
| ```ts | ||
| import { | ||
| generateKey, | ||
| encrypt, | ||
| decrypt, | ||
| commitmentHash, | ||
| splitKey, | ||
| combineKeyShares, | ||
| encryptFields, | ||
| buildKeyMap, | ||
| decryptFields, | ||
| } from "@validpay/node-sdk"; | ||
| const key = generateKey(); // base64 32-byte key | ||
| const blob = encrypt("hello world", key); // base64(iv[12] || authTag[16] || ciphertext) | ||
| const plain = decrypt(blob, key); // "hello world" | ||
| const hash = commitmentHash(plain); // SHA-256 hex | ||
| const [a, b] = splitKey(key); | ||
| const reconstructed = combineKeyShares(a, b); // === key | ||
| ``` | ||
| ### `ValidPayError` | ||
| All SDK errors throw `ValidPayError` with a stable `code`: | ||
| | Code | Meaning | | ||
| | ------------------------------- | ------------------------------------------------------------- | | ||
| | `invalid_config` | Missing `apiKey` (or other constructor options). | | ||
| | `invalid_argument` | Required method argument is missing or invalid. | | ||
| | `invalid_key` | Key is not valid base64 or not 32 bytes. | | ||
| | `invalid_blob` | Blob is not valid base64 or too short. | | ||
| | `decryption_failed` | Wrong key, or ciphertext tampered (GCM auth-tag failure). | | ||
| | `integrity_failure` | Commitment hash didn't match — server tampering detected. | | ||
| | `intent_revoked` | The intent has been revoked. | | ||
| | `split_key_required` | Intent uses split-key; use `verifySplitKeyIntent` instead. | | ||
| | `selective_disclosure_required` | Intent uses per-field encryption; use `verifySelectiveIntent`. | | ||
| | `invalid_role` | Role not present in the disclosure policy. | | ||
| | `missing_fragment` | API did not return a key fragment for a split-key intent. | | ||
| | `network_error` | `fetch` itself rejected (DNS, TCP, abort, etc.). | | ||
| | `http_error` | API returned non-2xx with no machine-readable error. | | ||
| | `not_found` | API returned 404 (e.g. unknown retrieval ID). | | ||
| | `unauthorized` | API returned 401 (invalid or missing API key). | | ||
| | `invalid_response` | API returned 2xx but response shape was unexpected. | | ||
| | `invalid_payload` | Decrypted bytes were not valid JSON. | | ||
| ## Blob format | ||
| `encrypt()` returns a base64 string whose decoded bytes are: | ||
| ``` | ||
| [ iv (12 bytes) | authTag (16 bytes) | ciphertext (variable) ] | ||
| ``` | ||
| This matches the Python SDK exactly, so blobs are interoperable in both directions. | ||
| ## Development | ||
| ```bash | ||
| npm install | ||
| npm test | ||
| npm run build | ||
| ``` | ||
| ## License | ||
| MIT — Copyright (c) 2026 MiLu Technologies LLC | ||
| MIT — see [LICENSE](./LICENSE). |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
74114
2055.73%19
375%786
1504.08%215
305.66%3
Infinity%2
100%5
Infinity%