13a12e6591
Phase 2 of ADR-0012 — closes the loop SPA → BFF → DB. With this PR a single user action (page load, click, form submit) produces one trace whose root span is owned by the SPA and whose child spans cover the BFF request, Postgres queries, and (eventually) Redis / downstream-API hops. Runtime libs added (production deps): - @opentelemetry/sdk-trace-web browser tracer + provider - @opentelemetry/exporter-trace-otlp-http OTLP/HTTP+JSON exporter - @opentelemetry/instrumentation auto-instrumentation runtime - @opentelemetry/instrumentation-fetch fetch + W3C traceparent propagation - @opentelemetry/instrumentation-document-load initial-paint timings - @opentelemetry/instrumentation-user-interaction click / keypress / submit Code: - apps/portal-shell/src/observability/tracing.ts — WebTracerProvider bootstrap. Documents the load-order constraint inline (must be the very first import of main.ts, same pattern as the BFF). No context-zone package because the workspace is zoneless (per ADR-0004); the default StackContextManager covers the auto-instrumentation cases. - main.ts now imports the tracing module as line 1. CORS plumbing for end-to-end propagation: - BFF (apps/portal-bff/src/main.ts) calls enableCors with a minimal dev allowlist (http://localhost:4200) and explicit permission for the W3C traceparent and tracestate headers. The full security-grade CORS belongs to phase-2 security ADR; this is the strict minimum for the SPA→BFF link to keep the trace context across origins. - OTel Collector (infra/local/otel-collector.yaml) gains a cors block on its OTLP/HTTP receiver so the browser's OTLP POST clears its own pre-flight. ADR-0012 §Confirmation: a new "Wired in the SPA foundation PR (phase 2)" block enumerates what landed here; the carry-over "Wired as features land" list is updated to drop the SPA-side SDK item that used to live there and to add a CORS-grade follow-up note. Verified locally: - pnpm exec nx run-many -t lint test build → 8 projects green. - pnpm audit clean. - After ./infra/local/dev.sh up observability and nx serve portal-shell, opening http://localhost:4200 produces a document_load trace in Jaeger with the SPA service.name; a manual fetch from DevTools to /api/health on the BFF produces a child span on the same trace.
153 lines
4.8 KiB
JSON
153 lines
4.8 KiB
JSON
{
|
|
"name": "apf-portal",
|
|
"version": "0.0.0",
|
|
"license": "MIT",
|
|
"packageManager": "pnpm@10.33.4",
|
|
"scripts": {
|
|
"prepare": "husky",
|
|
"ci:check": "pnpm exec nx affected -t format:check lint test build",
|
|
"ci:audit": "pnpm audit --audit-level=moderate",
|
|
"ci:commits": "pnpm exec commitlint --from ${COMMIT_LINT_FROM:-origin/main} --to HEAD --verbose",
|
|
"ci:perf": "pnpm exec nx build portal-shell --configuration=production && pnpm exec lhci autorun --config=./lighthouserc.js"
|
|
},
|
|
"private": true,
|
|
"lint-staged": {
|
|
"!(pnpm-lock).{ts,tsx,js,jsx,html,scss,css,md,json,yml,yaml}": [
|
|
"prettier --write"
|
|
]
|
|
},
|
|
"pnpm": {
|
|
"onlyBuiltDependencies": [
|
|
"@nestjs/core",
|
|
"@parcel/watcher",
|
|
"@prisma/client",
|
|
"@prisma/engines",
|
|
"@swc/core",
|
|
"esbuild",
|
|
"less",
|
|
"lmdb",
|
|
"msgpackr-extract",
|
|
"nx",
|
|
"prisma",
|
|
"unrs-resolver"
|
|
],
|
|
"overrides": {
|
|
"axios@<1.15.2": ">=1.15.2",
|
|
"@angular-devkit/core>ajv@<8.18.0": ">=8.18.0",
|
|
"brace-expansion@<5.0.5": ">=5.0.5",
|
|
"follow-redirects@<1.16.0": ">=1.16.0",
|
|
"ip-address@<10.1.1": ">=10.1.1",
|
|
"tmp@<0.2.4": ">=0.2.4",
|
|
"yaml@<2.8.3": ">=2.8.3"
|
|
}
|
|
},
|
|
"prisma": {
|
|
"schema": "apps/portal-bff/prisma/schema.prisma"
|
|
},
|
|
"devDependencies": {
|
|
"@analogjs/vite-plugin-angular": "~2.5.0",
|
|
"@analogjs/vitest-angular": "~2.5.0",
|
|
"@angular-devkit/core": "~21.2.0",
|
|
"@angular-devkit/schematics": "~21.2.0",
|
|
"@angular/build": "~21.2.0",
|
|
"@angular/cli": "~21.2.0",
|
|
"@angular/compiler-cli": "~21.2.0",
|
|
"@angular/language-service": "~21.2.0",
|
|
"@commitlint/cli": "^20.5.3",
|
|
"@commitlint/config-conventional": "^20.5.3",
|
|
"@eslint/js": "^9.8.0",
|
|
"@lhci/cli": "^0.15.1",
|
|
"@nestjs/schematics": "^11.0.0",
|
|
"@nestjs/testing": "^11.0.0",
|
|
"@nx/angular": "^22.7.1",
|
|
"@nx/devkit": "22.7.1",
|
|
"@nx/eslint": "^22.7.1",
|
|
"@nx/eslint-plugin": "22.7.1",
|
|
"@nx/jest": "22.7.1",
|
|
"@nx/js": "22.7.1",
|
|
"@nx/nest": "^22.7.1",
|
|
"@nx/node": "22.7.1",
|
|
"@nx/playwright": "22.7.1",
|
|
"@nx/vite": "^22.7.1",
|
|
"@nx/vitest": "22.7.1",
|
|
"@nx/web": "22.7.1",
|
|
"@nx/webpack": "22.7.1",
|
|
"@oxc-project/runtime": "^0.129.0",
|
|
"@playwright/test": "^1.36.0",
|
|
"@schematics/angular": "~21.2.0",
|
|
"@swc-node/register": "1.11.1",
|
|
"@swc/core": "1.15.33",
|
|
"@swc/helpers": "0.5.21",
|
|
"@tailwindcss/postcss": "^4.2.4",
|
|
"@types/jest": "^30.0.0",
|
|
"@types/node": "24.12.3",
|
|
"@typescript-eslint/utils": "^8.40.0",
|
|
"@vitest/coverage-v8": "~4.1.0",
|
|
"@vitest/ui": "~4.1.0",
|
|
"angular-eslint": "^21.2.0",
|
|
"eslint": "^9.8.0",
|
|
"eslint-config-prettier": "^10.0.0",
|
|
"eslint-plugin-playwright": "^1.6.2",
|
|
"husky": "^9.1.7",
|
|
"jest": "^30.0.2",
|
|
"jest-environment-node": "^30.0.2",
|
|
"jest-util": "^30.0.2",
|
|
"jsdom": "^29.0.0",
|
|
"jsonc-eslint-parser": "^2.1.0",
|
|
"lint-staged": "^17.0.0",
|
|
"nx": "22.7.1",
|
|
"pino-pretty": "^13.1.3",
|
|
"postcss": "^8.5.12",
|
|
"prettier": "^3.8.1",
|
|
"prisma": "^6.19.3",
|
|
"tailwindcss": "^4.2.4",
|
|
"ts-jest": "^29.4.0",
|
|
"ts-node": "10.9.2",
|
|
"tslib": "^2.3.0",
|
|
"typescript": "~5.9.2",
|
|
"typescript-eslint": "^8.40.0",
|
|
"vite": "^8.0.0",
|
|
"vitest": "^4.0.8",
|
|
"webpack-cli": "^5.1.4"
|
|
},
|
|
"dependencies": {
|
|
"@angular/common": "~21.2.0",
|
|
"@angular/compiler": "~21.2.0",
|
|
"@angular/core": "~21.2.0",
|
|
"@angular/forms": "~21.2.0",
|
|
"@angular/platform-browser": "~21.2.0",
|
|
"@angular/router": "~21.2.0",
|
|
"@nestjs/common": "^11.0.0",
|
|
"@nestjs/core": "^11.0.0",
|
|
"@nestjs/platform-express": "^11.0.0",
|
|
"@opentelemetry/api": "^1.9.1",
|
|
"@opentelemetry/exporter-trace-otlp-http": "^0.217.0",
|
|
"@opentelemetry/exporter-trace-otlp-proto": "^0.217.0",
|
|
"@opentelemetry/instrumentation": "^0.217.0",
|
|
"@opentelemetry/instrumentation-document-load": "^0.62.0",
|
|
"@opentelemetry/instrumentation-express": "^0.65.0",
|
|
"@opentelemetry/instrumentation-fetch": "^0.217.0",
|
|
"@opentelemetry/instrumentation-http": "^0.217.0",
|
|
"@opentelemetry/instrumentation-ioredis": "^0.65.0",
|
|
"@opentelemetry/instrumentation-nestjs-core": "^0.63.0",
|
|
"@opentelemetry/instrumentation-pg": "^0.69.0",
|
|
"@opentelemetry/instrumentation-pino": "^0.63.0",
|
|
"@opentelemetry/instrumentation-user-interaction": "^0.61.0",
|
|
"@opentelemetry/resources": "^2.7.1",
|
|
"@opentelemetry/sdk-node": "^0.217.0",
|
|
"@opentelemetry/sdk-trace-web": "^2.7.1",
|
|
"@opentelemetry/semantic-conventions": "^1.40.0",
|
|
"@prisma/client": "^6.19.3",
|
|
"axios": "^1.6.0",
|
|
"class-transformer": "^0.5.1",
|
|
"class-validator": "^0.15.1",
|
|
"nestjs-cls": "^6.2.0",
|
|
"nestjs-pino": "^4.6.1",
|
|
"nestjs-prisma": "^0.27.0",
|
|
"pino": "^10.3.1",
|
|
"pino-http": "^11.0.0",
|
|
"reflect-metadata": "^0.2.0",
|
|
"rxjs": "~7.8.0"
|
|
}
|
|
}
|