architecture: control plane - #69
Conversation
35b7937 to
260572e
Compare
|
|
||
| ## 2. Breaking Change Definition | ||
|
|
||
| A change is **breaking** if it requires any existing client to modify its code or configuration to continue working correctly. The following changes are always breaking: |
There was a problem hiding this comment.
This is well known fact, do we need to have it here?
There was a problem hiding this comment.
Will trim — drop the textbook semver preamble and keep only the DCM-specific versioning rules.
| DCM maintains version-compatible with registered OIS versions during the support lifecycle. A DCM instance running OIS v2 must continue to dispatch to providers registered on OIS v1 until the version is sunset. | ||
|
|
||
| When the OIS version is incremented: | ||
| 1. DCM announces the new OIS version via the event `governance.ois_version_released` |
There was a problem hiding this comment.
OIS version update is done via event and the rest of the communication is done via REST calls? Why?
There was a problem hiding this comment.
A new OIS version is a broadcast to all registered providers — one→many, asynchronous — so it's an event (governance.ois_version_released); a REST call would mean DCM polling each provider individually. Per-request dispatch stays REST because it's point-to-point and needs the provider's synchronous realized result. Announcement = fan-out (event); dispatch = request/response (REST). Will state this in the doc.
| Provider API (OIS):https://{dcm-instance}/provider/api/v1/ | ||
| Flow GUI API: https://{dcm-instance}/flow/api/v1/ |
There was a problem hiding this comment.
What is a reason those are separate endpoints?
There was a problem hiding this comment.
They're separate because Consumer / Admin / Provider (OIS) / Flow are distinct trust zones with their own auth + RBAC, and they version independently — the Consumer API can be at v2 while OIS is still v1. Separating the surfaces lets each evolve and be secured on its own. Will document the rationale.
There was a problem hiding this comment.
Following up on my earlier note: that sentence is now in §1.1 — the four surfaces are separate because they're distinct trust zones (Consumer, Admin, Provider/OIS, and Flow each carry their own auth + RBAC, and each versions independently — Consumer at v2 while OIS is still v1). So it's stated in the doc now, not just here.
| When a new major version is released, the previous version enters a **deprecation period**. The deprecation timeline is profile-governed — production deployments require longer support windows than development environments: | ||
|
|
||
| ```yaml | ||
| api_version_support_lifecycle: |
There was a problem hiding this comment.
Can you explain what this means? why there is dev? Why dev needs any deprecation timeline?
There was a problem hiding this comment.
dev surfaces don't need a deprecation window — I'll drop the timeline for dev.
There was a problem hiding this comment.
Done — dev now carries deprecation_notice_period: P0D (no guarantee) and the dev deprecation window is dropped. A dev surface can change without a timeline.
| ### 2.4 Event Routing Model | ||
|
|
||
| ``` | ||
| Event published: { type: "request.initiated", payload: {...}, entity_uuid: X } |
There was a problem hiding this comment.
So policy engine is using event-driven architecture, while the communication with providers is synchronous REST driven? What is a reason behind this?
There was a problem hiding this comment.
Deliberate: policy evaluation is one→many (a request event fans out to all matching policies, plus other subscribers like cost/drift) → event bus; provider dispatch is one→one and needs a synchronous realized result to advance the pipeline → REST. Fan-out/decoupled vs request/response. Will document.
| policies: | ||
| - step: 1 | ||
| handle: "org/policies/cost-check" | ||
| condition: "request.initiated AND resource_type=Compute.VirtualMachine AND tenant.profile=prod" |
There was a problem hiding this comment.
What is:
- request.initiated
- resource_type=
- tenant.profile
Where it's taken from? Who evaluate this object and where those vars are taken? How does the system knows it's a string or a variable?
There was a problem hiding this comment.
That's policy match-condition grammar. I'll document the fields, how variables resolve, and how string-vs-reference is distinguished.
There was a problem hiding this comment.
Done — the match-condition grammar is now documented: the grammar production, how variables resolve, and how a string literal is distinguished from a reference. So request.initiated, resource_type=, and tenant.profile are no longer opaque.
| cost_estimation_request: | ||
| catalog_item_uuid: <uuid> | ||
| assembled_fields: | ||
| cpu_count: 4 | ||
| memory_gb: 8 | ||
| storage_gb: 100 | ||
| tenant_uuid: <uuid> | ||
| requested_duration: P30D # optional; lifecycle estimate | ||
|
|
||
| cost_estimation_response: | ||
| estimated_cost: | ||
| per_hour: 0.32 | ||
| per_month: 230.40 | ||
| lifecycle_estimate: 691.20 # if requested_duration provided | ||
| currency: USD | ||
| confidence: high # high: current Cost Analysis data | ||
| # medium: data > PT1H old | ||
| # low: static fallback | ||
| breakdown: | ||
| - component: compute | ||
| per_hour: 0.28 | ||
| - component: ip_allocation | ||
| per_hour: 0.04 | ||
| cost_data_timestamp: <ISO 8601> |
There was a problem hiding this comment.
We really need to document every attribute of this "object". It's API endpoint etc... same for all other such random yamls in the doc. We need to know what the fields are. Like component: ip_allocation what are the component types, where are they defined. What a breakdown means, nothing is explained here.
There was a problem hiding this comment.
Done — every attribute now has a field reference under that block (component, breakdown, confidence, cost_data_source, and the rest). This was the recurring "document every field" theme across #69/#20, so I did it as one pass — if you spot another inline YAML that still reads as a black box, point me at it and it gets the same treatment.
| on_fail: halt | ||
| - step: 3 | ||
| handle: "org/policies/security-review" | ||
| condition: "always" |
There was a problem hiding this comment.
What is always? Variable, string, reserved word? Can that be documented? If we would implement the engine processing this conditions, we don't know how and what are all the options.
There was a problem hiding this comment.
always is a reserved match-condition keyword. I'll document the reserved words + the condition grammar so it's unambiguous.
There was a problem hiding this comment.
Done — always is now documented as a reserved match-condition keyword (unconditionally true), alongside the other reserved tokens (AND, OR, IN, true, false), so an implementer knows it's not a variable or string.
…y foundational principles (#15) * taxonomy: drop Dynamic Plugin dep; RHDH = one non-required GUI target (dcm-project/dcm #64, pkliczewski) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * taxonomy: consolidate dcm-project/dcm #64 review (pkliczewski) — apply foundational principles - Lifecycle events consumer-neutral: Request Orchestrator routes to ALL subscribers (Policy Engine + cost mgmt + drift), not one engine (principle: consumer-neutral mechanisms; #64 L68). - Add **Placement Policy** (8th typed policy) → answers "what about placement policy?" (L40), references ADR-019. - Trim the UI block to the Unified Shell concept + cross-ref the GUI specs; drop enumerated feature lists + GUI-001–010 detail (principle: right altitude — taxonomy = concept, spec = detail; #64 L183). - RTO/RPO + Dual-Write = standard DR/cutover concepts adopted by reference, keep only DCM-specific targets (don't-redefine-solved-standard gate, T5; #64 L192). - Liveness/readiness = standard k8s probe convention by reference, keep DCM-specific deps (T5; L218). Earlier commit removed the Dynamic-Plugin dependency (rejected upstream; L140). Design-ish items (#69 field docs, dual-write rationale depth) carried to the #163 re-sync. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * generalize homelab name in DISCUSSION-TOPICS (roadfeldt-observability -> a homelab observability stack) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…s) (#20) api-versioning.md: - defer the well-known SemVer baseline (cite semver.org); keep only the DCM-specific application - frame the breaking-change list as DCM's explicit authoritative checklist, not a generic tutorial; call out the DCM-specific entries - dev profile gets no deprecation guarantee (was P60D/P90D) — dev is for iteration, versions can break without a window - §7.2: add the event-vs-REST rationale for OIS version propagation (version/capability change = one-to-many fan-out = event; dispatch = point-to-point = sync REST) components.md: - §2.4: document why policy evaluation is event-driven (fan-out to many policies) but provider dispatch is synchronous REST (point-to-point, result needed to advance) - §2.5: add the match-condition grammar — expression syntax, the `always` reserved keyword, variable-path-by-reference vs literal, unresolved-path semantics - §3.4: add a field reference for the cost estimation/attribution objects Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…(sync) Sync from upstream croadfeldt/dcm. GateKeeper policy type -> Gating Policy (action gatekeep -> gate, op gatekeeping -> gating, enum gatekeeper -> gating). OPA Gatekeeper / Gatekeeper ConstraintTemplate references preserved. Files: architecture/control-plane/api-versioning.md architecture/control-plane/components.md Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Pushed the changes for this PR (synced from the upstream work). api-versioning.md
components.md
Separately, the GateKeeper → Gating Policy rename landed across the spec (the policy type collided with the OPA/Kubernetes Gatekeeper operator) — you'll see it in this and the other slices; the genuine OPA Gatekeeper references are preserved. |
Control-plane components, self-health, internal auth, session revocation, API versioning. Signed-off-by: Chris Roadfeldt <chris@roadfeldt.com> Signed-off-by: croadfeldt <chris@roadfeldt.com>
…(sync) Sync from upstream croadfeldt/dcm. GateKeeper policy type -> Gating Policy (action gatekeep -> gate, op gatekeeping -> gating, enum gatekeeper -> gating). OPA Gatekeeper / Gatekeeper ConstraintTemplate references preserved. Files: architecture/control-plane/api-versioning.md architecture/control-plane/components.md Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: croadfeldt <chris@roadfeldt.com>
5748f1f to
f3abf62
Compare
9a014c8 to
f3abf62
Compare
api-versioning.md: - defer the well-known SemVer baseline (cite semver.org); keep only the DCM-specific application - frame the breaking-change list as DCM's explicit authoritative checklist, not a generic tutorial; call out the DCM-specific entries - dev profile gets no deprecation guarantee (was P60D/P90D) — dev is for iteration, versions can break without a window - §7.2: add the event-vs-REST rationale for OIS version propagation (version/capability change = one-to-many fan-out = event; dispatch = point-to-point = sync REST) components.md: - §2.4: document why policy evaluation is event-driven (fan-out to many policies) but provider dispatch is synchronous REST (point-to-point, result needed to advance) - §2.5: add the match-condition grammar — expression syntax, the `always` reserved keyword, variable-path-by-reference vs literal, unresolved-path semantics - §3.4: add a field reference for the cost estimation/attribution objects Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Thanks @machacekondra — captured, not closed. Superseded by the ordered, scoped set (#109–#117), tracked in #108; your feedback carries forward as CF-9 (control-plane doc rigor — document every field, state the event-vs-REST rationale). See #108; please re-review on the new set. |
Decision: Control-plane components, self-health, internal auth, session revocation, API versioning.
Part of the staged
croadfeldt/dcm→dcm-project/dcmupstreaming: single-concern PRs, ≤3k lines, logical boundaries. (2430 lines, 5 files.)Draft — pending team re-engagement.