운영 문서와 상태판 동기화
This commit is contained in:
parent
3a9f70a97b
commit
eb77d7ec7c
10 changed files with 369 additions and 145 deletions
|
|
@ -25,19 +25,53 @@ The first implementation boundary is the engine gateway contract:
|
|||
- `POST /v1/stream`
|
||||
- SSE events: `token`, `done`, `error`
|
||||
- request/response models owned by `apps/api/app/contracts/engine_gateway.py`
|
||||
- gateway SSE line parsing owned by `EngineGatewaySseLineDecoder` behind `EngineClient.stream_packets()`
|
||||
|
||||
Both the FastAPI engine client and the current Python engine gateway import this same contract. A future Node.js gateway must preserve these shapes.
|
||||
Both the FastAPI engine client and the current Python engine gateway import this same contract. The API orchestrator consumes decoded `EngineGatewaySsePacket` values from `EngineClient.stream_packets()` instead of hand-parsing `event:`/`data:` lines. The current Python gateway also returns `/v1/generate` through `GenerateResponse.model_dump()` rather than a hand-mirrored dict literal. A future Node.js gateway must preserve these shapes.
|
||||
|
||||
The cross-runtime golden fixture is `apps/api/engine_gateway/golden/engine_gateway_contract.v1.json`, backed by `apps/api/engine_gateway/golden/engine_gateway_schema.v1.json`.
|
||||
The fixture pins a representative `/v1/generate` request/response, stream `token/done/error` frames, decoded packet payloads, and the provider `[DONE]` compatibility line. The schema artifact pins the same request/response/event shapes without requiring Python imports. The Python contract test validates that the schema artifact matches the current Pydantic contract and that the fixture passes both JSON Schema and the runtime SSE decoder. `scripts/check-engine-gateway-contract.mjs` reads the same artifacts from Node.js, decodes the SSE frames, ignores provider `[DONE]` compatibility lines, and proves packet-level equivalence without importing Python code. A future Node.js gateway should keep this runner green and then add live endpoint conformance on top of it.
|
||||
|
||||
For `/v1/stream`, gateway-to-API SSE frames are:
|
||||
|
||||
- `event: token` with `data: {"text": "..."}`
|
||||
- `event: done` with `data: {"provider": "...", "model": "...", "tokens_in": 0, "tokens_out": 0, "cost_usd": 0.0, "turns": 0}`
|
||||
- `event: error` with `data: {"detail": "..."}`
|
||||
|
||||
Provider pass-through sentinels such as `data: [DONE]` are ignored compatibility lines, not completion packets. A Node.js gateway must translate provider completion into the explicit `event: done` JSON frame above.
|
||||
|
||||
## Invariants
|
||||
|
||||
- `/personas` normal state remains `source:"database", degraded:false`; `seed_fallback` is not normal.
|
||||
- Browser credentials and BFF session behavior stay unchanged.
|
||||
- Browser-facing `/sessions/{id}/stream` SSE stays a separate app contract; the engine gateway stream uses JSON token payloads.
|
||||
- Browser-facing session list/dashboard/detail/review/share response DTOs stay stable across the Python route and any future Node read API.
|
||||
- RBAC, RLS, audit logging, and PII masking stay fail-closed.
|
||||
- OpenAPI generated frontend contracts stay current.
|
||||
- Existing ports and local/prod startup paths stay compatible until a service is deliberately replaced.
|
||||
|
||||
## Second Boundary
|
||||
|
||||
The second internal boundary is the browser-facing session read model.
|
||||
|
||||
`apps/api/app/session_read_model.py` now owns the session list, learner dashboard, session detail, session review, worksheet, teacher-review status, and share payload DTOs plus deterministic builders. `apps/api/app/routes/sessions.py` keeps route decorators, auth/role checks, consent/onboarding gates, RLS-backed persistence reads, mutations, streaming, and session lifecycle behavior.
|
||||
|
||||
This preserves the current FastAPI delivery path while making a future Node.js read API mirror one module's browser contract instead of re-deriving response shapes from mixed route code. Hidden/evaluator-only turn filtering, saved worksheet precedence, teacher read-only review status, and public share sanitization remain invariants.
|
||||
|
||||
## Evidence
|
||||
|
||||
- `python -B -m py_compile app/contracts/engine_gateway.py app/engine_client.py app/services/orchestrator.py engine_gateway/gateway.py engine_gateway/test_gateway_model.py app/test_orchestrator_masking.py app/test_session_turn_persistence.py`
|
||||
- `node scripts/check-engine-gateway-contract.mjs --json`
|
||||
- `python -B -m pytest -p no:cacheprovider engine_gateway/test_gateway_model.py -q` — 19 passed
|
||||
- `python -B -m pytest -p no:cacheprovider engine_gateway/test_gateway_model.py app/test_orchestrator_masking.py app/test_session_turn_persistence.py -q` — 50 passed
|
||||
- `apps/api/engine_gateway/golden/engine_gateway_contract.v1.json` and `apps/api/engine_gateway/golden/engine_gateway_schema.v1.json` validated by `engine_gateway/test_gateway_model.py`
|
||||
- `python -B -m py_compile app/session_read_model.py app/routes/sessions.py`
|
||||
- `python -B -m pytest -p no:cacheprovider app/test_session_turn_persistence.py app/test_evaluation_persistence.py app/test_session_share.py app/test_learner_dashboard.py app/test_rbac_idor.py app/test_teacher_dashboard.py -q` — 48 passed
|
||||
- `npm run check:api-types`
|
||||
- `npm run typecheck`
|
||||
|
||||
## Next Refactor Candidates
|
||||
|
||||
1. Split persona HTTP DTOs and mappers from `routes/personas.py` while preserving OpenAPI schema names.
|
||||
2. Split learner/review session read-model assembly from `routes/sessions.py`.
|
||||
1. Add live Node.js gateway endpoint conformance once a Node gateway implementation exists; the artifact runner is now in place.
|
||||
2. Split persona HTTP DTOs and mappers from `routes/personas.py` while preserving OpenAPI schema names.
|
||||
3. Leave `admin.py` mapper cleanup for later because RBAC, audit, and RLS blast radius is larger.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue