# ProcessPuzzle Testbed
![Build and Test](https://github.com/ZsZs/processpuzzle/actions/workflows/build-testbed.yml/badge.svg)
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=processpuzzle_testbed&metric=alert_status)](https://sonarcloud.io/summary?id=processpuzzle_testbed&branch=develop)
[![Node version](https://img.shields.io/npm/v/%40processpuzzle%2Ftestbed?style=flat)](https://www.npmjs.com/package/@processpuzzle/testbed)

## Introduction
ProcessPuzzle Testbed is the reference Angular application of the [ProcessPuzzle](https://processpuzzle.com) platform. It serves two purposes: it is a **living demonstration** of what can be built with the `@processpuzzle/*` libraries, and it is the **integration test harness** that exercises those libraries end-to-end in a realistic application context.

Each feature module of the testbed focuses on a single library — showing typical usage patterns, configuration options and the resulting UI — so that developers evaluating or adopting the framework can see the libraries at work before pulling them into their own projects. Browse the [live demo app](https://testbed.processpuzzle.de/home) to try it out, or explore the [source code on GitHub](https://github.com/ZsZs/processpuzzle).

## Demonstrated libraries
The testbed exercises the following libraries from the [ProcessPuzzle Framework](https://github.com/ZsZs/processpuzzle/tree/develop/libs):
- [@processpuzzle/util](https://github.com/ZsZs/processpuzzle/tree/develop/libs/js-shared/util) — general-purpose helpers, runtime config loader, error handler, logging and layout services.
- [@processpuzzle/base-entity](https://github.com/ZsZs/processpuzzle/tree/develop/libs/js-shared/base-entity-frontend) — Angular Material table and reactive form generator driven by entity definitions.
- [@processpuzzle/widgets](https://github.com/ZsZs/processpuzzle/tree/develop/libs/js-shared/widgets) — reusable UI widgets for application development.
- [@processpuzzle/auth](https://github.com/ZsZs/processpuzzle/tree/develop/libs/js-shared/auth) — authentication and authorization (OIDC / Keycloak).
- [@processpuzzle/test-util](https://github.com/ZsZs/processpuzzle/tree/develop/libs/js-shared/test-util) — helper utilities for unit testing.
- [@processpuzzle/e2e-testing](https://github.com/ZsZs/processpuzzle/tree/develop/libs/js-shared/e2e-testing) — building blocks for Playwright-based end-to-end tests.

## Configuration across stages
The testbed runs in four stages — `dev`, `ci`, `stage`, `prod` — using **the same compiled image**. Stage selection happens at container startup, not at build time.

### Two configuration layers

**1. Build-time environment** — `src/environments/environment.<stage>.ts` + `src/assets/runtime-env.json`

Both are auto-generated by `src/assets/setEnv.ts` from `.env` and CLI args, and hold the same two values:

```ts
{ FIREBASE_API_KEY: '...', PIPELINE_STAGE: 'dev' | 'ci' | 'stage' | 'prod' }
```

The JSON is bundled into the build output (`assets/runtime-env.json`) and is the standard source consumed by `main.ts`. The TS file remains only as a safety-net fallback for the case where the JSON is missing.

**2. Runtime configuration** — `src/run-time-conf/config.*.json`

Loaded at bootstrap by `ConfigurationService` (`libs/js-shared/util/.../configuration.service.ts`). On startup `main.ts`:

1. Fetches `assets/runtime-env.json` to discover the active `PIPELINE_STAGE` (falls back to the build-time `environment.ts`).
2. Builds the URL list:
   - `run-time-conf/config.common.json` (always)
   - `run-time-conf/config.<stage>.json`
   - any `CONFIGURATION_OVERRIDES`
3. Deep-merges the files in order — later files override earlier ones.

### Per-stage settings

| Stage | Backend | Auth provider | Notes |
|---|---|---|---|
| **dev** | REST `http://localhost:3000/` (common) | Keycloak `master` realm on `localhost:7070` | Firestore/Auth emulators on `8081`/`9099`, `level: debug` |
| **ci** | REST `localhost:3000` | Keycloak `processpuzzle` realm | Same emulators; runs inside `docker-compose-ci.yaml` |
| **stage** | Firestore Cloud Functions (`...-stage.cloudfunctions.net`) | `firebase-auth` | Real Firebase project `processpuzzle-testbed-stage` |
| **prod** | Firestore Cloud Functions | `firebase-auth` | Real Firebase prod project |

`config.common.keycloak.json` is an optional override profile that can be applied via `CONFIGURATION_OVERRIDES`.

### How the runtime layer is materialised in containers

The Dockerfile at `tools/docker/testbed/Dockerfile` is **stage-agnostic** — it just bundles the built Angular app under nginx. At container start, `docker-entrypoint.sh` **overwrites** the bundled `assets/runtime-env.json` with values from the container env:

```sh
envsubst '${PIPELINE_STAGE} ${FIREBASE_API_KEY}' \
  < /etc/templates/runtime-env.json.template \
  > /usr/share/nginx/html/assets/runtime-env.json
```

So the same image picks up a different stage purely from the container env vars `PIPELINE_STAGE` and `FIREBASE_API_KEY`. The Firebase API key is injected here (not committed in JSON) and merged into `BASE_CONFIGURATION.FIREBASE_CONFIGURATION` by `main.ts`.

### Docker compose files

- **`tools/docker/docker-compose-ci.yaml`** — full integration stack used in CI: testbed (nginx), Spring Boot backend, json-server, Firebase emulators, Keycloak + Postgres, MinIO. Passes `PIPELINE_STAGE=ci` and `FIREBASE_API_KEY` to the testbed container; all services healthchecked and on the `processpuzzle` bridge network.
- **`tools/docker/docker-compose-prod.yaml`** — minimal deployment template: only the testbed image + json-server, with `IMAGE_TAG` placeholder swapped at deploy time.
- **`tools/docker/minio/README.md`** — the MinIO sidecar's own README documents its custom image (pre-created `documents`/`images` buckets, `springboot/springboot123` service account) and credential override pattern.

### Flow summary

```
build-time:  setEnv.ts ──> environment.<stage>.ts   (fallback only)
                      └──> assets/runtime-env.json   (FIREBASE_API_KEY, PIPELINE_STAGE)
                                  │
container start (ci only):        ▼
docker-compose env vars ──envsubst──> assets/runtime-env.json  (overwrites the bundled file)
                                  │
                                  ▼
main.ts loads runtime-env.json ─> ConfigurationService merges:
       config.common.json  ◀── overridden by ──  config.<stage>.json  ◀── CONFIGURATION_OVERRIDES
                                  │
                                  ▼
                  RuntimeConfiguration (BASE / LANGUAGE / AUTH / LOGGING)
```