import type { HttpContext } from '@adonisjs/core/http' import type { NextFn } from '@adonisjs/core/types/http' import SeedOrchestrator from '#services/SeedOrchestrator' declare module '@adonisjs/core/http' { interface HttpContext { /** The seeding node that made this request (CONCEPT.md D38). */ seedNode: { id: number; name: string } } } /** * Seed API requests carry a node's bearer token (`node ace seed:token * `); anything else gets 401. The seed API is the only part of the app * reachable from the internet (traefik routes only /api/v1/seed there). */ export default class SeedNodeMiddleware { async handle(ctx: HttpContext, next: NextFn) { const header = ctx.request.header('authorization') ?? '' const token = header.startsWith('Bearer ') ? header.slice(7).trim() : '' const node = token ? await SeedOrchestrator.nodeForToken(token) : null if (!node) return ctx.response.unauthorized({ error: 'Unknown or disabled seed node token' }) ctx.seedNode = node return next() } }