// Backend app for the {{projectName}} project, backed by MariaDB. Read by // `voltro dev` (local) and `voltro serve` (production). // // `store: 'mariadb'` turns on the binlog CDC reader: real-time // subscriptions fan out across every replica via the database's binary // log (no Redis/NATS — the binlog IS the message bus). The DB must run // with `binlog_format=ROW` + `binlog_row_image=FULL` and a user holding // `REPLICATION SLAVE, REPLICATION CLIENT` — the compose baseline sets all // of this up; in prod the Helm baseline wires the per-pod `server_id`. // // `plugins` composes cross-cutting behaviour. File storage is on by // default (MinIO locally, S3 in prod). import { defineEnv, envVar } from '@voltro/env' import { storagePlugin } from '@voltro/plugin-storage' // Auth strategies (uncomment + configure to enable — see `auth` below): // import { jwtBearerStrategy } from '@voltro/protocol' // import { apiKeyStrategy } from '@voltro/protocol/apikey' // Typed environment — declare your env once; it's validated at boot (fail-fast) // and read on the server via `serverEnv` / `getSecret` from '@voltro/env/server'. // `access` is required: 'public' (browser-safe) or 'secret' (server-only, never // bundled). Run `voltro env` to see the manifest. See the Environment docs. export const env = defineEnv({ LOG_LEVEL: envVar.enum(['debug', 'info', 'warn', 'error'], { access: 'public', default: 'info' }), // Add your own, e.g.: // STRIPE_KEY: envVar.string({ access: 'secret' }), }) export default { type: 'api' as const, name: '{{capProjectName}}{{capAppName}}', store: 'mariadb' as const, env, plugins: [ // Blobs in object storage; metadata in `_voltro_storage_refs`. // Provider resolved from `STORAGE_PROVIDER` (minio | s3 | filesystem). storagePlugin(), ], // Auth: the built-in signed-cookie password strategy ALWAYS runs first; // these run after it, in order, until one matches or rejects. The same // chain serves dev and prod. Uncomment + configure for your IdP / keys. // // auth: { // strategies: [ // // JWKS cookie sessions — verifies a JWT from your IdP against its // // JWKS endpoint and maps a claim to the active org (tenantId). // jwtBearerStrategy({ // id: 'idp', // jwksUrl: process.env.JWKS_URL!, // issuer: process.env.JWT_ISSUER, // cookieName: '{{projectName}}-session', // claimsToTenantId: (claims) => (claims.org as string) ?? null, // }), // // `{{projectName}}_`-prefixed API keys: the strategy strips the // // prefix, sha256-hashes the token, and hands you the hash — // // look it up in your key table and return id/tenantId/scopes. // apiKeyStrategy({ // prefix: '{{projectName}}_', // resolveKey: async (hash) => { // // const row = await lookupApiKeyByHash(hash) // // return row ? { id: row.id, tenantId: row.orgId, scopes: row.scopes } : null // return null // }, // }), // ], // }, }