Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Contributing to DCM

DCM — the Data Center Management control plane — is open-source under Apache License 2.0. Contributions
to the control plane, the provider ecosystem, and the architecture docs are welcome. The architecture is
captured in `architecture/`; the major decisions are recorded as ADRs in `architecture/adr/`.

## Subject-scoped pull requests (default)

The default unit of contribution is **one subject per PR** — a single, complete logical change, titled
by its subject (e.g. "Enable cost provider", "Adopt FOCUS 1.4 for cost", "Add EgressFirewall to the
namespace"). Keep PRs to roughly ≤2–3k lines; if a subject is larger, split it along logical boundaries
into a sequence of independently reviewable, subject-scoped PRs rather than forcing one oversized change.
Prefer logical boundaries over size-driven cuts, and never bundle unrelated subjects. Lead every PR
description with a short **Why** (the rationale), linking the ADR or requirement when one exists.

## Document the why

Every non-trivial change records its rationale, not just its diff:
- **Architectural decisions** get an ADR in `architecture/adr/` (next available number; follow the
existing shape — Context, Decision, Alternatives Considered, Consequences). One decision per ADR;
don't bundle.
- **Requirement changes** update the relevant requirement set (`dcm-platform-requirements.md` and the
ID series — `ADS-`, `AUD-`, `RDG-`, …).
- A reviewer should be able to reconstruct *why* a change exists from the repo, not just *what* changed.

## Licensing

By contributing to DCM you agree your contributions are licensed under Apache License 2.0, matching the
project license.
867 changes: 867 additions & 0 deletions architecture/00-split-manifest.md

Large diffs are not rendered by default.

94 changes: 94 additions & 0 deletions architecture/adopted-standards-dcm.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# DCM — Adopted External Standards (the DCM-domain requirements)

UDLM defines the **Adopt** disposition: when a credible external standard already models a domain's data
(FOCUS for cost/usage, OpenCost for k8s allocation, OSCAL for compliance, SCIM for identity), the data
substrate carries only *identity*, a *version-pinned conformance reference*, and the *binding* — never
the standard's schema. See UDLM `design-principles/core-tenets.md` **T5** and
`design-principles/adopted-standards.md`.

> **License verdicts & the full adoption ledger live in UDLM** — `registry/standards-adoption-register.md` (what/why/where/when/who + license-compatibility verdict per standard, CI-enforced by ADOPT-001). This document does not restate verdicts; it states the DCM RUNTIME requirements.

That is the **Data** half. This document states the **DCM** half: the requirements DCM must implement
and enable so adopted standards actually work at runtime. It is an application of the
**Data ⇄ Policy boundary** (`data-policy-boundary.md`): **the data declares which standard versions are
in play; DCM (Policy/Provider runtime) negotiates, enforces, and translates between them.**

DCM **MUST** adhere to T5: it does not absorb an external standard's schema into its own persistence,
and does not become the system of record for adopted data — that data is referenced via an Information
Provider, lookup-only (`contracts/information-providers.md`).

> **Scope — Tier 2 only.** These requirements apply to **record/schema** standards (FOCUS, OpenCost,
> OSCAL, SCIM), which version in ways that change their shape. **Value/codelist** standards (ISO 4217,
> ISO 8601, RFC 4122) are adopted as a plain referenced field constraint — *no* support matrix, *no*
> version negotiation, *no* ADS requirements. Route by kind first (UDLM `adopted-standards.md` §1a).

## Requirements (ADS — Adopted Standards)

### Registration & discovery
- **ADS-001 — Provider support matrix.** DCM **MUST** accept and validate a provider's
`adopted_standard_support[]` declaration at registration: for each adopted standard, the supported
version range, a `preferred` version, and `direction` (`emit` | `consume` | `both`). It is validated
and trust-stamped like any other provider capability.
- **ADS-002 — Compatibility discovery.** DCM **MUST** expose, for discovery, which providers can serve
which standard versions, so an implementor can select a compatible provider before binding. Silent
incompatibility is not permitted.

### Negotiation, translation, enforcement (Policy)
- **ADS-003 — Version negotiation.** At binding time DCM **MUST** resolve the intersection of the
consumer/type **required** version range and the provider's **supported** range, selecting the
effective version (highest common, or `preferred` when inside the overlap).
- **ADS-004 — Translation as Policy.** When required and supported do not directly overlap, DCM **MAY**
translate between versions via a **registered, deterministic** mapping — preferably the standard's own
published migration. Translation is a **Policy act** (transformation is Policy, UDLM T2), evaluated and
**audited**; it is never an evaluator embedded in the portable data.
- **ADS-005 — Enforcement / reject.** If there is no compatible version **and** no registered
translation path, DCM **MUST** reject the binding as non-conformant and **surface** it — never
silently drop or downgrade.
- **ADS-006 — Implementor-bounded parameters.** Parameters defined by the standard but constrained by
the implementor (e.g. cost rate ranges, markup minimums, budget ceilings) **MUST** be enforced via
**policy-as-code** (OPA/Rego), not hard-coded — consistent with DCM's policy-governance model.

### Identity, provenance, audit (recording the decision)
- **ADS-007 — Identity join, no ownership.** DCM **MUST** resolve an adopted-standard binding using the
UDLM identity ↔ standard-column join (e.g. resource `uuid` ↔ FOCUS `ResourceId`) and **MUST NOT**
cache or persist the external records as a system of record — the data is served by the Information
Provider with the freshness/authority the IP contract provides
(`contracts/information-providers-advanced.md`).
- **ADS-008 — Effective-version provenance.** DCM **MUST** record the negotiated **effective version**
(and, when it translated, the source version + translation reference) as **provenance** on the
realized entity, and **MUST** lower confidence/authority for translated/derived values.
- **ADS-009 — Auditability.** The negotiation outcome (accept / translate / reject) and any translation
**MUST** be written to the tamper-evident audit log (`AUD-001/002`) as a decision — reproducible from
the immutable record.

### Lifecycle
- **ADS-010 — Standard version lifecycle.** DCM **MUST** track adopted-standard version deprecation and
allow a configured **minimum** and **preferred** version per environment, so an operator can require,
e.g., "FOCUS ≥ 1.3" platform-wide and let negotiation/translation satisfy older providers.

## How this maps to the boundary

| Step | Data (UDLM) — the noun | DCM (Policy/Provider) — the verb |
|---|---|---|
| Provider declares support | `adopted_standard_support[]` record | validate + register (ADS-001) |
| Consumer/type needs a version | `adopts[].version` range | — |
| Pick the version | — | **negotiate** required ∩ supported (ADS-003) |
| Versions don't match | registered migration reference | **translate** (ADS-004) or **reject** (ADS-005) |
| Bind to the resource | identity ↔ standard column | **resolve** join, IP lookup (ADS-007) |
| Record what happened | effective-version provenance slot | **write** provenance + audit (ADS-008/009) |
| Constrain parameters | the declared parameter values | **enforce** via Rego (ADS-006) |

> Test (same as the boundary doc): a **noun** (a support record, a version pin, a join key, a provenance
> slot) is UDLM's; a **verb** (negotiate, translate, enforce, reject, resolve, record) is DCM's.

## Worked example — cost (FOCUS + OpenCost)

The Cost Management Service Provider (`dcm-project/enhancements#57`) is the reference case: it declares
`adopted_standard_support` for FOCUS (`≥1.2 <2.0`, preferred 1.4, emit) and OpenCost (`1.x`); DCM
negotiates against a chargeback view that requires FOCUS ≥ 1.3 (allocation columns); rate ranges and
budgets are enforced by Rego (ADS-006); the effective version is recorded as provenance (ADS-008). The
cost data itself is **never** modeled in DCM/UDLM — it conforms to FOCUS and is served via the SP's
Information-Provider query API. This is what "adopt, don't absorb" looks like end-to-end.

See also: `data-policy-boundary.md`, UDLM `design-principles/adopted-standards.md` (the Data-side
contract), `dcm-platform-requirements.md` (the broader requirement set).
58 changes: 58 additions & 0 deletions architecture/data-policy-boundary.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# DCM ↔ UDLM — the Data / Policy responsibility boundary

DCM and UDLM are two domains separated by one **responsibility boundary** — a service / contract seam.
Getting it right is what keeps the data model portable, auditable, and sovereign, and keeps DCM's logic
where it belongs. This is the DCM-side statement of the boundary defined in UDLM's
`design-principles/core-tenets.md`.

| Domain | Owner | Responsibility |
|---|---|---|
| **Data** | UDLM | Custody of data through its lifecycle: identity, the four states, versioning, relationships, provenance, audit records, sovereignty fields. *Hold, move, reference, version, audit.* |
| **Policy** | **DCM** | **Application of policy** — transformation, enrichment, derivation, decision, governance. *Compute, derive, evaluate, decide, enforce.* |

**UDLM defines the contracts (Data, Provider, and Policy); DCM is where Policy is *applied*.** UDLM
carries the data policy acts on and records the decisions policy makes; it never executes logic. DCM
never becomes the system of record for lifecycle state; it applies logic over UDLM data.

## What DCM owns (the verbs)
- **Assembly** — Intent → Requested: merge Layers (data) under Policy (logic), recording per-field
provenance back into the UDLM record.
- **Policy evaluation** — Validation Policy, Transformation; the **Governance Matrix** and
**sovereignty/accreditation/trust** decisions; placement.
- **Dependency-graph application** — validate the DAG (`RDG-001`), order forward execution, run
compensation in reverse, schedule rehydration in dependency order.
- **Realization** — dispatch to Providers, collect Realized state, run Discovery → drift, resolve
conflicts (field ownership / server-side apply).
- **Audit production** — write the synchronous, append-only, Merkle-chained log (`AUD-001/002`).
- **Adopted-standard runtime** — for externally-adopted standards (FOCUS, OpenCost, OSCAL, SCIM), the
data carries identity + version pins; **DCM negotiates, translates, and enforces standard versions**
and records the effective version as provenance. Full requirements: `adopted-standards-dcm.md`
(`ADS-001…010`); the Data-side contract is UDLM `design-principles/adopted-standards.md` (tenet T5).
- **Enforcement** — reject changes to `immutable`/createOnly fields; reject sovereignty-boundary
violations; reject non-conformant data at the seam.

## What DCM must NOT do (boundary violations)
- Become the durable system of record for lifecycle state — that is UDLM data.
- **Absorb an adopted standard's schema** into DCM persistence, or become the system of record for
adopted data (cost, compliance, identity). That data conforms to its standard and is referenced via an
Information Provider, lookup-only (`adopted-standards-dcm.md`, `ADS-007`).
- Push executable logic *into* the portable data model. UDLM carries **no embedded expression
language**; all transformation/enrichment is DCM policy. This is what makes the contract layer
**deterministic and reproducible** (the precondition for tamper-evident audit and sovereignty):
determinism is structural in the data because the evaluator lives only in DCM.
- Let a runtime decision that legitimately depends on live state (e.g. placement by current capacity)
silently alter the contract. Such decisions are **recorded as decisions in the audit log**, never
written back as if they were the reproducible definition.

## Why the boundary holds the line on the four pillars
- **Audit:** data is immutable + version-pinned (`$id`); DCM produces the proofs. Reproducible forever.
- **Observability:** UDLM declares relationships + typed outputs; DCM reconciles observed vs declared.
- **Dependency graph:** UDLM carries typed edges; DCM constructs/validates/orders the DAG.
- **Sovereignty:** UDLM marks sovereignty fields `immutable` and bundles offline closures; DCM enforces
the Governance Matrix. Because no expression rides in the data, nothing can route around the boundary.

> Test: a **noun** (record, contract, edge, marker, pin) is UDLM's. A **verb** (assemble, evaluate,
> decide, enforce, transform, resolve) is DCM's.

See UDLM `design-principles/core-tenets.md` (T1–T4) and `cross-cutting-requirements.md` for the
substrate side; the Resource Type Registry (`registry/`) is the concrete Data-domain contract DCM applies.
Loading