@chitmark/sdk 0.6.1 → 0.6.3
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/README.md +24 -10
- package/dist/edge.cjs +65 -19
- package/dist/edge.cjs.map +1 -1
- package/dist/edge.d.cts +3 -2
- package/dist/edge.d.ts +3 -2
- package/dist/edge.js +63 -20
- package/dist/edge.js.map +1 -1
- package/dist/index.cjs +68 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -5
- package/dist/index.d.ts +14 -5
- package/dist/index.js +66 -20
- package/dist/index.js.map +1 -1
- package/dist/trusted-ip-Fb-K6nwG.d.cts +608 -0
- package/dist/trusted-ip-Fb-K6nwG.d.ts +608 -0
- package/package.json +12 -12
- package/dist/http-status-CYKIa-SM.d.cts +0 -435
- package/dist/http-status-CYKIa-SM.d.ts +0 -435
package/README.md
CHANGED
|
@@ -58,7 +58,12 @@ if (verdict.decision === "challenge") {
|
|
|
58
58
|
| **feedback** | `chitmark.feedback()` | `POST /v1/feedback` | After an outcome is known |
|
|
59
59
|
| **challenge** | `chitmark.challenge()` | `POST /v1/challenge` | On `challenge` or `degraded` |
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
Store-outage degradation on verify is **HTTP 200** with a Verdict
|
|
62
|
+
(`degraded: true`); the SDK deserializes it like any other Verdict. Verify
|
|
63
|
+
never returns HTTP 503. Timeouts and transport errors synthesize a local
|
|
64
|
+
degraded challenge Verdict and never throw on `verify`. HTTP 4xx / 429 Error
|
|
65
|
+
responses throw `ChitmarkApiError`. Set `onDegraded` to `challenge` (the only
|
|
66
|
+
supported value), never allow on degraded.
|
|
62
67
|
|
|
63
68
|
### Report outcomes
|
|
64
69
|
|
|
@@ -72,12 +77,12 @@ db.accounts.update(userId, { chitmarkEventId: verdict.eventId });
|
|
|
72
77
|
await chitmark.feedback({
|
|
73
78
|
eventId: account.chitmarkEventId, // the stored join key
|
|
74
79
|
outcome: "credit_burn", // converted | chargeback | abuse_confirmed | ...
|
|
75
|
-
value: 87.4, //
|
|
80
|
+
value: 87.4, // measured magnitude: `unit` rides along (default "usd"; also "credits" | "count")
|
|
76
81
|
observedAt: "2026-08-06T04:00:00Z",
|
|
77
82
|
});
|
|
78
83
|
```
|
|
79
84
|
|
|
80
|
-
Exact duplicate feedback bodies derive the same warehouse id, so
|
|
85
|
+
Exact duplicate feedback bodies derive the same warehouse id (`eventId` + `outcome` + `value` + `unit` + `observedAt`), so connector retries with a stable business timestamp never double-count a burned value. Prefer an `Idempotency-Key` anyway; omitting `observedAt` uses server time and is not safe for bare retries.
|
|
81
86
|
|
|
82
87
|
### Handle a challenge
|
|
83
88
|
|
|
@@ -107,23 +112,30 @@ if (issued.instructions.type === "pow") {
|
|
|
107
112
|
session: "sess_9f3a",
|
|
108
113
|
proof: { type: "proof_of_work", nonce: String(nonce) },
|
|
109
114
|
});
|
|
110
|
-
// Re-verify with context: { challengeId }
|
|
115
|
+
// Re-verify with context: { challengeId }; completion alone does not authorize.
|
|
111
116
|
}
|
|
112
117
|
```
|
|
113
118
|
|
|
114
119
|
### Verify the receipt
|
|
115
120
|
|
|
116
|
-
Every production verdict ships a `verdictToken`: an ES256 JWT bound to session, origin, and event. Verify
|
|
121
|
+
Every production verdict ships a `verdictToken`: an ES256 JWT bound to session, origin, and event. Verify authenticity, then authorize on the decision:
|
|
117
122
|
|
|
118
123
|
```typescript
|
|
119
124
|
const claims = await chitmark.verifyVerdictToken(verdict.verdictToken, {
|
|
120
|
-
session: "sess_9f3a",
|
|
121
|
-
|
|
125
|
+
session: "sess_9f3a",
|
|
126
|
+
tenantId: "org_acme",
|
|
122
127
|
});
|
|
123
|
-
|
|
128
|
+
|
|
129
|
+
if (claims.degraded || claims.decision !== "allow") {
|
|
130
|
+
throw new ChallengeRequiredError(); // HTTP 428 / challenge response
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Only now trust the allow.
|
|
124
134
|
```
|
|
125
135
|
|
|
126
|
-
Rejects expired tokens, unknown keys, bad signatures, and session or origin mismatches with typed `VerdictTokenError` codes.
|
|
136
|
+
Rejects expired tokens, unknown keys, bad signatures, and session or origin mismatches with typed `VerdictTokenError` codes. A verified token that is not a non-degraded `allow` must still fail closed.
|
|
137
|
+
|
|
138
|
+
Cache JWKS using HTTP headers: respect `Cache-Control` (`max-age=60`), and when `ETag` or `Last-Modified` are present use conditional requests (`If-None-Match` / `If-Modified-Since`) instead of a hard-coded refresh interval. Refresh immediately on unknown `kid`. Do not fetch on every verification. Every signed JWT requires `kid`. Keys are EC P-256 for ES256: require JWT `alg === "ES256"` before verifying (`wrong_algorithm` otherwise); never trust the token-requested alg. Rotation overlaps old and new keys; keep the retiring key until tokens under it expire (≥ 5 minutes + 60 seconds). An empty JWKS (`keys: []`) means verification is impossible: fail closed; never treat an empty set as proof a token is valid (local/CI may also emit `unsigned.<eventId>`). Pass a cached `jwks` option into `verifyVerdictToken` to skip the network call.
|
|
127
139
|
|
|
128
140
|
### PII modes
|
|
129
141
|
|
|
@@ -135,10 +147,12 @@ Rejects expired tokens, unknown keys, bad signatures, and session or origin mism
|
|
|
135
147
|
|
|
136
148
|
## Framework integrations
|
|
137
149
|
|
|
138
|
-
Express middleware and a Next.js route helper ship in the package
|
|
150
|
+
Express middleware and a Next.js route helper ship in the package. They normalize transient failures, challenge responses (HTTP 428), and deny (HTTP 403) for you. Handle raw status codes when using the low-level `Chitmark` client or curl.
|
|
139
151
|
|
|
140
152
|
```typescript
|
|
141
153
|
// Express: 403 on deny, 428 + challenge payload on challenge
|
|
154
|
+
// 428 means the request is not rejected permanently; a required verification
|
|
155
|
+
// precondition must be satisfied before the action can proceed.
|
|
142
156
|
import { chitmarkGate } from "@chitmark/sdk";
|
|
143
157
|
app.post("/signup", chitmarkGate(chitmark, "signup"), signupHandler);
|
|
144
158
|
|
package/dist/edge.cjs
CHANGED
|
@@ -186,6 +186,7 @@ function flattenHeaders(headers) {
|
|
|
186
186
|
}
|
|
187
187
|
|
|
188
188
|
// src/verify-token.ts
|
|
189
|
+
var VERDICT_TOKEN_ISSUER = "https://api.chitmark.com";
|
|
189
190
|
var VerdictTokenError = class extends ChitmarkError {
|
|
190
191
|
name = "VerdictTokenError";
|
|
191
192
|
constructor(code, message) {
|
|
@@ -194,7 +195,7 @@ var VerdictTokenError = class extends ChitmarkError {
|
|
|
194
195
|
};
|
|
195
196
|
var DEFAULT_JWKS_URL = "https://api.chitmark.com/.well-known/jwks.json";
|
|
196
197
|
var DEFAULT_LEEWAY_SECONDS = 30;
|
|
197
|
-
async function verifyVerdictToken(token, options
|
|
198
|
+
async function verifyVerdictToken(token, options) {
|
|
198
199
|
const nowMs = options.nowMs ?? Date.now();
|
|
199
200
|
const leewaySeconds = options.leewaySeconds ?? DEFAULT_LEEWAY_SECONDS;
|
|
200
201
|
const parts = token.split(".");
|
|
@@ -216,6 +217,12 @@ async function verifyVerdictToken(token, options = {}) {
|
|
|
216
217
|
`verdictToken must use ES256, got ${String(header["alg"])}`
|
|
217
218
|
);
|
|
218
219
|
}
|
|
220
|
+
if (header["typ"] !== "JWT") {
|
|
221
|
+
throw new VerdictTokenError(
|
|
222
|
+
"wrong_type",
|
|
223
|
+
`verdictToken must be a JWT, got ${String(header["typ"])}`
|
|
224
|
+
);
|
|
225
|
+
}
|
|
219
226
|
const kid = typeof header["kid"] === "string" ? header["kid"] : "";
|
|
220
227
|
if (!kid) {
|
|
221
228
|
throw new VerdictTokenError("unknown_kid", "verdictToken is missing kid");
|
|
@@ -229,15 +236,20 @@ async function verifyVerdictToken(token, options = {}) {
|
|
|
229
236
|
if (Number.isFinite(iat) && iat > nowSeconds + leewaySeconds) {
|
|
230
237
|
throw new VerdictTokenError("not_yet_valid", "verdictToken iat is in the future");
|
|
231
238
|
}
|
|
232
|
-
const
|
|
233
|
-
if (
|
|
239
|
+
const expectedIssuer = options.issuer ?? VERDICT_TOKEN_ISSUER;
|
|
240
|
+
if (payload["iss"] !== expectedIssuer) {
|
|
241
|
+
throw new VerdictTokenError(
|
|
242
|
+
"wrong_issuer",
|
|
243
|
+
"verdictToken was not issued by Chitmark"
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
if (payload["sub"] !== options.session) {
|
|
234
247
|
throw new VerdictTokenError(
|
|
235
248
|
"wrong_session",
|
|
236
249
|
"verdictToken was minted for a different session"
|
|
237
250
|
);
|
|
238
251
|
}
|
|
239
|
-
|
|
240
|
-
if (expectedTenantId !== void 0 && payload["tid"] !== expectedTenantId) {
|
|
252
|
+
if (payload["tid"] !== options.tenantId) {
|
|
241
253
|
throw new VerdictTokenError(
|
|
242
254
|
"wrong_tenant",
|
|
243
255
|
"verdictToken was minted for a different tenant"
|
|
@@ -352,9 +364,15 @@ var Chitmark = class {
|
|
|
352
364
|
}
|
|
353
365
|
/**
|
|
354
366
|
* Score + route an inbound action (signup / trial / …).
|
|
355
|
-
*
|
|
356
|
-
*
|
|
357
|
-
*
|
|
367
|
+
* Client budget defaults to 800ms.
|
|
368
|
+
*
|
|
369
|
+
* Store-outage degradation arrives as **HTTP 200** with a Verdict body
|
|
370
|
+
* (`degraded: true`, `decision: "challenge"`). The SDK deserializes that
|
|
371
|
+
* like any other Verdict. Verify never returns HTTP 503.
|
|
372
|
+
*
|
|
373
|
+
* HTTP 4xx / 429 Error responses throw `ChitmarkApiError`. Transport
|
|
374
|
+
* timeout / network failure (or a malformed 200 body) synthesizes a local
|
|
375
|
+
* degraded challenge Verdict (never allow, never crashes).
|
|
358
376
|
*
|
|
359
377
|
* Persist `v.eventId` on the account row: feedback joins only on that id.
|
|
360
378
|
*/
|
|
@@ -395,7 +413,17 @@ var Chitmark = class {
|
|
|
395
413
|
}
|
|
396
414
|
/**
|
|
397
415
|
* Report a downstream outcome joined on the stored eventId from verify.
|
|
398
|
-
*
|
|
416
|
+
*
|
|
417
|
+
* Security invariant: feedback cannot create attribution. It only attaches
|
|
418
|
+
* an outcome to an existing verify event for this tenant. Unknown or
|
|
419
|
+
* cross-tenant eventIds return 404. Never invent a join from email/IP.
|
|
420
|
+
*
|
|
421
|
+
* Append-only (not latest-wins): multiple outcomes may attach to one
|
|
422
|
+
* eventId. Exact duplicates share one feedbackId. Compatible labels
|
|
423
|
+
* coexist; conflicting pairs quarantine the new observation without
|
|
424
|
+
* deleting prior evidence. HTTP `{ ok: true }` still acknowledges
|
|
425
|
+
* quarantined ingest.
|
|
426
|
+
*
|
|
399
427
|
* `idempotencyKey` is sent as both the Idempotency-Key header and body field
|
|
400
428
|
* (header takes precedence server-side) so exact retries replay the original
|
|
401
429
|
* acknowledgement.
|
|
@@ -418,8 +446,8 @@ var Chitmark = class {
|
|
|
418
446
|
}
|
|
419
447
|
/**
|
|
420
448
|
* Complete a challenge by submitting its solved proof. Clears only the bound
|
|
421
|
-
* session, once.
|
|
422
|
-
*
|
|
449
|
+
* session, once. Does not authorize the action: re-verify with
|
|
450
|
+
* `context.challengeId` and proceed only on non-degraded allow.
|
|
423
451
|
*/
|
|
424
452
|
async completeChallenge(request) {
|
|
425
453
|
return this.request("/v1/challenge", {
|
|
@@ -429,12 +457,13 @@ var Chitmark = class {
|
|
|
429
457
|
}
|
|
430
458
|
/**
|
|
431
459
|
* Verify a verdictToken's signature against the API's JWKS and its session /
|
|
432
|
-
* tenant binding.
|
|
433
|
-
*
|
|
434
|
-
*
|
|
435
|
-
*
|
|
460
|
+
* tenant binding. Prefers a cached `jwks` (refresh periodically and on
|
|
461
|
+
* unknown `kid`); do not fetch on every call. Rejects expired tokens,
|
|
462
|
+
* unknown kids, and invalid signatures with `VerdictTokenError`. Always
|
|
463
|
+
* pass `session` and `tenantId` (required security boundary); `aud`
|
|
464
|
+
* optionally enforces the origin hint only.
|
|
436
465
|
*/
|
|
437
|
-
async verifyVerdictToken(token, options
|
|
466
|
+
async verifyVerdictToken(token, options) {
|
|
438
467
|
return verifyVerdictToken(token, {
|
|
439
468
|
...options,
|
|
440
469
|
jwksUrl: `${this.baseUrl}/.well-known/jwks.json`,
|
|
@@ -512,6 +541,13 @@ function isWellFormedVerdict(value) {
|
|
|
512
541
|
return typeof v.decision === "string" && VERDICT_DECISIONS.has(v.decision) && typeof v.eventId === "string" && v.eventId.length > 0 && typeof v.degraded === "boolean";
|
|
513
542
|
}
|
|
514
543
|
|
|
544
|
+
// src/trusted-ip.ts
|
|
545
|
+
function getTrustedClientIp(req) {
|
|
546
|
+
const platform = req.headers.get("cf-connecting-ip")?.trim() || req.headers.get("x-real-ip")?.trim() || req.headers.get("x-vercel-forwarded-for")?.split(",")[0]?.trim() || "";
|
|
547
|
+
if (platform) return platform;
|
|
548
|
+
return req.headers.get("x-forwarded-for")?.split(",")[0]?.trim() ?? "";
|
|
549
|
+
}
|
|
550
|
+
|
|
515
551
|
// src/http-status.ts
|
|
516
552
|
var CHITMARK_HTTP_STATUS = {
|
|
517
553
|
ok: 200,
|
|
@@ -531,15 +567,21 @@ var CHITMARK_HTTP_STATUS_MEANING = {
|
|
|
531
567
|
unauthorized: "API key is missing or invalid.",
|
|
532
568
|
forbidden: "Verify returned deny; block the action.",
|
|
533
569
|
notFound: "Referenced Chitmark resource was not found.",
|
|
534
|
-
conflict: "Idempotency key
|
|
535
|
-
preconditionRequired: "
|
|
570
|
+
conflict: "Idempotency key is already associated with a different payload fingerprint.",
|
|
571
|
+
preconditionRequired: "428 means the request is not rejected permanently; a required verification precondition must be satisfied before the action can proceed.",
|
|
536
572
|
tooManyRequests: "Request was rate limited."
|
|
537
573
|
};
|
|
574
|
+
function isEligibleAllow(verdict) {
|
|
575
|
+
return verdict.decision === "allow" && !verdict.degraded;
|
|
576
|
+
}
|
|
538
577
|
function verdictToHttpStatus(verdict) {
|
|
539
578
|
if (verdict.degraded || verdict.decision === "challenge") {
|
|
540
579
|
return CHITMARK_HTTP_STATUS.preconditionRequired;
|
|
541
580
|
}
|
|
542
581
|
if (verdict.decision === "deny") return CHITMARK_HTTP_STATUS.forbidden;
|
|
582
|
+
if (!isEligibleAllow(verdict)) {
|
|
583
|
+
return CHITMARK_HTTP_STATUS.preconditionRequired;
|
|
584
|
+
}
|
|
543
585
|
return CHITMARK_HTTP_STATUS.ok;
|
|
544
586
|
}
|
|
545
587
|
|
|
@@ -547,10 +589,11 @@ function verdictToHttpStatus(verdict) {
|
|
|
547
589
|
var ChitmarkEdge = class extends Chitmark {
|
|
548
590
|
/**
|
|
549
591
|
* Build a verify call from a Fetch Request (headers, IP, body fields).
|
|
592
|
+
* IP resolution uses {@link getTrustedClientIp} (`cf-connecting-ip` first).
|
|
550
593
|
*/
|
|
551
594
|
async verifyRequest(req, options) {
|
|
552
595
|
const url = new URL(req.url);
|
|
553
|
-
const ip =
|
|
596
|
+
const ip = getTrustedClientIp(req);
|
|
554
597
|
const userAgent = req.headers.get("user-agent") ?? "";
|
|
555
598
|
const headers = flattenHeaders(req.headers);
|
|
556
599
|
const subject = options.subject ?? {
|
|
@@ -578,10 +621,13 @@ exports.ChitmarkApiError = ChitmarkApiError;
|
|
|
578
621
|
exports.ChitmarkCore = Chitmark;
|
|
579
622
|
exports.ChitmarkEdge = ChitmarkEdge;
|
|
580
623
|
exports.ChitmarkError = ChitmarkError;
|
|
624
|
+
exports.VERDICT_TOKEN_ISSUER = VERDICT_TOKEN_ISSUER;
|
|
581
625
|
exports.VerdictTokenError = VerdictTokenError;
|
|
582
626
|
exports.degradedChallengeVerdict = degradedChallengeVerdict;
|
|
583
627
|
exports.enforceDegradedNeverAllow = enforceDegradedNeverAllow;
|
|
628
|
+
exports.getTrustedClientIp = getTrustedClientIp;
|
|
584
629
|
exports.hashEmailSha256 = hashEmailSha256;
|
|
630
|
+
exports.isEligibleAllow = isEligibleAllow;
|
|
585
631
|
exports.minimizeFormData = minimizeFormData;
|
|
586
632
|
exports.truncateIp = truncateIp;
|
|
587
633
|
exports.verdictToHttpStatus = verdictToHttpStatus;
|
package/dist/edge.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/internal/constants.ts","../src/pii.ts","../src/internal/prepare.ts","../src/verify-token.ts","../src/client.ts","../src/http-status.ts","../src/edge.ts"],"names":["out"],"mappings":"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","file":"edge.cjs","sourcesContent":["import type { ChitmarkErrorBody, Decision, Verdict } from \"./types.js\";\n\n/**\n * Base error for all Chitmark client failures.\n */\nexport class ChitmarkError extends Error {\n override name = \"ChitmarkError\";\n readonly status?: number;\n readonly code?: string;\n readonly body?: ChitmarkErrorBody | string;\n\n constructor(\n message: string,\n options?: { status?: number; code?: string; body?: ChitmarkErrorBody | string },\n ) {\n super(message);\n this.status = options?.status;\n this.code = options?.code;\n this.body = options?.body;\n }\n}\n\n/**\n * Raised when the API returns a non-2xx response.\n */\nexport class ChitmarkApiError extends ChitmarkError {\n override name = \"ChitmarkApiError\";\n\n constructor(status: number, body: ChitmarkErrorBody | string, message?: string) {\n const msg =\n message ??\n (typeof body === \"string\"\n ? body\n : body.message || body.error || `Chitmark API error (${status})`);\n super(msg, {\n status,\n code: typeof body === \"object\" ? (body.code ?? body.error) : undefined,\n body,\n });\n }\n}\n\n/**\n * Build the degraded challenge verdict used on timeout / transport failure.\n * Golden rule: fail to challenge, never to allow.\n */\nexport function degradedChallengeVerdict(reason: string, session?: string): Verdict {\n return {\n decision: \"challenge\" satisfies Decision,\n actorType: \"unknown\",\n confidence: 0,\n reasons: [reason],\n principal: {\n resolved: false,\n identityBasis: [\"degraded\"],\n },\n verdictToken: \"\",\n eventId: `evt_degraded_${session ?? \"unknown\"}`,\n degraded: true,\n enforcementMode: \"enforce\",\n };\n}\n\n/**\n * Ensure degraded responses never surface as allow (defense in depth client-side).\n */\nexport function enforceDegradedNeverAllow(verdict: Verdict): Verdict {\n if (verdict.degraded && verdict.decision === \"allow\") {\n return {\n ...verdict,\n decision: \"challenge\",\n reasons: [\n ...verdict.reasons,\n \"Client enforced: degraded decision must not be allow\",\n ],\n };\n }\n return verdict;\n}\n","import type { ChitmarkEnv } from \"../types.js\";\n\nexport const DEFAULT_BASE_URLS: Record<ChitmarkEnv, string> = {\n production: \"https://api.chitmark.com\",\n staging: \"https://api.staging.chitmark.com\",\n development: \"http://127.0.0.1:8787\",\n};\n\nexport const DEFAULT_TIMEOUT_MS = 800;\n/** Keep in parity with the package version and the Python SDK. */\nexport const SDK_VERSION = \"0.6.0\";\n\nexport function resolveBaseUrl(\n env: ChitmarkEnv = \"production\",\n baseUrl?: string,\n): string {\n return (baseUrl ?? DEFAULT_BASE_URLS[env]).replace(/\\/$/, \"\");\n}\n\n/**\n * CHITMARK_BASE_URL environment override, when present (Node only, no-op on\n * Workers/browsers where `process` is undefined).\n */\nexport function envBaseUrl(): string | undefined {\n if (typeof process === \"undefined\") return undefined;\n const value = process.env?.CHITMARK_BASE_URL;\n return value ? value.trim() : undefined;\n}\n","/**\n * Client-side PII minimization helpers.\n * Default SDK mode hashes email and truncates IP before leaving the customer process.\n */\n\n/**\n * SHA-256 hex digest of lowercased, trimmed email.\n * Uses Web Crypto (Node 18+, browsers, Workers).\n */\nexport async function hashEmailSha256(email: string): Promise<string> {\n const normalized = email.trim().toLowerCase();\n const data = new TextEncoder().encode(normalized);\n const digest = await crypto.subtle.digest(\"SHA-256\", data);\n return bufferToHex(digest);\n}\n\n/**\n * Truncate IPv4 to /24 or IPv6 to /48 for coarse geo without host identity.\n */\nexport function truncateIp(ip: string): string {\n const trimmed = ip.trim();\n // IPv4 (optionally from x-forwarded-for first hop)\n const first = trimmed.split(\",\")[0]?.trim() ?? trimmed;\n if (first.includes(\".\") && !first.includes(\":\")) {\n const parts = first.split(\".\");\n if (parts.length === 4) {\n return `${parts[0]}.${parts[1]}.${parts[2]}.0/24`;\n }\n }\n // IPv6: keep first 3 hextets (~/48)\n if (first.includes(\":\")) {\n const hextets = first.split(\":\").filter(Boolean);\n const head = hextets.slice(0, 3).join(\":\");\n return `${head}::/48`;\n }\n return first;\n}\n\n/**\n * Reduce form payload to non-PII keys (domain-style fields only for hashed mode).\n * Free-text is dropped; companyDomain-style keys are kept as-is when domain-like.\n */\nexport function minimizeFormData(\n formData: Record<string, unknown> | undefined,\n): Record<string, unknown> | undefined {\n if (!formData) return undefined;\n const allowed = new Set([\n \"companyDomain\",\n \"company_domain\",\n \"domain\",\n \"plan\",\n \"referrer\",\n \"utm_source\",\n \"utm_medium\",\n \"utm_campaign\",\n ]);\n const out: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(formData)) {\n if (allowed.has(key) && value != null) {\n out[key] = value;\n }\n }\n return Object.keys(out).length > 0 ? out : undefined;\n}\n\nfunction bufferToHex(buffer: ArrayBuffer): string {\n const bytes = new Uint8Array(buffer);\n let hex = \"\";\n for (const b of bytes) {\n hex += b.toString(16).padStart(2, \"0\");\n }\n return hex;\n}\n","import type { PiiMode, Subject } from \"../types.js\";\nimport { hashEmailSha256, minimizeFormData, truncateIp } from \"../pii.js\";\n\n/**\n * Apply client-side PII mode to a subject before the wire.\n */\nexport async function prepareSubject(\n subject: Subject,\n piiMode: PiiMode,\n): Promise<Subject> {\n if (piiMode === \"raw\") {\n return subject;\n }\n\n if (piiMode === \"none\") {\n return {\n userAgent: subject.userAgent,\n headers: pickWebBotAuthHeaders(subject.headers),\n };\n }\n\n // hashed (default)\n const prepared: Subject = {\n userAgent: subject.userAgent,\n headers: subject.headers,\n };\n\n if (subject.emailSha256) {\n prepared.emailSha256 = subject.emailSha256;\n } else if (subject.email) {\n prepared.emailSha256 = await hashEmailSha256(subject.email);\n }\n\n if (subject.ipTrunc) {\n prepared.ipTrunc = subject.ipTrunc;\n } else if (subject.ip) {\n prepared.ipTrunc = truncateIp(subject.ip);\n }\n\n const hashedForm = subject.formDataHashed ?? minimizeFormData(subject.formData);\n if (hashedForm) {\n prepared.formDataHashed = hashedForm;\n }\n\n return prepared;\n}\n\nfunction pickWebBotAuthHeaders(\n headers?: Record<string, string | string[] | undefined>,\n): Record<string, string> | undefined {\n if (!headers) return undefined;\n const keys = [\"signature-agent\", \"signature-input\", \"signature\"];\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(headers)) {\n const lower = k.toLowerCase();\n if (keys.includes(lower) && typeof v === \"string\") {\n out[lower] = v;\n } else if (keys.includes(lower) && Array.isArray(v) && v[0]) {\n out[lower] = v[0];\n }\n }\n return Object.keys(out).length > 0 ? out : undefined;\n}\n\n/**\n * Normalize header maps (Node / Fetch) to plain string records for JSON.\n */\nexport function flattenHeaders(\n headers?: Record<string, string | string[] | undefined> | Headers,\n): Record<string, string> | undefined {\n if (!headers) return undefined;\n if (headers instanceof Headers) {\n const out: Record<string, string> = {};\n headers.forEach((value, key) => {\n out[key.toLowerCase()] = value;\n });\n return out;\n }\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(headers)) {\n if (typeof v === \"string\") out[k.toLowerCase()] = v;\n else if (Array.isArray(v) && v[0]) out[k.toLowerCase()] = v[0];\n }\n return out;\n}\n","/**\n * Client-side verdictToken verification.\n *\n * A verdictToken is an ES256 JWT decision receipt minted by the edge and bound\n * to session (`sub`), origin hint (`aud`), issuing tenant (`tid`), and `jti`\n * with a short `exp`. This module validates shape, signature (against the JWKS\n * served from GET /.well-known/jwks.json), expiry, session binding, and, when\n * expected values are supplied, tenant and origin binding. `aud` reflects\n * request headers and is attacker influenced: always verify `session` and\n * `tenantId`, never `aud` alone. Rejection reasons are surfaced as\n * `VerdictTokenError.code`.\n */\n\nimport { ChitmarkError } from \"./errors.js\";\nimport type { ActorType, Decision } from \"./types.js\";\n\nexport interface VerdictTokenClaims {\n eventId: string;\n decision: Decision;\n actorType: ActorType;\n confidence: number;\n aud: string;\n sub: string;\n /** Issuing tenant, server-derived from the API key used at verify time. */\n tid: string;\n jti: string;\n iat: number;\n exp: number;\n degraded: boolean;\n}\n\nexport type VerdictTokenErrorCode =\n | \"malformed_token\"\n | \"wrong_algorithm\"\n | \"jwks_unavailable\"\n | \"unknown_kid\"\n | \"invalid_signature\"\n | \"expired\"\n | \"not_yet_valid\"\n | \"wrong_session\"\n | \"wrong_aud\"\n | \"wrong_tenant\";\n\nexport class VerdictTokenError extends ChitmarkError {\n override name = \"VerdictTokenError\";\n\n constructor(code: VerdictTokenErrorCode, message: string) {\n super(message, { code });\n }\n}\n\nexport interface VerifyVerdictTokenOptions {\n /** Expected session: token `sub` must equal this or verification fails. */\n session?: string;\n /** Expected issuing tenant: token `tid` must equal this or verification fails. */\n tenantId?: string;\n /** Expected origin hint: token `aud` must equal this or verification fails. */\n aud?: string;\n /** JWKS URL; defaults to https://api.chitmark.com/.well-known/jwks.json. */\n jwksUrl?: string;\n /** Pre-fetched JWKS; skips the network fetch when provided. */\n jwks?: { keys: Array<Record<string, unknown>> };\n /** Injectable fetch (Node 24+/browsers have a global). */\n fetch?: typeof fetch;\n /** Clock override for tests. */\n nowMs?: number;\n /** Clock skew tolerance in seconds; defaults to 30. */\n leewaySeconds?: number;\n}\n\nconst DEFAULT_JWKS_URL = \"https://api.chitmark.com/.well-known/jwks.json\";\nconst DEFAULT_LEEWAY_SECONDS = 30;\n\nexport async function verifyVerdictToken(\n token: string,\n options: VerifyVerdictTokenOptions = {},\n): Promise<VerdictTokenClaims> {\n const nowMs = options.nowMs ?? Date.now();\n const leewaySeconds = options.leewaySeconds ?? DEFAULT_LEEWAY_SECONDS;\n\n const parts = token.split(\".\");\n if (parts.length !== 3) {\n throw new VerdictTokenError(\"malformed_token\", \"verdictToken must be a JWT\");\n }\n const [headerB64, payloadB64, signatureB64] = parts as [string, string, string];\n\n let header: Record<string, unknown>;\n let payload: Record<string, unknown>;\n try {\n header = JSON.parse(decodeBase64Url(headerB64)) as Record<string, unknown>;\n payload = JSON.parse(decodeBase64Url(payloadB64)) as Record<string, unknown>;\n } catch {\n throw new VerdictTokenError(\"malformed_token\", \"verdictToken is not valid JWT JSON\");\n }\n\n if (header[\"alg\"] !== \"ES256\") {\n throw new VerdictTokenError(\n \"wrong_algorithm\",\n `verdictToken must use ES256, got ${String(header[\"alg\"])}`,\n );\n }\n const kid = typeof header[\"kid\"] === \"string\" ? header[\"kid\"] : \"\";\n if (!kid) {\n throw new VerdictTokenError(\"unknown_kid\", \"verdictToken is missing kid\");\n }\n\n const exp = typeof payload[\"exp\"] === \"number\" ? payload[\"exp\"] : NaN;\n const iat = typeof payload[\"iat\"] === \"number\" ? payload[\"iat\"] : NaN;\n const nowSeconds = Math.floor(nowMs / 1000);\n if (Number.isFinite(exp) && exp < nowSeconds - leewaySeconds) {\n throw new VerdictTokenError(\"expired\", \"verdictToken has expired\");\n }\n if (Number.isFinite(iat) && iat > nowSeconds + leewaySeconds) {\n throw new VerdictTokenError(\"not_yet_valid\", \"verdictToken iat is in the future\");\n }\n\n const expectedSession = options.session;\n if (expectedSession !== undefined && payload[\"sub\"] !== expectedSession) {\n throw new VerdictTokenError(\n \"wrong_session\",\n \"verdictToken was minted for a different session\",\n );\n }\n const expectedTenantId = options.tenantId;\n if (expectedTenantId !== undefined && payload[\"tid\"] !== expectedTenantId) {\n throw new VerdictTokenError(\n \"wrong_tenant\",\n \"verdictToken was minted for a different tenant\",\n );\n }\n const expectedAud = options.aud;\n if (expectedAud !== undefined && payload[\"aud\"] !== expectedAud) {\n throw new VerdictTokenError(\n \"wrong_aud\",\n \"verdictToken was minted for a different origin\",\n );\n }\n\n const jwk = await findJwk(kid, options);\n if (!jwk) {\n throw new VerdictTokenError(\"unknown_kid\", `JWKS has no key for kid ${kid}`);\n }\n\n let publicKey: CryptoKey;\n try {\n publicKey = await crypto.subtle.importKey(\n \"jwk\",\n jwk as unknown as JsonWebKey,\n { name: \"ECDSA\", namedCurve: \"P-256\" },\n false,\n [\"verify\"],\n );\n } catch {\n throw new VerdictTokenError(\n \"invalid_signature\",\n \"JWKS key is not a valid P-256 public key\",\n );\n }\n\n const signatureBytes = decodeBase64UrlBytes(signatureB64);\n const signatureBuffer = new ArrayBuffer(signatureBytes.byteLength);\n new Uint8Array(signatureBuffer).set(signatureBytes);\n\n const valid = await crypto.subtle.verify(\n { name: \"ECDSA\", hash: \"SHA-256\" },\n publicKey,\n signatureBuffer,\n new TextEncoder().encode(`${headerB64}.${payloadB64}`),\n );\n if (!valid) {\n throw new VerdictTokenError(\n \"invalid_signature\",\n \"verdictToken signature failed verification\",\n );\n }\n\n return payload as unknown as VerdictTokenClaims;\n}\n\nasync function findJwk(\n kid: string,\n options: VerifyVerdictTokenOptions,\n): Promise<Record<string, unknown> | undefined> {\n let jwks = options.jwks;\n if (!jwks) {\n const jwksUrl = options.jwksUrl ?? DEFAULT_JWKS_URL;\n try {\n const fetchImpl = options.fetch ?? globalThis.fetch.bind(globalThis);\n const res = await fetchImpl(jwksUrl);\n if (!res.ok) {\n throw new Error(`JWKS fetch failed with ${res.status}`);\n }\n jwks = (await res.json()) as { keys: Array<Record<string, unknown>> };\n } catch (err) {\n throw new VerdictTokenError(\n \"jwks_unavailable\",\n `Failed to load JWKS from ${jwksUrl}: ${\n err instanceof Error ? err.message : \"unknown error\"\n }`,\n );\n }\n }\n if (!Array.isArray(jwks.keys)) {\n throw new VerdictTokenError(\"jwks_unavailable\", \"JWKS response has no keys array\");\n }\n return jwks.keys.find((key) => key[\"kid\"] === kid);\n}\n\nfunction decodeBase64Url(value: string): string {\n const normalized = value.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const padded = normalized + \"=\".repeat((4 - (normalized.length % 4)) % 4);\n const binary = atob(padded);\n return new TextDecoder().decode(Uint8Array.from(binary, (ch) => ch.charCodeAt(0)));\n}\n\nfunction decodeBase64UrlBytes(value: string): Uint8Array {\n const normalized = value.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const padded = normalized + \"=\".repeat((4 - (normalized.length % 4)) % 4);\n const binary = atob(padded);\n const out = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i += 1) out[i] = binary.charCodeAt(i);\n return out;\n}\n","import {\n ChitmarkApiError,\n ChitmarkError,\n degradedChallengeVerdict,\n enforceDegradedNeverAllow,\n} from \"./errors.js\";\nimport {\n DEFAULT_TIMEOUT_MS,\n SDK_VERSION,\n envBaseUrl,\n resolveBaseUrl,\n} from \"./internal/constants.js\";\nimport { flattenHeaders, prepareSubject } from \"./internal/prepare.js\";\nimport {\n verifyVerdictToken,\n type VerdictTokenClaims,\n type VerifyVerdictTokenOptions,\n} from \"./verify-token.js\";\nimport type {\n ChallengeRequest,\n ChallengeResponse,\n ChallengeCompletionResponse,\n ChallengeProof,\n ChitmarkOptions,\n FeedbackRequest,\n FeedbackResponse,\n OnDegraded,\n PiiMode,\n Verdict,\n VerifyRequest,\n} from \"./types.js\";\n\n/**\n * Official Chitmark client (Open Agent Ledger): three verbs:\n * verify, feedback, challenge. Trust decisions on agent-mediated actions,\n * tuned by business outcomes.\n *\n * @example\n * ```ts\n * const chitmark = new Chitmark({ apiKey: process.env.CHITMARK_API_KEY! });\n * const verdict = await chitmark.verify({\n * action: \"signup\",\n * subject: { email, ip, userAgent },\n * });\n * ```\n */\nexport class Chitmark {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly timeoutMs: number;\n private readonly piiMode: PiiMode;\n private readonly onDegraded: OnDegraded;\n private readonly fetchImpl: typeof fetch;\n private readonly clientName: string;\n\n constructor(options: ChitmarkOptions) {\n if (!options.apiKey) {\n throw new ChitmarkError(\"Chitmark apiKey is required\");\n }\n if (options.onDegraded && options.onDegraded !== \"challenge\") {\n throw new ChitmarkError(\n 'onDegraded must be \"challenge\": fail to challenge, never to allow',\n );\n }\n this.apiKey = options.apiKey;\n this.baseUrl = resolveBaseUrl(options.env, options.baseUrl ?? envBaseUrl());\n this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n this.piiMode = options.piiMode ?? \"hashed\";\n this.onDegraded = \"challenge\";\n this.fetchImpl = options.fetch ?? globalThis.fetch.bind(globalThis);\n this.clientName = options.clientName ?? `chitmark-node/${SDK_VERSION}`;\n }\n\n /**\n * Score + route an inbound action (signup / trial / …).\n * Hot path at the edge; client budget defaults to 800ms.\n * On timeout/transport error, or a malformed verdict shape from the API,\n * returns a degraded challenge verdict (never allow, never crashes).\n *\n * Persist `v.eventId` on the account row: feedback joins only on that id.\n */\n async verify(request: VerifyRequest): Promise<Verdict> {\n const subject = await prepareSubject(\n {\n ...request.subject,\n headers: flattenHeaders(request.subject.headers),\n },\n this.piiMode,\n );\n\n const body: VerifyRequest = {\n ...request,\n subject,\n };\n\n try {\n const verdict = await this.request<Verdict>(\"/v1/verify\", {\n method: \"POST\",\n body,\n idempotencyKey: request.idempotencyKey,\n });\n if (!isWellFormedVerdict(verdict)) {\n return degradedChallengeVerdict(\n \"Degraded: verify returned a malformed verdict shape\",\n request.session,\n );\n }\n return enforceDegradedNeverAllow(verdict);\n } catch (err) {\n if (err instanceof ChitmarkApiError) {\n throw err;\n }\n return degradedChallengeVerdict(\n err instanceof Error ? `Degraded: ${err.message}` : \"Degraded: verify failed\",\n request.session,\n );\n }\n }\n\n /**\n * Report a downstream outcome joined on the stored eventId from verify.\n * This is the data moat: attribution is a schema contract, not a fuzzy match.\n * `idempotencyKey` is sent as both the Idempotency-Key header and body field\n * (header takes precedence server-side) so exact retries replay the original\n * acknowledgement.\n */\n async feedback(request: FeedbackRequest): Promise<FeedbackResponse> {\n return this.request<FeedbackResponse>(\"/v1/feedback\", {\n method: \"POST\",\n body: request,\n idempotencyKey: request.idempotencyKey,\n });\n }\n\n /**\n * Issue an asymmetric-cost challenge after decision === challenge | degraded.\n */\n async challenge(request: ChallengeRequest): Promise<ChallengeResponse> {\n return this.request<ChallengeResponse>(\"/v1/challenge\", {\n method: \"POST\",\n body: request,\n });\n }\n\n /**\n * Complete a challenge by submitting its solved proof. Clears only the bound\n * session, once. Re-verify with `context.challengeId` to have the next\n * verify honor the cleared session.\n */\n async completeChallenge(request: {\n eventId: string;\n challengeId: string;\n session: string;\n proof: ChallengeProof;\n }): Promise<ChallengeCompletionResponse> {\n return this.request<ChallengeCompletionResponse>(\"/v1/challenge\", {\n method: \"POST\",\n body: request,\n });\n }\n\n /**\n * Verify a verdictToken's signature against the API's JWKS and its session /\n * tenant binding. Rejects expired tokens, unknown kids, and\n * invalid signatures with `VerdictTokenError`. Pass `session` and `tenantId`\n * to enforce session and tenant binding (recommended); `aud` enforces the\n * origin hint only.\n */\n async verifyVerdictToken(\n token: string,\n options: Omit<VerifyVerdictTokenOptions, \"jwksUrl\" | \"fetch\"> = {},\n ): Promise<VerdictTokenClaims> {\n return verifyVerdictToken(token, {\n ...options,\n jwksUrl: `${this.baseUrl}/.well-known/jwks.json`,\n fetch: this.fetchImpl,\n });\n }\n\n /**\n * Low-level HTTP helper. Prefer verify / feedback / challenge.\n */\n async request<T>(\n path: string,\n init: {\n method: string;\n body?: unknown;\n idempotencyKey?: string;\n },\n ): Promise<T> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeoutMs);\n\n try {\n const headers: Record<string, string> = {\n Authorization: `Bearer ${this.apiKey}`,\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n \"User-Agent\": this.clientName,\n \"X-Chitmark-Client\": this.clientName,\n };\n if (init.idempotencyKey) {\n headers[\"Idempotency-Key\"] = init.idempotencyKey;\n }\n\n const res = await this.fetchImpl(`${this.baseUrl}${path}`, {\n method: init.method,\n headers,\n body: init.body !== undefined ? JSON.stringify(init.body) : undefined,\n signal: controller.signal,\n });\n\n const text = await res.text();\n let parsed: unknown = undefined;\n if (text) {\n try {\n parsed = JSON.parse(text) as unknown;\n } catch {\n parsed = text;\n }\n }\n\n if (!res.ok) {\n const errBody =\n typeof parsed === \"object\" && parsed !== null\n ? (parsed as { error?: string; message?: string; code?: string })\n : text;\n const normalized =\n typeof errBody === \"string\"\n ? errBody\n : {\n error: errBody.error ?? `http_${res.status}`,\n message: errBody.message,\n code: errBody.code,\n };\n throw new ChitmarkApiError(res.status, normalized);\n }\n\n return parsed as T;\n } catch (err) {\n if (err instanceof ChitmarkApiError) throw err;\n if (err instanceof Error && err.name === \"AbortError\") {\n throw new ChitmarkError(`Request timed out after ${this.timeoutMs}ms`, {\n code: \"timeout\",\n });\n }\n throw err instanceof Error\n ? new ChitmarkError(err.message, { code: \"transport\" })\n : new ChitmarkError(\"Unknown transport error\", { code: \"transport\" });\n } finally {\n clearTimeout(timer);\n }\n }\n\n /** Public accessors for inspection / tests. */\n get config(): {\n baseUrl: string;\n timeoutMs: number;\n piiMode: PiiMode;\n onDegraded: OnDegraded;\n } {\n return {\n baseUrl: this.baseUrl,\n timeoutMs: this.timeoutMs,\n piiMode: this.piiMode,\n onDegraded: this.onDegraded,\n };\n }\n}\n\nconst VERDICT_DECISIONS: ReadonlySet<string> = new Set([\"allow\", \"challenge\", \"deny\"]);\n\n/**\n * Minimal shape guard for a 200 verify response. A malformed verdict must\n * never be treated as allow: the gating fields are what gate correctness.\n */\nexport function isWellFormedVerdict(value: unknown): value is Verdict {\n if (typeof value !== \"object\" || value === null) return false;\n const v = value as Partial<Verdict>;\n return (\n typeof v.decision === \"string\" &&\n VERDICT_DECISIONS.has(v.decision) &&\n typeof v.eventId === \"string\" &&\n v.eventId.length > 0 &&\n typeof v.degraded === \"boolean\"\n );\n}\n","import type { Verdict } from \"./types.js\";\n\nexport const CHITMARK_HTTP_STATUS = {\n ok: 200,\n created: 201,\n badRequest: 400,\n unauthorized: 401,\n forbidden: 403,\n notFound: 404,\n conflict: 409,\n preconditionRequired: 428,\n tooManyRequests: 429,\n} as const;\n\nexport type ChitmarkHttpStatus =\n (typeof CHITMARK_HTTP_STATUS)[keyof typeof CHITMARK_HTTP_STATUS];\n\nexport const CHITMARK_HTTP_STATUS_MEANING = {\n ok: \"Request succeeded. For verify gates, continue only after an explicit non-degraded allow.\",\n created: \"Resource was created after an explicit non-degraded allow.\",\n badRequest: \"Required request fields are missing or malformed.\",\n unauthorized: \"API key is missing or invalid.\",\n forbidden: \"Verify returned deny; block the action.\",\n notFound: \"Referenced Chitmark resource was not found.\",\n conflict: \"Idempotency key was reused with a materially different payload.\",\n preconditionRequired:\n \"Verify returned challenge or degraded; require friction before continuing.\",\n tooManyRequests: \"Request was rate limited.\",\n} as const satisfies Record<keyof typeof CHITMARK_HTTP_STATUS, string>;\n\nexport function verdictToHttpStatus(verdict: Verdict): ChitmarkHttpStatus {\n if (verdict.degraded || verdict.decision === \"challenge\") {\n return CHITMARK_HTTP_STATUS.preconditionRequired;\n }\n if (verdict.decision === \"deny\") return CHITMARK_HTTP_STATUS.forbidden;\n return CHITMARK_HTTP_STATUS.ok;\n}\n","import { Chitmark } from \"./client.js\";\nimport type { Action, Verdict, VerifyContext, VerifyRequest } from \"./types.js\";\nimport { flattenHeaders } from \"./internal/prepare.js\";\n\nexport interface VerifyRequestFromRequestOptions {\n action: Action;\n session?: string;\n surface?: string;\n context?: VerifyContext;\n /** Dedupes retries; one verdict per action attempt. Sent as header + body. */\n idempotencyKey?: string;\n /** Optional body used for email / formData when already parsed. */\n body?: {\n email?: string;\n [key: string]: unknown;\n };\n /**\n * Override subject fields. By default reads IP / UA / headers from the Request.\n */\n subject?: VerifyRequest[\"subject\"];\n}\n\n/**\n * Edge-oriented helpers for Cloudflare Workers and other Fetch-API runtimes.\n * Import via `@chitmark/sdk/edge`.\n *\n * @example\n * ```ts\n * import { Chitmark } from \"@chitmark/sdk/edge\";\n * const chitmark = new Chitmark({ apiKey: env.CHITMARK_API_KEY });\n * const v = await chitmark.verifyRequest(req, { action: \"signup\" });\n * ```\n */\nexport class ChitmarkEdge extends Chitmark {\n /**\n * Build a verify call from a Fetch Request (headers, IP, body fields).\n */\n async verifyRequest(\n req: Request,\n options: VerifyRequestFromRequestOptions,\n ): Promise<Verdict> {\n const url = new URL(req.url);\n const ip =\n req.headers.get(\"cf-connecting-ip\") ??\n req.headers.get(\"x-forwarded-for\")?.split(\",\")[0]?.trim() ??\n \"\";\n const userAgent = req.headers.get(\"user-agent\") ?? \"\";\n const headers = flattenHeaders(req.headers);\n\n const subject = options.subject ?? {\n email: options.body?.email,\n ip,\n userAgent,\n headers,\n formData: options.body,\n };\n\n return this.verify({\n action: options.action,\n session: options.session,\n surface: options.surface ?? `${url.host}${url.pathname}`,\n subject,\n context: options.context,\n idempotencyKey: options.idempotencyKey,\n });\n }\n}\n\nexport { ChitmarkEdge as Chitmark };\nexport * from \"./types.js\";\nexport * from \"./errors.js\";\nexport * from \"./pii.js\";\nexport * from \"./http-status.js\";\nexport * from \"./verify-token.js\";\nexport { Chitmark as ChitmarkCore } from \"./client.js\";\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/internal/constants.ts","../src/pii.ts","../src/internal/prepare.ts","../src/verify-token.ts","../src/client.ts","../src/trusted-ip.ts","../src/http-status.ts","../src/edge.ts"],"names":["out"],"mappings":"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","file":"edge.cjs","sourcesContent":["import type { ChitmarkErrorBody, Decision, Verdict } from \"./types.js\";\n\n/**\n * Base error for all Chitmark client failures.\n */\nexport class ChitmarkError extends Error {\n override name = \"ChitmarkError\";\n readonly status?: number;\n readonly code?: string;\n readonly body?: ChitmarkErrorBody | string;\n\n constructor(\n message: string,\n options?: { status?: number; code?: string; body?: ChitmarkErrorBody | string },\n ) {\n super(message);\n this.status = options?.status;\n this.code = options?.code;\n this.body = options?.body;\n }\n}\n\n/**\n * Raised when the API returns a non-2xx response.\n */\nexport class ChitmarkApiError extends ChitmarkError {\n override name = \"ChitmarkApiError\";\n\n constructor(status: number, body: ChitmarkErrorBody | string, message?: string) {\n const msg =\n message ??\n (typeof body === \"string\"\n ? body\n : body.message || body.error || `Chitmark API error (${status})`);\n super(msg, {\n status,\n code: typeof body === \"object\" ? (body.code ?? body.error) : undefined,\n body,\n });\n }\n}\n\n/**\n * Build the degraded challenge verdict used on timeout / transport failure.\n * Golden rule: fail to challenge, never to allow.\n */\nexport function degradedChallengeVerdict(reason: string, session?: string): Verdict {\n return {\n decision: \"challenge\" satisfies Decision,\n actorType: \"unknown\",\n confidence: 0,\n reasons: [reason],\n principal: {\n resolved: false,\n identityBasis: [\"degraded\"],\n },\n verdictToken: \"\",\n eventId: `evt_degraded_${session ?? \"unknown\"}`,\n degraded: true,\n enforcementMode: \"enforce\",\n };\n}\n\n/**\n * Ensure degraded responses never surface as allow (defense in depth client-side).\n */\nexport function enforceDegradedNeverAllow(verdict: Verdict): Verdict {\n if (verdict.degraded && verdict.decision === \"allow\") {\n return {\n ...verdict,\n decision: \"challenge\",\n reasons: [\n ...verdict.reasons,\n \"Client enforced: degraded decision must not be allow\",\n ],\n };\n }\n return verdict;\n}\n","import type { ChitmarkEnv } from \"../types.js\";\n\nexport const DEFAULT_BASE_URLS: Record<ChitmarkEnv, string> = {\n production: \"https://api.chitmark.com\",\n staging: \"https://api.staging.chitmark.com\",\n development: \"http://127.0.0.1:8787\",\n};\n\nexport const DEFAULT_TIMEOUT_MS = 800;\n/** Keep in parity with the package version and the Python SDK. */\nexport const SDK_VERSION = \"0.6.0\";\n\nexport function resolveBaseUrl(\n env: ChitmarkEnv = \"production\",\n baseUrl?: string,\n): string {\n return (baseUrl ?? DEFAULT_BASE_URLS[env]).replace(/\\/$/, \"\");\n}\n\n/**\n * CHITMARK_BASE_URL environment override, when present (Node only, no-op on\n * Workers/browsers where `process` is undefined).\n */\nexport function envBaseUrl(): string | undefined {\n if (typeof process === \"undefined\") return undefined;\n const value = process.env?.CHITMARK_BASE_URL;\n return value ? value.trim() : undefined;\n}\n","/**\n * Client-side PII minimization helpers.\n * Default SDK mode hashes email and truncates IP before leaving the customer process.\n */\n\n/**\n * SHA-256 hex digest of lowercased, trimmed email.\n * Uses Web Crypto (Node 18+, browsers, Workers).\n */\nexport async function hashEmailSha256(email: string): Promise<string> {\n const normalized = email.trim().toLowerCase();\n const data = new TextEncoder().encode(normalized);\n const digest = await crypto.subtle.digest(\"SHA-256\", data);\n return bufferToHex(digest);\n}\n\n/**\n * Truncate IPv4 to /24 or IPv6 to /48 for coarse geo without host identity.\n */\nexport function truncateIp(ip: string): string {\n const trimmed = ip.trim();\n // IPv4 (optionally from x-forwarded-for first hop)\n const first = trimmed.split(\",\")[0]?.trim() ?? trimmed;\n if (first.includes(\".\") && !first.includes(\":\")) {\n const parts = first.split(\".\");\n if (parts.length === 4) {\n return `${parts[0]}.${parts[1]}.${parts[2]}.0/24`;\n }\n }\n // IPv6: keep first 3 hextets (~/48)\n if (first.includes(\":\")) {\n const hextets = first.split(\":\").filter(Boolean);\n const head = hextets.slice(0, 3).join(\":\");\n return `${head}::/48`;\n }\n return first;\n}\n\n/**\n * Reduce form payload to non-PII keys (domain-style fields only for hashed mode).\n * Free-text is dropped; companyDomain-style keys are kept as-is when domain-like.\n */\nexport function minimizeFormData(\n formData: Record<string, unknown> | undefined,\n): Record<string, unknown> | undefined {\n if (!formData) return undefined;\n const allowed = new Set([\n \"companyDomain\",\n \"company_domain\",\n \"domain\",\n \"plan\",\n \"referrer\",\n \"utm_source\",\n \"utm_medium\",\n \"utm_campaign\",\n ]);\n const out: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(formData)) {\n if (allowed.has(key) && value != null) {\n out[key] = value;\n }\n }\n return Object.keys(out).length > 0 ? out : undefined;\n}\n\nfunction bufferToHex(buffer: ArrayBuffer): string {\n const bytes = new Uint8Array(buffer);\n let hex = \"\";\n for (const b of bytes) {\n hex += b.toString(16).padStart(2, \"0\");\n }\n return hex;\n}\n","import type { PiiMode, Subject } from \"../types.js\";\nimport { hashEmailSha256, minimizeFormData, truncateIp } from \"../pii.js\";\n\n/**\n * Apply client-side PII mode to a subject before the wire.\n */\nexport async function prepareSubject(\n subject: Subject,\n piiMode: PiiMode,\n): Promise<Subject> {\n if (piiMode === \"raw\") {\n return subject;\n }\n\n if (piiMode === \"none\") {\n return {\n userAgent: subject.userAgent,\n headers: pickWebBotAuthHeaders(subject.headers),\n };\n }\n\n // hashed (default)\n const prepared: Subject = {\n userAgent: subject.userAgent,\n headers: subject.headers,\n };\n\n if (subject.emailSha256) {\n prepared.emailSha256 = subject.emailSha256;\n } else if (subject.email) {\n prepared.emailSha256 = await hashEmailSha256(subject.email);\n }\n\n if (subject.ipTrunc) {\n prepared.ipTrunc = subject.ipTrunc;\n } else if (subject.ip) {\n prepared.ipTrunc = truncateIp(subject.ip);\n }\n\n const hashedForm = subject.formDataHashed ?? minimizeFormData(subject.formData);\n if (hashedForm) {\n prepared.formDataHashed = hashedForm;\n }\n\n return prepared;\n}\n\nfunction pickWebBotAuthHeaders(\n headers?: Record<string, string | string[] | undefined>,\n): Record<string, string> | undefined {\n if (!headers) return undefined;\n const keys = [\"signature-agent\", \"signature-input\", \"signature\"];\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(headers)) {\n const lower = k.toLowerCase();\n if (keys.includes(lower) && typeof v === \"string\") {\n out[lower] = v;\n } else if (keys.includes(lower) && Array.isArray(v) && v[0]) {\n out[lower] = v[0];\n }\n }\n return Object.keys(out).length > 0 ? out : undefined;\n}\n\n/**\n * Normalize header maps (Node / Fetch) to plain string records for JSON.\n */\nexport function flattenHeaders(\n headers?: Record<string, string | string[] | undefined> | Headers,\n): Record<string, string> | undefined {\n if (!headers) return undefined;\n if (headers instanceof Headers) {\n const out: Record<string, string> = {};\n headers.forEach((value, key) => {\n out[key.toLowerCase()] = value;\n });\n return out;\n }\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(headers)) {\n if (typeof v === \"string\") out[k.toLowerCase()] = v;\n else if (Array.isArray(v) && v[0]) out[k.toLowerCase()] = v[0];\n }\n return out;\n}\n","/**\n * Client-side verdictToken verification.\n *\n * A verdictToken is an ES256 JWT decision receipt minted by the edge and bound\n * to session (`sub`), origin hint (`aud`), issuing tenant (`tid`), and a unique\n * `jti` (correlation id) with a short `exp` (5 minutes). Every signed token\n * requires a `kid` in the JWT header. Signature verification proves\n * authenticity and integrity; it does not make the JWT single-use. This module\n * always enforces `session` and `tenantId` (security boundary), validates\n * `iss` against the Chitmark issuer, and optionally `aud`. `aud` reflects\n * request headers and is attacker influenced: never enforce `aud` alone.\n * Rejection reasons are surfaced as `VerdictTokenError.code`.\n *\n * JWKS: respect `Cache-Control` and, when present, `ETag` /\n * `Last-Modified` via conditional requests (instead of a hard-coded\n * refresh interval). Refresh immediately on unknown `kid`. Do not fetch on\n * every verification; never permanently pin a single signing key. Each JWKS\n * key is EC P-256 for ES256: require JWT `alg === \"ES256\"` before verifying\n * (`wrong_algorithm` otherwise); never trust the token-requested algorithm.\n * Rotation overlaps old and new keys; keep the retiring key until tokens under it\n * expire (≥ 5 minutes + 60 seconds). Pass a cached `jwks` option to skip\n * the network call. An empty JWKS (`keys: []`) means no token can be\n * cryptographically verified: fail closed; never treat an empty set as\n * evidence that a token is valid (local/CI may emit `unsigned.<eventId>`).\n */\n\nimport { ChitmarkError } from \"./errors.js\";\nimport type { ActorType, Decision } from \"./types.js\";\n\n/** Canonical issuer claim on every signed verdictToken. */\nexport const VERDICT_TOKEN_ISSUER = \"https://api.chitmark.com\";\n\nexport interface VerdictTokenClaims {\n /** Issuer: https://api.chitmark.com. */\n iss: string;\n eventId: string;\n decision: Decision;\n actorType: ActorType;\n confidence: number;\n aud: string;\n sub: string;\n /** Issuing tenant, server-derived from the API key used at verify time. */\n tid: string;\n /** Unique token identifier (correlation). Not single-use unless you track it. */\n jti: string;\n iat: number;\n exp: number;\n degraded: boolean;\n}\n\nexport type VerdictTokenErrorCode =\n | \"malformed_token\"\n | \"wrong_algorithm\"\n | \"wrong_type\"\n | \"jwks_unavailable\"\n | \"unknown_kid\"\n | \"invalid_signature\"\n | \"expired\"\n | \"not_yet_valid\"\n | \"wrong_issuer\"\n | \"wrong_session\"\n | \"wrong_aud\"\n | \"wrong_tenant\";\n\nexport class VerdictTokenError extends ChitmarkError {\n override name = \"VerdictTokenError\";\n\n constructor(code: VerdictTokenErrorCode, message: string) {\n super(message, { code });\n }\n}\n\nexport interface VerifyVerdictTokenOptions {\n /** Expected session: token `sub` must equal this or verification fails. */\n session: string;\n /** Expected issuing tenant: token `tid` must equal this or verification fails. */\n tenantId: string;\n /** Expected origin hint: token `aud` must equal this or verification fails. */\n aud?: string;\n /**\n * Expected issuer (`iss`). Defaults to {@link VERDICT_TOKEN_ISSUER}.\n * Override only in tests.\n */\n issuer?: string;\n /** JWKS URL; defaults to https://api.chitmark.com/.well-known/jwks.json. */\n jwksUrl?: string;\n /**\n * Pre-fetched / cached JWKS; skips the network fetch when provided.\n * Prefer caching via HTTP headers (`Cache-Control`, `ETag`, and\n * `Last-Modified` when present) with conditional refresh and immediate\n * refresh on unknown `kid`, rather than fetching on every verification.\n */\n jwks?: { keys: Array<Record<string, unknown>> };\n /** Injectable fetch (Node 24+/browsers have a global). */\n fetch?: typeof fetch;\n /** Clock override for tests. */\n nowMs?: number;\n /** Clock skew tolerance in seconds; defaults to 30. */\n leewaySeconds?: number;\n}\n\nconst DEFAULT_JWKS_URL = \"https://api.chitmark.com/.well-known/jwks.json\";\nconst DEFAULT_LEEWAY_SECONDS = 30;\n\n/**\n * Verify a verdictToken signature and binding.\n *\n * `session` and `tenantId` are required: they are the security boundary for\n * cross-service authorization, not optional hints.\n */\nexport async function verifyVerdictToken(\n token: string,\n options: VerifyVerdictTokenOptions,\n): Promise<VerdictTokenClaims> {\n const nowMs = options.nowMs ?? Date.now();\n const leewaySeconds = options.leewaySeconds ?? DEFAULT_LEEWAY_SECONDS;\n\n const parts = token.split(\".\");\n if (parts.length !== 3) {\n throw new VerdictTokenError(\"malformed_token\", \"verdictToken must be a JWT\");\n }\n const [headerB64, payloadB64, signatureB64] = parts as [string, string, string];\n\n let header: Record<string, unknown>;\n let payload: Record<string, unknown>;\n try {\n header = JSON.parse(decodeBase64Url(headerB64)) as Record<string, unknown>;\n payload = JSON.parse(decodeBase64Url(payloadB64)) as Record<string, unknown>;\n } catch {\n throw new VerdictTokenError(\"malformed_token\", \"verdictToken is not valid JWT JSON\");\n }\n\n if (header[\"alg\"] !== \"ES256\") {\n throw new VerdictTokenError(\n \"wrong_algorithm\",\n `verdictToken must use ES256, got ${String(header[\"alg\"])}`,\n );\n }\n // RFC 8725 §3.11: explicit typing keeps this receipt distinct from any\n // other JWT a tenant might accept. The edge always mints typ \"JWT\".\n if (header[\"typ\"] !== \"JWT\") {\n throw new VerdictTokenError(\n \"wrong_type\",\n `verdictToken must be a JWT, got ${String(header[\"typ\"])}`,\n );\n }\n const kid = typeof header[\"kid\"] === \"string\" ? header[\"kid\"] : \"\";\n if (!kid) {\n throw new VerdictTokenError(\"unknown_kid\", \"verdictToken is missing kid\");\n }\n\n const exp = typeof payload[\"exp\"] === \"number\" ? payload[\"exp\"] : NaN;\n const iat = typeof payload[\"iat\"] === \"number\" ? payload[\"iat\"] : NaN;\n const nowSeconds = Math.floor(nowMs / 1000);\n if (Number.isFinite(exp) && exp < nowSeconds - leewaySeconds) {\n throw new VerdictTokenError(\"expired\", \"verdictToken has expired\");\n }\n if (Number.isFinite(iat) && iat > nowSeconds + leewaySeconds) {\n throw new VerdictTokenError(\"not_yet_valid\", \"verdictToken iat is in the future\");\n }\n\n const expectedIssuer = options.issuer ?? VERDICT_TOKEN_ISSUER;\n if (payload[\"iss\"] !== expectedIssuer) {\n throw new VerdictTokenError(\n \"wrong_issuer\",\n \"verdictToken was not issued by Chitmark\",\n );\n }\n if (payload[\"sub\"] !== options.session) {\n throw new VerdictTokenError(\n \"wrong_session\",\n \"verdictToken was minted for a different session\",\n );\n }\n if (payload[\"tid\"] !== options.tenantId) {\n throw new VerdictTokenError(\n \"wrong_tenant\",\n \"verdictToken was minted for a different tenant\",\n );\n }\n const expectedAud = options.aud;\n if (expectedAud !== undefined && payload[\"aud\"] !== expectedAud) {\n throw new VerdictTokenError(\n \"wrong_aud\",\n \"verdictToken was minted for a different origin\",\n );\n }\n\n const jwk = await findJwk(kid, options);\n if (!jwk) {\n throw new VerdictTokenError(\"unknown_kid\", `JWKS has no key for kid ${kid}`);\n }\n\n let publicKey: CryptoKey;\n try {\n publicKey = await crypto.subtle.importKey(\n \"jwk\",\n jwk as unknown as JsonWebKey,\n { name: \"ECDSA\", namedCurve: \"P-256\" },\n false,\n [\"verify\"],\n );\n } catch {\n throw new VerdictTokenError(\n \"invalid_signature\",\n \"JWKS key is not a valid P-256 public key\",\n );\n }\n\n const signatureBytes = decodeBase64UrlBytes(signatureB64);\n const signatureBuffer = new ArrayBuffer(signatureBytes.byteLength);\n new Uint8Array(signatureBuffer).set(signatureBytes);\n\n const valid = await crypto.subtle.verify(\n { name: \"ECDSA\", hash: \"SHA-256\" },\n publicKey,\n signatureBuffer,\n new TextEncoder().encode(`${headerB64}.${payloadB64}`),\n );\n if (!valid) {\n throw new VerdictTokenError(\n \"invalid_signature\",\n \"verdictToken signature failed verification\",\n );\n }\n\n return payload as unknown as VerdictTokenClaims;\n}\n\nasync function findJwk(\n kid: string,\n options: VerifyVerdictTokenOptions,\n): Promise<Record<string, unknown> | undefined> {\n let jwks = options.jwks;\n if (!jwks) {\n const jwksUrl = options.jwksUrl ?? DEFAULT_JWKS_URL;\n try {\n const fetchImpl = options.fetch ?? globalThis.fetch.bind(globalThis);\n const res = await fetchImpl(jwksUrl);\n if (!res.ok) {\n throw new Error(`JWKS fetch failed with ${res.status}`);\n }\n jwks = (await res.json()) as { keys: Array<Record<string, unknown>> };\n } catch (err) {\n throw new VerdictTokenError(\n \"jwks_unavailable\",\n `Failed to load JWKS from ${jwksUrl}: ${\n err instanceof Error ? err.message : \"unknown error\"\n }`,\n );\n }\n }\n if (!Array.isArray(jwks.keys)) {\n throw new VerdictTokenError(\"jwks_unavailable\", \"JWKS response has no keys array\");\n }\n return jwks.keys.find((key) => key[\"kid\"] === kid);\n}\n\nfunction decodeBase64Url(value: string): string {\n const normalized = value.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const padded = normalized + \"=\".repeat((4 - (normalized.length % 4)) % 4);\n const binary = atob(padded);\n return new TextDecoder().decode(Uint8Array.from(binary, (ch) => ch.charCodeAt(0)));\n}\n\nfunction decodeBase64UrlBytes(value: string): Uint8Array {\n const normalized = value.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const padded = normalized + \"=\".repeat((4 - (normalized.length % 4)) % 4);\n const binary = atob(padded);\n const out = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i += 1) out[i] = binary.charCodeAt(i);\n return out;\n}\n","import {\n ChitmarkApiError,\n ChitmarkError,\n degradedChallengeVerdict,\n enforceDegradedNeverAllow,\n} from \"./errors.js\";\nimport {\n DEFAULT_TIMEOUT_MS,\n SDK_VERSION,\n envBaseUrl,\n resolveBaseUrl,\n} from \"./internal/constants.js\";\nimport { flattenHeaders, prepareSubject } from \"./internal/prepare.js\";\nimport {\n verifyVerdictToken,\n type VerdictTokenClaims,\n type VerifyVerdictTokenOptions,\n} from \"./verify-token.js\";\nimport type {\n ChallengeRequest,\n ChallengeResponse,\n ChallengeCompletionResponse,\n ChallengeProof,\n ChitmarkOptions,\n FeedbackRequest,\n FeedbackResponse,\n OnDegraded,\n PiiMode,\n Verdict,\n VerifyRequest,\n} from \"./types.js\";\n\n/**\n * Official Chitmark client (Open Agent Ledger): three verbs:\n * verify, feedback, challenge. Trust decisions on agent-mediated actions,\n * tuned by business outcomes.\n *\n * @example\n * ```ts\n * const chitmark = new Chitmark({ apiKey: process.env.CHITMARK_API_KEY! });\n * const verdict = await chitmark.verify({\n * action: \"signup\",\n * subject: { email, ip, userAgent },\n * });\n * ```\n */\nexport class Chitmark {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly timeoutMs: number;\n private readonly piiMode: PiiMode;\n private readonly onDegraded: OnDegraded;\n private readonly fetchImpl: typeof fetch;\n private readonly clientName: string;\n\n constructor(options: ChitmarkOptions) {\n if (!options.apiKey) {\n throw new ChitmarkError(\"Chitmark apiKey is required\");\n }\n if (options.onDegraded && options.onDegraded !== \"challenge\") {\n throw new ChitmarkError(\n 'onDegraded must be \"challenge\": fail to challenge, never to allow',\n );\n }\n this.apiKey = options.apiKey;\n this.baseUrl = resolveBaseUrl(options.env, options.baseUrl ?? envBaseUrl());\n this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n this.piiMode = options.piiMode ?? \"hashed\";\n this.onDegraded = \"challenge\";\n this.fetchImpl = options.fetch ?? globalThis.fetch.bind(globalThis);\n this.clientName = options.clientName ?? `chitmark-node/${SDK_VERSION}`;\n }\n\n /**\n * Score + route an inbound action (signup / trial / …).\n * Client budget defaults to 800ms.\n *\n * Store-outage degradation arrives as **HTTP 200** with a Verdict body\n * (`degraded: true`, `decision: \"challenge\"`). The SDK deserializes that\n * like any other Verdict. Verify never returns HTTP 503.\n *\n * HTTP 4xx / 429 Error responses throw `ChitmarkApiError`. Transport\n * timeout / network failure (or a malformed 200 body) synthesizes a local\n * degraded challenge Verdict (never allow, never crashes).\n *\n * Persist `v.eventId` on the account row: feedback joins only on that id.\n */\n async verify(request: VerifyRequest): Promise<Verdict> {\n const subject = await prepareSubject(\n {\n ...request.subject,\n headers: flattenHeaders(request.subject.headers),\n },\n this.piiMode,\n );\n\n const body: VerifyRequest = {\n ...request,\n subject,\n };\n\n try {\n const verdict = await this.request<Verdict>(\"/v1/verify\", {\n method: \"POST\",\n body,\n idempotencyKey: request.idempotencyKey,\n });\n if (!isWellFormedVerdict(verdict)) {\n return degradedChallengeVerdict(\n \"Degraded: verify returned a malformed verdict shape\",\n request.session,\n );\n }\n return enforceDegradedNeverAllow(verdict);\n } catch (err) {\n if (err instanceof ChitmarkApiError) {\n throw err;\n }\n return degradedChallengeVerdict(\n err instanceof Error ? `Degraded: ${err.message}` : \"Degraded: verify failed\",\n request.session,\n );\n }\n }\n\n /**\n * Report a downstream outcome joined on the stored eventId from verify.\n *\n * Security invariant: feedback cannot create attribution. It only attaches\n * an outcome to an existing verify event for this tenant. Unknown or\n * cross-tenant eventIds return 404. Never invent a join from email/IP.\n *\n * Append-only (not latest-wins): multiple outcomes may attach to one\n * eventId. Exact duplicates share one feedbackId. Compatible labels\n * coexist; conflicting pairs quarantine the new observation without\n * deleting prior evidence. HTTP `{ ok: true }` still acknowledges\n * quarantined ingest.\n *\n * `idempotencyKey` is sent as both the Idempotency-Key header and body field\n * (header takes precedence server-side) so exact retries replay the original\n * acknowledgement.\n */\n async feedback(request: FeedbackRequest): Promise<FeedbackResponse> {\n return this.request<FeedbackResponse>(\"/v1/feedback\", {\n method: \"POST\",\n body: request,\n idempotencyKey: request.idempotencyKey,\n });\n }\n\n /**\n * Issue an asymmetric-cost challenge after decision === challenge | degraded.\n */\n async challenge(request: ChallengeRequest): Promise<ChallengeResponse> {\n return this.request<ChallengeResponse>(\"/v1/challenge\", {\n method: \"POST\",\n body: request,\n });\n }\n\n /**\n * Complete a challenge by submitting its solved proof. Clears only the bound\n * session, once. Does not authorize the action: re-verify with\n * `context.challengeId` and proceed only on non-degraded allow.\n */\n async completeChallenge(request: {\n eventId: string;\n challengeId: string;\n session: string;\n proof: ChallengeProof;\n }): Promise<ChallengeCompletionResponse> {\n return this.request<ChallengeCompletionResponse>(\"/v1/challenge\", {\n method: \"POST\",\n body: request,\n });\n }\n\n /**\n * Verify a verdictToken's signature against the API's JWKS and its session /\n * tenant binding. Prefers a cached `jwks` (refresh periodically and on\n * unknown `kid`); do not fetch on every call. Rejects expired tokens,\n * unknown kids, and invalid signatures with `VerdictTokenError`. Always\n * pass `session` and `tenantId` (required security boundary); `aud`\n * optionally enforces the origin hint only.\n */\n async verifyVerdictToken(\n token: string,\n options: Omit<VerifyVerdictTokenOptions, \"jwksUrl\" | \"fetch\">,\n ): Promise<VerdictTokenClaims> {\n return verifyVerdictToken(token, {\n ...options,\n jwksUrl: `${this.baseUrl}/.well-known/jwks.json`,\n fetch: this.fetchImpl,\n });\n }\n\n /**\n * Low-level HTTP helper. Prefer verify / feedback / challenge.\n */\n async request<T>(\n path: string,\n init: {\n method: string;\n body?: unknown;\n idempotencyKey?: string;\n },\n ): Promise<T> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeoutMs);\n\n try {\n const headers: Record<string, string> = {\n Authorization: `Bearer ${this.apiKey}`,\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n \"User-Agent\": this.clientName,\n \"X-Chitmark-Client\": this.clientName,\n };\n if (init.idempotencyKey) {\n headers[\"Idempotency-Key\"] = init.idempotencyKey;\n }\n\n const res = await this.fetchImpl(`${this.baseUrl}${path}`, {\n method: init.method,\n headers,\n body: init.body !== undefined ? JSON.stringify(init.body) : undefined,\n signal: controller.signal,\n });\n\n const text = await res.text();\n let parsed: unknown = undefined;\n if (text) {\n try {\n parsed = JSON.parse(text) as unknown;\n } catch {\n parsed = text;\n }\n }\n\n if (!res.ok) {\n const errBody =\n typeof parsed === \"object\" && parsed !== null\n ? (parsed as { error?: string; message?: string; code?: string })\n : text;\n const normalized =\n typeof errBody === \"string\"\n ? errBody\n : {\n error: errBody.error ?? `http_${res.status}`,\n message: errBody.message,\n code: errBody.code,\n };\n throw new ChitmarkApiError(res.status, normalized);\n }\n\n return parsed as T;\n } catch (err) {\n if (err instanceof ChitmarkApiError) throw err;\n if (err instanceof Error && err.name === \"AbortError\") {\n throw new ChitmarkError(`Request timed out after ${this.timeoutMs}ms`, {\n code: \"timeout\",\n });\n }\n throw err instanceof Error\n ? new ChitmarkError(err.message, { code: \"transport\" })\n : new ChitmarkError(\"Unknown transport error\", { code: \"transport\" });\n } finally {\n clearTimeout(timer);\n }\n }\n\n /** Public accessors for inspection / tests. */\n get config(): {\n baseUrl: string;\n timeoutMs: number;\n piiMode: PiiMode;\n onDegraded: OnDegraded;\n } {\n return {\n baseUrl: this.baseUrl,\n timeoutMs: this.timeoutMs,\n piiMode: this.piiMode,\n onDegraded: this.onDegraded,\n };\n }\n}\n\nconst VERDICT_DECISIONS: ReadonlySet<string> = new Set([\"allow\", \"challenge\", \"deny\"]);\n\n/**\n * Minimal shape guard for a 200 verify response. A malformed verdict must\n * never be treated as allow: the gating fields are what gate correctness.\n */\nexport function isWellFormedVerdict(value: unknown): value is Verdict {\n if (typeof value !== \"object\" || value === null) return false;\n const v = value as Partial<Verdict>;\n return (\n typeof v.decision === \"string\" &&\n VERDICT_DECISIONS.has(v.decision) &&\n typeof v.eventId === \"string\" &&\n v.eventId.length > 0 &&\n typeof v.degraded === \"boolean\"\n );\n}\n","/**\n * Resolve a client IP for verify subject signals from a Fetch Request.\n *\n * Prefer platform-set headers (`cf-connecting-ip`, `x-real-ip`,\n * `x-vercel-forwarded-for`). `X-Forwarded-For` is only safe when a trusted\n * proxy boundary strips or rewrites client-supplied values. Do not read XFF\n * on a directly reachable origin. On Cloudflare Workers, prefer\n * `verifyRequest` from `@chitmark/sdk/edge`, which owns this lookup.\n */\nexport function getTrustedClientIp(req: Request): string {\n const platform =\n req.headers.get(\"cf-connecting-ip\")?.trim() ||\n req.headers.get(\"x-real-ip\")?.trim() ||\n req.headers.get(\"x-vercel-forwarded-for\")?.split(\",\")[0]?.trim() ||\n \"\";\n if (platform) return platform;\n\n // Last resort: first XFF hop. Only valid behind a trusted proxy that\n // overwrites this header at the edge.\n return req.headers.get(\"x-forwarded-for\")?.split(\",\")[0]?.trim() ?? \"\";\n}\n","import type { Verdict } from \"./types.js\";\n\nexport const CHITMARK_HTTP_STATUS = {\n ok: 200,\n created: 201,\n badRequest: 400,\n unauthorized: 401,\n forbidden: 403,\n notFound: 404,\n conflict: 409,\n preconditionRequired: 428,\n tooManyRequests: 429,\n} as const;\n\nexport type ChitmarkHttpStatus =\n (typeof CHITMARK_HTTP_STATUS)[keyof typeof CHITMARK_HTTP_STATUS];\n\nexport const CHITMARK_HTTP_STATUS_MEANING = {\n ok: \"Request succeeded. For verify gates, continue only after an explicit non-degraded allow.\",\n created: \"Resource was created after an explicit non-degraded allow.\",\n badRequest: \"Required request fields are missing or malformed.\",\n unauthorized: \"API key is missing or invalid.\",\n forbidden: \"Verify returned deny; block the action.\",\n notFound: \"Referenced Chitmark resource was not found.\",\n conflict: \"Idempotency key is already associated with a different payload fingerprint.\",\n preconditionRequired:\n \"428 means the request is not rejected permanently; a required verification precondition must be satisfied before the action can proceed.\",\n tooManyRequests: \"Request was rate limited.\",\n} as const satisfies Record<keyof typeof CHITMARK_HTTP_STATUS, string>;\n\n/**\n * Explicit non-degraded allow. Use this (or `isEligibleAllow`) before any\n * protected action so unknown / malformed decisions cannot fall through.\n */\nexport type EligibleAllowVerdict = Verdict & {\n decision: \"allow\";\n degraded: false;\n};\n\n/**\n * Type guard for the only verdict that may continue a gated action.\n * Fail closed: anything that is not an explicit non-degraded allow is ineligible.\n */\nexport function isEligibleAllow(verdict: Verdict): verdict is EligibleAllowVerdict {\n return verdict.decision === \"allow\" && !verdict.degraded;\n}\n\n/**\n * Map a verify verdict to an HTTP status for framework drop-ins.\n * Unknown or malformed decisions fail to challenge (428), never to allow (200).\n */\nexport function verdictToHttpStatus(verdict: Verdict): ChitmarkHttpStatus {\n if (verdict.degraded || verdict.decision === \"challenge\") {\n return CHITMARK_HTTP_STATUS.preconditionRequired;\n }\n if (verdict.decision === \"deny\") return CHITMARK_HTTP_STATUS.forbidden;\n if (!isEligibleAllow(verdict)) {\n return CHITMARK_HTTP_STATUS.preconditionRequired;\n }\n return CHITMARK_HTTP_STATUS.ok;\n}\n","import { Chitmark } from \"./client.js\";\nimport type { Action, Verdict, VerifyContext, VerifyRequest } from \"./types.js\";\nimport { flattenHeaders } from \"./internal/prepare.js\";\nimport { getTrustedClientIp } from \"./trusted-ip.js\";\n\nexport interface VerifyRequestFromRequestOptions {\n action: Action;\n session?: string;\n surface?: string;\n context?: VerifyContext;\n /** Dedupes retries; one verdict per action attempt. Sent as header + body. */\n idempotencyKey?: string;\n /** Optional body used for email / formData when already parsed. */\n body?: {\n email?: string;\n [key: string]: unknown;\n };\n /**\n * Override subject fields. By default reads IP / UA / headers from the Request.\n */\n subject?: VerifyRequest[\"subject\"];\n}\n\n/**\n * Edge-oriented helpers for Cloudflare Workers and other Fetch-API runtimes.\n * Import via `@chitmark/sdk/edge`.\n *\n * @example\n * ```ts\n * import { Chitmark } from \"@chitmark/sdk/edge\";\n * const chitmark = new Chitmark({ apiKey: env.CHITMARK_API_KEY });\n * const v = await chitmark.verifyRequest(req, { action: \"signup\" });\n * ```\n */\nexport class ChitmarkEdge extends Chitmark {\n /**\n * Build a verify call from a Fetch Request (headers, IP, body fields).\n * IP resolution uses {@link getTrustedClientIp} (`cf-connecting-ip` first).\n */\n async verifyRequest(\n req: Request,\n options: VerifyRequestFromRequestOptions,\n ): Promise<Verdict> {\n const url = new URL(req.url);\n const ip = getTrustedClientIp(req);\n const userAgent = req.headers.get(\"user-agent\") ?? \"\";\n const headers = flattenHeaders(req.headers);\n\n const subject = options.subject ?? {\n email: options.body?.email,\n ip,\n userAgent,\n headers,\n formData: options.body,\n };\n\n return this.verify({\n action: options.action,\n session: options.session,\n surface: options.surface ?? `${url.host}${url.pathname}`,\n subject,\n context: options.context,\n idempotencyKey: options.idempotencyKey,\n });\n }\n}\n\nexport { ChitmarkEdge as Chitmark };\nexport * from \"./types.js\";\nexport * from \"./errors.js\";\nexport * from \"./pii.js\";\nexport * from \"./http-status.js\";\nexport * from \"./verify-token.js\";\nexport { getTrustedClientIp } from \"./trusted-ip.js\";\nexport { Chitmark as ChitmarkCore } from \"./client.js\";\n"]}
|
package/dist/edge.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { C as Chitmark, A as Action, V as VerifyContext, a as VerifyRequest, b as Verdict } from './
|
|
2
|
-
export { c as ActorType, d as CHITMARK_HTTP_STATUS, e as CHITMARK_HTTP_STATUS_MEANING, f as ChallengeCompletionResponse, g as ChallengeMethod, h as ChallengeProof, i as ChallengeRequest, j as ChallengeResponse, k as ChallengeRiskTier, l as ChitmarkApiError, m as ChitmarkEnv, n as ChitmarkError, o as ChitmarkErrorBody, p as ChitmarkHttpStatus, q as ChitmarkOptions, D as Decision, r as DecisionCosts, E as EnforcementMode, F as FeedbackRequest,
|
|
1
|
+
import { C as Chitmark, A as Action, V as VerifyContext, a as VerifyRequest, b as Verdict } from './trusted-ip-Fb-K6nwG.cjs';
|
|
2
|
+
export { c as ActorType, d as CHITMARK_HTTP_STATUS, e as CHITMARK_HTTP_STATUS_MEANING, f as ChallengeCompletionResponse, g as ChallengeMethod, h as ChallengeProof, i as ChallengeRequest, j as ChallengeResponse, k as ChallengeRiskTier, l as ChitmarkApiError, m as ChitmarkEnv, n as ChitmarkError, o as ChitmarkErrorBody, p as ChitmarkHttpStatus, q as ChitmarkOptions, D as Decision, r as DecisionCosts, E as EligibleAllowVerdict, s as EnforcementMode, F as FeedbackRequest, t as FeedbackResponse, u as FeedbackSource, v as FeedbackUnit, O as OnDegraded, w as Outcome, P as PiiMode, x as Principal, S as Subject, y as VERDICT_TOKEN_ISSUER, z as VerdictTokenClaims, B as VerdictTokenError, G as VerdictTokenErrorCode, H as VerifyVerdictTokenOptions, I as degradedChallengeVerdict, J as enforceDegradedNeverAllow, K as getTrustedClientIp, L as hashEmailSha256, M as isEligibleAllow, N as minimizeFormData, Q as truncateIp, R as verdictToHttpStatus, T as verifyVerdictToken } from './trusted-ip-Fb-K6nwG.cjs';
|
|
3
3
|
|
|
4
4
|
interface VerifyRequestFromRequestOptions {
|
|
5
5
|
action: Action;
|
|
@@ -32,6 +32,7 @@ interface VerifyRequestFromRequestOptions {
|
|
|
32
32
|
declare class ChitmarkEdge extends Chitmark {
|
|
33
33
|
/**
|
|
34
34
|
* Build a verify call from a Fetch Request (headers, IP, body fields).
|
|
35
|
+
* IP resolution uses {@link getTrustedClientIp} (`cf-connecting-ip` first).
|
|
35
36
|
*/
|
|
36
37
|
verifyRequest(req: Request, options: VerifyRequestFromRequestOptions): Promise<Verdict>;
|
|
37
38
|
}
|
package/dist/edge.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { C as Chitmark, A as Action, V as VerifyContext, a as VerifyRequest, b as Verdict } from './
|
|
2
|
-
export { c as ActorType, d as CHITMARK_HTTP_STATUS, e as CHITMARK_HTTP_STATUS_MEANING, f as ChallengeCompletionResponse, g as ChallengeMethod, h as ChallengeProof, i as ChallengeRequest, j as ChallengeResponse, k as ChallengeRiskTier, l as ChitmarkApiError, m as ChitmarkEnv, n as ChitmarkError, o as ChitmarkErrorBody, p as ChitmarkHttpStatus, q as ChitmarkOptions, D as Decision, r as DecisionCosts, E as EnforcementMode, F as FeedbackRequest,
|
|
1
|
+
import { C as Chitmark, A as Action, V as VerifyContext, a as VerifyRequest, b as Verdict } from './trusted-ip-Fb-K6nwG.js';
|
|
2
|
+
export { c as ActorType, d as CHITMARK_HTTP_STATUS, e as CHITMARK_HTTP_STATUS_MEANING, f as ChallengeCompletionResponse, g as ChallengeMethod, h as ChallengeProof, i as ChallengeRequest, j as ChallengeResponse, k as ChallengeRiskTier, l as ChitmarkApiError, m as ChitmarkEnv, n as ChitmarkError, o as ChitmarkErrorBody, p as ChitmarkHttpStatus, q as ChitmarkOptions, D as Decision, r as DecisionCosts, E as EligibleAllowVerdict, s as EnforcementMode, F as FeedbackRequest, t as FeedbackResponse, u as FeedbackSource, v as FeedbackUnit, O as OnDegraded, w as Outcome, P as PiiMode, x as Principal, S as Subject, y as VERDICT_TOKEN_ISSUER, z as VerdictTokenClaims, B as VerdictTokenError, G as VerdictTokenErrorCode, H as VerifyVerdictTokenOptions, I as degradedChallengeVerdict, J as enforceDegradedNeverAllow, K as getTrustedClientIp, L as hashEmailSha256, M as isEligibleAllow, N as minimizeFormData, Q as truncateIp, R as verdictToHttpStatus, T as verifyVerdictToken } from './trusted-ip-Fb-K6nwG.js';
|
|
3
3
|
|
|
4
4
|
interface VerifyRequestFromRequestOptions {
|
|
5
5
|
action: Action;
|
|
@@ -32,6 +32,7 @@ interface VerifyRequestFromRequestOptions {
|
|
|
32
32
|
declare class ChitmarkEdge extends Chitmark {
|
|
33
33
|
/**
|
|
34
34
|
* Build a verify call from a Fetch Request (headers, IP, body fields).
|
|
35
|
+
* IP resolution uses {@link getTrustedClientIp} (`cf-connecting-ip` first).
|
|
35
36
|
*/
|
|
36
37
|
verifyRequest(req: Request, options: VerifyRequestFromRequestOptions): Promise<Verdict>;
|
|
37
38
|
}
|