Context
Nest already exposes JWT-protected chat endpoints:
GET /v1/agreements/:agreementId/messages
POST /v1/agreements/:agreementId/messages
Frontend will be wired to these in a companion FE issue. Before that can work in production, the backend schema and create-agreement path must support real A↔B chat.
Problem
AgreementChatService inserts sender_id, but the FE SQL schema for agreement_messages (004-contacts-and-chat.sql) has no sender_id column → Nest insert will fail against current DB.
- On agreement create, if
agreement_participants insert fails, we only console.error and continue → counterparty cannot access the agreement or chat (Not a participant).
Scope (keep tight)
Out of scope
- Frontend wiring (separate FE issue)
- Realtime / WebSockets
- Rate limiting / MaxLength (nice-to-have later)
- Multi-wallet identity alignment (
user_wallets vs auth_users.wallet_public_key)
Acceptance criteria
- Applying the migration allows Nest to insert a message with
sender_id + sender_wallet.
- Creating an agreement always creates participant rows for both parties, or the create request fails.
- Only JWT users who are creator/participant can
GET/POST messages.
- Manual check: User A creates agreement with User B’s wallet → B can list messages (empty) and A can send one → B sees it.
Related
- Companion FE issue: wire AgreementChat to Nest + persist UUID (link after creation)
- Existing Nest module:
src/agreement-chat/
DoD
- PR on
main with migration + create harden
- Short proof in PR (SQL applied + curl/Postman or integration test for messages)
Closes #NN
Context
Nest already exposes JWT-protected chat endpoints:
GET /v1/agreements/:agreementId/messagesPOST /v1/agreements/:agreementId/messagesFrontend will be wired to these in a companion FE issue. Before that can work in production, the backend schema and create-agreement path must support real A↔B chat.
Problem
AgreementChatServiceinsertssender_id, but the FE SQL schema foragreement_messages(004-contacts-and-chat.sql) has nosender_idcolumn → Nest insert will fail against current DB.agreement_participantsinsert fails, we onlyconsole.errorand continue → counterparty cannot access the agreement or chat (Not a participant).Scope (keep tight)
agreement_messages.sender_id(UUID, preferably FK/auth_users.id; backfill nullable OK for old rows).scripts/(schema should live with the API that writes it).200 + { error }).Out of scope
user_walletsvsauth_users.wallet_public_key)Acceptance criteria
sender_id+sender_wallet.GET/POSTmessages.Related
src/agreement-chat/DoD
mainwith migration + create hardenCloses #NN