From 880b8f001604aeea1746f7c0d45c5b2e422ea731 Mon Sep 17 00:00:00 2001 From: Somnath Mirdha Date: Sat, 10 Oct 2026 00:47:03 +0530 Subject: [PATCH] signals: add source to consent records and team-level inference consent PUT Consent-gateway is now source-aware (cthulhu #179994/#179995/#179996): rows are keyed by (team_id, source, agent_id). Agent rows (source=agent) are unchanged; Serverless Inference consent is a single team-level row (source=inference, agent_id=""). - New PUT /v1/consent?source=inference {enabled} (signals_update_team_consent) to grant or revoke team-level inference consent. - GET /v1/consent accepts ?source=agent|inference and echoes source when filtered; consent records now include source. - agent_id is no longer format: uuid on consent_record (empty for team-level rows); per-agent endpoints document 400 for ?source=inference. - Signals tag description mentions both consent sources. --- specification/DigitalOcean-public.v2.yaml | 13 ++-- .../curl/signals_update_team_consent.yml | 7 +++ .../signals/models/agent_consent.yml | 9 +++ .../signals/models/consent_record.yml | 24 ++++++-- .../signals/models/list_consents.yml | 14 ++++- .../resources/signals/parameters.yml | 31 ++++++++++ .../responses/agent_consent_response.yml | 1 + .../responses/list_consents_response.yml | 8 +++ .../responses/update_consent_response.yml | 1 + .../update_team_consent_response.yml | 27 ++++++++ .../resources/signals/signals_get_consent.yml | 6 ++ .../signals/signals_list_consents.yml | 13 +++- .../signals/signals_update_consent.yml | 7 +++ .../signals/signals_update_team_consent.yml | 61 +++++++++++++++++++ 14 files changed, 212 insertions(+), 10 deletions(-) create mode 100644 specification/resources/signals/examples/curl/signals_update_team_consent.yml create mode 100644 specification/resources/signals/responses/update_team_consent_response.yml create mode 100644 specification/resources/signals/signals_update_team_consent.yml diff --git a/specification/DigitalOcean-public.v2.yaml b/specification/DigitalOcean-public.v2.yaml index 64304d0db..ca1d5dca8 100644 --- a/specification/DigitalOcean-public.v2.yaml +++ b/specification/DigitalOcean-public.v2.yaml @@ -600,10 +600,12 @@ tags: user disengagement, execution failures, and satisfaction indicators. Use the consent endpoints to manage whether signals collection is - enabled for each agent, the session endpoints to browse agent - conversations and their detected signals, the export endpoints - to create downloadable archives of signals data for offline analysis, - and the deletion endpoints to permanently delete signals data. + enabled — per agent for Harness Runtime (`source=agent`) and per team + for Serverless Inference chat completions (`source=inference`) — the + session endpoints to browse agent conversations and their detected + signals, the export endpoints to create downloadable archives of + signals data for offline analysis, and the deletion endpoints to + permanently delete signals data. - name: Sizes description: |- @@ -1873,6 +1875,9 @@ paths: get: $ref: "resources/signals/signals_list_consents.yml" + put: + $ref: "resources/signals/signals_update_team_consent.yml" + /v1/consent/{agent_id}: get: $ref: "resources/signals/signals_get_consent.yml" diff --git a/specification/resources/signals/examples/curl/signals_update_team_consent.yml b/specification/resources/signals/examples/curl/signals_update_team_consent.yml new file mode 100644 index 000000000..9c4afa7ac --- /dev/null +++ b/specification/resources/signals/examples/curl/signals_update_team_consent.yml @@ -0,0 +1,7 @@ +lang: cURL +source: |- + curl -X PUT \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \ + -d '{"enabled":true}' \ + "https://api.digitalocean.com/v1/consent?source=inference" diff --git a/specification/resources/signals/models/agent_consent.yml b/specification/resources/signals/models/agent_consent.yml index 2ef9f9365..73783714f 100644 --- a/specification/resources/signals/models/agent_consent.yml +++ b/specification/resources/signals/models/agent_consent.yml @@ -9,6 +9,14 @@ properties: type: integer description: The team ID that owns this consent record. example: 39449946 + source: + type: string + enum: + - agent + description: >- + The source this consent applies to. Always `agent` for per-agent + records returned by this endpoint. + example: agent agent_id: type: string format: uuid @@ -25,5 +33,6 @@ properties: example: "2026-08-10T10:09:25.738533Z" required: - team_id + - source - agent_id - enabled diff --git a/specification/resources/signals/models/consent_record.yml b/specification/resources/signals/models/consent_record.yml index 656c43297..14c8fc13d 100644 --- a/specification/resources/signals/models/consent_record.yml +++ b/specification/resources/signals/models/consent_record.yml @@ -1,5 +1,8 @@ type: object -description: A consent record indicating whether signals collection is enabled for an agent. +description: >- + A consent record indicating whether signals collection is enabled for a + source. Records with `source: agent` apply to one agent; the record with + `source: inference` applies to the whole team. properties: id: type: integer @@ -9,14 +12,26 @@ properties: type: integer description: The team ID that owns this consent record. example: 39449946 + source: + type: string + enum: + - agent + - inference + description: >- + The source this consent applies to. `agent` is per-agent consent for + Harness Runtime; `inference` is team-level consent for Serverless + Inference chat completions. + example: agent agent_id: type: string - format: uuid - description: The unique identifier of the agent. For Harness Runtime, this is the Environment Config ID. + description: >- + The unique identifier of the agent. For Harness Runtime, this is the + Environment Config ID. Empty for team-level records (`source: + inference`), which are not tied to an agent. example: 019fb3d2-8a56-72cc-8bf9-9d21510b2a99 enabled: type: boolean - description: Whether signals collection is enabled for this agent. + description: Whether signals collection is enabled for this source. example: true updated_at: type: string @@ -26,6 +41,7 @@ properties: required: - id - team_id + - source - agent_id - enabled - updated_at diff --git a/specification/resources/signals/models/list_consents.yml b/specification/resources/signals/models/list_consents.yml index e0596bc86..9032c5e2d 100644 --- a/specification/resources/signals/models/list_consents.yml +++ b/specification/resources/signals/models/list_consents.yml @@ -3,8 +3,20 @@ description: A wrapper for a list of consent records. properties: consents: type: array - description: A list of consent records for the team's agents. + description: >- + A list of consent records for the team. Includes per-agent records + (`source: agent`) and, when set, the team-level inference record + (`source: inference`). items: $ref: 'consent_record.yml' + source: + type: string + enum: + - agent + - inference + description: >- + Echoes the `source` filter when the request was filtered by source. + Omitted when the list was not filtered. + example: inference required: - consents diff --git a/specification/resources/signals/parameters.yml b/specification/resources/signals/parameters.yml index 963aa9936..78e80def2 100644 --- a/specification/resources/signals/parameters.yml +++ b/specification/resources/signals/parameters.yml @@ -28,6 +28,37 @@ export_id: format: uuid example: 9f13c09c-c877-436b-9863-dcc39c9dd737 +source: + in: query + name: source + description: >- + Filter consent records by source. `agent` returns per-agent records + (Harness Runtime); `inference` returns the team-level record for + Serverless Inference chat completions. When omitted, records for all + sources are returned. + required: false + schema: + type: string + enum: + - agent + - inference + example: inference + +source_required: + in: query + name: source + description: >- + The consent source to update. Only team-level sources are accepted on + this endpoint; currently `inference` (Serverless Inference chat + completions). Per-agent consent (`agent`) is managed with + `PUT /v1/consent/{agent_id}` instead. + required: true + schema: + type: string + enum: + - inference + example: inference + deletion_id: in: path name: deletion_id diff --git a/specification/resources/signals/responses/agent_consent_response.yml b/specification/resources/signals/responses/agent_consent_response.yml index 088b040ce..242aaaa3a 100644 --- a/specification/resources/signals/responses/agent_consent_response.yml +++ b/specification/resources/signals/responses/agent_consent_response.yml @@ -15,6 +15,7 @@ content: example: id: 13 team_id: 39449946 + source: agent agent_id: 019fb3d2-8a56-72cc-8bf9-9d21510b2a99 enabled: true updated_at: "2026-08-10T10:09:25.738533Z" diff --git a/specification/resources/signals/responses/list_consents_response.yml b/specification/resources/signals/responses/list_consents_response.yml index 98b5a1bc8..d4ffb12af 100644 --- a/specification/resources/signals/responses/list_consents_response.yml +++ b/specification/resources/signals/responses/list_consents_response.yml @@ -16,11 +16,19 @@ content: consents: - id: 13 team_id: 39449946 + source: agent agent_id: 019fb3d2-8a56-72cc-8bf9-9d21510b2a99 enabled: true updated_at: "2026-08-10T10:09:25.738533Z" - id: 6 team_id: 39449946 + source: agent agent_id: 019fb6b1-aad4-7d54-a74e-c5570d768148 enabled: true updated_at: "2026-08-07T10:10:16.385447Z" + - id: 21 + team_id: 39449946 + source: inference + agent_id: "" + enabled: true + updated_at: "2026-10-09T11:41:27.104822Z" diff --git a/specification/resources/signals/responses/update_consent_response.yml b/specification/resources/signals/responses/update_consent_response.yml index 0717d27ec..578b15632 100644 --- a/specification/resources/signals/responses/update_consent_response.yml +++ b/specification/resources/signals/responses/update_consent_response.yml @@ -21,6 +21,7 @@ content: consent: id: 13 team_id: 39449946 + source: agent agent_id: 019fb3d2-8a56-72cc-8bf9-9d21510b2a99 enabled: true updated_at: "2026-10-07T11:06:32.280572Z" diff --git a/specification/resources/signals/responses/update_team_consent_response.yml b/specification/resources/signals/responses/update_team_consent_response.yml new file mode 100644 index 000000000..dca47b716 --- /dev/null +++ b/specification/resources/signals/responses/update_team_consent_response.yml @@ -0,0 +1,27 @@ +description: The team-level consent record was updated successfully. + +headers: + ratelimit-limit: + $ref: '../../../shared/headers.yml#/ratelimit-limit' + ratelimit-remaining: + $ref: '../../../shared/headers.yml#/ratelimit-remaining' + ratelimit-reset: + $ref: '../../../shared/headers.yml#/ratelimit-reset' + +content: + application/json: + schema: + type: object + properties: + consent: + $ref: '../models/consent_record.yml' + required: + - consent + example: + consent: + id: 21 + team_id: 39449946 + source: inference + agent_id: "" + enabled: true + updated_at: "2026-10-09T11:41:27.104822Z" diff --git a/specification/resources/signals/signals_get_consent.yml b/specification/resources/signals/signals_get_consent.yml index f3a4548e4..4d94d15e6 100644 --- a/specification/resources/signals/signals_get_consent.yml +++ b/specification/resources/signals/signals_get_consent.yml @@ -7,6 +7,9 @@ description: | request to `/v1/consent/{agent_id}`. The response includes an `enabled` field indicating whether signals collection is on for this agent. + This endpoint only serves per-agent (`source: agent`) records. Team-level + inference consent is read from `GET /v1/consent?source=inference`. + tags: - Signals @@ -17,6 +20,9 @@ responses: '200': $ref: 'responses/agent_consent_response.yml' + '400': + $ref: '../../shared/responses/bad_request.yml' + '401': $ref: '../../shared/responses/unauthorized.yml' diff --git a/specification/resources/signals/signals_list_consents.yml b/specification/resources/signals/signals_list_consents.yml index f2590c200..6053e11a3 100644 --- a/specification/resources/signals/signals_list_consents.yml +++ b/specification/resources/signals/signals_list_consents.yml @@ -5,15 +5,26 @@ summary: List All Consent Records description: | To list all signals consent records for your team, send a GET request to `/v1/consent`. Each record indicates whether signals collection is enabled - for a specific agent. + for a source: per-agent records (`source: agent`) for Harness Runtime, and + the team-level record (`source: inference`) for Serverless Inference chat + completions. + + Pass `?source=agent` or `?source=inference` to return only that source's + records. When filtered, the response also echoes the `source`. tags: - Signals +parameters: + - $ref: 'parameters.yml#/source' + responses: '200': $ref: 'responses/list_consents_response.yml' + '400': + $ref: '../../shared/responses/bad_request.yml' + '401': $ref: '../../shared/responses/unauthorized.yml' diff --git a/specification/resources/signals/signals_update_consent.yml b/specification/resources/signals/signals_update_consent.yml index 5ad429a07..8d91d01bc 100644 --- a/specification/resources/signals/signals_update_consent.yml +++ b/specification/resources/signals/signals_update_consent.yml @@ -7,6 +7,10 @@ description: | PUT request to `/v1/consent/{agent_id}` with an `enabled` boolean in the request body. + This endpoint only manages per-agent (`source: agent`) consent. To manage + team-level consent for Serverless Inference, use + `PUT /v1/consent?source=inference` instead. + tags: - Signals @@ -32,6 +36,9 @@ responses: '200': $ref: 'responses/update_consent_response.yml' + '400': + $ref: '../../shared/responses/bad_request.yml' + '401': $ref: '../../shared/responses/unauthorized.yml' diff --git a/specification/resources/signals/signals_update_team_consent.yml b/specification/resources/signals/signals_update_team_consent.yml new file mode 100644 index 000000000..b7069c3b3 --- /dev/null +++ b/specification/resources/signals/signals_update_team_consent.yml @@ -0,0 +1,61 @@ +operationId: signals_update_team_consent + +summary: Update Team-Level Consent + +description: | + To enable or disable signals collection for a source that is consented at + the team level, send a PUT request to `/v1/consent?source=inference` with + an `enabled` boolean in the request body. Currently the only team-level + source is `inference`, which covers Serverless Inference chat completions + made by your team. + + To revoke consent, send the same request with `enabled` set to `false`. + The `source` query parameter is required. Per-agent consent for Harness + Runtime agents is managed with `PUT /v1/consent/{agent_id}` instead. + +tags: + - Signals + +parameters: + - $ref: 'parameters.yml#/source_required' + +requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + enabled: + type: boolean + description: Whether to enable signals collection for this source. + required: + - enabled + example: + enabled: true + +responses: + '200': + $ref: 'responses/update_team_consent_response.yml' + + '400': + $ref: '../../shared/responses/bad_request.yml' + + '401': + $ref: '../../shared/responses/unauthorized.yml' + + '429': + $ref: '../../shared/responses/too_many_requests.yml' + + '500': + $ref: '../../shared/responses/server_error.yml' + + default: + $ref: '../../shared/responses/unexpected_error.yml' + +x-codeSamples: + - $ref: 'examples/curl/signals_update_team_consent.yml' + +security: + - bearer_auth: + - 'signals:update'