A centralized changelog platform for LFX products. Provides a unified, public-facing timeline of product updates and an admin interface for teams to draft, review, and publish release notes with AI-assisted generation.
- π° Changelog feed β filterable timeline of published entries across all LFX products
- π¦ Per-product views β dedicated changelog pages for each of the 9 LFX products
- π Pretty URLs β human-readable slugs (e.g.,
/entry/security-march-2026-patches) - π Full-text search β OpenSearch-powered with fuzzy matching, highlighting, and product faceting
- ποΈ Changelog views β unseen-count tracking so external LFX apps can show notification badges
- π Dark mode β light/dark dual-theme with system preference detection
- π Dashboard β overview of drafts, published entries, and recent activity
- βοΈ Changelog editor β Markdown-based editor with live preview and category tagging
- π Role-based access β super admin, product admin, and editor roles with per-product scoping
- π€ Changelog agent β Claude Agent SDK pipeline that auto-generates drafts from GitHub commits, merged PRs, and releases
- π Blog generation β monthly roundup blog posts synthesized from recent changelogs, with admin editor and public feed
- π¬ Chat assistant β conversational AI that answers questions about changelog data with streaming responses
- π GitHub β GitHub App for repository tracking, release syncing, and webhook-driven changelog generation
- π¬ Slack β share published changelogs to Slack channels with rich BlockKit messages
- π MCP server β AI tool integration via the Model Context Protocol (Claude Desktop, Cursor, etc.)
- π Auth0 + API keys β OAuth sessions and scoped API keys for programmatic access (CI/CD, scripts, external tools)
- β‘ Server-side rendering β Angular SSR for fast initial loads and SEO
- π Observability β Datadog APM, RUM with session replay, and structured HTTP request logging
- π§ͺ E2E test suite β Playwright tests covering public pages, admin flows, RBAC, and API endpoints
| Layer | Technology |
|---|---|
| Monorepo | Turborepo + Yarn 4 workspaces |
| Frontend | Angular 20 (standalone components, signals, zoneless) |
| Backend | Express 5 (via Angular SSR server) |
| Database | PostgreSQL 16 |
| ORM | Prisma 7 with driver adapter |
| Validation | Zod 4 + OpenAPI 3.1 (Swagger UI at /docs) |
| Auth | Auth0 (express-openid-connect) |
| Styling | Tailwind CSS 4 (CSS-first config, custom components) |
| Testing | Playwright (E2E, API) |
| Integration | MCP SDK 1.x (Model Context Protocol) |
| CI/CD | GitHub Actions, ArgoCD, Helm, GHCR |
- Node.js >= 22
- Yarn 4.12.0 (managed via Corepack)
- Docker and Docker Compose (for PostgreSQL)
git clone https://github.com/linuxfoundation/lfx-changelog.git
cd lfx-changelog
corepack enable
yarn installcp apps/lfx-changelog/.env.example apps/lfx-changelog/.envEdit apps/lfx-changelog/.env with your values. See the Environment Variables section below for details.
yarn docker:upyarn db:generate
yarn db:migrate
yarn db:seedyarn startThe app runs at http://localhost:4204
The server supports two ways to configure the database connection: a single DATABASE_URL connection string, or individual DB_* variables (which the server assembles at runtime via buildConnectionString). Provide one or the other.
| Variable | Required | Description |
|---|---|---|
DATABASE_URL |
Yes* | PostgreSQL connection string (e.g., postgresql://changelog:changelog_dev@localhost:5432/lfx_changelog) |
DB_HOST |
Yes* | Database host (e.g., localhost) |
DB_PORT |
No | Database port (default: 5432) |
DB_NAME |
Yes* | Database name (e.g., lfx_changelog) |
DB_USER |
Yes* | Database user (e.g., changelog) |
DB_PASSWORD |
Yes* | Database password |
AUTH0_CLIENT_ID |
Yes | Auth0 application client ID |
AUTH0_CLIENT_SECRET |
Yes | Auth0 application client secret |
AUTH0_ISSUER_BASE_URL |
Yes | Auth0 tenant URL (e.g., https://your-tenant.auth0.com) |
AUTH0_SECRET |
Yes | Session encryption secret (min 32 characters) |
BASE_URL |
Yes | Application base URL (e.g., http://localhost:4204) |
GITHUB_APP_ID |
No | GitHub App ID for repository integration |
GITHUB_PRIVATE_KEY |
No | GitHub App RSA private key |
GITHUB_WEBHOOK_SECRET |
No | Secret for verifying GitHub webhook signatures (see Webhook Testing) |
LITELLM_API_KEY |
No | API key for AI changelog generation and AI chat |
AI_API_URL |
No | AI service endpoint URL (LiteLLM proxy) |
OPENSEARCH_URL |
No | OpenSearch endpoint for full-text search (e.g., https://search.example.com) |
SLACK_CLIENT_ID |
No | Slack OAuth client ID for Slack integration |
SLACK_CLIENT_SECRET |
No | Slack OAuth client secret |
SLACK_TOKEN_ENCRYPTION_KEY |
No | AES-256-GCM key for encrypting Slack tokens at rest (64 hex chars) |
WEBHOOK_STATE_SECRET |
No | HMAC secret for OAuth state CSRF protection (Slack + GitHub) |
DATADOG_RUM_APPLICATION_ID |
No | Datadog RUM application ID (client-side monitoring) |
DATADOG_RUM_CLIENT_ID |
No | Datadog RUM client token |
NODE_ENV |
No | development or production (default: development) |
PORT |
No | Server port (default: 4000) |
LOG_LEVEL |
No | Logging level: debug, info, warn, error (default: info) |
*Provide either DATABASE_URL or the DB_HOST/DB_NAME/DB_USER/DB_PASSWORD group.
| Script | Description |
|---|---|
yarn build |
Build all packages (shared + app) |
yarn start |
Start the SSR server |
yarn lint |
Run ESLint across all packages |
yarn format |
Format all files with Prettier |
yarn format:check |
Check formatting without writing |
yarn markdownlint |
Lint markdown files |
yarn markdownlint:fix |
Auto-fix markdown lint issues |
yarn docker:up |
Start PostgreSQL via Docker Compose |
yarn docker:down |
Stop PostgreSQL |
yarn db:generate |
Generate Prisma client |
yarn db:migrate |
Run database migrations |
yarn db:seed |
Seed the database with sample data |
yarn db:studio |
Open Prisma Studio (database GUI) |
yarn test |
Run tests across all workspaces |
yarn watch |
Build all packages in watch mode |
| Script | Description |
|---|---|
yarn start |
Angular dev server with live reload |
yarn build:dev |
Development build |
yarn build:prod |
Production build |
yarn lint |
Lint the Angular app |
yarn test |
Run Playwright E2E tests |
yarn test:headed |
Run E2E tests with browser visible |
yarn test:ui |
Run E2E tests in Playwright UI mode |
yarn test:report |
Open the last Playwright HTML report |
lfx-changelog/
βββ apps/lfx-changelog/ # Angular 20 SSR application
β βββ src/
β β βββ app/
β β β βββ layouts/ # Public and admin layout shells
β β β βββ modules/ # Feature modules (public + admin)
β β β βββ shared/ # Components, services, interfaces
β β βββ server/ # Express backend
β β β βββ controllers/ # Request handlers
β β β βββ services/ # Business logic + Prisma queries
β β β βββ routes/ # Route definitions
β β β βββ middleware/ # Auth, RBAC, validation, error handling
β β β βββ swagger/ # OpenAPI path definitions
β β β βββ helpers/ # Shared utilities (DB connection, etc.)
β β β βββ errors/ # Custom error classes
β β βββ environments/ # Environment configs
β βββ prisma/ # Schema, migrations, seed
β βββ e2e/ # Playwright E2E tests
β βββ setup/ # DB + auth setup projects
β βββ helpers/ # Test utilities (API, DB, Docker, fixtures)
β βββ pages/ # Page Object Model classes
β βββ specs/ # Test specs (public/, admin/, api/)
βββ packages/shared/ # @lfx-changelog/shared (Zod schemas, types, enums)
βββ packages/mcp-server/ # @lfx-changelog/mcp-server (MCP tools & resources)
βββ charts/lfx-changelog/ # Helm chart for Kubernetes deployment
βββ docs/ # Additional documentation
βββ docker-compose.yml # Local PostgreSQL (dev + test)
βββ Dockerfile # Multi-stage production build
βββ turbo.json # Turborepo task config
The application uses an Angular SSR server that also hosts the Express API backend. This single-server approach means:
- Public API (
/public/api/*) --- unauthenticated endpoints for reading published changelogs and products - Protected API (
/api/*) --- authenticated endpoints for CRUD operations, supporting both OAuth sessions and API keys - API docs (
/docs) --- interactive Swagger UI generated from Zod schemas via@asteasolutions/zod-to-openapi - MCP (
/mcp) --- Model Context Protocol endpoint for AI tool integration (Streamable HTTP) - SSR --- Angular pages are server-rendered for all routes
The API supports two authentication methods:
- OAuth sessions --- browser-based login via Auth0 (session cookies)
- API keys --- programmatic access via
Authorization: Bearer lfx_...orX-API-Key: lfx_...headers
API keys are scoped (changelogs:read, changelogs:write, products:read, products:write) and enforce the same role checks as OAuth sessions. See API Authentication for details on creating keys, endpoint permissions, and usage examples.
| Role | Scope | Permissions |
|---|---|---|
super_admin |
Global | Full access to all products, users, and settings |
product_admin |
Per-product | Manage changelogs and editors for assigned products |
editor |
Per-product | Create and edit changelogs for assigned products |
The PostgreSQL schema is managed by Prisma:
- Product --- LFX products with activation status, Font Awesome icons, and optional GitHub App installation
- ProductRepository --- GitHub repositories linked to products for release syncing and changelog generation
- GitHubRelease --- release metadata synced from GitHub (tag, notes, author, publish date)
- ChangelogEntry --- individual changelog entries with markdown content, versioning, slugs, and source tracking (
manualorautomated) - User --- users synced from Auth0 on first login
- UserRoleAssignment --- maps users to roles, optionally scoped to a product
- ApiKey --- scoped API keys for programmatic access, storing SHA-256 hashes with expiration and revocation tracking
- ChatConversation / ChatMessage --- AI chat conversation history with tool call persistence
- AutoChangelogLock --- distributed lock for concurrent auto-changelog generation across replicas
- SlackIntegration / SlackChannel / SlackNotification --- Slack workspace connections, channel config, and delivery tracking
yarn db:studio # Browse data in Prisma Studio
yarn db:migrate # Apply pending migrations
yarn db:seed # Reset and seed sample dataEnd-to-end tests use Playwright to verify the application from a user's perspective. Tests run against a real Angular SSR server backed by a test PostgreSQL database and authenticate through Auth0.
cd apps/lfx-changelog
yarn test # Run all tests (headless)
yarn test:headed # Run with browser visible
yarn test:ui # Run with Playwright UI modeTests automatically start a test database container on port 5433, run migrations, seed data, and launch the dev server --- no manual setup needed.
The test suite covers:
- Public pages --- changelog feed, product changelogs, theme toggle
- Admin flows --- dashboard, changelog editor, product and user management
- RBAC --- per-role access (super admin, product admin, editor, no-role)
- API endpoints --- public and protected REST endpoints via direct HTTP
See docs/testing/e2e-testing.md for the full testing guide.
GitHub Actions runs on every push to main and on pull requests:
| Job | Description |
|---|---|
| License headers | Verifies all source files include the required SPDX license header |
| Secret scan | Scans for leaked secrets using Trufflehog |
| E2E tests | Runs the full Playwright test suite against a test database |
| Workflow | Trigger | Image Tag |
|---|---|---|
docker-build-main.yml |
Push to main |
development |
docker-build-tag.yml |
Git tag push (v*) |
Semver (e.g., 1.2.3) |
docker-build-pr.yml |
PR with deploy-preview label |
changelog-pr-<number> |
All images are pushed to GHCR (ghcr.io/linuxfoundation/lfx-changelog).
The application deploys to Kubernetes via ArgoCD:
- Dev: merge to
mainbuilds image taggeddevelopment--- ArgoCD syncs and runs the migration Job before updating pods - Prod: git tag push builds a versioned image + publishes a signed Helm chart (with Cosign and SLSA provenance) --- ArgoCD syncs the new chart
Database migrations run automatically as a Helm pre-upgrade Job. See docs/database-migrations.md for details.
The production container runs as a non-root user on port 4000.
Adding the deploy-preview label to a PR builds and pushes a branch-specific image. ArgoCD provisions an isolated namespace (changelog-pr-<number>) with its own deployment. The preview is removed when the PR is closed or the label is removed.
| Document | Description |
|---|---|
| AI Chat | Agentic chat assistant, SSE streaming, conversation persistence |
| API Authentication | API keys, OAuth sessions, scopes, and usage examples |
| Changelog Agent | Claude Agent SDK pipeline, MCP tools, job tracking, webhooks |
| Changelog Views | Unseen-count tracking API for external LFX product apps |
| Database Migrations | Automated (CI/CD) and manual migration workflows |
| GitHub Integration | GitHub App, repo tracking, release sync, auto-changelog, webhooks |
| MCP Server | MCP tools, resources, and client setup |
| Observability | Datadog APM, RUM, session replay, HTTP logging, pretty URLs |
| OpenSearch | Full-text search, indexing, reindexing, MCP search tools |
| Remote Database Access | Connecting to RDS via kubectl port-forward |
| Slack Integration | OAuth flow, token encryption, posting changelogs to Slack |
| E2E Testing | Test architecture, patterns, and how to add tests |
| Webhook Testing | Testing GitHub release webhooks locally |
| Contributing | License headers, code style, commit conventions |
| Security | Vulnerability reporting |
See CONTRIBUTING.md for guidelines on submitting changes, license header requirements, and commit conventions.
MIT --- Copyright The Linux Foundation and each contributor to LFX.