first commit
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
## Context
|
||||
|
||||
`platform/` already contains typed domain resources, DTO contracts, model projections, validators, repositories, and `service.Core` workflows for the first platform resources. The current executable only exposes `/healthz`, so frontend, run, and plugin changes cannot yet rely on HTTP behavior for users, game plugins, server instances, AI providers, run endpoints, jobs, artifacts, log streams, or audit events.
|
||||
|
||||
This change stays inside `platform/` and implements the first HTTP adapter layer over the existing core service. It must preserve the repository structure rules: handlers belong in `api/`, request/response DTOs in `dto/`, domain rules in `domain/` and `validator/`, and storage concerns in `repo/` or future persistence packages.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- Expose create, list, and detail HTTP routes for core platform resources.
|
||||
- Keep handlers as adapters that decode named DTOs, call `service.Core`, and encode named DTO responses.
|
||||
- Return deterministic JSON error responses for malformed JSON, validation failures, duplicate IDs, missing resources, and unexpected failures.
|
||||
- Preserve AI provider redaction by returning `apiKeyRef` only and never raw API key material.
|
||||
- Make router construction injectable for tests and future persistence while retaining an in-memory default for local development.
|
||||
- Update `platform/api/routes.md` to reflect implemented routes.
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- No authentication, session, RBAC, or authorization engine.
|
||||
- No SQL database, migrations, or external persistence dependency.
|
||||
- No frontend or run-side implementation.
|
||||
- No run job claim/ack/result protocol implementation beyond platform-side job resource creation and query.
|
||||
- No plugin page bridge implementation, AI invocation endpoint, file content transfer, log body ingest, or artifact chunk transfer.
|
||||
- No billing, cloud host sales, agent-provider/cloud-provider workflows, or unrelated SaaS marketplace features.
|
||||
|
||||
## Decisions
|
||||
|
||||
### Decision 1: Use `net/http` ServeMux with explicit method dispatch
|
||||
|
||||
The platform will keep using the Go standard library. Route wiring will use `http.ServeMux` path patterns, `PathValue` for detail routes, and explicit method dispatch inside resource handlers so unsupported methods can return the named JSON error DTO.
|
||||
|
||||
Alternative considered: adding a third-party router. Rejected because the API surface is still small and the current module has no external runtime dependencies.
|
||||
|
||||
### Decision 2: Router accepts `service.Core`
|
||||
|
||||
`api.NewRouter()` will build the current in-memory service for local execution, while `api.NewRouterWithCore(core service.Core)` will allow tests and later persistence changes to provide a service implementation.
|
||||
|
||||
Alternative considered: constructing repositories directly inside every handler. Rejected because it hides storage choices in transport code and bypasses the service layer that already owns cross-resource invariants.
|
||||
|
||||
### Decision 3: DTO package owns request conversion and API envelopes
|
||||
|
||||
Create-request DTOs will expose `ToDomain()` helpers. Response DTOs and list/error envelopes will remain named structs under `platform/dto` so handlers do not define request/response shapes inline.
|
||||
|
||||
Alternative considered: constructing ad hoc response maps in handlers. Rejected because API contracts must remain discoverable and testable.
|
||||
|
||||
### Decision 4: Handlers map service errors to stable HTTP errors
|
||||
|
||||
Handlers will translate `validator.ValidationError` to `400`, malformed JSON to `400`, `repo.ErrNotFound` to `404`, `repo.ErrDuplicate` to `409`, and unexpected errors to `500`. All errors will use `dto.ErrorResponse`.
|
||||
|
||||
Alternative considered: returning plain-text `http.Error`. Rejected because clients need predictable JSON responses and AGENTS.md requires named error DTOs.
|
||||
|
||||
### Decision 5: Implement metadata routes only for logs and artifacts
|
||||
|
||||
This change implements log stream metadata and artifact metadata resources. Chunk upload/download, durable log ingest, tail transport, and storage adapters remain future changes because they affect run communication channels and transfer backpressure.
|
||||
|
||||
Alternative considered: implementing chunk and ingest endpoints now. Rejected because the delivery stream has separate changes for run channels, logs, and artifacts.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [Risk] In-memory default storage loses data on restart. Mitigation: document it as local development wiring and keep router injection ready for future persistence.
|
||||
- [Risk] Create/list/get routes are narrower than the full route catalog. Mitigation: document deferred lifecycle, chunk, ingest, and plugin bridge behavior explicitly in `platform/api/routes.md`.
|
||||
- [Risk] Query filter values are string-based and rely on domain enum strings. Mitigation: keep filters narrow and let create/update validation remain in the service and validator layers.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. Add DTO conversion helpers, list envelopes, and error DTOs.
|
||||
2. Add API router wiring and handlers over `service.Core`.
|
||||
3. Update route catalog documentation.
|
||||
4. Add focused handler tests for route behavior, validation/error mapping, and AI provider redaction.
|
||||
5. Verify with `go test ./...` from `platform/`, `scripts/check-structure.sh`, and strict OpenSpec validation.
|
||||
|
||||
Rollback before dependent changes is removal of the API handler additions and this OpenSpec change. After frontend, run, or plugin changes consume these routes, rollback must be handled through a new OpenSpec change.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- Which authentication/session mechanism will wrap these routes first?
|
||||
- Which persistent repository implementation should replace the in-memory default?
|
||||
- Which API pagination and sorting contract should be introduced once lists can grow beyond development-scale data?
|
||||
Reference in New Issue
Block a user