first commit

This commit is contained in:
npc0-hue
2026-07-11 14:56:10 +08:00
commit 7e05d0a4e7
660 changed files with 78119 additions and 0 deletions
@@ -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?