diff --git a/docs/openapi-tess.yaml b/docs/openapi-tess.yaml new file mode 100644 index 0000000..c348a69 --- /dev/null +++ b/docs/openapi-tess.yaml @@ -0,0 +1,389 @@ +openapi: 3.1.0 +info: { title: Mosaic Tess Gateway, version: 1.0.0 } +security: [{ sessionAuth: [] }] +paths: + /api/interaction/{agentName}/sessions: + { + get: + { + summary: List authorized runtime sessions, + parameters: + [ + { $ref: '#/components/parameters/agentName' }, + { $ref: '#/components/parameters/provider' }, + { $ref: '#/components/parameters/correlation' }, + ], + responses: { '200': { description: Sessions } }, + }, + } + /api/interaction/{agentName}/transitional-capabilities: + { + get: + { + summary: Get transitional capability matrix, + parameters: + [ + { $ref: '#/components/parameters/agentName' }, + { $ref: '#/components/parameters/provider' }, + { $ref: '#/components/parameters/correlation' }, + ], + responses: { '200': { description: Matrix } }, + }, + } + /api/interaction/{agentName}/tree: + { + get: + { + summary: Get authorized session tree, + parameters: + [ + { $ref: '#/components/parameters/agentName' }, + { $ref: '#/components/parameters/provider' }, + { $ref: '#/components/parameters/correlation' }, + ], + responses: { '200': { description: Tree } }, + }, + } + /api/interaction/{agentName}/sessions/{sessionId}/enroll: + { + post: + { + summary: Enroll a durable session, + parameters: + [ + { $ref: '#/components/parameters/agentName' }, + { $ref: '#/components/parameters/sessionId' }, + { $ref: '#/components/parameters/correlation' }, + ], + requestBody: { $ref: '#/components/requestBodies/Enroll' }, + responses: { '200': { description: Enrolled } }, + }, + } + /api/interaction/{agentName}/sessions/{sessionId}/attach: + { + post: + { + summary: Attach to a runtime session, + parameters: + [ + { $ref: '#/components/parameters/agentName' }, + { $ref: '#/components/parameters/sessionId' }, + { $ref: '#/components/parameters/correlation' }, + ], + requestBody: { $ref: '#/components/requestBodies/Attach' }, + responses: { '200': { description: Attachment } }, + }, + } + /api/interaction/{agentName}/sessions/{sessionId}/send: + { + post: + { + summary: Queue a durable provider send, + parameters: + [ + { $ref: '#/components/parameters/agentName' }, + { $ref: '#/components/parameters/sessionId' }, + { $ref: '#/components/parameters/correlation' }, + ], + requestBody: { $ref: '#/components/requestBodies/Send' }, + responses: { '200': { description: Queued } }, + }, + } + /api/interaction/{agentName}/sessions/{sessionId}/stop: + { + post: + { + summary: Stop a session with approval, + parameters: + [ + { $ref: '#/components/parameters/agentName' }, + { $ref: '#/components/parameters/sessionId' }, + { $ref: '#/components/parameters/correlation' }, + ], + requestBody: { $ref: '#/components/requestBodies/Stop' }, + responses: { '200': { description: Stopped }, '403': { description: Approval denied } }, + }, + } + /api/interaction/{agentName}/sessions/{sessionId}/recover: + { + post: + { + summary: Recover interrupted durable work, + parameters: + [ + { $ref: '#/components/parameters/agentName' }, + { $ref: '#/components/parameters/sessionId' }, + { $ref: '#/components/parameters/correlation' }, + ], + responses: { '200': { description: Recovered } }, + }, + } + /api/coord/mos/handoff: + { + post: + { + summary: Submit Mos handoff, + parameters: [{ $ref: '#/components/parameters/correlation' }], + requestBody: { $ref: '#/components/requestBodies/MosHandoff' }, + responses: { '200': { description: Receipt } }, + }, + } + /api/coord/mos/{handoffId}/observe: + { + get: + { + summary: Observe Mos handoff, + parameters: + [ + { $ref: '#/components/parameters/handoffId' }, + { $ref: '#/components/parameters/correlation' }, + ], + responses: { '200': { description: Observation } }, + }, + } + /api/coord/mos/{handoffId}/result: + { + get: + { + summary: Get Mos handoff result, + parameters: + [ + { $ref: '#/components/parameters/handoffId' }, + { $ref: '#/components/parameters/correlation' }, + ], + responses: { '200': { description: Result } }, + }, + } + /api/interaction/{agentName}/sessions/{sessionId}/stream: + { + get: + { + summary: Stream runtime events, + parameters: + [ + { $ref: '#/components/parameters/agentName' }, + { $ref: '#/components/parameters/sessionId' }, + { $ref: '#/components/parameters/correlation' }, + ], + responses: + { + '200': + { + description: Event stream, + content: { text/event-stream: { schema: { type: string } } }, + }, + }, + }, + } + /api/memory/preferences: + { + get: { summary: List preferences, responses: { '200': { description: Preferences } } }, + post: + { + summary: Upsert preference, + requestBody: { $ref: '#/components/requestBodies/Preference' }, + responses: { '200': { description: Preference } }, + }, + } + /api/memory/preferences/{key}: + { + get: + { + summary: Get preference, + parameters: [{ $ref: '#/components/parameters/key' }], + responses: { '200': { description: Preference } }, + }, + delete: + { + summary: Delete preference, + parameters: [{ $ref: '#/components/parameters/key' }], + responses: { '204': { description: Deleted } }, + }, + } + /api/memory/insights: + { + get: { summary: List insights, responses: { '200': { description: Insights } } }, + post: + { + summary: Create insight, + requestBody: { $ref: '#/components/requestBodies/Insight' }, + responses: { '200': { description: Insight } }, + }, + } + /api/memory/insights/{id}: + { + get: + { + summary: Get insight, + parameters: [{ $ref: '#/components/parameters/id' }], + responses: { '200': { description: Insight } }, + }, + delete: + { + summary: Delete insight, + parameters: [{ $ref: '#/components/parameters/id' }], + responses: { '204': { description: Deleted } }, + }, + } + /api/memory/search: + { + post: + { + summary: Search memory, + requestBody: { $ref: '#/components/requestBodies/Search' }, + responses: { '200': { description: Search results } }, + }, + } +components: + securitySchemes: { sessionAuth: { type: http, scheme: bearer } } + parameters: + agentName: { name: agentName, in: path, required: true, schema: { type: string } } + sessionId: { name: sessionId, in: path, required: true, schema: { type: string } } + provider: { name: provider, in: query, required: true, schema: { type: string } } + correlation: { name: X-Correlation-Id, in: header, required: true, schema: { type: string } } + key: { name: key, in: path, required: true, schema: { type: string } } + id: { name: id, in: path, required: true, schema: { type: string } } + requestBodies: + Enroll: + { + required: true, + content: + { + application/json: + { + schema: + { + type: object, + required: [providerId, runtimeSessionId], + properties: + { providerId: { type: string }, runtimeSessionId: { type: string } }, + }, + }, + }, + } + MosHandoff: + { + required: true, + content: + { + application/json: + { + schema: + { + type: object, + required: [idempotencyKey, summary], + properties: + { + idempotencyKey: { type: string }, + summary: { type: string }, + context: { type: string }, + missionId: { type: string }, + }, + }, + }, + }, + } + Attach: + { + content: + { + application/json: { schema: { type: object, properties: { mode: { enum: [read] } } } }, + }, + } + Send: + { + required: true, + content: + { + application/json: + { + schema: + { + type: object, + required: [content, idempotencyKey], + properties: { content: { type: string }, idempotencyKey: { type: string } }, + }, + }, + }, + } + Stop: + { + required: true, + content: + { + application/json: + { + schema: + { + type: object, + required: [approvalRef], + properties: { approvalRef: { type: string } }, + }, + }, + }, + } + Preference: + { + required: true, + content: + { + application/json: + { + schema: + { + type: object, + required: [key, value], + properties: + { + key: { type: string }, + value: {}, + category: { type: string }, + source: { type: string }, + }, + }, + }, + }, + } + Insight: + { + required: true, + content: + { + application/json: + { + schema: + { + type: object, + required: [content], + properties: + { + content: { type: string }, + source: { type: string }, + category: { type: string }, + metadata: { type: object }, + }, + }, + }, + }, + } + Search: + { + required: true, + content: + { + application/json: + { + schema: + { + type: object, + required: [query], + properties: + { + query: { type: string }, + limit: { type: integer }, + maxDistance: { type: number }, + }, + }, + }, + }, + } diff --git a/docs/tess/ADMIN-GUIDE.md b/docs/tess/ADMIN-GUIDE.md new file mode 100644 index 0000000..03b78c3 --- /dev/null +++ b/docs/tess/ADMIN-GUIDE.md @@ -0,0 +1,5 @@ +# Tess Administration + +Configure agent/provider identities outside client input. Verify `/health/ready` and provider health before enabling interaction clients. Every interaction request requires an authenticated actor and correlation header; tenant and owner scope are server-derived. Do not log or return service credentials. + +For an incident, preserve correlation IDs, inspect provider status and durable checkpoint/inbox/outbox state, then use the recovery endpoint. Do not retry an ambiguous external effect automatically. Stop operations require an exact one-time approval reference; provisioning or granting a broad admin capability does not replace that check. diff --git a/docs/tess/DEVELOPER-GUIDE.md b/docs/tess/DEVELOPER-GUIDE.md new file mode 100644 index 0000000..dfd534a --- /dev/null +++ b/docs/tess/DEVELOPER-GUIDE.md @@ -0,0 +1,3 @@ +# Tess Developer Guide + +Interaction adapters pass only server-derived actor/tenant scope, channel, and correlation to runtime providers. Durable session state owns inbox/outbox/checkpoint recovery. Use the OpenAPI contract rather than inventing routes; unsupported provider capabilities fail closed. diff --git a/docs/tess/M5-003-DOCUMENTATION-CHECKLIST.md b/docs/tess/M5-003-DOCUMENTATION-CHECKLIST.md new file mode 100644 index 0000000..5622d0a --- /dev/null +++ b/docs/tess/M5-003-DOCUMENTATION-CHECKLIST.md @@ -0,0 +1,8 @@ +# TESS-M5-003 Documentation Checklist + +- [x] `openapi-tess.yaml`: authenticated interaction endpoints including SSE stream, Mos handoff/observe/result, and memory preferences, insights, and search. +- [x] User guide: authorized session and handoff workflows. +- [x] Admin guide: provisioning, policy, health, and approval boundary. +- [x] Developer guide: scope, durable state, and provider adapter contract. +- [x] Plugin guide: replaceable-adapter, redaction, and identity-as-data rules. +- [x] Operations guide: readiness, recovery, ambiguous-effect safety, and tracing. diff --git a/docs/tess/OPERATIONS-GUIDE.md b/docs/tess/OPERATIONS-GUIDE.md new file mode 100644 index 0000000..e0a262e --- /dev/null +++ b/docs/tess/OPERATIONS-GUIDE.md @@ -0,0 +1,3 @@ +# Tess Operations and Recovery + +Check `/health/ready`, provider health, and effective policy before recovery. Recover durable sessions through the interaction recovery operation; it requeues only interrupted work and does not replay ambiguous external effects. Preserve correlation IDs for incident tracing and use Mos handoff observation/result endpoints for orchestration visibility. diff --git a/docs/tess/PLUGIN-GUIDE.md b/docs/tess/PLUGIN-GUIDE.md new file mode 100644 index 0000000..4d40348 --- /dev/null +++ b/docs/tess/PLUGIN-GUIDE.md @@ -0,0 +1,3 @@ +# Tess Plugin Authoring + +Plugins are replaceable adapters. Declare capabilities, derive scope from trusted context, preserve correlation IDs, redact before persistence/egress, and return unsupported operations as fail-closed results. Names and identities are configuration data, not literals in keys or defaults. diff --git a/docs/tess/USER-GUIDE.md b/docs/tess/USER-GUIDE.md new file mode 100644 index 0000000..90a85f1 --- /dev/null +++ b/docs/tess/USER-GUIDE.md @@ -0,0 +1,5 @@ +# Tess User Guide + +All HTTP interaction calls require authenticated session credentials and `X-Correlation-Id`. Use `GET /api/interaction/{agentName}/sessions?provider=...` to list only visible runtime sessions, then enroll with `POST .../sessions/{sessionId}/enroll` body `{providerId,runtimeSessionId}`. Attach uses `{mode:"read"}`; send uses `{content,idempotencyKey}`. Stop requires `{approvalRef}` and fails with 403 without the exact durable approval. Recovery only requeues interrupted durable work. + +Memory is user-scoped: preferences support list/get/upsert/delete; insights support list/get/create/delete; search body is `{query,limit?,maxDistance?}`. Mos work is handed off with `POST /api/coord/mos/handoff`; observe and result use the returned handoff ID.