🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

@taplid/client

Package Overview
Dependencies
Maintainers
1
Versions
40
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@taplid/client - npm Package Compare versions

Comparing version
0.5.15
to
0.5.16
+4
-1
dist/client.d.ts

@@ -1,2 +0,2 @@

import type { TaplidAuditRequest, TaplidAuditResponse, TaplidClientOptions, TaplidDecisionRouting, TaplidPublicLaneSummary, TaplidThresholdProximity } from './types.js';
import type { TaplidAuditRequest, TaplidAuditResponse, TaplidClientOptions, TaplidDecisionRouting, TaplidPublicLaneSummary, TaplidThresholdProximity, TaplidVerifyAuditReport, TaplidVerifyAuditRequest } from './types.js';
/** @internal Retained — routing no longer included in public response (ITD-192). */

@@ -17,3 +17,6 @@ export declare function isTaplidDecisionRouting(value: unknown): value is TaplidDecisionRouting;

}): Promise<TaplidAuditResponse>;
verifyAudit(input: TaplidVerifyAuditRequest, options?: {
signal?: AbortSignal | undefined;
}): Promise<TaplidVerifyAuditReport>;
}
//# sourceMappingURL=client.d.ts.map

@@ -527,2 +527,123 @@ import { TaplidApiError } from './errors.js';

}
// CHANGE [2026-06-16]: ITD-1131 — Verify Audit token normalizer. Mirrors
// normalizeAuditIdForRetrieval but allows dots (JWTs contain them) and a larger
// cap. CRITICAL: never put the token value itself into any error message.
const MAX_VERIFY_TOKEN_LENGTH = 8192;
function normalizeVerifyToken(token) {
const trimmed = token.trim();
if (trimmed.length === 0) {
throw new TaplidApiError({
code: 'invalid_request',
message: 'token must not be empty.',
retryable: false,
});
}
if (trimmed.length > MAX_VERIFY_TOKEN_LENGTH) {
throw new TaplidApiError({
code: 'invalid_request',
message: `token must not exceed ${MAX_VERIFY_TOKEN_LENGTH} characters.`,
retryable: false,
});
}
return trimmed;
}
// CHANGE [2026-06-16]: ITD-1131 — enforce EXACTLY ONE of auditId/token.
function serializeVerifyAuditRequest(input) {
// Defensive: a JavaScript caller (no compile-time checking) may pass
// null/undefined/garbage. Re-widen to `unknown` and treat a field as
// "provided" only when it is a string, so we throw a clean `invalid_request`
// instead of a raw TypeError from `.trim()` on a non-string.
const candidate = input;
if (!isRecord(candidate)) {
throw new TaplidApiError({
code: 'invalid_request',
message: 'verifyAudit requires an object with exactly one of auditId or token.',
retryable: false,
});
}
const hasAuditId = typeof candidate.auditId === 'string';
const hasToken = typeof candidate.token === 'string';
if (hasAuditId === hasToken) {
throw new TaplidApiError({
code: 'invalid_request',
message: 'Provide exactly one of auditId or token.',
retryable: false,
});
}
if (typeof candidate.auditId === 'string') {
return { auditId: normalizeAuditIdForRetrieval(candidate.auditId) };
}
if (typeof candidate.token === 'string') {
return { token: normalizeVerifyToken(candidate.token) };
}
// Unreachable: the exactly-one guard above guarantees one branch fired.
throw new TaplidApiError({
code: 'invalid_request',
message: 'Provide exactly one of auditId or token.',
retryable: false,
});
}
// CHANGE [2026-06-16]: ITD-1131 — Verify Audit report shape guard (separate
// from isTaplidAuditResponse; the embedded result reuses that guard).
function isTaplidVerifyAuditReport(value) {
if (!isRecord(value)) {
return false;
}
const statusOk = value.status === 'valid' ||
value.status === 'warning' ||
value.status === 'invalid';
const inputKindOk = value.inputKind === 'audit-id' || value.inputKind === 'token';
const boolsOk = typeof value.isSignatureValid === 'boolean' &&
typeof value.isIssuedByTaplid === 'boolean';
const triOk = (candidate) => candidate === null || typeof candidate === 'boolean';
const stringOrAbsent = (candidate) => candidate === undefined || typeof candidate === 'string';
const numberOrAbsent = (candidate) => candidate === undefined || typeof candidate === 'number';
// header/payload: null OR a record whose KNOWN fields carry the declared
// types (string/number). Unknown fields are ignored (forward-compatible).
const headerOk = value.header === null ||
(isRecord(value.header) &&
stringOrAbsent(value.header.alg) &&
stringOrAbsent(value.header.kid) &&
stringOrAbsent(value.header.typ));
const payloadOk = value.payload === null ||
(isRecord(value.payload) &&
stringOrAbsent(value.payload.aud) &&
stringOrAbsent(value.payload.auditId) &&
stringOrAbsent(value.payload.auditMode) &&
stringOrAbsent(value.payload.decision) &&
stringOrAbsent(value.payload.inputHash) &&
stringOrAbsent(value.payload.iss) &&
stringOrAbsent(value.payload.resultHash) &&
numberOrAbsent(value.payload.iat) &&
numberOrAbsent(value.payload.trustScore) &&
numberOrAbsent(value.payload.version));
const resultOk = value.result === null || isTaplidAuditResponse(value.result);
// errorMessage appears ONLY on an 'invalid' report — the server structurally
// guarantees this. Reject a contradictory success report that carries one.
const errorMessageOk = value.errorMessage === undefined
? true
: typeof value.errorMessage === 'string' && value.status === 'invalid';
return (statusOk &&
inputKindOk &&
boolsOk &&
triOk(value.resultHashMatches) &&
triOk(value.signedFieldsMatch) &&
headerOk &&
payloadOk &&
resultOk &&
errorMessageOk);
}
/**
* Strip ITD-192 removed fields from any embedded audit result, and defensively
* drop a stray top-level `token`. The verify endpoint never returns a token, but
* the SDK must never surface a raw token even if a proxy/older server injected one.
*/
function sanitizeVerifyAuditReport(report) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- destructure to strip
const { token: _token, ...rest } = report;
if (rest.result !== null) {
return { ...rest, result: sanitizeAuditResponse(rest.result) };
}
return rest;
}
function resolveAuditMode(input) {

@@ -757,3 +878,60 @@ const normalizedAuditMode = normalizeAuditMode(input.auditMode);

}
// CHANGE [2026-06-16]: ITD-1131 — verifyAudit: anonymous POST /verify-audit,
// no Authorization header even when #apiKey is set (mirrors getAudit). Sends a
// JSON body with exactly one of auditId/token; validates the verify report
// shape. The token value is never placed into any error message.
async verifyAudit(input, options) {
const requestBody = serializeVerifyAuditRequest(input);
const abortController = createAbortController({
signal: options?.signal,
timeoutMs: this.#timeoutMs,
});
try {
const response = await this.#fetch(new URL('/verify-audit', this.#baseUrl), {
method: 'POST',
headers: { 'content-type': 'application/json', accept: 'application/json' },
body: JSON.stringify(requestBody),
signal: abortController.signal,
});
const parsedBody = await parseJsonBody(response);
if (!response.ok) {
throw buildApiErrorFromResponse(response, parsedBody);
}
if (!isTaplidVerifyAuditReport(parsedBody)) {
throw new TaplidApiError({
code: 'invalid_response',
message: 'Taplid returned an unexpected verification response shape.',
requestId: resolveRequestId(response),
retryable: false,
statusCode: response.status,
});
}
return sanitizeVerifyAuditReport(parsedBody);
}
catch (error) {
if (error instanceof TaplidApiError) {
throw error;
}
if (isAbortError(error)) {
throw new TaplidApiError({
cause: error,
code: abortController.timedOut() ? 'timeout' : 'aborted',
message: abortController.timedOut()
? 'Taplid request timed out.'
: 'Taplid request was aborted.',
retryable: abortController.timedOut(),
});
}
throw new TaplidApiError({
cause: error,
code: 'network_error',
message: 'Taplid request failed before a response was received.',
retryable: true,
});
}
finally {
abortController.cleanup();
}
}
}
//# sourceMappingURL=client.js.map
+1
-1
export { Taplid } from './client.js';
export { TaplidApiError } from './errors.js';
export type { TaplidAuditEvidence, TaplidAuditMode, TaplidAuditRequest, TaplidAuditResponse, TaplidClientOptions, TaplidDecision, TaplidEvidenceSource, TaplidPublicContextSignalCategory, TaplidPublicDiagnosisSummary, TaplidPublicForensicContextDiagnostics, TaplidPublicForensicContextSignal, TaplidPublicForensicDiagnostics, TaplidPublicForensicEvidenceSummary, TaplidPublicForensicPromptDiagnostics, TaplidPublicForensicPromptSignal, TaplidPublicIssue, TaplidPublicLaneStrongestCode, TaplidPublicLaneSummary, TaplidPublicLaneSummaryLane, TaplidPublicRepairAction, TaplidPublicPromptSignalCategory, TaplidRepairPriority, TaplidRepairTarget, } from './types.js';
export type { TaplidAuditEvidence, TaplidAuditMode, TaplidAuditRequest, TaplidAuditResponse, TaplidClientOptions, TaplidDecision, TaplidEvidenceSource, TaplidPublicContextSignalCategory, TaplidPublicDiagnosisSummary, TaplidPublicForensicContextDiagnostics, TaplidPublicForensicContextSignal, TaplidPublicForensicDiagnostics, TaplidPublicForensicEvidenceSummary, TaplidPublicForensicPromptDiagnostics, TaplidPublicForensicPromptSignal, TaplidPublicIssue, TaplidPublicLaneStrongestCode, TaplidPublicLaneSummary, TaplidPublicLaneSummaryLane, TaplidPublicRepairAction, TaplidPublicPromptSignalCategory, TaplidRepairPriority, TaplidRepairTarget, TaplidVerifyAuditInputKind, TaplidVerifyAuditJwtHeader, TaplidVerifyAuditPayload, TaplidVerifyAuditReport, TaplidVerifyAuditRequest, TaplidVerifyAuditStatus, } from './types.js';
//# sourceMappingURL=index.d.ts.map

@@ -195,2 +195,37 @@ export declare const TAPLID_DECISIONS: readonly ["ALLOW", "REVIEW", "BLOCK"];

}
export type TaplidVerifyAuditStatus = 'valid' | 'warning' | 'invalid';
export type TaplidVerifyAuditInputKind = 'audit-id' | 'token';
export interface TaplidVerifyAuditRequest {
auditId?: string | undefined;
token?: string | undefined;
}
export interface TaplidVerifyAuditJwtHeader {
alg?: string | undefined;
kid?: string | undefined;
typ?: string | undefined;
}
export interface TaplidVerifyAuditPayload {
aud?: string | undefined;
auditId?: string | undefined;
auditMode?: string | undefined;
decision?: string | undefined;
iat?: number | undefined;
inputHash?: string | undefined;
iss?: string | undefined;
resultHash?: string | undefined;
trustScore?: number | undefined;
version?: number | undefined;
}
export interface TaplidVerifyAuditReport {
status: TaplidVerifyAuditStatus;
inputKind: TaplidVerifyAuditInputKind;
isSignatureValid: boolean;
isIssuedByTaplid: boolean;
resultHashMatches: boolean | null;
signedFieldsMatch: boolean | null;
header: TaplidVerifyAuditJwtHeader | null;
payload: TaplidVerifyAuditPayload | null;
result: TaplidAuditResponse | null;
errorMessage?: string | undefined;
}
export interface TaplidClientOptions {

@@ -197,0 +232,0 @@ apiKey?: string | undefined;

{
"name": "@taplid/client",
"version": "0.5.15",
"version": "0.5.16",
"description": "Official Node.js SDK for the hosted Taplid audit API.",

@@ -38,3 +38,3 @@ "keywords": [

"dependencies": {
"@taplid/contract": "0.5.15"
"@taplid/contract": "0.5.16"
},

@@ -41,0 +41,0 @@ "engines": {

@@ -37,2 +37,4 @@ # @taplid/client

TypeScript autocomplete exposes the three SDK methods: `taplid.audit(...)`, `taplid.getAudit(...)`, and `taplid.verifyAudit(...)`.
## Retrieve an audit

@@ -56,2 +58,32 @@

## Verify an audit
Verify a persisted audit ID or signed attestation token. No API key is required.
Verify by audit ID:
```ts
import { Taplid } from '@taplid/client';
const taplid = new Taplid();
const verification = await taplid.verifyAudit({
auditId: 'AUD-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
});
console.log(verification.status);
```
Verify by attestation token:
```ts
const verification = await taplid.verifyAudit({
token: 'eyJhbGciOiJFUzI1NiIsImtpZCI6InRhcGxpZC1lczI1Ni0yMDI2LTA2IiwidHlwIjoiSldUIn0...',
});
console.log(verification.status);
```
Audit ID verification checks the persisted public result, signed fields, issuer, signature, and result hash. Token-only verification checks the signature and issuer, but cannot check the result hash without the persisted audit result.
## Signed attestations

@@ -67,3 +99,3 @@

The `attestation.token` can be verified against the JWKS public key. The signed payload includes the `auditId`, `auditMode`, `decision`, `trustScore`, `inputHash`, and `resultHash`.
The `attestation.token` can be verified against the JWKS public key, by calling `taplid.verifyAudit(...)`, or by posting an `auditId` or `token` to `https://api.taplid.com/verify-audit`. The signed payload includes the `auditId`, `auditMode`, `decision`, `trustScore`, `inputHash`, and `resultHash`.

@@ -215,4 +247,4 @@ ## HTTP API Example

- [Taplid Audit](https://taplid.com/audit) - run audits in the browser
- [Taplid CLI](https://www.npmjs.com/package/@taplid/cli) - run audits locally or in CI with npx @taplid/cli audit request.json
- [Taplid MCP](https://www.npmjs.com/package/@taplid/mcp) - expose Taplid as a tool to MCP-capable AI clients
- [Taplid CLI](https://www.npmjs.com/package/@taplid/cli) - run, retrieve, and verify audits locally or in CI
- [Taplid MCP](https://www.npmjs.com/package/@taplid/mcp) - expose Taplid audit, retrieval, and verification tools to MCP-capable AI clients
- [Taplid CLI eval](https://www.npmjs.com/package/@taplid/cli) - CI threshold gate via `npx @taplid/cli eval request.json --api-key tap_live_... --pass-threshold 80` (exits non-zero when below)

@@ -219,0 +251,0 @@ - [Full docs](https://github.com/tonyfa/taplid#readme)