Documentation Index
Fetch the complete documentation index at: https://docs.lintliot.com/llms.txt
Use this file to discover all available pages before exploring further.
The Fastify adapter is a standard Fastify plugin. You register it with fastify.register() and it attaches a global preHandler hook that inspects every request before your route handlers run. It also decorates your fastify instance with a lintliot object, giving you permission guards and per-route rate limits anywhere in your app.
Prerequisites
Register the plugin
Register lintliotPlugin as the first plugin in your Fastify setup, before any other plugins or route definitions:
import Fastify from 'fastify'
import { lintliotPlugin } from '@lintliot/sdk/fastify'
const app = Fastify()
await app.register(lintliotPlugin, {
apiKey: process.env.LINTLIOT_API_KEY!,
})
app.get('/api/users', async (req, reply) => {
return { users: [] }
})
await app.listen({ port: 3000 })
Register lintliotPlugin before any other plugins or route definitions. Fastify runs preHandler hooks in registration order, so plugins registered earlier run first.
Plugin options
You can pass protection settings and security header configuration at registration time:
await app.register(lintliotPlugin, {
apiKey: process.env.LINTLIOT_API_KEY!,
protect: {
rateLimit: { max: 200, windowMs: 60_000 },
waf: 'block',
botDetection: true,
skipRoutes: ['/health'],
},
securityHeaders: true,
})
Setting securityHeaders: true adds CSP, HSTS, X-Frame-Options, Referrer-Policy, and other headers to every passing response.
By default the plugin also registers a /health route. To change the path or skip it:
await app.register(lintliotPlugin, {
apiKey: process.env.LINTLIOT_API_KEY!,
skipHealthcheck: false,
healthcheckPath: '/status',
})
Per-route permission guards
After registration, app.lintliot.can() is available on the decorated instance. Use it as a preHandler on any route:
app.delete('/api/users/:id', {
preHandler: app.lintliot.can('users:delete'),
}, async (req, reply) => {
return { deleted: true }
})
To require multiple permissions (all must pass):
app.post('/api/admin/billing', {
preHandler: app.lintliot.can('admin:write', 'billing:manage'),
}, billingHandler)
You can also use the standalone fastifyCan helper if you have a Lintliot instance outside the plugin:
import { fastifyCan } from '@lintliot/sdk/fastify'
app.delete('/api/posts/:id', {
preHandler: fastifyCan(lintliot, 'posts:delete'),
}, handler)
Per-route rate limiting
Use app.lintliot.rateLimit() to apply a stricter limit to a specific route:
app.post('/api/auth/login', {
preHandler: app.lintliot.rateLimit({ max: 5, windowMs: 60_000 }),
}, loginHandler)
Or use the standalone fastifyRateLimit helper:
import { fastifyRateLimit } from '@lintliot/sdk/fastify'
app.post('/api/auth/login', {
preHandler: fastifyRateLimit(lintliot, { max: 5, windowMs: 60_000 }),
}, loginHandler)
Access LintLiot context in route handlers
After the plugin’s preHandler runs, each request has a req.lintliot property with the resolved IP address and user ID:
app.get('/api/profile', async (req, reply) => {
const { ip, userId } = req.lintliot
return { ip, userId }
})
Programmatic permission check
For conditional logic within a handler, use app.lintliot.authorize:
app.get('/api/report', async (req, reply) => {
const canExport = await app.lintliot.authorize(req, 'reports:export')
if (!canExport) {
return reply.code(403).send({ error: 'Export not allowed on your plan' })
}
return generateReport()
})
Register routes for pentest discovery
Set autoRegisterRoutes: true to automatically send your Fastify route list to the LintLiot Pentest Engine after the server starts:
await app.register(lintliotPlugin, {
apiKey: process.env.LINTLIOT_API_KEY!,
autoRegisterRoutes: true,
})
Route registration is fire-and-forget and never blocks request handling.