// Api app config — a PUBLIC REST API. Read by `voltro dev`. // // What's wired here: // • restRoutes — the four `defineRestRoute` descriptors, registered // EXPLICITLY (REST routes are the one primitive that is NOT auto- // discovered — they're opt-in public HTTP surface). // • openapiPlugin — generates an OpenAPI 3.1 spec from those same // descriptors and serves it at GET /openapi.json + a Swagger UI at /docs. // Zero hand-maintained API docs: the descriptors ARE the spec. // • auth.strategies — an apiKeyStrategy so `Authorization: Bearer ` // resolves to a scoped Subject. The guarded routes gate on those scopes. // • idempotency — POST/PUT/PATCH/DELETE carrying `Idempotency-Key` are // deduplicated (replay the first response; 409 while in-flight). // // `store: 'memory'` keeps first-run zero-infra (no docker). Data resets on // every restart — switch to `store: 'postgres'` (+ a local postgres) for // anything real. import { apiKeyStrategy } from '@voltro/protocol/apikey' import { openapiPlugin } from '@voltro/plugin-openapi' import listProducts from './routes/v1/products.list.route' import getProduct from './routes/v1/products.get.route' import createProduct from './routes/v1/products.create.route' import deleteProduct from './routes/v1/products.delete.route' // The descriptors, in one array — handed to BOTH `restRoutes` (to mount them) // and `openapiPlugin` (to document them). const routes = [listProducts, getProduct, createProduct, deleteProduct] // ─── DEV ONLY ──────────────────────────────────────────────────────────── // A single hardcoded API key so the guarded routes work the moment you boot: // // curl -H 'Authorization: Bearer restdemo_devkey' ... // // The strategy SHA-256-hashes the full bearer token and hands the hash to // `resolveKey`; we match it to a fixed scoped Subject. In PRODUCTION, delete // the constant below and look the hash up against your own key store (apps // store key HASHES, never raw tokens) — or flip on the framework's first- // class `apiKeys: true` for admin-gated issue/list/revoke against // `_voltro_api_keys`. This demo key is the moral equivalent of a sample // password in a README: fine for a starter, never for a real deployment. const DEMO_KEY_SHA256 = 'c8917896a6fbdd429ca2410e6e1958953d7421393f649d44fe8fc88c267441cd' // sha256('restdemo_devkey') export default { type: 'api' as const, name: '{{capProjectName}}{{capAppName}}', store: 'memory' as const, auth: { strategies: [ apiKeyStrategy({ prefix: 'restdemo_', resolveKey: (hash) => hash === DEMO_KEY_SHA256 ? { id: 'svc_demo', tenantId: 'acme', scopes: ['products:read', 'products:write'] } : null, }), ], }, plugins: [ openapiPlugin({ routes, info: { title: '{{capProjectName}} API', version: '1.0.0' }, // specPath: '/openapi.json' (default) · docsPath: '/docs' (default) }), ], // Public REST endpoints — registered explicitly, NOT auto-discovered. restRoutes: routes, // Idempotency-Key dedup for the mutating routes (records in _voltro_idempotency). idempotency: true, }