Skip to content

docs(adr) promote Cosmos ARM-vs-data-plane split to ADR-0012#65

Merged
jkeeley2073 merged 1 commit into
mainfrom
Dev-Adr0012CosmosArmDataPlaneSplit
May 4, 2026
Merged

docs(adr) promote Cosmos ARM-vs-data-plane split to ADR-0012#65
jkeeley2073 merged 1 commit into
mainfrom
Dev-Adr0012CosmosArmDataPlaneSplit

Conversation

@jkeeley2073
Copy link
Copy Markdown
Contributor

Summary

First Phase 2 PR: promote the locked Cosmos schema-CRUD-via-ARM / item-CRUD-via-data-plane-SDK invariant from CLAUDE.md and session memory to formal ADR-0012, per docs/build-spec.md Phase 2 § Scope item 1.

The underlying decision was made and shipped in PR #63 (2026-05-04) after PR #62 attempted a custom Cosmos data-plane RBAC role granting Microsoft.DocumentDB/databaseAccounts/sqlDatabases/* and was rejected by Azure runtime validation: data-plane RBAC genuinely does not model schema-mutation actions, regardless of role definition. ADR-0012 captures the lesson permanently so the same path isn't retried.

The ADR documents the load-bearing precision that the operational consequences require two role assignments in TWO INDEPENDENT RBAC systemsCosmos DB Operator in Azure RBAC for ARM ops, plus Cosmos DB Built-in Data Contributor in Cosmos SQL RBAC (a separate system from Azure RBAC) for item ops. Subscription Owner inheritance covers Azure RBAC but does NOT automatically grant Cosmos SQL RBAC. Verified via az role definition list --name "Cosmos DB Operator" (returns the role); the data-plane role's well-known ID 00000000-0000-0000-0000-000000000002 is documented inline.

Three cross-reference edits land in the same PR so the documentation is internally consistent at every commit:

  • CLAUDE.md § Cosmos persistence: inline rationale collapses to a one-line ADR-0012 pointer (the showcase posture aim — CLAUDE.md references ADRs rather than duplicating content)
  • CLAUDE.md § Locked invariants item 4: adds ADR-0012 pointer
  • docs/guardrails.md § Locked decisions: adds ADR-0012 pointer
  • docs/adr/README.md index: adds 0011 (pre-existing oversight — the reconciliation ADR landed in PR feat(sync) scraper-to-Machine reconciliation service + ADR 0011 #35 but the index was never updated) and 0012

Test Plan

  • Docs-only PR; no code paths affected.
  • dotnet build PinballWizard.slnx --nologo and dotnet test PinballWizard.slnx are expected to remain green (507 / 507).
  • Cross-references verified: every link from CLAUDE.md / guardrails.md / adr/README.md / build-spec.md to the new ADR resolves; the ADR's References section links back correctly.

Out of Scope

  • ADR-0013 (two-tier Bicep deploy with deployPhase2 gate) — companion Phase 2 § Scope item 2; ships in its own PR.
  • Other Phase 2 workingestion_sources seed, OPDB sync against deployed Cosmos, OTel groundwork, Playwright bump, Dependabot triage, Stern Playwright asymmetry resolution, work-email proactive denylist all remain Phase 2 § Scope items in their own PRs.

Checklist

  • CI is green (build + test + coverage + CodeQL + sanitization) — will verify after the workflows run
  • PR title follows the Conventional Commits format
  • If this is a new architectural decision, an ADR has been added — yes, ADR-0012 is the headline artifact of this PR; the decision itself was locked in PR feat(infra) ARM-backed CosmosBootstrapper supersedes broken PR #62 RBAC #63 and is now formally recorded
  • If user-visible behavior changes, README.md and/or docs/ are updated — yes, three docs updated alongside the ADR for cross-reference coherence
  • If a memory is now stale, it has been updated or removed — N/A; memory entries already reference the spec docs and ADRs as canonical
  • No TODO / FIXME / commented-out code committed
  • No new entries in <NoWarn> without justification — N/A; no code

Pre-push self-audit (additive PRs)

N/A for this PR — docs-only, no scraper / options class / extension / additive code surface. Per docs/guardrails.md § "Per-PR gate" and CLAUDE.md § "PR self-audit", "Doc-only PRs and pure dependency bumps may skip" the audit. Identity check still verified:

  • git log -1 --format='%an <%ae>'Jim Keeley <94459922+jkeeley2073@users.noreply.github.com>

🤖 Generated with Claude Code

Promote the locked Cosmos schema-CRUD-via-ARM, item-CRUD-via-
data-plane-SDK invariant from CLAUDE.md + session memory to a formal
ADR per Phase 2 § Scope item 1. The decision was made and shipped in
PR #63 (2026-05-04) after PR #62 attempted a custom Cosmos data-plane
RBAC role granting `Microsoft.DocumentDB/databaseAccounts/sqlDatabases/*`
and was rejected by Azure runtime validation: data-plane RBAC genuinely
does not model schema-mutation actions.

ADR-0012 captures:

- Why both SDK surfaces matter (data-plane SDK convenience methods make
  the wrong path tempting; ARM SDK is the correct schema-CRUD path)
- The failed PR #62 attempt as documented context, so the same custom-
  role path is not retried
- The locked solution (ICosmosProvisioner abstraction with
  ArmCosmosProvisioner + DataPlaneCosmosProvisioner selected at
  DI-resolution time by Cosmos:AccountResourceId presence)
- Operational consequences with the load-bearing precision: two role
  assignments in TWO INDEPENDENT RBAC systems — Cosmos DB Operator in
  Azure RBAC for ARM ops, plus Cosmos DB Built-in Data Contributor in
  Cosmos SQL RBAC for item ops. Subscription Owner inheritance covers
  Azure RBAC but does NOT automatically grant Cosmos SQL RBAC, which
  must be explicitly assigned at the Cosmos account scope
- Four alternatives considered and rejected (data-plane SDK with master
  keys; the failed PR #62 custom-role attempt; containers in Bicep;
  no-abstraction-caller-picks)

Three cross-reference edits land in the same PR so the documentation
is internally consistent at every commit:

- CLAUDE.md § Cosmos persistence — inline rationale collapses to a
  one-line ADR-0012 pointer (the showcase posture aim: CLAUDE.md
  references ADRs rather than duplicating their content)
- CLAUDE.md § Locked invariants item 4 — adds ADR-0012 pointer
- docs/guardrails.md § Locked decisions — adds ADR-0012 pointer
- docs/adr/README.md index — adds 0011 (pre-existing oversight; the
  reconciliation ADR landed in PR #35 but the index was never updated)
  and 0012

ADR-0013 (two-tier Bicep deploy with deployPhase2 gate) is the
companion Phase 2 § Scope item 2 promotion; ships in its own PR.
@jkeeley2073 jkeeley2073 added the claude-code Generated with Claude Code label May 4, 2026
@jkeeley2073 jkeeley2073 merged commit d127819 into main May 4, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

claude-code Generated with Claude Code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant