341 lines
19 KiB
Text
341 lines
19 KiB
Text
|
|
let m = import "ontology/defaults/manifest.ncl" in
|
||
|
|
|
||
|
|
m.make_manifest {
|
||
|
|
project = "provisioning",
|
||
|
|
repo_kind = 'Mixed,
|
||
|
|
|
||
|
|
description = "Multi-crate Rust platform for cloud infrastructure provisioning: typed Nickel schemas validated at the NCL layer, formula DAG execution engine, SOLID-enforced service boundaries, pluggable providers and taskservs, NATS-brokered orchestration, Cedar authorization, and full-architecture solo mode for single-operator deployments.",
|
||
|
|
|
||
|
|
consumption_modes = [
|
||
|
|
m.make_consumption_mode {
|
||
|
|
consumer = 'Developer,
|
||
|
|
needs = ['OntologyExport],
|
||
|
|
audit_level = 'Standard,
|
||
|
|
description = "Uses provisioning CLI and workspace definitions to manage infrastructure. Extends via providers and taskservs.",
|
||
|
|
},
|
||
|
|
m.make_consumption_mode {
|
||
|
|
consumer = 'Agent,
|
||
|
|
needs = ['OntologyExport, 'JsonSchema],
|
||
|
|
audit_level = 'Quick,
|
||
|
|
description = "Reads .ontology/core.ncl to understand constraints and boundaries. Uses CLI and orchestrator APIs for infrastructure operations.",
|
||
|
|
},
|
||
|
|
],
|
||
|
|
|
||
|
|
layers = [
|
||
|
|
m.make_layer {
|
||
|
|
id = "schemas",
|
||
|
|
paths = ["schemas/"],
|
||
|
|
committed = true,
|
||
|
|
description = "Nickel type schemas for all infrastructure configuration: providers, workspaces, platform services, extensions.",
|
||
|
|
},
|
||
|
|
m.make_layer {
|
||
|
|
id = "core",
|
||
|
|
paths = ["core/"],
|
||
|
|
committed = true,
|
||
|
|
description = "CLI, libraries, plugins, Nushell scripts — the user-facing surface of provisioning.",
|
||
|
|
},
|
||
|
|
m.make_layer {
|
||
|
|
id = "platform",
|
||
|
|
paths = ["platform/"],
|
||
|
|
committed = true,
|
||
|
|
description = "Orchestrator, Control Center, Vault, Extension Registry — the control plane services.",
|
||
|
|
},
|
||
|
|
m.make_layer {
|
||
|
|
id = "catalog",
|
||
|
|
paths = ["catalog/"],
|
||
|
|
committed = true,
|
||
|
|
description = "Providers, taskservs, clusters, components, domain artifacts — IaC building block catalog and federated integration domain contracts.",
|
||
|
|
},
|
||
|
|
m.make_layer {
|
||
|
|
id = "config",
|
||
|
|
paths = ["config/", "templates/"],
|
||
|
|
committed = true,
|
||
|
|
description = "Default configuration files and infrastructure templates.",
|
||
|
|
},
|
||
|
|
m.make_layer {
|
||
|
|
id = "self-description",
|
||
|
|
paths = [".ontology/"],
|
||
|
|
committed = true,
|
||
|
|
description = "Provisioning consuming on+re: axioms, tensions, practices, state, gates, ADRs.",
|
||
|
|
},
|
||
|
|
],
|
||
|
|
|
||
|
|
operational_modes = [
|
||
|
|
m.make_op_mode {
|
||
|
|
id = "dev",
|
||
|
|
visible_layers = ["schemas", "core", "platform", "catalog", "config", "self-description"],
|
||
|
|
description = "Full development view — all layers visible.",
|
||
|
|
},
|
||
|
|
m.make_op_mode {
|
||
|
|
id = "platform-focus",
|
||
|
|
visible_layers = ["schemas", "platform", "config"],
|
||
|
|
description = "Platform engineering focus — schemas, platform services, and configuration.",
|
||
|
|
},
|
||
|
|
m.make_op_mode {
|
||
|
|
id = "catalog-focus",
|
||
|
|
visible_layers = ["schemas", "catalog", "config"],
|
||
|
|
description = "Catalog development focus — schemas, providers, taskservs, components, and configuration.",
|
||
|
|
},
|
||
|
|
],
|
||
|
|
|
||
|
|
config_surface = m.make_config_surface {
|
||
|
|
config_root = ".typedialog/provisioning/",
|
||
|
|
entry_point = "config.ncl",
|
||
|
|
kind = 'TypeDialog,
|
||
|
|
contracts_path = ".typedialog/provisioning/schemas",
|
||
|
|
overrides_dir = ".typedialog/provisioning/generated",
|
||
|
|
sections = [
|
||
|
|
m.make_config_section {
|
||
|
|
id = "provisioning",
|
||
|
|
file = "config.ncl",
|
||
|
|
contract = "schemas/provisioning-config.ncl",
|
||
|
|
description = "Root workspace configuration generated by TypeDialog — project metadata, services, database, deployment target, network, storage, monitoring, security.",
|
||
|
|
rationale = "Consumer projects declare what infrastructure they need via an interactive TypeDialog form. The NCL output is the single source of truth fed to the orchestrator. TypeDialog fragments (database-postgres, deployment-k8s, etc.) ensure only valid combinations are generated.",
|
||
|
|
mutable = true,
|
||
|
|
consumers = [
|
||
|
|
m.make_config_consumer { id = "orchestrator", kind = 'RustStruct, ref = "provisioning_orchestrator::config::OrchestratorConfig", fields = ["services", "deployment", "database"] },
|
||
|
|
m.make_config_consumer { id = "configure-nu", kind = 'NuScript, ref = ".typedialog/provisioning/configure.nu" },
|
||
|
|
m.make_config_consumer { id = "ci-woodpecker", kind = 'CiPipeline, ref = ".woodpecker/ci.yml" },
|
||
|
|
],
|
||
|
|
},
|
||
|
|
m.make_config_section {
|
||
|
|
id = "database",
|
||
|
|
file = "schemas/database.ncl",
|
||
|
|
contract = "schemas/database.ncl",
|
||
|
|
description = "Database type and connection parameters — supports sqlite, postgres, surrealdb, mysql. Generated into the root config via TypeDialog database-* fragments.",
|
||
|
|
rationale = "Database configuration is the most provider-specific section. TypeDialog fragments enforce valid parameter combinations per engine (e.g. journal_mode only valid for SQLite).",
|
||
|
|
mutable = false,
|
||
|
|
consumers = [
|
||
|
|
m.make_config_consumer { id = "orchestrator", kind = 'RustStruct, ref = "provisioning_orchestrator::config::OrchestratorConfig", fields = ["database"] },
|
||
|
|
],
|
||
|
|
},
|
||
|
|
m.make_config_section {
|
||
|
|
id = "deployment",
|
||
|
|
file = "schemas/deployment.ncl",
|
||
|
|
contract = "schemas/deployment.ncl",
|
||
|
|
description = "Deployment target — docker-compose or kubernetes. Drives which taskservs are activated and which providers are called.",
|
||
|
|
rationale = "Deployment target selection is the primary branching decision in workspace execution. TypeDialog deployment-docker and deployment-k8s fragments capture the full parameter space for each target.",
|
||
|
|
mutable = false,
|
||
|
|
consumers = [
|
||
|
|
m.make_config_consumer { id = "orchestrator", kind = 'RustStruct, ref = "provisioning_orchestrator::config::OrchestratorConfig", fields = ["deployment"] },
|
||
|
|
],
|
||
|
|
},
|
||
|
|
m.make_config_section {
|
||
|
|
id = "monitoring",
|
||
|
|
file = "schemas/monitoring.ncl",
|
||
|
|
contract = "schemas/monitoring.ncl",
|
||
|
|
description = "Observability configuration — metrics, logging, alerting. Optional; defaults from .typedialog/provisioning/defaults/monitoring-defaults.ncl.",
|
||
|
|
mutable = false,
|
||
|
|
consumers = [
|
||
|
|
m.make_config_consumer { id = "orchestrator", kind = 'RustStruct, ref = "provisioning_orchestrator::config::OrchestratorConfig", fields = ["monitoring"] },
|
||
|
|
],
|
||
|
|
},
|
||
|
|
],
|
||
|
|
},
|
||
|
|
|
||
|
|
capabilities = [
|
||
|
|
m.make_capability {
|
||
|
|
id = "formula-dag-execution",
|
||
|
|
name = "Formula DAG Execution Engine",
|
||
|
|
summary = "Typed DAG-based workflow execution with topological parallelism, retry, and rollback.",
|
||
|
|
rationale = "Positional task arrays collapse on dependency ambiguity and lack parallelism signals. Formula nodes declare depends_on, on_error, parallel, max_retries — enabling the orchestrator to derive a topological execution plan without imperative scripting.",
|
||
|
|
how = "Workspace TOML declares Formula nodes; orchestrator's formula.rs converts to DependencyGraph via topological sort; BatchExecutor executes ready nodes in parallel via NATS work queues.",
|
||
|
|
artifacts = ["schemas/lib/formula.ncl", "platform/crates/orchestrator/src/formula.rs", "platform/crates/orchestrator/src/batch.rs"],
|
||
|
|
adrs = ["adr-016-workspace-formula-dag"],
|
||
|
|
nodes = ["formula-dag-execution"],
|
||
|
|
},
|
||
|
|
m.make_capability {
|
||
|
|
id = "workspace-contract",
|
||
|
|
name = "Typed Workspace Contracts",
|
||
|
|
summary = "Nickel-validated workspace definitions that compose providers, taskservs, and ingredients into infrastructure DAGs.",
|
||
|
|
rationale = "Raw TOML workspace files have no type safety — invalid configs surface as runtime errors. Nickel schemas catch structural errors at write time, before any provider API is called.",
|
||
|
|
how = "CLI validates workspace TOML against schemas/config/workspace_config/ contracts via nickel export before submitting to orchestrator. Orchestrator re-validates on receipt.",
|
||
|
|
artifacts = ["schemas/config/workspace_config/", "core/crates/", "examples/workspaces/"],
|
||
|
|
nodes = ["workspace-contract"],
|
||
|
|
},
|
||
|
|
m.make_capability {
|
||
|
|
id = "provider-plugin-system",
|
||
|
|
name = "Provider Plugin System",
|
||
|
|
summary = "25-function pluggable interface for infrastructure providers — add a provider without changing the platform.",
|
||
|
|
rationale = "Hardcoded provider logic makes multi-cloud support a fork, not an extension. The provider interface isolates provider specifics behind a stable contract.",
|
||
|
|
how = "Each provider implements the ProviderInterface trait (25 functions). Orchestrator dispatches operations via the interface; provider implementations are loaded from catalog/providers/.",
|
||
|
|
artifacts = ["catalog/providers/", "platform/crates/orchestrator/src/"],
|
||
|
|
nodes = ["provider-abstraction", "taskserv-pattern"],
|
||
|
|
},
|
||
|
|
m.make_capability {
|
||
|
|
id = "solo-mode-deployment",
|
||
|
|
name = "Solo Mode — Full-Architecture Single-Operator Deployment",
|
||
|
|
summary = "Run the full platform on a laptop: embedded SurrealDB (RocksDB), child NATS server, solo_auth_middleware replacing JWT+Cedar.",
|
||
|
|
rationale = "Simplified mono-binary for solo creates two divergent code paths. Solo mode keeps the same binaries and NATS subjects — scripts written for solo work in multi-user unchanged.",
|
||
|
|
how = "--mode solo flag activates solo_auth_middleware (auto-injects admin session), SurrealDB switches to kv-surrealkv (RocksDB), NATS starts as child process. service-manager.nu orchestrates startup.",
|
||
|
|
artifacts = ["platform/crates/control-center/src/middleware/", "platform/crates/orchestrator/src/nats.rs"],
|
||
|
|
adrs = ["adr-015-solo-mode-architecture"],
|
||
|
|
nodes = ["solo-mode"],
|
||
|
|
},
|
||
|
|
m.make_capability {
|
||
|
|
id = "nats-brokered-orchestration",
|
||
|
|
name = "NATS JetStream Orchestration",
|
||
|
|
summary = "All inter-service task dispatch via NATS JetStream work queues with at-least-once delivery and state machine tracking.",
|
||
|
|
rationale = "HTTP synchronous task dispatch couples orchestrator latency to provider API latency. NATS decouples dispatch from execution, enables fan-out to taskserv workers, and provides durable state even if a worker crashes mid-task.",
|
||
|
|
how = "Orchestrator publishes tasks to JetStream streams per provider type. Taskserv workers consume via pull consumers with ack/nack. Task state machine tracks pending → running → completed/failed in SurrealDB.",
|
||
|
|
artifacts = ["platform/crates/orchestrator/src/workflow.rs", "platform/crates/platform-nats/"],
|
||
|
|
adrs = ["adr-012-nats-event-broker"],
|
||
|
|
nodes = ["platform-dispatch"],
|
||
|
|
},
|
||
|
|
m.make_capability {
|
||
|
|
id = "nickel-config-hierarchy",
|
||
|
|
name = "Nickel-Validated Configuration Hierarchy",
|
||
|
|
summary = "5-level config precedence with NCL contracts: runtime args > env vars > user config > infra config > system defaults.",
|
||
|
|
rationale = "Ad-hoc env var overrides without schema validation cause silent misconfiguration. The Nickel merge layer validates every override level against the same contracts before deserialization.",
|
||
|
|
how = "platform-config's ConfigLoader trait runs collect_env_overrides() → nickel export → serde::Deserialize. Override files are written to config/*.overrides.ncl and merged via & at the entry point.",
|
||
|
|
artifacts = ["platform/crates/platform-config/src/format.rs", "schemas/config/"],
|
||
|
|
adrs = ["adr-013-surrealdb-global-store"],
|
||
|
|
nodes = ["config-hierarchy", "type-safety-nickel"],
|
||
|
|
},
|
||
|
|
m.make_capability {
|
||
|
|
id = "solid-enforcement",
|
||
|
|
name = "SOLID Boundary Enforcement",
|
||
|
|
summary = "6 compile-time and runtime SOLID boundaries: orchestrator-only provider calls, control-center-only auth, vault-only secrets.",
|
||
|
|
rationale = "Without enforced boundaries, authorization and secrets logic diffuses across services. ADR-014 documents 6 hard boundaries with 6 enforcement layers (compile-time, dev-time, pre-commit, CI, runtime, audit).",
|
||
|
|
how = "Clippy rules, grep CI checks, Cedar policies, and runtime middleware enforce the boundaries. solo_auth_middleware is the only documented auth bypass and requires --mode solo.",
|
||
|
|
artifacts = ["platform/crates/orchestrator/", "platform/crates/control-center/", "platform/secretumvault/"],
|
||
|
|
adrs = ["adr-014-solid-enforcement"],
|
||
|
|
nodes = ["solid-boundaries"],
|
||
|
|
},
|
||
|
|
],
|
||
|
|
|
||
|
|
requirements = [
|
||
|
|
m.make_requirement {
|
||
|
|
id = "rust",
|
||
|
|
name = "Rust toolchain",
|
||
|
|
kind = 'Tool,
|
||
|
|
env = 'Development,
|
||
|
|
version = "1.75+",
|
||
|
|
impact = "Platform services and CLI cannot compile.",
|
||
|
|
provision = "rustup toolchain install stable",
|
||
|
|
},
|
||
|
|
m.make_requirement {
|
||
|
|
id = "nushell",
|
||
|
|
name = "Nushell",
|
||
|
|
kind = 'Tool,
|
||
|
|
env = 'Both,
|
||
|
|
version = "0.110+",
|
||
|
|
impact = "Reflection modes, service-manager.nu, and CLI scripts cannot execute.",
|
||
|
|
provision = "cargo install nu",
|
||
|
|
},
|
||
|
|
m.make_requirement {
|
||
|
|
id = "nickel",
|
||
|
|
name = "Nickel",
|
||
|
|
kind = 'Tool,
|
||
|
|
env = 'Both,
|
||
|
|
version = "1.15+",
|
||
|
|
impact = "Schema validation and config export cannot run. platform-config's ConfigLoader cannot operate.",
|
||
|
|
provision = "cargo install nickel-lang-cli",
|
||
|
|
},
|
||
|
|
m.make_requirement {
|
||
|
|
id = "surrealdb",
|
||
|
|
name = "SurrealDB",
|
||
|
|
kind = 'Service,
|
||
|
|
env = 'Production,
|
||
|
|
version = "2.3+",
|
||
|
|
required = false,
|
||
|
|
impact = "Multi-user deployments cannot persist task state, Cedar policies, or audit logs. Solo mode uses embedded RocksDB.",
|
||
|
|
provision = "Deploy surrealdb container or binary; solo mode uses kv-surrealkv.",
|
||
|
|
},
|
||
|
|
m.make_requirement {
|
||
|
|
id = "nats-server",
|
||
|
|
name = "NATS Server (JetStream)",
|
||
|
|
kind = 'Service,
|
||
|
|
env = 'Both,
|
||
|
|
impact = "Orchestrator cannot dispatch tasks; taskserv workers cannot receive work items. Solo mode manages nats-server as a child process.",
|
||
|
|
provision = "Install nats-server in PATH for solo mode; deploy NATS cluster for multi-user.",
|
||
|
|
},
|
||
|
|
m.make_requirement {
|
||
|
|
id = "cedar-policy",
|
||
|
|
name = "Cedar policy engine",
|
||
|
|
kind = 'Infrastructure,
|
||
|
|
env = 'Production,
|
||
|
|
required = false,
|
||
|
|
impact = "Cedar-based authorization unavailable in multi-user mode. Solo mode uses solo_auth_middleware which bypasses Cedar entirely.",
|
||
|
|
provision = "Policies stored in SurrealDB; loaded by control-center at startup.",
|
||
|
|
},
|
||
|
|
],
|
||
|
|
|
||
|
|
critical_deps = [
|
||
|
|
m.make_critical_dep {
|
||
|
|
id = "surrealdb-crate",
|
||
|
|
name = "SurrealDB client crate",
|
||
|
|
ref = "surrealdb@3",
|
||
|
|
used_for = "Task state machine persistence, Cedar policy storage, audit log, workspace history.",
|
||
|
|
failure_impact = "All stateful operations (task tracking, policy evaluation, audit) stop. Solo mode continues via kv-surrealkv but loses SurrealDB WS protocol.",
|
||
|
|
mitigation = "Feature-gated: --no-default-features disables SurrealDB for dev builds. Solo mode uses embedded kv-surrealkv (RocksDB).",
|
||
|
|
},
|
||
|
|
m.make_critical_dep {
|
||
|
|
id = "async-nats",
|
||
|
|
name = "async-nats",
|
||
|
|
ref = "async-nats@0.46",
|
||
|
|
used_for = "All inter-service task dispatch, NATS JetStream work queues, taskserv worker consumers.",
|
||
|
|
failure_impact = "Orchestrator cannot dispatch workflows; taskserv workers go idle. Solo mode manages nats-server as child — child crash is fatal.",
|
||
|
|
mitigation = "Feature-gated via platform-nats crate. Solo mode restarts nats-server on SIGTERM.",
|
||
|
|
},
|
||
|
|
m.make_critical_dep {
|
||
|
|
id = "cedar-policy-crate",
|
||
|
|
name = "cedar-policy",
|
||
|
|
ref = "cedar-policy@4.8",
|
||
|
|
used_for = "Authorization decisions in control-center: policy evaluation, RBAC, resource-level access control.",
|
||
|
|
failure_impact = "All authorization decisions in multi-user mode fail closed. Solo mode unaffected (solo_auth_middleware bypasses Cedar).",
|
||
|
|
mitigation = "Compile-time link; no runtime loading. cedar-policy is the Cedar Reference Implementation — stable API surface.",
|
||
|
|
},
|
||
|
|
m.make_critical_dep {
|
||
|
|
id = "secretumvault",
|
||
|
|
name = "secretumvault",
|
||
|
|
ref = "secretumvault (local path ../../../Development/secretumvault)",
|
||
|
|
used_for = "Secrets management: age key management, Shamir threshold unsealing, secret storage for provider credentials.",
|
||
|
|
failure_impact = "Vault service cannot start; provider credential injection fails. All infrastructure operations that require provider API keys stop.",
|
||
|
|
mitigation = "Local path dependency — pinned to checkout. Solo mode uses filesystem backend (age key).",
|
||
|
|
},
|
||
|
|
m.make_critical_dep {
|
||
|
|
id = "axum",
|
||
|
|
name = "axum",
|
||
|
|
ref = "axum@0.8",
|
||
|
|
used_for = "HTTP API layer for orchestrator, control-center, extension-registry, ai-service, mcp-server.",
|
||
|
|
failure_impact = "All HTTP API surfaces become unavailable. CLI falls back to NATS direct where supported.",
|
||
|
|
mitigation = "axum@0.8 is maintained by the Tokio project; API stability is high.",
|
||
|
|
},
|
||
|
|
],
|
||
|
|
|
||
|
|
domain_provides = {
|
||
|
|
id = "provisioning-platform",
|
||
|
|
name = "Provisioning Platform",
|
||
|
|
schema_path = "reflection/schemas/",
|
||
|
|
impl_repo_kind = "DevWorkspace",
|
||
|
|
kind = 'Implicit,
|
||
|
|
description = "Workspace infrastructure contracts: cluster topology, state dimensions, gate membranes, and operational modes for DevWorkspace projects.",
|
||
|
|
},
|
||
|
|
|
||
|
|
registry_provides = m.make_registry_provides {
|
||
|
|
participant = "provisioning",
|
||
|
|
registries = m.make_registries_config {
|
||
|
|
default = "primary",
|
||
|
|
registries = [
|
||
|
|
m.make_registry_entry {
|
||
|
|
id = "primary",
|
||
|
|
endpoint = "reg.librecloud.online",
|
||
|
|
role = 'primary,
|
||
|
|
tls = true,
|
||
|
|
namespaces = {
|
||
|
|
own = ["domains/provisioning/", "modes/provisioning/"],
|
||
|
|
prefixes = ["domains/provisioning/", "modes/provisioning/"],
|
||
|
|
},
|
||
|
|
},
|
||
|
|
],
|
||
|
|
},
|
||
|
|
},
|
||
|
|
|
||
|
|
level = {
|
||
|
|
index = 'Domain,
|
||
|
|
name = "provisioning-domain",
|
||
|
|
parent = "ontoref-base",
|
||
|
|
},
|
||
|
|
}
|