Skip to content

docs(auth): self-registering (CIMD) clients get commerce by configuration; connect/details returns clientOrigin - #409

Merged
r-marques merged 4 commits into
mainfrom
docs/3394-cimd-trust-overlay
Sep 21, 2026
Merged

r-marques merged 4 commits into
mainfrom
docs/3394-cimd-trust-overlay

Conversation

@r-marques

@r-marques r-marques commented Sep 15, 2026

Copy link
Copy Markdown
Member

Docs half of nevermined-io/nvm-monorepo#3546 (nvm-monorepo#3394, epic nvm-monorepo#3458): a self-registering CIMD client (ChatGPT, Claude Code, any MCP host presenting an https URL as its client_id) is granted commerce by configuration — identity from its metadata document, trust from the operator.

Merge after nvm-monorepo#3546 deploys (the clientOrigin field and the CIMD branch of connect/details do not exist on the API until then).

Pages modified

  • integrate/authentication/oauth-authorization-code.mdx — new section "Self-registering clients: identity from the document, trust from the operator" under "Connectors and consent": what a CIMD client_id is, why the document can never grant account-level authority (BCK.OAUTH.0018), how an operator lists a URL (trust fields only, no redirect URIs, named consent types, de-listing resets), the out-of-the-box table (ChatGPT https://chatgpt.com/oauth/client.json, Claude Code https://claude.ai/oauth/claude-code-client-metadata, both ["commerce"]), the host-beside-name rule and clientOrigin, and BCK.OAUTH.0031.
  • integrate/authentication/for-agents.mdx — the "Get a key" step tells an MCP host with a URL client_id what it gets with no registration and what commerce additionally needs, linking to the section above.
  • products/catalog/mcp.mdx — "Auth & transport" gains "Which hosts can be granted commerce": ChatGPT and Claude Code out of the box, an unlisted host is refused at the consent screen (never silently granted), the domain shown beside the name.
  • api-reference/oauth-openapi.json (hand-maintained; edited as text, JSON re-validated) — ConnectDetails.clientOrigin (string, nullable, in required[] — the API always sends it, null for a static connector), connectorName description, the /oauth/connect/details operation description (CIMD resolution + 0031), ConnectDetailsRequest.client_id description. Written from the API's rendered document (ConnectDetailsDto, pinned by oauth-error-openapi.spec.ts), not the decorators.

Cross-references added: for-agents.mdx → and products/catalog/mcp.mdx → the new oauth-authorization-code.mdx#self-registering-clients-identity-from-the-document-trust-from-the-operator anchor.

Checks

  • mintlify broken-links: success, no broken links found.
  • PR previews are currently absent (CLAUDE.md "Testing & Preview Workflow" step 3); the pages were fetched from a local mintlify dev — both edited pages answer 200 and render the new headings ("Self-registering clients: identity from the document, trust from the operator", "Which hosts can be granted commerce").
  • docs.json unchanged (no new page). architecture.md unchanged.
  • Does not overlap docs#404's hunks (the iss / scope work edits the Prerequisites list, Step 1 and the Note; this PR adds a new ### section below the per-consent-type one and touches different openapi.json lines).

🤖 Generated with Claude Code


2026-09-21 — out of draft. Production is enabled and in effect (argocd#646 merged + synced; connect/details["commerce"] on both prod tiers), so the gate these drafts waited on is met. Stacked PR: base = #404 (docs/3527-oauth-scope-consent-and-iss); #411#414 follow. Rebased onto the current pages (main restructured for-agents.mdx / overview.mdx and grew mcp.mdx meanwhile); mintlify broken-links green. Merge in order — GitHub retargets each base to main as the previous one lands.

@aaitor aaitor left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 REQUEST_CHANGES

The CIMD trust-overlay documentation is accurate and genuinely well-verified against the merged nvm-monorepo#3546 source — the error codes (BCK.OAUTH.0018/0031), the clientOrigin contract, "omit → grants nothing (never both)", "an entry that lists redirectUris is refused as malformed", and the de-listing/reset behaviour all check out, and the OpenAPI change is correct (this file is openapi: 3.0.0, so nullable: true is the right spelling and matches every other field). One HIGH blocks: the repeated "out of the box on every tier" claim is true on staging but not yet true on production, and the PR's merge-gate points at the wrong dependency.

HIGH

  • out of the box on every Nevermined tier (oauth-authorization-code.mdx L119/L123–124, for-agents.mdx L42, products/catalog/mcp.mdx L52) — enabled on staging (argocd#644/#645, merged 2026-09-16) but not on production: the enabling change is argocd#646, still open/unmerged, and production has no auto-sync. On merge, docs deploy from main immediately, so a live user who follows this page to connect ChatGPT/Claude Code for commerce gets refused with BCK.OAUTH.0018 — the exact error the page attributes to unlisted hosts. Hold until argocd#646 is merged and synced on both production tiers; fix the PR's merge-gate to name it (#3546 alone is necessary but not sufficient).

LOW

  • The out-of-the-box table lists 2 CIMD clients; the deployed config grants commerce to 3 — it also lists https://claude.ai/oauth/mcp-oauth-client-metadata (claude.ai's hosted MCP connector). (oauth-authorization-code.mdx L124)
  • OpenAPI connectorName description drops the DTO's "falls back to the client_id when unregistered" clause, so "never the caller-supplied client_id" now reads as unconditional. (oauth-openapi.json L313)

Verification I ran

  • gh pr view/diff/checks #409; read all four changed files. Local checkout is on another branch, so head content came from the diff + gh api .../contents?ref=….
  • Cross-checked every behavioural claim against merged nvm-monorepo#3546 (MERGED 2026-09-15): connect-details.dto.ts (clientOrigin string|null, "Always present" → correctly added to required[]), oauth-client.service.ts (readCimdTrust null→[], resetUnlistedCimdTrust, CIMD_ANCHOR_TRUST), oauth-client-bootstrap.service.ts (a URL entry with redirectUris/orgId is rejected whole), configurations.ts (bootstrapClients empty by default), codes.mdx (0031 present).
  • Verified deployed config against the remote argocd (not the stale local checkout): staging both tiers ✅ (#644/#645 merged); production both tiers ❌ (#646 open); production has no auto-sync.
  • Anchor slugs: the new heading's Mintlify slug matches both cross-reference links exactly.
  • CI: Mintlify Deployment = skipping (known PR-preview outage since #389 — not a red check). Docs-only; no leanness pass applicable.

Everything else in the diff is correct and ships as-is once production is enabled — the "out of the box" wording itself is fair then; this is a timing/merge-gate block, not a content rewrite.

Comment thread integrate/authentication/oauth-authorization-code.mdx
Comment thread integrate/authentication/oauth-authorization-code.mdx
Comment thread integrate/authentication/for-agents.mdx Outdated
Comment thread products/catalog/mcp.mdx Outdated
Comment thread api-reference/oauth-openapi.json Outdated
@aaitor

aaitor commented Sep 21, 2026

Copy link
Copy Markdown
Member

No description provided.

@r-marques
r-marques force-pushed the docs/3394-cimd-trust-overlay branch from b0f18c5 to c6cd1f7 Compare September 21, 2026 12:13

@aaitor aaitor left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-review of my 09-17 changes-requested, at c6cd1f71 (a rebase onto #404's fold; 409's own diff is byte-identical to the one I reviewed at b0f18c5b). All three findings are folded:

  1. HIGH — "out of the box on every tier": the gate is met. argocd#646 is merged (2026-09-18) and production-api-{live,sandbox}.yaml on main lists all three CIMD URLs at ["commerce"], matching the table row for row. The manual production sync I couldn't re-measure from here (no cluster access) — I'm relying on the PR body's statement that connect/details answers ["commerce"] on both prod tiers.
  2. LOW — third table row: present (claude.ai's hosted connector).
  3. LOW — connectorName fallback clause: present.

Re-verified against nvm-monorepo main: BCK.OAUTH.0031 on both /oauth/authorize and connect/details, BCK.OAUTH.0018 for an unlisted client, clientOrigin (string|null, always sent) and the host shown beside the connector name on the consent screen, URL trust entries needing no name or redirects, and the OpenAPI file still parses. One new should-fix inline — a log line the operator recipe promises that the API doesn't write. My old threads on this PR are addressed and can be resolved.

Comment thread integrate/authentication/oauth-authorization-code.mdx Outdated

@aaitor aaitor left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Approved with comments — no blockers; 1 should-fix, 0 nit(s) left inline.

Inline review: #409 (review)

@r-marques
r-marques force-pushed the docs/3394-cimd-trust-overlay branch from c6cd1f7 to 1b6c6df Compare September 21, 2026 12:36
Base automatically changed from docs/3527-oauth-scope-consent-and-iss to main September 21, 2026 12:36
r-marques and others added 4 commits September 21, 2026 14:37
…tion; connect/details returns clientOrigin

nvm-monorepo#3394: a client presenting an https URL as its client_id needs no registration for
agent-specific grants; a commerce grant needs the operator to have listed that URL — ChatGPT and
Claude Code are listed out of the box. The consent screen shows the URL's host beside the
self-asserted name; POST /oauth/connect/details returns it as `clientOrigin`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…e the claude.ai connector among the listed CIMD clients

- oauth-openapi.json: restore the DTO's "Falls back to the client_id when the registry has no
  name" clause (LOW).
- The "listed out of the box" claim now names the three CIMD identities production will carry
  (argocd#646: ChatGPT, claude.ai's connector, Claude Code). The claim's truth on production is
  the merge gate for this PR (HIGH) — it stays draft until #646 is synced.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…argocd#645/#646)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…d off the authorize link or the vendor's metadata (docs#409 should-fix)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@r-marques
r-marques force-pushed the docs/3394-cimd-trust-overlay branch from 1b6c6df to 51e26cf Compare September 21, 2026 12:37
@r-marques
r-marques merged commit 854bd68 into main Sep 21, 2026
@r-marques
r-marques deleted the docs/3394-cimd-trust-overlay branch September 21, 2026 12:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants