fix: repair cp1252-mangled em-dashes and ellipsis in the reference-app wiki
All checks were successful
continuous-integration/drone/push Build is passing

All four 06_reference_app pages round-tripped U+2014 (em-dash) and U+2026
(ellipsis) through cp1252 during earlier PowerShell edits; restored the
characters and regenerated the wiki HTML + MCP modules.
This commit is contained in:
2026-10-20 23:48:08 +05:30
parent a7f0576f1d
commit 7f951f3fe7
13 changed files with 69 additions and 69 deletions

View File

@@ -1,7 +1,7 @@
# Reference App — Overview
# Reference App — Overview
The standards ship a **runnable sample** of the whole blueprint: the **vet**
veterinary-clinic application. It exists to be copied — it is the reference
veterinary-clinic application. It exists to be copied — it is the reference
for how a real domain sits on the architecture, and the code an agent pulls
through the MCP tools (`get_app_template`, `get_app_component`).
@@ -17,12 +17,12 @@ through the MCP tools (`get_app_template`, `get_app_component`).
| Aggregate | What it demonstrates |
|---------------|---------------------------------------------------------------|
| **parents** | The simplest CRUD slice (no foreign keys) — copy this first |
| **parents** | The simplest CRUD slice (no foreign keys) — copy this first |
| **pets** | Embedded list-of-refs (`parents[]`), file upload, enum fields |
| **treatments**| Plain resource with pricing fields |
| **vets** | Plain resource; target of prefetch FKs |
| **appointments** | Single FKs (`pet`, `vet`, `treatment`) expanded on read, filtered list |
| **jobs** | The worker's queue — durable status machine |
| **jobs** | The worker's queue — durable status machine |
The pipeline axis ships one worked family, **`appointment_reminder`**, plus the
reusable `pipelines/shared/` scaffold and a `worker.py` that dispatches jobs by
@@ -41,7 +41,7 @@ python -m scripts.seed # optional: seed demo data (mongo backend)
```
The default `REPO_BACKEND=memory` means the API boots with **no external
services** — repositories are process-local dictionaries. Switch to
services** — repositories are process-local dictionaries. Switch to
`REPO_BACKEND=mongo` for persistence (see `.env.example`).
The client pairs with it:
@@ -60,11 +60,11 @@ npm run dev # Vite dev server
(`{AUTH_SERVER}` introspection). Without a reachable auth-server the API
answers `401` on resource routes; `/health` stays public. For a local
no-auth demo, remove the `security` block from `openapi.yaml` and the
global security entry — see
global security entry — see
[Auth Integration](../lib/22_auth_integration/).
## Next
- [Domain & API](02_domain_and_api.md) — walking the resource axis
- [Pipelines & Worker](03_pipelines_and_worker.md) — the pipeline axis
- [Client Admin](04_client_admin.md) — the spec-driven frontend
- [Domain & API](02_domain_and_api.md) — walking the resource axis
- [Pipelines & Worker](03_pipelines_and_worker.md) — the pipeline axis
- [Client Admin](04_client_admin.md) — the spec-driven frontend

View File

@@ -1,4 +1,4 @@
# Domain & API — the resource axis
# Domain & API — the resource axis
Every aggregate follows the same four-file slice
([CRUD Template](../lib/21_crud_template/)); walk `parents` first, then
@@ -13,10 +13,10 @@ domain/parents/
db.py # ParentDocument(Parent, BaseDocument) + create_parent_repo()
service.py # ParentCrudsService(CrudsServiceAdaptor[...]) + get_parent_service()
interfaces/parents/
routes.py # list/create/get/update/delete — names == operationIds
routes.py # list/create/get/update/delete — names == operationIds
```
Wiring happens in exactly one place — the composition root
Wiring happens in exactly one place — the composition root
`init.py`:
```python
@@ -41,7 +41,7 @@ single source of truth: `main.py` builds an `OpenAPIFirstApp` that binds each
re-export of every routes module). There are no decorator routers.
The x- extension fields on schemas and properties are what make the admin
client render itself — see [Auto-Rendered Admin](../lib/40_ui_admin/) and
client render itself — see [Auto-Rendered Admin](../lib/40_ui_admin/) and
the worked `Job` schema (enum selects, hidden fields, filterable columns).
## Foreign keys (appointments)
@@ -54,7 +54,7 @@ fully expanded objects:
pet = await expand_ref(svc(request, "pet"), body.get("pet"), "pet")
```
The list endpoint additionally filters by date prefix and embedded fk ids —
The list endpoint additionally filters by date prefix and embedded fk ids —
client-side over the repository result, the pattern for small reference data.
## Ids on the wire
@@ -67,7 +67,7 @@ Mongo persistence layer consistent.
## Tests
- `tests/integration/test_openapi_app_builds.py` — generic gate: every
- `tests/integration/test_openapi_app_builds.py` — generic gate: every
`operationId` resolves and the app builds. Copy it verbatim.
- `tests/unit/test_jobs_routes.py` — the pattern for route unit tests with a
- `tests/unit/test_jobs_routes.py` — the pattern for route unit tests with a
service double (no HTTP client needed).

View File

@@ -1,4 +1,4 @@
# Pipelines & Worker — the pipeline axis
# Pipelines & Worker — the pipeline axis
The sample proves the full loop: **API creates a job document → worker polls →
pipeline family runs → job reaches a terminal status.**
@@ -46,7 +46,7 @@ reminder = await pipeline.run(appointment_id)
```
To add a family: copy `appointment_reminder/`, replace the stages, call
`register(kind, variant, root_cls)` — see
`register(kind, variant, root_cls)` — see
[Pipeline Scaffold](../lib/50_pipeline_scaffold/).
## The worker
@@ -56,7 +56,7 @@ documents into execution:
1. poll `job_svc.search({"status": "pending"})` on `WORKER_POLL_SECONDS`
2. claim a job: `status → processing`
3. dispatch through the `HANDLERS` table — `HANDLERS[job.kind](job, resources)`
3. dispatch through the `HANDLERS` table — `HANDLERS[job.kind](job, resources)`
4. on success `status → done`; on exception `status → failed`,
`retry_count += 1`, `error_message` captured; jobs at
`WORKER_MAX_RETRIES` are skipped
@@ -69,17 +69,17 @@ HANDLERS: dict[str, Callable] = {
```
The worker shares the composition root: `from init import init` gives it the
same wired services the API uses — one place to add a dependency.
same wired services the API uses — one place to add a dependency.
!!! note "Same process model in production"
API and worker are separate processes (see `docker-compose.yaml`: `api`,
`worker`, `mongo`). Any in-memory progress bus is per-process; to surface
live progress through the API, swap the bus adaptor for a broker-backed
one — see [Worker & Progress](../lib/51_worker_and_progress/).
one — see [Worker & Progress](../lib/51_worker_and_progress/).
## Tests
- `tests/unit/test_appointment_reminder_pipeline.py` — stage units + the wired
- `tests/unit/test_appointment_reminder_pipeline.py` — stage units + the wired
root against a fake service.
- `tests/unit/test_worker.py` — dispatch, done/failed transitions, retry
- `tests/unit/test_worker.py` — dispatch, done/failed transitions, retry
exhaustion, using an in-memory job service double and a cancelled poll task.

View File

@@ -1,7 +1,7 @@
# Client Admin — the spec-driven frontend
# Client Admin — the spec-driven frontend
The client sample (`standards/src/templates/client/`) renders a full admin —
auth pages, resource lists, forms, detail views — **from the server's
The client sample (`standards/src/templates/client/`) renders a full admin —
auth pages, resource lists, forms, detail views — **from the server's
`openapi.yaml`**, driven entirely by the x- extension fields. There are no
hand-written screens per resource.
@@ -9,10 +9,10 @@ hand-written screens per resource.
A Vite + React + MUI app wiring the two Aetos packages:
- **`@aetoskia/react-openapi`** — fetches `${VITE_API_BASE_URL}/openapi.json`,
- **`@aetoskia/react-openapi`** — fetches `${VITE_API_BASE_URL}/openapi.json`,
builds the router and the resource admin from the spec's schemas and x-
fields (list columns, autocomplete, fk pickers, enum selects, hidden fields…)
- **`@aetoskia/react-auth`** — login/register/logout against the auth-server
fields (list columns, autocomplete, fk pickers, enum selects, hidden fields…)
- **`@aetoskia/react-auth`** — login/register/logout against the auth-server
paths declared in the spec's `securitySchemes.bearerAuth`, and attaches the
JWT to every API call
- a shared MUI theme (`src/shared-theme/`) and the shell
@@ -40,7 +40,7 @@ npm run dev
Open the dev-server URL; the admin lists Parents, Pets, Treatments, Vets,
Appointments and Jobs straight from the vet spec. Edit `openapi.yaml` on the
server and the client follows on reload — the spec is the contract on both
server and the client follows on reload — the spec is the contract on both
sides.
## Where the x- extensions come from