@solinkify/gate
Advanced tools
| /** Response header carrying the hash the gate filed, for immediate checking. */ | ||
| export declare const DELIVERY_HASH_HEADER = "x-solinkify-content-sha256"; | ||
| /** Default ceiling on what will be buffered to hash: 8 MB. */ | ||
| export declare const DEFAULT_DELIVERY_MAX_BYTES: number; | ||
| /** SHA-256 of raw bytes, lowercase hex. WebCrypto so this also runs on edge. */ | ||
| export declare function sha256Bytes(bytes: Uint8Array | ArrayBuffer): Promise<string>; | ||
| /** SHA-256 of a string, lowercase hex. */ | ||
| export declare function sha256Text(text: string): Promise<string>; | ||
| export interface FileDeliveryOptions { | ||
| apiUrl: string; | ||
| paymentId: string; | ||
| creatorWallet: string; | ||
| contentSha256: string; | ||
| contentLength: number; | ||
| } | ||
| /** | ||
| * File the creator-side hash. Fire-and-forget by design: a delivery record is | ||
| * bookkeeping, and a slow or down backend must never hold up paid content. | ||
| * Resolves to true only when the record was actually stored. | ||
| */ | ||
| export declare function fileCreatorDelivery(opts: FileDeliveryOptions): Promise<boolean>; | ||
| /** | ||
| * Hash a served `Response` and file it, returning a Response the caller can | ||
| * still send. The body is consumed to hash it, so a replacement carrying the | ||
| * same bytes is returned. | ||
| * | ||
| * Returns the original response untouched when there is nothing to record | ||
| * (no payment id, no body, or a body over the size ceiling). | ||
| */ | ||
| export declare function recordResponseDelivery(response: Response, opts: { | ||
| apiUrl: string; | ||
| creatorWallet: string; | ||
| paymentId: string | null | undefined; | ||
| maxBytes?: number; | ||
| }): Promise<Response>; | ||
| //# sourceMappingURL=delivery.d.ts.map |
| {"version":3,"file":"delivery.d.ts","sourceRoot":"","sources":["../src/delivery.ts"],"names":[],"mappings":"AAiBA,gFAAgF;AAChF,eAAO,MAAM,oBAAoB,+BAA+B,CAAC;AAEjE,8DAA8D;AAC9D,eAAO,MAAM,0BAA0B,QAAkB,CAAC;AAU1D,gFAAgF;AAChF,wBAAsB,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAOlF;AAED,0CAA0C;AAC1C,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAE9D;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC,CAiBrF;AAED;;;;;;;GAOG;AACH,wBAAsB,sBAAsB,CAC1C,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE;IACJ,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACrC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GACA,OAAO,CAAC,QAAQ,CAAC,CA8BnB"} |
+102
| // Delivery records — the creator half. | ||
| // | ||
| // x402 proves a payment happened and says nothing about what came back. When | ||
| // `deliveryRecords` is on, the gate hashes the body it served for a paid | ||
| // request and files that hash against the payment id. The paying agent files | ||
| // its own hash of what it received; a third party can then ask whether the two | ||
| // agree (GET /api/gate/delivery/{payment_id}). | ||
| // | ||
| // This is a commitment, not a proof of honest content: a creator that serves | ||
| // garbage can record the hash of that garbage. What it removes is the ability | ||
| // to serve one thing and later claim another. | ||
| // | ||
| // COST, which is why this is opt-in: hashing needs the whole body, so a | ||
| // streaming response has to be buffered. Bodies over `maxBytes` are skipped | ||
| // rather than held in memory, and the filing itself is fire-and-forget so it | ||
| // never delays or breaks the response the agent is waiting for. | ||
| /** Response header carrying the hash the gate filed, for immediate checking. */ | ||
| export const DELIVERY_HASH_HEADER = 'x-solinkify-content-sha256'; | ||
| /** Default ceiling on what will be buffered to hash: 8 MB. */ | ||
| export const DEFAULT_DELIVERY_MAX_BYTES = 8 * 1024 * 1024; | ||
| const encoder = new TextEncoder(); | ||
| function toHex(buffer) { | ||
| return Array.from(new Uint8Array(buffer)) | ||
| .map((b) => b.toString(16).padStart(2, '0')) | ||
| .join(''); | ||
| } | ||
| /** SHA-256 of raw bytes, lowercase hex. WebCrypto so this also runs on edge. */ | ||
| export async function sha256Bytes(bytes) { | ||
| const input = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes); | ||
| // Copy into a fresh ArrayBuffer: a Uint8Array view may be a slice of a larger | ||
| // buffer, and digesting the view's buffer would hash the wrong bytes. | ||
| const copy = new Uint8Array(input.byteLength); | ||
| copy.set(input); | ||
| return toHex(await crypto.subtle.digest('SHA-256', copy)); | ||
| } | ||
| /** SHA-256 of a string, lowercase hex. */ | ||
| export async function sha256Text(text) { | ||
| return sha256Bytes(encoder.encode(text)); | ||
| } | ||
| /** | ||
| * File the creator-side hash. Fire-and-forget by design: a delivery record is | ||
| * bookkeeping, and a slow or down backend must never hold up paid content. | ||
| * Resolves to true only when the record was actually stored. | ||
| */ | ||
| export async function fileCreatorDelivery(opts) { | ||
| try { | ||
| const res = await fetch(`${opts.apiUrl}/api/gate/delivery`, { | ||
| method: 'POST', | ||
| headers: { 'Content-Type': 'application/json' }, | ||
| body: JSON.stringify({ | ||
| payment_id: opts.paymentId, | ||
| creator_wallet: opts.creatorWallet, | ||
| content_sha256: opts.contentSha256, | ||
| content_length: opts.contentLength, | ||
| side: 'creator', | ||
| }), | ||
| }); | ||
| return res.ok; | ||
| } | ||
| catch { | ||
| return false; // never surface a bookkeeping failure to the agent | ||
| } | ||
| } | ||
| /** | ||
| * Hash a served `Response` and file it, returning a Response the caller can | ||
| * still send. The body is consumed to hash it, so a replacement carrying the | ||
| * same bytes is returned. | ||
| * | ||
| * Returns the original response untouched when there is nothing to record | ||
| * (no payment id, no body, or a body over the size ceiling). | ||
| */ | ||
| export async function recordResponseDelivery(response, opts) { | ||
| if (!opts.paymentId || !response.body) | ||
| return response; | ||
| const declared = Number(response.headers.get('content-length') ?? '0'); | ||
| const ceiling = opts.maxBytes ?? DEFAULT_DELIVERY_MAX_BYTES; | ||
| if (declared > ceiling) | ||
| return response; // too big to hold; skip rather than buffer | ||
| let bytes; | ||
| try { | ||
| bytes = new Uint8Array(await response.clone().arrayBuffer()); | ||
| } | ||
| catch { | ||
| return response; // unreadable body (already consumed upstream): leave it alone | ||
| } | ||
| if (bytes.byteLength > ceiling) | ||
| return response; | ||
| const hash = await sha256Bytes(bytes); | ||
| // Not awaited: the record is filed alongside the response, not before it. | ||
| void fileCreatorDelivery({ | ||
| apiUrl: opts.apiUrl, | ||
| paymentId: opts.paymentId, | ||
| creatorWallet: opts.creatorWallet, | ||
| contentSha256: hash, | ||
| contentLength: bytes.byteLength, | ||
| }); | ||
| // `bytes` is a view; hand the Response its own buffer so the body type is | ||
| // unambiguous across the DOM and Node typings. | ||
| const out = new Response(bytes.buffer.slice(0), response); | ||
| out.headers.set(DELIVERY_HASH_HEADER, hash); | ||
| return out; | ||
| } |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"astro.d.ts","sourceRoot":"","sources":["../src/astro.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAG7C,UAAU,gBAAgB;IACxB,OAAO,EAAE,OAAO,CAAC;CAClB;AACD,KAAK,SAAS,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAC;AAEzC,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,IAIlC,SAAS,gBAAgB,EAAE,MAAM,SAAS,KAAG,OAAO,CAAC,QAAQ,CAAC,CAO7E"} | ||
| {"version":3,"file":"astro.d.ts","sourceRoot":"","sources":["../src/astro.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAG7C,UAAU,gBAAgB;IACxB,OAAO,EAAE,OAAO,CAAC;CAClB;AACD,KAAK,SAAS,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAC;AAEzC,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,IAIlC,SAAS,gBAAgB,EAAE,MAAM,SAAS,KAAG,OAAO,CAAC,QAAQ,CAAC,CAS7E"} |
+4
-2
@@ -7,3 +7,3 @@ // Astro middleware adapter. Perfect fit for content sites. | ||
| import { assertValidConfig, resolveConfig, evaluateGate } from './core.js'; | ||
| import { fetchRequestToInfo, gateBlockResponse, gateChallengeResponse, markVerified } from './fetch.js'; | ||
| import { fetchRequestToInfo, gateBlockResponse, gateChallengeResponse, finishVerified } from './fetch.js'; | ||
| export function createAstroGate(config) { | ||
@@ -19,4 +19,6 @@ assertValidConfig(config); | ||
| const response = await next(); | ||
| return result.verified ? markVerified(response, result.botName) : response; | ||
| if (!result.verified) | ||
| return response; | ||
| return finishVerified(response, resolved, result.botName, context.request.headers.get('x-solinkify-payment')); | ||
| }; | ||
| } |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"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"} | ||
| {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"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"} |
+9
-0
@@ -9,2 +9,3 @@ // Framework-agnostic core for @solinkify/gate. | ||
| import { detectBot } from './detector.js'; | ||
| import { DEFAULT_DELIVERY_MAX_BYTES } from './delivery.js'; | ||
| import { verifyBotIp } from './detectors/verify-ip.js'; | ||
@@ -61,2 +62,4 @@ import { analyzeHeadless } from './detectors/headless-heuristics.js'; | ||
| analytics: config.analytics ?? true, | ||
| deliveryRecords: config.deliveryRecords ?? false, | ||
| deliveryMaxBytes: config.deliveryMaxBytes ?? DEFAULT_DELIVERY_MAX_BYTES, | ||
| challenge: config.challenge ?? false, | ||
@@ -207,2 +210,5 @@ challengeDifficulty: Math.min(20, Math.max(8, config.challengeDifficulty ?? 12)), | ||
| access_modes: buildAccessModes(config), | ||
| // Only claimed when the gate really files a hash — an agent that sees this | ||
| // flag will look for a record, and a false promise is worse than silence. | ||
| ...(config.deliveryRecords ? { delivery_records: true } : {}), | ||
| }; | ||
@@ -281,2 +287,5 @@ } | ||
| access_modes: buildAccessModes(config), | ||
| // Only claimed when the gate really files a hash — an agent that sees this | ||
| // flag will look for a record, and a false promise is worse than silence. | ||
| ...(config.deliveryRecords ? { delivery_records: true } : {}), | ||
| }; | ||
@@ -283,0 +292,0 @@ } |
+6
-0
@@ -18,2 +18,8 @@ import type { GateRequestInfo, GateResult, ResolvedGateConfig } from './core.js'; | ||
| /** | ||
| * Finish a verified response: verification headers, plus a delivery record when | ||
| * the gate is configured to file one. Adapters that hold a `Response` call this | ||
| * so the recording rule lives in one place. | ||
| */ | ||
| export declare function finishVerified(response: Response, resolved: ResolvedGateConfig, botName: string | null | undefined, paymentId: string | null | undefined): Promise<Response>; | ||
| /** | ||
| * One-call guard for any Fetch handler: evaluate a `Request` and either return a | ||
@@ -20,0 +26,0 @@ * 402 `Response` to send now, or produce the downstream `Response` via `next` |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../src/fetch.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAEjF;;;mFAGmF;AACnF,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,UAAO,GAAG,eAAe,CAcvF;AAED,4DAA4D;AAC5D,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,OAAO,CAAC,UAAU,EAAE;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,CAAC,GAC/C,QAAQ,CAKV;AAED,kFAAkF;AAClF,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,OAAO,CAAC,UAAU,EAAE;IAAE,MAAM,EAAE,WAAW,CAAA;CAAE,CAAC,GACnD,QAAQ,CAKV;AAED,kFAAkF;AAClF,wBAAgB,YAAY,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,QAAQ,CAI7F;AAED;;;;;;GAMG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,kBAAkB,EAC5B,IAAI,EAAE,MAAM,OAAO,CAAC,QAAQ,CAAC,GAAG,QAAQ,GACvC,OAAO,CAAC,QAAQ,CAAC,CAMnB"} | ||
| {"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../src/fetch.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAGjF;;;mFAGmF;AACnF,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,UAAO,GAAG,eAAe,CAcvF;AAED,4DAA4D;AAC5D,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,OAAO,CAAC,UAAU,EAAE;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,CAAC,GAC/C,QAAQ,CAKV;AAED,kFAAkF;AAClF,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,OAAO,CAAC,UAAU,EAAE;IAAE,MAAM,EAAE,WAAW,CAAA;CAAE,CAAC,GACnD,QAAQ,CAKV;AAED,kFAAkF;AAClF,wBAAgB,YAAY,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,QAAQ,CAI7F;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAClC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACnC,OAAO,CAAC,QAAQ,CAAC,CASnB;AAED;;;;;;GAMG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,kBAAkB,EAC5B,IAAI,EAAE,MAAM,OAAO,CAAC,QAAQ,CAAC,GAAG,QAAQ,GACvC,OAAO,CAAC,QAAQ,CAAC,CAQnB"} |
+20
-1
@@ -6,2 +6,3 @@ // Shared helpers for Web Fetch API frameworks (Astro, SvelteKit, Hono, Nuxt/ | ||
| import { evaluateGate } from './core.js'; | ||
| import { recordResponseDelivery } from './delivery.js'; | ||
| /** Extract the neutral GateRequestInfo from a Fetch `Request`. | ||
@@ -47,2 +48,18 @@ * A Fetch `Request` carries no socket, so with `trustProxy: false` the IP is | ||
| /** | ||
| * Finish a verified response: verification headers, plus a delivery record when | ||
| * the gate is configured to file one. Adapters that hold a `Response` call this | ||
| * so the recording rule lives in one place. | ||
| */ | ||
| export async function finishVerified(response, resolved, botName, paymentId) { | ||
| const marked = markVerified(new Response(response.body, response), botName); | ||
| if (!resolved.deliveryRecords) | ||
| return marked; | ||
| return recordResponseDelivery(marked, { | ||
| apiUrl: resolved.apiUrl, | ||
| creatorWallet: resolved.wallet, | ||
| paymentId, | ||
| maxBytes: resolved.deliveryMaxBytes, | ||
| }); | ||
| } | ||
| /** | ||
| * One-call guard for any Fetch handler: evaluate a `Request` and either return a | ||
@@ -61,3 +78,5 @@ * 402 `Response` to send now, or produce the downstream `Response` via `next` | ||
| const response = await next(); | ||
| return result.verified ? markVerified(new Response(response.body, response), result.botName) : response; | ||
| if (!result.verified) | ||
| return response; | ||
| return finishVerified(response, resolved, result.botName, request.headers.get('x-solinkify-payment')); | ||
| } |
+2
-3
@@ -7,3 +7,3 @@ // Hono middleware adapter — covers Hono on Cloudflare Workers, Deno, Bun, | ||
| import { assertValidConfig, resolveConfig, evaluateGate } from './core.js'; | ||
| import { fetchRequestToInfo, gateBlockResponse, gateChallengeResponse } from './fetch.js'; | ||
| import { fetchRequestToInfo, gateBlockResponse, gateChallengeResponse, finishVerified } from './fetch.js'; | ||
| export function createHonoGate(config) { | ||
@@ -20,6 +20,5 @@ assertValidConfig(config); | ||
| if (result.verified) { | ||
| c.res.headers.set('X-Solinkify-Verified', 'true'); | ||
| c.res.headers.set('X-Solinkify-Bot', result.botName ?? 'unknown'); | ||
| c.res = await finishVerified(c.res, resolved, result.botName, c.req.raw.headers.get('x-solinkify-payment')); | ||
| } | ||
| }; | ||
| } |
+2
-0
@@ -24,2 +24,4 @@ export { protectFromAI } from './middleware.js'; | ||
| export { checkRateExceeded } from './rate.js'; | ||
| export { recordResponseDelivery, fileCreatorDelivery, sha256Bytes, sha256Text, DELIVERY_HASH_HEADER, DEFAULT_DELIVERY_MAX_BYTES, } from './delivery.js'; | ||
| export type { FileDeliveryOptions } from './delivery.js'; | ||
| export { stablecoinMint, STABLECOIN_MINTS } from './constants.js'; | ||
@@ -26,0 +28,0 @@ export type { Stablecoin, SolanaNetwork } from './constants.js'; |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGhD,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACvE,YAAY,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAG7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,YAAY,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGzF,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,YAAY,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxD,YAAY,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAC3G,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG7F,OAAO,EACL,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,WAAW,EACX,aAAa,EACb,eAAe,EACf,cAAc,EACd,WAAW,EACX,sBAAsB,EACtB,gBAAgB,EAChB,YAAY,EACZ,eAAe,GAChB,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,eAAe,EAAE,UAAU,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAGpG,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAGxC,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAGhD,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,cAAc,EACd,UAAU,EACV,SAAS,EACT,eAAe,GAChB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAG9C,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAGhE,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC9E,YAAY,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AACrE,YAAY,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAG9D,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAClE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,YAAY,EACV,UAAU,EACV,QAAQ,EACR,WAAW,EACX,aAAa,EACb,kBAAkB,EAClB,eAAe,EACf,uBAAuB,EACvB,qBAAqB,EACrB,WAAW,EACX,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,YAAY,CAAC"} | ||
| {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"} |
+2
-0
@@ -26,2 +26,4 @@ // Next.js adapter (default entry) | ||
| export { checkRateExceeded } from './rate.js'; | ||
| // Delivery records (opt-in): hash what was served, file it against the payment | ||
| export { recordResponseDelivery, fileCreatorDelivery, sha256Bytes, sha256Text, DELIVERY_HASH_HEADER, DEFAULT_DELIVERY_MAX_BYTES, } from './delivery.js'; | ||
| // Multi-stablecoin helpers | ||
@@ -28,0 +30,0 @@ export { stablecoinMint, STABLECOIN_MINTS } from './constants.js'; |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"sveltekit.d.ts","sourceRoot":"","sources":["../src/sveltekit.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAG7C,UAAU,cAAc;IACtB,OAAO,EAAE,OAAO,CAAC;CAClB;AACD,UAAU,mBAAmB;IAC3B,KAAK,EAAE,cAAc,CAAC;IACtB,OAAO,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;CACvD;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,UAAU,IAItC,oBAAoB,mBAAmB,KAAG,OAAO,CAAC,QAAQ,CAAC,CAO1E"} | ||
| {"version":3,"file":"sveltekit.d.ts","sourceRoot":"","sources":["../src/sveltekit.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAG7C,UAAU,cAAc;IACtB,OAAO,EAAE,OAAO,CAAC;CAClB;AACD,UAAU,mBAAmB;IAC3B,KAAK,EAAE,cAAc,CAAC;IACtB,OAAO,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;CACvD;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,UAAU,IAItC,oBAAoB,mBAAmB,KAAG,OAAO,CAAC,QAAQ,CAAC,CAS1E"} |
@@ -9,3 +9,3 @@ // SvelteKit server hook adapter. | ||
| import { assertValidConfig, resolveConfig, evaluateGate } from './core.js'; | ||
| import { fetchRequestToInfo, gateBlockResponse, gateChallengeResponse, markVerified } from './fetch.js'; | ||
| import { fetchRequestToInfo, gateBlockResponse, gateChallengeResponse, finishVerified } from './fetch.js'; | ||
| export function createSvelteKitGate(config) { | ||
@@ -21,4 +21,6 @@ assertValidConfig(config); | ||
| const response = await resolve(event); | ||
| return result.verified ? markVerified(response, result.botName) : response; | ||
| if (!result.verified) | ||
| return response; | ||
| return finishVerified(response, resolved, result.botName, event.request.headers.get('x-solinkify-payment')); | ||
| }; | ||
| } |
+18
-0
@@ -68,2 +68,14 @@ export interface GateConfig { | ||
| /** | ||
| * Record what was served for each paid request: the gate hashes the response | ||
| * body and files it against the payment id, the paying agent files its own | ||
| * hash, and either party can later show whether the two agree. | ||
| * | ||
| * OFF by default because hashing needs the whole body, so a streamed response | ||
| * has to be buffered. Bodies larger than `deliveryMaxBytes` are skipped. | ||
| * Adapters that never see the body (Next.js middleware) ignore this. | ||
| */ | ||
| deliveryRecords?: boolean; | ||
| /** Ceiling on a buffered body, in bytes. Default 8 MB. */ | ||
| deliveryMaxBytes?: number; | ||
| /** | ||
| * Lapis 4 — JS proof-of-work challenge (opt-in AGRESIF, default false). | ||
@@ -162,2 +174,5 @@ * Semua trafik NON-bot di path terproteksi harus lolos interstisial JS sekali | ||
| access_modes?: GateAccessModes; | ||
| /** True when this gate files a hash of what it served for each paid | ||
| * request, so an agent can check its own copy against the record. */ | ||
| delivery_records?: boolean; | ||
| } | ||
@@ -233,2 +248,5 @@ /** No-tx-per-request access options: pre-paid balance (deposit once via | ||
| access_modes?: GateAccessModes; | ||
| /** True when this gate files a hash of what it served for each paid | ||
| * request, so an agent can check its own copy against the record. */ | ||
| delivery_records?: boolean; | ||
| } | ||
@@ -235,0 +253,0 @@ export interface VerificationRequest { |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"} | ||
| {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,SAAS,CAAC;IAC3C;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC;IACnB;;;;OAIG;IACH,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;;;;;OAQG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,0DAA0D;IAC1D,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,mFAAmF;IACnF,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,wDAAwD;IACxD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,SAAS,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IACjC;;;;;;;;OAQG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,mEAAmE;IACnE,GAAG,EAAE,MAAM,CAAC;IACZ,gEAAgE;IAChE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,8EAA8E;AAC9E,MAAM,WAAW,WAAW;IAC1B,sDAAsD;IACtD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,QAAQ;IACvB,4EAA4E;IAC5E,OAAO,EAAE,MAAM,CAAC;IAChB,iFAAiF;IACjF,UAAU,EAAE,MAAM,CAAC;IACnB,gEAAgE;IAChE,KAAK,EAAE,MAAM,CAAC;IACd,8EAA8E;IAC9E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,MAAM,GAAG,QAAQ,CAAC;CAC/B;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,kBAAkB,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IACpC,OAAO,EAAE;QACP,cAAc,EAAE,MAAM,CAAC;QACvB,UAAU,EAAE,MAAM,CAAC;QACnB,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,IAAI,EAAE;QACJ,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IAEF,uEAAuE;IACvE,WAAW,EAAE,CAAC,CAAC;IACf;wCACoC;IACpC,QAAQ,EAAE,gBAAgB,CAAC;IAC3B;iFAC6E;IAC7E,OAAO,EAAE,uBAAuB,EAAE,CAAC;IACnC,wEAAwE;IACxE,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,4EAA4E;IAC5E,YAAY,CAAC,EAAE,eAAe,CAAC;IAC/B;0EACsE;IACtE,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;iDAEiD;AACjD,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE;QACP,6EAA6E;QAC7E,MAAM,EAAE,MAAM,CAAC;QACf,yEAAyE;QACzE,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,YAAY,EAAE;QACZ,8EAA8E;QAC9E,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED,+DAA+D;AAC/D,MAAM,WAAW,gBAAgB;IAC/B,oFAAoF;IACpF,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;+DAE+D;AAC/D,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,OAAO,CAAC;IAChB,iFAAiF;IACjF,OAAO,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,MAAM,EAAE,MAAM,CAAC;IACf,0DAA0D;IAC1D,KAAK,EAAE,MAAM,CAAC;IACd,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAC;IACd,8EAA8E;IAC9E,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED;+EAC+E;AAC/E,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,GAAG,CAAC;IACb,IAAI,EAAE,WAAW,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE;QACP,MAAM,EAAE,oBAAoB,CAAC;QAC7B,cAAc,EAAE,MAAM,CAAC;QACvB,YAAY,EAAE,MAAM,CAAC;QACrB,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,kEAAkE;IAClE,SAAS,EAAE,KAAK,CAAC;QACf,WAAW,EAAE,MAAM,CAAC;QACpB,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC,CAAC;IACH,IAAI,EAAE;QAAE,WAAW,EAAE,CAAC,CAAC;QAAC,QAAQ,EAAE,gBAAgB,CAAC;QAAC,OAAO,EAAE,uBAAuB,EAAE,CAAA;KAAE,CAAC;IACzF,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,4EAA4E;IAC5E,YAAY,CAAC,EAAE,eAAe,CAAC;IAC/B;0EACsE;IACtE,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,QAAQ,GAAG,UAAU,GAAG,UAAU,GAAG,UAAU,CAAC;IACvD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;+CAE2C;IAC3C,OAAO,CAAC,EAAE,WAAW,CAAC;CACvB;AAED,sEAAsE;AACtE,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,2EAA2E;IAC3E,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,2CAA2C;IAC3C,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,qEAAqE;IACrE,WAAW,EAAE,MAAM,CAAC;CACrB"} |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAG7C,MAAM,WAAW,SAAS;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,wBAAwB,CAAC,EAAE,MAAM,CAAC;CACnC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,MAAM,OAAO,CAAC,QAAQ,CAAC,GAAG,QAAQ,GACvC,OAAO,CAAC,QAAQ,CAAC,CA4CnB;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,KACnB,SAAS,OAAO,EAAE,KAAK,SAAS,KAAG,OAAO,CAAC,QAAQ,CAAC,CAkBnE"} | ||
| {"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAI7C,MAAM,WAAW,SAAS;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,wBAAwB,CAAC,EAAE,MAAM,CAAC;CACnC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,MAAM,OAAO,CAAC,QAAQ,CAAC,GAAG,QAAQ,GACvC,OAAO,CAAC,QAAQ,CAAC,CAwCnB;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,KACnB,SAAS,OAAO,EAAE,KAAK,SAAS,KAAG,OAAO,CAAC,QAAQ,CAAC,CAkBnE"} |
+4
-7
| import { assertValidConfig, resolveConfig, evaluateGate } from './core.js'; | ||
| import { finishVerified } from './fetch.js'; | ||
| /** | ||
@@ -51,9 +52,5 @@ * Cloudflare Worker / Web Fetch adapter — framework-agnostic, works on any | ||
| const response = await next(); | ||
| if (result.verified) { | ||
| const mutable = new Response(response.body, response); | ||
| mutable.headers.set('X-Solinkify-Verified', 'true'); | ||
| mutable.headers.set('X-Solinkify-Bot', result.botName ?? 'unknown'); | ||
| return mutable; | ||
| } | ||
| return response; | ||
| if (!result.verified) | ||
| return response; | ||
| return finishVerified(response, resolved, result.botName, request.headers.get('x-solinkify-payment')); | ||
| } | ||
@@ -60,0 +57,0 @@ /** |
+6
-1
| { | ||
| "name": "@solinkify/gate", | ||
| "version": "0.4.1", | ||
| "version": "0.4.2", | ||
| "description": "Creator middleware (Next.js, Express, Cloudflare Workers) — blocks AI scrapers with HTTP 402 paywall, monetizes ethical AI agents on Solana.", | ||
@@ -73,2 +73,7 @@ "type": "module", | ||
| "default": "./dist/lambda-edge.js" | ||
| }, | ||
| "./delivery": { | ||
| "types": "./dist/delivery.d.ts", | ||
| "import": "./dist/delivery.js", | ||
| "default": "./dist/delivery.js" | ||
| } | ||
@@ -75,0 +80,0 @@ }, |
+39
-0
@@ -262,2 +262,41 @@ # @solinkify/gate | ||
| ## Delivery records (opt-in): prove what was served | ||
| x402 proves a payment happened and says nothing about what came back. Turn this | ||
| on and the gate hashes the body it served for a paid request and files that hash | ||
| against the payment id. The paying agent files its own hash of what it received, | ||
| and anyone holding the payment id can ask whether the two agree. | ||
| ```ts | ||
| protectFromAI({ | ||
| wallet: 'YOUR_WALLET', | ||
| price: 0.001, | ||
| deliveryRecords: true, // off by default | ||
| deliveryMaxBytes: 8 * 1024 * 1024, // skip bodies larger than this | ||
| }); | ||
| ``` | ||
| Paid responses come back with `x-solinkify-content-sha256`, and the 402 manifest | ||
| and `/.well-known/solinkify` both advertise `delivery_records: true` so agents | ||
| know to expect one. Read the result: | ||
| ```bash | ||
| curl https://api.solinkify.com/api/gate/delivery/<payment_id> | ||
| # → { creator: {...}, agent: {...}, match: true } | ||
| ``` | ||
| **What it proves.** That neither side can serve one thing and later claim | ||
| another. `match: false` is evidence; `match: null` means only one side filed. | ||
| It is NOT proof the content was correct: a creator that serves garbage can | ||
| record the hash of that garbage. | ||
| **Cost.** Hashing needs the whole body, so responses are buffered up to | ||
| `deliveryMaxBytes` (larger ones stream as usual and are skipped). Filing is | ||
| fire-and-forget and never delays or fails the response. | ||
| **Where it works.** Adapters that can see the response body: `guardFetch`, | ||
| Astro, SvelteKit, Hono, Cloudflare Workers, and the reverse proxy. Next.js | ||
| middleware, Nuxt, Lambda@Edge and the WordPress plugin never touch the body, so | ||
| the flag is ignored there and only the agent side can be filed. | ||
| ## SEO-safe by default (+ robots.txt) | ||
@@ -264,0 +303,0 @@ |
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
172006
7.84%83
3.75%2838
7.3%342
12.87%9
12.5%