# Routelarch > Audit one Express or Fastify API service before it ships - will an async handler hang the request and crash the process, is the body parser in front of the routes, is SQL built from request input, what reaches the client when something throws, who can call the write routes, is the token really verified - then fix it. The free check runs in the browser and uploads nothing: it lexes the pasted .js/.ts/.mjs/.cjs files (plus package.json for the Express or Fastify version), resolves require() and import between them, maps every app and router, every route with its method, full path through its mount, middleware chain and handler, and every use() in registration order, and runs 17 deterministic checks drawn from Node.js backend practice. The paid audit rates errors, input, security and operations, confirms or dismisses every flag and gives exact before/after edits per finding; the paid fix lane writes the whole fixed file(s) and a changes list tied to the flags. The page checks every quote and line against the paste, applies every edit and file back into the paste and re-runs its checks, and calls out a reply that repeats a credential from the paste. App: https://routelarch.skillsafe.ai/ API tutorial: https://routelarch.skillsafe.ai/api.html ## Input - The files pasted into one box, each introduced by a `// file: ` line (`server.js`, `routes/orders.js`, `middleware/auth.js`, `package.json`); dropped files or a dropped src folder are joined that way automatically (node_modules, dist, build and test files skipped). A paste with no file line is read as one file (server.js). - Nothing is installed or run: every flag is a reading of the text, with the file and line it points at. Strings, template literals, regex literals and comments are lexed out first, so a string that mentions req.body is never a finding. Handlers passed by name (`router.post("/", ctrl.create)`) are found in the pasted file they come from; a mount (`app.use("/api/orders", router)`) gives each route its full path. - Middleware, helpers and database code in files that were not pasted are outside the check (EX-18 names every handler it could not find); so is the deployment. The service's own tests and a real request against each changed route stay the ground truth. ## Flags the free check raises - EX-01 (high on Express 4, medium when the version is unknown, none on Express 5 or with express-async-errors): an async route handler or middleware with an await or throw outside a try whose catch passes the error on, and not wrapped in an asyncHandler-style call. - EX-02 (medium): the Express app has no four-parameter error handler, registers it before routes or routers that come after it, or registers an error handler with fewer than four parameters. - EX-03 (medium; low for the raw error object): err.stack, or the caught error itself, sent in a response from a catch block or an error handler. - EX-04 (high): a route reads req.body and no express.json()/urlencoded() is registered before it (on its router, or on the app before its mount), when the app entry is pasted. - EX-05 (high; medium for MongoDB): a query call (query, execute, raw, $queryRawUnsafe, ...) whose SQL is a template literal or concatenation holding request input (directly or through a variable built from it); a MongoDB filter that is req.body or req.query whole. - EX-06 (medium): req.body passed whole to create/insert/update/save/set, spread into a record, set as data:, or copied with Object.assign. - EX-07 (medium): a literal in a secret-named binding or property (password, secret, token, api key, jwt/session secret ...), a connection string with a password, or a literal jwt.sign() key. - EX-08 (high; medium for ignoreExpiration; low for no algorithms list): jsonwebtoken decode() in a function that never calls verify(), an algorithms list that admits "none", verify() with ignoreExpiration: true or with no algorithms option. - EX-09 (medium; low for cors() with no options or '*' with credentials): cors() or @fastify/cors with credentials: true and origin: true or an origin function that always allows; Access-Control-Allow-Origin echoed from the request with credentials. - EX-10 (medium): an if-branch in an Express handler that sends a response with no return, where the handler goes on to send another. - EX-11 (medium): a POST login, token, password-reset, signup or verify route with no rate limiter in its chain, on its router, on its mount or on the app before it. - EX-12 (medium; low for existsSync/statSync): readFileSync, readdirSync, execSync, pbkdf2Sync, scryptSync, bcrypt hashSync/compareSync, zlib *Sync and similar inside a request handler or middleware. - EX-13 (high for file paths and shell commands, medium for redirects): request input in sendFile/download/createReadStream/readFile/path.join (unless path.basename, a root option or a startsWith check), in exec/execSync (or spawn with shell: true), or as the target of res.redirect. - EX-14 (medium): POST, PUT, PATCH or DELETE routes (not login, signup, webhook, health ...) with no auth middleware in their chain, on their router or mount, or in a Fastify hook, whose handler never reads req.user. - EX-15 (high on Express 5, low when the version is unknown, none on Express 4): req.param(), res.sendfile(), app.del(), res.send(status, body), res.json(status, body), bodyParser(), redirect('back'), and route paths with a bare *, an optional :param? or regex characters. - EX-16 (low): an Express app with no helmet() (and x-powered-by not disabled); a listen() with no SIGTERM/SIGINT handling anywhere. - EX-17 (low): a Fastify route that reads request.body, params or query and declares no schema. - EX-18 (info): context - the framework and version, counts, handlers not in the paste, whether the app entry was pasted. ## Free extras - Every route with its full path, handler, middleware chain and what it reads from the request; every use() in registration order with what each argument is (body parser, auth, rate limit, CORS, helmet, router, error handler); every file with its role. - Put any audit finding (or all of them, or the fixed files) back into the paste and re-run the check; undo puts the original back. - Exports: the check as Markdown, the flags as CSV, the edited or fixed code, a unified .patch of every changed file for `git apply`, the findings or changes as CSV, the whole result as JSON. A file cut from a large paste is named -partial. - A large paste: the run is sent at most 60,000 characters of code, and the page's facts are capped too (the most severe flags first); every cut is named in `facts.notes`. ## Paid lanes (the `task` field) - `audit`: `{task, verdict: blocked|needs_work|ready, headline, service, areas: [{area: errors|input|security|operations, status: sound|fragile|broken, note}], findings: [{id, flags, file, line, severity, area, title, evidence, why, edits: [{before, after}]}], flag_answers: [{flag, status: confirmed|dismissed, reason}], plan, questions, summary}`. `before` is an exact slice of the file, applied in order. - `fix`: `{task, verdict: fixed|partial, headline, files: [{path, content}], changes: [{file, function, flags, change, why}], verify, open: [{item, flags, reason}], questions, summary}`. `content` is the whole file; at most two new files; every route keeps its method and path and every export survives unless the note allows otherwise. - Run input: `{task, code, facts, note?, audit_handoff?, retry_note?}` - all strings; `facts` is the page's analysis as a JSON string. The audit hands its findings to the fix lane with every edit applied to `code`. - Model: gpt-terra, 10% publisher markup. A run needs a signed-in account; the reservation shown before a run is a hold, and only what the run uses is charged. ## Sources - nodejs-backend-patterns by Seth Hobson, wshobson/agents (github.com/wshobson/agents, plugins/javascript-typescript/skills/nodejs-backend-patterns), MIT - https://skillsafe.ai/skill/@wshobson/nodejs-backend-patterns - The checks and the reconciliation are original to this app. Express and Fastify are OpenJS Foundation projects; Routelarch is not affiliated with or endorsed by the OpenJS Foundation, Express or Fastify.