Document the withdraw_source Context action
SI
6d ago+57+57+01234567890123456789-3-3-0123456789
Summary
Documents the new withdraw_source action of the shared POST /api/context / MCP Context operation:
- Request variant.
request_idplus exactly one ofsource_idorsource_version_id(a nestedoneOfof required sets), with optionalorganization_id.source_version_idis what callers can already find on main, assourceVersionIdsin brief and saved-brief input manifests. The previous text wrongly said that source IDs appear in manifests. - Example. A
withdrawSourceexample using a version ID. - 200 receipt shape.
context-source-withdrawal-v1withwithdrawn_at,already_withdrawn, andaffected= recorded lineage, which is identical on replay. - Behavior. Every result on the source is relabelled
withdrawn(rows kept), documents whose current result used it lose it, and future reads, briefs and saved snapshots withhold that evidence. The withdrawal is sticky for the workspace, source kind and URL, so a later or in-flight job cannot republish it and ingestion that needs it accepted fails with a conflict. There is no restore. - 409. The description now says that
withdraw_sourcehas no idempotency key and can be retried unchanged.
This advances the CE08 Done-when item that withdrawn/private sources disappear from future authorized reads and derived briefs. The operate page is frontmatter-only and is unchanged.
Refs recoupable/app#2124 (child of epic recoupable/app#2116).
Merge sequencing
docs → database → api → app. This is the contract-first PR. Sibling PRs on branch claude/ctx-2124-source-withdrawal: recoupable/database#102 (migration + transaction tests, including the late-writer fence) and recoupable/api#1008 (withdraw_source over HTTP and MCP). There is no app PR, because this slice has no UI. It does not depend on any open PR.
Known text conflicts:
- Many open docs PRs (#357–#371) edit the same one-line operation
description, so expect a trivial rebase. - Ticket #2125's docs#361 adds "source withdrawal … not exposed yet". Whichever merges second must drop that clause.
Verification
- Ran:
python3 -c "import json;json.load(open('api-reference/openapi/context.json'))": parses. The request-bodyoneOflists ingest, read, brief, save_brief, read_brief and withdraw_source. Thewithdraw_sourcevariant requiresactionandrequest_id, its nestedoneOfrequiressource_idorsource_version_id, and thewithdrawSourceexample usessource_version_id. Edits were anchored text replacements, each matching exactly once. - Red → green: not applicable to a JSON contract change. The api PR's tests cover the documented input (including exactly-one identifiers) and the receipt shape. The database PR's tests assert every documented receipt key and type.
- Not verified: Mintlify rendering of the nested
oneOf, hosted deployment, live providers, production database.
Out of scope / known gaps
- A restore/un-withdraw operation.
- Scoped corrections, refresh or recomputation after withdrawal.
- Duplicate-article corroboration rules.
- Deletion/retention of original private bytes (owned by database#94/#95 + api#986–#991).
- Cancel/refresh transports (#2125), workflows, paid calls, and any UI.
🤖 Generated with Claude Code