chore: wire PostgreSQL + Prisma per ADR-0006

Add Prisma 7 + nestjs-prisma. The schema lives at
apps/portal-bff/prisma/schema.prisma with provider postgresql; the new
prisma-client generator (Prisma 7 default) outputs the typed client to
apps/portal-bff/generated/prisma/ which is gitignored.

apps/portal-bff/src/app/app.module.ts imports PrismaModule.forRoot
({ isGlobal: true }) so PrismaService is injectable across the BFF
without per-module imports.

apps/portal-bff/.env.example documents DATABASE_URL with a local-dev
default, plus a forward list of env vars introduced by upcoming phases
and ADRs (auth, sessions, MFA, observability, audit, downstream APIs)
- catalog reference, not implementation. The actual .env stays
gitignored at both repo root and app levels.

prisma.config.ts (Prisma 7's TypeScript config) is committed; it loads
DATABASE_URL via dotenv. Schema and migrations paths are pinned to
prisma/ relative to the bff app.

PostgreSQL provisioning, RLS policies for the dual-audience design,
the dedicated audit schema with role grants (audit_owner / audit_writer
/ audit_reader / audit_archiver per ADR-0013), and column-level
encryption for L3-scoped data are out of scope of this commit -
they belong with the future on-prem infrastructure ADR.
This commit is contained in:
Julien Gautier
2026-04-30 17:28:54 +02:00
parent cd1d482aa8
commit 2b0e20bd85
7 changed files with 847 additions and 1 deletions
+51
View File
@@ -0,0 +1,51 @@
# BFF environment template
# Copy to .env (which is gitignored) and fill in actual values for local development.
# Production values are managed by the platform's secret manager (see future infrastructure ADR).
# Postgres connection (per ADR-0006)
# Local dev default: dockerised Postgres on port 5432, schema 'public'.
DATABASE_URL="postgresql://portal:portal@localhost:5432/portal_dev?schema=public"
# Future env vars introduced by upcoming phases / ADRs:
#
# Auth flow (ADR-0009):
# ENTRA_TENANT_ID
# ENTRA_CLIENT_ID
# ENTRA_CLIENT_SECRET (or ENTRA_CLIENT_CERT_PATH)
# ENTRA_ACCEPTED_TENANT_IDS
# ENTRA_REDIRECT_URI
# ENTRA_POST_LOGOUT_REDIRECT_URI
# SESSION_SECRET
#
# Sessions (ADR-0010):
# REDIS_URL (or REDIS_SENTINEL_HOSTS + REDIS_SENTINEL_NAME)
# REDIS_PASSWORD
# REDIS_TLS ('true' in prod)
# SESSION_ENCRYPTION_KEY (32-byte base64)
# SESSION_IDLE_TIMEOUT_SECONDS (default 1800)
# SESSION_ABSOLUTE_TIMEOUT_SECONDS (default 43200)
#
# MFA (ADR-0011):
# MFA_FRESHNESS_SECONDS (default 600)
#
# Observability (ADR-0012):
# LOG_LEVEL ('info' in prod, 'debug' in dev)
# LOG_USER_ID_SALT (per-environment salt)
# OTEL_SERVICE_NAME ('portal-bff')
# OTEL_SERVICE_VERSION
# OTEL_RESOURCE_ATTRIBUTES
# OTEL_EXPORTER_OTLP_ENDPOINT
# OTEL_EXPORTER_OTLP_PROTOCOL ('http/protobuf')
# OTEL_TRACES_SAMPLER ('always_on' in v1)
#
# Audit trail (ADR-0013):
# AUDIT_DATABASE_URL (separate creds, role 'audit_writer')
# AUDIT_ARCHIVER_DATABASE_URL (role 'audit_archiver', for the retention purge job)
# AUDIT_RETENTION_DAYS (default 365)
#
# Downstream API access (ADR-0014):
# OBO_CACHE_ENCRYPTION_KEY (32-byte base64, distinct from SESSION_ENCRYPTION_KEY)
# BFF_JWKS_PRIVATE_KEY_PATH
# BFF_JWKS_KID
# <SERVICE>_API_BASE_URL (per integrated downstream)
# <SERVICE>_TIMEOUT_MS (optional, defaults to 5000)
+5
View File
@@ -0,0 +1,5 @@
node_modules
# Keep environment variables out of version control
.env
/generated/prisma
+14
View File
@@ -0,0 +1,14 @@
// This file was generated by Prisma, and assumes you have installed the following:
// npm install --save-dev prisma dotenv
import "dotenv/config";
import { defineConfig } from "prisma/config";
export default defineConfig({
schema: "prisma/schema.prisma",
migrations: {
path: "prisma/migrations",
},
datasource: {
url: process.env["DATABASE_URL"],
},
});
+13
View File
@@ -0,0 +1,13 @@
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
// Get a free hosted Postgres database in seconds: `npx create-db`
generator client {
provider = "prisma-client"
output = "../generated/prisma"
}
datasource db {
provider = "postgresql"
}
+2 -1
View File
@@ -1,9 +1,10 @@
import { Module } from '@nestjs/common';
import { PrismaModule } from 'nestjs-prisma';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
imports: [],
imports: [PrismaModule.forRoot({ isGlobal: true })],
controllers: [AppController],
providers: [AppService],
})