## Context PRD: [`docs/PRD.md`](../blob/main/docs/PRD.md) §§6.4, 7 (messages). Milestone **M1**. Parent slices: [`docs/ISSUES.md`](../blob/main/docs/ISSUES.md) #5. ## Goal Append-only messages under a thread; list/page with stable ordering; tenant-scoped. ## Out of scope - Job claim, attach/remote-control - Real-time push (notify plane) - Full-text search ## Prerequisites - Sessions HTTP issue (server + Store wiring) - Key helpers for message paths ## API | Method | Path | Behavior | |--------|------|----------| | POST | `/v1/orgs/{org}/projects/{project}/threads/{thread_id}/messages` | Append message; server assigns `id` + timestamps; returns 201 + body | | GET | `/v1/orgs/{org}/projects/{project}/threads/{thread_id}/messages` | List messages in stable order (ascending `created_at` then `id`); support simple `limit` + `cursor` or `after_id` | Message fields: `id`, `thread_id`, `sender_actor_id`, `role` (`user`\|`assistant`\|`system`\|`tool`\|`agent`), `content`, `refs` (optional), `created_at`. Storage: one object per message key from helpers (not a single giant JSON array). ## Acceptance criteria - [ ] POST appends without CAS races clobbering other messages - [ ] GET returns deterministic order - [ ] Listing never returns messages from another org/project/thread - [ ] Invalid role → 400 - [ ] `make check` green ## Required tests 1. POST two messages → GET returns both in order 2. Cross-tenant/thread isolation (different project keys invisible) 3. Pagination cursor behavior if implemented (empty page at end) ## Makefile / gate Unchanged `make check`. ## Dependencies Blocked on HTTP sessions issue. ## How to hand to Aixgo Code Apply **`ax:go`** after sessions API merged.
Activity