Record a Context Opportunity

The platform's ONE writable, platform-native advisory object. Records one Context Opportunity — an evidence-backed proposal that some governed domain's context may warrant an action (create/revise/confirm/challenge/invalidate/supersede/review). This is a THIN delegate to the same U7R.2 domain service used by the implemented REST and GraphQL write transports: it never writes a governed-domain table directly, and it creates ONLY an opportunity record — it never approves, mutates, promotes, or supersedes governed truth. The external MCP runtime does not register an opportunity write tool today. Reads (POST /api/v1/context/unified with domains:["opportunity"]) use the separate context-engine:read scope and are never gated by the write feature flag. This write endpoint requires context-opportunity:write and is gated by the server-side CONTEXT_OPPORTUNITY_WRITES_ENABLED flag (default off) until the U7R.2 migration is applied and verified live in the target environment — when disabled, this endpoint returns feature_disabled (403) rather than a 500.

POST/api/v1/context/opportunities

Purpose

Let an AI session, ticket workflow, or any authorized producer record an advisory opportunity for a human (or the owning domain's own workflow) to later review, without ever granting write access to governed decisions, requirements, commitments, or any other domain table.

Security

Tenancy (account) is always derived from the credential, never the request body. A project-scoped opportunity is rejected with 404 (anti-oracle, indistinguishable from a nonexistent project) if the caller cannot access that project.

Recommended uses

  • An MCP conversation surfaces a decision-worthy statement that the decision domain has not yet recorded
  • A code review or PR finds an implementation detail that contradicts a documented requirement
  • An automated recovery scan or execution engine detects a risk signal worth a human review

Not intended for

  • Approving, rejecting, or promoting an opportunity into a governed object — that is a future, human-only governance slice, not this endpoint
  • Writing to any governed-domain table (decisions, requirements, commitments, tickets, sprints) directly
  • Storing a full conversation transcript — source.excerpt is bounded and privacy-gated, never a full transcript

Authorization

context-opportunity:writeapi key scoperequired
Required scope when calling with an API key.

Request body

opportunityobjectrequired
{ opportunity_type, target_domain, proposed_operation, title, summary, current_object_ref?, proposed_value?, confidence?, promotion_target?, detected_at? }. target_domain can never be "opportunity".
sourceobjectrequired
{ source_kind, source_id, source_system, actor: { kind, id?, system? }, source_occurred_at?, ingested_at?, trace_ref?, interaction_ref?, excerpt? }. excerpt is bounded (max 1000 chars) and dropped unless privacy.excerpt_permission allows it.
privacyobjectrequired
{ visibility_classification, excerpt_permission, source_access_policy?, retention_classification? }. A caller-requested visibility narrower than or equal to the source's own privacy floor wins; the server never widens it.
evidencearrayoptional
Up to 25 EvidenceReference objects (provider_id, source_id, source_type, provenance_quality, …). References only, never raw source content.
relationshipsarrayoptional
Up to 25 typed relationships to other governed objects or opportunities: { verb, target_kind, object?, opportunity_id?, note? }.
dedupobjectoptional
{ idempotency_key?, producer_key? }. The same idempotency_key with the same content is a safe no-op replay across the implemented REST and GraphQL transports.
project_idstringoptional
Scopes the opportunity to a project. Rejected with 404 if the caller cannot access it.
engagement_idstringoptional
Scopes the opportunity to an engagement.
subjectobjectoptional
Optional addressed subject { type, id }.
trace_contextstringoptional
Opaque observability trace id; never source content.
Example request
{
  "opportunity": {
    "opportunity_type": "discovered_decision",
    "target_domain": "decision",
    "proposed_operation": "create",
    "title": "Tax category decision worth recording",
    "summary": "A conversation surfaced a decision the decision domain may want to record."
  },
  "source": {
    "source_kind": "mcp_session",
    "source_id": "session_abc123",
    "source_system": "mcp",
    "actor": {
      "kind": "ai",
      "system": "mcp"
    }
  },
  "privacy": {
    "visibility_classification": "restricted",
    "excerpt_permission": "none"
  },
  "project_id": "24ea6df2-7f4c-4c32-9fc1-6c8a0cb5b4b2",
  "dedup": {
    "idempotency_key": "mcp-session-abc123-decision-1"
  }
}

Request

curl -X POST "https://www.digitalstack360.com/api/v1/context/opportunities" \
  -H "Authorization: Bearer $DS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"opportunity":{"opportunity_type":"discovered_decision","target_domain":"decision","proposed_operation":"create","title":"Tax category decision worth recording","summary":"A conversation surfaced a decision the decision domain may want to record."},"source":{"source_kind":"mcp_session","source_id":"session_abc123","source_system":"mcp","actor":{"kind":"ai","system":"mcp"}},"privacy":{"visibility_classification":"restricted","excerpt_permission":"none"},"project_id":"24ea6df2-7f4c-4c32-9fc1-6c8a0cb5b4b2","dedup":{"idempotency_key":"mcp-session-abc123-decision-1"}}'

Examples use a placeholder key from your environment. Store your key in $DS_API_KEY — never commit it.

Response

200 OK
{
  "data": {
    "opportunity_id": "8a043c6e-52ab-4df1-8b7a-afec991a05a2",
    "lifecycle_state": "submitted",
    "idempotent_replay": false,
    "recorded_at": "2026-07-21T09:00:00Z",
    "authority": {
      "authority_type": "advisory",
      "owning_domain": "opportunity",
      "owning_system": "opportunity",
      "mutable_here": true
    },
    "target_domain": "decision",
    "proposed_operation": "create"
  },
  "meta": {
    "request_id": "req_…",
    "idempotent_replay": false
  }
}

Errors

401
missing_auth

No credentials provided

401
invalid_api_key

API key is invalid or revoked

400
bad_request

Invalid/forbidden field, unsupported target domain, or a request the domain service rejected as malformed

403
scope_insufficient

Key lacks context-opportunity:write scope

403
forbidden

Cross-account or actor-mismatch: the request cannot assert a tenancy or identity the resolved credential does not hold

403
feature_disabled

Context Opportunity writes are not enabled in this environment (CONTEXT_OPPORTUNITY_WRITES_ENABLED is off)

404
not_found

The addressed project is not accessible to this principal (anti-oracle: indistinguishable from a nonexistent project)