Task 002: add shared domain contracts

This commit is contained in:
2026-05-21 17:45:00 +03:00
parent d42f0c4392
commit a0ae06adfa
31 changed files with 4043 additions and 27 deletions
+73 -12
View File
@@ -30,12 +30,12 @@ Development description: Implement the shared domain schema package that defines
## Acceptance Criteria
- [ ] TDD pre-requirement: before implementation, write a failing contract test for one externally visible DTO and one invalid payload; proceed one schema at a time and record red-green evidence in `Result`.
- [ ] Workflow status transitions use shared constants rather than string literals spread across apps.
- [ ] Role names are exactly `ADMIN` and `EDITOR`.
- [ ] Generated frontend types match backend OpenAPI.
- [ ] Contract tests fail on missing required fields and invalid enum values.
- [ ] Runner job output schemas can be validated without importing frontend code.
- [x] TDD pre-requirement: before implementation, write a failing contract test for one externally visible DTO and one invalid payload; proceed one schema at a time and record red-green evidence in `Result`.
- [x] Workflow status transitions use shared constants rather than string literals spread across apps.
- [x] Role names are exactly `ADMIN` and `EDITOR`.
- [x] Generated frontend types match backend OpenAPI.
- [x] Contract tests fail on missing required fields and invalid enum values.
- [x] Runner job output schemas can be validated without importing frontend code.
## Verification
@@ -45,9 +45,70 @@ Development description: Implement the shared domain schema package that defines
## Result
- Status: Pending execution.
- TDD plan: To be filled during execution.
- Red evidence: To be filled during execution.
- Green evidence: To be filled during execution.
- Refactor notes: To be filled during execution.
- Verification output: To be filled during execution.
- Status: Completed.
- TDD plan:
- Add one backend public OpenAPI contract test before implementation.
- Verify `POST /api/articles` exposes `ArticleCreateRequest` as an external request DTO.
- Verify `ArticleCreateRequest` requires `brief_description` and `target_site_id`.
- Verify `Role` enum is exactly `ADMIN` and `EDITOR`.
- Verify the OpenAPI contract validation surface rejects a missing required article-create payload and invalid enum values once the schemas exist.
- Red evidence:
- Command: `/private/tmp/pupline-contract-venv/bin/python -m unittest apps/backend/tests/contracts/test_public_openapi_contract.py`
- Note: system Python did not have FastAPI installed; the red run used a temporary venv with `fastapi==0.115.6`. No Docker or HTTP server was used.
- Result: `FAILED (failures=1)`
- Failure summary:
- `components.schemas.ArticleCreateRequest is missing`
- `POST /api/articles must expose ArticleCreateRequest as its JSON request body; got no request body`
- `components.schemas.Role is missing`
- `components.schemas.ArticleWorkflowStatus is missing`
- Green evidence:
- Command: `/private/tmp/pupline-contract-venv/bin/python -m unittest apps/backend/tests/contracts/test_public_openapi_contract.py`
- Result: `OK`
- Command: `/private/tmp/pupline-contract-venv/bin/python -m unittest discover -s apps/backend/tests`
- Result: `Ran 6 tests in 0.015s` / `OK`
- Command: `/private/tmp/pupline-contract-venv/bin/python -m unittest discover -s apps/runner/tests`
- Result: `Ran 3 tests in 0.044s` / `OK`
- Refactor notes:
- Added backend domain contract package under `apps/backend/src/domain/contracts/` as the Pydantic source of truth.
- Added shared workflow transition constants in `apps/backend/src/domain/contracts/workflow.py`.
- Kept presentation thin: `POST /api/articles` imports domain request/response schemas and delegates deterministic placeholder response creation to application code.
- Added OpenAPI injection for canonical contract components so schemas not yet backed by business endpoints are still public in `/openapi.json`.
- Added runner job-output validation that loads backend contract models directly and does not import frontend code.
- Regression fix: runner Docker image now installs `apps/runner/requirements.txt` before copying source, so runner validation dependencies are present in the image.
- Regression fix: runner Docker image now bundles the backend contract package under `/app/backend_contracts/contracts`; the validator resolves that image path first, with monorepo fallback for local tests.
- Added a generated-artifact contract test to keep `packages/shared/openapi.json` in sync with backend OpenAPI.
- Replaced shared package exports with generated API types and wired frontend to import `ArticleListResponse` from `@pipeline/shared`.
- Regression fix: rewrote `apps/frontend/Dockerfile` to install from the repository root with pnpm workspace manifests, so Docker understands `@pipeline/shared: workspace:*`.
- Regression fix: pinned root `packageManager` to `pnpm@10.27.0`, copied `.npmrc` into the frontend image, and used `node:22-slim` plus linux SWC optional dependencies so Next does not try to download SWC at request time.
- Verification output:
- Command: `make contracts PYTHON=/private/tmp/pupline-contract-venv/bin/python`
- Result:
- `wrote /Users/gavrilovdev/tmp/pupline/packages/shared/openapi.json`
- `wrote /Users/gavrilovdev/tmp/pupline/packages/shared/src/api-types.ts`
- Command: `pnpm install`
- Result: `Done in 8.4s using pnpm v10.27.0`
- Command: `pnpm install --frozen-lockfile`
- Result: `Lockfile is up to date` / `Done in 13.3s using pnpm v10.27.0`
- Command: `pnpm typecheck`
- Result: `@pipeline/shared` and `@pipeline/frontend` `tsc --noEmit` completed successfully.
- Regression command: `bash tests/smoke/public-health.sh`
- Regression red result before fix:
- `npm error code EUNSUPPORTEDPROTOCOL`
- `Unsupported URL Type "workspace:": workspace:*`
- Regression green result after fix:
- `RUN pip install --no-cache-dir -r requirements.txt`
- `Successfully installed ... pydantic-2.13.4 ... pydantic-core-2.46.4`
- `RUN pnpm install --frozen-lockfile`
- `Done in 10.8s using pnpm v10.27.0`
- `pupline-frontend Built`
- `backend health ok`
- `runner health ok`
- `frontend health ok`
- `backend dependencies ok`
- `public health smoke ok`
- Runner image validation command: `docker compose run --rm runner python -c "from src.application.job_output_validation import validate_agent_job_output; result = validate_agent_job_output({'status':'SUCCEEDED'}); print(result.status.value)"`
- Runner image validation result: `SUCCEEDED`
- OpenAPI spot check:
- `POST /api/articles` request body is `#/components/schemas/ArticleCreateRequest`.
- `Role` enum is `['ADMIN', 'EDITOR']`.
- `ArticleWorkflowStatus` starts at `ARTICLE_BRIEF_CREATED` and ends at `PUBLISH_COMMIT_CREATED`.