Topolo Docs Topolo Platform
Open workspace

Update a Consent data-subject request status

Record a reviewed processing status, verify the scoped request and distinguish audit and notification effects from underlying data work.

Outcome

Update a Consent data-subject request’s recorded processing status and append an audit event. This action records a label; it does not carry out the underlying data request.

Action: app_topolo_consent.dsr_requests.status.update.

POST /api/dsr-requests/{requestId}/status

Before you start

  1. Verify the original credential, production environment, organization and actual canonical Consent workspace. Bind the workspace separately from request input. Discover the real DSR request id from authorized existing records; a request id, project key or email is not a workspace grant.

  2. This POST route requires app_topolo_consent.workspace:write and a verified workspace grant of at least read_write. The verification list separately requires workspace:read. Preserve original API-key bindings and named-workspace refusals; do not switch principals or broaden scope after a denial.

  3. Review the current request, actual work performed, intended status and note before approving the mutation. A fulfilled/closed label is operational bookkeeping here; do not mark real underlying data work complete solely because this endpoint accepts a label. Notes become retained audit data; include only appropriate necessary information.

Request and supported states

{
  "requestId": "dsr_fixture_request",
  "status": "verifying",
  "note": "Fixture review has started."
}

The id is fictional and the example is unrun. Discover actual records, validate/plan the exact intended input and obtain approval before a real mutation. Workspace binding is separate. requestId and status are required; note is optional but, if present, must satisfy the current schema. A missing required field is a local preflight error rather than a captured HTTP response.

Supported status strings: submitted, verifying, in_progress, fulfilled, rejected, appealed, closed.

Effects and ordering

After caller/permission/workspace checks, the handler requires the events/audit database and parses the body. The schema only requires a nonempty status string, while the handler accepts exactly submitted,verifying,in_progress,fulfilled,rejected,appealed,closed. Another nonempty value can pass local schema validation and receive400/invalid_dsr_status.

The request SELECT filters id alone and reads id,project_id,project_key,request_type,status before access is checked through the associated project’s verified workspace. A missing request or absent/unreachable associated project returns404/dsr_request_not_found. Do not claim the request is workspace-filtered in its first SQL query; a missing control database can also leave the associated project unresolved.

The handler does not enforce a transition graph or require an expected version/current status. It accepts any of the seven labels after the scope checks, updates status and updated_at, and can overwrite a concurrent change. Repeating an unchanged label is still a write and appends another DSR event; no idempotency key is accepted.

The source schedules completion-notification work only when status actually changes to fulfilled,rejected or closed and an execution context is available. It does not schedule that work for submitted,verifying,in_progress or appealed, or for an unchanged terminal label. Notification errors are caught separately; returned status is not delivery proof.

A DSR event is inserted after the status update, including request/project/workspace ids, previous and next status, normalized optional note and actor information derived from the authenticated context. Update, asynchronous notification work and audit insert are not one atomic transaction. A later audit/transport failure can leave the status changed and notification work already started; read state before any retry.

Successful output is exactly {id,status,updatedAt}; it does not include an audit event id, approval signature, exported data, deletion certificate or notification receipt. Changing this record does not itself fulfill a data-access/deletion request, perform organization erasure/export, run AI or verify a person’s legal rights.

Complete worked responses

Move a reviewed request into verification

Complete source-derived synthetic/unrun HTTP200 response. Assumes an existing submitted fixture request in the verified workspace, bound control/events databases, approved read_write/write authority and the illustrated request clock. No status/audit/notification operation occurred.

Input:

{
  "requestId": "dsr_fixture_request",
  "status": "verifying",
  "note": "Fixture review has started."
}

Response:

{
  "id": "dsr_fixture_request",
  "status": "verifying",
  "updatedAt": "2026-10-21T00:00:00.000Z"
}

Read back the actual request. The nonterminal change does not schedule this handler’s completion notification; it still writes status and an event.

Record completion after separately verified underlying work

Complete source-derived synthetic/unrun HTTP200 response. Assumes current status in_progress, the same verified scope/storage/authority, separately approved underlying-work evidence and an available execution context. No actual data processing or notification was executed for this example.

Input:

{
  "requestId": "dsr_fixture_request",
  "status": "fulfilled",
  "note": "Fixture underlying work reviewed separately."
}

Response:

{
  "id": "dsr_fixture_request",
  "status": "fulfilled",
  "updatedAt": "2026-10-21T00:00:00.000Z"
}

The status change can schedule completion-notification work. Verify the audit and underlying outcome separately; this body is not a delivery or erasure receipt.

Reject an unsupported nonempty status

Source-derived synthetic/unrun HTTP400 refusal. The current nonempty-string schema accepts completed, but the source status vocabulary does not. Assumes prior Auth/workspace/permission and events-database checks pass; this status guard runs before the request SELECT or mutation.

Input:

{
  "requestId": "dsr_fixture_request",
  "status": "completed"
}

Response:

{
  "error": "invalid_dsr_status"
}

Choose only the reviewed appropriate source-supported status; no mutation happened in this illustrated refusal branch.

Conceal an inaccessible request as not found

Source-derived synthetic/unrun HTTP404 refusal. Assumes original caller checks pass and a stored fixture request’s associated project is outside the verified workspace. This external fixture condition is not an input flag or a live cross-workspace probe.

Input:

{
  "requestId": "dsr_fixture_request",
  "status": "verifying"
}

Response:

{
  "error": "dsr_request_not_found"
}

Preserve the refusal and original scope. Do not guess another id or widen workspace access; absence and inaccessible/unresolved project share this response.

Verify and recover

Use the current app_topolo_consent.dsr_requests.list action with the original credential and same workspace. Its source returns requests plus source; compare the exact request id, projectKey, status and updatedAt to the intended change. Separate read eligibility is required.

That list is the latest100 requests by created_at across its accessible project set, which is capped at500 projects. It is not an exhaustive request history or a guaranteed point lookup. Missing storage or no accessible projects can also produce an empty list. If the target is not returned, verification is UNKNOWN; retain the actual evidence and ask the existing owner for a supported scoped read/trace instead of assuming the write failed or blindly repeating it.

Verify actual data-processing work, audit outcome and any notification delivery through their own authorized evidence. A matching status response or list row proves none of those outcomes by itself. Preserve concurrent changes and actual request/refusal evidence.

There is no atomic rollback or audit-event deletion here. After read-back and concurrency review, a separately approved call may restore a known prior status if it is one of the seven accepted values, with a factual correction note. That adds another event, changes updatedAt and can trigger notification work under the same terminal-change rule; it cannot retract an earlier event or delivered notification. Do not invent an event-delete endpoint, restore an unknown prior label or repeat after an uncertain result without reconciliation.

Refusals

400 / invalid_dsr_status: Use exactly one of submitted,verifying,in_progress,fulfilled,rejected,appealed,closed after reviewing the actual state and work. Schema-valid nonempty text is not sufficient.

404 / dsr_request_not_found: Reconcile the actual request and its associated project with original verified scope. Do not infer definitive absence or broaden access; unresolved control storage/project can also prevent reachability.

503 / database_unavailable: The events/audit database is unavailable. Preserve actual evidence and route dependency restoration to the existing service owner before an authorized retry.

Outer authentication, permission and workspace refusals occur before these handler branches. Uncaught storage/audit failures can occur after the status write; preserve their actual status/code/request evidence instead of inventing an exact shared response or assuming nothing changed. Malformed JSON is normalized to an empty body by the route helper, but normal local action validation rejects missing required fields before transport.

Change log

  • 2026-10-21: Added the actual status vocabulary, original workspace authority, write/notification/audit ordering, complete illustrative unrun responses and bounded read-back/compensation limits. Recorded status is distinguished from underlying data processing, complete audit history and notification delivery.