──────
Build and Push Docker Images / detect-changes (push) Successful in 11s
Build and Push Docker Images / build-auth-api (push) Successful in 1m0s
Build and Push Docker Images / build-employee-api (push) Successful in 1m2s
Build and Push Docker Images / build-transit-api (push) Successful in 1m1s
Build and Push Docker Images / build-error-log-api (push) Successful in 1m5s
Build and Push Docker Images / build-admin-ui (push) Successful in 1m13s
Build and Push Docker Images / build-monitoring-ui (push) Successful in 1m15s
Build and Push Docker Images / deploy-test-node (push) Successful in 3s

### Summary of Changes
  1. Documentation Consolidation:
      • Relocated the docs/ folder and all repository .md files (README.md, DEPLOYMENT.md, DOCKER_README.md,
      DOMAINS_README.md, GETTING_STARTED.md, CI_CD_PORTAINER_GUIDE.md, ADMIN_DEPLOYMENT_SUMMARY.md,
      SECURITY_PRIVATE_FILES.md, handoff.md, azure-project-plan.md, plus service-specific READMEs) into .
      • Updated document links in README.md.
  2. AI Agent Project Map:
      • Created PROJECT_MAP.md in the project root containing complete architecture diagrams, service specs, ports, DB
      schemas, environment variables, and developer workflows.
      • Added PROJECT_MAP.md to .gitignore.
  3. Monitoring UI & Infrastructure Integration:
      • Added monitoring_ui service to docker-compose.yml (port 5175).
      • Configured Gitea workflow docker-build.yml for monitoring_ui builds.
      • Added CORS middleware headers in index.js.
      • Added nginx.conf copy step in Dockerfile.

  ──────
  ### Recommended Commit Message

    docs: consolidate project documentation into monitoring_ui and add agent project map

    - Move all markdown documentation files and docs/ folder into monitoring_ui/docs/
    - Update documentation hub index (monitoring_ui/docs/README.md) with relative paths
    - Generate comprehensive AI agent reference map (PROJECT_MAP.md) in repository root
    - Add PROJECT_MAP.md and monitoring_ui build output/env overrides to .gitignore
    - Integrate monitoring_ui service into docker-compose.yml and Gitea CI workflow
    - Configure CORS handling in employee_api for monitoring dashboard access
    ──────
  ### Alternative Short Commit Message

    refactor(docs): move docs to monitoring_ui and create AI agent PROJECT_MAP.md
This commit is contained in:
Sven laptop
2026-09-20 23:33:55 +02:00
parent f935bbeb8c
commit 635a130f0b
195 changed files with 28309 additions and 957 deletions
@@ -0,0 +1,68 @@
<!-- azure-cor-disclaimer -->
> **Important:** This skill provides guidance and recommended instructions to assist the AI system. Outputs are not guaranteed to be complete, correct, secure, or applicable to every scenario. Results should be reviewed and validated by a human before being applied. The AI model may choose not to follow all instructions exactly, and additional verification may be required.
# {Emulator Name}
> **Template** — Copy this file to `emulators/{name}.md` when adding a new emulator.
---
## Docker Image
<!-- Official image and recommended pinned tag. -->
```
{org}/{image}:{tag}
```
## docker-compose Service Block
<!-- Complete service YAML block, ready to paste. Includes ports, volumes, health check. -->
```yaml
services:
{service-name}:
image: {org}/{image}:{tag}
ports:
- "{host-port}:{container-port}"
volumes:
- ./.{service-name}:/data
restart: unless-stopped
```
## Connection String
<!-- Default local connection string for the app to use. -->
```
{connection-string}
```
## Required App Environment Variables
<!-- Variable names the app must set to point at this emulator. -->
| Variable | Value |
|----------|-------|
| `{VAR_NAME}` | `{value}` |
## Healthcheck (Database Emulators Only)
<!-- If this emulator is a database, include a healthcheck block in the docker-compose service above AND document it here. The migration service (see migrations.md) depends on `condition: service_healthy` to wait for the database before running migrations. Without a healthcheck, auto-migration will not work. -->
<!-- Delete this section if the emulator is not a database. -->
## Container Runtime Support
<!-- State whether this emulator has been certified for Docker, Podman, or both. -->
<!-- The compose service block is engine-agnostic, but some Microsoft emulator images make Docker-specific assumptions (privileged mode, architecture, licensing). -->
<!-- If this emulator is NOT yet certified for Podman, say so here so the generation phase emits a `⚠️ LIMITED SUPPORT` warning when the plan selects Podman. -->
| Docker | Podman |
|--------|--------|
| {✅ certified / 🔲 planned} | {✅ certified / 🔲 planned} |
## Notes
<!-- Platform caveats (arm64/x86), known issues, resource requirements. -->
<!-- Note any Podman-specific caveats here (SELinux `:Z` labels on Linux, rootless port ranges, Podman-machine bind-mount paths). -->
@@ -0,0 +1,50 @@
<!-- azure-cor-disclaimer -->
> **Important:** This skill provides guidance and recommended instructions to assist the AI system. Outputs are not guaranteed to be complete, correct, secure, or applicable to every scenario. Results should be reviewed and validated by a human before being applied. The AI model may choose not to follow all instructions exactly, and additional verification may be required.
# Azurite (Azure Blob / Queue / Table Storage)
## Docker Image
```
mcr.microsoft.com/azure-storage/azurite
```
## docker-compose Service Block
```yaml
services:
azurite:
image: mcr.microsoft.com/azure-storage/azurite
# Overriding the default command requires re-specifying --blobHost/--queueHost/--tableHost 0.0.0.0
# so Azurite listens on all interfaces (the image's default). Without them, Azurite falls back to
# 127.0.0.1 inside the container and becomes unreachable from the host via port mapping.
# --skipApiVersionCheck allows newer Azure SDK API versions to work with older Azurite releases.
command: azurite --blobHost 0.0.0.0 --queueHost 0.0.0.0 --tableHost 0.0.0.0 --skipApiVersionCheck
ports:
- "10000:10000"
- "10001:10001"
- "10002:10002"
volumes:
- ./.azurite:/data
restart: unless-stopped
```
## Connection String
```
UseDevelopmentStorage=true
```
## Required App Environment Variables
| Variable | Value |
|----------|-------|
| `AzureWebJobsStorage` (Functions) | `UseDevelopmentStorage=true` |
| `AZURE_STORAGE_CONNECTION_STRING` (SDK) | `UseDevelopmentStorage=true` |
## Notes
- Ports: 10000 (Blob), 10001 (Queue), 10002 (Table)
- **Consolidation:** If multiple storage bindings are detected (blob + queue + table), use a **single** Azurite service — not one per binding type.
- The Event Hubs Emulator requires Azurite for checkpointing. If both are needed, the `azurite` service is shared.
- **Container runtime:** Certified for both **Docker** and **Podman** — the service block above is unchanged for either engine. Under Podman on Windows/macOS the ports are published from the Podman machine to the host exactly as with Docker; no `:Z`/`:z` volume label is needed for the `./.azurite` bind mount.
@@ -0,0 +1,128 @@
<!-- azure-cor-disclaimer -->
> **Important:** This skill provides guidance and recommended instructions to assist the AI system. Outputs are not guaranteed to be complete, correct, secure, or applicable to every scenario. Results should be reviewed and validated by a human before being applied. The AI model may choose not to follow all instructions exactly, and additional verification may be required.
# PostgreSQL
> PostgreSQL has no Azure-provided emulator. Use the standard `postgres` Docker image for local development. If the project targets **Azure Cosmos DB for PostgreSQL**, note in the plan that no local emulator is available.
## Docker Image
```
postgres:16
```
## docker-compose Service Block
Declare the local credentials **once** in a workspace-root `.env`, then reference them everywhere
else. Compose interpolates `${...}` from `.env` (or the shell environment), so the same values feed
the database service and every application service.
`.env` is required — without it Compose interpolates `${POSTGRES_USER}` to an empty string and the
database silently fails to authenticate:
```
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
POSTGRES_DB=localdev
```
> ⛔ **`.gitignore` must list `.env` before you create it.** A credential that reaches a commit is
> compromised and has to be rotated — deleting it in a later commit leaves the value in history and
> in every existing clone and fork. Private repositories are no exception. If the project has no
> `.gitignore`, or has one that omits `.env`, fix that before writing the file.
> **Never inline a concrete `user:password@host` URL** in a generated file — build it from the
> variables above. Beyond hard-coding a credential, such literals are rewritten by secret-redaction
> filters, and a masked value starting with `*` is a fatal YAML parse error: YAML reads a leading
> `*` as an alias reference.
```yaml
services:
postgres:
image: postgres:16
ports:
- "5432:5432"
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
interval: 5s
timeout: 5s
retries: 5
start_period: 30s
restart: unless-stopped
# Declare the named volume at the top level of the compose file (merge into an
# existing top-level `volumes:` key if the file already has one).
volumes:
postgres_data:
```
> ⛔ **Use a named volume for the Postgres data dir — not a `./.postgres` bind mount.** On its first
> start Postgres's `initdb` sets the data directory's permissions to `0700`, which requires `chown`/`chmod`
> on the mount. Against a **host bind mount on Windows/macOS** — especially **rootless Podman**, where the
> container user can't change ownership of a Windows-side path — that fails with
> `could not change permissions of directory "/var/lib/postgresql/data": Operation not permitted`, and the
> database never initializes. A **named volume** is managed inside the engine's VM (ext4), so `initdb`
> succeeds on Docker Desktop and Podman alike. This also sidesteps the bind-mount performance and
> permission quirks Postgres hits on Docker Desktop for Windows/macOS. (Azurite and most other emulators
> tolerate a workspace bind mount fine — this named-volume rule is specific to database emulators like
> Postgres that `chown` their data directory.)
## Connection String
The host depends on where the client runs:
| Client location | Host |
|---|---|
| Host machine (VS Code debug target, `npm` task) | `localhost` |
| Another docker-compose service | `postgres` (the service name) |
```
postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@localhost:5432/${POSTGRES_DB}
```
## Required App Environment Variables
Declare these in the workspace-root **`.env`**, alongside the `POSTGRES_*` values:
| Variable | Value |
|----------|-------|
| `DATABASE_URL` | `postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@localhost:5432/${POSTGRES_DB}` |
| `POSTGRES_CONNECTION_STRING` | `postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@localhost:5432/${POSTGRES_DB}` |
> Use whichever variable name the project's ORM or SDK expects. Both forms above are shown as reference.
> When the value is set on a docker-compose service, replace the `localhost` host with `postgres`.
> **`.env` must declare every key `.env.example` declares.** `.env.example` is documentation —
> nothing loads it, so a key that appears only there is undefined at run time.
> **A runtime settings file does not cover host-run tasks.** `local.settings.json` is read by the
> Azure Functions host and a compose `environment:` block by its own container; neither reaches a
> VS Code task that runs a tool directly on the host, such as `npm run db:migrate`. That client
> fails with "Unable to acquire a connection", which reads like an unready database but is a
> missing variable — it never opened a socket. Put the value in `.env` so both paths resolve it.
## Healthcheck
The healthcheck is included in the docker-compose service block above. It uses `pg_isready` to verify PostgreSQL is accepting connections. The migration service (see [migrations.md](../migrations.md)) depends on `condition: service_healthy` to wait for readiness before running migrations.
```yaml
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
interval: 5s
timeout: 5s
retries: 5
start_period: 30s
```
## Notes
- Port 5432 is the standard PostgreSQL port.
- Default credentials (`postgres`/`postgres`) are intentionally simple for local dev and are declared in the workspace-root `.env`. Never use in production.
- Data is persisted to the **named volume `postgres_data`** (managed by the container engine, not a workspace folder). Reset it with `docker compose down -v` / `podman compose down -v`, or `docker volume rm <project>_postgres_data`. Because it is not a workspace directory, it needs no `.vscode/settings.json` `files.exclude` entry and is not part of the workspace stale-**directory** preflight check.
- **Container runtime:** Certified for both **Docker** and **Podman** — the service block, healthcheck, and named `postgres_data` volume are unchanged for either engine. The named volume (not a bind mount) is what lets `initdb` run under rootless Podman on Windows/macOS. The `condition: service_healthy` gate that migrations depend on is honored by both `docker compose` and `podman compose`.