Card data is tokenised on the client by the gateway SDK; server code never reads a raw card number, verification code or expiry from the request and never passes a raw card to a gateway call; browser code never posts raw card fields to the application's own server. No AI engine is involved: the verdict is reproducible from the source alone.
Inputs
Non-test code files of the checkout (JavaScript, TypeScript, Python, PHP) and the dependency manifests (package.json, composer.json, requirements.txt, pyproject.toml, Pipfile), to detect the gateway. Files are classified as browser or server code (Python and PHP are server; JavaScript and TypeScript by path, 'use client' and what they touch). Server code is analysed per FUNCTION UNIT (tokens, function units, calls and route registrations of Next, Express, Fastify, Koa, Hono, Nest, Lambda, Django, Flask, FastAPI and Laravel, plus the code outside every function); browser code per call. Identifiers are read from tokens: a card field named in a string, a comment or a log message never counts. Paths listed in excludes (test, spec and tmp files, __tests__, __mocks__, fixtures, test, tests and audit-scripts folders) are never analysed. Nothing of the checkout is executed.
Decision rule
A file is judged SERVER only with proof of its own runtime or of the import graph: the language (Python, PHP), a `server-only` import or a `'use server'` directive, a location the framework declares as server (route.ts, middleware, pages/api, app/api, *.server.*, +server, wsgi/asgi), a Node built-in or server-only package, an HTTP response sink or a Lambda handler export, importing a module that is itself proven to run on a server, or a server folder by framework convention. It is judged BROWSER when it declares `'use client'` or imports `client-only`, when its code touches the DOM, a Web Worker scope, `new Worker(`, a React client hook or a browser-environment polyfill, when a client-declared file of the checkout imports it, when it sits in a browser folder by convention, or when it only uses a Web API the browser serves (`crypto.subtle`, `globalThis.crypto`, `CryptoKey`, `new Blob`, `atob`) with no server evidence at all. NEITHER is NOT server: the shared layer of a monorepo is never accused on a folder name, and the trace says the layer is unproven. `workers/` is not a server folder (a worker folder is a browser convention as often as a server one). Not applicable when no gateway SDK, namespace or API host is referenced in the code or the dependency manifests. FAIL (HIGH, with the line) when a server function reads a raw card number, PAN, CVV/CVC or security code out of the request — a member access, an index or an accessor call on the request object (req.body.cardNumber, request.POST['cvv'], $request->input('card_number'), $_POST['pan']) or a destructuring whose source is the request — or when a server function passes a raw card to a gateway SDK call that creates a token, source, payment method, charge or transaction (a card wrapper with a number or verification key, or a number key next to a verification or expiry key). Reading only the expiry from the request is MEDIUM (blocks in Extended suites). FAIL (HIGH) when browser code calls fetch, axios, jQuery, XMLHttpRequest or a .post/.put of the application with a body that names the PAN or the verification code, unless the call targets a gateway host or a tokenisation endpoint. Roots that usually hold the parsed body (body, payload, data, params, input, form, event) count only inside a function that receives the request (a registered route handler, a function reading the request object, or one whose first parameter is the request or the event). PASS when a gateway is in use and no server function and no browser call matches; the summary counts the functions scanned. Not judged by this check (declared): card fields read from a request object passed to a helper under a name outside the request vocabulary (unless they reach a gateway call), typed request models read through a parameter of another name, a gateway call whose argument is a variable built elsewhere, a browser body built from a variable or a FormData whose fields are not visible in the call, persistence or logging of card data (other checks of the suite), and proprietary client-side encryption or tokenisation flows the rules do not recognise.
Type
deterministic
1.1.2: WHERE A FILE RUNS is decided from the FILE (and, when the file alone does not say, from the import graph of the checkout), never from a list of folder names of one particular repository, and a file whose server nature is UNPROVEN is never reported as server code. A monorepo has a SHARED layer — a package the browser bundle and the services both import — and the old rule read every ambiguous file as server: WebCrypto of the browser (`crypto.subtle` in a shared e2ee service that a client component imports) came out as "key generation in server code", once per product sharing the layer. The evidence is now, strongest first: the language (Python, PHP); a `server-only`/`client-only` import or a `'use server'`/`'use client'` directive; a location the framework declares as server (route.ts, middleware, pages/api, app/api, *.server.*, +server, wsgi/asgi); a browser runtime in the code (DOM member, Web Worker scope, `new Worker(`, a React client hook, a browser-environment polyfill such as fake-indexeddb or jsdom); a server runtime in the code (Node built-in, server-only package such as express/mongodb/winston/@aws-sdk, HTTP response sink, Lambda handler export); the IMPORT GRAPH (a module a client-declared file imports runs in the browser, a module that imports a server-proven module runs on a server); the folder convention (`workers/` is no longer one of them: a worker folder is a browser convention as often as a server one); a universal Web API of the browser with no server evidence at all; otherwise unproven, which is never server. Found by the attestation campaign of the platform (2026-09-25): 73 of the 252 high findings of every project were this one classification. (1.1.1: the browser asset folders of the server-rendered frameworks (static/, wwwroot/ and Laravel resources/js/) are classified as browser code, like public/ and assets/ already were: browser JavaScript of a Django, Flask or Go application was being analysed as server code (false positive found by the control bench of the audit scripts). (1.1.0: deterministic: the rule runs over the static analysis kit (tokens, function units, calls, imports, routes) with no AI engine; exact decisionRule and languages published; not-applicable with the reason when the checkout gives nothing to evaluate. Server code is analysed per FUNCTION UNIT: a raw card field (PAN/CVV; expiry = MEDIUM) read out of the request or passed to a gateway SDK call is HIGH; browser fetch/axios/XHR posting the PAN/CVV to a non-gateway URL is HIGH.))
// server code is analysed per FUNCTION UNIT of the static analysis kit; identifiers come from tokens, never from strings or comments
const GATEWAY_CARD_CALL = /(?:^|[.\\])(?:tokens?|sources?|paymentMethods?|charges?|transactions?|Token|PaymentMethod|creditCard)\.(?:create|sale|charge|confirm)$/i; // + a card wrapper with a number/cvv key -> FAIL
// browser: fetch/axios/$.post/XMLHttpRequest with a body naming the PAN or the CVV and no gateway host -> FAIL; no gateway referenced -> not-applicable
The full script is disclosed on request in a read-only viewer (never published on GitHub); the attestation binds to this exact hash.