You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add service_agents endpoints for case contact-linking and notes, reusing
existing admin-only domain logic for the agent-facing surface.
- bin-openapi-manager: Add put: to service_agents/contact_cases/{id} for
contact attach/detach
- bin-openapi-manager: Add service_agents/contact_cases/{id}/notes and
.../notes/{note_id} paths (list/create/delete), POST body restricted to
text only (author derived server-side, never client-supplied)
- bin-api-manager: Add ServiceAgentCaseUpdateContact, mirroring admin
CaseUpdateContact with PermissionAll gate
- bin-api-manager: Add ServiceAgentCaseNoteList/Create/Delete; Create
derives author from the caller's own agent identity
(cmcasenote.AuthorTypeAgent + a.AgentID()); Delete restricts to the
note's own author via a list-then-match lookup (no single-note-get RPC
exists); both reject non-agent identities (accesskey/delegate/direct)
since AgentID() is meaningless for them
- bin-api-manager: Add PutServiceAgentsContactCasesId and
Get/Post/DeleteServiceAgentsContactCasesIdNotes* server handlers
- bin-api-manager: Add servicehandler and server-level tests covering
agent-permission success, tenant isolation, direct/accesskey rejection,
and note-ownership enforcement (author mismatch, nil author, not found)
Copy file name to clipboardExpand all lines: bin-api-manager/gens/openapi_redoc/openapi.json
+243Lines changed: 243 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -17949,6 +17949,182 @@
17949
17949
}
17950
17950
}
17951
17951
},
17952
+
"/service_agents/contact_cases/{id}/notes": {
17953
+
"get": {
17954
+
"summary": "List notes for a case",
17955
+
"description": "List all notes for the case of the given ID. Notes are an internal,\nagent-facing annotation on a Case and never appear in any\ncustomer-facing webhook or response.\n",
17956
+
"tags": [
17957
+
"Service Agent"
17958
+
],
17959
+
"parameters": [
17960
+
{
17961
+
"name": "id",
17962
+
"in": "path",
17963
+
"required": true,
17964
+
"schema": {
17965
+
"type": "string",
17966
+
"format": "uuid",
17967
+
"example": "550e8400-e29b-41d4-a716-446655440000"
17968
+
},
17969
+
"description": "The unique identifier of the case. Returned from the `GET /service_agents/contact_cases` response."
"description": "Create a new note on the case of the given ID, authored by the\ncalling agent. The author is derived server-side from the caller's\nown agent identity -- the request only carries the note text, so an\nagent can never author a note as another agent or as the system.\nNotes are an internal, agent-facing annotation on a Case and never\nappear in any customer-facing webhook or response.\n",
18003
+
"tags": [
18004
+
"Service Agent"
18005
+
],
18006
+
"parameters": [
18007
+
{
18008
+
"name": "id",
18009
+
"in": "path",
18010
+
"required": true,
18011
+
"schema": {
18012
+
"type": "string",
18013
+
"format": "uuid",
18014
+
"example": "550e8400-e29b-41d4-a716-446655440000"
18015
+
},
18016
+
"description": "The unique identifier of the case. Returned from the `GET /service_agents/contact_cases` response."
"description": "Delete the note of the given note ID on the case of the given case\nID. An agent may only delete a note it authored itself; notes\nauthored by another agent or by the system cannot be deleted\nthrough this endpoint.\n",
18072
+
"tags": [
18073
+
"Service Agent"
18074
+
],
18075
+
"parameters": [
18076
+
{
18077
+
"name": "id",
18078
+
"in": "path",
18079
+
"required": true,
18080
+
"schema": {
18081
+
"type": "string",
18082
+
"format": "uuid",
18083
+
"example": "550e8400-e29b-41d4-a716-446655440000"
18084
+
},
18085
+
"description": "The unique identifier of the case. Returned from the `GET /service_agents/contact_cases` response."
18086
+
},
18087
+
{
18088
+
"name": "note_id",
18089
+
"in": "path",
18090
+
"required": true,
18091
+
"schema": {
18092
+
"type": "string",
18093
+
"format": "uuid",
18094
+
"example": "33333333-0000-0000-0000-000000000003"
18095
+
},
18096
+
"description": "The unique identifier of the note. Returned from the `GET /service_agents/contact_cases/{id}/notes` response."
18097
+
}
18098
+
],
18099
+
"responses": {
18100
+
"200": {
18101
+
"description": "Case note deleted successfully.",
18102
+
"content": {
18103
+
"application/json": {
18104
+
"schema": {
18105
+
"type": "object"
18106
+
}
18107
+
}
18108
+
}
18109
+
},
18110
+
"400": {
18111
+
"$ref": "#/components/responses/BadRequest"
18112
+
},
18113
+
"401": {
18114
+
"$ref": "#/components/responses/Unauthenticated"
18115
+
},
18116
+
"403": {
18117
+
"$ref": "#/components/responses/PermissionDenied"
18118
+
},
18119
+
"404": {
18120
+
"$ref": "#/components/responses/NotFound"
18121
+
},
18122
+
"500": {
18123
+
"$ref": "#/components/responses/InternalError"
18124
+
}
18125
+
}
18126
+
}
18127
+
},
17952
18128
"/service_agents/contact_cases/{id}": {
17953
18129
"get": {
17954
18130
"summary": "Get detailed case info",
@@ -17996,6 +18172,73 @@
17996
18172
"$ref": "#/components/responses/InternalError"
17997
18173
}
17998
18174
}
18175
+
},
18176
+
"put": {
18177
+
"summary": "Attach or detach a case's contact",
18178
+
"description": "Attaches the case to a specific existing Contact, or detaches it,\nvia a direct contact_id write. Send a non-empty contact_id to\nattach; send an empty string to detach. The target contact_id must\nbelong to the same customer as the case; a cross-tenant contact_id\nis rejected as not found. Every attach/detach is recorded as a\ncase_contact_attributed/case_contact_detached event, queryable via\nbin-timeline-manager's audit log.\n",
18179
+
"tags": [
18180
+
"Service Agent"
18181
+
],
18182
+
"parameters": [
18183
+
{
18184
+
"name": "id",
18185
+
"in": "path",
18186
+
"required": true,
18187
+
"schema": {
18188
+
"type": "string",
18189
+
"format": "uuid",
18190
+
"example": "550e8400-e29b-41d4-a716-446655440000"
18191
+
},
18192
+
"description": "The unique identifier of the case. Returned from the `GET /service_agents/contact_cases` response."
18193
+
}
18194
+
],
18195
+
"requestBody": {
18196
+
"required": true,
18197
+
"content": {
18198
+
"application/json": {
18199
+
"schema": {
18200
+
"type": "object",
18201
+
"required": [
18202
+
"contact_id"
18203
+
],
18204
+
"properties": {
18205
+
"contact_id": {
18206
+
"type": "string",
18207
+
"description": "The contact to attach. Empty string detaches. Deliberately NOT format: uuid -- the internal RPC-layer uuid.UUID field cannot unmarshal a literal empty string, so this HTTP-layer field stays a plain string and the \"\" -> uuid.Nil conversion happens explicitly in the handler.",
18208
+
"example": "660e8400-e29b-41d4-a716-446655440001"
18209
+
}
18210
+
}
18211
+
}
18212
+
}
18213
+
}
18214
+
},
18215
+
"responses": {
18216
+
"200": {
18217
+
"description": "The case after the contact attach/detach.",
0 commit comments