### 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
6.4 KiB
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
postgresDocker 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
⛔
.gitignoremust list.envbefore 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@hostURL 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.
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
./.postgresbind mount. On its first start Postgres'sinitdbsets the data directory's permissions to0700, which requireschown/chmodon 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 withcould 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), soinitdbsucceeds 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 thatchowntheir 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
localhosthost withpostgres.
.envmust declare every key.env.exampledeclares..env.exampleis 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.jsonis read by the Azure Functions host and a composeenvironment:block by its own container; neither reaches a VS Code task that runs a tool directly on the host, such asnpm 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.envso 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) depends on condition: service_healthy to wait for readiness before running migrations.
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 withdocker compose down -v/podman compose down -v, ordocker volume rm <project>_postgres_data. Because it is not a workspace directory, it needs no.vscode/settings.jsonfiles.excludeentry 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_datavolume are unchanged for either engine. The named volume (not a bind mount) is what letsinitdbrun under rootless Podman on Windows/macOS. Thecondition: service_healthygate that migrations depend on is honored by bothdocker composeandpodman compose.