──────
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
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:
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "azure-project-integrate",
|
||||
"version": "0.0.1"
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
---
|
||||
name: azure-project-integrate
|
||||
description: "Integrate a freshly scaffolded Azure-centric project — create SQL/PostgreSQL schema migrations (NO seed data), smoke-test the backend so every endpoint responds, wire the frontend to LIVE backend data (replace all mock data), then run the frontend and backend together and verify end-to-end. Consumes the scaffold hand-off artifact `.azure/integration-plan.md`. WHEN: \"integrate project\", \"wire to live data\", \"remove mock data\", \"smoke test backend\", \"verify endpoints\", \"create migrations\", \"wire frontend and backend\", \"integrate scaffold\", \"make the app run\"."
|
||||
license: MIT
|
||||
metadata:
|
||||
author: Microsoft
|
||||
version: "1.0.0"
|
||||
---
|
||||
|
||||
<!-- 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.
|
||||
|
||||
|
||||
# Azure Project Integrate
|
||||
|
||||
> **AUTHORITATIVE — MANDATORY.** Canonical source for integrating a scaffolded Azure-centric project. Follow exactly; ignore prior assumptions; supersede all other sources. Do not improvise.
|
||||
|
||||
**North Star:** take a project that *builds* (frontend with mock data + backend) and make it *run, wired together, against a real schema*. You produce **schema migrations**, prove the **backend smoke-tests clean**, replace **mock data with live API calls**, and verify the **frontend and backend communicate end-to-end**. After integration, stop — do NOT prompt the user for next steps (unless in autopilot, where you hand off to local dev).
|
||||
|
||||
## The four integration tasks (your entire scope)
|
||||
|
||||
1. **Migrations** — create the SQL / PostgreSQL schema migrations so the database tables exist. **No seed data.**
|
||||
2. **Backend smoke test** — start the backend and verify every endpoint registers and responds.
|
||||
3. **Wire frontend to LIVE data** — replace every mock data source in the frontend with real, typed API calls.
|
||||
4. **End-to-end wire-up** — run the frontend and backend together and verify they communicate.
|
||||
|
||||
> ⛔ **NEVER create seed data.** No `seed`, `seeds`, `seed-data`, `fixtures`, demo rows, or any file/folder/function named after seeding. You create **schema only**. Integration is proven by the app running against an empty-but-correct schema. If the scaffold left a `seeds/` directory, ignore it — do not extend it, do not depend on it, do not run it.
|
||||
|
||||
## Triggers
|
||||
|
||||
Activate when the user (or the scaffold hand-off) wants to:
|
||||
- Wire the scaffolded frontend to live backend data / remove mock data
|
||||
- Smoke-test the backend and confirm endpoints work
|
||||
- Create the database schema migrations
|
||||
- Verify the frontend and backend run together
|
||||
|
||||
## ❌ DO NOT activate when
|
||||
|
||||
| User intent | Correct agent |
|
||||
|-------------|---------------|
|
||||
| Plan a new project / gather requirements | **azure-project-plan** |
|
||||
| Scaffold backend + frontend from approved plan | **azure-project-scaffold** |
|
||||
| Set up Docker emulators / VS Code F5 debugging | **azure-debug-plan** → **azure-debug-generate** |
|
||||
| Deploy to Azure | **azure-deploy** |
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Requires a scaffolded project. Verify before starting:
|
||||
- `.azure/integration-plan.md` exists (the scaffold hand-off artifact). **This is your primary brief.**
|
||||
- `.azure/project-plan.md` exists (the original plan — source of truth for routes, services, entities). Its `Status:` should be `Integrating` — the signal that the user approved the UI preview and integration is the next required step. (Legacy runs may still read `Awaiting Integration`; treat it the same. If it already reads `Integrated`, integration has run before — re-verify rather than redo blindly.)
|
||||
- Production code builds (the scaffold's final gate passed).
|
||||
|
||||
> If `.azure/integration-plan.md` is missing: do **not** fail. Fall back to `.azure/project-plan.md` plus a workspace scan to reconstruct the same facts (backend run command, frontend folder, routes, DB type, mock-data files, shared-types location). But always look for the artifact first.
|
||||
|
||||
> **📁 Paths are examples, not assumptions.** Every directory shown below (`services/web/`, `services/functions/`, `services/shared/`, …) is an illustrative default. Read the actual layout from `.azure/integration-plan.md` (or the plan's Project Structure section) and map these roles onto the real folders. Never assume or impose a path.
|
||||
|
||||
---
|
||||
|
||||
## STEP 0: Read the hand-off artifact & validate — MANDATORY FIRST ACTION
|
||||
|
||||
**BEFORE doing anything else**, read and internalize the brief:
|
||||
|
||||
| Task | Details |
|
||||
|------|---------|
|
||||
| Read `.azure/integration-plan.md` | The scaffold agent wrote this for you. Extract: backend project path + run command + port; frontend project path + build/dev commands; the API route inventory (method + path); the database type + migration tool + migration directory + connection env vars; the **API seam to swap** (`src/api/index.ts`) + the **mock files to delete** (`src/api/mockClient.ts`, `src/mocks/*`, the dev-only Mock State Switcher `src/api/previewState.ts` + its corner-switcher component); the shared-types/package location; the health endpoint. |
|
||||
| Read `.azure/project-plan.md` | Cross-check routes (Section 7), services (Section 4), entities/types, and the database choice. The plan is the source of truth where the artifact is silent. |
|
||||
| Scan the workspace | Confirm the folders the artifact names actually exist. List the frontend `src/` to locate the API seam (`src/api/` — `index.ts`, `mockClient.ts`) and the mock data (`src/mocks/`). List the backend functions folder to count handlers. List the migration directory. |
|
||||
| Check database type | If the plan/artifact specifies PostgreSQL or Azure SQL (relational), migrations are **mandatory** (Step 1). If the project uses only non-relational storage (Cosmos, Table, Blob), Step 1's SQL migrations are N/A — note it and skip to Step 2. |
|
||||
|
||||
> **✅ Checkpoint**: Artifact loaded (or reconstructed from the plan + scan). You know: the backend run command, the frontend folder + commands, the full route list, the DB type + migration tool + directory, the API seam to repoint (`src/api/index.ts`), and the exact mock files to delete.
|
||||
|
||||
---
|
||||
|
||||
## STEP 1: Database Schema Migrations (NO SEED DATA)
|
||||
|
||||
> ⛛ **MANDATORY for relational databases (PostgreSQL / Azure SQL).** Skip only if the project has no relational database. Without migrations, every handler fails with `relation "X" does not exist` — the smoke test in Step 2 cannot pass.
|
||||
|
||||
**Goal**: Repeatable schema management — every table the handlers read/write exists, with full constraints. **Schema only. No data.**
|
||||
|
||||
| Task | Details |
|
||||
|------|---------|
|
||||
| Identify the migration tool | From the artifact/plan: Knex (Node.js) / Alembic (Python) / EF Core (.NET). If none configured, add the conventional one for the stack and wire its config. |
|
||||
| Derive the schema from the entities + handlers | For each entity type / collection the handlers use, define a table. Read the handler data-access patterns so columns and types match what the code actually reads/writes. |
|
||||
| Write the migration(s) | Each migration MUST contain a complete `up()` with `CREATE TABLE` (all columns, types) and a `down()` that reverses it. **Empty migration files do NOT satisfy this step.** After writing, list the directory and verify each file is non-zero size. |
|
||||
| Add constraints | `UNIQUE` on business-unique fields, `FOREIGN KEY` with `ON DELETE`, `CHECK` for enums, `INDEX` on queried columns. (See [migrations.md](.github/agents/azure-project-integrate/references/migrations.md).) |
|
||||
| Create / confirm the migration runner | A script or command to apply migrations forward and roll back. Add an npm/poetry/dotnet script if missing (e.g. `"migrate"`, `"migrate:rollback"`). |
|
||||
| Verify table names match handlers | Cross-reference every table against the collection/table names the handlers use. Document the mapping if a `collectionToTable` map exists. |
|
||||
| Apply the migrations | Run the migrate command against the local database (start the local DB / emulator if the artifact documents one). Confirm it applies with **zero errors** and the tables now exist. |
|
||||
|
||||
> ⛔ **DO NOT** create `seeds/`, `seed.ts`, `seed-data.json`, fixtures, or insert demo rows. If the scaffold created any, leave them untouched and do not invoke them. The schema must stand on its own.
|
||||
|
||||
> **✅ Checkpoint**:
|
||||
> - Migration files exist and each is non-empty (list the directory, verify > 0 bytes).
|
||||
> - Migrations apply cleanly against the local database — tables created, zero errors.
|
||||
> - Every plan/handler table has a corresponding `CREATE TABLE` with constraints.
|
||||
> - **No seed/fixture/demo-data files were created or run.**
|
||||
|
||||
---
|
||||
|
||||
## STEP 2: Backend Smoke Test
|
||||
|
||||
**Goal**: Prove the backend actually starts and every endpoint registers and responds — catching the runtime errors (broken imports, constructor crashes, missing tables) that a compile-time build never surfaces.
|
||||
|
||||
| Task | Details |
|
||||
|------|---------|
|
||||
| Ensure config/env is present | Confirm `.env` / `local.settings.json` has the values the backend needs (DB connection string pointing at the local DB from Step 1, required service vars). Use the scaffold's `.env.example` as the template. **Do not** commit secrets. |
|
||||
| Build the backend | Run the backend build (`npm run build` / `tsc` / `dotnet build` / `python -m py_compile`). Zero errors. If `TS2307` import errors appear, the shared package exports are broken — fix before continuing. |
|
||||
| Verify the `main`/entry field | For Azure Functions Node v4, list `dist/` and confirm the `main` glob matches the compiled handlers (a parent `rootDir` nests output deeper). Fix before starting the host. |
|
||||
| Start the backend host | Run the run command from the artifact (e.g. `func start`, `npm start`, `dotnet run`). It MUST actually execute — do not skip. |
|
||||
| Verify all functions register | Read the host console output. **Every** route from the inventory must register. `No job functions found` or `ERR_MODULE_NOT_FOUND` = an import/build bug — fix and restart. |
|
||||
| Hit the health endpoint | `GET /api/health` (or the artifact's health path) → expect `200`. Confirms the app serves. |
|
||||
| Probe representative endpoints | For each entity area, exercise at least one endpoint (a `GET` list/read, and ideally one write). Expect a structured response or a well-formed validation/`4xx` error — **not** a `500` from a missing table or crashed service. A clean `4xx` for missing auth/body is a PASS; a `500` is a FAIL to investigate. |
|
||||
| Stop the host when done | Stop the backend process after probing (leave it running only if Step 4 needs it concurrently). |
|
||||
|
||||
**Reference**: [smoke-test.md](.github/agents/azure-project-integrate/references/smoke-test.md) for the per-runtime start commands, how to read host output, and the pass/fail matrix.
|
||||
|
||||
> **✅ Checkpoint**:
|
||||
> - Backend builds with zero errors and the host starts.
|
||||
> - Every endpoint in the inventory registers.
|
||||
> - `GET /api/health` → `200`.
|
||||
> - Probed endpoints return structured responses or clean `4xx` — **no `500`s from schema/runtime bugs**.
|
||||
> - Any failure found here was fixed and re-verified, not deferred.
|
||||
|
||||
---
|
||||
|
||||
## STEP 3: Wire the Frontend to LIVE Data
|
||||
|
||||
**Goal**: Replace every mock data source in the frontend with real, typed calls to the backend verified in Step 2. After this step, **no mock data layer is in use**.
|
||||
|
||||
> **Skip** only if the project has no frontend.
|
||||
|
||||
| Task | Details |
|
||||
|------|---------|
|
||||
| Locate the seam | The scaffold left a stable `ApiClient` seam: `src/api/types.ts` (interface), `src/api/mockClient.ts` (mock impl), `src/api/index.ts` (the one-line swap point). Pages/hooks import only `api` from `src/api/`. Confirm this seam exists (artifact + scan). |
|
||||
| Replace local types with shared types | Point `src/api/types.ts` at the shared package (e.g. `import type { PublicUser } from '@app/shared'`); delete the frontend's duplicated entity types. The `ApiClient` shape is unchanged. **No `any` types.** |
|
||||
| Build the live client | Add `src/api/client.ts` — a second implementation of the **same `ApiClient` interface** (typed `: ApiClient`), method-for-method against the route inventory, base URL from env. |
|
||||
| **Swap the seam (one file)** | Edit `src/api/index.ts` so `api` points at the live client (`mockClient` → `liveClient`). This single line wires every page/hook to live data — **no page or hook edits**. |
|
||||
| Configure the dev proxy | Point the dev server's `/api` proxy at the backend host (e.g. `http://localhost:7071`) so the frontend reaches live endpoints in development. |
|
||||
| Remove the mock layer | Delete `src/api/mockClient.ts` and `src/mocks/*` (and local types now sourced from shared). A lingering `import … from './mockClient'` or `'../mocks'` = NOT done. |
|
||||
| **Remove the Mock State Switcher** | Delete the dev-only state switcher the scaffold added: `src/api/previewState.ts`, its corner-switcher component, and every `previewState` import/usage in the mock client, pages, hooks, and app shell. Live data is the only source now — the forced `loading`/`empty`/`error` override must be gone. A lingering `import … previewState` or a rendered Data/Loading/Empty/Error switcher = NOT done. |
|
||||
| Keep correct file extensions | JSX (`<Component />`) MUST be `.tsx`; pure TS `.ts`. |
|
||||
| Rebuild the frontend | Run `npm --prefix <frontend> run build` (cwd-independent). Zero errors, zero `any`. |
|
||||
|
||||
> ⚠️ **No mock data may remain in use.** Searching the frontend `src/` for `mock` / `mockData` / `previewState` must turn up nothing that is still imported. `useState<any>` or untyped responses = NOT done.
|
||||
|
||||
> **Reference**: [wire-live-data.md](.github/agents/azure-project-integrate/references/wire-live-data.md) for the one-file seam swap, the typed-client pattern, and the dev-proxy config per framework.
|
||||
|
||||
> **✅ Checkpoint**:
|
||||
> - Frontend builds with zero errors and zero `any`.
|
||||
> - The mock layer (`src/api/mockClient.ts`, `src/mocks/*`) is deleted or no longer imported anywhere.
|
||||
> - The Mock State Switcher (`src/api/previewState.ts` + corner switcher component) is deleted and no longer imported anywhere.
|
||||
> - The seam (`src/api/index.ts`) points at the live client; pages/hooks were not edited.
|
||||
> - The dev proxy targets the backend host.
|
||||
|
||||
---
|
||||
|
||||
## STEP 4: End-to-End Wire-Up Verification
|
||||
|
||||
**Goal**: Run the frontend and backend **together** and confirm they actually communicate over the wire.
|
||||
|
||||
| Task | Details |
|
||||
|------|---------|
|
||||
| Start the backend | Start the backend host (from Step 2) so it is listening. |
|
||||
| Start the frontend dev server | Start the frontend dev server (`npm --prefix <frontend> run dev`) with the dev proxy pointing at the backend. |
|
||||
| Verify a live request path | Confirm the frontend successfully fetches from the backend — inspect the dev-server/host logs for a real `/api/...` request returning `200` (or load a page via the browser tool and confirm live data renders, not a mock placeholder). At least one page MUST display data that came from the running backend. |
|
||||
| Verify a write path (if applicable) | If the app has a create/update flow, exercise one and confirm the backend receives it and the frontend reflects the result. |
|
||||
| Capture evidence | Record the request/response (path, status) that proves frontend → backend wiring works. |
|
||||
| Shut down cleanly | Stop both processes after verifying. |
|
||||
|
||||
**Reference**: [end-to-end.md](.github/agents/azure-project-integrate/references/end-to-end.md) for running both processes concurrently cross-platform and reading the evidence.
|
||||
|
||||
> **✅ Checkpoint**:
|
||||
> - Frontend and backend ran concurrently.
|
||||
> - At least one real `/api/...` request from the frontend hit the backend and returned `200` with live data (no mock).
|
||||
> - Evidence captured. Both processes stopped cleanly.
|
||||
|
||||
---
|
||||
|
||||
## STEP 5: Wrap Up
|
||||
|
||||
**Goal**: Confirm all four tasks pass, update status, and stop.
|
||||
|
||||
| Task | Details |
|
||||
|------|---------|
|
||||
| Confirm all four checkpoints passed | Migrations applied · backend smoke-tested · frontend on live data · end-to-end verified. |
|
||||
| Update the artifact | Mark `.azure/integration-plan.md` items complete (or append a short "Integration results" section: what was migrated, which endpoints passed, the mock files removed, the end-to-end evidence). |
|
||||
| Update plan status | Set `.azure/project-plan.md` status to `Integrated`. |
|
||||
| Print completion | Summarize: migrations created, endpoints verified, mock layer removed, end-to-end request proven. Announce: **"Integration complete!"** |
|
||||
| **Open the Next Steps view, then stop** | Call the `open_scaffold_next_steps_view` tool with no arguments (`{}`) to surface the post-integration "What's next?" view. Then **STOP** — the view owns the next hand-off (set up local development, or deploy). Do **NOT** ask the user what to do next; do **NOT** call `vscode_askQuestions`. (Autopilot exception: **skip** this view and hand off via the `start_local_development` tool per the agent's autopilot rule.) |
|
||||
|
||||
> **✅ Final Checkpoint**:
|
||||
> 1. Migrations exist, are non-empty, apply cleanly — **no seed data**.
|
||||
> 2. Backend host starts, all endpoints register, `GET /api/health` → 200, probes return no schema/runtime `500`s.
|
||||
> 3. Frontend builds clean on live data; mock layer removed; no `any`.
|
||||
> 4. Frontend + backend ran together; a real `/api/...` request returned live data.
|
||||
> 5. `.azure/project-plan.md` = `Integrated`; artifact updated.
|
||||
> 6. Opened the **Next Steps view** (the `open_scaffold_next_steps_view` tool), then stopped — **no follow-up prompt** (autopilot instead hands off to `azure-debug-plan`).
|
||||
|
||||
---
|
||||
|
||||
## Outputs
|
||||
|
||||
| Artifact | Location |
|
||||
|----------|----------|
|
||||
| Schema migrations | The project's migration directory (e.g. `services/functions/migrations/`) — **schema only, no seeds** |
|
||||
| Real typed API client | `services/web/src/api/client.ts` + seam repoint in `services/web/src/api/index.ts` (or the project's frontend) |
|
||||
| Dev proxy config | The frontend dev-server config (e.g. `vite.config.ts`) |
|
||||
| Updated artifact | `.azure/integration-plan.md` (results appended) |
|
||||
| Plan status | `.azure/project-plan.md` → `Integrated` |
|
||||
| **Next step** | Open the Next Steps view via the `open_scaffold_next_steps_view` tool (autopilot instead hands off to `azure-debug-plan`) |
|
||||
|
||||
---
|
||||
|
||||
## Next
|
||||
|
||||
> After integration completes, announce **"Integration complete!"**, then open the post-integration **Next Steps view** by calling the `open_scaffold_next_steps_view` tool (no arguments). After opening it, **stop** — the view drives the next hand-off (local development or deploy). Do NOT ask the user what to do next — do NOT call `vscode_askQuestions` or print plain-text follow-up suggestions. (Autopilot exception: **skip** the view and hand off via the `start_local_development` tool with the `[AUTOPILOT MODE]` marker.)
|
||||
@@ -0,0 +1,40 @@
|
||||
<!-- 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.
|
||||
|
||||
# End-to-End Wire-Up Verification
|
||||
|
||||
> Read at **Step 4**. How to run the frontend and backend together and prove they communicate.
|
||||
|
||||
---
|
||||
|
||||
## Run both processes concurrently (cross-platform)
|
||||
|
||||
Start each in its own terminal (async), never with shell-specific backgrounding (`&`, `Start-Job` chains):
|
||||
|
||||
1. **Backend** — the run command from the artifact, e.g. `func start` (cwd = backend folder). Wait until the host prints that all functions registered.
|
||||
2. **Frontend** — `npm --prefix services/web run dev` (cwd-independent). Wait until the dev server prints its local URL.
|
||||
|
||||
The frontend dev proxy (configured in Step 3) forwards `/api` to the backend, so the two talk over `localhost`.
|
||||
|
||||
---
|
||||
|
||||
## Prove the wiring
|
||||
|
||||
You need **at least one real `/api/...` request from the frontend that hits the backend and returns `200` with live data** — not a mock placeholder. Any one of:
|
||||
|
||||
- **Logs**: the backend host logs an incoming `GET /api/...` → `200` that originated from the dev server (not your manual curl).
|
||||
- **Browser**: load a page with the browser tool; confirm it renders data that came from the backend (and that the network panel shows the `/api` call succeeding). The data must match what the empty-schema backend returns (often an empty list rendering the "empty" state — that is still a valid live response, distinct from mock content).
|
||||
- **Write path** (if the app has one): perform a create/update in the UI; confirm the backend receives it and the UI reflects the result.
|
||||
|
||||
---
|
||||
|
||||
## Capture evidence & shut down
|
||||
|
||||
- Record the proof: the request path, method, and status (e.g. `GET /api/users → 200`) that demonstrates frontend → backend wiring.
|
||||
- Stop both processes cleanly when done (do not leave servers running).
|
||||
|
||||
---
|
||||
|
||||
## Distinguishing live from mock
|
||||
|
||||
If a page still shows the scaffold's mock content (named demo records, lorem data) while the backend DB is empty, the frontend is **still on mock data** — return to Step 3. A correctly wired app against an empty schema typically shows empty/loading states populated by real (empty) responses, or real data you created via a write path.
|
||||
@@ -0,0 +1,54 @@
|
||||
<!-- 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.
|
||||
|
||||
# Schema Migrations (NO seed data)
|
||||
|
||||
> Read at **Step 1**. Canonical guidance for creating SQL / PostgreSQL schema migrations during integration. **Schema only — never seed data.**
|
||||
|
||||
---
|
||||
|
||||
## The one hard rule
|
||||
|
||||
You create **structure**, not **content**. Allowed: `CREATE TABLE`, `ALTER TABLE`, constraints, indexes, the migration runner. **Forbidden:** `INSERT`, demo rows, and any file/folder/function named `seed`, `seeds`, `seed-data`, `fixtures`. If the scaffold already produced seed files, leave them where they are — do not extend, run, or depend on them.
|
||||
|
||||
---
|
||||
|
||||
## Per-stack migration tool
|
||||
|
||||
| Stack | Tool | Create | Apply | Roll back |
|
||||
|-------|------|--------|-------|-----------|
|
||||
| Node.js / TypeScript | Knex | `knex migrate:make <name>` | `knex migrate:latest` | `knex migrate:rollback` |
|
||||
| Python | Alembic | `alembic revision -m "<name>"` | `alembic upgrade head` | `alembic downgrade -1` |
|
||||
| C# / .NET | EF Core | `dotnet ef migrations add <Name>` | `dotnet ef database update` | `dotnet ef database update <Prev>` |
|
||||
|
||||
Add the apply/rollback commands as scripts (`"migrate"`, `"migrate:rollback"`) if the scaffold did not.
|
||||
|
||||
---
|
||||
|
||||
## Every migration file MUST contain real code
|
||||
|
||||
- A complete `up()` (or `upgrade()`): `CREATE TABLE` with **all** columns and types the handlers use.
|
||||
- A complete `down()` (or `downgrade()`): reverses the `up()` (`DROP TABLE`, etc.).
|
||||
- After writing, **list the directory and confirm each file is > 0 bytes**. An empty migration file does not satisfy Step 1.
|
||||
|
||||
## Constraints to include (Step 1 requires these)
|
||||
|
||||
| Constraint | When |
|
||||
|-----------|------|
|
||||
| `UNIQUE` | Business-unique fields (email, slug, external id) |
|
||||
| `FOREIGN KEY … ON DELETE` | Every relationship; choose `CASCADE` / `SET NULL` deliberately |
|
||||
| `CHECK` | Enum-like columns (status, role) |
|
||||
| `INDEX` | Columns used in `WHERE` / `JOIN` / `ORDER BY` |
|
||||
| `NOT NULL` + sensible defaults | Required columns; timestamps default to `now()` |
|
||||
|
||||
## Derive the schema from real usage
|
||||
|
||||
Read the handler data-access code (and the entity types) before writing columns — the table must match what the code actually reads and writes. Cross-reference every table name against the collection/table names the handlers use (a `collectionToTable` map if one exists). A mismatch here is the #1 cause of `relation "X" does not exist` at smoke-test time.
|
||||
|
||||
## Apply, then prove
|
||||
|
||||
1. Start the local database / emulator if the artifact documents one.
|
||||
2. Run the apply command. Expect zero errors.
|
||||
3. Confirm the tables now exist (the migration tool's status command, or a `\dt` against the local DB).
|
||||
|
||||
The proof that migrations are correct is **Step 2's smoke test passing** — handlers querying these tables must not 500.
|
||||
@@ -0,0 +1,53 @@
|
||||
<!-- 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.
|
||||
|
||||
# Backend Smoke Test
|
||||
|
||||
> Read at **Step 2**. How to start the backend and prove every endpoint registers and responds.
|
||||
|
||||
---
|
||||
|
||||
## Per-runtime start command
|
||||
|
||||
| Runtime | Build | Start host | Default port |
|
||||
|---------|-------|-----------|--------------|
|
||||
| Azure Functions (Node v4 / TS) | `npm run build` | `func start` | 7071 |
|
||||
| Azure Functions (Python v2) | `python -m py_compile` (or build) | `func start` | 7071 |
|
||||
| Azure Functions (.NET isolated) | `dotnet build` | `func start` (or `dotnet run`) | 7071 |
|
||||
| Plain Node API | `npm run build` | `npm start` | project-defined |
|
||||
|
||||
Run the exact command the artifact (`.azure/integration-plan.md`) documents — it reflects the real project.
|
||||
|
||||
---
|
||||
|
||||
## Before starting: config & build
|
||||
|
||||
- Ensure `.env` / `local.settings.json` has the values the host needs — especially the **DB connection string** pointing at the local database from Step 1. Use `.env.example` as the template. Never commit secrets.
|
||||
- Build first. Zero errors. `TS2307: Cannot find module '@app/shared'` → the shared package exports/build are broken; fix before starting.
|
||||
- For Functions Node v4: list `dist/` and confirm the `main` glob matches the compiled handler paths. A parent `rootDir` nests output one level deeper (`dist/functions/src/functions/*.js`). Fix `main` before starting or no functions register.
|
||||
|
||||
---
|
||||
|
||||
## Reading host output (pass/fail)
|
||||
|
||||
| Console signal | Meaning | Action |
|
||||
|----------------|---------|--------|
|
||||
| Each function name listed under "Functions:" | Registered | PASS |
|
||||
| `No job functions found.` | Build/`main` mismatch | Fix `main`/build, restart |
|
||||
| `ERR_MODULE_NOT_FOUND` / broken import | Bad import or missing dist | Fix import/build, restart |
|
||||
| Constructor throws on startup | A service (often Enhancement) throws in its constructor | Defer config validation out of the constructor / wrap in try-catch, restart |
|
||||
|
||||
---
|
||||
|
||||
## Probing endpoints
|
||||
|
||||
| Probe | Expected | Verdict |
|
||||
|-------|----------|---------|
|
||||
| `GET /api/health` | `200` with status body | PASS (required) |
|
||||
| `GET` a list/read endpoint | `200` with array/object, or clean `401/400` | PASS |
|
||||
| A write endpoint with missing/invalid body | `400`/`401` structured error | PASS (validation working) |
|
||||
| Any endpoint returning `500` | Schema missing, service crash, unhandled error | **FAIL — investigate & fix** |
|
||||
|
||||
A clean `4xx` (missing auth, invalid body) is a **PASS** — it proves validation and routing work. A `500` is a **FAIL**: most often a missing table (revisit Step 1) or a service constructor crash.
|
||||
|
||||
Use `curl`/`Invoke-RestMethod` or the browser tool to hit endpoints. Stop the host when probing is done (unless Step 4 will reuse it).
|
||||
@@ -0,0 +1,94 @@
|
||||
<!-- 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.
|
||||
|
||||
# Wire Frontend to Live Data
|
||||
|
||||
> Read at **Step 3**. The scaffold built the frontend behind a stable `ApiClient` seam (`src/api/`), so wiring to live data is a **one-file swap** at the seam plus a types switch — not a call-site rewrite.
|
||||
|
||||
---
|
||||
|
||||
## The seam the scaffold left you
|
||||
|
||||
The scaffold wired the frontend so **no page or hook imports the mock directly**. They all import a single `api` object from `services/web/src/api/`:
|
||||
|
||||
- `src/api/types.ts` — the `ApiClient` interface (one method per endpoint in the route inventory).
|
||||
- `src/api/mockClient.ts` — the mock implementation of `ApiClient` (reads `src/mocks/data.ts`).
|
||||
- `src/api/index.ts` — the **single swap point**: `export const api: ApiClient = mockClient;`
|
||||
|
||||
Your job is to add the live implementation and repoint that one file. Because pages/hooks import only `api` from the seam, **you do not touch them**.
|
||||
|
||||
---
|
||||
|
||||
## Goal: no mock data remains in use
|
||||
|
||||
After this step, a search of the frontend `src/` for `mock` / `mockData` / `previewState` must find nothing that is still imported. The app fetches everything from the live backend.
|
||||
|
||||
---
|
||||
|
||||
## Replacement recipe (one-file swap)
|
||||
|
||||
1. **Adopt shared types.** Point `src/api/types.ts` (or the local entity types it references) at the shared package instead of the duplicated local types:
|
||||
```ts
|
||||
import type { PublicUser, CreateUserRequest } from '@app/shared';
|
||||
```
|
||||
No `any`. The `ApiClient` interface stays the same shape — only the types it references come from the shared contract.
|
||||
2. **Build the live client** at `src/api/client.ts` — a second implementation of the **same `ApiClient` interface**, method-for-method, so it drops into the seam without touching callers:
|
||||
```ts
|
||||
import type { ApiClient } from './types';
|
||||
import type { PublicUser, CreateUserRequest } from '@app/shared';
|
||||
|
||||
const BASE = import.meta.env.VITE_API_BASE ?? '/api';
|
||||
|
||||
async function request<T>(path: string, init?: RequestInit): Promise<T> {
|
||||
const res = await fetch(`${BASE}${path}`, {
|
||||
headers: { 'Content-Type': 'application/json', ...(init?.headers ?? {}) },
|
||||
...init,
|
||||
});
|
||||
if (!res.ok) {
|
||||
const body = await res.json().catch(() => ({}));
|
||||
throw new ApiError(res.status, body?.error?.message ?? res.statusText);
|
||||
}
|
||||
return res.json() as Promise<T>;
|
||||
}
|
||||
|
||||
export const liveClient: ApiClient = {
|
||||
listUsers: () => request<PublicUser[]>('/users'),
|
||||
getUser: (id) => request<PublicUser>(`/users/${id}`),
|
||||
// ...one method per endpoint, matching the ApiClient interface exactly
|
||||
};
|
||||
```
|
||||
Because `liveClient` is typed `: ApiClient`, the compiler guarantees it covers every method the pages already call.
|
||||
3. **Swap the seam — the one file that changes.** Edit `src/api/index.ts` so `api` points at the live client:
|
||||
```ts
|
||||
import type { ApiClient } from './types';
|
||||
import { liveClient } from './client';
|
||||
export const api: ApiClient = liveClient;
|
||||
export type { ApiClient } from './types';
|
||||
```
|
||||
That single line (`mockClient` → `liveClient`) is the entire wire-up for the call sites. **No page or hook edits.**
|
||||
4. **Remove the mock layer.** Delete `src/api/mockClient.ts` and `src/mocks/*` (and any local duplicated types now sourced from shared). A lingering `import … from './mockClient'` or `from '../mocks'` means the step is not done.
|
||||
5. **Remove the Mock State Switcher.** The scaffold always adds a dev-only state switcher (`src/api/previewState.ts` + a fixed-corner Data/Loading/Empty/Error component) that forces the mock client into `loading` / `empty` / `error`. Delete `src/api/previewState.ts`, its corner-switcher component, and every `previewState` import/usage in the mock client, pages, hooks, and app shell. Live data is the only source now — a lingering `import … previewState` or a rendered Data/Loading/Empty/Error switcher means the step is not done.
|
||||
6. **Rebuild.** `npm --prefix services/web run build` — zero errors, zero `any`. Fix any `.ts`/`.tsx` extension mismatch (JSX must be `.tsx`).
|
||||
|
||||
> **If the scaffold did NOT leave a `src/api/` seam** (older scaffold, or a hand-written frontend): fall back to the call-site approach — find every `import … from '.../mocks'`, replace with a real `api.*` call, preserve the four data states. But first establish the seam (`src/api/index.ts`) so any future change stays a one-file swap.
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Dev proxy (so `/api` reaches the backend)
|
||||
|
||||
Point the dev server's `/api` proxy at the backend host from Step 2.
|
||||
|
||||
**Vite** (`vite.config.ts`):
|
||||
```ts
|
||||
export default defineConfig({
|
||||
server: {
|
||||
host: true, // preserve preview compatibility (webview iframe / forwarded host)
|
||||
allowedHosts: true, // dev-only: don't 403-block the webview / forwarded origin
|
||||
strictPort: false,
|
||||
proxy: { '/api': { target: 'http://localhost:7071', changeOrigin: true } },
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
**Keep** the `host` / `allowedHosts` / `strictPort` settings the scaffold added — they let the frontend load inside a webview iframe and forwarded (remote / Codespaces) hosts; only add the `proxy` entry. For other frameworks use their equivalent proxy config (Next.js `rewrites`, Angular `proxy.conf.json`). Keep the target in sync with the backend port the artifact documents.
|
||||
Reference in New Issue
Block a user