chore: add ontology reflection

This commit is contained in:
Jesús Pérez 2026-05-12 02:40:14 +01:00
parent 0d202708b9
commit 30c7afbc95
Signed by: jesus
GPG key ID: 9F243E355E0BC939
385 changed files with 4038 additions and 84826 deletions

View file

@ -64,6 +64,18 @@ offline = false
# Strict version requirements for dependencies
# force-non-semver-pre = true
[profile.ci-test]
# Pre-commit: no debug info, no incremental — shared .rlib between test + docs hooks
inherits = "test"
debug = 0
incremental = false
[profile.ci]
# CI pipeline: line-tables-only for actionable backtraces on remote failures
inherits = "test"
debug = "line-tables-only"
incremental = false
[alias]
# Custom cargo commands
build-all = "build --all-targets"

9
.gitignore vendored
View file

@ -7,6 +7,7 @@
kcl
*.k
old_config
rollback_instructions*
docs/book
@ -107,6 +108,10 @@ platform/*/config.local.*
**/output/
!**/output/.gitkeep
# Generated Dockerfiles (source of truth = Nickel templates)
platform/crates/*/Dockerfile
docker-compose.build.yml
# === TEMPORARY & BACKUP FILES ===
*.bak
*.backup
@ -123,6 +128,9 @@ platform/*/config.local.*
.zed/
.coder/
.claude/
.opencode
.openpackage
.AGENTS.md
.migration/
#.shellcheckrc
.DS_Store
@ -184,3 +192,4 @@ test-logs/
# ============================================================================
# End of .gitignore model
# ============================================================================
.aider*

37
.ontology/connections.ncl Normal file
View file

@ -0,0 +1,37 @@
let s = import "reflection/schemas/connections.ncl" in
{
upstream = [
{
project = "ontoref",
kind = 'LibraryDependency,
node = "protocol-as-standalone",
via = "local",
note = "Ontoref protocol: .ontology/ schemas, ADR lifecycle, reflection modes, daemon sync.",
},
{
project = "stratumiops",
kind = 'LibraryDependency,
node = "",
via = "local",
note = "stratum-graph, stratum-state, platform-nats, platform-db used by orchestrator and platform services.",
},
{
project = "secretumvault",
kind = 'LibraryDependency,
node = "",
via = "local",
note = "Embedded in platform/secretumvault — Vault service for secrets management. Local age key in solo mode, Shamir threshold in multi-user.",
},
],
downstream = [
{
project = "ontoref",
kind = 'CoDeveloped,
node = "dag-visualization",
via = "dag-ui",
note = "Provisioning DAG graph exposed to ontoref-daemon as a DagGraphProvider plugin. Co-developed: provisioning emits structured DAG events on provisioning.dag.>; ontoref-daemon consumes and visualizes them.",
},
],
peers = [],
} | s.Connections

633
.ontology/core.ncl Normal file
View file

@ -0,0 +1,633 @@
let d = import "ontology/defaults/core.ncl" in
{
nodes = [
# ── Axioms (invariant = true) ─────────────────────────────────────────────
d.make_node {
id = "config-driven-always",
name = "Config-Driven Always",
pole = 'Yang,
level = 'Axiom,
description = "Never hardcoded, always configuration. Runtime args > env > user config > infra config > defaults. TOML/YAML are output formats, never source of truth.",
invariant = true,
artifact_paths = ["config/", "schemas/config/"],
},
d.make_node {
id = "type-safety-nickel",
name = "Type Safety via Nickel",
pole = 'Yang,
level = 'Axiom,
description = "Nickel schemas for all infrastructure configuration. TOML/YAML are generated output, never source of truth. Every config change is validated at the schema level before reaching runtime.",
invariant = true,
artifact_paths = ["schemas/"],
},
d.make_node {
id = "solid-boundaries",
name = "SOLID Architecture Boundaries",
pole = 'Yang,
level = 'Axiom,
description = "6 hard boundaries with 6 layers of enforcement. Orchestrator ONLY does provider APIs + SSH. Auth decisions ONLY in Control Center. Secrets ONLY via Vault. Violations caught at compile-time, dev-time, pre-commit, CI, runtime, and audit.",
invariant = true,
artifact_paths = ["platform/crates/orchestrator/", "platform/crates/control-center/", "platform/secretumvault/"],
},
d.make_node {
id = "provider-abstraction",
name = "Provider Abstraction",
pole = 'Yang,
level = 'Axiom,
description = "Providers as pluggable interface of 25 functions. New provider = implement interface, not change platform. Provider implementations are isolated in catalog/providers/.",
invariant = true,
artifact_paths = ["catalog/providers/"],
},
# ── Tensions ──────────────────────────────────────────────────────────────
d.make_node {
id = "nickel-complexity-vs-accessibility",
name = "Nickel Complexity vs Accessibility",
pole = 'Spiral,
level = 'Tension,
description = "Richer Nickel schemas provide better validation and safety but increase the barrier of entry for contributors. The balance: compose pattern over merge operator, progressive schema layers.",
},
d.make_node {
id = "monorepo-vs-split",
name = "Monorepo vs Split Repos",
pole = 'Spiral,
level = 'Tension,
description = "Everything in one repo simplifies development and cross-cutting changes but complicates CI, ownership boundaries, and workspace isolation.",
},
d.make_node {
id = "centralized-vs-scripted",
name = "Centralized Orchestration vs Scripts",
pole = 'Spiral,
level = 'Tension,
description = "Orchestrator provides audit trail, rollback, and state machine but adds complexity vs direct provider scripts. Solo mode mitigates by keeping full architecture with relaxed auth.",
},
d.make_node {
id = "extension-graph-vs-declarative-config",
name = "Extension Ontology vs Pure Config",
pole = 'Spiral,
level = 'Tension,
description = "The planned extension to embed ontology nodes in metadata.ncl makes extensions graph-aware but blurs the line between configuration and code. Simple extensions should remain pure config; only extensions with non-trivial platform relationships should declare ontology nodes. The resolution: ontology fields in metadata.ncl are optional and additive — the base metadata contract stays simple.",
},
d.make_node {
id = "nushell-vs-rust-boundary",
name = "Nushell Library Boundary vs Rust Platform",
pole = 'Spiral,
level = 'Tension,
description = "The Nushell CLI library (core/nulib/) grows to cover operations that could be in Rust platform crates. Moving logic to Rust improves type safety and testability; keeping it in Nushell keeps it operator-scriptable and writable without recompilation. Partial resolution via smart-interface-unification (ADR-029): Rust owns the Registry and all Tool dispatch semantics; Nushell owns orchestration sequences, the three-tier fallback probe chain, and the required legacy closure per operation. The boundary is now structural — operations cross it via tool-call, not via direct Nushell reimplementation.",
},
# ── Practices ─────────────────────────────────────────────────────────────
d.make_node {
id = "nushell-cli-library",
name = "Nushell CLI Library",
pole = 'Yang,
level = 'Practice,
description = "The primary user-facing command surface — 60+ Nushell modules in core/nulib/ covering all platform operations: server/cluster/taskserv/workspace lifecycle, batch ops, provider discovery, extension loading, orchestrator integration, AI tooling, secrets, observability. The CLI composes nulib modules; the library consumes platform APIs and extension metadata.",
artifact_paths = ["core/nulib/", "core/nulib/main_provisioning/", "core/nulib/lib_provisioning/"],
},
d.make_node {
id = "extension-metadata-contract",
name = "Extension Metadata Contract",
pole = 'Yin,
level = 'Practice,
description = "Every extension (taskserv, provider, cluster) declares a metadata.ncl: name, version, category, description, typed dependencies, tags, and best_practices references. This contract is the machine-readable extension interface consumed by the CLI loader, schema validator, and orchestrator dependency resolver. Future: metadata.ncl will also declare ontology nodes, connecting extension capabilities to the platform DAG.",
artifact_paths = ["catalog/taskservs/*/metadata.ncl", "catalog/providers/*/", "catalog/clusters/"],
},
d.make_node {
id = "taskserv-dependency-dag",
name = "Taskserv Dependency DAG",
pole = 'Yang,
level = 'Practice,
description = "Taskservs form a typed dependency DAG via their metadata.ncl `dependencies` field. Execution order: infrastructure → networking/storage → container_runtime → kubernetes/databases/development → applications. The orchestrator resolves this DAG before building the formula execution plan — no taskserv executes before its declared dependencies complete.",
artifact_paths = ["catalog/taskservs/", "platform/crates/orchestrator/src/formula.rs"],
},
d.make_node {
id = "taskserv-pattern",
name = "TaskServ Pattern",
pole = 'Yang,
level = 'Practice,
description = "Extensions that serve infrastructure tasks — each taskserv declares dependencies, capabilities, and contracts. They consume workspace config and produce infrastructure operations. 10 built-in taskservs: infrastructure, networking, storage, container_runtime, kubernetes, databases, applications, development, cluster, misc.",
artifact_paths = ["catalog/taskservs/"],
},
d.make_node {
id = "workspace-layer-resolution",
name = "Workspace Layer Resolution",
pole = 'Yin,
level = 'Practice,
description = "Three-tier priority system for workspace configuration composition: Core Layer (Priority 100, catalog/) → Workspace Templates (Priority 200, workspace/templates/) → Infrastructure-Specific (Priority 300, workspace/infra/{name}/). Higher priority overrides lower. Enables shared patterns to be extracted to templates while infrastructure-specific concerns stay local.",
artifact_paths = ["workspace/layers/", "workspace/templates/", "workspace/registry/"],
},
d.make_node {
id = "workspace-as-implementation-plan",
name = "Workspace as Implementation Plan",
pole = 'Yin,
level = 'Practice,
description = "A workspace IS the implementation plan. It declares the complete typed composition: which providers, which taskservs with their dependencies, which formula DAG nodes, which clusters. The platform validates the composition against schemas and resolves the execution plan from it — no imperative scripting. Workspaces make infrastructure intent explicit and auditable.",
artifact_paths = ["workspace/templates/", "examples/workspaces/", "schemas/config/workspace_config/"],
},
d.make_node {
id = "workspace-contract",
name = "Workspace Contract",
pole = 'Yin,
level = 'Practice,
description = "Workspaces are typed compositions of ingredients in DAGs. Each workspace declares what it needs via Nickel schemas; the platform validates and provisions accordingly.",
artifact_paths = ["schemas/config/workspace_config/"],
},
d.make_node {
id = "platform-dispatch",
name = "Platform Dispatch Model",
pole = 'Yang,
level = 'Practice,
description = "Orchestrator dispatches tasks via NATS work queues, maintains state machine per task, and provides rollback capability. All provider API calls flow through this single dispatch point.",
artifact_paths = ["platform/crates/orchestrator/src/workflow.rs", "platform/crates/orchestrator/src/batch.rs"],
},
d.make_node {
id = "config-hierarchy",
name = "Configuration Hierarchy",
pole = 'Yin,
level = 'Practice,
description = "5-level config precedence: Runtime args > env vars > user config > infra config > system defaults. Implemented via Nickel schema composition and Nushell config loading.",
artifact_paths = ["schemas/config/", "config/config.defaults.toml"],
},
d.make_node {
id = "formula-dag-execution",
name = "Formula DAG Execution",
pole = 'Yang,
level = 'Practice,
description = "Workspace taskserv execution modeled as typed DAGs. Formulas replace positional arrays: each node declares depends_on, on_error, parallel, max_retries. Orchestrator converts via formula.rs into DependencyGraph for topological parallel execution.",
artifact_paths = ["schemas/lib/formula.ncl", "platform/crates/orchestrator/src/formula.rs"],
},
d.make_node {
id = "solo-mode",
name = "Solo Mode Architecture",
pole = 'Yin,
level = 'Practice,
description = "Full platform architecture with relaxed auth — solo_auth_middleware replaces JWT+Cedar, injecting a fixed admin session gated behind --mode solo runtime flag. Same binaries, same NATS subjects, same SurrealDB schema. SurrealDB uses embedded RocksDB, NATS runs as child process. Enables single-operator deployments and CI integration tests without external infrastructure.",
artifact_paths = ["platform/crates/control-center/src/middleware/", "platform/crates/orchestrator/src/nats.rs"],
},
# ── Smart Interface Unification (ADR-029) ────────────────────────────────
d.make_node {
id = "provisioning-registry",
name = "Provisioning Core Registry",
pole = 'Yang,
level = 'Practice,
description = "provisioning-core::Registry is the shared dispatch table for all 37 Tool implementations. Every surface (CLI binary, HTTP daemon, MCP server) must invoke operations through Registry::invoke — no surface may bypass it with direct tool instantiation. This structural constraint is the mechanism that makes semantic parity across surfaces a compile-time guarantee rather than a convention.",
artifact_paths = ["platform/crates/provisioning-core/src/", "platform/crates/provisioning-core/src/registry.rs"],
},
d.make_node {
id = "smart-interface-unification",
name = "Smart Interface Unification",
pole = 'Yang,
level = 'Practice,
description = "Three-tier fallback chain in Nushell (platform/clients/fallback.nu::tool-call): tier 1 probes the HTTP daemon, tier 2 spawns provisioning-tool as a child process, tier 3 executes the caller-supplied Nushell legacy closure. The probe sequence runs at call time; no daemon state is managed by the operator. All three tiers dispatch through provisioning-core::Registry. Tier-3 closures are the offline-first guarantee and can only be retired per-operation after G3 passes for that operation.",
artifact_paths = [
"core/nulib/platform/clients/fallback.nu",
"core/nulib/platform/clients/daemon.nu",
"core/nulib/platform/clients/provisioning_tool.nu",
"platform/crates/provisioning-tool/",
"platform/crates/provisioning-daemon/",
"platform/scripts/start-provisioning-daemon.nu",
"justfiles/daemon.just",
],
},
d.make_node {
id = "g3-contract-invariant",
name = "G3 Contract Invariant",
pole = 'Yin,
level = 'Practice,
description = "The contract-tests crate asserts that CLI, HTTP daemon, and MCP server produce semantically equivalent payloads and identical error codes for every fixture tool. Five tests must pass: listing agreement, echo agreement, invalid-param error agreement, failing-tool error agreement, tools/list count agreement. normalise() defines what 'equivalent' means by stripping volatile fields. G3 is the CI mechanism that converts sync-irrenunciable into an architectural invariant.",
artifact_paths = ["platform/crates/contract-tests/"],
},
# ── Reflection modes ──────────────────────────────────────────────────────
d.make_node {
id = "mode-provisioning-assess",
name = "Mode: provisioning-assess",
pole = 'Yin,
level = 'Practice,
description = "On+re reflection mode: assess system readiness across orchestrator, CLI, control center, schema coverage, and KCL migration dimensions.",
artifact_paths = ["reflection/modes/provisioning-assess.ncl"],
},
d.make_node {
id = "mode-provisioning-audit",
name = "Mode: provisioning-audit",
pole = 'Yin,
level = 'Practice,
description = "On+re reflection mode: validate config, list and verify taskservs, check Nickel contracts, verify provider integrity, check axiom coherence.",
artifact_paths = ["reflection/modes/provisioning-audit.ncl"],
},
d.make_node {
id = "mode-provisioning-coverage",
name = "Mode: provisioning-coverage",
pole = 'Yin,
level = 'Practice,
description = "On+re reflection mode: map extension ecosystem maturity — taskservs, providers, clusters — and identify coverage gaps.",
artifact_paths = ["reflection/modes/provisioning-coverage.ncl"],
},
d.make_node {
id = "mode-provisioning-validate-formula",
name = "Mode: provisioning-validate-formula",
pole = 'Yin,
level = 'Practice,
description = "On+re reflection mode: cross-validate a workspace Formula DAG — typecheck, taskserv existence, metadata dep coverage, ConflictsWith detection, DAG acyclicity.",
artifact_paths = ["reflection/modes/provisioning-validate-formula.ncl"],
},
d.make_node {
id = "typedialog-web-ui",
name = "TypeDialog Schema-Driven Web UI",
pole = 'Yin,
level = 'Practice,
description = "Nickel schemas are the single source of truth for web form generation. TypeDialog reads contracts from `.typedialog/provisioning/schemas/` and generates validated HTML forms with no manual form code. Supports multi-user collaborative workflows (draft → review → approve), embedded in the control center dashboard. TUI is a fallback for SSH-only environments. Primary value: schema drift between form and config is structurally impossible.",
artifact_paths = [".typedialog/provisioning/", ".typedialog/provisioning/schemas/", ".typedialog/provisioning/form.toml"],
},
d.make_node {
id = "ai-rag-surface",
name = "Schema-Aware AI and RAG Surface",
pole = 'Yang,
level = 'Practice,
description = "AI config generation constrained by Nickel schemas — cannot produce invalid configs. RAG indexes Nickel schemas, docs, and past deployments as retrieval context. ai-service is the HTTP entry point (Cedar-gated); mcp-server exposes tool calling; rag crate manages vector store and embeddings. Cedar policy forbids AI from accessing secrets and requires human approval before any deployment.",
artifact_paths = ["platform/crates/ai-service/", "platform/crates/mcp-server/", "platform/crates/rag/"],
},
# ── DAG architecture (three-layer) ───────────────────────────────────────
d.make_node {
id = "extension-capability-dag",
name = "Extension Capability DAG",
pole = 'Yang,
level = 'Practice,
description = "Extensions declare typed capability provides/requires/conflicts_with in metadata.ncl. Resolution maps required capabilities to concrete extensions before formula execution. Enables conflict detection and dependency ordering without hardcoded extension names.",
artifact_paths = ["catalog/taskservs/*/metadata.ncl", "schemas/lib/dag/contracts.ncl"],
},
d.make_node {
id = "workspace-composition-dag",
name = "Workspace Composition DAG",
pole = 'Yang,
level = 'Practice,
description = "Workspaces declare inter-formula dependencies as a typed DAG via dag.ncl. Formula execution ordering and health gates between formula groups are schema-validated by the WorkspaceComposition Nickel contract and enforced at runtime by WorkspaceComposition::into_workflow in formula.rs.",
artifact_paths = ["schemas/lib/dag/contracts.ncl", "platform/crates/orchestrator/src/formula.rs"],
},
d.make_node {
id = "capability-resolution",
name = "Capability Resolution",
pole = 'Yang,
level = 'Practice,
description = "ResolutionPolicy maps required capabilities (from extension requires fields) to concrete extensions (from extension provides fields). Strict mode: all Required capabilities must resolve before execution proceeds. Optional gaps allowed only when resolution.allow_optional_gaps = true.",
artifact_paths = ["schemas/lib/dag/contracts.ncl", "schemas/config/dag/main.ncl"],
},
d.make_node {
id = "capability-granularity-vs-simplicity",
name = "Capability Granularity vs Simplicity",
pole = 'Spiral,
level = 'Tension,
description = "Fine-grained capabilities enable precise conflict detection but increase taxonomy maintenance burden. Initial set of 9 coarse capabilities (server-lifecycle, networking, storage, container-runtime, orchestration, database, application-deployment, dev-tooling, hypervisor) chosen to defer premature optimization.",
},
d.make_node {
id = "mode-provisioning-dag-integrity",
name = "Mode: provisioning-dag-integrity",
pole = 'Yin,
level = 'Practice,
description = "On+re reflection mode: audit all taskservs for provides/requires/conflicts_with completeness, validate capability graph has no unresolved Required deps, check that ConflictsWith pairs don't coexist in any formula. Runs after B3 migration.",
artifact_paths = ["reflection/modes/provisioning-dag-integrity.ncl"],
},
# ── CI pipelines ──────────────────────────────────────────────────────────
d.make_node {
id = "ci-github-actions",
name = "CI: GitHub Actions",
pole = 'Yang,
level = 'Practice,
description = "GitHub Actions pipelines: nushell-lint, nickel-typecheck, rust-ci. Enforce code quality and schema validity on every PR.",
artifact_paths = [".github/workflows/nushell-lint.yml", ".github/workflows/nickel-typecheck.yml", ".github/workflows/rust-ci.yml"],
},
d.make_node {
id = "ci-woodpecker",
name = "CI: Woodpecker",
pole = 'Yang,
level = 'Practice,
description = "Woodpecker CI pipelines: ci.yml and ci-advanced.yml. Self-hosted CI for provisioning workloads.",
artifact_paths = [".woodpecker/ci.yml", ".woodpecker/ci-advanced.yml"],
},
# ── Examples ──────────────────────────────────────────────────────────────
d.make_node {
id = "scenario-workspaces",
name = "Scenario: Workspaces",
pole = 'Yin,
level = 'Practice,
description = "Example workspace configurations demonstrating the workspace contract pattern, server composition, and formula DAGs.",
artifact_paths = ["examples/workspaces"],
},
# ── Platform service nodes (previously only in artifact_paths) ────────────
d.make_node {
id = "vault-service",
name = "Vault Service — Multi-Backend Secrets",
pole = 'Yin,
level = 'Practice,
description = "SOLID boundary for all secret storage and retrieval. Three backends: Age (development, filesystem key), Cosmian KMS (production, HSM-backed), RustyVault (self-hosted). Provider credentials are leased, never stored raw. Secrets never transit NATS — only lease_id references are published to the event bus. Cedar policies in the control-center prevent any other service from calling vault endpoints directly.",
artifact_paths = ["platform/crates/vault-service/", "platform/crates/vault-service/src/"],
},
d.make_node {
id = "extension-registry-service",
name = "Extension Registry — OCI Distribution Surface",
pole = 'Yang,
level = 'Practice,
description = "OCI-compliant registry proxy that distributes provisioning extensions (taskservs, providers, cluster definitions) as OCI artifacts. Validates digests, caches manifests via LRU, emits extension lifecycle events to NATS. Enables versioned extension delivery without requiring a full OCI registry deployment — the proxy layer handles authentication and manifest caching transparently.",
artifact_paths = ["platform/crates/extension-registry/", "platform/crates/extension-registry/src/"],
},
d.make_node {
id = "ncl-sync-daemon",
name = "NCL Sync Daemon — Config Compilation Pipeline",
pole = 'Yang,
level = 'Practice,
description = "Daemon that watches Nickel (NCL) source files, compiles them to JSON on change, and keeps the config cache fresh for Nushell processes that cannot afford `nickel export` startup cost on every invocation. File-watching via the `notify` crate; optional NATS publication for cross-process cache invalidation. Resolves the tension between type-safe NCL source of truth and low-latency config reads at CLI time.",
artifact_paths = ["platform/crates/ncl-sync/", "platform/crates/ncl-sync/src/"],
},
d.make_node {
id = "prvng-cli-daemon",
name = "prvng-cli — Zero-Cost CLI Query Daemon",
pole = 'Yang,
level = 'Practice,
description = "Unix-socket daemon (`~/.local/share/provisioning/cli.sock`) that answers command registry lookups with sub-millisecond latency. Eliminates the Nushell startup + `nickel export` cost from the bash wrapper's `_validate_command` path. File-watches `commands-registry.json` via the `notify` crate; auto-shuts after 60s idle; restarted by the bash wrapper on next invocation. The wrapper falls through to grep+JSON cache if the socket is absent.",
artifact_paths = ["platform/crates/prvng-cli/", "platform/crates/prvng-cli/src/"],
},
d.make_node {
id = "platform-shared-infra",
name = "Platform Shared Infrastructure Crates",
pole = 'Yin,
level = 'Practice,
description = "Three workspace libraries consumed by all platform services: `platform-config` (centralized config loading with Nickel merge layer), `platform-nats` (shared NATS JetStream bridge with retry loop, explicit ACK, and subject prefixing under `provisioning.>`), and `platform-db` (SurrealDB connection pool supporting embedded RocksDB for solo mode, SurrealKV for dev, and WebSocket for multi-user production). These three crates are the only infrastructure primitives that cross service boundaries in the Rust layer.",
artifact_paths = ["platform/crates/platform-config/", "platform/crates/platform-nats/", "platform/crates/platform-db/"],
},
d.make_node {
id = "platform-crate-naming",
name = "Platform Workspace Crate Naming Convention",
pole = 'Yin,
level = 'Practice,
description = "Four-rule naming convention applied to all workspace crates (ADR-030): (1) shared library crates use `platform-<name>` package name; (2) smart interface layer uses `provisioning-<name>`; (3) service binary package names are short — `provisioning-` prefix lives only in `[[bin]] name`; (4) ecosystem crates with many existing `use` callers use `platform-<name>` package name + `[lib] name = 'old_name'` to preserve Rust crate names without modifying call sites. The convention disambiguates workspace dep declarations and eliminates crates.io name collision risk for generic names.",
artifact_paths = ["platform/Cargo.toml", "platform/crates/", "platform/prov-ecosystem/crates/"],
},
d.make_node {
id = "ops-contract-dual-mode",
name = "Ops Contract Dual-Mode — Pending Queue + Switchable Signer",
pole = 'Yang,
level = 'Practice,
description = "NATS JetStream-based ops coordination with three subject namespaces (ops.pending, ops.cmd, ops.audit) and JWT-signed commands carrying scoped permissions, monotonic sequence, idempotency key, and expected_state_version. Signers (keeper-daemon for auto, keeper-cli for manual) are interchangeable subscribers to ops.pending — switching modes is operational (start/stop daemon), not architectural. ops-controller is the single per-workspace WorkQueue consumer of ops.cmd, persisting in-flight ops to SurrealDB before ack to survive restart. Multi-emitter coordination is delegated to JetStream stream order with optimistic concurrency on expected_state_version. ADR-037.",
artifact_paths = ["adrs/adr-037-ops-contract-dual-mode.ncl", "platform/crates/ops-keeper/", "platform/crates/ops-controller/", "schemas/lib/ops_contract.ncl"],
},
d.make_node {
id = "decentralized-governance-radicle",
name = "Decentralized Governance — Radicle Heartwood Substrate",
pole = 'Yin,
level = 'Practice,
description = "Radicle Heartwood as the substrate for governance, desired-state, and audit ledger across all workspaces. Three repos per workspace: policy-<workspace> (M-of-N delegation among operators), <workspace>-desired (M-of-N + CI keys), <workspace>-state (single delegate: ops-controller key). Keeper policy is declarative-only Nickel — parsed by Rust matcher, never evaluated as code. Audit mirror sidecar bridges NATS ops.audit subjects to <workspace>-state commits with jti idempotency. Operators may use any frontend (git, jj) over their local Radicle replica. Domain-level commands (governance delegations, governance signers) read local clones uniformly. ADR-038.",
artifact_paths = ["adrs/adr-038-radicle-decentralized-governance.ncl", "platform/crates/audit-mirror/", "schemas/lib/radicle.ncl", "schemas/lib/keeper_policy.ncl"],
},
d.make_node {
id = "ephemeral-build-infrastructure",
name = "Ephemeral Build Infrastructure — Golden Runners + S3-Backed zot",
pole = 'Yang,
level = 'Practice,
description = "Build pipeline using orchestrator-spawned ephemeral VMs from periodically-rebuilt golden images (buildkit-runner-golden). Per-build sizing resolved from .build-spec.ncl declaration, p95 historical, or language defaults. zot relocated from libre-daoshi to libre-wuji with S3-compatible backend (versioning + cross-region replication for DR). Multi-tenant zot layout serves /images, /cache, /sccache, /crates with JWT-scoped auth. BuildKit registry-cache and sccache S3-backend both terminate at zot for warm-cache cold-spawn. buildkit-launcher (Woodpecker plugin) is a thin bridge to orchestrator's VM lease semantics. ADR-039.",
artifact_paths = ["adrs/adr-039-build-infrastructure-ephemeral.ncl", "catalog/components/buildkit_runner.ncl", "platform/crates/buildkit-launcher/", "schemas/lib/build_spec.ncl"],
},
d.make_node {
id = "federated-integration-modes",
name = "Federated Integration Modes — OCI Domain Artifacts",
pole = 'Yang,
level = 'Practice,
description = "Cross-project integration via typed OCI domain artifacts. Each project declares an IntegrationMode in its own reflection/modes/ with domains_used pointing to versioned artifacts at reg.librecloud.online/domains/<id>:<semver>. Provisioning is a peer participant — not a plugin host; no filesystem coupling exists between participants. Cabling files at infra/<ws>/integrations/<mode-id>.ncl resolve domain context fields to concrete sources (sops, component, literal, env). Domains are OCI artifacts with mediaType application/vnd.ontoref.domain.v1 containing a typed Nickel contract. Initial catalog: secret-delivery 0.1.0, event-emission 0.1.0, result-reporting 0.1.0. prvng integration domain publish/pull/describe/verify manage the OCI surface. ADR-042.",
artifact_paths = ["adrs/adr-042-ecosystem-integration-modes.ncl", "schemas/lib/integration/", "catalog/domains/", "core/nulib/platform/oci/domain_client.nu", "core/nulib/cli/integration.nu"],
},
],
edges = [
# Axiom manifestations
{ from = "config-driven-always", to = "type-safety-nickel", kind = 'ManifestsIn, weight = 'High,
note = "Nickel is the manifestation of config-driven — typed schemas enforce the axiom" },
{ from = "config-driven-always", to = "config-hierarchy", kind = 'ManifestsIn, weight = 'High,
note = "The 5-level hierarchy implements the config-driven axiom at runtime" },
{ from = "workspace-contract", to = "config-driven-always", kind = 'ManifestsIn, weight = 'High,
note = "Workspaces are the user-facing manifestation of config-driven infrastructure" },
# Tension relationships
{ from = "type-safety-nickel", to = "nickel-complexity-vs-accessibility", kind = 'Contradicts, weight = 'Medium,
note = "The axiom generates the tension — stricter types vs contributor friction" },
{ from = "platform-dispatch", to = "centralized-vs-scripted", kind = 'Resolves, weight = 'High,
note = "The dispatch model is the resolution of centralized vs scripted" },
# Structural relationships
{ from = "solid-boundaries", to = "platform-dispatch", kind = 'ValidatedBy, weight = 'High,
note = "SOLID boundaries are validated by the dispatch model — only orchestrator touches providers" },
{ from = "solid-boundaries", to = "provider-abstraction", kind = 'Contains, weight = 'High,
note = "Provider abstraction is a corollary of SOLID boundaries" },
{ from = "solo-mode", to = "solid-boundaries", kind = 'ValidatedBy, weight = 'Medium,
note = "Solo mode preserves SOLID boundaries — auth bypass is the only runtime difference, not an architectural bypass" },
{ from = "solo-mode", to = "centralized-vs-scripted", kind = 'Resolves, weight = 'Medium,
note = "Solo mode proves single-operator usefulness without sacrificing the centralized architecture" },
{ from = "provider-abstraction", to = "taskserv-pattern", kind = 'Complements, weight = 'Medium,
note = "Providers and taskservs are complementary extension points" },
{ from = "taskserv-pattern", to = "workspace-contract", kind = 'FlowsTo, weight = 'High,
note = "Taskservs consume what workspaces declare — the data flow direction" },
# TypeDialog and AI relationships
{ from = "typedialog-web-ui", to = "type-safety-nickel", kind = 'ManifestsIn, weight = 'High,
note = "TypeDialog is the user-facing manifestation of type-safety-nickel — schema contracts drive form generation" },
{ from = "typedialog-web-ui", to = "workspace-as-implementation-plan", kind = 'Complements, weight = 'High,
note = "TypeDialog is the authoring UI for workspace implementation plans" },
{ from = "ai-rag-surface", to = "type-safety-nickel", kind = 'ValidatedBy, weight = 'High,
note = "Nickel schemas constrain AI generation — AI cannot produce configs that fail schema validation" },
{ from = "ai-rag-surface", to = "solid-boundaries", kind = 'ValidatedBy, weight = 'High,
note = "Cedar policies enforce AI cannot read secrets or deploy without human approval" },
{ from = "ai-rag-surface", to = "typedialog-web-ui", kind = 'Complements, weight = 'Medium,
note = "AI fills TypeDialog forms; TypeDialog provides the schema context AI is constrained by" },
# Extension ecosystem relationships
{ from = "extension-metadata-contract", to = "taskserv-pattern", kind = 'ValidatedBy, weight = 'High,
note = "Metadata contracts formalize the taskserv interface — every taskserv must satisfy the metadata contract to be loaded" },
{ from = "extension-metadata-contract", to = "provider-abstraction", kind = 'ValidatedBy, weight = 'Medium,
note = "Provider extensions also declare metadata — the contract applies across all extension categories" },
{ from = "taskserv-dependency-dag", to = "taskserv-pattern", kind = 'ManifestsIn, weight = 'High,
note = "The dependency DAG is the runtime expression of taskserv relationship declarations" },
{ from = "taskserv-dependency-dag", to = "formula-dag-execution", kind = 'FlowsTo, weight = 'High,
note = "Taskserv dependency graph feeds into the formula DAG execution plan — dependency resolution precedes formula construction" },
{ from = "extension-metadata-contract", to = "extension-graph-vs-declarative-config", kind = 'Contradicts, weight = 'Medium,
note = "Adding ontology fields to metadata.ncl is the planned evolution that generates this tension" },
# DAG architecture relationships
{ from = "extension-capability-dag", to = "type-safety-nickel", kind = 'ManifestsIn, weight = 'High,
note = "Capability declarations are Nickel contracts — provides/requires/conflicts_with are schema-validated" },
{ from = "extension-capability-dag", to = "extension-metadata-contract", kind = 'ManifestsIn, weight = 'High,
note = "Capability fields extend the extension-metadata-contract; backwards-compatible via defaults" },
{ from = "capability-resolution", to = "formula-dag-execution", kind = 'FlowsTo, weight = 'High,
note = "Capability resolution produces the extension binding map consumed by formula execution" },
{ from = "workspace-composition-dag", to = "config-driven-always", kind = 'ManifestsIn, weight = 'High,
note = "dag.ncl is a typed Nickel declaration — no imperative composition scripts" },
{ from = "workspace-composition-dag", to = "formula-dag-execution", kind = 'FlowsTo, weight = 'High,
note = "Composition DAG drives the inter-formula execution order and health gate injection" },
{ from = "extension-capability-dag", to = "capability-granularity-vs-simplicity", kind = 'ManifestsIn, weight = 'Medium,
note = "The capability taxonomy is the direct expression of this tension" },
{ from = "mode-provisioning-dag-integrity", to = "extension-capability-dag", kind = 'ValidatedBy, weight = 'High,
note = "Integrity mode is the verification pass for the capability DAG" },
# Workspace relationships
{ from = "workspace-as-implementation-plan", to = "workspace-contract", kind = 'ManifestsIn, weight = 'High,
note = "Workspace-as-plan is the semantic interpretation; workspace contract is the schema mechanism that enforces it" },
{ from = "workspace-layer-resolution", to = "workspace-contract", kind = 'ManifestsIn, weight = 'High,
note = "Layer resolution is the composition mechanism that realizes the workspace contract from template fragments" },
{ from = "workspace-as-implementation-plan", to = "formula-dag-execution", kind = 'FlowsTo, weight = 'High,
note = "The workspace composition is the input from which the formula DAG execution plan is derived" },
{ from = "workspace-layer-resolution", to = "config-driven-always", kind = 'ManifestsIn, weight = 'Medium,
note = "Layer resolution is config-driven-always applied to workspace composition — no imperative override paths" },
# Nushell CLI library relationships
{ from = "nushell-cli-library", to = "workspace-as-implementation-plan", kind = 'ManifestsIn, weight = 'High,
note = "CLI library is the primary authoring surface for workspace definitions — workspace commands drive the full lifecycle" },
{ from = "nushell-cli-library", to = "centralized-vs-scripted", kind = 'Contradicts, weight = 'Medium,
note = "The CLI library's size generates the nushell-vs-rust-boundary tension — it could absorb orchestrator logic" },
{ from = "nushell-cli-library", to = "nushell-vs-rust-boundary", kind = 'ManifestsIn, weight = 'High,
note = "The library's growth is the direct expression of this tension" },
# Smart Interface Unification relationships (ADR-029)
{ from = "provisioning-registry", to = "solid-boundaries", kind = 'ManifestsIn, weight = 'High,
note = "Registry::invoke is the single dispatch path — surfaces cannot bypass it; enforced by ADR-029 constraint registry-sole-dispatch-path" },
{ from = "provisioning-registry", to = "nushell-vs-rust-boundary", kind = 'Resolves, weight = 'High,
note = "Registry is the structural boundary: Rust owns dispatch semantics, Nushell owns orchestration sequences and the legacy closure" },
{ from = "smart-interface-unification", to = "nushell-cli-library", kind = 'ManifestsIn, weight = 'High,
note = "tool-call / tool-list in nulib/platform/clients/fallback.nu is the Nushell expression of the three-tier architecture" },
{ from = "smart-interface-unification", to = "provisioning-registry", kind = 'FlowsTo, weight = 'High,
note = "All three tiers ultimately converge on Registry::invoke — the fallback chain selects the transport, not the dispatch logic" },
{ from = "smart-interface-unification", to = "ai-rag-surface", kind = 'Complements, weight = 'Medium,
note = "mcp-server is now Registry-backed — MCP tool calling and AI tool calling use the same dispatch path" },
{ from = "g3-contract-invariant", to = "provisioning-registry", kind = 'ValidatedBy, weight = 'High,
note = "G3 is the runtime evidence that Registry dispatch produces identical semantics across all three surfaces" },
{ from = "g3-contract-invariant", to = "smart-interface-unification", kind = 'ValidatedBy, weight = 'High,
note = "G3 is the CI gate that prevents surface drift — the invariant that makes sync-irrenunciable structural" },
{ from = "smart-interface-unification", to = "config-driven-always", kind = 'ManifestsIn, weight = 'Medium,
note = "Tier selection is driven by environment probes at call time, not by hardcoded configuration — the fallback chain is config-driven" },
# Platform service node relationships
{ from = "vault-service", to = "solid-boundaries", kind = 'ManifestsIn, weight = 'High,
note = "Vault is the concrete implementation of the secrets SOLID boundary — Cedar policies enforce no other service touches vault endpoints" },
{ from = "vault-service", to = "config-driven-always", kind = 'ManifestsIn, weight = 'High,
note = "Backend selection (Age/Cosmian/RustyVault) is purely configuration — same binary, different backend at runtime" },
{ from = "extension-registry-service", to = "provider-abstraction", kind = 'Complements, weight = 'Medium,
note = "Extension registry distributes the versioned artifacts that implement provider and taskserv extensions" },
{ from = "extension-registry-service", to = "extension-metadata-contract", kind = 'ValidatedBy, weight = 'High,
note = "Registry validates OCI artifact digests; the metadata.ncl contract inside each artifact is validated by the CLI loader on install" },
{ from = "ncl-sync-daemon", to = "type-safety-nickel", kind = 'ManifestsIn, weight = 'High,
note = "NCL sync makes NCL the live source of truth — JSON cache is always derived from NCL, never edited directly" },
{ from = "ncl-sync-daemon", to = "config-hierarchy", kind = 'ManifestsIn, weight = 'High,
note = "The JSON cache NCL sync maintains is the artifact consumed by the 5-level config hierarchy at runtime" },
{ from = "prvng-cli-daemon", to = "nushell-cli-library", kind = 'Complements, weight = 'High,
note = "prvng-cli eliminates the startup cost that made fast bash-wrapper validation infeasible — the CLI library benefits from sub-ms command lookup" },
{ from = "prvng-cli-daemon", to = "nushell-vs-rust-boundary", kind = 'Resolves, weight = 'Medium,
note = "Unix-socket daemon shifts command validation entirely to Rust, removing the Nu + nickel export cost from the hot path" },
{ from = "platform-shared-infra", to = "solid-boundaries", kind = 'ManifestsIn, weight = 'High,
note = "platform-config/nats/db are the only infra primitives crossing service boundaries — they are the shared substrate SOLID boundaries operate over" },
{ from = "platform-shared-infra", to = "solo-mode", kind = 'ManifestsIn, weight = 'High,
note = "Solo mode is implemented entirely in platform-db (embedded RocksDB) and platform-nats (child process) — no solo-specific code in the business services" },
{ from = "platform-crate-naming", to = "monorepo-vs-split", kind = 'Resolves, weight = 'Medium,
note = "The naming convention makes the monorepo workspace unambiguous — dep declarations carry project affiliation without splitting into separate repos" },
{ from = "platform-crate-naming", to = "config-driven-always", kind = 'Complements, weight = 'Low,
note = "Consistent naming is a prerequisite for config-driven extension loading — ambiguous package names would make programmatic workspace dep discovery fragile" },
# Ops contract dual-mode relationships (ADR-037)
{ from = "ops-contract-dual-mode", to = "solid-boundaries", kind = 'ManifestsIn, weight = 'High,
note = "ops-controller is a new SOLID boundary — consumes from ops.cmd, applies via orchestrator API, writes to ops.audit and SurrealDB; never calls provider APIs or auth services directly" },
{ from = "ops-contract-dual-mode", to = "config-driven-always", kind = 'ManifestsIn, weight = 'High,
note = "Mode switch (auto/manual/hybrid) is operational state, not configuration — keeper policy is declarative Nickel, ops contract is JWT scopes; no hardcoded mode constants" },
{ from = "ops-contract-dual-mode", to = "centralized-vs-scripted", kind = 'Resolves, weight = 'High,
note = "Pending queue + replaceable signer means automated CI and manual operator paths converge on the same contract — no fork between centralized and scripted" },
{ from = "ops-contract-dual-mode", to = "platform-shared-infra", kind = 'FlowsTo, weight = 'High,
note = "ops contract uses platform-nats for JetStream and platform-db for SurrealDB persistence — built on the same shared substrate as orchestrator" },
# Decentralized governance relationships (ADR-038)
{ from = "decentralized-governance-radicle", to = "config-driven-always", kind = 'ManifestsIn, weight = 'High,
note = "Radicle repos (policy/desired/state) are versioned configuration with cryptographic provenance — config-driven extends to governance itself" },
{ from = "decentralized-governance-radicle", to = "type-safety-nickel", kind = 'ManifestsIn, weight = 'High,
note = "keeper policy uses declarative-only Nickel schema — type-safe data, never executed as code" },
{ from = "decentralized-governance-radicle", to = "monorepo-vs-split", kind = 'Resolves, weight = 'Medium,
note = "Three-repo split per workspace separates governance/desired/audit by authority profile without compromising the source-code monorepo" },
{ from = "decentralized-governance-radicle", to = "ops-contract-dual-mode", kind = 'Complements, weight = 'High,
note = "ops contract handles transit (NATS); Radicle handles permanent record (audit ledger via mirror sidecar) and governance (delegations)" },
# Ephemeral build infrastructure relationships (ADR-039)
{ from = "ephemeral-build-infrastructure", to = "provider-abstraction", kind = 'FlowsTo, weight = 'High,
note = "buildkit_runner is a component spawned via orchestrator's VM lifecycle — same provider abstraction as taskservs" },
{ from = "ephemeral-build-infrastructure", to = "config-driven-always", kind = 'ManifestsIn, weight = 'High,
note = "Per-build sizing resolved from .build-spec.ncl declaration, historical p95, or language defaults — no hardcoded sizing" },
{ from = "ephemeral-build-infrastructure", to = "ops-contract-dual-mode", kind = 'FlowsTo, weight = 'Medium,
note = "Build artifacts (image push to zot) trigger downstream deploy ops via ops.pending — build pipeline emits ops, does not apply them" },
{ from = "ephemeral-build-infrastructure", to = "extension-registry-service", kind = 'Complements, weight = 'Medium,
note = "zot multi-tenant /crates and /images coexist with extension-registry's OCI distribution — both are OCI-spec consumers of the same backing storage" },
# Federated integration modes relationships (ADR-042)
{ from = "federated-integration-modes", to = "type-safety-nickel", kind = 'ManifestsIn, weight = 'High,
note = "Cabling contracts and domain contracts are Nickel NCL — type safety extends to integration context assembly" },
{ from = "federated-integration-modes", to = "solid-boundaries", kind = 'ValidatedBy, weight = 'High,
note = "No filesystem coupling between participants — each project is an autonomous peer consuming typed OCI artifacts" },
{ from = "federated-integration-modes", to = "ephemeral-build-infrastructure", kind = 'Complements, weight = 'Medium,
note = "Domain artifacts are stored in the same zot registry as build artifacts — OCI storage is shared substrate" },
{ from = "federated-integration-modes", to = "config-driven-always", kind = 'ManifestsIn, weight = 'High,
note = "Cabling files are declarative config — no imperative wiring; context assembly reads config, not code" },
],
}

45
.ontology/gate.ncl Normal file
View file

@ -0,0 +1,45 @@
let d = import "ontology/defaults/gate.ncl" in
{
membranes = [
d.make_membrane {
id = "control-plane-readiness",
name = "Control Plane Readiness",
description = "Controls when the provisioning control plane is ready for production deployment and multi-user mode.",
permeability = 'Low,
accepts = ['EcosystemRelevance],
protects = ["production deployment", "multi-user mode"],
opening_condition = {
max_tension_dimensions = 2,
pending_transitions = 2,
core_stable = true,
description = "Orchestrator + Control Center operational, NATS streams configured and stable, SOLID boundaries passing all 6 enforcement layers, Cedar policies loaded and evaluated.",
},
closing_condition = "Any SOLID enforcement layer failing or NATS stream misconfiguration detected.",
max_duration = 'Indefinite,
protocol = 'Challenge,
active = false,
},
d.make_membrane {
id = "workspace-certification",
name = "Workspace Certification",
description = "Controls when a workspace is ready for production use — all taskservs validated, config schema-checked, provider capabilities matched.",
permeability = 'Medium,
accepts = ['EcosystemRelevance, 'OpportunityAlignment],
protects = ["workspace production use"],
opening_condition = {
max_tension_dimensions = 3,
pending_transitions = 3,
core_stable = true,
description = "All taskservs in workspace have dependencies.ncl, config validates via nickel typecheck, provider capabilities match requirements.",
},
closing_condition = "Workspace config fails schema validation or provider capabilities no longer match declared requirements.",
max_duration = 'Indefinite,
protocol = 'Observe,
active = false,
},
],
}

340
.ontology/manifest.ncl Normal file
View file

@ -0,0 +1,340 @@
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",
},
}

249
.ontology/state.ncl Normal file
View file

@ -0,0 +1,249 @@
let d = import "ontology/defaults/state.ncl" in
{
dimensions = [
d.make_dimension {
id = "orchestrator-maturity",
name = "Orchestrator Maturity",
description = "Orchestrator service readiness — from functional prototype to production-grade task execution engine.",
current_state = "functional",
desired_state = "production",
horizon = 'Months,
states = [],
transitions = [
d.make_transition {
from = "functional",
to = "production",
condition = "All 6 SOLID enforcement layers passing, NATS streams stable, task state machine handles all error paths with rollback, formula DAG execution covers all taskserv dependency combinations.",
catalyst = "Control Center JWT auth and Cedar policy evaluation wired end-to-end; solo mode auth bypass verified against ADR-015 constraints.",
blocker = "Cedar policy definitions stored in SurrealDB not finalized; WebSocket task status streaming not connected to NATS push consumers.",
horizon = 'Months,
},
],
},
d.make_dimension {
id = "cli-maturity",
name = "CLI and Nushell Library Maturity",
description = "CLI v3 and core/nulib/ stability — the primary user interface and Nushell command library for all platform operations.",
current_state = "stable-v3",
desired_state = "stable-v3",
horizon = 'Continuous,
states = [],
transitions = [],
},
d.make_dimension {
id = "control-center-maturity",
name = "Control Center Maturity",
description = "Control Center service readiness — from bootstrapped to operational with live auth, Cedar policies, and WebSocket streaming.",
current_state = "bootstrapped",
desired_state = "operational",
horizon = 'Months,
states = [],
transitions = [
d.make_transition {
from = "bootstrapped",
to = "operational",
condition = "JWT auth middleware active in non-solo mode, Cedar policies loaded from SurrealDB and evaluated on all protected routes, WebSocket task status streaming connected to NATS push consumers.",
catalyst = "Solo mode (ADR-015) fully tested end-to-end as staging environment for multi-user auth path.",
blocker = "Cedar policy definitions not finalized; WebSocket streaming not connected to NATS; IaC detection and rules handlers partially commented out in router.",
horizon = 'Months,
},
],
},
d.make_dimension {
id = "schema-coverage",
name = "Schema Coverage",
description = "Nickel schema coverage across all configuration surfaces — from partial to comprehensive.",
current_state = "partial",
desired_state = "comprehensive",
horizon = 'Months,
states = [],
transitions = [
d.make_transition {
from = "partial",
to = "comprehensive",
condition = "All provider configs, workspace configs, platform service configs, extension metadata (taskserv dependency declarations), and TypeDialog forms covered by typed Nickel schemas. Extension metadata.ncl files cover all 10 built-in taskservs.",
catalyst = "Extension ontology evolution (ADR-019 AI surface) requiring schema for RAG indexing.",
blocker = "Some extensions still use raw TOML or KCL remnants for metadata. TypeDialog schemas cover workspace config but not all platform service configs.",
horizon = 'Months,
},
],
},
d.make_dimension {
id = "kcl-migration",
name = "KCL Migration",
description = "Migration from KCL to Nickel — completed, continuous maintenance only.",
current_state = "completed",
desired_state = "completed",
horizon = 'Continuous,
states = [],
transitions = [],
},
d.make_dimension {
id = "smart-interface-migration",
name = "Smart Interface Migration",
description = "Migration of all 37 Nushell operations from direct legacy dispatch to the three-tier fallback chain (HTTP daemon → provisioning-tool → Nushell closure). Infrastructure complete; operation wiring is the remaining work.",
current_state = "bootstrapped",
desired_state = "migrated",
horizon = 'Months,
states = [],
transitions = [
d.make_transition {
from = "bootstrapped",
to = "migrated",
condition = "All 37 operations call tool-call / tool-list with a real Nushell legacy closure; G3 contract test passes for each migrated operation; no handler calls the orchestrator or provider APIs directly from nulib without going through the Registry.",
catalyst = "G3 contract test gates each migration — an operation can only retire its tier-3 closure after G3 passes for it. Daemon install via `just daemon install` makes tier-1 available on developer machines.",
blocker = "36 operations still dispatch via Nushell legacy directly; only workspace_list is wired to the fallback chain. Migration is per-operation and non-breaking.",
horizon = 'Months,
},
],
},
d.make_dimension {
id = "extension-ecosystem-maturity",
name = "Internal Extension Mechanism Maturity",
description = "Maturity of the internal extension mechanism (taskservs and providers) — from basic metadata contracts to capability-aware DAG resolution to ontology-aware impact analysis. Distinct from federated integration modes (ADR-042) which governs cross-project integration via OCI domain artifacts.",
current_state = "capability-aware",
desired_state = "ontology-aware",
horizon = 'Months,
states = [],
transitions = [
d.make_transition {
from = "metadata-contracts",
to = "capability-aware",
condition = "All 10 built-in taskserv metadata.ncl files migrated with provides/requires/conflicts_with fields. provisioning-dag-integrity reflection mode runs clean. CLI `provisioning extensions capabilities` outputs correct capability table.",
catalyst = "Three-layer DAG architecture (ADR-016) requiring typed capability declarations for formula dependency resolution.",
blocker = "Completed — B2 (schema extension) and B3 (metadata migration) done in DAG architecture session.",
horizon = 'Continuous,
},
d.make_transition {
from = "capability-aware",
to = "ontology-aware",
condition = "Extension metadata.ncl can optionally declare ontology node IDs; orchestrator resolves extension DAG against platform ontology for impact analysis; CLI reports which ontology nodes are affected by a given workspace execution.",
catalyst = "AI RAG surface (ADR-019) requiring extension ontology data for schema-aware config generation.",
blocker = "Ontology node schema not yet added to metadata.ncl contract; no tooling to validate ontology references in extension metadata.",
horizon = 'Months,
},
],
},
d.make_dimension {
id = "ops-contract-evolution",
name = "Ops Contract Evolution (ADR-037)",
description = "Evolution of the dual-mode ops contract — from architectural decision to implemented crates to production deployment with multi-emitter coordination proven under load.",
current_state = "designed",
desired_state = "production",
horizon = 'Months,
states = [],
transitions = [
d.make_transition {
from = "designed",
to = "implemented",
condition = "ops-keeper crate (keeper-daemon + keeper-cli binaries) compiles and passes unit tests; ops-controller crate subscribes to OPS_CMD JetStream stream and applies ops idempotently with SurrealDB persistence of in-flight state; schemas/lib/ops_contract.ncl + keeper_policy.ncl validated; NATS JetStream streams OPS_PENDING/OPS_CMD/OPS_AUDIT created with correct retention.",
catalyst = "ADR-037 accepted; design discussion produced 23 implementation tasks with explicit per-layer (domain/project/workspace) impact mapping.",
blocker = "Implementation not yet started — designed but no crates exist. Ordered prerequisite: schemas first, then ops-keeper crate, then ops-controller crate, then NATS config.",
horizon = 'Months,
},
d.make_transition {
from = "implemented",
to = "production",
condition = "VM-ops workspace deployed with keeper-daemon running; libre-wuji ops-controller deployed with single-replica WorkQueue consumer; daoshi-CI Woodpecker pipelines emit ops via buildkit-launcher publish step; multi-emitter conflict scenario verified in staging (two emitters, second receives 409); operator-only mode tested via switch_to_operator_only playbook; pending queue depth and oldest-message-age observable in Prometheus.",
catalyst = "ops contract is gating for ADR-039 build infrastructure (build pipeline emits deploy ops via ops.pending) — production readiness blocks the deploy-from-CI path.",
blocker = "Implementation phase not complete; observability stack not deployed in libre-wuji; VM-ops workspace not yet provisioned.",
horizon = 'Months,
},
],
},
d.make_dimension {
id = "integration-modes-maturity",
name = "Federated Integration Modes Maturity (ADR-042)",
description = "Maturity of the federated integration modes protocol — from schema definitions and OCI domain artifacts to assembled context delivery to fully-wired invoke pipeline.",
current_state = "schema-defined",
desired_state = "assembled",
horizon = 'Months,
states = [],
transitions = [
d.make_transition {
from = "schema-defined",
to = "assembled",
condition = "context-assembler crate reads cabling.ncl + SOPS secrets + component outputs and produces a typed SecretDeliveryContext JSON envelope; `prvng integration invoke <mode-id>` pipes the assembled context to the mode binary stdin; lian-build provisioning mode receives the envelope and emits a valid ResultEnvelope; `prvng integration subscribe <mode-id>` scaffolds a cabling file skeleton in infra/<ws>/integrations/.",
catalyst = "context-assembler Nushell module complete (platform/integrations/context_assembler.nu); `prvng integration invoke/subscribe/validate` all wired; 7 domain artifacts in zot (secret-delivery, event-emission, result-reporting, compute-provisioning, registry-access, cache-management, backup-policy-binding 0.1.0); all signed with cosign; lian-build + cloudatasave modes declared with domain locks + libre-wuji cablings.",
blocker = "lian-build binary does not yet read stdin context — end-to-end live invoke not yet proven.",
horizon = 'Months,
},
d.make_transition {
from = "assembled",
to = "production",
condition = "cloudatasave integration mode declared with its own lock + cabling; cosign signing applied to all domain artifacts in zot; zot trust policy rejects unsigned domain artifacts; NATS event-emission domain wired to production JetStream subjects in each workspace cabling.",
catalyst = "cosign signing complete for all 9 artifacts (7 domains + 2 modes) ✓; zot imagetrust extension enabled in configmap ✓; cloudatasave mode + lock + cabling declared ✓; client-side cosign verify in domain-verify + subscribe ✓; key rotation documented in docs/guides/cosign-key-rotation.md ✓; ZOT_ADMIN_PASS in zot.sops.yaml + adminPolicy for regadm + server-side cosign trust key uploaded (HTTP 200) ✓.",
blocker = "NATS event-emission wiring not yet live; lian-build binary stdin implementation external dependency.",
horizon = 'Months,
},
],
},
d.make_dimension {
id = "governance-model-state",
name = "Decentralized Governance Model State (ADR-038)",
description = "Adoption state of Radicle Heartwood as governance and audit substrate across all workspaces.",
current_state = "designed",
desired_state = "active",
horizon = 'Months,
states = [],
transitions = [
d.make_transition {
from = "designed",
to = "bootstrapped",
condition = "Radicle Heartwood seed nodes installed on every operator laptop, on libre-daoshi designated node, on libre-wuji designated node, and on ops-vm; per-operator Radicle identities created; for each workspace, three repos (policy/desired/state) initialized with correct delegation profiles (M-of-N for policy/desired, single ops-controller for state); audit-mirror sidecar deployed in libre-wuji subscribing to ops.audit subjects with jti idempotency check.",
catalyst = "ADR-038 accepted; ops contract (ADR-037) requires the audit ledger to land somewhere durable and decentralized — Radicle is that target.",
blocker = "Implementation not started; Radicle CLI familiarity required across operators; bootstrap playbook not yet written; ops-controller signing keys not yet generated for state repo delegation.",
horizon = 'Months,
},
d.make_transition {
from = "bootstrapped",
to = "active",
condition = "policy-<workspace> patches signed by quorum and deployed in production; keeper-daemon polls policy repo for latest commit and applies declarative matcher; <workspace>-state ledger receiving live audit events from wuji; operator on/off-boarding playbooks tested with delegation patches; cross-replica gossip lag measured and within acceptable bounds (seconds-to-minutes for policy/desired updates).",
catalyst = "First production op signed via the new contract validates the end-to-end path: emitter → pending → keeper signs per policy → ops-controller applies → audit lands in Radicle state repo.",
blocker = "Bootstrap phase incomplete; production deployment requires both ADR-037 (ops) and ADR-038 (governance) implemented and validated together.",
horizon = 'Months,
},
],
},
d.make_dimension {
id = "build-infrastructure-state",
name = "Build Infrastructure State (ADR-039)",
description = "Maturity of ephemeral-runner + S3-backed zot build pattern — from architectural decision to operational golden image v1 to dynamic-sizing production.",
current_state = "designed",
desired_state = "production",
horizon = 'Months,
states = [],
transitions = [
d.make_transition {
from = "designed",
to = "golden-image-v1",
condition = "Initial buildkit-runner-golden image built off-platform (laptop or external CI) and pushed to bootstrap zot; weekly rebuild Woodpecker pipeline defined; orchestrator vm_pool extended with buildkit lifecycle (spawn from golden + cleanup hook); buildkit-launcher crate compiles; .build-spec.ncl schema validated against schemas/lib/build_spec.ncl.",
catalyst = "Vapora and other Rust workloads need a build path; current absence of build infrastructure means manual local builds — gating for production deploys.",
blocker = "Implementation not started; bootstrap golden image must be produced manually first time; zot relocation from libre-daoshi to libre-wuji not yet executed.",
horizon = 'Months,
},
d.make_transition {
from = "golden-image-v1",
to = "production",
condition = "zot deployed in libre-wuji with S3 backend (versioning + cross-region replication); multi-tenant auth configured (daoshi-CI write to /images /cache /sccache /crates; wuji-pods read /images; operators write /crates); BuildKit registry-cache and sccache S3 backend pointing at zot.wuji.local proven on Vapora-class build with measured cold-spawn-to-completion time; OOM auto-retry verified once and bounded; weekly golden image rebuild running on schedule with no manual intervention; cross-provider replication tested via failover drill.",
catalyst = "Production deploys via ops contract (ADR-037) require image artifacts in zot — build infrastructure is on the critical path for the deploy-from-CI flow.",
blocker = "Golden image v1 phase incomplete; zot still in libre-daoshi; observability for build metrics (Prometheus on builder VMs) not deployed.",
horizon = 'Months,
},
],
},
],
}

56
.ontology/workflow.ncl Normal file
View file

@ -0,0 +1,56 @@
let W = import "reflection/schemas/workflow.ncl" in
let D = import "reflection/defaults/workflow.ncl" in
# Workflow declaration for provisioning.
# Each layer is independent — layers form a set, not a chain.
# Regenerate artifacts after editing: ore workflow generate
# Preview changes: ore workflow diff
{
layers = [
# ── Commit-fast: pre-commit local checks ─────────────────────────────────
# Generates entries for .pre-commit-config.yaml (printed for manual merge).
{
id = "commit-fast",
trigger = 'OnCommit,
validations = [
"rust-fmt",
"rust-clippy",
"nextest-ci-test",
"deny-subset",
"docs-drift",
"manifest-coverage",
],
builds = [],
distributions = [],
providers = [W.pre_commit "pre-commit"],
},
# ── CI-standard: push/PR pipeline ────────────────────────────────────────
# Generates .woodpecker/ci.yml and justfiles/workflow.just.
{
id = "ci-standard",
trigger = 'OnPR,
validations = [
"rust-clippy-all",
"nextest-ci",
"deny-subset",
"docs-check",
"nickel-typecheck",
"nushell-check",
],
builds = ["release-native"],
distributions = [],
providers = [
W.woodpecker ".woodpecker/ci.yml",
W.justfile "ci-standard",
],
},
],
validations = D.validations,
builds = D.builds,
distributions = {},
}

View file

@ -92,7 +92,7 @@ vim .typedialog/ci/config.ncl
**This project uses Nickel format by default** for all configuration files.
### Why Nickel?
### Why Nickel
- ✅ **Typed configuration** - Static type checking with `nickel typecheck`
- ✅ **Documentation** - Generate docs with `nickel doc config.ncl`
@ -320,7 +320,7 @@ Edit `config.ncl` and add under `ci.tools`:
enable_pre_commit = false
```
## Need Help?
## Need Help
For detailed documentation, see:

View file

@ -1,4 +1,7 @@
# AI Service DAG Workflow Configuration Fragment
name = "dag"
description = "AI Service DAG Workflow Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -15,7 +18,8 @@ min = 1
name = "ai_dag_max_concurrent_tasks"
nickel_path = ["ai_service", "dag", "max_concurrent_tasks"]
prompt = "Max Concurrent Tasks"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = 600000
@ -25,7 +29,8 @@ min = 10000
name = "ai_dag_task_timeout"
nickel_path = ["ai_service", "dag", "task_timeout"]
prompt = "Task Timeout (ms)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = 5
@ -35,4 +40,5 @@ min = 0
name = "ai_dag_retry_attempts"
nickel_path = ["ai_service", "dag", "retry_attempts"]
prompt = "Retry Attempts"
type = "number"
type = "custom"
custom_type = "Number"

View file

@ -1,4 +1,7 @@
# AI Service MCP Integration Fragment
name = "mcp_integration"
description = "AI Service MCP Integration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -34,4 +37,5 @@ min = 1000
name = "ai_mcp_timeout"
nickel_path = ["ai_service", "mcp", "timeout"]
prompt = "Timeout (ms)"
type = "number"
type = "custom"
custom_type = "Number"

View file

@ -1,4 +1,7 @@
# AI Service Monitoring Configuration Fragment
name = "monitoring"
description = "AI Service Monitoring Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -24,4 +27,5 @@ min = 5000
name = "ai_monitoring_metrics_interval"
nickel_path = ["ai_service", "monitoring", "metrics_interval"]
prompt = "Metrics Interval (ms)"
type = "number"
type = "custom"
custom_type = "Number"

View file

@ -1,4 +1,7 @@
# AI Service RAG Integration Fragment
name = "rag_integration"
description = "AI Service RAG Integration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -34,4 +37,5 @@ min = 1000
name = "ai_rag_timeout"
nickel_path = ["ai_service", "rag", "timeout"]
prompt = "Timeout (ms)"
type = "number"
type = "custom"
custom_type = "Number"

View file

@ -1,4 +1,7 @@
# AI Service Server Configuration Fragment
name = "server"
description = "AI Service Server Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -25,7 +28,8 @@ name = "ai_service_server_port"
nickel_path = ["ai_service", "server", "port"]
prompt = "Server Port"
required = true
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = 4
@ -36,4 +40,5 @@ name = "ai_service_server_workers"
nickel_path = ["ai_service", "server", "workers"]
prompt = "Worker Threads"
required = true
type = "number"
type = "custom"
custom_type = "Number"

View file

@ -2,7 +2,8 @@
## Overview
TypeDialog form fields can reference constraints from `constraints.toml` using Jinja2-style template syntax. This provides a **single source of truth** for validation limits across forms, Nickel schemas, and validators.
TypeDialog form fields can reference constraints from `constraints.toml` using Jinja2-style template syntax.
This provides a **single source of truth** for validation limits across forms, Nickel schemas, and validators.
## Pattern

View file

@ -6,7 +6,9 @@
## Summary
Constraint interpolation has been implemented for critical numeric form fields, providing a single source of truth for validation limits. The comprehensive mapping guide documents which constraints should be applied to remaining fragments.
Constraint interpolation has been implemented for critical numeric form fields, providing a single
source of truth for validation limits. The comprehensive mapping guide documents which constraints
should be applied to remaining fragments.
## Completed Fragments ✅
@ -295,4 +297,5 @@ Ready to proceed with implementation:
---
**To contribute**: Pick any unchecked fragment above and follow the pattern in `constraint_interpolation_guide.md`. Each constraint update takes ~5 minutes per fragment.
**To contribute**: Pick any unchecked fragment above and follow the pattern in
`constraint_interpolation_guide.md`. Each constraint update takes ~5 minutes per fragment.

View file

@ -1,4 +1,7 @@
# Control Center Compliance & Audit Configuration Fragment
name = "compliance_section"
description = "Control Center Compliance & Audit Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -25,7 +28,8 @@ min = "${constraint.control_center.audit.retention_days.min}"
name = "audit_retention_days"
nickel_path = ["audit", "storage", "retention_days"]
prompt = "Audit Retention (days)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "audit_enabled == true"
@ -72,7 +76,8 @@ min = 1
name = "compliance_validation_interval"
nickel_path = ["compliance", "validation", "interval_hours"]
prompt = "Validation Interval (hours)"
type = "number"
type = "custom"
custom_type = "Number"
# Data Retention
[[elements]]
@ -84,7 +89,8 @@ min = 1
name = "compliance_data_retention_years"
nickel_path = ["compliance", "data_retention", "policy_years"]
prompt = "Data Retention Policy (years)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "compliance_enabled == true"
@ -95,7 +101,8 @@ min = 90
name = "compliance_audit_log_days"
nickel_path = ["compliance", "data_retention", "audit_log_days"]
prompt = "Audit Log Retention (days)"
type = "number"
type = "custom"
custom_type = "Number"
# Encryption Requirements
[[elements]]

View file

@ -1,4 +1,7 @@
# Control Center Policy Engine Configuration Fragment
name = "policy_section"
description = "Control Center Policy Engine Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -33,7 +36,8 @@ min = 60
name = "policy_cache_ttl"
nickel_path = ["policy", "cache", "ttl"]
prompt = "Cache TTL (seconds)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "policy_enabled == true && policy_cache_enabled == true"
@ -44,7 +48,8 @@ min = 100
name = "policy_cache_max_policies"
nickel_path = ["policy", "cache", "max_policies"]
prompt = "Max Cached Policies"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "policy_enabled == true"
@ -64,4 +69,5 @@ min = 1
name = "policy_versioning_max_versions"
nickel_path = ["policy", "versioning", "max_versions"]
prompt = "Max Policy Versions"
type = "number"
type = "custom"
custom_type = "Number"

View file

@ -1,4 +1,7 @@
# Control Center RBAC Configuration Fragment
name = "rbac_section"
description = "Control Center RBAC Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false

View file

@ -1,5 +1,7 @@
# Control Center Security Configuration Fragment
# JWT, RBAC, MFA, rate limiting
name = "security_section"
description = "Control Center Security Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -47,7 +49,8 @@ min = "${constraint.control_center.jwt.token_expiration.min}"
name = "jwt_token_expiration"
nickel_path = ["security", "jwt", "token_expiration"]
prompt = "Token Expiration (seconds)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "jwt_enabled == true"
@ -58,7 +61,8 @@ min = "${constraint.control_center.jwt.refresh_expiration.min}"
name = "jwt_refresh_expiration"
nickel_path = ["security", "jwt", "refresh_expiration"]
prompt = "Refresh Token Expiration (seconds)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "jwt_enabled == true"
@ -124,7 +128,8 @@ min = "${constraint.control_center.rate_limiting.max_requests.min}"
name = "rate_limiting_max_requests"
nickel_path = ["security", "rate_limiting", "max_requests"]
prompt = "Max Requests per Window"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "rate_limiting_enabled == true"
@ -135,7 +140,8 @@ min = "${constraint.control_center.rate_limiting.window_seconds.min}"
name = "rate_limiting_window"
nickel_path = ["security", "rate_limiting", "window_seconds"]
prompt = "Rate Limit Window (seconds)"
type = "number"
type = "custom"
custom_type = "Number"
# TLS Configuration
[[elements]]
@ -163,7 +169,8 @@ min = 300
name = "sessions_max_age"
nickel_path = ["security", "sessions", "max_age"]
prompt = "Session Max Age (seconds)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "sessions_enabled == true"

View file

@ -1,4 +1,7 @@
# Control Center User Management Configuration Fragment
name = "users_section"
description = "Control Center User Management Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -54,7 +57,8 @@ min = 1
name = "users_sessions_max_active"
nickel_path = ["users", "sessions", "max_active"]
prompt = "Max Active Sessions per User"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "users_enabled == true"
@ -65,7 +69,8 @@ min = 300
name = "users_sessions_idle_timeout"
nickel_path = ["users", "sessions", "idle_timeout"]
prompt = "Session Idle Timeout (seconds)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "users_enabled == true"
@ -76,7 +81,8 @@ min = 3600
name = "users_sessions_absolute_timeout"
nickel_path = ["users", "sessions", "absolute_timeout"]
prompt = "Absolute Session Timeout (seconds)"
type = "number"
type = "custom"
custom_type = "Number"
# User Audit
[[elements]]

View file

@ -1,5 +1,7 @@
# PostgreSQL Database Configuration Fragment
# Used by: control-center, installer (when backend = postgresql)
name = "database_postgres_section"
description = "PostgreSQL Database Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -33,7 +35,8 @@ min = "${constraint.common.server.port.min}"
name = "database_postgres_port"
nickel_path = ["database", "port"]
prompt = "PostgreSQL Port"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
help = "PostgreSQL database name"
@ -68,7 +71,8 @@ min = 5
name = "database_pool_size"
nickel_path = ["database", "pool_size"]
prompt = "Connection Pool Size"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = 30
@ -78,7 +82,8 @@ min = 10
name = "database_timeout"
nickel_path = ["database", "timeout"]
prompt = "Timeout (seconds)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = 3
@ -88,7 +93,8 @@ min = 0
name = "database_retry_attempts"
nickel_path = ["database", "retry_attempts"]
prompt = "Retry Attempts"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = 100
@ -98,4 +104,5 @@ min = 1000
name = "database_retry_delay"
nickel_path = ["database", "retry_delay"]
prompt = "Retry Delay (ms)"
type = "number"
type = "custom"
custom_type = "Number"

View file

@ -1,5 +1,7 @@
# RocksDB Database Configuration Fragment
# Used by: control-center, installer (when backend = rocksdb)
name = "database_rocksdb_section"
description = "RocksDB Database Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -33,7 +35,8 @@ min = 1
name = "database_pool_size"
nickel_path = ["database", "pool_size"]
prompt = "Connection Pool Size"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = 30
@ -43,7 +46,8 @@ min = 10
name = "database_timeout"
nickel_path = ["database", "timeout"]
prompt = "Timeout (seconds)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = 3
@ -53,7 +57,8 @@ min = 0
name = "database_retry_attempts"
nickel_path = ["database", "retry_attempts"]
prompt = "Retry Attempts"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = 100
@ -63,4 +68,5 @@ min = 1000
name = "database_retry_delay"
nickel_path = ["database", "retry_delay"]
prompt = "Retry Delay (ms)"
type = "number"
type = "custom"
custom_type = "Number"

View file

@ -1,5 +1,7 @@
# SurrealDB Database Configuration Fragment
# Used by: orchestrator, control-center (when backend = surrealdb)
name = "database_surrealdb_section"
description = "SurrealDB Database Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -48,7 +50,8 @@ min = 1
name = "database_pool_size"
nickel_path = ["database", "pool_size"]
prompt = "Connection Pool Size"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = 30
@ -58,7 +61,8 @@ min = 10
name = "database_timeout"
nickel_path = ["database", "timeout"]
prompt = "Timeout (seconds)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = 3
@ -68,7 +72,8 @@ min = 0
name = "database_retry_attempts"
nickel_path = ["database", "retry_attempts"]
prompt = "Retry Attempts"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = 100
@ -78,4 +83,5 @@ min = 1000
name = "database_retry_delay"
nickel_path = ["database", "retry_delay"]
prompt = "Retry Delay (ms)"
type = "number"
type = "custom"
custom_type = "Number"

View file

@ -1,6 +1,7 @@
# Database Backend Selection Fragment
# This fragment allows selecting the appropriate database backend (RocksDB, SurrealDB, PostgreSQL)
# Based on the selection, include the corresponding database-*-section.toml fragment
name = "database_backend_selection"
description = "Database Backend Selection Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -26,7 +27,7 @@ default = false
help = "RocksDB: Embedded key-value store. Zero external dependencies, local filesystem storage, good for solo/multiuser modes. Limited to single instance."
name = "rocksdb_info"
prompt = "RocksDB Info"
type = "info"
type = "section"
[[elements]]
condition = "database_backend_selection == 'surrealdb_embedded'"
@ -34,7 +35,7 @@ default = false
help = "SurrealDB (Embedded): In-process SurrealDB. No external server needed, queryable JSON/SQL, suitable for small to medium deployments."
name = "surrealdb_embedded_info"
prompt = "SurrealDB Embedded Info"
type = "info"
type = "section"
[[elements]]
condition = "database_backend_selection == 'surrealdb_server'"
@ -42,7 +43,7 @@ default = false
help = "SurrealDB (Server): External SurrealDB server. Scalable multi-instance, HA ready, suitable for multiuser/enterprise modes."
name = "surrealdb_server_info"
prompt = "SurrealDB Server Info"
type = "info"
type = "section"
[[elements]]
condition = "database_backend_selection == 'postgresql'"
@ -50,7 +51,7 @@ default = false
help = "PostgreSQL: Traditional RDBMS. Proven stability, full ACID, complex queries, suitable for enterprise with HA via replication."
name = "postgresql_info"
prompt = "PostgreSQL Info"
type = "info"
type = "section"
# Backend Selection Guidelines
[[elements]]
@ -66,7 +67,7 @@ default = false
help = "Recommended for Solo: RocksDB (simplest) or SurrealDB Embedded (more features, same simplicity)"
name = "solo_recommendation"
prompt = "Solo Recommendation"
type = "info"
type = "section"
[[elements]]
condition = "deployment_mode == 'multiuser'"
@ -74,7 +75,7 @@ default = false
help = "Recommended for MultiUser: SurrealDB Server (scalable, easy clustering) or PostgreSQL (if you need traditional RDBMS)"
name = "multiuser_recommendation"
prompt = "MultiUser Recommendation"
type = "info"
type = "section"
[[elements]]
condition = "deployment_mode == 'cicd'"
@ -82,7 +83,7 @@ default = false
help = "Recommended for CI/CD: SurrealDB Embedded (ephemeral, no external deps) or RocksDB (fastest)"
name = "cicd_recommendation"
prompt = "CI/CD Recommendation"
type = "info"
type = "section"
[[elements]]
condition = "deployment_mode == 'enterprise'"
@ -90,4 +91,4 @@ default = false
help = "Recommended for Enterprise: SurrealDB Server HA (native clustering) or PostgreSQL with replication + external backup service"
name = "enterprise_recommendation"
prompt = "Enterprise Recommendation"
type = "info"
type = "section"

View file

@ -1,4 +1,7 @@
# Deployment Mode Selection Fragment
name = "mode_selection"
description = "Deployment Mode Selection Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -32,7 +35,7 @@ default = false
help = "Solo Mode: Single developer environment. Filesystem/RocksDB storage, 2-4 CPU cores, 4GB RAM. Minimal security, no HA. Ideal for local development and testing."
name = "mode_solo_info"
prompt = "Solo Mode"
type = "info"
type = "section"
# MultiUser Mode Info (conditional)
[[elements]]
@ -41,7 +44,7 @@ default = false
help = "MultiUser Mode: Team development environment. PostgreSQL/SurrealDB, 4-8 CPU cores, 8GB RAM. RBAC enabled, shared storage, staging-ready. Ideal for team collaboration."
name = "mode_multiuser_info"
prompt = "MultiUser Mode"
type = "info"
type = "section"
# CI/CD Mode Info (conditional)
[[elements]]
@ -50,7 +53,7 @@ default = false
help = "CI/CD Mode: Automated testing and pipeline environment. Ephemeral storage, 8+ CPU cores, 16GB RAM. API-driven, minimal UI, optimized for throughput. Ideal for automated testing."
name = "mode_cicd_info"
prompt = "CI/CD Mode"
type = "info"
type = "section"
# Enterprise Mode Info (conditional)
[[elements]]
@ -59,7 +62,7 @@ default = false
help = "Enterprise Mode: Production high-availability environment. SurrealDB cluster, PostgreSQL HA, 16+ CPU cores, 32+ GB RAM. MFA required, compliance, full monitoring. Ideal for production deployments."
name = "mode_enterprise_info"
prompt = "Enterprise Mode"
type = "info"
type = "section"
# Mode-Specific Default Values (informational)
[[elements]]

View file

@ -1,4 +1,7 @@
# Extension Registry Authentication Fragment
name = "auth"
description = "Extension Registry Authentication Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false

View file

@ -1,4 +1,7 @@
# Extension Registry Cache Configuration Fragment
name = "cache"
description = "Extension Registry Cache Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -15,7 +18,8 @@ min = 10
name = "registry_cache_capacity"
nickel_path = ["extension_registry", "cache", "capacity"]
prompt = "Cache Capacity"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = 300
@ -25,7 +29,8 @@ min = 30
name = "registry_cache_ttl"
nickel_path = ["extension_registry", "cache", "ttl"]
prompt = "Cache TTL (seconds)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = true

View file

@ -1,4 +1,7 @@
# Extension Registry Gitea Configuration Fragment
name = "gitea"
description = "Extension Registry Gitea Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -44,7 +47,8 @@ min = 5000
name = "registry_gitea_timeout"
nickel_path = ["extension_registry", "gitea", "timeout"]
prompt = "Timeout (ms)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "registry_gitea_enabled == true"

View file

@ -1,4 +1,7 @@
# Extension Registry OCI Configuration Fragment
name = "oci"
description = "Extension Registry OCI Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -44,7 +47,8 @@ min = 5000
name = "registry_oci_timeout"
nickel_path = ["extension_registry", "oci", "timeout"]
prompt = "Timeout (ms)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "registry_oci_enabled == true"

View file

@ -1,4 +1,7 @@
# Extension Registry Server Configuration Fragment
name = "server"
description = "Extension Registry Server Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -25,7 +28,8 @@ name = "registry_server_port"
nickel_path = ["extension_registry", "server", "port"]
prompt = "Server Port"
required = true
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = 4
@ -36,7 +40,8 @@ name = "registry_server_workers"
nickel_path = ["extension_registry", "server", "workers"]
prompt = "Worker Threads"
required = true
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = false

View file

@ -1,4 +1,7 @@
# Installer Database Configuration Fragment
name = "database_section"
description = "Installer Database Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -62,7 +65,8 @@ min = 30
name = "migration_timeout_seconds"
nickel_path = ["installer", "database", "migrations", "timeout_seconds"]
prompt = "Migration Timeout (seconds)"
type = "number"
type = "custom"
custom_type = "Number"
# Database Backup
[[elements]]
@ -110,7 +114,8 @@ min = 1
name = "backup_retention_days"
nickel_path = ["installer", "database", "backup", "retention_days"]
prompt = "Backup Retention (days)"
type = "number"
type = "custom"
custom_type = "Number"
# Database Verification
[[elements]]
@ -185,7 +190,8 @@ min = 1
name = "connection_pool_size"
nickel_path = ["installer", "database", "pool_size"]
prompt = "Connection Pool Size"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = 300
@ -195,7 +201,8 @@ min = 10
name = "connection_pool_timeout"
nickel_path = ["installer", "database", "pool_timeout_seconds"]
prompt = "Pool Timeout (seconds)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = 3600
@ -205,7 +212,8 @@ min = 60
name = "connection_idle_timeout"
nickel_path = ["installer", "database", "idle_timeout_seconds"]
prompt = "Idle Timeout (seconds)"
type = "number"
type = "custom"
custom_type = "Number"
# Database Optimization
[[elements]]

View file

@ -1,4 +1,7 @@
# Installer High Availability Configuration Fragment
name = "ha_section"
description = "Installer High Availability Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -26,7 +29,8 @@ min = 3
name = "ha_cluster_size"
nickel_path = ["installer", "ha", "cluster_size"]
prompt = "Cluster Size"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "ha_enabled == true"
@ -87,7 +91,8 @@ min = 1
name = "ha_db_quorum_size"
nickel_path = ["installer", "ha", "database", "quorum_size"]
prompt = "DB Quorum Size"
type = "number"
type = "custom"
custom_type = "Number"
# Health Checks
[[elements]]
@ -108,7 +113,8 @@ min = 1
name = "ha_health_check_interval"
nickel_path = ["installer", "ha", "health_checks", "interval_seconds"]
prompt = "Health Check Interval (seconds)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "ha_health_checks_enabled == true"
@ -119,7 +125,8 @@ min = 1000
name = "ha_health_check_timeout"
nickel_path = ["installer", "ha", "health_checks", "timeout_ms"]
prompt = "Health Check Timeout (ms)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "ha_health_checks_enabled == true"
@ -130,7 +137,8 @@ min = 1
name = "ha_health_check_failure_threshold"
nickel_path = ["installer", "ha", "health_checks", "failure_threshold"]
prompt = "Failure Threshold"
type = "number"
type = "custom"
custom_type = "Number"
# Failover Configuration
[[elements]]
@ -161,7 +169,8 @@ min = 0
name = "ha_failover_delay"
nickel_path = ["installer", "ha", "failover", "delay_seconds"]
prompt = "Failover Delay (seconds)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "ha_failover_enabled == true && ha_failover_strategy == 'priority_based'"
@ -172,7 +181,8 @@ min = 0
name = "ha_node_priority"
nickel_path = ["installer", "ha", "failover", "node_priority"]
prompt = "Node Priority"
type = "number"
type = "custom"
custom_type = "Number"
# Split Brain Prevention
[[elements]]
@ -193,7 +203,8 @@ min = 5
name = "ha_split_brain_timeout"
nickel_path = ["installer", "ha", "split_brain", "timeout_seconds"]
prompt = "Split-Brain Timeout (seconds)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "ha_split_brain_enabled == true"
@ -224,7 +235,8 @@ min = 300
name = "ha_backup_interval"
nickel_path = ["installer", "ha", "backup", "interval_seconds"]
prompt = "Backup Interval (seconds)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "ha_backup_enabled == true"
@ -235,7 +247,8 @@ min = 1
name = "ha_backup_retention_days"
nickel_path = ["installer", "ha", "backup", "retention_days"]
prompt = "Backup Retention (days)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "ha_backup_enabled == true"
@ -285,4 +298,5 @@ min = 5
name = "ha_metrics_interval"
nickel_path = ["installer", "ha", "metrics", "interval_seconds"]
prompt = "Metrics Interval (seconds)"
type = "number"
type = "custom"
custom_type = "Number"

View file

@ -1,4 +1,7 @@
# Installer Installation Strategy Configuration Fragment
name = "installation_section"
description = "Installer Installation Strategy Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -26,7 +29,8 @@ min = 1
name = "parallel_services"
nickel_path = ["installer", "installation", "parallel_services"]
prompt = "Parallel Services"
type = "number"
type = "custom"
custom_type = "Number"
# Installation Timeout
[[elements]]
@ -37,7 +41,8 @@ min = 0
name = "installation_timeout_seconds"
nickel_path = ["installer", "installation", "timeout_seconds"]
prompt = "Installation Timeout (seconds)"
type = "number"
type = "custom"
custom_type = "Number"
# Rollback Strategy
[[elements]]
@ -183,7 +188,8 @@ min = 5000
name = "validation_timeout"
nickel_path = ["installer", "installation", "validation", "timeout_ms"]
prompt = "Validation Timeout (ms)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "validate_installation == true"
@ -221,7 +227,8 @@ min = 1
name = "auto_recovery_max_attempts"
nickel_path = ["installer", "installation", "auto_recovery", "max_attempts"]
prompt = "Max Recovery Attempts"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "auto_recovery_enabled == true"
@ -231,4 +238,5 @@ min = 5
name = "auto_recovery_delay_seconds"
nickel_path = ["installer", "installation", "auto_recovery", "delay_seconds"]
prompt = "Recovery Delay (seconds)"
type = "number"
type = "custom"
custom_type = "Number"

View file

@ -1,4 +1,7 @@
# Installer Networking Configuration Fragment
name = "networking_section"
description = "Installer Networking Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -61,7 +64,8 @@ min = 1
name = "dns_port"
nickel_path = ["installer", "networking", "dns", "port"]
prompt = "DNS Port"
type = "number"
type = "custom"
custom_type = "Number"
# TLS/HTTPS Configuration
[[elements]]
@ -146,7 +150,8 @@ min = 1
name = "firewall_rate_limit_rpm"
nickel_path = ["installer", "networking", "firewall", "rate_limiting", "requests_per_minute"]
prompt = "Rate Limit (req/min)"
type = "number"
type = "custom"
custom_type = "Number"
# Load Balancer Configuration
[[elements]]
@ -176,7 +181,8 @@ min = "${constraint.common.server.port.min}"
name = "load_balancer_http_port"
nickel_path = ["installer", "networking", "load_balancer", "http_port"]
prompt = "Load Balancer HTTP Port"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "install_load_balancer == true"
@ -187,7 +193,8 @@ min = "${constraint.common.server.port.min}"
name = "load_balancer_https_port"
nickel_path = ["installer", "networking", "load_balancer", "https_port"]
prompt = "Load Balancer HTTPS Port"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "install_load_balancer == true"
@ -282,4 +289,5 @@ min = 5
name = "traffic_monitoring_interval"
nickel_path = ["installer", "networking", "monitoring", "interval_seconds"]
prompt = "Monitoring Interval (seconds)"
type = "number"
type = "custom"
custom_type = "Number"

View file

@ -1,4 +1,7 @@
# Installer Post-Installation Configuration Fragment
name = "post_install_section"
description = "Installer Post-Installation Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -139,7 +142,8 @@ min = 30
name = "verification_timeout"
nickel_path = ["installer", "post_install", "verification", "timeout_seconds"]
prompt = "Verification Timeout (seconds)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "run_verification_tests == true"

View file

@ -1,4 +1,7 @@
# Installer Preflight Checks Configuration Fragment
name = "preflight_section"
description = "Installer Preflight Checks Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -25,7 +28,8 @@ min = 1
name = "min_disk_gb"
nickel_path = ["installer", "preflight", "disk_space_check", "min_disk_gb"]
prompt = "Min Disk Space (GB)"
type = "number"
type = "custom"
custom_type = "Number"
# Memory Check
[[elements]]
@ -45,7 +49,8 @@ min = 1
name = "min_memory_gb"
nickel_path = ["installer", "preflight", "memory_check", "min_memory_gb"]
prompt = "Min Memory (GB)"
type = "number"
type = "custom"
custom_type = "Number"
# CPU Check
[[elements]]
@ -65,7 +70,8 @@ min = 1
name = "min_cpu_cores"
nickel_path = ["installer", "preflight", "cpu_check", "min_cpu_cores"]
prompt = "Min CPU Cores"
type = "number"
type = "custom"
custom_type = "Number"
# Network Check
[[elements]]

View file

@ -1,4 +1,7 @@
# Installer Services Selection Fragment
name = "services_section"
description = "Installer Services Selection Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -125,7 +128,8 @@ min = "${constraint.common.server.port.min}"
name = "orchestrator_port"
nickel_path = ["installer", "services", "orchestrator", "port"]
prompt = "Orchestrator Port"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "install_control_center == true"
@ -136,7 +140,8 @@ min = "${constraint.common.server.port.min}"
name = "control_center_port"
nickel_path = ["installer", "services", "control_center", "port"]
prompt = "Control Center Port"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "install_mcp_server == true"
@ -147,7 +152,8 @@ min = "${constraint.common.server.port.min}"
name = "mcp_server_port"
nickel_path = ["installer", "services", "mcp_server", "port"]
prompt = "MCP Server Port"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "install_api_gateway == true"
@ -158,7 +164,8 @@ min = "${constraint.common.server.port.min}"
name = "api_gateway_port"
nickel_path = ["installer", "services", "api_gateway", "port"]
prompt = "API Gateway Port"
type = "number"
type = "custom"
custom_type = "Number"
# Service Update Strategy
[[elements]]
@ -186,4 +193,5 @@ min = 5
name = "health_check_interval"
nickel_path = ["installer", "services", "health_checks", "interval_seconds"]
prompt = "Health Check Interval (seconds)"
type = "number"
type = "custom"
custom_type = "Number"

View file

@ -1,4 +1,7 @@
# Installer Storage Configuration Fragment
name = "storage_section"
description = "Installer Storage Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -25,7 +28,8 @@ min = 10
name = "storage_size_gb"
nickel_path = ["installer", "storage", "size_gb"]
prompt = "Storage Size (GB)"
type = "number"
type = "custom"
custom_type = "Number"
# Storage Backend Selection
[[elements]]
@ -193,7 +197,8 @@ min = 2
name = "storage_replication_factor"
nickel_path = ["installer", "storage", "replication", "factor"]
prompt = "Replication Factor"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "storage_replication_enabled == true"
@ -223,7 +228,8 @@ min = 7
name = "storage_cleanup_retention_days"
nickel_path = ["installer", "storage", "cleanup", "retention_days"]
prompt = "Retention Period (days)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "storage_cleanup_enabled == true"

View file

@ -1,4 +1,7 @@
# Installer Target Configuration Fragment
name = "target_section"
description = "Installer Target Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -49,7 +52,8 @@ min = "${constraint.common.server.port.min}"
name = "remote_ssh_port"
nickel_path = ["installer", "target", "remote_ssh_port"]
prompt = "SSH Port"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "target_type == 'remote'"

View file

@ -1,4 +1,7 @@
# Installer Upgrades Configuration Fragment
name = "upgrades_section"
description = "Installer Upgrades Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -63,7 +66,8 @@ min = 1
name = "rolling_upgrade_parallel"
nickel_path = ["installer", "upgrades", "rolling", "parallel_services"]
prompt = "Parallel Services"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "upgrade_strategy == 'canary'"
@ -74,7 +78,8 @@ min = 1
name = "canary_percentage"
nickel_path = ["installer", "upgrades", "canary", "traffic_percentage"]
prompt = "Canary Traffic %"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "upgrade_strategy == 'canary'"
@ -85,7 +90,8 @@ min = 30
name = "canary_duration_seconds"
nickel_path = ["installer", "upgrades", "canary", "duration_seconds"]
prompt = "Canary Duration (seconds)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "upgrade_strategy == 'maintenance_window'"
@ -115,7 +121,8 @@ min = 600
name = "maintenance_duration_seconds"
nickel_path = ["installer", "upgrades", "maintenance_window", "max_duration_seconds"]
prompt = "Max Duration (seconds)"
type = "number"
type = "custom"
custom_type = "Number"
# Pre-Upgrade Checks
[[elements]]
@ -190,7 +197,8 @@ min = 5
name = "backup_timeout_minutes"
nickel_path = ["installer", "upgrades", "backup_timeout_minutes"]
prompt = "Backup Timeout (minutes)"
type = "number"
type = "custom"
custom_type = "Number"
# Upgrade Rollback
[[elements]]
@ -220,7 +228,8 @@ min = 30
name = "rollback_validation_delay"
nickel_path = ["installer", "upgrades", "rollback", "validation_delay_seconds"]
prompt = "Validation Delay (seconds)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "enable_rollback_on_failure == true"
@ -290,7 +299,8 @@ min = 5
name = "post_upgrade_health_check_interval"
nickel_path = ["installer", "upgrades", "post_upgrade", "health_check_interval_seconds"]
prompt = "Health Check Interval (seconds)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "health_checks_post_upgrade == true"
@ -301,7 +311,8 @@ min = 60
name = "post_upgrade_monitoring_duration"
nickel_path = ["installer", "upgrades", "post_upgrade", "monitoring_duration_seconds"]
prompt = "Monitoring Duration (seconds)"
type = "number"
type = "custom"
custom_type = "Number"
# Version Constraints
[[elements]]

View file

@ -1,5 +1,7 @@
# Logging Configuration Fragment
# Optional for all services
name = "logging_section"
description = "Logging Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -43,7 +45,8 @@ min = "${constraint.common.logging.max_file_size.min}"
name = "logging_max_file_size"
nickel_path = ["logging", "file", "max_size"]
prompt = "Max File Size (bytes)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "logging_file_enabled == true"
@ -54,4 +57,5 @@ min = "${constraint.common.logging.max_backups.min}"
name = "logging_max_backups"
nickel_path = ["logging", "file", "max_backups"]
prompt = "Max Backup Files"
type = "number"
type = "custom"
custom_type = "Number"

View file

@ -1,4 +1,7 @@
# MCP Server Prompts Configuration Fragment
name = "prompts_section"
description = "MCP Server Prompts Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -24,7 +27,8 @@ min = "${constraint.mcp_server.prompts.max_templates.min}"
name = "prompts_max_templates"
nickel_path = ["prompts", "max_templates"]
prompt = "Max Prompt Templates"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "prompts_enabled == true"
@ -44,7 +48,8 @@ min = 60
name = "prompts_cache_ttl"
nickel_path = ["prompts", "cache", "ttl"]
prompt = "Cache TTL (seconds)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "prompts_enabled == true"
@ -64,4 +69,5 @@ min = 1
name = "prompts_versioning_max_versions"
nickel_path = ["prompts", "versioning", "max_versions"]
prompt = "Max Prompt Versions"
type = "number"
type = "custom"
custom_type = "Number"

View file

@ -1,4 +1,7 @@
# MCP Server Resources Configuration Fragment
name = "resources_section"
description = "MCP Server Resources Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -24,7 +27,8 @@ min = "${constraint.mcp_server.resources.max_size.min}"
name = "resources_max_size"
nickel_path = ["resources", "max_size"]
prompt = "Max Resource Size (bytes)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "resources_enabled == true"
@ -44,7 +48,8 @@ min = 10
name = "resources_cache_max_size_mb"
nickel_path = ["resources", "cache", "max_size_mb"]
prompt = "Max Cache Size (MB)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "resources_enabled == true && resources_cache_enabled == true"
@ -55,7 +60,8 @@ min = "${constraint.mcp_server.resources.cache_ttl.min}"
name = "resources_cache_ttl"
nickel_path = ["resources", "cache", "ttl"]
prompt = "Cache TTL (seconds)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "resources_enabled == true"
@ -75,4 +81,5 @@ min = 1
name = "resources_validation_max_depth"
nickel_path = ["resources", "validation", "max_depth"]
prompt = "Max Nesting Depth"
type = "number"
type = "custom"
custom_type = "Number"

View file

@ -1,4 +1,7 @@
# MCP Server Sampling Configuration Fragment
name = "sampling_section"
description = "MCP Server Sampling Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -24,7 +27,8 @@ min = "${constraint.mcp_server.sampling.max_tokens.min}"
name = "sampling_max_tokens"
nickel_path = ["sampling", "max_tokens"]
prompt = "Max Tokens"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "sampling_enabled == true"
@ -44,7 +48,8 @@ min = 0.0
name = "sampling_temperature"
nickel_path = ["sampling", "temperature"]
prompt = "Temperature"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "sampling_enabled == true"
@ -64,4 +69,5 @@ min = 60
name = "sampling_cache_ttl"
nickel_path = ["sampling", "cache", "ttl"]
prompt = "Cache TTL (seconds)"
type = "number"
type = "custom"
custom_type = "Number"

View file

@ -1,4 +1,7 @@
# MCP Server Tools Configuration Fragment
name = "tools_section"
description = "MCP Server Tools Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -24,7 +27,8 @@ min = "${constraint.mcp_server.tools.max_concurrent.min}"
name = "tools_max_concurrent"
nickel_path = ["tools", "max_concurrent"]
prompt = "Max Concurrent Tools"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "tools_enabled == true"
@ -35,7 +39,8 @@ min = "${constraint.mcp_server.tools.timeout.min}"
name = "tools_timeout"
nickel_path = ["tools", "timeout"]
prompt = "Tool Timeout (ms)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "tools_enabled == true"
@ -72,4 +77,5 @@ min = 60
name = "tools_cache_ttl"
nickel_path = ["tools", "cache", "ttl"]
prompt = "Cache TTL (seconds)"
type = "number"
type = "custom"
custom_type = "Number"

View file

@ -1,5 +1,7 @@
# Monitoring Configuration Fragment
# Optional for all services
name = "monitoring_section"
description = "Monitoring Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -34,4 +36,5 @@ min = "${constraint.common.monitoring.metrics_interval.min}"
name = "monitoring_metrics_interval"
nickel_path = ["monitoring", "metrics", "interval"]
prompt = "Metrics Collection Interval (seconds)"
type = "number"
type = "custom"
custom_type = "Number"

View file

@ -1,4 +1,7 @@
# Orchestrator Batch Workflow Configuration Fragment
name = "batch_section"
description = "Orchestrator Batch Workflow Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -15,7 +18,8 @@ min = "${constraint.orchestrator.batch.parallel_limit.min}"
name = "batch_parallel_limit"
nickel_path = ["batch", "parallel_limit"]
prompt = "Parallel Limit"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = 1800000
@ -25,7 +29,8 @@ min = "${constraint.orchestrator.batch.operation_timeout.min}"
name = "batch_operation_timeout"
nickel_path = ["batch", "operation_timeout"]
prompt = "Operation Timeout (ms)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = true
@ -43,7 +48,8 @@ min = 10
name = "batch_checkpoint_interval"
nickel_path = ["batch", "checkpointing", "interval"]
prompt = "Checkpoint Interval"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "batch_checkpointing_enabled == true"
@ -53,7 +59,8 @@ min = 1
name = "batch_checkpoint_max_checkpoints"
nickel_path = ["batch", "checkpointing", "max_checkpoints"]
prompt = "Max Checkpoints"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = true
@ -82,7 +89,8 @@ min = 1
name = "batch_rollback_max_depth"
nickel_path = ["batch", "rollback", "max_rollback_depth"]
prompt = "Max Rollback Depth"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = false

View file

@ -1,4 +1,7 @@
# Orchestrator Extensions Configuration Fragment
name = "extensions_section"
description = "Orchestrator Extensions Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -65,7 +68,8 @@ min = 300
name = "extensions_discovery_interval"
nickel_path = ["orchestrator", "extensions", "discovery_interval_seconds"]
prompt = "Discovery Interval (seconds)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "auto_load_extensions == true"
@ -76,7 +80,8 @@ min = "${constraint.orchestrator.extensions.max_concurrent.min}"
name = "extensions_max_concurrent"
nickel_path = ["orchestrator", "extensions", "max_concurrent"]
prompt = "Max Concurrent Extensions"
type = "number"
type = "custom"
custom_type = "Number"
# Extension Execution Settings
[[elements]]
@ -88,7 +93,8 @@ min = 1000
name = "extensions_init_timeout"
nickel_path = ["orchestrator", "extensions", "init_timeout_ms"]
prompt = "Init Timeout (ms)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "auto_load_extensions == true"
@ -117,7 +123,8 @@ min = 64
name = "extensions_sandbox_max_memory_mb"
nickel_path = ["orchestrator", "extensions", "sandbox", "max_memory_mb"]
prompt = "Max Memory (MB)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "auto_load_extensions == true && extensions_sandbox_enabled == true"
@ -128,7 +135,8 @@ min = 0.1
name = "extensions_sandbox_max_cpu"
nickel_path = ["orchestrator", "extensions", "sandbox", "max_cpu"]
prompt = "Max CPU Cores"
type = "number"
type = "custom"
custom_type = "Number"
# Extension Versioning and Compatibility
[[elements]]
@ -168,7 +176,8 @@ min = 5000
name = "extensions_health_check_interval"
nickel_path = ["orchestrator", "extensions", "health_check", "interval_ms"]
prompt = "Health Check Interval (ms)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "auto_load_extensions == true && extensions_health_check_enabled == true"
@ -179,4 +188,5 @@ min = 1
name = "extensions_health_check_failure_threshold"
nickel_path = ["orchestrator", "extensions", "health_check", "failure_threshold"]
prompt = "Failure Threshold"
type = "number"
type = "custom"
custom_type = "Number"

View file

@ -1,4 +1,7 @@
# Orchestrator Performance Configuration Fragment
name = "performance_section"
description = "Orchestrator Performance Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -44,7 +47,8 @@ min = 256
name = "memory_max_heap_mb"
nickel_path = ["orchestrator", "performance", "memory_limits", "max_heap_mb"]
prompt = "Max Heap Memory (MB)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "memory_limits_enabled == true"
@ -55,7 +59,8 @@ min = 128
name = "memory_initial_heap_mb"
nickel_path = ["orchestrator", "performance", "memory_limits", "initial_heap_mb"]
prompt = "Initial Heap Memory (MB)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "memory_limits_enabled == true"
@ -66,7 +71,8 @@ min = 50
name = "memory_gc_threshold_percent"
nickel_path = ["orchestrator", "performance", "memory_limits", "gc_threshold_percent"]
prompt = "GC Threshold (%)"
type = "number"
type = "custom"
custom_type = "Number"
# Profiling Settings
[[elements]]
@ -96,7 +102,8 @@ min = 10
name = "profiling_sample_rate"
nickel_path = ["orchestrator", "performance", "profiling", "sample_rate_hz"]
prompt = "Sampling Rate (Hz)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "profiling_enabled == true"
@ -135,7 +142,8 @@ min = 1
name = "profiling_memory_min_size_kb"
nickel_path = ["orchestrator", "performance", "profiling", "memory_profiling", "min_alloc_kb"]
prompt = "Min Allocation Size (KB)"
type = "number"
type = "custom"
custom_type = "Number"
# Caching and Optimization
[[elements]]
@ -155,7 +163,8 @@ min = 1000
name = "inline_cache_max_entries"
nickel_path = ["orchestrator", "performance", "inline_cache", "max_entries"]
prompt = "Max Cache Entries"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "inline_cache_enabled == true"
@ -166,7 +175,8 @@ min = 60
name = "inline_cache_ttl"
nickel_path = ["orchestrator", "performance", "inline_cache", "ttl_seconds"]
prompt = "Cache TTL (seconds)"
type = "number"
type = "custom"
custom_type = "Number"
# Thread Pool Configuration
[[elements]]
@ -177,7 +187,8 @@ min = 1
name = "thread_pool_size"
nickel_path = ["orchestrator", "performance", "thread_pool", "size"]
prompt = "Thread Pool Size"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = 128
@ -187,7 +198,8 @@ min = 8
name = "thread_pool_queue_size"
nickel_path = ["orchestrator", "performance", "thread_pool", "queue_size"]
prompt = "Work Queue Size"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = "work_stealing"
@ -216,7 +228,8 @@ min = 1
name = "async_io_worker_threads"
nickel_path = ["orchestrator", "performance", "async_io", "worker_threads"]
prompt = "I/O Worker Threads"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "async_io_enabled == true"
@ -227,4 +240,5 @@ min = 256
name = "async_io_max_in_flight"
nickel_path = ["orchestrator", "performance", "async_io", "max_in_flight"]
prompt = "Max I/O In Flight"
type = "number"
type = "custom"
custom_type = "Number"

View file

@ -1,4 +1,7 @@
# Orchestrator Queue Configuration Fragment
name = "queue_section"
description = "Orchestrator Queue Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -15,7 +18,8 @@ min = "${constraint.orchestrator.queue.concurrent_tasks.min}"
name = "queue_max_concurrent_tasks"
nickel_path = ["queue", "max_concurrent_tasks"]
prompt = "Max Concurrent Tasks"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = 3
@ -25,7 +29,8 @@ min = "${constraint.orchestrator.queue.retry_attempts.min}"
name = "queue_retry_attempts"
nickel_path = ["queue", "retry_attempts"]
prompt = "Retry Attempts"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = 5000
@ -35,7 +40,8 @@ min = "${constraint.orchestrator.queue.retry_delay.min}"
name = "queue_retry_delay"
nickel_path = ["queue", "retry_delay"]
prompt = "Retry Delay (ms)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = 3600000
@ -45,7 +51,8 @@ min = "${constraint.orchestrator.queue.task_timeout.min}"
name = "queue_task_timeout"
nickel_path = ["queue", "task_timeout"]
prompt = "Task Timeout (ms)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = true

View file

@ -1,4 +1,7 @@
# Orchestrator Storage Configuration Fragment
name = "storage_section"
description = "Orchestrator Storage Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -98,7 +101,8 @@ min = 60
name = "storage_cache_ttl"
nickel_path = ["orchestrator", "storage", "cache", "ttl"]
prompt = "Cache TTL (seconds)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "storage_cache_enabled == true"
@ -109,7 +113,8 @@ min = 10
name = "storage_cache_max_entries"
nickel_path = ["orchestrator", "storage", "cache", "max_entries"]
prompt = "Max Cache Entries"
type = "number"
type = "custom"
custom_type = "Number"
# Storage Compression Configuration
[[elements]]
@ -139,7 +144,8 @@ min = 1
name = "storage_compression_level"
nickel_path = ["orchestrator", "storage", "compression", "level"]
prompt = "Compression Level"
type = "number"
type = "custom"
custom_type = "Number"
# Storage Garbage Collection
[[elements]]
@ -159,7 +165,8 @@ min = 3600
name = "storage_gc_retention"
nickel_path = ["orchestrator", "storage", "gc", "retention_seconds"]
prompt = "GC Retention (seconds)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "storage_gc_enabled == true"
@ -170,4 +177,5 @@ min = 300
name = "storage_gc_interval"
nickel_path = ["orchestrator", "storage", "gc", "interval_seconds"]
prompt = "GC Interval (seconds)"
type = "number"
type = "custom"
custom_type = "Number"

View file

@ -1,4 +1,7 @@
# Provisioning Daemon Actions Configuration Fragment
name = "actions"
description = "Provisioning Daemon Actions Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false

View file

@ -1,4 +1,7 @@
# Provisioning Daemon Configuration Fragment
name = "daemon"
description = "Provisioning Daemon Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -23,7 +26,8 @@ min = 5
name = "daemon_poll_interval"
nickel_path = ["provisioning_daemon", "daemon", "poll_interval"]
prompt = "Poll Interval (seconds)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = 4
@ -33,4 +37,5 @@ min = 1
name = "daemon_max_workers"
nickel_path = ["provisioning_daemon", "daemon", "max_workers"]
prompt = "Max Workers"
type = "number"
type = "custom"
custom_type = "Number"

View file

@ -1,4 +1,7 @@
# Provisioning Daemon Health Check Configuration Fragment
name = "health"
description = "Provisioning Daemon Health Check Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -15,7 +18,8 @@ min = 5000
name = "daemon_health_check_interval"
nickel_path = ["provisioning_daemon", "health", "check_interval"]
prompt = "Check Interval (ms)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = 30000
@ -25,7 +29,8 @@ min = 1000
name = "daemon_health_check_timeout"
nickel_path = ["provisioning_daemon", "health", "timeout"]
prompt = "Timeout (ms)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = 3
@ -35,4 +40,5 @@ min = 1
name = "daemon_health_failure_threshold"
nickel_path = ["provisioning_daemon", "health", "failure_threshold"]
prompt = "Failure Threshold"
type = "number"
type = "custom"
custom_type = "Number"

View file

@ -1,4 +1,7 @@
# Provisioning Daemon Logging Configuration Fragment
name = "logging"
description = "Provisioning Daemon Logging Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false

View file

@ -1,4 +1,7 @@
# Provisioning Daemon Worker Configuration Fragment
name = "workers"
description = "Provisioning Daemon Worker Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -15,7 +18,8 @@ min = 1
name = "daemon_worker_pool_size"
nickel_path = ["provisioning_daemon", "workers", "pool_size"]
prompt = "Pool Size"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = 1000
@ -25,7 +29,8 @@ min = 10
name = "daemon_worker_task_queue_size"
nickel_path = ["provisioning_daemon", "workers", "task_queue_size"]
prompt = "Queue Size"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = 300000
@ -35,4 +40,5 @@ min = 10000
name = "daemon_worker_timeout"
nickel_path = ["provisioning_daemon", "workers", "timeout"]
prompt = "Timeout (ms)"
type = "number"
type = "custom"
custom_type = "Number"

View file

@ -1,4 +1,7 @@
# RAG Embeddings Configuration Fragment
name = "embeddings"
description = "RAG Embeddings Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -43,7 +46,8 @@ min = 1
name = "rag_embeddings_batch_size"
nickel_path = ["rag", "embeddings", "batch_size"]
prompt = "Batch Size"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
condition = "rag_embeddings_provider != 'local'"

View file

@ -1,4 +1,7 @@
# RAG Document Ingestion Configuration Fragment
name = "ingestion"
description = "RAG Document Ingestion Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -31,7 +34,8 @@ min = 128
name = "rag_ingestion_chunk_size"
nickel_path = ["rag", "ingestion", "chunk_size"]
prompt = "Chunk Size"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = 50
@ -41,7 +45,8 @@ min = 0
name = "rag_ingestion_overlap"
nickel_path = ["rag", "ingestion", "overlap"]
prompt = "Chunk Overlap"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = "md, txt, toml"

View file

@ -1,4 +1,7 @@
# RAG Language Model Configuration Fragment
name = "llm"
description = "RAG Language Model Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -54,7 +57,8 @@ min = 0.0
name = "rag_llm_temperature"
nickel_path = ["rag", "llm", "temperature"]
prompt = "Temperature"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = 2048
@ -64,4 +68,5 @@ min = 1
name = "rag_llm_max_tokens"
nickel_path = ["rag", "llm", "max_tokens"]
prompt = "Max Tokens"
type = "number"
type = "custom"
custom_type = "Number"

View file

@ -1,4 +1,7 @@
# RAG Retrieval Configuration Fragment
name = "retrieval"
description = "RAG Retrieval Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -15,7 +18,8 @@ min = 1
name = "rag_retrieval_top_k"
nickel_path = ["rag", "retrieval", "top_k"]
prompt = "Top K Results"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = 0.75
@ -25,7 +29,8 @@ min = 0.0
name = "rag_retrieval_similarity_threshold"
nickel_path = ["rag", "retrieval", "similarity_threshold"]
prompt = "Similarity Threshold"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = false

View file

@ -1,4 +1,7 @@
# RAG Vector Database Configuration Fragment
name = "vector_db"
description = "RAG Vector Database Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false

View file

@ -1,5 +1,7 @@
# HTTP Server Configuration Fragment
# Used by all services: orchestrator, control-center, mcp-server
name = "server_section"
description = "HTTP Server Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -26,7 +28,8 @@ name = "server_port"
nickel_path = ["server", "port"]
prompt = "Server Port"
required = true
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = 4
@ -36,7 +39,8 @@ min = "${constraint.common.server.workers.min}"
name = "server_workers"
nickel_path = ["server", "workers"]
prompt = "Worker Threads"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = 75
@ -46,7 +50,8 @@ min = "${constraint.common.server.keep_alive.min}"
name = "server_keep_alive"
nickel_path = ["server", "keep_alive"]
prompt = "Keep-Alive Timeout (seconds)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = 100
@ -56,7 +61,8 @@ min = "${constraint.common.server.max_connections.min}"
name = "server_max_connections"
nickel_path = ["server", "max_connections"]
prompt = "Max Connections"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = 30000
@ -65,7 +71,8 @@ min = 1000
name = "server_request_timeout"
nickel_path = ["server", "request_timeout"]
prompt = "Request Timeout (ms)"
type = "number"
type = "custom"
custom_type = "Number"
[[elements]]
default = true
@ -82,4 +89,5 @@ min = 1
name = "server_shutdown_timeout"
nickel_path = ["server", "shutdown_timeout"]
prompt = "Shutdown Timeout (seconds)"
type = "number"
type = "custom"
custom_type = "Number"

View file

@ -1,4 +1,7 @@
# Vault Service High Availability Configuration Fragment
name = "ha"
description = "Vault Service High Availability Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false

View file

@ -1,4 +1,7 @@
# Vault Service Mount Point Configuration Fragment
name = "mount"
description = "Vault Service Mount Point Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false

View file

@ -1,4 +1,7 @@
# Vault Service Server Configuration Fragment
name = "server"
description = "Vault Service Server Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false
@ -25,4 +28,5 @@ name = "vault_server_port"
nickel_path = ["vault_service", "server", "port"]
prompt = "Server Port"
required = true
type = "number"
type = "custom"
custom_type = "Number"

View file

@ -1,4 +1,7 @@
# Vault Service Storage Configuration Fragment
name = "storage"
description = "Vault Service Storage Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false

View file

@ -1,4 +1,7 @@
# Vault Service TLS Configuration Fragment
name = "tls"
description = "Vault Service TLS Configuration Fragment"
display_mode = "complete"
[[elements]]
border_bottom = false

View file

@ -1,5 +1,7 @@
# Workspace Configuration Fragment
# Used by all services: orchestrator, control-center, mcp-server, installer
name = "workspace_section"
description = "Workspace Configuration Fragment"
display_mode = "complete"
[[elements]]
help = "Name of the workspace this service will serve"

View file

@ -53,10 +53,12 @@ export def main [
# Build TypeDialog command with nickel-roundtrip pattern
let cmd_args: list<string> = if $config_exists {
# Load existing config, allow editing, save updated config with template
["nickel-roundtrip", $config_path, $form_path, "--output", $config_path, "--template", $template_path]
# Args: nickel-roundtrip --output <out> --ncl-template <tpl> <input> <form>
["nickel-roundtrip", "--output", $config_path, "--ncl-template", $template_path, $config_path, $form_path]
} else {
# Create new config from form with template
["nickel-roundtrip", $form_path, "--output", $config_path, "--template", $template_path]
# Args: nickel-roundtrip --output <out> --ncl-template <tpl> <form>
["nickel-roundtrip", "--output", $config_path, "--ncl-template", $template_path, $form_path]
}
ansi print-working "Starting TypeDialog editor (backend: $backend)..."

View file

@ -111,7 +111,7 @@ export def get-template-path [template_name: string]: nothing -> string {
}
export def get-output-config-path [service: string, mode: string]: nothing -> string {
(project-root) | path join "config" "runtime" "generated" $"($service).($mode).toml"
(project-root) | path join ".." "platform" "config" $"($service).($mode).toml"
}
export def validate-service [service: string]: nothing -> nothing {

View file

@ -61,7 +61,7 @@ def main [
# Determine project path
let project_path = if ($project | is-empty) { $env.PWD } else { $project }
let tools_path = ($env.TOOLS_PATH? | default "/Users/Akasha/Tools")
let tools_path = ($env.TOOLS_PATH? | default ($env.HOME | path join "Tools"))
let prov_dir = ($project_path | path join ".typedialog" "provisioning")
# Verify provisioning is installed

View file

@ -1,84 +1,51 @@
# Woodpecker CI Pipeline
# Equivalent to GitHub Actions CI workflow
# Generated by dev-system/ci
# Generated by ore workflow generate — layer: ci-standard
# Source: .ontology/workflow.ncl
# Do not edit manually — regenerate with: ore workflow generate --layer ci-standard
when:
event: [push, pull_request, manual]
branch:
- main
- develop
steps:
# === LINTING ===
lint-rust:
rust-clippy-all:
image: rust:latest
commands:
- curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to /usr/local/bin
- rustup component add clippy
- cargo fmt --all -- --check
- cargo clippy --all-targets -- -D warnings
- cargo clippy --all-targets --all-features -- -D warnings
lint-bash:
image: koalaman/shellcheck-alpine:stable
commands:
- apk add --no-cache curl bash
- find . -name '*.sh' -type f ! -path './target/*' -exec shellcheck {} +
lint-nickel:
nickel-typecheck:
image: rust:latest
commands:
- cargo install nickel-lang-cli --locked
- find . -name '*.ncl' -type f ! -path './target/*' -exec nickel typecheck {} \;
- nickel typecheck
lint-nushell:
nushell-check:
image: rust:latest
commands:
- cargo install nu --locked
- find . -name '*.nu' -type f ! -path './target/*' -exec nu --ide-check 100 {} \;
- find . -name '*.nu' ! -path '*/target/*' -print0 | xargs -0 -I\{\} nu --ide-check 100 \{\}
lint-markdown:
image: node:alpine
commands:
- npm install -g markdownlint-cli2
- markdownlint-cli2 '**/*.md' '#node_modules' '#target'
# === TESTING ===
test:
nextest-ci:
image: rust:latest
commands:
- cargo test --workspace --all-features
depends_on:
- lint-rust
- lint-bash
- lint-nickel
- lint-nushell
- lint-markdown
- cargo install cargo-nextest --locked
- cargo nextest run --all-features --workspace --profile ci --cargo-profile ci
depends_on: ["rust-clippy-all", "nickel-typecheck", "nushell-check"]
environment:
RUST_BACKTRACE: 1
# === BUILD ===
build:
image: rust:latest
commands:
- cargo build --release
depends_on:
- test
# === SECURITY ===
security-audit:
image: rust:latest
commands:
- cargo install cargo-audit --locked
- cargo audit --deny warnings
depends_on:
- lint-rust
license-check:
deny-subset:
image: rust:latest
commands:
- cargo install cargo-deny --locked
- cargo deny check licenses advisories
depends_on:
- lint-rust
docs-check:
image: rust:latest
commands:
- RUSTDOCFLAGS="-D rustdoc::broken-intra-doc-links -D rustdoc::private-intra-doc-links" cargo doc --no-deps --workspace --profile ci -q
depends_on: ["rust-clippy-all", "nickel-typecheck", "nushell-check"]
build-release-native:
image: rust:latest
commands:
- cargo build --release --workspace
depends_on: ["rust-clippy-all", "nickel-typecheck", "nushell-check"]

View file

@ -11,10 +11,12 @@
**Constraints added/amended**:
- `bash-wrapper-has-no-runner-reference` — now permits `provisioning-cli.nu` as transitional fallback
- `universal-fallback-is-transitional` — 22 unmapped commands are explicit migration debt; must be resolved before lazy-load architecture is considered complete
- `universal-fallback-is-transitional` — 22 unmapped commands are explicit migration debt;
must be resolved before lazy-load architecture is considered complete
- `every-registry-command-has-thin-handler` — made directional (progress metric, not gate)
**Rejected approach**: Single-entry `provisioning-cli.nu` for hot paths — measured at 3.1s vs 0.080.15s for thin handlers. All 15 dispatcher wrappers fire at module-load regardless of invoked command.
**Rejected approach**: Single-entry `provisioning-cli.nu` for hot paths — measured at 3.1s vs 0.080.15s
for thin handlers. All 15 dispatcher wrappers fire at module-load regardless of invoked command.
**Files**: `adrs/adr-025-unified-lazy-loading.ncl`
@ -88,7 +90,9 @@
## 📋 Summary
Complete migration to Nickel-based infrastructure-as-code with consolidated configuration strategy. Legacy KCL schemas, deprecated config files, and redundant documentation removed. New project structure with `.cargo/`, `.github/`, and schema-driven configuration system.
Complete migration to Nickel-based infrastructure-as-code with consolidated configuration strategy.
Legacy KCL schemas, deprecated config files, and redundant documentation removed.
New project structure with `.cargo/`, `.github/`, and schema-driven configuration system.
---

View file

@ -2,7 +2,8 @@
## Our Pledge
We, as members, contributors, and leaders, pledge to make participation in our project and community a harassment-free experience for everyone, regardless of:
We, as members, contributors, and leaders, pledge to make participation in our project and community
a harassment-free experience for everyone, regardless of:
- Age
- Body size
@ -44,7 +45,8 @@ Examples of unacceptable behavior include:
## Enforcement Responsibilities
Project maintainers are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate corrective action in response to unacceptable behavior.
Project maintainers are responsible for clarifying and enforcing our standards of acceptable behavior
and will take appropriate corrective action in response to unacceptable behavior.
Maintainers have the right and responsibility to:

View file

@ -4,7 +4,8 @@ Thank you for your interest in contributing! This document provides guidelines a
## Code of Conduct
This project adheres to a Code of Conduct. By participating, you are expected to uphold this code. Please see [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) for details.
This project adheres to a Code of Conduct. By participating, you are expected to uphold this code.
Please see [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) for details.
## Getting Started
@ -121,7 +122,7 @@ Maintainers handle releases following semantic versioning:
- MINOR: New features (backward compatible)
- PATCH: Bug fixes
## Questions?
## Questions
- Check existing documentation and issues
- Ask in discussions or open an issue

View file

@ -1,391 +0,0 @@
# Platform Configuration Management
This directory manages **runtime configurations** for provisioning platform services.
## Structure
```bash
provisioning/config/
├── runtime/ # 🔒 PRIVATE (gitignored)
│ ├── .gitignore # Runtime files are private
│ ├── orchestrator.solo.ncl # Runtime config (editable)
│ ├── vault-service.multiuser.ncl # Runtime config (editable)
│ └── generated/ # 📄 Auto-generated TOMLs
│ ├── orchestrator.solo.toml # Exported from .ncl
│ └── vault-service.multiuser.toml
├── examples/ # 📘 PUBLIC (reference)
│ ├── orchestrator.solo.example.ncl
│ └── orchestrator.enterprise.example.ncl
├── README.md # This file
└── setup-platform-config.sh # ← See provisioning/scripts/setup-platform-config.sh
```
## Quick Start
### 1. Setup Platform Configuration (First Time)
```toml
# Interactive wizard (recommended)
./provisioning/scripts/setup-platform-config.sh
# Or quick setup for all services in solo mode
./provisioning/scripts/setup-platform-config.sh --quick-mode --mode solo
```
### 2. Run Services
```bash
# Service reads config from generated TOML
export ORCHESTRATOR_MODE=solo
cargo run -p orchestrator
# Or with explicit config path
export ORCHESTRATOR_CONFIG=provisioning/config/runtime/generated/orchestrator.solo.toml
cargo run -p orchestrator
```
### 3. Update Configuration
**Option A: Interactive (Recommended)**
```toml
# Update via TypeDialog UI
./provisioning/scripts/setup-platform-config.sh --service orchestrator --mode solo
```
**Option B: Manual Edit**
```bash
# Edit Nickel directly
vim provisioning/config/runtime/orchestrator.solo.ncl
# ⚠️ CRITICAL: Regenerate TOML afterward
./provisioning/scripts/setup-platform-config.sh --generate-toml
```
## Configuration Layers
```toml
📘 PUBLIC (provisioning/schemas/platform/)
├── schemas/ → Type contracts (Nickel)
├── defaults/ → Base configuration values
│ └── deployment/ → Mode-specific overlays (solo/multiuser/cicd/enterprise)
├── validators/ → Business logic validation
└── common/
└── helpers.ncl → Merge functions
⬇️ COMPOSITION PROCESS ⬇️
🔒 PRIVATE (provisioning/config/runtime/)
├── orchestrator.solo.ncl ← User editable
│ (imports schemas + defaults + mode overlay)
│ (uses helpers.compose_config for merge)
└── generated/
└── orchestrator.solo.toml ← Auto-exported for Rust services
(generated by: nickel export --format toml)
```
## Key Concepts
### Schema (Type Contract)
- **File**: `provisioning/schemas/platform/schemas/orchestrator.ncl`
- **Purpose**: Defines valid fields, types, constraints
- **Status**: 📘 PUBLIC, versioned, source of truth
- **Edit**: Rarely (architecture changes only)
### Defaults (Base Values)
- **File**: `provisioning/schemas/platform/defaults/orchestrator-defaults.ncl`
- **Purpose**: Default values for all orchestrator settings
- **Status**: 📘 PUBLIC, versioned, part of product
- **Edit**: When changing default behavior
### Mode Overlay (Tuning)
- **File**: `provisioning/schemas/platform/defaults/deployment/solo-defaults.ncl`
- **Purpose**: Mode-specific resource/behavior tuning
- **Status**: 📘 PUBLIC, versioned
- **Example**: solo mode uses 2 CPU, enterprise uses 16+ CPU
### Runtime Config (User Customization)
- **File**: `provisioning/config/runtime/orchestrator.solo.ncl`
- **Purpose**: Actual deployment configuration (can be hand-edited)
- **Status**: 🔒 PRIVATE, gitignored
- **Edit**: Yes, use setup script or edit manually + regenerate TOML
### Generated TOML (Service Consumption)
- **File**: `provisioning/config/runtime/generated/orchestrator.solo.toml`
- **Purpose**: What Rust services actually read
- **Status**: 🔒 PRIVATE, gitignored, auto-generated
- **Edit**: NO - regenerate from .ncl instead
- **Generation**: `nickel export --format toml <ncl_file>`
## Workflows
### Scenario 1: First-Time Setup
```bash
# 1. Run setup script
./provisioning/scripts/setup-platform-config.sh
# 2. Choose action (TypeDialog or Quick Mode)
# ↓
# TypeDialog: User fills form → generates orchestrator.solo.ncl
# Quick Mode: Composes defaults + mode overlay → generates all 8 services
# 3. Script auto-exports to TOML
# orchestrator.solo.ncl → orchestrator.solo.toml
# 4. Service reads TOML
# cargo run -p orchestrator (reads generated/orchestrator.solo.toml)
```
### Scenario 2: Update Configuration
```toml
# Option A: Interactive TypeDialog
./provisioning/scripts/setup-platform-config.sh
--service orchestrator
--mode solo
--backend web
# Result: Updated orchestrator.solo.ncl + auto-exported TOML
# Option B: Manual Edit
vim provisioning/config/runtime/orchestrator.solo.ncl
# ⚠️ CRITICAL: Must regenerate TOML
./provisioning/scripts/setup-platform-config.sh --generate-toml
# Result: Updated TOML in generated/
```
### Scenario 3: Switch Deployment Mode
```bash
# From solo to enterprise
./provisioning/scripts/setup-platform-config.sh --quick-mode --mode enterprise
# Result: All 8 services configured for enterprise mode
# 16+ CPU, 32+ GB RAM, HA setup, KMS integration, etc.
```
### Scenario 4: Workspace-Specific Overrides
```bash
workspace_librecloud/
├── config/
│ └── platform-overrides.ncl # Workspace customization
# Example:
# {
# orchestrator.server.port = 9999,
# orchestrator.workspace.name = "librecloud",
# vault-service.storage.path = "./workspace_librecloud/data/vault"
# }
```
## Important Notes
### ⚠️ Manual Edits Require TOML Regeneration
If you edit `.ncl` files directly:
```nickel
# 1. Edit the .ncl file
vim provisioning/config/runtime/orchestrator.solo.ncl
# 2. ALWAYS regenerate TOML
./provisioning/scripts/setup-platform-config.sh --generate-toml
# Service will NOT see your changes until TOML is regenerated
```
### 🔒 Private by Design
Runtime configs are **gitignored** for good reasons:
- **May contain secrets**: Encrypted credentials, API keys, tokens
- **Deployment-specific**: Different values per environment
- **User-customized**: Each developer/workspace has different needs
- **Not shared**: Don't commit locally-built configs
### 📘 Schemas are Public
Schema/defaults in `provisioning/schemas/` are **version-controlled**:
- Product definition (part of releases)
- Shared across team
- Source of truth for config structure
- Can reference in documentation
### 🔄 Idempotent Setup
The setup script is safe to run multiple times:
```bash
# Safe: Updates only what's needed
./provisioning/scripts/setup-platform-config.sh --quick-mode --mode enterprise
# Safe: Doesn't overwrite unless --clean is used
./provisioning/scripts/setup-platform-config.sh --generate-toml
# Use --clean to start fresh
./provisioning/scripts/setup-platform-config.sh --clean
```
## Service Configuration Paths
Each service loads config using this priority:
```toml
1. Environment variable: ORCHESTRATOR_CONFIG=/path/to/custom.toml
2. Mode-specific runtime: provisioning/config/runtime/generated/orchestrator.{MODE}.toml
3. Fallback defaults: provisioning/schemas/platform/defaults/orchestrator-defaults.ncl
```
## Configuration Composition (Technical)
The setup script uses Nickel's `helpers.compose_config` function:
```nickel
# Generated .ncl file imports:
let helpers = import "provisioning/schemas/platform/common/helpers.ncl"
let defaults = import "provisioning/schemas/platform/defaults/orchestrator-defaults.ncl"
let mode_config = import "provisioning/schemas/platform/defaults/deployment/solo-defaults.ncl"
# Compose: base + mode overlay
helpers.compose_config defaults mode_config {}
# ^base ^mode overlay ^user overrides (empty if not customized)
```
This ensures:
- Type safety (validated by Nickel schema)
- Proper layering (base + mode + user)
- Reproducibility (same compose always produces same result)
- Extensibility (can add user layer via Nickel import)
## Troubleshooting
### Config Won't Generate TOML
```toml
# Check Nickel syntax
nickel typecheck provisioning/config/runtime/orchestrator.solo.ncl
# Check for schema import errors
nickel export --format json provisioning/config/runtime/orchestrator.solo.ncl
# View detailed error message
nickel typecheck -i provisioning/config/runtime/orchestrator.solo.ncl 2>&1 | less
```
### Service Won't Start
```bash
# Verify TOML exists
ls -la provisioning/config/runtime/generated/orchestrator.solo.toml
# Verify TOML syntax
toml-cli validate provisioning/config/runtime/generated/orchestrator.solo.toml
# Check service config loading
RUST_LOG=debug cargo run -p orchestrator 2>&1 | head -50
```
### Wrong Configuration Being Used
```toml
# Verify environment mode
echo $ORCHESTRATOR_MODE # Should be: solo, multiuser, cicd, or enterprise
# Check which file service is reading
ORCHESTRATOR_CONFIG=provisioning/config/runtime/generated/orchestrator.solo.toml
cargo run -p orchestrator
# Verify file modification time
ls -lah provisioning/config/runtime/generated/orchestrator.*.toml
```
## Integration Points
### ⚠️ Provisioning Installer Status
**Current Status**: Installer NOT YET IMPLEMENTED
The `setup-platform-config.sh` script is a **standalone tool** that:
- ✅ Works independently from the provisioning installer
- ✅ Can be called manually for configuration setup
- ⏳ Will be integrated into the installer once it's implemented
**For Now**: Use script manually before running services:
```bash
# Manual setup (until installer is implemented)
cd /path/to/project-provisioning
./provisioning/scripts/setup-platform-config.sh --quick-mode --mode solo
# Then run services
export ORCHESTRATOR_MODE=solo
cargo run -p orchestrator
```
### Future: Integration into Provisioning Installer
Once `provisioning/scripts/install.sh` is implemented, it will automatically call this script:
```bash
#!/bin/bash
# provisioning/scripts/install.sh (FUTURE - NOT YET IMPLEMENTED)
# Pre-flight checks (verification of dependencies, paths, permissions)
check_dependencies() {
command -v nickel >/dev/null || { echo "Nickel required"; exit 1; }
command -v nu >/dev/null || { echo "Nushell required"; exit 1; }
}
check_dependencies
# Install core provisioning system
echo "Installing provisioning system..."
# (install implementation details here)
# Setup platform configurations
echo "Setting up platform configurations..."
./provisioning/scripts/setup-platform-config.sh --quick-mode --mode solo
# Build and test platform services
echo "Building platform services..."
cargo build -p orchestrator -p control-center -p mcp-server
# Verify services are operational
echo "Verification complete - services ready to run"
```
### CI/CD Pipeline Integration
For automated CI/CD setups (can use now):
```bash
#!/bin/bash
# ci/setup.sh
# Setup configurations for CI/CD mode
cd /path/to/project-provisioning
./provisioning/scripts/setup-platform-config.sh
--quick-mode
--mode cicd
# Result: All services configured for CI/CD mode
# (ephemeral, API-driven, fast cleanup, minimal resource footprint)
# Run tests
cargo test --all
# Deploy (CI/CD specific)
docker-compose -f provisioning/platform/infrastructure/docker/docker-compose.cicd.yml up
```
---
**Version**: 1.0.0
**Last Updated**: 2026-01-05
**Script Reference**: `provisioning/scripts/setup-platform-config.sh`

View file

@ -1,538 +0,0 @@
# AI Integration Configuration for Provisioning Platform
# This file configures the AI system including LLM providers, RAG, MCP, and security policies.
# ============================================================================
# Core AI Configuration
# ============================================================================
[ai]
# Enable/disable AI features globally
enabled = true
# LLM Provider Selection
# Options: "anthropic" | "openai" | "local" | "azure-openai"
provider = "anthropic"
# Model Selection
# Anthropic: "claude-sonnet-4", "claude-opus-4", "claude-haiku-4"
# OpenAI: "gpt-4-turbo", "gpt-4", "gpt-3.5-turbo"
# Local: "llama-3-70b", "mistral-large", "codellama-34b"
model = "claude-sonnet-4"
# Model Temperature (0.0-1.0)
# Lower = more deterministic, Higher = more creative
temperature = 0.7
# Maximum tokens for responses
max_tokens = 4096
# Request timeout (seconds)
timeout = 60
# ============================================================================
# AI Features - Fine-Grained Control
# ============================================================================
[ai.features]
# AI-assisted form filling (typdialog-ai)
# Real-time suggestions and field value predictions
form_assistance = true
# Natural language configuration generation (typdialog-prov-gen)
# Convert plain English to Nickel configs
config_generation = true
# Autonomous AI agents (typdialog-ag)
# WARNING: Agents can execute multi-step workflows
# Recommended: false for production (enable per-use-case)
autonomous_agents = false
# AI-powered troubleshooting
# Analyze logs and suggest fixes for failed deployments
troubleshooting = true
# Configuration optimization
# AI reviews configs and suggests improvements
optimization = true
# Validation error explanations
# AI explains Nickel validation errors in plain language
error_explanations = true
# ============================================================================
# LLM Provider Configuration
# ============================================================================
[ai.anthropic]
# Anthropic Claude API configuration
api_key = "env:ANTHROPIC_API_KEY" # Load from environment variable
api_url = "https://api.anthropic.com/v1"
max_retries = 3
retry_delay_ms = 1000
# Rate limits (per minute)
max_requests_per_minute = 50
max_tokens_per_minute = 100000
[ai.openai]
# OpenAI GPT-4 API configuration
api_key = "env:OPENAI_API_KEY"
api_url = "https://api.openai.com/v1"
max_retries = 3
organization_id = "" # Optional
retry_delay_ms = 1000
# Rate limits (per minute)
max_requests_per_minute = 60
max_tokens_per_minute = 150000
[ai.local]
# Local LLM configuration (Ollama, LlamaCpp, vLLM)
# Use for air-gapped deployments or privacy-critical scenarios
context_length = 8192
model_path = "/opt/provisioning/models/llama-3-70b"
num_gpu_layers = 40 # GPU acceleration
server_url = "http://localhost:11434" # Ollama default
# ============================================================================
# Model Context Protocol (MCP) Server
# ============================================================================
[ai.mcp]
# MCP server configuration
enabled = true
max_retries = 3
server_url = "http://localhost:9000"
timeout = 30
# Tool calling configuration
[ai.mcp.tools]
enabled = true
# Available tools for LLM
# Tools provide structured actions the LLM can invoke
tools = [
"nickel_validate", # Validate Nickel configuration
"schema_query", # Query Nickel schema information
"config_generate", # Generate configuration snippets
"cedar_check", # Check Cedar authorization policies
"deployment_status", # Query deployment status
"log_analyze", # Analyze deployment logs
]
# ============================================================================
# Retrieval-Augmented Generation (RAG)
# ============================================================================
[ai.rag]
# Enable RAG system
enabled = true
# Vector Store Configuration
# Options: "qdrant" | "milvus" | "pgvector" | "chromadb"
collection_name = "provisioning-knowledge"
vector_store = "qdrant"
vector_store_url = "http://localhost:6333"
# Embedding Model
# OpenAI: "text-embedding-3-large", "text-embedding-3-small"
# Local: "all-MiniLM-L6-v2", "bge-large-en-v1.5"
embedding_api_key = "env:OPENAI_API_KEY" # For OpenAI embeddings
embedding_model = "text-embedding-3-large"
# Document Chunking
chunk_overlap = 50 # Overlap between chunks
chunk_size = 512 # Characters per chunk
max_chunks_per_query = 10 # Top-k retrieval
# ============================================================================
# RAG Index Configuration
# ============================================================================
[ai.rag.index]
# What to index for RAG retrieval
# Index Nickel schemas (RECOMMENDED: true)
# Provides AI with schema definitions and contracts
schemas = true
schemas_path = "provisioning/schemas"
# Index documentation (RECOMMENDED: true)
# Provides AI with user guides and best practices
docs = true
docs_path = "docs"
# Index past deployments (RECOMMENDED: true)
# AI learns from successful deployment patterns
deployments = true
deployments_path = "workspaces"
# Index best practices (RECOMMENDED: true)
# Inject organizational patterns and conventions
best_practices = true
best_practices_path = ".claude/patterns"
# Index deployment logs (WARNING: Privacy concerns)
# Logs may contain sensitive data, enable only if sanitized
logs = false
logs_retention_days = 30
# Reindexing schedule
auto_reindex = true
reindex_interval_hours = 24
# ============================================================================
# Security and Access Control
# ============================================================================
[ai.security]
# Cedar policy store for AI access control
cedar_policy_store = "/etc/provisioning/cedar-policies/ai"
# AI cannot suggest secret values (CRITICAL: keep true)
# AI can suggest secret names/paths but not retrieve actual secrets
max_secret_suggestions = 0
# Require human approval for critical operations (CRITICAL: keep true)
# Operations requiring approval:
# - Deployments to production
# - Configuration changes affecting security
# - Secret rotation
# - Infrastructure deletion
require_human_approval = true
# Audit all AI operations (CRITICAL: keep true)
# Log every AI request, response, and action
audit_all_operations = true
# Data sanitization before sending to LLM
# Remove sensitive data from prompts
[ai.security.sanitization]
sanitize_credentials = true # Remove passwords, API keys
sanitize_ip_addresses = false # Keep for troubleshooting
sanitize_pii = true # Remove personally identifiable info
sanitize_secrets = true # Remove secret values
# Allowed data for LLM
allowed_data = [
"nickel_schemas", # Schema definitions (public)
"documentation", # User docs (public)
"error_messages", # Validation errors (sanitized)
"resource_names", # Infrastructure resource identifiers
]
# Forbidden data for LLM (NEVER send to external LLM)
forbidden_data = [
"secret_values", # Passwords, API keys, tokens
"private_keys", # SSH keys, TLS keys, encryption keys
"pii", # Email addresses, names, phone numbers
"credentials", # Authentication credentials
"session_tokens", # User session data
]
# ============================================================================
# Rate Limiting and Cost Control
# ============================================================================
[ai.rate_limiting]
# Per-user rate limits
requests_per_day = 2000
requests_per_hour = 500
requests_per_minute = 60
# Token limits (to control LLM API costs)
tokens_per_day = 1000000 # 1M tokens/day
tokens_per_month = 30000000 # 30M tokens/month
# Cost limits (USD)
cost_limit_per_day = "100.00"
cost_limit_per_month = "2000.00"
# Alert thresholds
cost_alert_threshold = 0.8 # Alert at 80% of limit
# Rate limit exceeded behavior
# Options: "queue" | "reject" | "throttle"
exceed_behavior = "queue"
max_queue_size = 100
# ============================================================================
# Caching
# ============================================================================
[ai.caching]
# Enable response caching to reduce LLM API calls
enabled = true
# Cache TTL (time-to-live)
ttl = "1h"
# Cache backend
# Options: "redis" | "memcached" | "in-memory"
backend = "redis"
redis_url = "redis://localhost:6379"
# Cache key strategy
# "prompt" = Cache by exact prompt (high precision, low hit rate)
# "semantic" = Cache by semantic similarity (lower precision, high hit rate)
cache_strategy = "semantic"
semantic_similarity_threshold = 0.95
# Cache statistics
log_cache_misses = false
track_hit_rate = true
# ============================================================================
# Observability and Monitoring
# ============================================================================
[ai.observability]
# Logging level for AI operations
# Options: "trace" | "debug" | "info" | "warn" | "error"
log_level = "info"
# Trace all AI requests (detailed logging)
# WARNING: Generates large log volume
trace_all_requests = true
# Store conversation history (for debugging and learning)
conversation_retention_days = 30
store_conversations = true
# Metrics collection
[ai.observability.metrics]
enabled = true
export_format = "prometheus" # "prometheus" | "opentelemetry"
export_port = 9090
# Metrics to collect
metrics = [
"request_count", # Total AI requests
"request_duration", # Latency histogram
"token_usage", # Input/output tokens
"cost_tracking", # USD cost per request
"cache_hit_rate", # Cache effectiveness
"validation_success_rate", # Generated config validity
"human_approval_rate", # How often humans approve AI output
]
# Distributed tracing
[ai.observability.tracing]
enabled = true
jaeger_endpoint = "http://localhost:14268/api/traces"
sample_rate = 0.1 # Sample 10% of requests
# ============================================================================
# AI Agent Configuration (typdialog-ag)
# ============================================================================
[ai.agents]
# WARNING: Autonomous agents can execute multi-step workflows
# Enable with caution, only for trusted users
# Enable AI agents globally
enabled = false
# Maximum iterations per agent execution
# Prevents infinite loops
max_iterations = 20
# Agent timeout (seconds)
timeout = 300
# Require approval for each agent action (RECOMMENDED: true)
# If false, agent executes entire workflow autonomously
require_step_approval = true
# Agent types
[ai.agents.types]
# Provisioning agent: End-to-end infrastructure setup
provisioning_agent = false
# Troubleshooting agent: Diagnose and fix deployment issues
troubleshooting_agent = true
# Optimization agent: Analyze and improve configurations
optimization_agent = true
# Security audit agent: Review configs for vulnerabilities
security_audit_agent = true
# ============================================================================
# Configuration Generation (typdialog-prov-gen)
# ============================================================================
[ai.config_generation]
# Default schema for generated configs
default_schema = "workspace"
# Validation mode
# "strict" = Reject any invalid config
# "permissive" = Allow configs with warnings
validation_mode = "strict"
# Best practice injection
# Automatically add security/performance best practices
inject_best_practices = true
# Template usage
# Use pre-defined templates as starting points
template_directory = "provisioning/templates"
use_templates = true
# ============================================================================
# Form Assistance (typdialog-ai)
# ============================================================================
[ai.form_assistance]
# Real-time suggestions as user types
real_time_suggestions = true
# Minimum characters before triggering suggestions
min_chars_for_suggestions = 3
# Maximum suggestions per field
max_suggestions = 5
# Suggestion confidence threshold (0.0-1.0)
# Only show suggestions with confidence above threshold
confidence_threshold = 0.7
# Natural language form filling
# User can describe entire form in plain English
nl_form_filling = true
# ============================================================================
# Environment-Specific Overrides
# ============================================================================
# Development environment
[ai.environments.dev]
cost_limit_per_day = "10.00"
enabled = true
model = "gpt-4-turbo"
provider = "openai" # Cheaper for dev
require_human_approval = false # Faster iteration
# Staging environment
[ai.environments.staging]
cost_limit_per_day = "50.00"
enabled = true
model = "claude-sonnet-4"
provider = "anthropic"
require_human_approval = true
# Production environment
[ai.environments.production]
autonomous_agents = false # NEVER enable in production
cost_limit_per_day = "100.00"
enabled = true
model = "claude-sonnet-4"
provider = "anthropic"
require_human_approval = true # ALWAYS true for production
# ============================================================================
# Integration with Other Services
# ============================================================================
[ai.integration]
# Orchestrator integration
orchestrator_api_key = "env:ORCHESTRATOR_API_KEY"
orchestrator_url = "https://orchestrator.example.com"
# SecretumVault integration (for secret name suggestions only)
secretum_vault_token = "env:VAULT_TOKEN"
secretum_vault_url = "https://vault.example.com:8200"
# AI can query secret names/paths but NEVER values
# Typdialog Web UI integration
typdialog_url = "https://forms.provisioning.example.com"
typdialog_websocket_enabled = true
# ============================================================================
# Advanced Settings
# ============================================================================
[ai.advanced]
# Prompt engineering
system_prompt_template = "provisioning/ai/prompts/system.txt"
user_prompt_template = "provisioning/ai/prompts/user.txt"
# Context window management
context_truncation_strategy = "sliding_window" # "sliding_window" | "summarize"
max_context_tokens = 100000 # Claude Sonnet 4 context window
# Streaming responses
enable_streaming = true
stream_chunk_size = 100 # Characters per chunk
# Concurrent requests
max_concurrent_requests = 10
# ============================================================================
# Experimental Features (Use at Your Own Risk)
# ============================================================================
[ai.experimental]
# Multi-agent collaboration
# Multiple AI agents work together on complex tasks
multi_agent_collaboration = false
# Reinforcement learning from human feedback (RLHF)
# Learn from user corrections to improve over time
rlhf_enabled = false
# Fine-tuning on deployment history
# Train custom models on organization-specific patterns
fine_tuning = false
fine_tuning_dataset_path = "provisioning/ai/fine-tuning-data"
# ============================================================================
# Compliance and Legal
# ============================================================================
[ai.compliance]
# Data residency requirements
# Ensure LLM provider complies with data residency laws
data_residency = "us" # "us" | "eu" | "local"
# GDPR compliance mode
gdpr_data_retention_days = 90
gdpr_mode = false
# SOC 2 compliance logging
soc2_logging = false
# Terms of service acceptance
# Must explicitly accept LLM provider TOS
tos_accepted = false
tos_version = "2025-01-08"
# IMPORTANT NOTES:
#
# 1. API Keys: NEVER hardcode API keys. Always use environment variables.
# Example: api_key = "env:ANTHROPIC_API_KEY"
#
# 2. Security: Keep require_human_approval = true for production.
# AI-generated configs must be reviewed by humans.
#
# 3. Costs: Monitor LLM API usage. Set appropriate cost_limit_per_day.
# Default limits are conservative but may need adjustment.
#
# 4. Privacy: For sensitive workloads, use local models (no external API calls).
# Set provider = "local" and configure local model path.
#
# 5. RAG Index: Regularly reindex to keep AI knowledge up-to-date.
# Set auto_reindex = true and adjust reindex_interval_hours.
#
# 6. Cedar Policies: Define fine-grained AI access control in Cedar.
# Location: /etc/provisioning/cedar-policies/ai
#
# 7. Audit Logs: AI operations are security-critical. Keep audit_all_operations = true.
# Logs stored in: /var/log/provisioning/ai-audit.log
#
# 8. Agents: Autonomous agents are powerful but risky.
# Enable only for specific use cases, never globally in production.
# Version: 1.0
# Last Updated: 2025-01-08

View file

@ -1,116 +0,0 @@
# Provisioning Platform Default Configuration
# This file defines defaults for all provisioning system configuration
# Documentation Configuration
[documentation]
# mdBook base URL for hosted documentation
# Set to empty string ("") to use local files only (default)
# Set to a URL when mdBook is hosted (e.g., "https://docs.provisioning.local")
mdbook_base_url = ""
# Enable mdBook URL resolution
# When true and mdbook_base_url is set, CLI will show documentation URLs
# When false or mdbook_base_url empty, uses local files only
mdbook_enabled = false
# Local documentation paths (relative to provisioning root)
docs_root = "docs/src"
guides_path = "docs/src/guides"
api_reference_path = "docs/src/api-reference"
architecture_path = "docs/src/architecture"
# Help System Configuration
[help]
# Help system language/locale
# Options: "en-US", "es-ES", or other supported locales
# Falls back to English if locale not available
locale = "en-US"
# Use internationalized help (Fluent-based)
# When true: Uses help_system_fluent.nu with translations
# When false: Uses help_system.nu with English-only help
use_fluent = false
# Logging Configuration
[logging]
# Minimum log level: "off", "error", "warn", "info", "debug", "trace"
level = "info"
# Log output format: "text" or "json"
format = "text"
# Cache Configuration
[cache]
# Enable caching of parsed configurations
enabled = true
# Cache directory (relative to provisioning root)
dir = ".cache/provisioning"
# Cache TTL in seconds (0 = no expiration)
ttl = 3600
# Performance Configuration
[performance]
# Maximum parallel operations
max_parallel = 4
# Operation timeout in seconds
timeout = 300
# Network Configuration
[network]
# HTTP/REST service port
http_port = 8080
# MCP server port
mcp_port = 8081
# Orchestrator service port
orchestrator_port = 5000
# Security Configuration
[security]
# Enable strict mode (enforces all security checks)
strict_mode = false
# TLS/SSL for service communication
enable_tls = false
# Certificate paths (required if enable_tls = true)
cert_path = ""
key_path = ""
# Environment-Specific Configuration
# ⚠️ DEPRECATED: Environments are now defined in Nickel (ADR-003: Nickel as Source of Truth)
# Location: provisioning/schemas/config/environments/main.ncl
# The loader attempts to load from Nickel first, then falls back to this TOML section
# This section is kept for backward compatibility only - DO NOT USE for new configurations
#
# [environments]
# [environments.dev]
# debug_enabled = true
# debug_log_level = "debug"
# [environments.prod]
# debug_enabled = false
# debug_log_level = "warn"
# Configuration Notes
#
# 1. User Configuration Override
# Users can override these defaults by creating:
# ~/.config/provisioning/user_config.toml
#
# 2. Environment Variables
# Can override any setting with: PROVISIONING_<SECTION>_<KEY>
# Example: PROVISIONING_DOCUMENTATION_MDBOOK_BASE_URL="https://docs.example.com"
#
# 3. Workspace Configuration
# Workspace-specific config in: workspace/config/provisioning-config.toml
#
# 4. Loading Hierarchy
# 1. CLI arguments (highest priority)
# 2. Environment variables
# 3. User config (~/.config/provisioning/user_config.toml)
# 4. Workspace config (workspace/config/provisioning-config.toml)
# 5. This file (lowest priority)

View file

@ -1,494 +0,0 @@
# Example Platform Service Configurations
This directory contains reference configurations for platform services in different deployment modes. These examples show realistic settings and best practices for each mode.
## What Are These Examples?
These are **Nickel configuration files** (.ncl format) that demonstrate how to configure the provisioning platform services. They show:
- Recommended settings for each deployment mode
- How to customize services for your environment
- Best practices for development, staging, and production
- Performance tuning for different scenarios
- Security settings appropriate to each mode
## Directory Structure
```bash
provisioning/config/examples/
├── README.md # This file
├── orchestrator.solo.example.ncl # Development mode reference
├── orchestrator.multiuser.example.ncl # Team staging reference
└── orchestrator.enterprise.example.ncl # Production reference
```
## Deployment Modes
### Solo Mode (Development)
**File**: `orchestrator.solo.example.ncl`
**Characteristics**:
- 2 CPU, 4GB RAM (lightweight)
- Single user/developer
- Local development machine
- Minimal resource consumption
- No TLS or authentication
- In-memory storage
**When to use**:
- Local development
- Testing configurations
- Learning the platform
- CI/CD test environments
**Key Settings**:
- workers: 2
- max_concurrent_tasks: 2
- max_memory: 1GB
- tls: disabled
- auth: disabled
### Multiuser Mode (Team Staging)
**File**: `orchestrator.multiuser.example.ncl`
**Characteristics**:
- 4 CPU, 8GB RAM (moderate)
- Multiple concurrent users
- Team staging environment
- Production-like testing
- Basic TLS and token auth
- Filesystem storage with caching
**When to use**:
- Team development
- Integration testing
- Staging environment
- Pre-production validation
- Multi-user environments
**Key Settings**:
- workers: 4
- max_concurrent_tasks: 10
- max_memory: 4GB
- tls: enabled (certificates required)
- auth: token-based
- storage: filesystem with replication
### Enterprise Mode (Production)
**File**: `orchestrator.enterprise.example.ncl`
**Characteristics**:
- 16+ CPU, 32+ GB RAM (high-performance)
- Multi-team, multi-workspace
- Production mission-critical
- Full redundancy and HA
- OAuth2/Enterprise auth
- Distributed storage with replication
- Full monitoring, tracing, audit
**When to use**:
- Production deployment
- Mission-critical systems
- High-availability requirements
- Multi-tenant environments
- Compliance requirements (SOC2, ISO27001)
**Key Settings**:
- workers: 16
- max_concurrent_tasks: 100
- max_memory: 32GB
- tls: mandatory (TLS 1.3)
- auth: OAuth2 (enterprise provider)
- storage: distributed with 3-way replication
- monitoring: comprehensive with tracing
- disaster_recovery: enabled
- compliance: SOC2, ISO27001
## How to Use These Examples
### Step 1: Copy the Appropriate Example
Choose the example that matches your deployment mode:
```bash
# For development (solo)
cp provisioning/config/examples/orchestrator.solo.example.ncl
provisioning/config/runtime/orchestrator.solo.ncl
# For team staging (multiuser)
cp provisioning/config/examples/orchestrator.multiuser.example.ncl
provisioning/config/runtime/orchestrator.multiuser.ncl
# For production (enterprise)
cp provisioning/config/examples/orchestrator.enterprise.example.ncl
provisioning/config/runtime/orchestrator.enterprise.ncl
```
### Step 2: Customize for Your Environment
Edit the copied file to match your specific setup:
```bash
# Edit the configuration
vim provisioning/config/runtime/orchestrator.solo.ncl
# Examples of customizations:
# - Change workspace path to your project
# - Adjust worker count based on CPU cores
# - Set your domain names and hostnames
# - Configure storage paths for your filesystem
# - Update certificate paths for production
# - Set logging endpoints for your infrastructure
```
### Step 3: Validate Configuration
Verify the configuration is syntactically correct:
```toml
# Check Nickel syntax
nickel typecheck provisioning/config/runtime/orchestrator.solo.ncl
# View generated TOML
nickel export --format toml provisioning/config/runtime/orchestrator.solo.ncl
```
### Step 4: Generate TOML
Export the Nickel configuration to TOML format for service consumption:
```nickel
# Use setup script to generate TOML
./provisioning/scripts/setup-platform-config.sh --generate-toml
# Or manually export
nickel export --format toml provisioning/config/runtime/orchestrator.solo.ncl >
provisioning/config/runtime/generated/orchestrator.solo.toml
```
### Step 5: Run Services
Start your platform services with the generated configuration:
```toml
# Set the deployment mode
export ORCHESTRATOR_MODE=solo
# Run the orchestrator
cargo run -p orchestrator
```
## Configuration Reference
### Solo Mode Example Settings
```toml
server.workers = 2
queue.max_concurrent_tasks = 2
performance.max_memory = 1000 # 1GB max
security.tls.enabled = false # No TLS for local dev
security.auth.enabled = false # No auth for local dev
```
**Use case**: Single developer on local machine
### Multiuser Mode Example Settings
```toml
server.workers = 4
queue.max_concurrent_tasks = 10
performance.max_memory = 4000 # 4GB max
security.tls.enabled = true # Enable TLS
security.auth.type = "token" # Token-based auth
```
**Use case**: Team of 5-10 developers in staging
### Enterprise Mode Example Settings
```toml
server.workers = 16
queue.max_concurrent_tasks = 100
performance.max_memory = 32000 # 32GB max
security.tls.enabled = true # TLS 1.3 only
security.auth.type = "oauth2" # OAuth2 for enterprise
storage.replication.factor = 3 # 3-way replication
```
**Use case**: Production with 100+ users across multiple teams
## Key Configuration Sections
### Server Configuration
Controls HTTP server behavior:
```bash
server = {
host = "0.0.0.0", # Bind address
port = 9090, # Listen port
workers = 4, # Worker threads
max_connections = 200, # Concurrent connections
request_timeout = 30000, # Milliseconds
}
```
### Storage Configuration
Controls data persistence:
```bash
storage = {
backend = "filesystem", # filesystem or distributed
path = "/var/lib/provisioning/orchestrator/data",
cache.enabled = true,
replication.enabled = true,
replication.factor = 3, # 3-way replication for HA
}
```
### Queue Configuration
Controls task queuing:
```bash
queue = {
max_concurrent_tasks = 10,
retry_attempts = 3,
task_timeout = 3600000, # 1 hour in milliseconds
priority_queue = true, # Enable priority for tasks
metrics = true, # Enable queue metrics
}
```
### Security Configuration
Controls authentication and encryption:
```bash
security = {
tls = {
enabled = true,
cert_path = "/etc/provisioning/certs/cert.crt",
key_path = "/etc/provisioning/certs/key.key",
min_tls_version = "1.3",
},
auth = {
enabled = true,
type = "oauth2", # oauth2, token, or none
provider = "okta",
},
encryption = {
enabled = true,
algorithm = "aes-256-gcm",
},
}
```
### Logging Configuration
Controls log output and persistence:
```bash
logging = {
level = "info", # debug, info, warning, error
format = "json",
output = "both", # stdout, file, or both
file = {
enabled = true,
path = "/var/log/orchestrator.log",
rotation.max_size = 104857600, # 100MB per file
},
}
```
### Monitoring Configuration
Controls observability and metrics:
```bash
monitoring = {
enabled = true,
metrics.enabled = true,
health_check.enabled = true,
distributed_tracing.enabled = true,
audit_logging.enabled = true,
}
```
## Customization Examples
### Example 1: Change Workspace Name
Change the workspace identifier in solo mode:
```bash
workspace = {
name = "myproject",
path = "./provisioning/data/orchestrator",
}
```
Instead of default "development", use "myproject".
### Example 2: Custom Server Port
Change server port from default 9090:
```bash
server = {
port = 8888,
}
```
Useful if port 9090 is already in use.
### Example 3: Enable TLS in Solo Mode
Add TLS certificates to solo development:
```bash
security = {
tls = {
enabled = true,
cert_path = "./certs/localhost.crt",
key_path = "./certs/localhost.key",
},
}
```
Useful for testing TLS locally before production.
### Example 4: Custom Storage Path
Use custom storage location:
```bash
storage = {
path = "/mnt/fast-storage/orchestrator/data",
}
```
Useful if you have fast SSD storage available.
### Example 5: Increase Workers for Staging
Increase from 4 to 8 workers in multiuser:
```bash
server = {
workers = 8,
}
```
Useful when you have more CPU cores available.
## Troubleshooting Configuration
### Issue: "Configuration Won't Validate"
```toml
# Check for Nickel syntax errors
nickel typecheck provisioning/config/runtime/orchestrator.solo.ncl
# Get detailed error message
nickel typecheck -i provisioning/config/runtime/orchestrator.solo.ncl
```
The typecheck command will show exactly where the syntax error is.
### Issue: "Service Won't Start"
```bash
# Verify TOML was exported correctly
cat provisioning/config/runtime/generated/orchestrator.solo.toml | head -20
# Check TOML syntax is valid
toml-cli validate provisioning/config/runtime/generated/orchestrator.solo.toml
```
The TOML must be valid for the Rust service to parse it.
### Issue: "Service Uses Wrong Configuration"
```toml
# Verify deployment mode is set
echo $ORCHESTRATOR_MODE
# Check which TOML file service reads
ls -lah provisioning/config/runtime/generated/orchestrator.*.toml
# Verify TOML modification time is recent
stat provisioning/config/runtime/generated/orchestrator.solo.toml
```
The service reads from `orchestrator.{MODE}.toml` based on environment variable.
## Best Practices
### Development (Solo Mode)
1. Start simple using the solo example as-is first
2. Iterate gradually, making one change at a time
3. Enable logging by setting level = "debug" for troubleshooting
4. Disable security features for local development (TLS/auth)
5. Store data in ./provisioning/data/ which is gitignored
### Staging (Multiuser Mode)
1. Mirror production settings to test realistically
2. Enable authentication even in staging to test auth flows
3. Enable TLS with valid certificates to test secure connections
4. Set up monitoring metrics and health checks
5. Plan worker count based on expected concurrent users
### Production (Enterprise Mode)
1. Follow the enterprise example as baseline configuration
2. Use secure vault for storing credentials and secrets
3. Enable redundancy with 3-way replication for HA
4. Enable full monitoring with distributed tracing
5. Test failover scenarios regularly
6. Enable audit logging for compliance
7. Enforce TLS 1.3 and certificate rotation
## Migration Between Modes
To upgrade from solo → multiuser → enterprise:
```bash
# 1. Backup current configuration
cp provisioning/config/runtime/orchestrator.solo.ncl
provisioning/config/runtime/orchestrator.solo.ncl.bak
# 2. Copy new example for target mode
cp provisioning/config/examples/orchestrator.multiuser.example.ncl
provisioning/config/runtime/orchestrator.multiuser.ncl
# 3. Customize for your environment
vim provisioning/config/runtime/orchestrator.multiuser.ncl
# 4. Validate and generate TOML
./provisioning/scripts/setup-platform-config.sh --generate-toml
# 5. Update mode environment variable and restart
export ORCHESTRATOR_MODE=multiuser
cargo run -p orchestrator
```
## Related Documentation
- **Platform Configuration Guide**: `provisioning/docs/src/getting-started/05-platform-configuration.md`
- **Configuration README**: `provisioning/config/README.md`
- **System Status**: `provisioning/config/SETUP_STATUS.md`
- **Setup Script Reference**: `provisioning/scripts/setup-platform-config.sh.md`
- **Advanced TypeDialog Guide**: `provisioning/docs/src/development/typedialog-platform-config-guide.md`
---
**Version**: 1.0.0
**Last Updated**: 2026-01-05
**Status**: Ready to use

View file

@ -1,15 +0,0 @@
# Example: Control Center Service Configuration (Solo Development Mode)
#
# Control Center is the web UI and management console.
# Copy this file to provisioning/config/runtime/control-center.solo.ncl
#
# Generated: 2026-01-05
let helpers = import "../../schemas/platform/common/helpers.ncl" in
let defaults = import "../../schemas/platform/defaults/control-center-defaults.ncl" in
let mode_config = import "../../schemas/platform/defaults/deployment/solo-defaults.ncl" in
# Solo mode composition
helpers.compose_config defaults mode_config {
# Optional: Customize for your development setup
}

View file

@ -1,193 +0,0 @@
[control_center.audit]
enabled = false
redact_sensitive = true
[control_center.audit.storage]
immutable = false
retention_days = 90
[control_center.compliance]
enabled = false
encryption_required = false
[control_center.compliance.data_retention]
audit_log_days = 2555
policy_years = 7
[control_center.compliance.validation]
enabled = false
interval_hours = 24
[control_center.database]
backend = "rocksdb"
max_retries = "3"
path = "/var/lib/provisioning/control-center/data"
pool_size = 10
retry = true
timeout = 30
[control_center.integrations.ldap]
enabled = false
[control_center.integrations.oauth2]
enabled = false
[control_center.integrations.webhooks]
enabled = false
[control_center.logging]
format = "&"
level = "&"
outputs = ["stdout"]
[control_center.logging.fields]
caller = false
hostname = true
pid = true
service_name = true
stack_trace = false
timestamp = true
[control_center.logging.file]
compress = false
max_age = 30
max_backups = 10
max_size = 104857600
path = "/var/log/provisioning/service.log"
[control_center.logging.performance]
enabled = false
memory_info = false
slow_threshold = 1000
[control_center.logging.sampling]
enabled = false
initial = 100
thereafter = 100
[control_center.logging.syslog]
protocol = "udp"
[control_center.monitoring]
enabled = false
[control_center.monitoring.alerting]
enabled = false
[control_center.monitoring.health_check]
enabled = false
endpoint = "/health"
healthy_threshold = 2
interval = 30
timeout = 5000
type = "&"
unhealthy_threshold = 3
[control_center.monitoring.metrics]
buffer_size = 1000
enabled = false
interval = 60
prometheus_path = "/metrics"
retention_days = 30
[control_center.monitoring.resources]
alert_threshold = 80
cpu = false
disk = false
memory = false
network = false
[control_center.monitoring.tracing]
enabled = false
sample_rate = 0.1
[control_center.policy]
enabled = true
[control_center.policy.cache]
enabled = true
max_policies = 10000
ttl = 3600
[control_center.policy.versioning]
enabled = true
max_versions = 20
[control_center.rbac]
attribute_based = false
default_role = "user"
dynamic_roles = false
enabled = true
hierarchy = true
[control_center.rbac.roles]
admin = true
operator = true
viewer = true
[control_center.security.cors]
allow_credentials = false
enabled = false
[control_center.security.jwt]
algorithm = "HS256"
audience = "provisioning"
expiration = 3600
issuer = "control-center"
refresh_expiration = 86400
secret = "change_me_in_production"
[control_center.security.mfa]
lockout_duration = 15
max_attempts = "5"
methods = ["totp"]
required = false
[control_center.security.rate_limiting]
enabled = false
max_requests = "1000"
window_seconds = 60
[control_center.security.rbac]
default_role = "user"
enabled = true
inheritance = true
[control_center.security.session]
idle_timeout = 3600
max_duration = 86400
tracking = false
[control_center.security.tls]
client_auth = false
enabled = false
[control_center.server]
graceful_shutdown = true
host = "127.0.0.1"
keep_alive = 75
max_connections = 100
port = 8080
request_timeout = 30000
shutdown_timeout = 30
workers = 4
[control_center.users]
audit_enabled = false
enabled = true
[control_center.users.registration]
auto_assign_role = "user"
enabled = true
requires_approval = false
[control_center.users.sessions]
absolute_timeout = 86400
idle_timeout = 3600
max_active = 5
[control_center.workspace]
enabled = true
multi_workspace = false
name = "default"
path = "/var/lib/provisioning/control-center"

View file

@ -1,86 +0,0 @@
# Extension Registry Configuration - Enterprise Example
# High-availability, multi-source, multi-registry production deployment
[server]
enable_compression = true
enable_cors = true
host = "0.0.0.0"
port = 8082
workers = 8
# Primary internal Gitea instance
[[sources.gitea]]
id = "primary-internal-gitea"
organization = "platform-extensions"
timeout_seconds = 30
token_path = "/etc/secrets/gitea-primary-token.txt"
url = "https://gitea.internal.company.com"
verify_ssl = true
# Secondary internal Gitea (failover)
[[sources.gitea]]
id = "secondary-internal-gitea"
organization = "platform-extensions"
timeout_seconds = 30
token_path = "/etc/secrets/gitea-secondary-token.txt"
url = "https://gitea-secondary.internal.company.com"
verify_ssl = true
# Forgejo for community extensions
[[sources.forgejo]]
id = "enterprise-forgejo"
organization = "platform"
timeout_seconds = 30
token_path = "/etc/secrets/forgejo-token.txt"
url = "https://forge.company.com"
verify_ssl = true
# GitHub organization
[[sources.github]]
id = "company-github"
organization = "company-platform"
timeout_seconds = 30
token_path = "/etc/secrets/github-token.txt"
verify_ssl = true
# Primary enterprise OCI registry (Zot)
[[distributions.oci]]
id = "primary-oci-zot"
namespace = "platform/extensions"
registry = "zot.internal.company.com"
timeout_seconds = 30
verify_ssl = true
# Secondary enterprise OCI registry (Harbor)
[[distributions.oci]]
auth_token_path = "/etc/secrets/harbor-token.txt"
id = "secondary-oci-harbor"
namespace = "platform"
registry = "harbor.internal.company.com"
timeout_seconds = 30
verify_ssl = true
# Public Docker Hub for external distribution
[[distributions.oci]]
auth_token_path = "/etc/secrets/docker-hub-token.txt"
id = "public-docker-hub"
namespace = "company-open-source"
registry = "docker.io"
timeout_seconds = 30
verify_ssl = true
# Public GHCR for open-source projects
[[distributions.oci]]
auth_token_path = "/etc/secrets/ghcr-token.txt"
id = "public-ghcr"
namespace = "company-open-source"
registry = "ghcr.io"
timeout_seconds = 30
verify_ssl = true
# Caching configuration for high-traffic enterprise environment
[cache]
capacity = 5000
enable_list_cache = true
enable_metadata_cache = true
ttl_seconds = 600

View file

@ -1,89 +0,0 @@
# Extension Registry Configuration - Multi-Backend Example
# This example demonstrates the new multi-instance architecture supporting
# multiple Git-based sources (Gitea, Forgejo, GitHub) and multiple OCI registries
[server]
enable_compression = true
enable_cors = false
host = "0.0.0.0"
port = 8082
workers = 4
# Multiple Git-based source backends
# Internal Gitea instance for private extensions
[[sources.gitea]]
id = "internal-gitea"
organization = "provisioning"
timeout_seconds = 30
token_path = "/etc/secrets/gitea-internal-token.txt"
url = "https://gitea.internal.example.com"
verify_ssl = true
# Public Gitea instance for community extensions
[[sources.gitea]]
id = "public-gitea"
organization = "provisioning-extensions"
timeout_seconds = 30
token_path = "/etc/secrets/gitea-public-token.txt"
url = "https://gitea.public.example.com"
verify_ssl = true
# Forgejo sources (Git-compatible)
[[sources.forgejo]]
id = "community-forgejo"
organization = "provisioning"
timeout_seconds = 30
token_path = "/etc/secrets/forgejo-token.txt"
url = "https://forgejo.community.example.com"
verify_ssl = true
# GitHub sources
[[sources.github]]
id = "org-github"
organization = "my-organization"
timeout_seconds = 30
token_path = "/etc/secrets/github-token.txt"
verify_ssl = true
# Multiple OCI distribution registries
# Internal Zot registry
[[distributions.oci]]
id = "internal-zot"
namespace = "provisioning/extensions"
registry = "zot.internal.example.com"
timeout_seconds = 30
verify_ssl = true
# Public Harbor registry
[[distributions.oci]]
auth_token_path = "/etc/secrets/harbor-token.txt"
id = "public-harbor"
namespace = "provisioning"
registry = "harbor.public.example.com"
timeout_seconds = 30
verify_ssl = true
# Docker Hub
[[distributions.oci]]
auth_token_path = "/etc/secrets/docker-hub-token.txt"
id = "docker-hub"
namespace = "myorg"
registry = "docker.io"
timeout_seconds = 30
verify_ssl = true
# GHCR (GitHub Container Registry)
[[distributions.oci]]
auth_token_path = "/etc/secrets/ghcr-token.txt"
id = "ghcr"
namespace = "my-organization"
registry = "ghcr.io"
timeout_seconds = 30
verify_ssl = true
# Caching configuration
[cache]
capacity = 1000
enable_list_cache = true
enable_metadata_cache = true
ttl_seconds = 300

View file

@ -1,25 +0,0 @@
# Extension Registry Configuration - Solo/Minimal Example
# Minimal configuration for development or single-backend deployments
# Old single-instance format (auto-migrated to multi-instance on startup)
[server]
enable_compression = true
enable_cors = false
host = "127.0.0.1"
port = 8082
workers = 2
# Single Gitea backend (auto-migrated to sources.gitea[0])
[gitea]
organization = "provisioning"
timeout_seconds = 30
token_path = "/etc/secrets/gitea-token.txt"
url = "http://localhost:3000"
verify_ssl = false
# Caching configuration
[cache]
capacity = 100
enable_list_cache = true
enable_metadata_cache = true
ttl_seconds = 300

View file

@ -1,23 +0,0 @@
# Example: Orchestrator Service Configuration (Enterprise Production Mode)
#
# This is a reference configuration showing typical settings for production deployment.
# Copy this file to provisioning/config/runtime/orchestrator.enterprise.ncl and customize
# as needed for your production environment.
#
# Enterprise mode (16+ CPU, 32+ GB RAM):
# - Production deployments
# - High availability and redundancy
# - Multi-team/multi-workspace
# - Mission-critical workloads
# - Full monitoring and security
#
# Generated: 2026-01-05
let helpers = import "../../schemas/platform/common/helpers.ncl" in
let defaults = import "../../schemas/platform/defaults/orchestrator-defaults.ncl" in
let mode_config = import "../../schemas/platform/defaults/deployment/enterprise-defaults.ncl" in
# Enterprise mode composition: base defaults + mode overlay
helpers.compose_config defaults mode_config {
# Optional: Production overrides
}

View file

@ -1,126 +0,0 @@
[orchestrator.batch]
metrics = false
operation_timeout = 1800000
parallel_limit = 5
[orchestrator.batch.checkpointing]
enabled = true
interval = 100
max_checkpoints = 10
[orchestrator.batch.rollback]
enabled = true
max_rollback_depth = 5
strategy = "checkpoint_based"
[orchestrator.extensions]
auto_load = false
discovery_interval = 300
max_concurrent = 5
sandbox = true
timeout = 30000
[orchestrator.logging]
format = "&"
level = "&"
outputs = ["stdout"]
[orchestrator.logging.fields]
caller = false
hostname = true
pid = true
service_name = true
stack_trace = false
timestamp = true
[orchestrator.logging.file]
compress = false
max_age = 30
max_backups = 10
max_size = 104857600
path = "/var/log/provisioning/service.log"
[orchestrator.logging.performance]
enabled = false
memory_info = false
slow_threshold = 1000
[orchestrator.logging.sampling]
enabled = false
initial = 100
thereafter = 100
[orchestrator.logging.syslog]
protocol = "udp"
[orchestrator.monitoring]
enabled = false
[orchestrator.monitoring.alerting]
enabled = false
[orchestrator.monitoring.health_check]
enabled = false
endpoint = "/health"
healthy_threshold = 2
interval = 30
timeout = 5000
type = "&"
unhealthy_threshold = 3
[orchestrator.monitoring.metrics]
buffer_size = 1000
enabled = false
interval = 60
prometheus_path = "/metrics"
retention_days = 30
[orchestrator.monitoring.resources]
alert_threshold = 80
cpu = false
disk = false
memory = false
network = false
[orchestrator.monitoring.tracing]
enabled = false
sample_rate = 0.1
[orchestrator.queue]
max_concurrent_tasks = 5
metrics = false
persist = true
priority_queue = false
retry_attempts = 3
retry_delay = 5000
task_timeout = 3600000
[orchestrator.queue.dead_letter_queue]
enabled = true
max_size = 1000
[orchestrator.server]
graceful_shutdown = true
host = "127.0.0.1"
keep_alive = 75
max_connections = 100
port = 9090
request_timeout = 30000
shutdown_timeout = 30
workers = 4
[orchestrator.storage]
backend = "filesystem"
path = "/var/lib/provisioning/orchestrator/data"
[orchestrator.storage.cache]
enabled = true
eviction_policy = "lru"
ttl = 3600
type = "in_memory"
[orchestrator.workspace]
enabled = true
multi_workspace = false
name = "default"
path = "/var/lib/provisioning/orchestrator"

View file

@ -1,22 +0,0 @@
# Example: Orchestrator Service Configuration (Multiuser Team Mode)
#
# This is a reference configuration showing typical settings for team staging.
# Copy this file to provisioning/config/runtime/orchestrator.multiuser.ncl and customize
# as needed for your environment.
#
# Multiuser mode (4 CPU, 8GB RAM):
# - Team staging environments
# - Multiple concurrent users
# - Moderate production-like testing
# - Integration testing
#
# Generated: 2026-01-05
let helpers = import "../../schemas/platform/common/helpers.ncl" in
let defaults = import "../../schemas/platform/defaults/orchestrator-defaults.ncl" in
let mode_config = import "../../schemas/platform/defaults/deployment/multiuser-defaults.ncl" in
# Multiuser mode composition: base defaults + mode overlay
helpers.compose_config defaults mode_config {
# Optional: Custom overrides for your team environment
}

View file

@ -1,21 +0,0 @@
# Example: Orchestrator Service Configuration (Solo Development Mode)
#
# This is a reference configuration showing typical settings for solo development.
# Copy this file to provisioning/config/runtime/orchestrator.solo.ncl and customize
# as needed for your environment.
#
# Solo mode (2 CPU, 4GB RAM):
# - Local development
# - Testing and validation
# - Single-user deployments
#
# Generated: 2026-01-05
let helpers = import "../../schemas/platform/common/helpers.ncl" in
let defaults = import "../../schemas/platform/defaults/orchestrator-defaults.ncl" in
let mode_config = import "../../schemas/platform/defaults/deployment/solo-defaults.ncl" in
# Solo mode composition: base defaults + mode overlay
helpers.compose_config defaults mode_config {
# Optional: User customizations (empty for defaults)
}

View file

@ -1,126 +0,0 @@
[orchestrator.batch]
metrics = false
operation_timeout = 1800000
parallel_limit = 5
[orchestrator.batch.checkpointing]
enabled = true
interval = 100
max_checkpoints = 10
[orchestrator.batch.rollback]
enabled = true
max_rollback_depth = 5
strategy = "checkpoint_based"
[orchestrator.extensions]
auto_load = false
discovery_interval = 300
max_concurrent = 5
sandbox = true
timeout = 30000
[orchestrator.logging]
format = "&"
level = "&"
outputs = ["stdout"]
[orchestrator.logging.fields]
caller = false
hostname = true
pid = true
service_name = true
stack_trace = false
timestamp = true
[orchestrator.logging.file]
compress = false
max_age = 30
max_backups = 10
max_size = 104857600
path = "/var/log/provisioning/service.log"
[orchestrator.logging.performance]
enabled = false
memory_info = false
slow_threshold = 1000
[orchestrator.logging.sampling]
enabled = false
initial = 100
thereafter = 100
[orchestrator.logging.syslog]
protocol = "udp"
[orchestrator.monitoring]
enabled = false
[orchestrator.monitoring.alerting]
enabled = false
[orchestrator.monitoring.health_check]
enabled = false
endpoint = "/health"
healthy_threshold = 2
interval = 30
timeout = 5000
type = "&"
unhealthy_threshold = 3
[orchestrator.monitoring.metrics]
buffer_size = 1000
enabled = false
interval = 60
prometheus_path = "/metrics"
retention_days = 30
[orchestrator.monitoring.resources]
alert_threshold = 80
cpu = false
disk = false
memory = false
network = false
[orchestrator.monitoring.tracing]
enabled = false
sample_rate = 0.1
[orchestrator.queue]
max_concurrent_tasks = 5
metrics = false
persist = true
priority_queue = false
retry_attempts = 3
retry_delay = 5000
task_timeout = 3600000
[orchestrator.queue.dead_letter_queue]
enabled = true
max_size = 1000
[orchestrator.server]
graceful_shutdown = true
host = "127.0.0.1"
keep_alive = 75
max_connections = 100
port = 9090
request_timeout = 30000
shutdown_timeout = 30
workers = 4
[orchestrator.storage]
backend = "filesystem"
path = "/var/lib/provisioning/orchestrator/data"
[orchestrator.storage.cache]
enabled = true
eviction_policy = "lru"
ttl = 3600
type = "in_memory"
[orchestrator.workspace]
enabled = true
multi_workspace = false
name = "default"
path = "/var/lib/provisioning/orchestrator"

View file

@ -1,15 +0,0 @@
# Example: Vault Service Configuration (Solo Development Mode)
#
# Vault Service handles secrets management and encryption.
# Copy this file to provisioning/config/runtime/vault-service.solo.ncl
#
# Generated: 2026-01-05
let helpers = import "../../schemas/platform/common/helpers.ncl" in
let defaults = import "../../schemas/platform/defaults/vault-service-defaults.ncl" in
let mode_config = import "../../schemas/platform/defaults/deployment/solo-defaults.ncl" in
# Solo mode composition
helpers.compose_config defaults mode_config {
# Optional: Customize for your development setup
}

2
core

@ -1 +1 @@
Subproject commit adb28be45a8c7ea2763da8b680bf719b0b128be7
Subproject commit 85ab055ccb5cccea5a9ff04c7c4a0566a2de8c0d

View file

@ -1,103 +0,0 @@
// Markdownlint-cli2 Configuration
// Documentation quality enforcement aligned with CLAUDE.md guidelines
// See: https://github.com/igorshubovych/markdownlint-cli2
{
"config": {
"default": true,
// Headings - enforce proper hierarchy
"MD001": false, // heading-increment (relaxed - allow flexibility)
"MD026": { "punctuation": ".,;:!?" }, // heading-punctuation
// Lists - enforce consistency
"MD004": { "style": "consistent" }, // ul-style (consistent list markers)
"MD005": false, // inconsistent-indentation (relaxed)
"MD007": { "indent": 2 }, // ul-indent
"MD029": false, // ol-prefix (allow flexible list numbering)
"MD030": { "ul_single": 1, "ol_single": 1, "ul_multi": 1, "ol_multi": 1 },
// Code blocks - fenced only
"MD046": { "style": "fenced" }, // code-block-style
// CRITICAL: MD040 only checks for missing language on opening fence.
// It does NOT catch malformed closing fences with language specifiers (e.g., ```plaintext).
// This is a CommonMark violation that must be caught by custom pre-commit hook.
// Pre-commit hook: check-malformed-fences (provisioning/core/.pre-commit-config.yaml)
// Script: provisioning/scripts/check-malformed-fences.nu
// Formatting - strict whitespace
"MD009": true, // no-hard-tabs
"MD010": true, // hard-tabs
"MD011": true, // reversed-link-syntax
"MD018": true, // no-missing-space-atx
"MD019": true, // no-multiple-space-atx
"MD020": true, // no-missing-space-closed-atx
"MD021": true, // no-multiple-space-closed-atx
"MD023": true, // heading-starts-line
"MD027": true, // no-multiple-spaces-blockquote
"MD037": true, // no-space-in-emphasis
"MD039": true, // no-space-in-links
// Trailing content
"MD012": false, // no-multiple-blanks (relaxed - allow formatting space)
"MD024": false, // no-duplicate-heading (too strict for docs)
"MD028": false, // no-blanks-blockquote (relaxed)
"MD031": false, // blanks-around-fences (too strict for technical docs)
"MD047": true, // single-trailing-newline
// Links and references
"MD034": true, // no-bare-urls (links must be formatted)
"MD040": true, // fenced-code-language (code blocks need language)
"MD042": true, // no-empty-links
// HTML - allow for documentation formatting and images
"MD033": { "allowed_elements": ["br", "hr", "details", "summary", "p", "img"] },
// Line length - relaxed for technical documentation
"MD013": {
"line_length": 150,
"heading_line_length": 150,
"code_block_line_length": 150,
"code_blocks": true,
"tables": true,
"headers": true,
"headers_line_length": 150,
"strict": false,
"stern": false
},
// Images
"MD045": true, // image-alt-text
// Disable rules that conflict with relaxed style
"MD003": false, // consistent-indentation
"MD041": false, // first-line-heading
"MD025": false, // single-h1 / multiple-top-level-headings
"MD022": false, // blanks-around-headings (flexible spacing)
"MD032": false, // blanks-around-lists (flexible spacing)
"MD035": false, // hr-style (consistent)
"MD036": false, // no-emphasis-as-heading
"MD044": false, // proper-names
"MD060": true // table-column-style (enforce proper table formatting)
},
// Documentation patterns
"globs": [
"docs/**/*.md",
"!docs/node_modules/**",
"!docs/build/**"
],
// Ignore build artifacts, external content, and operational directories
"ignores": [
"node_modules/**",
"target/**",
".git/**",
"build/**",
"dist/**",
".coder/**",
".claude/**",
".wrks/**",
".vale/**"
]
}

View file

@ -1,48 +0,0 @@
[book]
title = "Provisioning Platform Documentation"
authors = ["Provisioning Team"]
language = "en"
multilingual = false
src = "src"
description = "Enterprise-grade Infrastructure as Code platform - Complete documentation"
[build]
build-dir = "book"
create-missing = true
[output.html]
default-theme = "rust"
preferred-dark-theme = "navy"
smart-punctuation = true
mathjax-support = false
copy-fonts = true
no-section-label = false
git-repository-url = "https://github.com/your-org/provisioning"
git-repository-icon = "fa-github"
edit-url-template = "https://github.com/your-org/provisioning/edit/main/provisioning/docs/{path}"
site-url = "/provisioning/"
[output.html.fold]
enable = true
level = 1
[output.html.search]
enable = true
limit-results = 30
teaser-word-count = 30
use-boolean-and = true
boost-title = 2
boost-hierarchy = 1
boost-paragraph = 1
expand = true
[output.html.playground]
editable = true
copyable = true
copy-js = true
line-numbers = true
runnable = false
[preprocessor.links]
[preprocessor.index]

View file

@ -1 +0,0 @@
This file makes sure that Github Pages doesn't process mdBook's output.

View file

@ -1,238 +0,0 @@
<!DOCTYPE HTML>
<html lang="en" class="rust sidebar-visible" dir="ltr">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Page not found - Provisioning Platform Documentation</title>
<base href="/">
<!-- Custom HTML head -->
<meta name="description" content="Enterprise-grade Infrastructure as Code platform - Complete documentation">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff">
<link rel="icon" href="favicon.svg">
<link rel="shortcut icon" href="favicon.png">
<link rel="stylesheet" href="css/variables.css">
<link rel="stylesheet" href="css/general.css">
<link rel="stylesheet" href="css/chrome.css">
<link rel="stylesheet" href="css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
<link rel="stylesheet" href="fonts/fonts.css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" id="highlight-css" href="highlight.css">
<link rel="stylesheet" id="tomorrow-night-css" href="tomorrow-night.css">
<link rel="stylesheet" id="ayu-highlight-css" href="ayu-highlight.css">
<!-- Custom theme stylesheets -->
<!-- Provide site root and default themes to javascript -->
<script>
const path_to_root = "";
const default_light_theme = "rust";
const default_dark_theme = "navy";
</script>
<!-- Start loading toc.js asap -->
<script src="toc.js"></script>
</head>
<body>
<div id="mdbook-help-container">
<div id="mdbook-help-popup">
<h2 class="mdbook-help-title">Keyboard shortcuts</h2>
<div>
<p>Press <kbd></kbd> or <kbd></kbd> to navigate between chapters</p>
<p>Press <kbd>S</kbd> or <kbd>/</kbd> to search in the book</p>
<p>Press <kbd>?</kbd> to show this help</p>
<p>Press <kbd>Esc</kbd> to hide this help</p>
</div>
</div>
</div>
<div id="body-container">
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script>
try {
let theme = localStorage.getItem('mdbook-theme');
let sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script>
const default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? default_dark_theme : default_light_theme;
let theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
const html = document.documentElement;
html.classList.remove('rust')
html.classList.add(theme);
html.classList.add("js");
</script>
<input type="checkbox" id="sidebar-toggle-anchor" class="hidden">
<!-- Hide / unhide sidebar before it is displayed -->
<script>
let sidebar = null;
const sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
} else {
sidebar = 'hidden';
}
sidebar_toggle.checked = sidebar === 'visible';
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<!-- populated by js -->
<mdbook-sidebar-scrollbox class="sidebar-scrollbox"></mdbook-sidebar-scrollbox>
<noscript>
<iframe class="sidebar-iframe-outer" src="toc.html"></iframe>
</noscript>
<div id="sidebar-resize-handle" class="sidebar-resize-handle">
<div class="sidebar-resize-indicator"></div>
</div>
</nav>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar-hover-placeholder"></div>
<div id="menu-bar" class="menu-bar sticky">
<div class="left-buttons">
<label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</label>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="default_theme">Auto</button></li>
<li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
<button id="search-toggle" class="icon-button" type="button" title="Search (`/`)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="/ s" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>
<h1 class="menu-title">Provisioning Platform Documentation</h1>
<div class="right-buttons">
<a href="print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
<a href="https://github.com/your-org/provisioning" title="Git repository" aria-label="Git repository">
<i id="git-repository-button" class="fa fa-github"></i>
</a>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script>
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<main>
<h1 id="document-not-found-404"><a class="header" href="#document-not-found-404">Document not found (404)</a></h1>
<p>This URL is invalid, sorry. Please use the navigation bar or search to continue.</p>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
</nav>
</div>
<!-- Livereload script (if served using the cli tool) -->
<script>
const wsProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
const wsAddress = wsProtocol + "//" + location.host + "/" + "__livereload";
const socket = new WebSocket(wsAddress);
socket.onmessage = function (event) {
if (event.data === "reload") {
socket.close();
location.reload();
}
};
window.onbeforeunload = function() {
socket.close();
}
</script>
<script>
window.playground_line_numbers = true;
</script>
<script>
window.playground_copyable = true;
</script>
<script src="ace.js"></script>
<script src="mode-rust.js"></script>
<script src="editor.js"></script>
<script src="theme-dawn.js"></script>
<script src="theme-tomorrow_night.js"></script>
<script src="elasticlunr.min.js"></script>
<script src="mark.min.js"></script>
<script src="searcher.js"></script>
<script src="clipboard.min.js"></script>
<script src="highlight.js"></script>
<script src="book.js"></script>
<!-- Custom JS scripts -->
</div>
</body>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

Before

Width:  |  Height:  |  Size: 433 KiB

Some files were not shown because too many files have changed in this diff Show more