Task 002: add shared domain contracts
This commit is contained in:
@@ -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`.
|
||||
|
||||
Reference in New Issue
Block a user