feat(sessions): add SessionAdapter — REST CRUD for sessions/milestones/episodes (#50)
CI / CI (pull_request) Successful in 2m55s
CI / CI (pull_request) Successful in 2m55s
New internal/sessions package with Handler bridging 7 REST endpoints to: - POST /memory/ingest on poimen-memory:8080 (writes) - GraphQL hybridSearch/entity on poimen-graphql:8090 (reads) Adapter registration: X-Service: sessions with resources 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 (prevents key:value injection on user fields). Limit capped at 200. GraphQL error body detected and surfaced as 502. tracing.NewTransport wired for cross-service trace propagation. JWT forwarded to both upstreams for auth. 30 tests in handler_test.go covering all 7 handlers + EpisodeID helper. Closes #50
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
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"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user