CI / CI (push) Successful in 3m15s
Closes #50 ## Changes - `internal/sessions/handler.go` — new Handler; 7 endpoints dispatched via `X-Upstream-Path`; writes to `poimen-memory` via `/memory/ingest`; reads from `poimen-graphql` via GraphQL `hybridSearch`/`entity` - `internal/serviceadapter/session_adapter.go` — `NewSessionAdapter()` + `GetSessionSpec()` with 5 resources - `cmd/gateway/main.go` — register sessions adapter after memory adapter - `internal/serviceadapter/adapters.go` — add `sessions` case to factory - `internal/sessions/handler_test.go` — 30 tests, all pass ## Design - `X-Service: sessions` + `X-Resource: <sessions|session|milestones|episodes|episode>` - IDs via query params (`?session_id=`, `?episode_id=`) — dispatcher does not substitute path params - `episode_id = sha256(session_id+milestone_id+attempt)` per §4.14 Q6 - Content JSON-encoded (injection-safe) - `tracing.NewTransport` wired for cross-service trace propagation - GraphQL `errors` array detected, surfaced as 502 - limit capped at 200 --------- Co-authored-by: Admin Bot <[email protected]> Reviewed-on: #51
108 lines
3.1 KiB
Go
108 lines
3.1 KiB
Go
package serviceadapter
|
|
|
|
import (
|
|
"forgejo.riotpiao.com/rock/homelab-frontend/internal/sessions"
|
|
)
|
|
|
|
// NewSessionAdapter creates a ServiceAdapter for the sessions service.
|
|
//
|
|
// Route mapping (all via X-Service: sessions):
|
|
//
|
|
// X-Resource Verb upstream path handler
|
|
// ──────────────────────────────────────────────────────────────
|
|
// sessions POST /v1/sessions/create create session
|
|
// sessions GET /v1/sessions/list list sessions (?status=,?cwd=)
|
|
// session GET /v1/sessions/get get session (?session_id=)
|
|
// session PATCH /v1/sessions/patch update session(?session_id=)
|
|
// milestones POST /v1/sessions/milestones/create create milestone(?session_id=)
|
|
// episodes GET /v1/sessions/episodes/list list episodes (?session_id=)
|
|
// episode GET /v1/sessions/episodes/get get episode (?session_id=,?episode_id=)
|
|
//
|
|
// Path params (:id, :eid) are passed as query params because the ServiceAdapter
|
|
// dispatcher does not substitute URL path parameters.
|
|
func NewSessionAdapter() *ServiceAdapter {
|
|
return &ServiceAdapter{
|
|
Namespace: "poimen",
|
|
ServiceName: "sessions",
|
|
Handler: sessions.NewHandler(),
|
|
Spec: *GetSessionSpec(),
|
|
}
|
|
}
|
|
|
|
// GetSessionSpec returns the ServiceAdapter spec for the sessions service.
|
|
func GetSessionSpec() *Spec {
|
|
return &Spec{
|
|
ServiceName: "sessions",
|
|
Upstream: Upstream{
|
|
URL: "internal://sessions",
|
|
TimeoutSeconds: 30,
|
|
},
|
|
Auth: Auth{
|
|
Required: true,
|
|
Capability: "sessions:read",
|
|
},
|
|
Resources: []Resource{
|
|
{
|
|
Name: "sessions",
|
|
Methods: []Method{
|
|
{
|
|
Verb: "POST",
|
|
UpstreamPath: "/v1/sessions/create",
|
|
Auth: &Auth{Required: true, Capability: "sessions:write"},
|
|
},
|
|
{
|
|
Verb: "GET",
|
|
UpstreamPath: "/v1/sessions/list",
|
|
Auth: &Auth{Required: true, Capability: "sessions:read"},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "session",
|
|
Methods: []Method{
|
|
{
|
|
Verb: "GET",
|
|
UpstreamPath: "/v1/sessions/get",
|
|
Auth: &Auth{Required: true, Capability: "sessions:read"},
|
|
},
|
|
{
|
|
Verb: "PATCH",
|
|
UpstreamPath: "/v1/sessions/patch",
|
|
Auth: &Auth{Required: true, Capability: "sessions:write"},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "milestones",
|
|
Methods: []Method{
|
|
{
|
|
Verb: "POST",
|
|
UpstreamPath: "/v1/sessions/milestones/create",
|
|
Auth: &Auth{Required: true, Capability: "sessions:write"},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "episodes",
|
|
Methods: []Method{
|
|
{
|
|
Verb: "GET",
|
|
UpstreamPath: "/v1/sessions/episodes/list",
|
|
Auth: &Auth{Required: true, Capability: "sessions:read"},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "episode",
|
|
Methods: []Method{
|
|
{
|
|
Verb: "GET",
|
|
UpstreamPath: "/v1/sessions/episodes/get",
|
|
Auth: &Auth{Required: true, Capability: "sessions:read"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
}
|