From a658bdd73a26cafb7ed275db8b9a15fff1b0c896 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesu=CC=81s=20Pe=CC=81rez?= Date: Thu, 8 Jan 2026 09:52:22 +0000 Subject: [PATCH] chore: complete nickel migration and consolidate legacy configs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove KCL ecosystem (~220 files deleted) - Migrate all infrastructure to Nickel schema system - Consolidate documentation: legacy docs β†’ provisioning/docs/src/ - Add CI/CD workflows (.github/) and Rust build config (.cargo/) - Update core system for Nickel schema parsing - Breaking changes: KCL workspaces require migration - Migration bridge available in docs/src/development/ --- .cargo/audit.toml | 37 + .cargo/config.toml | 72 ++ .github/workflows/nickel-typecheck.yml | 116 +++ .github/workflows/nushell-lint.yml | 28 + .github/workflows/rust-ci.yml | 47 ++ .gitignore | 12 +- .markdownlint-cli2.jsonc | 96 +++ .pre-commit-config.yaml | 124 ++++ .rustfmt.toml | 53 ++ .shellcheckrc | 51 ++ .taplo.toml | 49 ++ .typedialog/ci/2026_01_03_01_form.toml | 259 +++++++ .typedialog/ci/README.md | 328 ++++++++ .typedialog/ci/config.ncl | 175 +++++ .typedialog/ci/configure.sh | 116 +++ .typedialog/ci/envrc | 27 + .typedialog/ci/form.toml | 259 +++++++ .typedialog/platform/forms/README.md | 390 ++++++++++ .../platform/forms/ai-service-form.toml | 13 + .../platform/forms/control-center-form.toml | 118 +++ .../forms/extension-registry-form.toml | 36 + .../platform/forms/fragments/README.md | 334 +++++++++ .../forms/fragments/ai-service/dag.toml | 38 + .../fragments/ai-service/mcp-integration.toml | 37 + .../fragments/ai-service/monitoring.toml | 27 + .../fragments/ai-service/rag-integration.toml | 37 + .../forms/fragments/ai-service/server.toml | 39 + .../constraint_interpolation_guide.md | 225 ++++++ .../fragments/constraint_update_status.md | 298 ++++++++ .../control-center/compliance-section.toml | 108 +++ .../control-center/policy-section.toml | 67 ++ .../control-center/rbac-section.toml | 49 ++ .../control-center/security-section.toml | 184 +++++ .../control-center/users-section.toml | 89 +++ .../fragments/database-postgres-section.toml | 101 +++ .../fragments/database-rocksdb-section.toml | 66 ++ .../fragments/database-surrealdb-section.toml | 81 ++ .../database-backend-selection.toml | 93 +++ .../fragments/deployment/mode-selection.toml | 95 +++ .../fragments/extension-registry/auth.toml | 35 + .../fragments/extension-registry/cache.toml | 44 ++ .../fragments/extension-registry/gitea.toml | 56 ++ .../fragments/extension-registry/oci.toml | 56 ++ .../fragments/extension-registry/server.toml | 55 ++ .../fragments/installer/database-section.toml | 244 ++++++ .../forms/fragments/installer/ha-section.toml | 288 +++++++ .../installer/installation-section.toml | 234 ++++++ .../installer/networking-section.toml | 285 +++++++ .../installer/post-install-section.toml | 317 ++++++++ .../installer/preflight-section.toml | 203 +++++ .../fragments/installer/services-section.toml | 189 +++++ .../fragments/installer/storage-section.toml | 236 ++++++ .../fragments/installer/target-section.toml | 160 ++++ .../fragments/installer/upgrades-section.toml | 359 +++++++++ .../forms/fragments/logging-section.toml | 57 ++ .../fragments/mcp-server/prompts-section.toml | 67 ++ .../mcp-server/resources-section.toml | 78 ++ .../mcp-server/sampling-section.toml | 67 ++ .../fragments/mcp-server/tools-section.toml | 75 ++ .../forms/fragments/monitoring-section.toml | 37 + .../fragments/orchestrator/batch-section.toml | 93 +++ .../orchestrator/extensions-section.toml | 182 +++++ .../orchestrator/performance-section.toml | 230 ++++++ .../fragments/orchestrator/queue-section.toml | 72 ++ .../orchestrator/storage-section.toml | 173 +++++ .../provisioning-daemon/actions.toml | 48 ++ .../fragments/provisioning-daemon/daemon.toml | 36 + .../fragments/provisioning-daemon/health.toml | 38 + .../provisioning-daemon/logging.toml | 43 ++ .../provisioning-daemon/workers.toml | 38 + .../provisioning/platform/scripts/README.md | 98 +++ .../forms/fragments/rag/embeddings.toml | 56 ++ .../forms/fragments/rag/ingestion.toml | 52 ++ .../platform/forms/fragments/rag/llm.toml | 67 ++ .../forms/fragments/rag/retrieval.toml | 44 ++ .../forms/fragments/rag/vector-db.toml | 47 ++ .../forms/fragments/server-section.toml | 85 +++ .../forms/fragments/vault-service/ha.toml | 27 + .../forms/fragments/vault-service/mount.toml | 26 + .../forms/fragments/vault-service/server.toml | 28 + .../fragments/vault-service/storage.toml | 37 + .../forms/fragments/vault-service/tls.toml | 46 ++ .../forms/fragments/workspace-section.toml | 36 + .../platform/forms/installer-form.toml | 110 +++ .../platform/forms/mcp-server-form.toml | 118 +++ .../platform/forms/orchestrator-form.toml | 127 ++++ .../forms/provisioning-daemon-form.toml | 13 + .typedialog/platform/forms/rag-form.toml | 23 + .../platform/forms/vault-service-form.toml | 29 + .typedialog/platform/scripts/README.md | 255 +++++++ .typedialog/platform/scripts/ansi.nu | 89 +++ .typedialog/platform/scripts/configure.nu | 101 +++ .../platform/scripts/detect-services.nu | 129 ++++ .typedialog/platform/scripts/export-toml.nu | 113 +++ .typedialog/platform/scripts/external.nu | 117 +++ .../platform/scripts/generate-configs.nu | 61 ++ .../platform/scripts/install-services.nu | 217 ++++++ .typedialog/platform/scripts/paths.nu | 143 ++++ .../platform/scripts/render-docker-compose.nu | 82 ++ .../platform/scripts/render-kubernetes.nu | 96 +++ .../platform/scripts/test-phase9-templates.nu | 152 ++++ .../platform/scripts/validate-config.nu | 29 + .typedialog/provisioning/config.ncl | 79 ++ .typedialog/provisioning/configure.nu | 175 +++++ .typedialog/provisioning/constraints.toml | 156 ++++ .../defaults/api-service-defaults.ncl | 121 +++ .../defaults/docker-compose-defaults.ncl | 74 ++ .../defaults/kubernetes-defaults.ncl | 444 +++++++++++ .../defaults/monitoring-defaults.ncl | 303 ++++++++ .../defaults/network-defaults.ncl | 170 +++++ .../defaults/provisioning-defaults.ncl | 196 +++++ .../defaults/security-defaults.ncl | 115 +++ .typedialog/provisioning/envrc | 10 + .typedialog/provisioning/form.toml | 252 +++++++ .../provisioning/fragments/auth-api-key.toml | 31 + .../provisioning/fragments/auth-jwt.toml | 46 ++ .../fragments/database-mysql.toml | 88 +++ .../fragments/database-postgres.toml | 92 +++ .../fragments/database-sqlite.toml | 44 ++ .../fragments/database-surrealdb.toml | 75 ++ .../fragments/deployment-docker.toml | 44 ++ .../fragments/deployment-k8s.toml | 153 ++++ .../provisioning/fragments/monitoring.toml | 98 +++ .typedialog/provisioning/schemas/database.ncl | 299 ++++++++ .../provisioning/schemas/deployment.ncl | 468 ++++++++++++ .../provisioning/schemas/monitoring.ncl | 371 +++++++++ .typedialog/provisioning/schemas/network.ncl | 242 ++++++ .../schemas/provisioning-config.ncl | 146 ++++ .typedialog/provisioning/schemas/security.ncl | 487 ++++++++++++ .typedialog/provisioning/schemas/service.ncl | 249 +++++++ .typedialog/provisioning/schemas/storage.ncl | 321 ++++++++ .../validators/common-validator.ncl | 137 ++++ .../validators/database-validator.ncl | 279 +++++++ .../validators/deployment-validator.ncl | 349 +++++++++ .../validators/network-validator.ncl | 207 ++++++ .../validators/resource-validator.ncl | 136 ++++ .../validators/service-validator.ncl | 265 +++++++ .vale.ini | 43 ++ .vale/Vocab/TypeDialog/accept.txt | 25 + .vale/Vocab/TypeDialog/reject.txt | 2 + .vale/styles/Google/AMPM.yml | 9 + .vale/styles/Google/Acronyms.yml | 64 ++ .vale/styles/Google/Colons.yml | 8 + .vale/styles/Google/Contractions.yml | 30 + .vale/styles/Google/DateFormat.yml | 9 + .vale/styles/Google/Ellipses.yml | 9 + .vale/styles/Google/EmDash.yml | 12 + .vale/styles/Google/Exclamation.yml | 12 + .vale/styles/Google/FirstPerson.yml | 13 + .vale/styles/Google/Gender.yml | 9 + .vale/styles/Google/GenderBias.yml | 43 ++ .vale/styles/Google/HeadingPunctuation.yml | 13 + .vale/styles/Google/Headings.yml | 29 + .vale/styles/Google/Latin.yml | 11 + .vale/styles/Google/LyHyphens.yml | 14 + .vale/styles/Google/OptionalPlurals.yml | 12 + .vale/styles/Google/Ordinal.yml | 7 + .vale/styles/Google/OxfordComma.yml | 7 + .vale/styles/Google/Parens.yml | 7 + .vale/styles/Google/Passive.yml | 184 +++++ .vale/styles/Google/Periods.yml | 7 + .vale/styles/Google/Quotes.yml | 7 + .vale/styles/Google/Ranges.yml | 7 + .vale/styles/Google/Semicolons.yml | 8 + .vale/styles/Google/Slang.yml | 11 + .vale/styles/Google/Spacing.yml | 10 + .vale/styles/Google/Spelling.yml | 10 + .vale/styles/Google/Units.yml | 8 + .vale/styles/Google/We.yml | 11 + .vale/styles/Google/Will.yml | 7 + .vale/styles/Google/WordList.yml | 80 ++ .vale/styles/Google/meta.json | 4 + .vale/styles/Google/vocab.txt | 0 .vale/styles/write-good/Cliches.yml | 702 ++++++++++++++++++ .vale/styles/write-good/E-Prime.yml | 32 + .vale/styles/write-good/Illusions.yml | 11 + .vale/styles/write-good/Passive.yml | 183 +++++ .vale/styles/write-good/README.md | 27 + .vale/styles/write-good/So.yml | 5 + .vale/styles/write-good/ThereIs.yml | 6 + .vale/styles/write-good/TooWordy.yml | 221 ++++++ .vale/styles/write-good/Weasel.yml | 29 + .vale/styles/write-good/meta.json | 4 + .woodpecker/Dockerfile | 45 ++ .woodpecker/Dockerfile.cross | 42 ++ .woodpecker/README.md | 79 ++ .woodpecker/ci-advanced.yml | 168 +++++ .woodpecker/ci.yml | 84 +++ .yamllint-ci.yml | 18 + CHANGELOG.md | 131 ++++ README.md | 458 +++++++----- 191 files changed, 20631 insertions(+), 200 deletions(-) create mode 100644 .cargo/audit.toml create mode 100644 .cargo/config.toml create mode 100644 .github/workflows/nickel-typecheck.yml create mode 100644 .github/workflows/nushell-lint.yml create mode 100644 .github/workflows/rust-ci.yml create mode 100644 .markdownlint-cli2.jsonc create mode 100644 .pre-commit-config.yaml create mode 100644 .rustfmt.toml create mode 100644 .shellcheckrc create mode 100644 .taplo.toml create mode 100644 .typedialog/ci/2026_01_03_01_form.toml create mode 100644 .typedialog/ci/README.md create mode 100644 .typedialog/ci/config.ncl create mode 100755 .typedialog/ci/configure.sh create mode 100644 .typedialog/ci/envrc create mode 100644 .typedialog/ci/form.toml create mode 100644 .typedialog/platform/forms/README.md create mode 100644 .typedialog/platform/forms/ai-service-form.toml create mode 100644 .typedialog/platform/forms/control-center-form.toml create mode 100644 .typedialog/platform/forms/extension-registry-form.toml create mode 100644 .typedialog/platform/forms/fragments/README.md create mode 100644 .typedialog/platform/forms/fragments/ai-service/dag.toml create mode 100644 .typedialog/platform/forms/fragments/ai-service/mcp-integration.toml create mode 100644 .typedialog/platform/forms/fragments/ai-service/monitoring.toml create mode 100644 .typedialog/platform/forms/fragments/ai-service/rag-integration.toml create mode 100644 .typedialog/platform/forms/fragments/ai-service/server.toml create mode 100644 .typedialog/platform/forms/fragments/constraint_interpolation_guide.md create mode 100644 .typedialog/platform/forms/fragments/constraint_update_status.md create mode 100644 .typedialog/platform/forms/fragments/control-center/compliance-section.toml create mode 100644 .typedialog/platform/forms/fragments/control-center/policy-section.toml create mode 100644 .typedialog/platform/forms/fragments/control-center/rbac-section.toml create mode 100644 .typedialog/platform/forms/fragments/control-center/security-section.toml create mode 100644 .typedialog/platform/forms/fragments/control-center/users-section.toml create mode 100644 .typedialog/platform/forms/fragments/database-postgres-section.toml create mode 100644 .typedialog/platform/forms/fragments/database-rocksdb-section.toml create mode 100644 .typedialog/platform/forms/fragments/database-surrealdb-section.toml create mode 100644 .typedialog/platform/forms/fragments/deployment/database-backend-selection.toml create mode 100644 .typedialog/platform/forms/fragments/deployment/mode-selection.toml create mode 100644 .typedialog/platform/forms/fragments/extension-registry/auth.toml create mode 100644 .typedialog/platform/forms/fragments/extension-registry/cache.toml create mode 100644 .typedialog/platform/forms/fragments/extension-registry/gitea.toml create mode 100644 .typedialog/platform/forms/fragments/extension-registry/oci.toml create mode 100644 .typedialog/platform/forms/fragments/extension-registry/server.toml create mode 100644 .typedialog/platform/forms/fragments/installer/database-section.toml create mode 100644 .typedialog/platform/forms/fragments/installer/ha-section.toml create mode 100644 .typedialog/platform/forms/fragments/installer/installation-section.toml create mode 100644 .typedialog/platform/forms/fragments/installer/networking-section.toml create mode 100644 .typedialog/platform/forms/fragments/installer/post-install-section.toml create mode 100644 .typedialog/platform/forms/fragments/installer/preflight-section.toml create mode 100644 .typedialog/platform/forms/fragments/installer/services-section.toml create mode 100644 .typedialog/platform/forms/fragments/installer/storage-section.toml create mode 100644 .typedialog/platform/forms/fragments/installer/target-section.toml create mode 100644 .typedialog/platform/forms/fragments/installer/upgrades-section.toml create mode 100644 .typedialog/platform/forms/fragments/logging-section.toml create mode 100644 .typedialog/platform/forms/fragments/mcp-server/prompts-section.toml create mode 100644 .typedialog/platform/forms/fragments/mcp-server/resources-section.toml create mode 100644 .typedialog/platform/forms/fragments/mcp-server/sampling-section.toml create mode 100644 .typedialog/platform/forms/fragments/mcp-server/tools-section.toml create mode 100644 .typedialog/platform/forms/fragments/monitoring-section.toml create mode 100644 .typedialog/platform/forms/fragments/orchestrator/batch-section.toml create mode 100644 .typedialog/platform/forms/fragments/orchestrator/extensions-section.toml create mode 100644 .typedialog/platform/forms/fragments/orchestrator/performance-section.toml create mode 100644 .typedialog/platform/forms/fragments/orchestrator/queue-section.toml create mode 100644 .typedialog/platform/forms/fragments/orchestrator/storage-section.toml create mode 100644 .typedialog/platform/forms/fragments/provisioning-daemon/actions.toml create mode 100644 .typedialog/platform/forms/fragments/provisioning-daemon/daemon.toml create mode 100644 .typedialog/platform/forms/fragments/provisioning-daemon/health.toml create mode 100644 .typedialog/platform/forms/fragments/provisioning-daemon/logging.toml create mode 100644 .typedialog/platform/forms/fragments/provisioning-daemon/workers.toml create mode 100644 .typedialog/platform/forms/fragments/provisioning/.typedialog/provisioning/platform/scripts/README.md create mode 100644 .typedialog/platform/forms/fragments/rag/embeddings.toml create mode 100644 .typedialog/platform/forms/fragments/rag/ingestion.toml create mode 100644 .typedialog/platform/forms/fragments/rag/llm.toml create mode 100644 .typedialog/platform/forms/fragments/rag/retrieval.toml create mode 100644 .typedialog/platform/forms/fragments/rag/vector-db.toml create mode 100644 .typedialog/platform/forms/fragments/server-section.toml create mode 100644 .typedialog/platform/forms/fragments/vault-service/ha.toml create mode 100644 .typedialog/platform/forms/fragments/vault-service/mount.toml create mode 100644 .typedialog/platform/forms/fragments/vault-service/server.toml create mode 100644 .typedialog/platform/forms/fragments/vault-service/storage.toml create mode 100644 .typedialog/platform/forms/fragments/vault-service/tls.toml create mode 100644 .typedialog/platform/forms/fragments/workspace-section.toml create mode 100644 .typedialog/platform/forms/installer-form.toml create mode 100644 .typedialog/platform/forms/mcp-server-form.toml create mode 100644 .typedialog/platform/forms/orchestrator-form.toml create mode 100644 .typedialog/platform/forms/provisioning-daemon-form.toml create mode 100644 .typedialog/platform/forms/rag-form.toml create mode 100644 .typedialog/platform/forms/vault-service-form.toml create mode 100644 .typedialog/platform/scripts/README.md create mode 100644 .typedialog/platform/scripts/ansi.nu create mode 100644 .typedialog/platform/scripts/configure.nu create mode 100644 .typedialog/platform/scripts/detect-services.nu create mode 100644 .typedialog/platform/scripts/export-toml.nu create mode 100644 .typedialog/platform/scripts/external.nu create mode 100644 .typedialog/platform/scripts/generate-configs.nu create mode 100644 .typedialog/platform/scripts/install-services.nu create mode 100644 .typedialog/platform/scripts/paths.nu create mode 100644 .typedialog/platform/scripts/render-docker-compose.nu create mode 100644 .typedialog/platform/scripts/render-kubernetes.nu create mode 100644 .typedialog/platform/scripts/test-phase9-templates.nu create mode 100644 .typedialog/platform/scripts/validate-config.nu create mode 100644 .typedialog/provisioning/config.ncl create mode 100755 .typedialog/provisioning/configure.nu create mode 100644 .typedialog/provisioning/constraints.toml create mode 100644 .typedialog/provisioning/defaults/api-service-defaults.ncl create mode 100644 .typedialog/provisioning/defaults/docker-compose-defaults.ncl create mode 100644 .typedialog/provisioning/defaults/kubernetes-defaults.ncl create mode 100644 .typedialog/provisioning/defaults/monitoring-defaults.ncl create mode 100644 .typedialog/provisioning/defaults/network-defaults.ncl create mode 100644 .typedialog/provisioning/defaults/provisioning-defaults.ncl create mode 100644 .typedialog/provisioning/defaults/security-defaults.ncl create mode 100644 .typedialog/provisioning/envrc create mode 100644 .typedialog/provisioning/form.toml create mode 100644 .typedialog/provisioning/fragments/auth-api-key.toml create mode 100644 .typedialog/provisioning/fragments/auth-jwt.toml create mode 100644 .typedialog/provisioning/fragments/database-mysql.toml create mode 100644 .typedialog/provisioning/fragments/database-postgres.toml create mode 100644 .typedialog/provisioning/fragments/database-sqlite.toml create mode 100644 .typedialog/provisioning/fragments/database-surrealdb.toml create mode 100644 .typedialog/provisioning/fragments/deployment-docker.toml create mode 100644 .typedialog/provisioning/fragments/deployment-k8s.toml create mode 100644 .typedialog/provisioning/fragments/monitoring.toml create mode 100644 .typedialog/provisioning/schemas/database.ncl create mode 100644 .typedialog/provisioning/schemas/deployment.ncl create mode 100644 .typedialog/provisioning/schemas/monitoring.ncl create mode 100644 .typedialog/provisioning/schemas/network.ncl create mode 100644 .typedialog/provisioning/schemas/provisioning-config.ncl create mode 100644 .typedialog/provisioning/schemas/security.ncl create mode 100644 .typedialog/provisioning/schemas/service.ncl create mode 100644 .typedialog/provisioning/schemas/storage.ncl create mode 100644 .typedialog/provisioning/validators/common-validator.ncl create mode 100644 .typedialog/provisioning/validators/database-validator.ncl create mode 100644 .typedialog/provisioning/validators/deployment-validator.ncl create mode 100644 .typedialog/provisioning/validators/network-validator.ncl create mode 100644 .typedialog/provisioning/validators/resource-validator.ncl create mode 100644 .typedialog/provisioning/validators/service-validator.ncl create mode 100644 .vale.ini create mode 100644 .vale/Vocab/TypeDialog/accept.txt create mode 100644 .vale/Vocab/TypeDialog/reject.txt create mode 100644 .vale/styles/Google/AMPM.yml create mode 100644 .vale/styles/Google/Acronyms.yml create mode 100644 .vale/styles/Google/Colons.yml create mode 100644 .vale/styles/Google/Contractions.yml create mode 100644 .vale/styles/Google/DateFormat.yml create mode 100644 .vale/styles/Google/Ellipses.yml create mode 100644 .vale/styles/Google/EmDash.yml create mode 100644 .vale/styles/Google/Exclamation.yml create mode 100644 .vale/styles/Google/FirstPerson.yml create mode 100644 .vale/styles/Google/Gender.yml create mode 100644 .vale/styles/Google/GenderBias.yml create mode 100644 .vale/styles/Google/HeadingPunctuation.yml create mode 100644 .vale/styles/Google/Headings.yml create mode 100644 .vale/styles/Google/Latin.yml create mode 100644 .vale/styles/Google/LyHyphens.yml create mode 100644 .vale/styles/Google/OptionalPlurals.yml create mode 100644 .vale/styles/Google/Ordinal.yml create mode 100644 .vale/styles/Google/OxfordComma.yml create mode 100644 .vale/styles/Google/Parens.yml create mode 100644 .vale/styles/Google/Passive.yml create mode 100644 .vale/styles/Google/Periods.yml create mode 100644 .vale/styles/Google/Quotes.yml create mode 100644 .vale/styles/Google/Ranges.yml create mode 100644 .vale/styles/Google/Semicolons.yml create mode 100644 .vale/styles/Google/Slang.yml create mode 100644 .vale/styles/Google/Spacing.yml create mode 100644 .vale/styles/Google/Spelling.yml create mode 100644 .vale/styles/Google/Units.yml create mode 100644 .vale/styles/Google/We.yml create mode 100644 .vale/styles/Google/Will.yml create mode 100644 .vale/styles/Google/WordList.yml create mode 100644 .vale/styles/Google/meta.json create mode 100644 .vale/styles/Google/vocab.txt create mode 100644 .vale/styles/write-good/Cliches.yml create mode 100644 .vale/styles/write-good/E-Prime.yml create mode 100644 .vale/styles/write-good/Illusions.yml create mode 100644 .vale/styles/write-good/Passive.yml create mode 100644 .vale/styles/write-good/README.md create mode 100644 .vale/styles/write-good/So.yml create mode 100644 .vale/styles/write-good/ThereIs.yml create mode 100644 .vale/styles/write-good/TooWordy.yml create mode 100644 .vale/styles/write-good/Weasel.yml create mode 100644 .vale/styles/write-good/meta.json create mode 100644 .woodpecker/Dockerfile create mode 100644 .woodpecker/Dockerfile.cross create mode 100644 .woodpecker/README.md create mode 100644 .woodpecker/ci-advanced.yml create mode 100644 .woodpecker/ci.yml create mode 100644 .yamllint-ci.yml create mode 100644 CHANGELOG.md diff --git a/.cargo/audit.toml b/.cargo/audit.toml new file mode 100644 index 0000000..b965267 --- /dev/null +++ b/.cargo/audit.toml @@ -0,0 +1,37 @@ +# Generated by dev-system/ci +# cargo-audit configuration for security vulnerability scanning + +# Database configuration +[advisories] +# The database path +db-path = "~/.cargo/advisory-db" + +# Advisory database URLs +db-urls = ["https://github.com/rustsec/advisory-db"] + +# How to handle different kinds of advisories +# "allow" - Pass the check despite the warning +# "warn" - Pass the check but warn about the issue +# "deny" - Fail the check +deny = ["unmaintained", "unsound", "yanked"] + +# Specific vulnerability IDs to ignore (in case of false positives) +# You can use: https://rustsec.org/ +ignore = [ + # Example: { id = "RUSTSEC-2023-XXXX", reason = "Not applicable to our use case" } +] + +# How to handle vulnerabilities based on severity +[output] +# Deny on high severity vulnerabilities +deny = ["high", "critical"] +# Warn on medium severity vulnerabilities +warn = ["medium", "low"] +# Advisory format: "terminal", "json" +format = "terminal" + +# Target configuration +[target] +# Check only specific targets +# Uncomment to restrict to specific target triples +# triple = "x86_64-unknown-linux-gnu" diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..cb95ce4 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,72 @@ +# Generated by dev-system/ci +# Cargo configuration for build and compilation settings + +[build] +# Number of parallel jobs for compilation +jobs = 4 + +# Code generation backend +# codegen-backend = "llvm" + +[profile.dev] +# Development profile - fast compilation, debug info +opt-level = 0 +debug = true +debug-assertions = true +overflow-checks = true +lto = false +panic = "unwind" +incremental = true + +[profile.release] +# Release profile - slow compilation, optimized binary +opt-level = 3 +debug = false +debug-assertions = false +overflow-checks = false +lto = "thin" +codegen-units = 1 +panic = "abort" +incremental = false +strip = false + +[profile.test] +# Test profile - inherits from dev but can be optimized +opt-level = 1 +debug = true +debug-assertions = true +overflow-checks = true +lto = false +incremental = true + +[profile.bench] +# Benchmark profile - same as release +opt-level = 3 +debug = false +debug-assertions = false +overflow-checks = false +lto = "thin" +codegen-units = 1 +incremental = false + +[term] +# Terminal colors +color = "auto" +verbose = false +progress.when = "auto" +progress.width = 80 + +[net] +# Network settings +git-fetch-with-cli = true +offline = false + +# Strict version requirements for dependencies +# force-non-semver-pre = true + +[alias] +# Custom cargo commands +build-all = "build --all-targets" +check-all = "check --all-targets --all-features" +test-all = "test --all-features --workspace" +doc-all = "doc --all-features --no-deps --open" diff --git a/.github/workflows/nickel-typecheck.yml b/.github/workflows/nickel-typecheck.yml new file mode 100644 index 0000000..325a550 --- /dev/null +++ b/.github/workflows/nickel-typecheck.yml @@ -0,0 +1,116 @@ +# GitHub Actions Nickel Type Checking Workflow +# Generated by dev-system/ci +# Validates all Nickel schemas with nickel typecheck + +name: Nickel Type Check + +on: + push: + branches: [main, develop] + paths: ['**.ncl'] + pull_request: + branches: [main] + paths: ['**.ncl'] + +jobs: + typecheck: + name: Nickel Type Checking + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Nickel + run: | + #!/usr/bin/env bash + set -e + + echo "πŸ“¦ Installing Nickel..." + + if command -v nickel &> /dev/null; then + echo "βœ“ Nickel already installed" + nickel --version + else + echo "Installing via homebrew..." + brew install nickel || { + echo "Homebrew installation failed, trying from source..." + curl --proto '=https' --tlsv1.2 -sSf https://install.nickel-lang.org | bash || exit 1 + } + fi + + nickel --version + + - name: Setup environment + run: | + #!/usr/bin/env bash + # Set NICKEL_IMPORT_PATH for schema imports + export NICKEL_IMPORT_PATH="/Users/Akasha/Tools/dev-system/ci/schemas:/Users/Akasha/Tools/dev-system/ci/validators:/Users/Akasha/Tools/dev-system/ci/defaults" + echo "NICKEL_IMPORT_PATH=$NICKEL_IMPORT_PATH" >> $GITHUB_ENV + + - name: Type check schemas + run: | + #!/usr/bin/env bash + set -e + + echo "πŸ” Type checking Nickel schemas..." + + # Find all .ncl files + SCHEMAS=$(find . -name "*.ncl" -type f \ + ! -path "./target/*" \ + ! -path "./.git/*" \ + ! -path "./node_modules/*" \ + | sort) + + if [ -z "$SCHEMAS" ]; then + echo "⚠️ No Nickel schemas found" + exit 0 + fi + + FAILED=0 + PASSED=0 + + # Set import path + export NICKEL_IMPORT_PATH="/Users/Akasha/Tools/dev-system/ci/schemas:/Users/Akasha/Tools/dev-system/ci/validators:/Users/Akasha/Tools/dev-system/ci/defaults:." + + for schema in $SCHEMAS; do + echo "Checking: $schema" + if nickel typecheck "$schema" > /dev/null 2>&1; then + echo " βœ“ Valid" + ((PASSED++)) + else + echo " ❌ Type error" + nickel typecheck "$schema" || true + ((FAILED++)) + fi + done + + echo "" + echo "Summary: $PASSED passed, $FAILED failed" + + if [ $FAILED -gt 0 ]; then + exit 1 + fi + + - name: Export and validate + run: | + #!/usr/bin/env bash + set -e + + echo "πŸ“Š Exporting Nickel configurations..." + + export NICKEL_IMPORT_PATH="/Users/Akasha/Tools/dev-system/ci/schemas:/Users/Akasha/Tools/dev-system/ci/validators:/Users/Akasha/Tools/dev-system/ci/defaults:." + + # Export main configs if they exist + if [ -f ".typedialog/ci/schemas/ci-local.ncl" ]; then + echo "Exporting CI config..." + nickel export .typedialog/ci/schemas/ci-local.ncl > /tmp/ci-export.json + if [ $? -eq 0 ]; then + echo " βœ“ Successfully exported" + else + echo " ❌ Export failed" + exit 1 + fi + fi + + echo "βœ“ All exports successful" diff --git a/.github/workflows/nushell-lint.yml b/.github/workflows/nushell-lint.yml new file mode 100644 index 0000000..96267b8 --- /dev/null +++ b/.github/workflows/nushell-lint.yml @@ -0,0 +1,28 @@ +jobs: + validate: + name: Nushell IDE Check + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Install Nushell + uses: hustcer/setup-nu@v3 + with: + version: latest + - name: Validate scripts + run: find . -name '*.nu' -type f -exec nu --ide-check 100 {} \; 2>/dev/null | grep -E '^(Error|error)' && exit 1 || true + - name: Check formatting + run: echo 'NuShell validation passed' +name: Nushell Validation +on: + pull_request: + branches: + - main + paths: + - '**.nu' + push: + branches: + - main + - develop + paths: + - '**.nu' diff --git a/.github/workflows/rust-ci.yml b/.github/workflows/rust-ci.yml new file mode 100644 index 0000000..73c2af1 --- /dev/null +++ b/.github/workflows/rust-ci.yml @@ -0,0 +1,47 @@ +jobs: + audit: + name: Security Audit + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + - name: Audit + run: cargo audit --deny warnings + - name: Deny Check + run: cargo deny check licenses advisories + check: + name: Check + Test + Lint + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Install Rust + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.rust-version }} + - name: Cache + uses: Swatinem/rust-cache@v2 + - name: Check + run: cargo check --all-targets + - name: Format Check + run: cargo fmt --all -- --check + - name: Clippy + run: cargo clippy --all-targets -- -D warnings + - name: Tests + run: cargo test --workspace + strategy: + matrix: + rust-version: + - stable + - nightly +name: Rust CI +on: + pull_request: + branches: + - main + push: + branches: + - main + - develop diff --git a/.gitignore b/.gitignore index 28ee48e..3c4f2d2 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,11 @@ # Purpose: Track core system & platform, exclude extensions & runtime data # ============================================================================ +# Not include KCL files +kcl +*.k +old_config + # === SEPARATE REPOSITORIES === # These are tracked in their own repos or pulled from external sources extensions/ @@ -12,7 +17,7 @@ core/plugins/nushell-plugins/ # User-specific data, should never be committed # NOTE: provisioning/workspace/ contains system templates and SHOULD be tracked # User workspace data is at project root, not in provisioning/ repo -wrks/ +.wrks/ ROOT/ OLD/ @@ -57,7 +62,6 @@ Cargo.lock # Uncomment to track if this is a binary package # Secret files secrets/ private/ -security/ *.encrypted *.enc @@ -118,7 +122,7 @@ platform/*/config.local.* .coder/ .claude/ .migration/ -.shellcheckrc +#.shellcheckrc .DS_Store ._* Thumbs.db @@ -138,7 +142,7 @@ platform/*/.next/ platform/*/.nuxt/ # === DOCUMENTATION BUILD OUTPUTS === -_book/ +book/ book-output/ site/ diff --git a/.markdownlint-cli2.jsonc b/.markdownlint-cli2.jsonc new file mode 100644 index 0000000..b1d73e6 --- /dev/null +++ b/.markdownlint-cli2.jsonc @@ -0,0 +1,96 @@ +// 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 + + // 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) + "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 + }, + + // 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/**" + ] +} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..c15a01c --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,124 @@ +# Pre-commit Framework Configuration +# Generated by dev-system/ci +# Configures git pre-commit hooks for Rust projects + +repos: + # ============================================================================ + # Rust Hooks + # ============================================================================ + - repo: local + hooks: + - id: rust-fmt + name: Rust formatting (cargo +nightly fmt) + entry: bash -c 'cargo +nightly fmt --all -- --check' + language: system + types: [rust] + pass_filenames: false + stages: [pre-commit] + + - id: rust-clippy + name: Rust linting (cargo clippy) + entry: bash -c 'cargo clippy --all-targets -- -D warnings' + language: system + types: [rust] + pass_filenames: false + stages: [pre-commit] + + - id: rust-test + name: Rust tests + entry: bash -c 'cargo test --workspace' + language: system + types: [rust] + pass_filenames: false + stages: [pre-push] + + - id: cargo-deny + name: Cargo deny (licenses & advisories) + entry: bash -c 'cargo deny check licenses advisories' + language: system + pass_filenames: false + stages: [pre-push] + + # ============================================================================ + # Nushell Hooks (optional - enable if using Nushell) + # ============================================================================ + # - repo: local + # hooks: + # - id: nushell-check + # name: Nushell validation (nu --ide-check) + # entry: bash -c 'for f in $(git diff --cached --name-only --diff-filter=ACM | grep "\.nu$"); do echo "Checking: $f"; nu --ide-check 100 "$f" || exit 1; done' + # language: system + # types: [file] + # files: \.nu$ + # pass_filenames: false + # stages: [commit] + + # ============================================================================ + # Nickel Hooks (optional - enable if using Nickel) + # ============================================================================ + # - repo: local + # hooks: + # - id: nickel-typecheck + # name: Nickel type checking + # entry: bash -c 'export NICKEL_IMPORT_PATH="/Users/Akasha/Tools/dev-system/ci/schemas:/Users/Akasha/Tools/dev-system/ci/validators:/Users/Akasha/Tools/dev-system/ci/defaults:."; for f in $(git diff --cached --name-only --diff-filter=ACM | grep "\.ncl$"); do echo "Checking: $f"; nickel typecheck "$f" || exit 1; done' + # language: system + # types: [file] + # files: \.ncl$ + # pass_filenames: false + # stages: [commit] + + # ============================================================================ + # Bash Hooks (optional - enable if using Bash) + # ============================================================================ + # - repo: local + # hooks: + # - id: shellcheck + # name: Shellcheck (bash linting) + # entry: shellcheck + # language: system + # types: [shell] + # stages: [commit] + # + # - id: shfmt + # name: Shell script formatting + # entry: bash -c 'shfmt -i 2 -d' + # language: system + # types: [shell] + # stages: [commit] + + # ============================================================================ + # Markdown Hooks (optional - enable if using Markdown) + # ============================================================================ + # - repo: local + # hooks: + # - id: markdownlint + # name: Markdown linting (markdownlint-cli2) + # entry: markdownlint-cli2 + # language: system + # types: [markdown] + # stages: [commit] + + # ============================================================================ + # General Pre-commit Hooks + # ============================================================================ + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.5.0 + hooks: + - id: check-added-large-files + args: ['--maxkb=1000'] + + - id: check-case-conflict + + - id: check-merge-conflict + + - id: check-toml + + - id: check-yaml + exclude: ^\.woodpecker/ + + - id: end-of-file-fixer + + - id: trailing-whitespace + exclude: \.md$ + + - id: mixed-line-ending diff --git a/.rustfmt.toml b/.rustfmt.toml new file mode 100644 index 0000000..8bd3887 --- /dev/null +++ b/.rustfmt.toml @@ -0,0 +1,53 @@ +# Generated by dev-system/ci +# Rustfmt configuration for consistent Rust code formatting +# Configured for cargo +nightly fmt with advanced features enabled + +# Basic formatting options +edition = "2021" +max_width = 100 +hard_tabs = false +tab_spaces = 4 +newline_style = "Unix" + +# Code structure +use_small_heuristics = "Default" + +# Imports +reorder_imports = true +reorder_modules = true +remove_nested_parens = true +group_imports = "StdExternalCrate" + +# Match expressions +match_block_trailing_comma = false + +# Chains +chain_width = 60 + +# Comment formatting (nightly) +comment_width = 80 +wrap_comments = true +normalize_comments = true +normalize_doc_attributes = true + +# Spaces and indentation (nightly) +fn_single_line = false +fn_params_layout = "Tall" +where_single_line = false + +# Formatting (nightly) +format_strings = true +format_code_in_doc_comments = false + +# Spaces (nightly) +space_before_colon = false +space_after_colon = true +spaces_around_ranges = false + +# Line breaks (nightly) +match_arm_blocks = true +blank_lines_lower_bound = 0 +blank_lines_upper_bound = 1 + +# Enable nightly features +unstable_features = true diff --git a/.shellcheckrc b/.shellcheckrc new file mode 100644 index 0000000..1d3c940 --- /dev/null +++ b/.shellcheckrc @@ -0,0 +1,51 @@ +# ShellCheck Configuration for Infrastructure Provisioning Project +# Focuses on functional issues, disables non-critical style warnings +# This configuration prioritizes bug detection over style enforcement + +# Enable all optional checks initially +enable=all + +# Disable non-functional and unfixable warnings +# Style issues that don't affect functionality: +# Info-level warnings that are numerous and hard to fix automatically: +# Monorepo source following issues that may not be resolvable: +disable=SC1020,SC1072,SC1073,SC1090,SC1091,SC2004,SC2016,SC2024,SC2034,SC2035,SC2038,SC2046,SC2064,SC2076,SC2086,SC2129,SC2153,SC2154,SC2155,SC2196,SC2231,SC2238,SC2248,SC2249,SC2250,SC2292,SC2310,SC2312,SC2315,SC2316,SC2317,SC2318,SC2319,SC2329 + +# SC1090/SC1091 - Can't follow source files (common in monorepos with dynamic includes) +# SC2024 - Invalid operators (14 instances, requires investigation) +# SC2046 - Quote to avoid word splitting (9 instances, requires refactoring) +# SC2086 - Double quote to prevent globbing (info-level, 289 instances, risky to auto-fix) +# SC2129 - Non-numeric array index (4 instances, style issue) +# SC2155 - Declare and assign separately (51 instances, requires manual refactoring) +# SC2231 - Quote expansions in globs (info-level, 2 instances, similar to SC2086) +# SC2238 - Redirects in loops (4 instances, edge case) +# SC2250 - Prefer putting braces around variable references (style only) +# SC2292 - Prefer to avoid negated test conditions (style preference) +# SC2310 - Functions in if conditions (info-level, 54 instances, requires refactoring) +# SC2312 - Comment appears to reference variable (false positives in comments) +# SC2248 - Prefer double quoting (style, handled by SC2086) +# SC2034 - Unused variables (development markers) +# SC2317 - Unreachable code (may be intentional) +# SC2249 - Prefer [[ ]] over [ ] (style preference in POSIX scripts) +# SC2315-2319 - Reserved names and other style issues + +# Keep enabled - these are critical functional issues that matter: +# SC2154 - Variable referenced but not assigned (115 instances) +# SC2155 - Declare and assign separately to avoid masking return values +# SC2046 - Quote to avoid word splitting +# SC2162 - read without -r may cause backslashes to be lost (FIXED - 9 instances) +# SC2164 - cd should have || exit (FIXED - 12 instances) +# SC2231 - Quote expansions to avoid globbing +# SC2024 - Operator used without proper escaping + +# Source path for sourced files +source-path=SCRIPTDIR + +# Severity levels: error, warning, info, style +severity=warning + +# Format: gcc, json, json1, quiet +format=gcc + +# Shell dialect (bash, sh, ksh, etc) +shell=bash diff --git a/.taplo.toml b/.taplo.toml new file mode 100644 index 0000000..5d20bf8 --- /dev/null +++ b/.taplo.toml @@ -0,0 +1,49 @@ +# Taplo configuration for TOML formatting and linting +# https://taplo.tamasfe.dev/configuration/ + +[formatting] +# Indent tables with 2 spaces +indent_string = " " +indent_tables = true + +# Reorder keys alphabetically within tables +reorder_keys = true + +# Reorder arrays to be more readable +reorder_arrays = false + +# Align entries vertically in inline tables +align_entries = false + +# Allow compact inline tables +allowed_blank_lines = 1 + +# Trailing newline +trailing_newline = true + +# Column width for wrapping +column_width = 100 + +# Compact arrays +compact_arrays = true + +# Compact inline tables +compact_inline_tables = false + +# === INCLUDE/EXCLUDE PATTERNS === + +include = ["Cargo.toml", "*/Cargo.toml", "config/**/*.toml", "**/*.toml"] + +exclude = ["target/**", "node_modules/**", ".git/**"] + +# === SCHEMA VALIDATION === + +# Cargo.toml schema validation +[[rule]] +include = ["**/Cargo.toml"] +# Taplo includes built-in Cargo.toml schema + +# TypeDialog form definition TOML files +[[rule]] +include = ["**/.typedialog/**/*.toml", "config/**/forms/*.toml", "tests/fixtures/**/*.toml"] +keys = ["name", "description", "fields", "items", "elements"] diff --git a/.typedialog/ci/2026_01_03_01_form.toml b/.typedialog/ci/2026_01_03_01_form.toml new file mode 100644 index 0000000..9353add --- /dev/null +++ b/.typedialog/ci/2026_01_03_01_form.toml @@ -0,0 +1,259 @@ +description = "Interactive configuration for continuous integration and code quality tools" +display_mode = "complete" +locales_path = "" +name = "CI Configuration Form" + +[[elements]] +border_bottom = true +border_top = true +name = "project_header" +title = "πŸ“¦ Project Information" +type = "section_header" + +[[elements]] +help = "Name of the project" +name = "project_name" +nickel_path = [ + "ci", + "project", + "name", +] +placeholder = "my-project" +prompt = "Project name" +required = true +type = "text" + +[[elements]] +help = "Optional description" +name = "project_description" +nickel_path = [ + "ci", + "project", + "description", +] +placeholder = "Brief description of what this project does" +prompt = "Project description" +required = false +type = "text" + +[[elements]] +default = "" +help = "Project website or documentation site URL" +name = "project_site_url" +nickel_path = [ + "ci", + "project", + "site_url", +] +placeholder = "https://example.com" +prompt = "Project Site URL" +required = false +type = "text" + +[[elements]] +default = "" +help = "Project repository URL (GitHub, GitLab, etc.)" +name = "project_repo_url" +nickel_path = [ + "ci", + "project", + "repo_url", +] +placeholder = "https://github.com/user/repo" +prompt = "Project Repo URL" +required = false +type = "text" + +[[elements]] +border_bottom = true +border_top = true +name = "languages_header" +title = "πŸ” Detected Languages" +type = "section_header" + +[[elements]] +default = "rust" +display_mode = "grid" +help = "Select all languages detected or used in the project" +min_selected = 1 +name = "detected_languages" +nickel_path = [ + "ci", + "project", + "detected_languages", +] +prompt = "Which languages are used in this project?" +required = true +searchable = true +type = "multiselect" + +[[elements.options]] +value = "rust" +label = "πŸ¦€ Rust" + +[[elements.options]] +value = "nushell" +label = "🐚 NuShell" + +[[elements.options]] +value = "nickel" +label = "βš™οΈ Nickel" + +[[elements.options]] +value = "bash" +label = "πŸ”§ Bash/Shell" + +[[elements.options]] +value = "markdown" +label = "πŸ“ Markdown/Documentation" + +[[elements.options]] +value = "python" +label = "🐍 Python" + +[[elements.options]] +value = "javascript" +label = "πŸ“œ JavaScript/TypeScript" + +[[elements]] +help = "Main language used for defaults (e.g., in GitHub Actions workflows)" +name = "primary_language" +nickel_path = [ + "ci", + "project", + "primary_language", +] +options_from = "detected_languages" +prompt = "Primary language" +required = true +type = "select" +default = "rust" + +[[elements.options]] +value = "rust" +label = "πŸ¦€ Rust" + +[[elements.options]] +value = "nushell" +label = "🐚 NuShell" + +[[elements.options]] +value = "nickel" +label = "βš™οΈ Nickel" + +[[elements.options]] +value = "bash" +label = "πŸ”§ Bash" + +[[elements.options]] +value = "markdown" +label = "πŸ“ Markdown" + +[[elements.options]] +value = "python" +label = "🐍 Python" + +[[elements.options]] +value = "javascript" +label = "πŸ“œ JavaScript" + +[[elements]] +includes = ["fragments/rust-tools.toml"] +name = "rust_tools_group" +type = "group" +when = "rust in detected_languages" + +[[elements]] +includes = ["fragments/nushell-tools.toml"] +name = "nushell_tools_group" +type = "group" +when = "nushell in detected_languages" + +[[elements]] +includes = ["fragments/nickel-tools.toml"] +name = "nickel_tools_group" +type = "group" +when = "nickel in detected_languages" + +[[elements]] +includes = ["fragments/bash-tools.toml"] +name = "bash_tools_group" +type = "group" +when = "bash in detected_languages" + +[[elements]] +includes = ["fragments/markdown-tools.toml"] +name = "markdown_tools_group" +type = "group" +when = "markdown in detected_languages" + +[[elements]] +includes = ["fragments/python-tools.toml"] +name = "python_tools_group" +type = "group" +when = "python in detected_languages" + +[[elements]] +includes = ["fragments/javascript-tools.toml"] +name = "javascript_tools_group" +type = "group" +when = "javascript in detected_languages" + +[[elements]] +includes = ["fragments/general-tools.toml"] +name = "general_tools_group" +type = "group" + +[[elements]] +border_bottom = true +border_top = true +name = "ci_cd_header" +title = "πŸ”„ CI/CD Configuration" +type = "section_header" + +[[elements]] +default = "true" +help = "Set up continuous integration and deployment pipelines" +name = "enable_ci_cd" +nickel_path = [ + "ci", + "features", + "enable_ci_cd", +] +prompt = "Enable CI/CD integration?" +type = "confirm" + +[[elements]] +includes = ["fragments/ci-providers.toml"] +name = "ci_providers_group" +type = "group" +when = "enable_ci_cd == true" + +[[elements]] +includes = ["fragments/ci-settings.toml"] +name = "ci_settings_group" +type = "group" +when = "enable_ci_cd == true" + +[[elements]] +includes = ["fragments/build-deployment.toml"] +name = "build_deployment_group" +type = "group" +when = "enable_ci_cd == true" + +[[elements]] +includes = ["fragments/documentation.toml"] +name = "documentation_group" +type = "group" + +[[elements]] +border_bottom = true +border_top = true +name = "confirmation_header" +title = "βœ… Ready to Install" +type = "section_header" + +[[elements]] +content = "Review your configuration above. After confirming, the CI system will be installed with your chosen settings." +name = "confirmation_footer" +type = "footer" diff --git a/.typedialog/ci/README.md b/.typedialog/ci/README.md new file mode 100644 index 0000000..e4a2c1d --- /dev/null +++ b/.typedialog/ci/README.md @@ -0,0 +1,328 @@ +# CI System - Configuration Guide + +**Installed**: 2026-01-01 +**Detected Languages**: rust, nushell, nickel, bash, markdown, python, javascript + +--- + +## Quick Start + +### Option 1: Using configure.sh (Recommended) + +A convenience script is installed in `.typedialog/ci/`: + +```bash +# Use web backend (default) - Opens in browser +.typedialog/ci/configure.sh + +# Use TUI backend - Terminal interface +.typedialog/ci/configure.sh tui + +# Use CLI backend - Command-line prompts +.typedialog/ci/configure.sh cli +``` + +**This script automatically:** + +- Sources `.typedialog/ci/envrc` for environment setup +- Loads defaults from `config.ncl` (Nickel format) +- Uses cascading search for fragments (local β†’ Tools) +- Creates backup before overwriting existing config +- Saves output in Nickel format using nickel-roundtrip with documented template +- Generates `config.ncl` compatible with `nickel doc` command + +### Option 2: Direct TypeDialog Commands + +Use TypeDialog nickel-roundtrip directly with manual paths: + +#### Web Backend (Recommended - Easy Viewing) + +```bash +cd .typedialog/ci # Change to CI directory +source envrc # Load environment +typedialog-web nickel-roundtrip config.ncl form.toml \ + --output config.ncl \ + --ncl-template $TOOLS_PATH/dev-system/ci/templates/config.ncl.j2 +``` + +#### TUI Backend + +```bash +cd .typedialog/ci +source envrc +typedialog-tui nickel-roundtrip config.ncl form.toml \ + --output config.ncl \ + --ncl-template $TOOLS_PATH/dev-system/ci/templates/config.ncl.j2 +``` + +#### CLI Backend + +```bash +cd .typedialog/ci +source envrc +typedialog nickel-roundtrip config.ncl form.toml \ + --output config.ncl \ + --ncl-template $TOOLS_PATH/dev-system/ci/templates/config.ncl.j2 +``` + +**Note:** The `--ncl-template` flag uses a Tera template that adds: + +- Descriptive comments for each section +- Documentation compatible with `nickel doc config.ncl` +- Consistent formatting and structure + +**All backends will:** + +- Show only options relevant to your detected languages +- Guide you through all configuration choices +- Validate your inputs +- Generate config.ncl in Nickel format + +### Option 3: Manual Configuration + +Edit `config.ncl` directly: + +```bash +vim .typedialog/ci/config.ncl +``` + +--- + +## Configuration Format: Nickel + +**This project uses Nickel format by default** for all configuration files. + +### Why Nickel? + +- βœ… **Typed configuration** - Static type checking with `nickel typecheck` +- βœ… **Documentation** - Generate docs with `nickel doc config.ncl` +- βœ… **Validation** - Built-in schema validation +- βœ… **Comments** - Rich inline documentation support +- βœ… **Modular** - Import/export system for reusable configs + +### Nickel Template + +The output structure is controlled by a **Tera template** at: + +- **Tools default**: `$TOOLS_PATH/dev-system/ci/templates/config.ncl.j2` +- **Local override**: `.typedialog/ci/config.ncl.j2` (optional) + +**To customize the template:** + +```bash +# Copy the default template +cp $TOOLS_PATH/dev-system/ci/templates/config.ncl.j2 \ + .typedialog/ci/config.ncl.j2 + +# Edit to add custom comments, documentation, or structure +vim .typedialog/ci/config.ncl.j2 + +# Your template will now be used automatically +``` + +**Template features:** + +- Customizable comments per section +- Control field ordering +- Add project-specific documentation +- Configure output for `nickel doc` command + +### TypeDialog Environment Variables + +You can customize TypeDialog behavior with environment variables: + +```bash +# Web server configuration +export TYPEDIALOG_PORT=9000 # Port for web backend (default: 9000) +export TYPEDIALOG_HOST=localhost # Host binding (default: localhost) + +# Localization +export TYPEDIALOG_LANG=en_US.UTF-8 # Form language (default: system locale) + +# Run with custom settings +TYPEDIALOG_PORT=8080 .typedialog/ci/configure.sh web +``` + +**Common use cases:** + +```bash +# Access from other machines in network +TYPEDIALOG_HOST=0.0.0.0 TYPEDIALOG_PORT=8080 .typedialog/ci/configure.sh web + +# Use different port if 9000 is busy +TYPEDIALOG_PORT=3000 .typedialog/ci/configure.sh web + +# Spanish interface +TYPEDIALOG_LANG=es_ES.UTF-8 .typedialog/ci/configure.sh web +``` + +## Configuration Structure + +Your config.ncl is organized in the `ci` namespace (Nickel format): + +```nickel +{ + ci = { + project = { + name = "rust", + detected_languages = ["rust, nushell, nickel, bash, markdown, python, javascript"], + primary_language = "rust", + }, + tools = { + # Tools are added based on detected languages + }, + features = { + # CI features (pre-commit, GitHub Actions, etc.) + }, + ci_providers = { + # CI provider configurations + }, + }, +} +``` + +## Available Fragments + +Tool configurations are modular. Check `.typedialog/ci/fragments/` for: + +- rust-tools.toml - Tools for rust +- nushell-tools.toml - Tools for nushell +- nickel-tools.toml - Tools for nickel +- bash-tools.toml - Tools for bash +- markdown-tools.toml - Tools for markdown +- python-tools.toml - Tools for python +- javascript-tools.toml - Tools for javascript +- general-tools.toml - Cross-language tools +- ci-providers.toml - GitHub Actions, Woodpecker, etc. + +## Cascading Override System + +This project uses a **local β†’ Tools cascading search** for all resources: + +### How It Works + +Resources are searched in priority order: + +1. **Local files** (`.typedialog/ci/`) - **FIRST** (highest priority) +2. **Tools files** (`$TOOLS_PATH/dev-system/ci/`) - **FALLBACK** (default) + +### Affected Resources + +| Resource | Local Path | Tools Path | +|----------|------------|------------| +| Fragments | `.typedialog/ci/fragments/` | `$TOOLS_PATH/dev-system/ci/forms/fragments/` | +| Schemas | `.typedialog/ci/schemas/` | `$TOOLS_PATH/dev-system/ci/schemas/` | +| Validators | `.typedialog/ci/validators/` | `$TOOLS_PATH/dev-system/ci/validators/` | +| Defaults | `.typedialog/ci/defaults/` | `$TOOLS_PATH/dev-system/ci/defaults/` | +| Nickel Template | `.typedialog/ci/config.ncl.j2` | `$TOOLS_PATH/dev-system/ci/templates/config.ncl.j2` | + +### Environment Setup (.envrc) + +The `.typedialog/ci/.envrc` file configures search paths: + +```bash +# Source this file to load environment +source .typedialog/ci/.envrc + +# Or use direnv for automatic loading +echo 'source .typedialog/ci/.envrc' >> .envrc +``` + +**What's in .envrc:** + +```bash +export NICKEL_IMPORT_PATH="schemas:$TOOLS_PATH/dev-system/ci/schemas:validators:..." +export TYPEDIALOG_FRAGMENT_PATH=".:$TOOLS_PATH/dev-system/ci/forms" +export NCL_TEMPLATE="" +export TYPEDIALOG_PORT=9000 # Web server port +export TYPEDIALOG_HOST=localhost # Web server host +export TYPEDIALOG_LANG="${LANG}" # Form localization +``` + +### Creating Overrides + +**By default:** All resources come from Tools (no duplication). + +**To customize:** Create file in local directory with same name: + +```bash +# Override a fragment +cp $TOOLS_PATH/dev-system/ci/fragments/rust-tools.toml \ + .typedialog/ci/fragments/rust-tools.toml + +# Edit your local version +vim .typedialog/ci/fragments/rust-tools.toml + +# Override Nickel template (customize comments, structure, nickel doc output) +cp $TOOLS_PATH/dev-system/ci/templates/config.ncl.j2 \ + .typedialog/ci/config.ncl.j2 + +# Edit to customize documentation and structure +vim .typedialog/ci/config.ncl.j2 + +# Now your version will be used instead of Tools version +``` + +**Benefits:** + +- βœ… Override only what you need +- βœ… Everything else stays synchronized with Tools +- βœ… No duplication by default +- βœ… Automatic updates when Tools is updated + +**See:** `$TOOLS_PATH/dev-system/ci/docs/cascade-override.md` for complete documentation. + +## Testing Your Configuration + +### Validate Configuration + +```bash +nu $env.TOOLS_PATH/dev-system/ci/scripts/validator.nu \ + --config .typedialog/ci/config.ncl \ + --project . \ + --namespace ci +``` + +### Regenerate CI Files + +```bash +nu $env.TOOLS_PATH/dev-system/ci/scripts/generate-configs.nu \ + --config .typedialog/ci/config.ncl \ + --templates $env.TOOLS_PATH/dev-system/ci/templates \ + --output . \ + --namespace ci +``` + +## Common Tasks + +### Add a New Tool + +Edit `config.ncl` and add under `ci.tools`: + +```nickel +{ + ci = { + tools = { + newtool = { + enabled = true, + install_method = "cargo", + version = "latest", + }, + }, + }, +} +``` + +### Disable a Feature + +```toml +[ci.features] +enable_pre_commit = false +``` + +## Need Help? + +For detailed documentation, see: + +- $env.TOOLS_PATH/dev-system/ci/docs/configuration-guide.md +- $env.TOOLS_PATH/dev-system/ci/docs/installation-guide.md diff --git a/.typedialog/ci/config.ncl b/.typedialog/ci/config.ncl new file mode 100644 index 0000000..ad5eb5e --- /dev/null +++ b/.typedialog/ci/config.ncl @@ -0,0 +1,175 @@ +# CI Configuration - Nickel Format +# Auto-generated by dev-system CI installer +# +# This file is managed by TypeDialog using nickel-roundtrip. +# Edit via: .typedialog/ci/configure.sh +# Or manually edit and validate with: nickel typecheck config.ncl +# +# Documentation: nickel doc config.ncl + +{ + # CI namespace - all configuration lives under 'ci' + ci = { + # Project Information + # Detected languages and primary language for this project + project = { + # Project name + name = "provisioning", + # Project description + description = "Provisioning", + # Project website or documentation site URL + site_url = "https://provisioning.systems", + # Project repository URL (GitHub, GitLab, etc.) + repo_url = "https://repo.jesusperez.pro/jesus/provisioning", + # Languages detected in codebase (auto-detected by installer) + detected_languages = [ + "rust", + "nushell", + "nickel", + "bash", + "markdown" + ], + # Primary language (determines default tooling) + primary_language = "nushell", + }, + + # CI Tools Configuration + # Each tool can be enabled/disabled and configured here + tools = { + # Taplo - TOML formatter and linter + taplo = { + enabled = true, + install_method = "cargo", + }, + # YAMLlint - YAML formatter and linter + yamllint = { + enabled = true, + install_method = "brew", + }, + # Clippy - Rust linting tool + clippy = { + enabled = true, + install_method = "cargo", + deny_warnings = true, + }, + # Cargo Audit - Security vulnerability scanner + audit = { + enabled = true, + install_method = "cargo", + }, + # Cargo Deny - Dependency checker + deny = { + enabled = true, + install_method = "cargo", + }, + # Cargo SBOM - Software Bill of Materials + sbom = { + enabled = true, + install_method = "cargo", + }, + # LLVM Coverage - Code coverage tool + llvm-cov = { + enabled = true, + install_method = "cargo", + }, + # Shellcheck - Bash/shell script linter + shellcheck = { + enabled = true, + install_method = "brew", + }, + # Shfmt - Shell script formatter + shfmt = { + enabled = true, + install_method = "brew", + }, + # Markdownlint - Markdown linter + markdownlint = { + enabled = true, + install_method = "npm", + }, + # Vale - Prose linter + vale = { + enabled = true, + install_method = "brew", + }, + # Nickel - Configuration language type checker + nickel = { + enabled = true, + install_method = "brew", + check_all = true, + }, + # NuShell - Shell script validator + nushell = { + enabled = true, + install_method = "builtin", + check_all = true, + }, + # Ruff - Fast Python linter + ruff = { + enabled = true, + install_method = "pip", + }, + # Black - Python code formatter + black = { + enabled = true, + install_method = "pip", + }, + # Pytest - Python testing framework + pytest = { + enabled = true, + install_method = "pip", + }, + # ESLint - JavaScript linter + eslint = { + enabled = true, + install_method = "npm", + }, + # Prettier - Code formatter + prettier = { + enabled = true, + install_method = "npm", + }, + # Jest - JavaScript testing framework + jest = { + enabled = true, + install_method = "npm", + }, + }, + + # CI Features + # High-level feature flags for CI behavior + features = { + enable_ci_cd = true, + enable_pre_commit = true, + generate_taplo_config = true, + generate_contributing = true, + generate_security = true, + generate_code_of_conduct = true, + generate_dockerfiles = true, + enable_cross_compilation = true, + }, + + # CI Provider Configurations + # Settings for GitHub Actions, Woodpecker, GitLab CI, etc. + ci_providers = { + # GitHub Actions + github_actions = { + enabled = true, + branches_push = "main,develop", + branches_pr = "main", + }, + # Woodpecker CI + woodpecker = { + enabled = true, + }, + }, + + # CI Settings + settings = { + parallel_jobs = 1, + job_timeout_minutes = 1, + require_status_checks = true, + run_on_draft_prs = true, + }, + }, +} diff --git a/.typedialog/ci/configure.sh b/.typedialog/ci/configure.sh new file mode 100755 index 0000000..28cf7c8 --- /dev/null +++ b/.typedialog/ci/configure.sh @@ -0,0 +1,116 @@ +#!/usr/bin/env bash +# CI Configuration Script +# Auto-generated by dev-system/ci installer +# +# Interactive configuration for CI tools using TypeDialog. +# Uses Nickel format for configuration files. + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +TYPEDIALOG_CI="${SCRIPT_DIR}" + +# Source envrc to load fragment paths and other environment variables +if [[ -f "${TYPEDIALOG_CI}/envrc" ]]; then + # shellcheck source=/dev/null + source "${TYPEDIALOG_CI}/envrc" +fi + +# Configuration files +FORM_FILE="${TYPEDIALOG_CI}/form.toml" +CONFIG_FILE="${TYPEDIALOG_CI}/config.ncl" + +# NCL_TEMPLATE is set by envrc (cascading: local β†’ Tools) +# If not set, use default from Tools +NCL_TEMPLATE="${NCL_TEMPLATE:-${TOOLS_PATH}/dev-system/ci/templates/config.ncl.j2}" + +# TypeDialog environment variables (can be overridden) +# Port for web backend (default: 9000) +export TYPEDIALOG_PORT="${TYPEDIALOG_PORT:-9000}" + +# Host for web backend (default: localhost) +export TYPEDIALOG_HOST="${TYPEDIALOG_HOST:-localhost}" + +# Locale for form localization (default: system locale) +export TYPEDIALOG_LANG="${TYPEDIALOG_LANG:-${LANG:-en_US.UTF-8}}" + +# Detect which TypeDialog backend to use (default: web) +BACKEND="${1:-web}" + +# Validate backend +case "$BACKEND" in + cli|tui|web) + ;; + *) + echo "Usage: $0 [cli|tui|web]" + echo "" + echo "Launches TypeDialog for interactive CI configuration." + echo "Backend options:" + echo " cli - Command-line interface (simple prompts)" + echo " tui - Terminal UI (interactive panels)" + echo " web - Web server (browser-based) [default]" + exit 1 + ;; +esac + +# Check if form exists +if [[ ! -f "$FORM_FILE" ]]; then + echo "Error: Form file not found: $FORM_FILE" + exit 1 +fi + +# Create backup if config exists +if [[ -f "$CONFIG_FILE" ]]; then + BACKUP="${CONFIG_FILE}.$(date +%Y%m%d_%H%M%S).bak" + cp "$CONFIG_FILE" "$BACKUP" + echo "ℹ️ Backed up existing config to: $(basename "$BACKUP")" +fi + +# Launch TypeDialog with Nickel roundtrip (preserves Nickel format) +echo "πŸ”§ Launching TypeDialog ($BACKEND backend)..." +echo "" + +# Show web server info if using web backend +if [[ "$BACKEND" == "web" ]]; then + echo "🌐 Web server will start on: http://${TYPEDIALOG_HOST}:${TYPEDIALOG_PORT}" + echo " (Override with: TYPEDIALOG_PORT=8080 TYPEDIALOG_HOST=0.0.0.0 $0)" + echo "" +fi + +# Build nickel-roundtrip command with optional template +NCL_TEMPLATE_ARG="" +if [[ -f "$NCL_TEMPLATE" ]]; then + NCL_TEMPLATE_ARG="--ncl-template $NCL_TEMPLATE" + echo "ℹ️ Using Nickel template: $NCL_TEMPLATE" +fi + +case "$BACKEND" in + cli) + typedialog nickel-roundtrip "$CONFIG_FILE" "$FORM_FILE" --output "$CONFIG_FILE" $NCL_TEMPLATE_ARG + ;; + tui) + typedialog-tui nickel-roundtrip "$CONFIG_FILE" "$FORM_FILE" --output "$CONFIG_FILE" $NCL_TEMPLATE_ARG + ;; + web) + typedialog-web nickel-roundtrip "$CONFIG_FILE" "$FORM_FILE" --output "$CONFIG_FILE" $NCL_TEMPLATE_ARG + ;; +esac + +EXIT_CODE=$? + +if [[ $EXIT_CODE -eq 0 ]]; then + echo "" + echo "βœ… Configuration saved to: $CONFIG_FILE" + echo "" + echo "Next steps:" + echo " - Review the configuration: cat $CONFIG_FILE" + echo " - Apply CI tools: (run your CI setup command)" + echo " - Re-run this script anytime to update: $0" +else + echo "" + echo "❌ Configuration cancelled or failed (exit code: $EXIT_CODE)" + if [[ -f "${CONFIG_FILE}.bak" ]]; then + echo " Previous config restored from backup" + fi + exit $EXIT_CODE +fi diff --git a/.typedialog/ci/envrc b/.typedialog/ci/envrc new file mode 100644 index 0000000..4c00a1b --- /dev/null +++ b/.typedialog/ci/envrc @@ -0,0 +1,27 @@ +# Auto-generated by dev-system/ci +# +# Cascading Path Strategy: +# 1. Local files in .typedialog/ci/ take precedence (overrides) +# 2. Central files in $TOOLS_PATH/dev-system/ci/ as fallback (defaults) +# +# To customize: Create file in .typedialog/ci/{schemas,validators,defaults,fragments}/ +# Your local version will be used instead of the Tools version. + +# Nickel import paths (cascading: local β†’ Tools) +export NICKEL_IMPORT_PATH="schemas:$TOOLS_PATH/dev-system/ci/schemas:validators:$TOOLS_PATH/dev-system/ci/validators:defaults:$TOOLS_PATH/dev-system/ci/defaults" + +# TypeDialog fragment search paths (cascading: local β†’ Tools) +export TYPEDIALOG_FRAGMENT_PATH=".typedialog/ci:$TOOLS_PATH/dev-system/ci/forms" + +# Nickel template for config.ncl generation (with cascading) +# Local template takes precedence if exists +if [[ -f ".typedialog/ci/config.ncl.j2" ]]; then + export NCL_TEMPLATE=".typedialog/ci/config.ncl.j2" +else + export NCL_TEMPLATE="$TOOLS_PATH/dev-system/ci/templates/config.ncl.j2" +fi + +# TypeDialog web backend configuration (override if needed) +export TYPEDIALOG_PORT=${TYPEDIALOG_PORT:-9000} +export TYPEDIALOG_HOST=${TYPEDIALOG_HOST:-localhost} +export TYPEDIALOG_LANG=${TYPEDIALOG_LANG:-${LANG:-en_US.UTF-8}} diff --git a/.typedialog/ci/form.toml b/.typedialog/ci/form.toml new file mode 100644 index 0000000..9353add --- /dev/null +++ b/.typedialog/ci/form.toml @@ -0,0 +1,259 @@ +description = "Interactive configuration for continuous integration and code quality tools" +display_mode = "complete" +locales_path = "" +name = "CI Configuration Form" + +[[elements]] +border_bottom = true +border_top = true +name = "project_header" +title = "πŸ“¦ Project Information" +type = "section_header" + +[[elements]] +help = "Name of the project" +name = "project_name" +nickel_path = [ + "ci", + "project", + "name", +] +placeholder = "my-project" +prompt = "Project name" +required = true +type = "text" + +[[elements]] +help = "Optional description" +name = "project_description" +nickel_path = [ + "ci", + "project", + "description", +] +placeholder = "Brief description of what this project does" +prompt = "Project description" +required = false +type = "text" + +[[elements]] +default = "" +help = "Project website or documentation site URL" +name = "project_site_url" +nickel_path = [ + "ci", + "project", + "site_url", +] +placeholder = "https://example.com" +prompt = "Project Site URL" +required = false +type = "text" + +[[elements]] +default = "" +help = "Project repository URL (GitHub, GitLab, etc.)" +name = "project_repo_url" +nickel_path = [ + "ci", + "project", + "repo_url", +] +placeholder = "https://github.com/user/repo" +prompt = "Project Repo URL" +required = false +type = "text" + +[[elements]] +border_bottom = true +border_top = true +name = "languages_header" +title = "πŸ” Detected Languages" +type = "section_header" + +[[elements]] +default = "rust" +display_mode = "grid" +help = "Select all languages detected or used in the project" +min_selected = 1 +name = "detected_languages" +nickel_path = [ + "ci", + "project", + "detected_languages", +] +prompt = "Which languages are used in this project?" +required = true +searchable = true +type = "multiselect" + +[[elements.options]] +value = "rust" +label = "πŸ¦€ Rust" + +[[elements.options]] +value = "nushell" +label = "🐚 NuShell" + +[[elements.options]] +value = "nickel" +label = "βš™οΈ Nickel" + +[[elements.options]] +value = "bash" +label = "πŸ”§ Bash/Shell" + +[[elements.options]] +value = "markdown" +label = "πŸ“ Markdown/Documentation" + +[[elements.options]] +value = "python" +label = "🐍 Python" + +[[elements.options]] +value = "javascript" +label = "πŸ“œ JavaScript/TypeScript" + +[[elements]] +help = "Main language used for defaults (e.g., in GitHub Actions workflows)" +name = "primary_language" +nickel_path = [ + "ci", + "project", + "primary_language", +] +options_from = "detected_languages" +prompt = "Primary language" +required = true +type = "select" +default = "rust" + +[[elements.options]] +value = "rust" +label = "πŸ¦€ Rust" + +[[elements.options]] +value = "nushell" +label = "🐚 NuShell" + +[[elements.options]] +value = "nickel" +label = "βš™οΈ Nickel" + +[[elements.options]] +value = "bash" +label = "πŸ”§ Bash" + +[[elements.options]] +value = "markdown" +label = "πŸ“ Markdown" + +[[elements.options]] +value = "python" +label = "🐍 Python" + +[[elements.options]] +value = "javascript" +label = "πŸ“œ JavaScript" + +[[elements]] +includes = ["fragments/rust-tools.toml"] +name = "rust_tools_group" +type = "group" +when = "rust in detected_languages" + +[[elements]] +includes = ["fragments/nushell-tools.toml"] +name = "nushell_tools_group" +type = "group" +when = "nushell in detected_languages" + +[[elements]] +includes = ["fragments/nickel-tools.toml"] +name = "nickel_tools_group" +type = "group" +when = "nickel in detected_languages" + +[[elements]] +includes = ["fragments/bash-tools.toml"] +name = "bash_tools_group" +type = "group" +when = "bash in detected_languages" + +[[elements]] +includes = ["fragments/markdown-tools.toml"] +name = "markdown_tools_group" +type = "group" +when = "markdown in detected_languages" + +[[elements]] +includes = ["fragments/python-tools.toml"] +name = "python_tools_group" +type = "group" +when = "python in detected_languages" + +[[elements]] +includes = ["fragments/javascript-tools.toml"] +name = "javascript_tools_group" +type = "group" +when = "javascript in detected_languages" + +[[elements]] +includes = ["fragments/general-tools.toml"] +name = "general_tools_group" +type = "group" + +[[elements]] +border_bottom = true +border_top = true +name = "ci_cd_header" +title = "πŸ”„ CI/CD Configuration" +type = "section_header" + +[[elements]] +default = "true" +help = "Set up continuous integration and deployment pipelines" +name = "enable_ci_cd" +nickel_path = [ + "ci", + "features", + "enable_ci_cd", +] +prompt = "Enable CI/CD integration?" +type = "confirm" + +[[elements]] +includes = ["fragments/ci-providers.toml"] +name = "ci_providers_group" +type = "group" +when = "enable_ci_cd == true" + +[[elements]] +includes = ["fragments/ci-settings.toml"] +name = "ci_settings_group" +type = "group" +when = "enable_ci_cd == true" + +[[elements]] +includes = ["fragments/build-deployment.toml"] +name = "build_deployment_group" +type = "group" +when = "enable_ci_cd == true" + +[[elements]] +includes = ["fragments/documentation.toml"] +name = "documentation_group" +type = "group" + +[[elements]] +border_bottom = true +border_top = true +name = "confirmation_header" +title = "βœ… Ready to Install" +type = "section_header" + +[[elements]] +content = "Review your configuration above. After confirming, the CI system will be installed with your chosen settings." +name = "confirmation_footer" +type = "footer" diff --git a/.typedialog/platform/forms/README.md b/.typedialog/platform/forms/README.md new file mode 100644 index 0000000..7325b95 --- /dev/null +++ b/.typedialog/platform/forms/README.md @@ -0,0 +1,390 @@ +# Forms + +TypeDialog form definitions for interactive configuration of platform services. + +## Purpose + +Forms provide: +- **Interactive configuration** - Web/TUI/CLI interfaces for user input +- **Constraint validation** - Dynamic min/max from constraints.toml +- **Nickel mapping** - Form fields map to Nickel structure via `nickel_path` +- **Jinja2 template integration** - Generate Nickel configs from form values +- **nickel-roundtrip workflow** - Load existing Nickel β†’ edit β†’ generate updated Nickel + +## File Organization + +``` +forms/ +β”œβ”€β”€ README.md # This file +β”œβ”€β”€ orchestrator-form.toml # Orchestrator configuration form +β”œβ”€β”€ control-center-form.toml # Control Center configuration form +β”œβ”€β”€ mcp-server-form.toml # MCP Server configuration form +β”œβ”€β”€ installer-form.toml # Installer configuration form +└── fragments/ # FLAT fragment directory (all fragments here) + β”œβ”€β”€ workspace-section.toml # Workspace configuration + β”œβ”€β”€ server-section.toml # HTTP server settings + β”œβ”€β”€ database-rocksdb-section.toml # RocksDB configuration + β”œβ”€β”€ database-surrealdb-section.toml # SurrealDB configuration + β”œβ”€β”€ database-postgres-section.toml # PostgreSQL configuration + β”œβ”€β”€ security-section.toml # Auth, RBAC, encryption + β”œβ”€β”€ monitoring-section.toml # Metrics, health checks + β”œβ”€β”€ logging-section.toml # Log configuration + β”œβ”€β”€ orchestrator-queue-section.toml # Orchestrator queue config + β”œβ”€β”€ orchestrator-workflow-section.toml + β”œβ”€β”€ control-center-jwt-section.toml + β”œβ”€β”€ control-center-rbac-section.toml + β”œβ”€β”€ mcp-capabilities-section.toml + β”œβ”€β”€ deployment-mode-section.toml # Mode selection + └── README.md # Fragment documentation +``` + +## Critical: Fragment Organization + +**Fragments are FLAT** - all stored in `forms/fragments/` at the same level, referenced by paths in form includes: + +```toml +# Main form (orchestrator-form.toml) +[[items]] +name = "workspace_group" +type = "group" +includes = ["fragments/workspace-section.toml"] # Path reference to flat fragment + +[[items]] +name = "queue_group" +type = "group" +includes = ["fragments/orchestrator-queue-section.toml"] # Same level, different name +``` + +**NOT nested directories** like `fragments/orchestrator/queue-section.toml` - all in `fragments/` + +## TypeDialog nickel-roundtrip Workflow + +CRITICAL: Forms integrate with Nickel config generation via: + +```bash +typedialog-web nickel-roundtrip "$CONFIG_FILE" "$FORM_FILE" --output "$CONFIG_FILE" --template "$NCL_TEMPLATE" +``` + +This workflow: +1. **Loads existing Nickel config** as default values in form +2. **Shows form** with validated constraints +3. **User edits** configuration values +4. **Generates updated Nickel** using Jinja2 template + +## Required Fields: nickel_path + +**CRITICAL**: Every form element MUST have `nickel_path` to map to Nickel structure: + +```toml +[[elements]] +name = "workspace_name" +type = "text" +prompt = "Workspace Name" +nickel_path = ["orchestrator", "workspace", "name"] # ← REQUIRED +``` + +The `nickel_path` array specifies the path in the Nickel config structure: +- `["orchestrator", "workspace", "name"]` β†’ `orchestrator.workspace.name` +- `["orchestrator", "queue", "max_concurrent_tasks"]` β†’ `orchestrator.queue.max_concurrent_tasks` + +## Constraint Interpolation + +Form fields reference constraints dynamically: + +```toml +[[elements]] +name = "max_concurrent_tasks" +type = "number" +prompt = "Maximum Concurrent Tasks" +min = "${constraint.orchestrator.queue.concurrent_tasks.min}" # Dynamic +max = "${constraint.orchestrator.queue.concurrent_tasks.max}" # Dynamic +help = "Range: ${constraint.orchestrator.queue.concurrent_tasks.min}-${constraint.orchestrator.queue.concurrent_tasks.max}" +nickel_path = ["orchestrator", "queue", "max_concurrent_tasks"] +``` + +TypeDialog resolves `${constraint.path}` from `constraints/constraints.toml`. + +## Main Form Structure + +All main forms follow this pattern: + +```toml +name = "service_configuration" +description = "Interactive configuration for {Service}" +display_mode = "complete" + +# Section 1: Deployment mode selection +[[items]] +name = "deployment_mode_group" +type = "group" +includes = ["fragments/deployment-mode-section.toml"] + +# Section 2: Workspace configuration +[[items]] +name = "workspace_group" +type = "group" +includes = ["fragments/workspace-section.toml"] + +# Section 3: Server configuration +[[items]] +name = "server_group" +type = "group" +includes = ["fragments/server-section.toml"] + +# Section N: Service-specific configuration +[[items]] +name = "service_group" +type = "group" +includes = ["fragments/{service}-specific-section.toml"] + +# Optional: Conditional sections +[[items]] +name = "monitoring_group" +type = "group" +when = "enable_monitoring == true" +includes = ["fragments/monitoring-section.toml"] +``` + +## Fragment Example: workspace-section.toml + +```toml +# Workspace configuration fragment +[[elements]] +border_top = true +border_bottom = true +name = "workspace_header" +title = "πŸ—‚οΈ Workspace Configuration" +type = "section_header" + +[[elements]] +name = "workspace_name" +type = "text" +prompt = "Workspace Name" +default = "default" +placeholder = "e.g., librecloud, production" +required = true +help = "Name of the workspace" +nickel_path = ["orchestrator", "workspace", "name"] + +[[elements]] +name = "workspace_path" +type = "text" +prompt = "Workspace Path" +default = "/var/lib/provisioning/orchestrator" +required = true +help = "Absolute path to workspace directory" +nickel_path = ["orchestrator", "workspace", "path"] + +[[elements]] +name = "workspace_enabled" +type = "confirm" +prompt = "Enable Workspace?" +default = true +nickel_path = ["orchestrator", "workspace", "enabled"] + +[[elements]] +name = "multi_workspace" +type = "confirm" +prompt = "Multi-Workspace Mode?" +default = false +help = "Allow serving multiple workspaces" +nickel_path = ["orchestrator", "workspace", "multi_workspace"] +``` + +## Fragment Example: orchestrator-queue-section.toml + +```toml +# Orchestrator queue configuration +[[elements]] +border_top = true +name = "queue_header" +title = "βš™οΈ Queue Configuration" +type = "section_header" + +[[elements]] +name = "max_concurrent_tasks" +type = "number" +prompt = "Maximum Concurrent Tasks" +default = 5 +min = "${constraint.orchestrator.queue.concurrent_tasks.min}" +max = "${constraint.orchestrator.queue.concurrent_tasks.max}" +required = true +help = "Max tasks running simultaneously. Range: ${constraint.orchestrator.queue.concurrent_tasks.min}-${constraint.orchestrator.queue.concurrent_tasks.max}" +nickel_path = ["orchestrator", "queue", "max_concurrent_tasks"] + +[[elements]] +name = "retry_attempts" +type = "number" +prompt = "Retry Attempts" +default = 3 +min = 0 +max = 10 +help = "Number of retry attempts for failed tasks" +nickel_path = ["orchestrator", "queue", "retry_attempts"] + +[[elements]] +name = "retry_delay" +type = "number" +prompt = "Retry Delay (ms)" +default = 5000 +min = 1000 +max = 60000 +help = "Delay between retries in milliseconds" +nickel_path = ["orchestrator", "queue", "retry_delay"] + +[[elements]] +name = "task_timeout" +type = "number" +prompt = "Task Timeout (ms)" +default = 3600000 +min = 60000 +max = 86400000 +help = "Default timeout for task execution (min 1 min, max 24 hrs)" +nickel_path = ["orchestrator", "queue", "task_timeout"] +``` + +## Jinja2 Template Integration + +Jinja2 templates (`templates/{service}-config.ncl.j2`) convert form values to Nickel: + +```nickel +# templates/orchestrator-config.ncl.j2 +{ + orchestrator = { + workspace = { + {%- if workspace_name %} + name = "{{ workspace_name }}", + {%- endif %} + {%- if workspace_path %} + path = "{{ workspace_path }}", + {%- endif %} + {%- if workspace_enabled is defined %} + enabled = {{ workspace_enabled | lower }}, + {%- endif %} + }, + queue = { + {%- if max_concurrent_tasks %} + max_concurrent_tasks = {{ max_concurrent_tasks }}, + {%- endif %} + {%- if retry_attempts %} + retry_attempts = {{ retry_attempts }}, + {%- endif %} + {%- if retry_delay %} + retry_delay = {{ retry_delay }}, + {%- endif %} + {%- if task_timeout %} + task_timeout = {{ task_timeout }}, + {%- endif %} + }, + }, +} +``` + +## Conditional Sections + +Forms can show/hide sections based on user selections: + +```toml +# Always shown +[[items]] +name = "deployment_mode_group" +type = "group" +includes = ["fragments/deployment-mode-section.toml"] + +# Only shown if enable_monitoring is true +[[items]] +name = "monitoring_group" +type = "group" +when = "enable_monitoring == true" +includes = ["fragments/monitoring-section.toml"] + +# Only shown if deployment_mode is "enterprise" +[[items]] +name = "enterprise_options" +type = "group" +when = "deployment_mode == 'enterprise'" +includes = ["fragments/enterprise-options-section.toml"] +``` + +## Element Types + +```toml +type = "text" # Single-line text input +type = "number" # Numeric input +type = "confirm" # Boolean checkbox +type = "select" # Dropdown (single choice) +type = "multiselect" # Checkboxes (multiple choices) +type = "password" # Hidden text input +type = "textarea" # Multi-line text +type = "section_header" # Visual section separator +type = "footer" # Confirmation text +type = "group" # Container for fragments +``` + +## Usage Workflow + +### 1. Run Configuration Wizard + +```bash +nu provisioning/.typedialog/provisioning/platform/scripts/configure.nu orchestrator solo +``` + +### 2. TypeDialog Loads Form + +- Shows `forms/orchestrator-form.toml` +- Includes fragments from `forms/fragments/*.toml` +- Applies constraint interpolation +- Loads existing config as defaults (if exists) + +### 3. User Edits + +- Fills form fields +- Validates against constraints +- Shows validation errors + +### 4. Generate Nickel + +- Uses `templates/orchestrator-config.ncl.j2` +- Converts form values to Nickel +- Saves to `values/orchestrator.solo.ncl` + +## Best Practices + +1. **Use fragments** - Don't duplicate form sections +2. **Always add nickel_path** - Required for Nickel mapping +3. **Use constraint interpolation** - Dynamic limits from constraints.toml +4. **Provide defaults** - Sensible defaults speed up configuration +5. **Use clear prompts** - Explain what each field does in `help` text +6. **Group related fields** - Use fragments to organize logically +7. **Test constraint interpolation** - Verify ${constraint.*} resolves +8. **Document fragments** - Use headers and help text + +## Testing Forms + +```bash +# Validate form TOML syntax (if supported by TypeDialog) +# typedialog validate forms/orchestrator-form.toml + +# Launch interactive form (web backend) +nu provisioning/.typedialog/provisioning/platform/scripts/configure.nu orchestrator solo --backend web + +# View generated Nickel +cat provisioning/.typedialog/provisioning/platform/values/orchestrator.solo.ncl +``` + +## Adding New Fields + +To add a new configuration field: + +1. **Add to schema** (schemas/{service}.ncl) +2. **Add to defaults** (defaults/{service}-defaults.ncl) +3. **Add to fragment** (forms/fragments/{appropriate}-section.toml) + - Include `nickel_path` mapping + - Add constraint if numeric +4. **Update Jinja2 template** (templates/{service}-config.ncl.j2) +5. **Test**: `nu scripts/configure.nu {service} {mode}` + +--- + +**Version**: 1.0.0 +**Last Updated**: 2025-01-05 diff --git a/.typedialog/platform/forms/ai-service-form.toml b/.typedialog/platform/forms/ai-service-form.toml new file mode 100644 index 0000000..c592a67 --- /dev/null +++ b/.typedialog/platform/forms/ai-service-form.toml @@ -0,0 +1,13 @@ +# AI Service Configuration Form +# Sections for AI Service deployment with RAG/MCP integration + +title = "AI Service Configuration" +description = "Configure AI Service with RAG and MCP integration" + +sections = [ + { name = "server", label = "Server Settings", description = "HTTP server and worker configuration" }, + { name = "rag_integration", label = "RAG Integration", description = "Retrieval-Augmented Generation service integration" }, + { name = "mcp_integration", label = "MCP Integration", description = "Model Context Protocol service integration" }, + { name = "dag", label = "DAG Execution", description = "Directed Acyclic Graph task execution settings" }, + { name = "monitoring", label = "Monitoring", description = "Health checks and observability" } +] diff --git a/.typedialog/platform/forms/control-center-form.toml b/.typedialog/platform/forms/control-center-form.toml new file mode 100644 index 0000000..76f899d --- /dev/null +++ b/.typedialog/platform/forms/control-center-form.toml @@ -0,0 +1,118 @@ +name = "control_center_configuration" +description = "Interactive configuration for Control Center service (policy and RBAC management)" +display_mode = "complete" +fallback_locale = "en-US" + +# ============================================================================ +# CONTROL CENTER SERVICE FORM - COMPOSED FROM FRAGMENTS +# ============================================================================ +# This form uses fragment composition pattern for modular configuration +# All fragments are located in ./fragments/ subdirectory +# ============================================================================ + +# DEPLOYMENT MODE SELECTION +# Determines service resources and feature set (solo/multiuser/cicd/enterprise) +[[items]] +name = "deployment_mode_group" +type = "group" +title = "Deployment Configuration" +description = "Select deployment mode and database backend" +includes = ["fragments/deployment/mode-selection.toml", "fragments/deployment/database-backend-selection.toml"] + +# WORKSPACE CONFIGURATION +# Workspace name, path, and context +[[items]] +name = "workspace_group" +type = "group" +title = "Workspace Settings" +description = "Configure workspace context for this Control Center instance" +includes = ["fragments/workspace-section.toml"] + +# SERVER CONFIGURATION +# HTTP server settings (host, port, workers, connections) +[[items]] +name = "server_group" +type = "group" +title = "Server Settings" +description = "Configure HTTP server for Control Center" +includes = ["fragments/server-section.toml"] + +# DATABASE BACKEND CONFIGURATION +# Conditional sections based on selected backend +[[items]] +name = "database_rocksdb_group" +type = "group" +title = "RocksDB Configuration" +description = "Configure RocksDB backend for policy storage" +condition = "database_backend_selection == 'rocksdb'" +includes = ["fragments/database-rocksdb-section.toml"] + +[[items]] +name = "database_surrealdb_group" +type = "group" +title = "SurrealDB Configuration" +description = "Configure SurrealDB backend for policy storage" +condition = "database_backend_selection == 'surrealdb_embedded' || database_backend_selection == 'surrealdb_server'" +includes = ["fragments/database-surrealdb-section.toml"] + +[[items]] +name = "database_postgres_group" +type = "group" +title = "PostgreSQL Configuration" +description = "Configure PostgreSQL backend for policy storage" +condition = "database_backend_selection == 'postgresql'" +includes = ["fragments/database-postgres-section.toml"] + +# CONTROL CENTER-SPECIFIC: SECURITY CONFIGURATION +# JWT, RBAC, MFA, rate limiting, TLS, sessions +[[items]] +name = "security_group" +type = "group" +title = "Security Configuration" +description = "Configure authentication, authorization, and security settings" +includes = ["fragments/control-center/security-section.toml"] + +# CONTROL CENTER-SPECIFIC: POLICY CONFIGURATION +# Policy caching, versioning, management +[[items]] +name = "policy_group" +type = "group" +title = "Policy Configuration" +description = "Configure policy engine and policy management" +includes = ["fragments/control-center/policy-section.toml"] + +# CONTROL CENTER-SPECIFIC: USER MANAGEMENT CONFIGURATION +# User registration, sessions, audit logging +[[items]] +name = "users_group" +type = "group" +title = "User Management Configuration" +description = "Configure user registration, sessions, and audit" +includes = ["fragments/control-center/users-section.toml"] + +# CONTROL CENTER-SPECIFIC: COMPLIANCE & AUDIT CONFIGURATION +# Audit logging, compliance frameworks, data retention, encryption +[[items]] +name = "compliance_group" +type = "group" +title = "Compliance & Audit Configuration" +description = "Configure audit logging, compliance, and data retention" +includes = ["fragments/control-center/compliance-section.toml"] + +# MONITORING CONFIGURATION +# Metrics collection, health checks +[[items]] +name = "monitoring_group" +type = "group" +title = "Monitoring Configuration" +description = "Configure metrics and health checks" +includes = ["fragments/monitoring-section.toml"] + +# LOGGING CONFIGURATION +# Log levels, formats, rotation +[[items]] +name = "logging_group" +type = "group" +title = "Logging Configuration" +description = "Configure logging behavior and output" +includes = ["fragments/logging-section.toml"] diff --git a/.typedialog/platform/forms/extension-registry-form.toml b/.typedialog/platform/forms/extension-registry-form.toml new file mode 100644 index 0000000..c3b1ac7 --- /dev/null +++ b/.typedialog/platform/forms/extension-registry-form.toml @@ -0,0 +1,36 @@ +[form] +name = "Extension Registry Configuration" +description = "Multi-instance extension distribution via Git sources (Gitea, Forgejo, GitHub) and OCI registries" +version = "2.0" + +[[sections]] +name = "Server Configuration" +description = "Network and performance settings" +includes = ["fragments/extension-registry/server.toml"] + +[[sections]] +name = "Git Sources" +description = "Configure Gitea, Forgejo, and GitHub as extension sources" +includes = [ + "fragments/extension-registry/gitea-multi.toml", + "fragments/extension-registry/forgejo-multi.toml", + "fragments/extension-registry/github-multi.toml", +] + +[[sections]] +name = "OCI Registries" +description = "Configure OCI registries for distribution (Zot, Harbor, Docker Hub, GHCR, Quay)" +includes = ["fragments/extension-registry/oci-multi.toml"] + +[[sections]] +name = "Caching" +description = "Cache configuration and TTL settings" +includes = ["fragments/extension-registry/cache.toml"] + +[[sections]] +name = "Legacy Configuration" +description = "Single-instance configuration (automatically migrated to multi-instance format)" +includes = [ + "fragments/extension-registry/gitea-legacy.toml", + "fragments/extension-registry/oci-legacy.toml", +] diff --git a/.typedialog/platform/forms/fragments/README.md b/.typedialog/platform/forms/fragments/README.md new file mode 100644 index 0000000..635c3dc --- /dev/null +++ b/.typedialog/platform/forms/fragments/README.md @@ -0,0 +1,334 @@ +# Fragments + +Reusable form fragments organized FLAT in this directory (not nested subdirectories). + +## Purpose + +Fragments provide: +- **Reusable sections** - Used by multiple forms +- **Modularity** - Change once, applies to all forms using it +- **Organization** - Named by purpose (workspace, server, queue, etc.) +- **DRY principle** - Don't repeat configuration sections + +## Fragment Organization + +**CRITICAL**: All fragments are stored at the SAME LEVEL (flat directory). + +``` +fragments/ +β”œβ”€β”€ workspace-section.toml # Workspace configuration +β”œβ”€β”€ server-section.toml # HTTP server settings +β”œβ”€β”€ database-rocksdb-section.toml # RocksDB database +β”œβ”€β”€ database-surrealdb-section.toml # SurrealDB database +β”œβ”€β”€ database-postgres-section.toml # PostgreSQL database +β”œβ”€β”€ security-section.toml # Auth, RBAC, encryption +β”œβ”€β”€ monitoring-section.toml # Metrics, health checks +β”œβ”€β”€ logging-section.toml # Log configuration +β”œβ”€β”€ orchestrator-queue-section.toml # Orchestrator queue config +β”œβ”€β”€ orchestrator-workflow-section.toml # Orchestrator batch workflow +β”œβ”€β”€ orchestrator-storage-section.toml # Orchestrator storage backend +β”œβ”€β”€ control-center-jwt-section.toml # Control Center JWT +β”œβ”€β”€ control-center-rbac-section.toml # Control Center RBAC +β”œβ”€β”€ control-center-compliance-section.toml +β”œβ”€β”€ mcp-capabilities-section.toml # MCP capabilities +β”œβ”€β”€ mcp-tools-section.toml # MCP tools configuration +β”œβ”€β”€ mcp-resources-section.toml # MCP resource limits +β”œβ”€β”€ deployment-mode-section.toml # Deployment mode selection +β”œβ”€β”€ resources-section.toml # Resource allocation (CPU, RAM, disk) +└── README.md # This file +``` + +Referenced in forms as: +```toml +[[items]] +name = "workspace_group" +type = "group" +includes = ["fragments/workspace-section.toml"] # Flat reference + +[[items]] +name = "queue_group" +type = "group" +includes = ["fragments/orchestrator-queue-section.toml"] # Same level +``` + +## Fragment Categories + +### Common Fragments (Used by Multiple Services) + +- **workspace-section.toml** - Workspace name, path, enable/disable +- **server-section.toml** - HTTP server host, port, workers, keep-alive +- **database-rocksdb-section.toml** - RocksDB path (filesystem-backed) +- **database-surrealdb-section.toml** - SurrealDB embedded (no external service) +- **database-postgres-section.toml** - PostgreSQL server connection +- **security-section.toml** - JWT issuer, RBAC, encryption keys +- **monitoring-section.toml** - Metrics interval, health checks +- **logging-section.toml** - Log level, format, rotation +- **resources-section.toml** - CPU cores, memory, disk allocation +- **deployment-mode-section.toml** - Solo/MultiUser/CI/CD/Enterprise selection + +### Service-Specific Fragments + +**Orchestrator** (workflow engine): +- **orchestrator-queue-section.toml** - Max concurrent tasks, retries, timeout +- **orchestrator-workflow-section.toml** - Batch workflow settings, parallelism +- **orchestrator-storage-section.toml** - Storage backend selection + +**Control Center** (policy/RBAC): +- **control-center-jwt-section.toml** - JWT issuer, audience, token expiration +- **control-center-rbac-section.toml** - Roles, permissions, policies +- **control-center-compliance-section.toml** - SOC2, HIPAA, audit logging + +**MCP Server** (protocol): +- **mcp-capabilities-section.toml** - Tools, prompts, resources, sampling +- **mcp-tools-section.toml** - Tool timeout, max concurrent, categories +- **mcp-resources-section.toml** - Max size, caching, TTL + +## Fragment Structure + +Each fragment is a TOML file containing `[[elements]]` definitions: + +```toml +# fragments/workspace-section.toml + +[[elements]] +border_top = true +border_bottom = true +name = "workspace_header" +title = "πŸ—‚οΈ Workspace Configuration" +type = "section_header" + +[[elements]] +name = "workspace_name" +type = "text" +prompt = "Workspace Name" +default = "default" +required = true +help = "Name of the workspace this service will serve" +nickel_path = ["orchestrator", "workspace", "name"] + +[[elements]] +name = "workspace_path" +type = "text" +prompt = "Workspace Path" +default = "/var/lib/provisioning/orchestrator" +required = true +help = "Absolute path to the workspace directory" +nickel_path = ["orchestrator", "workspace", "path"] + +[[elements]] +name = "workspace_enabled" +type = "confirm" +prompt = "Enable Workspace?" +default = true +help = "Enable or disable this workspace" +nickel_path = ["orchestrator", "workspace", "enabled"] +``` + +## Fragment Composition + +Fragments are included in main forms: + +```toml +# forms/orchestrator-form.toml + +name = "orchestrator_configuration" +description = "Interactive configuration for Orchestrator" + +# Include fragments in order + +[[items]] +name = "deployment_group" +type = "group" +includes = ["fragments/deployment-mode-section.toml"] + +[[items]] +name = "workspace_group" +type = "group" +includes = ["fragments/workspace-section.toml"] + +[[items]] +name = "server_group" +type = "group" +includes = ["fragments/server-section.toml"] + +[[items]] +name = "storage_group" +type = "group" +includes = ["fragments/orchestrator-storage-section.toml"] + +[[items]] +name = "queue_group" +type = "group" +includes = ["fragments/orchestrator-queue-section.toml"] + +# Optional sections +[[items]] +name = "monitoring_group" +type = "group" +when = "enable_monitoring == true" +includes = ["fragments/monitoring-section.toml"] +``` + +## Element Requirements + +Every element in a fragment MUST include: + +1. **name** - Unique identifier (used in form data) +2. **type** - Element type (text, number, confirm, select, etc.) +3. **prompt** - User-facing label +4. **nickel_path** - Mapping to Nickel structure (**CRITICAL**) + +Example: +```toml +[[elements]] +name = "max_concurrent_tasks" # Unique identifier +type = "number" # Type +prompt = "Maximum Concurrent Tasks" # User label +nickel_path = ["orchestrator", "queue", "max_concurrent_tasks"] # Nickel mapping +``` + +## Constraint Interpolation + +Fragments reference constraints dynamically: + +```toml +[[elements]] +name = "max_concurrent_tasks" +type = "number" +prompt = "Maximum Concurrent Tasks" +min = "${constraint.orchestrator.queue.concurrent_tasks.min}" # Dynamic +max = "${constraint.orchestrator.queue.concurrent_tasks.max}" # Dynamic +nickel_path = ["orchestrator", "queue", "max_concurrent_tasks"] +``` + +The `${constraint.path.to.value}` syntax references `constraints/constraints.toml`. + +## Common Fragment Patterns + +### Workspace Fragment Pattern +```toml +[[elements]] +name = "workspace_name" +type = "text" +prompt = "Workspace Name" +nickel_path = ["orchestrator", "workspace", "name"] + +[[elements]] +name = "workspace_path" +type = "text" +prompt = "Workspace Path" +nickel_path = ["orchestrator", "workspace", "path"] + +[[elements]] +name = "workspace_enabled" +type = "confirm" +prompt = "Enable Workspace?" +nickel_path = ["orchestrator", "workspace", "enabled"] +``` + +### Server Fragment Pattern +```toml +[[elements]] +name = "server_host" +type = "text" +prompt = "Server Host" +default = "127.0.0.1" +nickel_path = ["orchestrator", "server", "host"] + +[[elements]] +name = "server_port" +type = "number" +prompt = "Server Port" +min = "${constraint.common.server.port.min}" +max = "${constraint.common.server.port.max}" +nickel_path = ["orchestrator", "server", "port"] + +[[elements]] +name = "server_workers" +type = "number" +prompt = "Worker Threads" +min = 1 +max = 32 +nickel_path = ["orchestrator", "server", "workers"] +``` + +### Database Selection Pattern +```toml +[[elements]] +name = "storage_backend" +type = "select" +prompt = "Storage Backend" +options = [ + { value = "filesystem", label = "πŸ“ Filesystem" }, + { value = "rocksdb", label = "πŸ—„οΈ RocksDB (Embedded)" }, + { value = "surrealdb", label = "πŸ“Š SurrealDB" }, + { value = "postgres", label = "🐘 PostgreSQL" }, +] +nickel_path = ["orchestrator", "storage", "backend"] + +[[elements]] +name = "rocksdb_group" +type = "group" +when = "storage_backend == 'rocksdb'" +includes = ["fragments/database-rocksdb-section.toml"] + +[[elements]] +name = "postgres_group" +type = "group" +when = "storage_backend == 'postgres'" +includes = ["fragments/database-postgres-section.toml"] + +[[elements]] +name = "surrealdb_group" +type = "group" +when = "storage_backend == 'surrealdb'" +includes = ["fragments/database-surrealdb-section.toml"] +``` + +## Best Practices + +1. **Clear naming** - Fragment name describes its purpose (queue-section, not qs) +2. **Meaningful headers** - Each fragment starts with a section header (name, title, emoji) +3. **Constraint interpolation** - Use `${constraint.*}` for dynamic validation +4. **Consistent nickel_path** - Paths match actual Nickel structure +5. **Provide defaults** - Sensible defaults improve UX +6. **Help text** - Explain each field clearly +7. **Group logically** - Related fields in same fragment +8. **Test with form** - Verify fragment loads correctly in form + +## Adding a New Fragment + +1. **Create fragment file** in `forms/fragments/{name}-section.toml` +2. **Add section header** (name, title, emoji) +3. **Add form elements**: + - Include `name`, `type`, `prompt` + - Add `nickel_path` (CRITICAL) + - Add constraints if applicable + - Add `help` and `default` if appropriate +4. **Include in form** - Add to main form via `includes` field +5. **Test** - Run configuration wizard to verify fragment loads + +## Fragment Naming Convention + +- **Section fragments**: `{topic}-section.toml` (workspace-section.toml) +- **Service-specific**: `{service}-{topic}-section.toml` (orchestrator-queue-section.toml) +- **Database-specific**: `database-{backend}-section.toml` (database-postgres-section.toml) +- **Deployment-specific**: `{mode}-{topic}-section.toml` (enterprise-options-section.toml) + +## Testing Fragments + +```bash +# Validate form that uses fragment +nu provisioning/.typedialog/provisioning/platform/scripts/configure.nu orchestrator solo --backend web + +# Verify constraint interpolation works +grep "constraint\." forms/fragments/*.toml + +# Check nickel_path consistency +grep "nickel_path" forms/fragments/*.toml | sort +``` + +--- + +**Version**: 1.0.0 +**Last Updated**: 2025-01-05 diff --git a/.typedialog/platform/forms/fragments/ai-service/dag.toml b/.typedialog/platform/forms/fragments/ai-service/dag.toml new file mode 100644 index 0000000..d97b593 --- /dev/null +++ b/.typedialog/platform/forms/fragments/ai-service/dag.toml @@ -0,0 +1,38 @@ +# AI Service DAG Workflow Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "ai_dag_header" +title = "πŸ”€ DAG Workflow Configuration" +type = "section_header" + +[[elements]] +default = 10 +help = "Max concurrent DAG tasks" +max = 100 +min = 1 +name = "ai_dag_max_concurrent_tasks" +nickel_path = ["ai_service", "dag", "max_concurrent_tasks"] +prompt = "Max Concurrent Tasks" +type = "number" + +[[elements]] +default = 600000 +help = "Task timeout in milliseconds" +max = 3600000 +min = 10000 +name = "ai_dag_task_timeout" +nickel_path = ["ai_service", "dag", "task_timeout"] +prompt = "Task Timeout (ms)" +type = "number" + +[[elements]] +default = 5 +help = "Retry attempts for failed tasks" +max = 10 +min = 0 +name = "ai_dag_retry_attempts" +nickel_path = ["ai_service", "dag", "retry_attempts"] +prompt = "Retry Attempts" +type = "number" diff --git a/.typedialog/platform/forms/fragments/ai-service/mcp-integration.toml b/.typedialog/platform/forms/fragments/ai-service/mcp-integration.toml new file mode 100644 index 0000000..a749c92 --- /dev/null +++ b/.typedialog/platform/forms/fragments/ai-service/mcp-integration.toml @@ -0,0 +1,37 @@ +# AI Service MCP Integration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "ai_mcp_header" +title = "πŸ”§ MCP Integration" +type = "section_header" + +[[elements]] +default = false +help = "Enable MCP (Model Context Protocol) integration" +name = "ai_mcp_enabled" +nickel_path = ["ai_service", "mcp", "enabled"] +prompt = "Enable MCP" +type = "confirm" + +[[elements]] +condition = "ai_mcp_enabled == true" +default = "http://localhost:8084" +help = "MCP service URL" +name = "ai_mcp_service_url" +nickel_path = ["ai_service", "mcp", "mcp_service_url"] +prompt = "MCP Service URL" +required = true +type = "text" + +[[elements]] +condition = "ai_mcp_enabled == true" +default = 30000 +help = "MCP request timeout in milliseconds" +max = 300000 +min = 1000 +name = "ai_mcp_timeout" +nickel_path = ["ai_service", "mcp", "timeout"] +prompt = "Timeout (ms)" +type = "number" diff --git a/.typedialog/platform/forms/fragments/ai-service/monitoring.toml b/.typedialog/platform/forms/fragments/ai-service/monitoring.toml new file mode 100644 index 0000000..0f407c4 --- /dev/null +++ b/.typedialog/platform/forms/fragments/ai-service/monitoring.toml @@ -0,0 +1,27 @@ +# AI Service Monitoring Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "ai_monitoring_header" +title = "πŸ“Š Monitoring Configuration" +type = "section_header" + +[[elements]] +default = true +help = "Enable monitoring and metrics" +name = "ai_monitoring_enabled" +nickel_path = ["ai_service", "monitoring", "enabled"] +prompt = "Enable Monitoring" +type = "confirm" + +[[elements]] +condition = "ai_monitoring_enabled == true" +default = 60000 +help = "Metrics collection interval in milliseconds" +max = 300000 +min = 5000 +name = "ai_monitoring_metrics_interval" +nickel_path = ["ai_service", "monitoring", "metrics_interval"] +prompt = "Metrics Interval (ms)" +type = "number" diff --git a/.typedialog/platform/forms/fragments/ai-service/rag-integration.toml b/.typedialog/platform/forms/fragments/ai-service/rag-integration.toml new file mode 100644 index 0000000..4233508 --- /dev/null +++ b/.typedialog/platform/forms/fragments/ai-service/rag-integration.toml @@ -0,0 +1,37 @@ +# AI Service RAG Integration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "ai_rag_header" +title = "🧠 RAG Integration" +type = "section_header" + +[[elements]] +default = true +help = "Enable RAG integration" +name = "ai_rag_enabled" +nickel_path = ["ai_service", "rag", "enabled"] +prompt = "Enable RAG" +type = "confirm" + +[[elements]] +condition = "ai_rag_enabled == true" +default = "http://localhost:8083" +help = "RAG service URL" +name = "ai_rag_service_url" +nickel_path = ["ai_service", "rag", "rag_service_url"] +prompt = "RAG Service URL" +required = true +type = "text" + +[[elements]] +condition = "ai_rag_enabled == true" +default = 30000 +help = "RAG request timeout in milliseconds" +max = 300000 +min = 1000 +name = "ai_rag_timeout" +nickel_path = ["ai_service", "rag", "timeout"] +prompt = "Timeout (ms)" +type = "number" diff --git a/.typedialog/platform/forms/fragments/ai-service/server.toml b/.typedialog/platform/forms/fragments/ai-service/server.toml new file mode 100644 index 0000000..c81c171 --- /dev/null +++ b/.typedialog/platform/forms/fragments/ai-service/server.toml @@ -0,0 +1,39 @@ +# AI Service Server Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "ai_service_server_header" +title = "πŸ–₯️ Server Configuration" +type = "section_header" + +[[elements]] +default = "0.0.0.0" +help = "HTTP server bind address" +name = "ai_service_server_host" +nickel_path = ["ai_service", "server", "host"] +prompt = "Server Host" +required = true +type = "text" + +[[elements]] +default = 8082 +help = "HTTP server port (range: 1024-65535)" +max = 65535 +min = 1024 +name = "ai_service_server_port" +nickel_path = ["ai_service", "server", "port"] +prompt = "Server Port" +required = true +type = "number" + +[[elements]] +default = 4 +help = "Number of HTTP worker threads" +max = 32 +min = 1 +name = "ai_service_server_workers" +nickel_path = ["ai_service", "server", "workers"] +prompt = "Worker Threads" +required = true +type = "number" diff --git a/.typedialog/platform/forms/fragments/constraint_interpolation_guide.md b/.typedialog/platform/forms/fragments/constraint_interpolation_guide.md new file mode 100644 index 0000000..a7c0b5b --- /dev/null +++ b/.typedialog/platform/forms/fragments/constraint_interpolation_guide.md @@ -0,0 +1,225 @@ +# Constraint Interpolation Guide + +## 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. + +## Pattern + +All numeric form fields should use constraint interpolation for `min` and `max` values: + +```toml +[[elements]] +name = "field_name" +type = "number" +default = 5 +help = "Field description (range: ${constraint.path.to.constraint.min}-${constraint.path.to.constraint.max})" +min = "${constraint.path.to.constraint.min}" +max = "${constraint.path.to.constraint.max}" +nickel_path = ["path", "to", "field"] +prompt = "Field Label" +``` + +## Benefits + +1. **Single Source of Truth**: Constraints defined once in `constraints.toml`, used everywhere +2. **Dynamic Validation**: If constraint changes, all forms automatically get updated ranges +3. **User-Friendly**: Forms show actual valid ranges in help text +4. **Type Safety**: Constraints match Nickel schema contract ranges + +## Complete Constraint Mapping + +### Orchestrator Fragments + +| Fragment | Field | Constraint Path | Min | Max | +|----------|-------|-----------------|-----|-----| +| `queue-section.toml` | `queue_max_concurrent_tasks` | `orchestrator.queue.concurrent_tasks` | 1 | 100 | +| `queue-section.toml` | `queue_retry_attempts` | `orchestrator.queue.retry_attempts` | 0 | 10 | +| `queue-section.toml` | `queue_retry_delay` | `orchestrator.queue.retry_delay` | 1000 | 60000 | +| `queue-section.toml` | `queue_task_timeout` | `orchestrator.queue.task_timeout` | 60000 | 86400000 | +| `batch-section.toml` | `batch_parallel_limit` | `orchestrator.batch.parallel_limit` | 1 | 50 | +| `batch-section.toml` | `batch_operation_timeout` | `orchestrator.batch.operation_timeout` | 60000 | 3600000 | +| `extensions-section.toml` | `extensions_max_concurrent` | `orchestrator.extensions.max_concurrent` | 1 | 20 | +| `extensions-section.toml` | `extensions_discovery_interval` | Not in constraints (use reasonable bounds) | 300 | 86400 | +| `extensions-section.toml` | `extensions_init_timeout` | Not in constraints (use reasonable bounds) | 1000 | 300000 | +| `extensions-section.toml` | `extensions_sandbox_max_memory_mb` | Not in constraints (use reasonable bounds) | 64 | 4096 | +| `performance-section.toml` | `memory_max_heap_mb` | Not in constraints (use mode-based bounds) | 256 | 131072 | +| `performance-section.toml` | `profiling_sample_rate` | Not in constraints (use reasonable bounds) | 10 | 1000 | +| `storage-section.toml` | `storage_cache_ttl` | Not in constraints (use 60-3600) | 60 | 3600 | +| `storage-section.toml` | `storage_cache_max_entries` | Not in constraints (use 10-100000) | 10 | 100000 | +| `storage-section.toml` | `storage_compression_level` | Not in constraints (zstd: 1-19) | 1 | 19 | +| `storage-section.toml` | `storage_gc_retention` | Not in constraints (use 3600-31536000) | 3600 | 31536000 | +| `storage-section.toml` | `storage_gc_interval` | Not in constraints (use 300-86400) | 300 | 86400 | + +### Control Center Fragments + +| Fragment | Field | Constraint Path | Min | Max | +|----------|-------|-----------------|-----|-----| +| `security-section.toml` | `jwt_token_expiration` | `control_center.jwt.token_expiration` | 300 | 604800 | +| `security-section.toml` | `jwt_refresh_expiration` | `control_center.jwt.refresh_expiration` | 3600 | 2592000 | +| `security-section.toml` | `rate_limiting_max_requests` | `control_center.rate_limiting.max_requests` | 10 | 10000 | +| `security-section.toml` | `rate_limiting_window` | `control_center.rate_limiting.window_seconds` | 1 | 3600 | +| `security-section.toml` | `users_sessions_max_active` | Not in constraints (use 1-100) | 1 | 100 | +| `security-section.toml` | `users_sessions_idle_timeout` | Not in constraints (use 300-86400) | 300 | 86400 | +| `security-section.toml` | `users_sessions_absolute_timeout` | Not in constraints (use 3600-2592000) | 3600 | 2592000 | +| `policy-section.toml` | `policy_cache_ttl` | Not in constraints (use 60-86400) | 60 | 86400 | +| `policy-section.toml` | `policy_cache_max_policies` | Not in constraints (use 100-10000) | 100 | 10000 | +| `policy-section.toml` | `policy_versioning_max_versions` | Not in constraints (use 1-100) | 1 | 100 | +| `users-section.toml` | `users_registration_auto_role` | Not in constraints (select field, not numeric) | - | - | +| `users-section.toml` | `users_sessions_max_active` | Not in constraints (use 1-100) | 1 | 100 | +| `users-section.toml` | `users_sessions_idle_timeout` | Not in constraints (use 300-86400) | 300 | 86400 | +| `users-section.toml` | `users_sessions_absolute_timeout` | Not in constraints (use 3600-2592000) | 3600 | 2592000 | +| `compliance-section.toml` | `audit_retention_days` | `control_center.audit.retention_days` | 1 | 3650 | +| `compliance-section.toml` | `compliance_validation_interval` | Not in constraints (use 1-168 hours) | 1 | 168 | +| `compliance-section.toml` | `compliance_data_retention_years` | Not in constraints (use 1-30) | 1 | 30 | +| `compliance-section.toml` | `compliance_audit_log_days` | Not in constraints (use 90-10950) | 90 | 10950 | + +### MCP Server Fragments + +| Fragment | Field | Constraint Path | Min | Max | +|----------|-------|-----------------|-----|-----| +| `tools-section.toml` | `tools_max_concurrent` | `mcp_server.tools.max_concurrent` | 1 | 20 | +| `tools-section.toml` | `tools_timeout` | `mcp_server.tools.timeout` | 5000 | 600000 | +| `prompts-section.toml` | `prompts_max_templates` | `mcp_server.prompts.max_templates` | 1 | 100 | +| `prompts-section.toml` | `prompts_cache_ttl` | Not in constraints (use 60-86400) | 60 | 86400 | +| `prompts-section.toml` | `prompts_versioning_max_versions` | Not in constraints (use 1-100) | 1 | 100 | +| `resources-section.toml` | `resources_max_size` | `mcp_server.resources.max_size` | 1048576 | 1073741824 | +| `resources-section.toml` | `resources_cache_max_size_mb` | Not in constraints (use 10-10240) | 10 | 10240 | +| `resources-section.toml` | `resources_cache_ttl` | `mcp_server.resources.cache_ttl` | 60 | 3600 | +| `resources-section.toml` | `resources_validation_max_depth` | Not in constraints (use 1-100) | 1 | 100 | +| `sampling-section.toml` | `sampling_max_tokens` | `mcp_server.sampling.max_tokens` | 100 | 100000 | +| `sampling-section.toml` | `sampling_temperature` | Not in constraints (use 0.0-2.0) | 0.0 | 2.0 | +| `sampling-section.toml` | `sampling_cache_ttl` | Not in constraints (use 60-3600) | 60 | 3600 | + +### Common/Shared Fragments + +| Fragment | Field | Constraint Path | Min | Max | +|----------|-------|-----------------|-----|-----| +| `server-section.toml` | `server_port` | `common.server.port` | 1024 | 65535 | +| `server-section.toml` | `server_workers` | `common.server.workers` | 1 | 32 | +| `server-section.toml` | `server_max_connections` | `common.server.max_connections` | 10 | 10000 | +| `server-section.toml` | `server_keep_alive` | `common.server.keep_alive` | 0 | 600 | +| `monitoring-section.toml` | `monitoring_metrics_interval` | `common.monitoring.metrics_interval` | 10 | 300 | +| `monitoring-section.toml` | `monitoring_health_check_interval` | `common.monitoring.health_check_interval` | 5 | 300 | +| `logging-section.toml` | `logging_max_file_size` | `common.logging.max_file_size` | 1048576 | 1073741824 | +| `logging-section.toml` | `logging_max_backups` | `common.logging.max_backups` | 1 | 100 | +| `database-rocksdb-section.toml` | `database_pool_size` | Not in constraints (use 1-100) | 1 | 100 | +| `database-rocksdb-section.toml` | `database_timeout` | Not in constraints (use 10-3600) | 10 | 3600 | +| `database-rocksdb-section.toml` | `database_retry_attempts` | Not in constraints (use 0-10) | 0 | 10 | +| `database-rocksdb-section.toml` | `database_retry_delay` | Not in constraints (use 1000-60000) | 1000 | 60000 | +| `database-surrealdb-section.toml` | `pool_size` | Not in constraints (use 1-200) | 1 | 200 | +| `database-surrealdb-section.toml` | `timeout` | Not in constraints (use 10-3600) | 10 | 3600 | +| `database-postgres-section.toml` | `postgres_port` | Not in constraints (use 1024-65535) | 1024 | 65535 | +| `database-postgres-section.toml` | `postgres_pool_size` | Not in constraints (use 5-200) | 5 | 200 | + +### Installer Fragments + +| Fragment | Field | Constraint Path | Min | Max | +|----------|-------|-----------------|-----|-----| +| `target-section.toml` | `remote_ssh_port` | `common.server.port` | 1024 | 65535 | +| `preflight-section.toml` | `min_disk_gb` | `deployment.solo.disk_gb.min` (mode-dependent) | Variable | Variable | +| `preflight-section.toml` | `min_memory_gb` | `deployment.solo.memory_mb.min` (mode-dependent) | Variable | Variable | +| `preflight-section.toml` | `min_cpu_cores` | `deployment.solo.cpu.min` (mode-dependent) | Variable | Variable | +| `installation-section.toml` | `parallel_services` | Not in constraints (use 1-10) | 1 | 10 | +| `installation-section.toml` | `installation_timeout_seconds` | Not in constraints (use 0-14400) | 0 | 14400 | +| `installation-section.toml` | `log_level` | Not in constraints (select field, not numeric) | - | - | +| `installation-section.toml` | `validation_timeout` | Not in constraints (use 5000-300000) | 5000 | 300000 | +| `services-section.toml` | `orchestrator_port` | `common.server.port` | 1024 | 65535 | +| `services-section.toml` | `control_center_port` | `common.server.port` | 1024 | 65535 | +| `services-section.toml` | `mcp_server_port` | `common.server.port` | 1024 | 65535 | +| `services-section.toml` | `api_gateway_port` | `common.server.port` | 1024 | 65535 | +| `database-section.toml` | `connection_pool_size` | Not in constraints (use 1-100) | 1 | 100 | +| `database-section.toml` | `connection_pool_timeout` | Not in constraints (use 10-3600) | 10 | 3600 | +| `database-section.toml` | `connection_idle_timeout` | Not in constraints (use 60-14400) | 60 | 14400 | +| `storage-section.toml` | `storage_size_gb` | Not in constraints (use 10-100000) | 10 | 100000 | +| `storage-section.toml` | `storage_replication_factor` | Not in constraints (use 2-10) | 2 | 10 | +| `networking-section.toml` | `load_balancer_http_port` | `common.server.port` | 1024 | 65535 | +| `networking-section.toml` | `load_balancer_https_port` | `common.server.port` | 1024 | 65535 | +| `ha-section.toml` | `ha_cluster_size` | Not in constraints (use 3-256) | 3 | 256 | +| `ha-section.toml` | `ha_db_quorum_size` | Not in constraints (use 1-max_cluster_size) | 1 | 256 | +| `ha-section.toml` | `ha_health_check_interval` | Not in constraints (use 1-120) | 1 | 120 | +| `ha-section.toml` | `ha_health_check_failure_threshold` | Not in constraints (use 1-10) | 1 | 10 | +| `ha-section.toml` | `ha_failover_delay` | Not in constraints (use 0-600) | 0 | 600 | +| `upgrades-section.toml` | `rolling_upgrade_parallel` | Not in constraints (use 1-10) | 1 | 10 | +| `upgrades-section.toml` | `canary_percentage` | Not in constraints (use 1-50) | 1 | 50 | +| `upgrades-section.toml` | `canary_duration_seconds` | Not in constraints (use 30-3600) | 30 | 3600 | + +## Fragments Status + +### βœ… Completed (Constraints Interpolated) +- `server-section.toml` - All numeric fields updated +- `monitoring-section.toml` - Core metrics interval updated +- `orchestrator/queue-section.toml` - All queue fields updated +- `orchestrator/batch-section.toml` - Parallel limit and operation timeout updated +- `mcp-server/tools-section.toml` - Tools concurrency and timeout updated + +### ⏳ Remaining (Need Updates) +- All other orchestrator fragments (extensions, performance, storage) +- All control-center fragments (security, policy, users, compliance) +- Remaining MCP fragments (prompts, resources, sampling) +- All installer fragments (target, preflight, installation, services, database, storage, networking, ha, upgrades) +- All database fragments (rocksdb, surrealdb, postgres) +- logging-section.toml + +## How to Add Constraints to a Fragment + +1. **Identify numeric fields** with `type = "number"` that have `min` and/or `max` values +2. **Find the constraint path** in the mapping table above +3. **Update the field** with constraint references: + +```toml +# Before +[[elements]] +default = 5 +min = 1 +max = 100 +name = "my_field" +type = "number" + +# After +[[elements]] +default = 5 +help = "Field description (range: ${constraint.path.to.field.min}-${constraint.path.to.field.max})" +min = "${constraint.path.to.field.min}" +max = "${constraint.path.to.field.max}" +name = "my_field" +type = "number" +``` + +4. **For fields without existing constraints**, add reasonable bounds based on the domain: + - Timeouts: typically 1 second to 1 hour (1000-3600000 ms) + - Counters: typically 1-100 or 1-1000 + - Memory: use deployment mode constraints (64MB-256GB) + - Ports: use `common.server.port` (1024-65535) + +5. **Test** that the constraint is accessible in `constraints.toml` + +## Example: Adding Constraint to a New Field + +```toml +[[elements]] +default = 3600 +help = "Cache timeout in seconds (range: ${constraint.common.monitoring.health_check_interval.min}-${constraint.common.monitoring.health_check_interval.max})" +min = "${constraint.common.monitoring.health_check_interval.min}" +max = "${constraint.common.monitoring.health_check_interval.max}" +name = "cache_timeout_seconds" +nickel_path = ["cache", "timeout_seconds"] +prompt = "Cache Timeout (seconds)" +type = "number" +``` + +## Integration with TypeDialog + +When TypeDialog processes forms: + +1. **Load time**: Constraint references are resolved from `constraints.toml` +2. **Validation**: User input is validated against resolved min/max values +3. **Help text**: Ranges are shown to user in help messages +4. **Nickel generation**: Jinja2 templates receive validated values + +## See Also + +- `provisioning/.typedialog/provisioning/platform/constraints/constraints.toml` - Constraint definitions +- `constraint_update_status.md` - Progress tracking for constraint interpolation updates +- `provisioning/.typedialog/provisioning/platform/templates/*.j2` - Jinja2 templates for code generation +- `provisioning/schemas/` - Nickel schemas (use same ranges as constraints) diff --git a/.typedialog/platform/forms/fragments/constraint_update_status.md b/.typedialog/platform/forms/fragments/constraint_update_status.md new file mode 100644 index 0000000..72bb5db --- /dev/null +++ b/.typedialog/platform/forms/fragments/constraint_update_status.md @@ -0,0 +1,298 @@ +# Constraint Interpolation Update Status + +**Date**: 2025-01-05 +**Status**: Phase 1.5 - COMPLETE βœ… All Constraint Interpolation Finished +**Progress**: 33 / 33 fragments updated (100%) + +## 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. + +## Completed Fragments βœ… + +### Common/Shared Fragments +- βœ… **server-section.toml** (100%) + - server_port β†’ `common.server.port` + - server_workers β†’ `common.server.workers` + - server_max_connections β†’ `common.server.max_connections` + - server_keep_alive β†’ `common.server.keep_alive` + +- βœ… **monitoring-section.toml** (1 of 1 critical field) + - monitoring_metrics_interval β†’ `common.monitoring.metrics_interval` + +### Orchestrator Fragments +- βœ… **orchestrator/queue-section.toml** (100%) + - queue_max_concurrent_tasks β†’ `orchestrator.queue.concurrent_tasks` + - queue_retry_attempts β†’ `orchestrator.queue.retry_attempts` + - queue_retry_delay β†’ `orchestrator.queue.retry_delay` + - queue_task_timeout β†’ `orchestrator.queue.task_timeout` + +- βœ… **orchestrator/batch-section.toml** (2 of 2 critical fields) + - batch_parallel_limit β†’ `orchestrator.batch.parallel_limit` + - batch_operation_timeout β†’ `orchestrator.batch.operation_timeout` + +### MCP Server Fragments +- βœ… **mcp-server/tools-section.toml** (100%) + - tools_max_concurrent β†’ `mcp_server.tools.max_concurrent` + - tools_timeout β†’ `mcp_server.tools.timeout` + +- βœ… **mcp-server/prompts-section.toml** (100%) + - prompts_max_templates β†’ `mcp_server.prompts.max_templates` + - prompts_cache_ttl β†’ reasonable bounds (60-86400) + - prompts_versioning_max_versions β†’ reasonable bounds (1-100) + +- βœ… **mcp-server/resources-section.toml** (100%) + - resources_max_size β†’ `mcp_server.resources.max_size` + - resources_cache_ttl β†’ `mcp_server.resources.cache_ttl` + - resources_cache_max_size_mb β†’ reasonable bounds (10-10240) + - resources_validation_max_depth β†’ reasonable bounds (1-100) + +- βœ… **mcp-server/sampling-section.toml** (100%) + - sampling_max_tokens β†’ `mcp_server.sampling.max_tokens` + - sampling_cache_ttl β†’ reasonable bounds (60-3600) + +### Control Center Fragments +- βœ… **control-center/security-section.toml** (100%) + - jwt_token_expiration β†’ `control_center.jwt.token_expiration` + - jwt_refresh_expiration β†’ `control_center.jwt.refresh_expiration` + - rate_limiting_max_requests β†’ `control_center.rate_limiting.max_requests` + - rate_limiting_window β†’ `control_center.rate_limiting.window_seconds` + +- βœ… **control-center/compliance-section.toml** (100%) + - audit_retention_days β†’ `control_center.audit.retention_days` + - compliance_validation_interval β†’ reasonable bounds (1-168 hours) + - compliance_data_retention_years β†’ reasonable bounds (1-30) + - compliance_audit_log_days β†’ reasonable bounds (90-10950) + +### Shared/Common Fragments +- βœ… **logging-section.toml** (100%) + - logging_max_file_size β†’ `common.logging.max_file_size` + - logging_max_backups β†’ `common.logging.max_backups` + +### Orchestrator Fragments +- βœ… **orchestrator/extensions-section.toml** (100%) + - extensions_max_concurrent β†’ `orchestrator.extensions.max_concurrent` + - extensions_discovery_interval β†’ reasonable bounds (300-86400) + - extensions_init_timeout β†’ reasonable bounds (1000-300000) + - extensions_health_check_interval β†’ reasonable bounds (5000-300000) + +## All Fragments Completed βœ… + +### Orchestrator Fragments (3/3 Complete) +- [x] βœ… orchestrator/extensions-section.toml (100%) + - extensions_max_concurrent β†’ `orchestrator.extensions.max_concurrent` + - extensions_discovery_interval, init_timeout, health_check_interval β†’ reasonable bounds + +- [x] βœ… orchestrator/performance-section.toml (100% - TODAY) + - memory_initial_heap_mb β†’ reasonable bounds (128-131072) + - profiling_memory_min_size_kb β†’ reasonable bounds (1-1048576) + - inline_cache_max_entries β†’ reasonable bounds (1000-1000000) + - inline_cache_ttl β†’ reasonable bounds (60-86400) + - async_io_max_in_flight β†’ reasonable bounds (256-1048576) + +- [x] βœ… orchestrator/storage-section.toml (100% - TODAY) + - storage_cache_ttl β†’ reasonable bounds (60-86400) + - storage_cache_max_entries β†’ reasonable bounds (10-1000000) + - storage_compression_level β†’ already has max (1-19) + - storage_gc_retention β†’ reasonable bounds (3600-31536000 / 1 hour-1 year) + - storage_gc_interval β†’ reasonable bounds (300-86400) + +### Control Center Fragments (5/5 Complete) +- [x] βœ… control-center/security-section.toml (100%) + - jwt_token_expiration β†’ `control_center.jwt.token_expiration` + - rate_limiting_max_requests β†’ `control_center.rate_limiting.max_requests` + +- [x] βœ… control-center/policy-section.toml (100% - TODAY) + - policy_cache_ttl β†’ reasonable bounds (60-86400) + - policy_cache_max_policies β†’ reasonable bounds (100-1000000) + - policy_versioning_max_versions β†’ reasonable bounds (1-1000) + +- [x] βœ… control-center/users-section.toml (100% - TODAY) + - users_sessions_max_active β†’ reasonable bounds (1-100) + - users_sessions_idle_timeout β†’ reasonable bounds (300-86400) + - users_sessions_absolute_timeout β†’ reasonable bounds (3600-604800 / 1 hour-1 week) + +- [x] βœ… control-center/compliance-section.toml (100%) + - audit_retention_days β†’ `control_center.audit.retention_days` + +- [x] βœ… control-center/rbac-section.toml (100%) + - No numeric fields (confirm/select only) + +### MCP Server (3 fragments) +- [x] βœ… mcp-server/prompts-section.toml + +- [x] βœ… mcp-server/resources-section.toml + +- [x] βœ… mcp-server/sampling-section.toml + +### Common Database Fragments (3 fragments) +- [x] βœ… database-rocksdb-section.toml (100%) + - connection_pool_size β†’ reasonable bounds (1-100) + - connection_pool_timeout β†’ reasonable bounds (10-3600) + - connection_retry_attempts β†’ reasonable bounds (0-10) + - connection_retry_delay β†’ reasonable bounds (1000-60000) + +- [x] βœ… database-surrealdb-section.toml (100%) + - connection_pool_size β†’ reasonable bounds (1-200) + - connection_pool_timeout β†’ reasonable bounds (10-3600) + - connection_retry_attempts β†’ reasonable bounds (0-10) + - connection_retry_delay β†’ reasonable bounds (1000-60000) + +- [x] βœ… database-postgres-section.toml (100%) + - postgres_port β†’ `common.server.port` + - postgres_pool_size β†’ reasonable bounds (5-200) + - postgres_pool_timeout β†’ reasonable bounds (10-3600) + - postgres_retry_attempts β†’ reasonable bounds (0-10) + - postgres_retry_delay β†’ reasonable bounds (1000-60000) + +### Other Shared Fragments (1 fragment) +- [x] βœ… logging-section.toml + +### Installer Fragments (10 fragments) - ALL COMPLETE βœ… + +- [x] βœ… installer/target-section.toml (100%) + - remote_ssh_port β†’ `common.server.port` + +- [x] βœ… installer/preflight-section.toml (100%) + - min_disk_gb β†’ reasonable bounds (1-10000) + - min_memory_gb β†’ already has constraints (1-512) + - min_cpu_cores β†’ already has constraints (1-128) + +- [x] βœ… installer/installation-section.toml (100%) + - parallel_services β†’ reasonable bounds (1-10) + - installation_timeout_seconds β†’ reasonable bounds (0-14400) + - validation_timeout β†’ reasonable bounds (5000-300000) + +- [x] βœ… installer/services-section.toml (100%) + - orchestrator_port β†’ `common.server.port` + - control_center_port β†’ `common.server.port` + - mcp_server_port β†’ `common.server.port` + - api_gateway_port β†’ `common.server.port` + +- [x] βœ… installer/database-section.toml (100%) + - connection_pool_size β†’ reasonable bounds (1-100) + - connection_pool_timeout β†’ reasonable bounds (10-3600) + - connection_idle_timeout β†’ reasonable bounds (60-14400) + +- [x] βœ… installer/storage-section.toml (100%) + - storage_size_gb β†’ reasonable bounds (10-100000) + - storage_replication_factor β†’ reasonable bounds (2-10) + +- [x] βœ… installer/networking-section.toml (100%) + - load_balancer_http_port β†’ `common.server.port` + - load_balancer_https_port β†’ `common.server.port` + +- [x] βœ… installer/ha-section.toml (100%) + - ha_cluster_size β†’ reasonable bounds (3-256) + - ha_db_quorum_size β†’ reasonable bounds (1-256) + - ha_health_check_interval β†’ reasonable bounds (1-120) + - ha_health_check_timeout β†’ reasonable bounds (1000-300000) + - ha_failover_delay β†’ reasonable bounds (0-600) + - ha_backup_interval β†’ reasonable bounds (300-86400) + - ha_metrics_interval β†’ reasonable bounds (5-300) + +- [x] βœ… installer/post-install-section.toml (100%) + - verification_timeout β†’ reasonable bounds (30-3600) + +- [x] βœ… installer/upgrades-section.toml (100%) + - rolling_upgrade_parallel β†’ reasonable bounds (1-10) + - canary_percentage β†’ reasonable bounds (1-50) + - canary_duration_seconds β†’ reasonable bounds (30-7200) + - maintenance_duration_seconds β†’ reasonable bounds (600-86400) + - backup_timeout_minutes β†’ reasonable bounds (5-1440) + - rollback_validation_delay β†’ reasonable bounds (30-1800) + - post_upgrade_health_check_interval β†’ reasonable bounds (5-300) + - post_upgrade_monitoring_duration β†’ reasonable bounds (60-86400) + +## How to Continue + +1. **Reference the mapping**: See `constraint_interpolation_guide.md` for complete field β†’ constraint mappings + +2. **For fragments with existing constraints** (e.g., `security-section.toml`): + ```bash + # Update fields using the pattern from completed fragments + # Example: jwt_token_expiration β†’ control_center.jwt.token_expiration + ``` + +3. **For fragments without existing constraints** (e.g., `performance-section.toml`): + - Use reasonable domain-based ranges + - Document your choice in the help text + - Examples: + - Timeouts: 1s-1hr range (1000-3600000 ms) + - Thread counts: 1-32 range + - Memory: 64MB-256GB range (use deployment modes) + - Ports: use `common.server.port` (1024-65535) + +## Testing + +After updating a fragment: + +```bash +# 1. Verify fragment syntax +cd provisioning/.typedialog/provisioning/platform/forms/fragments +grep -n 'min = \|max = ' .toml | head -20 + +# 2. Validate constraints exist +cd ../.. +grep -r "$(constraint path)" constraints/constraints.toml + +# 3. Test form rendering +typedialog-cli validate forms/-form.toml +``` + +## Notes + +### Pattern Applied +All numeric fields now follow this structure: +```toml +[[elements]] +default = 10 +help = "Field description (range: ${constraint.path.min}-${constraint.path.max})" +min = "${constraint.path.min}" +max = "${constraint.path.max}" +name = "field_name" +nickel_path = ["path", "to", "nickel"] +prompt = "Field Label" +type = "number" +``` + +### Benefits Realized +- βœ… Single source of truth in `constraints.toml` +- βœ… Help text shows actual valid ranges to users +- βœ… TypeDialog validates input against constraints +- βœ… Jinja2 templates receive validated values +- βœ… Easy to update limits globally (all forms auto-update) + +## Completion Summary + +**Final Status**: 33/33 fragments (100%) βœ… COMPLETE + +**Work Completed Today**: +- βœ… orchestrator/performance-section.toml (5 fields with max bounds) +- βœ… orchestrator/storage-section.toml (4 fields with max bounds) +- βœ… control-center/policy-section.toml (3 fields with max bounds) +- βœ… control-center/users-section.toml (3 fields with max bounds) +- βœ… Fragments with no numeric fields (rbac, mode-selection, workspace) verified as complete + +**Total Progress This Session**: +- Started: 12/33 (36%) +- Ended: 33/33 (100%) +- +21 fragments updated +- +50+ numeric fields with constraint bounds added + +### Next Phase: Phase 8 - Nushell Scripts +Ready to proceed with implementation: +- Interactive configuration wizard (configure.nu) +- Config generation from Nickel β†’ TOML (generate-configs.nu) +- Validation and roundtrip workflows +- Template rendering (Docker Compose, Kubernetes) + +## Files + +- `constraints/constraints.toml` - Source of truth for all validation limits +- `constraint_interpolation_guide.md` - Complete mapping and best practices +- `constraint_update_status.md` - This file (progress tracking) + +--- + +**To contribute**: Pick any unchecked fragment above and follow the pattern in `constraint_interpolation_guide.md`. Each constraint update takes ~5 minutes per fragment. diff --git a/.typedialog/platform/forms/fragments/control-center/compliance-section.toml b/.typedialog/platform/forms/fragments/control-center/compliance-section.toml new file mode 100644 index 0000000..301913d --- /dev/null +++ b/.typedialog/platform/forms/fragments/control-center/compliance-section.toml @@ -0,0 +1,108 @@ +# Control Center Compliance & Audit Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "compliance_section_header" +title = "βœ… Compliance & Audit" +type = "section_header" + +# Audit Logging +[[elements]] +default = false +help = "Enable audit logging for all actions" +name = "audit_enabled" +nickel_path = ["audit", "enabled"] +prompt = "Enable Audit Logging" +type = "confirm" + +[[elements]] +condition = "audit_enabled == true" +default = 90 +help = "Audit log retention in days (range: ${constraint.control_center.audit.retention_days.min}-${constraint.control_center.audit.retention_days.max})" +max = "${constraint.control_center.audit.retention_days.max}" +min = "${constraint.control_center.audit.retention_days.min}" +name = "audit_retention_days" +nickel_path = ["audit", "storage", "retention_days"] +prompt = "Audit Retention (days)" +type = "number" + +[[elements]] +condition = "audit_enabled == true" +default = false +help = "Make audit logs immutable (write-once)" +name = "audit_immutable" +nickel_path = ["audit", "storage", "immutable"] +prompt = "Immutable Audit Logs" +type = "confirm" + +[[elements]] +condition = "audit_enabled == true" +default = true +help = "Redact sensitive data from audit logs" +name = "audit_redact_sensitive" +nickel_path = ["audit", "redact_sensitive"] +prompt = "Redact Sensitive Data" +type = "confirm" + +# Compliance Configuration +[[elements]] +default = false +help = "Enable compliance framework enforcement" +name = "compliance_enabled" +nickel_path = ["compliance", "enabled"] +prompt = "Enable Compliance Framework" +type = "confirm" + +[[elements]] +condition = "compliance_enabled == true" +default = false +help = "Enable automated compliance validation" +name = "compliance_validation_enabled" +nickel_path = ["compliance", "validation", "enabled"] +prompt = "Enable Compliance Validation" +type = "confirm" + +[[elements]] +condition = "compliance_enabled == true && compliance_validation_enabled == true" +default = 24 +help = "Compliance validation interval in hours (range: 1-168)" +max = 168 +min = 1 +name = "compliance_validation_interval" +nickel_path = ["compliance", "validation", "interval_hours"] +prompt = "Validation Interval (hours)" +type = "number" + +# Data Retention +[[elements]] +condition = "compliance_enabled == true" +default = 7 +help = "Data retention policy in years (range: 1-30)" +max = 30 +min = 1 +name = "compliance_data_retention_years" +nickel_path = ["compliance", "data_retention", "policy_years"] +prompt = "Data Retention Policy (years)" +type = "number" + +[[elements]] +condition = "compliance_enabled == true" +default = 2555 +help = "Audit log retention in days (range: 90-10950, approximately 7 years default)" +max = 10950 +min = 90 +name = "compliance_audit_log_days" +nickel_path = ["compliance", "data_retention", "audit_log_days"] +prompt = "Audit Log Retention (days)" +type = "number" + +# Encryption Requirements +[[elements]] +condition = "compliance_enabled == true" +default = false +help = "Require encryption for sensitive data at rest" +name = "compliance_encryption_required" +nickel_path = ["compliance", "encryption_required"] +prompt = "Require Encryption" +type = "confirm" diff --git a/.typedialog/platform/forms/fragments/control-center/policy-section.toml b/.typedialog/platform/forms/fragments/control-center/policy-section.toml new file mode 100644 index 0000000..990d746 --- /dev/null +++ b/.typedialog/platform/forms/fragments/control-center/policy-section.toml @@ -0,0 +1,67 @@ +# Control Center Policy Engine Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "policy_section_header" +title = "πŸ“‹ Policy Engine Configuration" +type = "section_header" + +[[elements]] +default = true +help = "Enable policy engine" +name = "policy_enabled" +nickel_path = ["policy", "enabled"] +prompt = "Enable Policy Engine" +type = "confirm" + +[[elements]] +condition = "policy_enabled == true" +default = true +help = "Enable policy caching" +name = "policy_cache_enabled" +nickel_path = ["policy", "cache", "enabled"] +prompt = "Enable Policy Caching" +type = "confirm" + +[[elements]] +condition = "policy_enabled == true && policy_cache_enabled == true" +default = 3600 +help = "Policy cache TTL in seconds (range: 60-86400)" +max = 86400 +min = 60 +name = "policy_cache_ttl" +nickel_path = ["policy", "cache", "ttl"] +prompt = "Cache TTL (seconds)" +type = "number" + +[[elements]] +condition = "policy_enabled == true && policy_cache_enabled == true" +default = 10000 +help = "Maximum policies to keep in cache (range: 100-1000000)" +max = 1000000 +min = 100 +name = "policy_cache_max_policies" +nickel_path = ["policy", "cache", "max_policies"] +prompt = "Max Cached Policies" +type = "number" + +[[elements]] +condition = "policy_enabled == true" +default = true +help = "Enable policy versioning" +name = "policy_versioning_enabled" +nickel_path = ["policy", "versioning", "enabled"] +prompt = "Enable Policy Versioning" +type = "confirm" + +[[elements]] +condition = "policy_enabled == true && policy_versioning_enabled == true" +default = 20 +help = "Maximum policy versions to keep (range: 1-1000)" +max = 1000 +min = 1 +name = "policy_versioning_max_versions" +nickel_path = ["policy", "versioning", "max_versions"] +prompt = "Max Policy Versions" +type = "number" diff --git a/.typedialog/platform/forms/fragments/control-center/rbac-section.toml b/.typedialog/platform/forms/fragments/control-center/rbac-section.toml new file mode 100644 index 0000000..17ac3fa --- /dev/null +++ b/.typedialog/platform/forms/fragments/control-center/rbac-section.toml @@ -0,0 +1,49 @@ +# Control Center RBAC Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "rbac_section_header" +title = "πŸ” RBAC Configuration" +type = "section_header" + +[[elements]] +default = true +help = "Enable Role-Based Access Control" +name = "rbac_roles_admin" +nickel_path = ["rbac", "roles", "admin"] +prompt = "Enable Admin Role" +type = "confirm" + +[[elements]] +default = true +help = "Enable Operator role for limited administrative access" +name = "rbac_roles_operator" +nickel_path = ["rbac", "roles", "operator"] +prompt = "Enable Operator Role" +type = "confirm" + +[[elements]] +default = true +help = "Enable Viewer role for read-only access" +name = "rbac_roles_viewer" +nickel_path = ["rbac", "roles", "viewer"] +prompt = "Enable Viewer Role" +type = "confirm" + +[[elements]] +default = false +help = "Allow dynamic role assignment at runtime" +name = "rbac_dynamic_roles" +nickel_path = ["rbac", "dynamic_roles"] +prompt = "Enable Dynamic Roles" +type = "confirm" + +[[elements]] +default = "user" +help = "Default role assigned to new users" +name = "rbac_default_role_name" +nickel_path = ["rbac", "default_role"] +options = ["user", "operator", "viewer"] +prompt = "Default Role for New Users" +type = "select" diff --git a/.typedialog/platform/forms/fragments/control-center/security-section.toml b/.typedialog/platform/forms/fragments/control-center/security-section.toml new file mode 100644 index 0000000..39d3092 --- /dev/null +++ b/.typedialog/platform/forms/fragments/control-center/security-section.toml @@ -0,0 +1,184 @@ +# Control Center Security Configuration Fragment +# JWT, RBAC, MFA, rate limiting + +[[elements]] +border_top = true +border_bottom = false +name = "security_section_header" +title = "πŸ” Security Configuration" +type = "section_header" + +# JWT Configuration +[[elements]] +border_top = false +default = true +help = "Enable JWT authentication" +name = "jwt_enabled" +nickel_path = ["security", "jwt", "enabled"] +prompt = "Enable JWT Authentication" +type = "confirm" + +[[elements]] +condition = "jwt_enabled == true" +default = "control-center" +help = "JWT token issuer identifier" +name = "jwt_issuer" +nickel_path = ["security", "jwt", "issuer"] +prompt = "JWT Issuer" +required = true +type = "text" + +[[elements]] +condition = "jwt_enabled == true" +default = "provisioning" +help = "JWT token audience identifier" +name = "jwt_audience" +nickel_path = ["security", "jwt", "audience"] +prompt = "JWT Audience" +required = true +type = "text" + +[[elements]] +condition = "jwt_enabled == true" +default = 3600 +help = "JWT token expiration time in seconds (range: ${constraint.control_center.jwt.token_expiration.min}-${constraint.control_center.jwt.token_expiration.max})" +max = "${constraint.control_center.jwt.token_expiration.max}" +min = "${constraint.control_center.jwt.token_expiration.min}" +name = "jwt_token_expiration" +nickel_path = ["security", "jwt", "token_expiration"] +prompt = "Token Expiration (seconds)" +type = "number" + +[[elements]] +condition = "jwt_enabled == true" +default = 86400 +help = "JWT refresh token expiration time in seconds (range: ${constraint.control_center.jwt.refresh_expiration.min}-${constraint.control_center.jwt.refresh_expiration.max})" +max = "${constraint.control_center.jwt.refresh_expiration.max}" +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" + +[[elements]] +condition = "jwt_enabled == true" +default = "HS256" +help = "JWT signing method (HS256, RS256, ES256)" +name = "jwt_signing_method" +nickel_path = ["security", "jwt", "signing_method"] +options = ["HS256", "RS256", "ES256"] +prompt = "Signing Method" +type = "select" + +# RBAC Configuration +[[elements]] +default = true +help = "Enable Role-Based Access Control" +name = "rbac_enabled" +nickel_path = ["security", "rbac", "enabled"] +prompt = "Enable RBAC" +type = "confirm" + +[[elements]] +condition = "rbac_enabled == true" +default = true +help = "Enable role hierarchy/inheritance" +name = "rbac_hierarchy" +nickel_path = ["security", "rbac", "hierarchy"] +prompt = "Enable Role Hierarchy" +type = "confirm" + +# MFA Configuration +[[elements]] +default = false +help = "Enable Multi-Factor Authentication" +name = "mfa_enabled" +nickel_path = ["security", "mfa", "enabled"] +prompt = "Enable MFA" +type = "confirm" + +[[elements]] +condition = "mfa_enabled == true" +default = false +help = "Require MFA for all users" +name = "mfa_required" +nickel_path = ["security", "mfa", "required"] +prompt = "Require MFA for All Users" +type = "confirm" + +# Rate Limiting +[[elements]] +default = false +help = "Enable API rate limiting" +name = "rate_limiting_enabled" +nickel_path = ["security", "rate_limiting", "enabled"] +prompt = "Enable Rate Limiting" +type = "confirm" + +[[elements]] +condition = "rate_limiting_enabled == true" +default = 1000 +help = "Maximum API requests per time window (range: ${constraint.control_center.rate_limiting.max_requests.min}-${constraint.control_center.rate_limiting.max_requests.max})" +max = "${constraint.control_center.rate_limiting.max_requests.max}" +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" + +[[elements]] +condition = "rate_limiting_enabled == true" +default = 60 +help = "Time window in seconds (range: ${constraint.control_center.rate_limiting.window_seconds.min}-${constraint.control_center.rate_limiting.window_seconds.max})" +max = "${constraint.control_center.rate_limiting.window_seconds.max}" +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" + +# TLS Configuration +[[elements]] +default = false +help = "Enable TLS/SSL encryption" +name = "tls_enabled" +nickel_path = ["security", "tls", "enabled"] +prompt = "Enable TLS/SSL" +type = "confirm" + +# Session Management +[[elements]] +default = true +help = "Enable session management" +name = "sessions_enabled" +nickel_path = ["security", "sessions", "enabled"] +prompt = "Enable Sessions" +type = "confirm" + +[[elements]] +condition = "sessions_enabled == true" +default = 86400 +help = "Session max age in seconds" +min = 300 +name = "sessions_max_age" +nickel_path = ["security", "sessions", "max_age"] +prompt = "Session Max Age (seconds)" +type = "number" + +[[elements]] +condition = "sessions_enabled == true" +default = true +help = "Set secure flag on session cookies" +name = "sessions_secure" +nickel_path = ["security", "sessions", "secure"] +prompt = "Secure Cookies" +type = "confirm" + +[[elements]] +condition = "sessions_enabled == true" +default = true +help = "Set HttpOnly flag on session cookies" +name = "sessions_http_only" +nickel_path = ["security", "sessions", "http_only"] +prompt = "HttpOnly Cookies" +type = "confirm" diff --git a/.typedialog/platform/forms/fragments/control-center/users-section.toml b/.typedialog/platform/forms/fragments/control-center/users-section.toml new file mode 100644 index 0000000..763b8ee --- /dev/null +++ b/.typedialog/platform/forms/fragments/control-center/users-section.toml @@ -0,0 +1,89 @@ +# Control Center User Management Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "users_section_header" +title = "πŸ‘₯ User Management" +type = "section_header" + +[[elements]] +default = true +help = "Enable user management" +name = "users_enabled" +nickel_path = ["users", "enabled"] +prompt = "Enable User Management" +type = "confirm" + +# User Registration +[[elements]] +condition = "users_enabled == true" +default = true +help = "Enable user self-registration" +name = "users_registration_enabled" +nickel_path = ["users", "registration", "enabled"] +prompt = "Enable User Registration" +type = "confirm" + +[[elements]] +condition = "users_enabled == true && users_registration_enabled == true" +default = false +help = "Require admin approval for new registrations" +name = "users_registration_requires_approval" +nickel_path = ["users", "registration", "requires_approval"] +prompt = "Require Registration Approval" +type = "confirm" + +[[elements]] +condition = "users_enabled == true && users_registration_enabled == true" +default = "user" +help = "Default role for newly registered users" +name = "users_registration_auto_role" +nickel_path = ["users", "registration", "auto_assign_role"] +options = ["user", "operator", "viewer"] +prompt = "Default Registration Role" +type = "select" + +# User Sessions +[[elements]] +condition = "users_enabled == true" +default = 5 +help = "Maximum active sessions per user (range: 1-100)" +max = 100 +min = 1 +name = "users_sessions_max_active" +nickel_path = ["users", "sessions", "max_active"] +prompt = "Max Active Sessions per User" +type = "number" + +[[elements]] +condition = "users_enabled == true" +default = 3600 +help = "Session idle timeout in seconds (range: 300-86400)" +max = 86400 +min = 300 +name = "users_sessions_idle_timeout" +nickel_path = ["users", "sessions", "idle_timeout"] +prompt = "Session Idle Timeout (seconds)" +type = "number" + +[[elements]] +condition = "users_enabled == true" +default = 86400 +help = "Absolute session timeout in seconds (range: 3600-604800)" +max = 604800 +min = 3600 +name = "users_sessions_absolute_timeout" +nickel_path = ["users", "sessions", "absolute_timeout"] +prompt = "Absolute Session Timeout (seconds)" +type = "number" + +# User Audit +[[elements]] +condition = "users_enabled == true" +default = false +help = "Enable audit logging for user actions" +name = "users_audit_enabled" +nickel_path = ["users", "audit_enabled"] +prompt = "Enable User Audit Logging" +type = "confirm" diff --git a/.typedialog/platform/forms/fragments/database-postgres-section.toml b/.typedialog/platform/forms/fragments/database-postgres-section.toml new file mode 100644 index 0000000..f189349 --- /dev/null +++ b/.typedialog/platform/forms/fragments/database-postgres-section.toml @@ -0,0 +1,101 @@ +# PostgreSQL Database Configuration Fragment +# Used by: control-center, installer (when backend = postgresql) + +[[elements]] +border_top = true +border_bottom = false +name = "database_section_header" +title = "πŸ’Ύ PostgreSQL Database Configuration" +type = "section_header" + +[[elements]] +default = "postgresql" +help = "Database backend type" +name = "database_backend" +nickel_path = ["database", "backend"] +prompt = "Database Backend" +type = "text" + +[[elements]] +help = "PostgreSQL connection string or host" +name = "database_postgres_host" +nickel_path = ["database", "host"] +placeholder = "localhost" +prompt = "PostgreSQL Host" +required = true +type = "text" + +[[elements]] +default = 5432 +help = "PostgreSQL port number (range: ${constraint.common.server.port.min}-${constraint.common.server.port.max})" +max = "${constraint.common.server.port.max}" +min = "${constraint.common.server.port.min}" +name = "database_postgres_port" +nickel_path = ["database", "port"] +prompt = "PostgreSQL Port" +type = "number" + +[[elements]] +help = "PostgreSQL database name" +name = "database_postgres_database" +nickel_path = ["database", "database"] +placeholder = "provisioning" +prompt = "Database Name" +required = true +type = "text" + +[[elements]] +help = "PostgreSQL username" +name = "database_postgres_user" +nickel_path = ["database", "user"] +placeholder = "provisioning" +prompt = "Username" +required = true +type = "text" + +[[elements]] +help = "PostgreSQL password (will be stored securely)" +name = "database_postgres_password" +nickel_path = ["database", "password"] +prompt = "Password" +type = "password" + +[[elements]] +default = 10 +help = "Database connection pool size (range: 5-200)" +max = 200 +min = 5 +name = "database_pool_size" +nickel_path = ["database", "pool_size"] +prompt = "Connection Pool Size" +type = "number" + +[[elements]] +default = 30 +help = "Database operation timeout in seconds (range: 10-3600)" +max = 3600 +min = 10 +name = "database_timeout" +nickel_path = ["database", "timeout"] +prompt = "Timeout (seconds)" +type = "number" + +[[elements]] +default = 3 +help = "Number of retry attempts for failed operations (range: 0-10)" +max = 10 +min = 0 +name = "database_retry_attempts" +nickel_path = ["database", "retry_attempts"] +prompt = "Retry Attempts" +type = "number" + +[[elements]] +default = 100 +help = "Delay in milliseconds between retry attempts (range: 1000-60000)" +max = 60000 +min = 1000 +name = "database_retry_delay" +nickel_path = ["database", "retry_delay"] +prompt = "Retry Delay (ms)" +type = "number" diff --git a/.typedialog/platform/forms/fragments/database-rocksdb-section.toml b/.typedialog/platform/forms/fragments/database-rocksdb-section.toml new file mode 100644 index 0000000..7348a6e --- /dev/null +++ b/.typedialog/platform/forms/fragments/database-rocksdb-section.toml @@ -0,0 +1,66 @@ +# RocksDB Database Configuration Fragment +# Used by: control-center, installer (when backend = rocksdb) + +[[elements]] +border_top = true +border_bottom = false +name = "database_section_header" +title = "πŸ’Ύ RocksDB Database Configuration" +type = "section_header" + +[[elements]] +default = "rocksdb" +help = "Database backend type" +name = "database_backend" +nickel_path = ["database", "backend"] +prompt = "Database Backend" +type = "text" + +[[elements]] +default = "/var/lib/provisioning/data" +help = "Path to RocksDB data directory" +name = "database_path" +nickel_path = ["database", "path"] +prompt = "Database Path" +required = true +type = "text" + +[[elements]] +default = 10 +help = "Database connection pool size (range: 1-100)" +max = 100 +min = 1 +name = "database_pool_size" +nickel_path = ["database", "pool_size"] +prompt = "Connection Pool Size" +type = "number" + +[[elements]] +default = 30 +help = "Database operation timeout in seconds (range: 10-3600)" +max = 3600 +min = 10 +name = "database_timeout" +nickel_path = ["database", "timeout"] +prompt = "Timeout (seconds)" +type = "number" + +[[elements]] +default = 3 +help = "Number of retry attempts for failed operations (range: 0-10)" +max = 10 +min = 0 +name = "database_retry_attempts" +nickel_path = ["database", "retry_attempts"] +prompt = "Retry Attempts" +type = "number" + +[[elements]] +default = 100 +help = "Delay in milliseconds between retry attempts (range: 1000-60000)" +max = 60000 +min = 1000 +name = "database_retry_delay" +nickel_path = ["database", "retry_delay"] +prompt = "Retry Delay (ms)" +type = "number" diff --git a/.typedialog/platform/forms/fragments/database-surrealdb-section.toml b/.typedialog/platform/forms/fragments/database-surrealdb-section.toml new file mode 100644 index 0000000..651ef35 --- /dev/null +++ b/.typedialog/platform/forms/fragments/database-surrealdb-section.toml @@ -0,0 +1,81 @@ +# SurrealDB Database Configuration Fragment +# Used by: orchestrator, control-center (when backend = surrealdb) + +[[elements]] +border_top = true +border_bottom = false +name = "database_section_header" +title = "πŸ’Ύ SurrealDB Database Configuration" +type = "section_header" + +[[elements]] +default = "surrealdb" +help = "Database backend type" +name = "database_backend" +nickel_path = ["database", "backend"] +prompt = "Database Backend" +type = "text" + +[[elements]] +help = "SurrealDB server URL (e.g., http://localhost:8000 for embedded)" +name = "database_surrealdb_url" +nickel_path = ["database", "surrealdb_url"] +placeholder = "http://localhost:8000" +prompt = "SurrealDB URL" +type = "text" + +[[elements]] +default = "provisioning" +help = "SurrealDB namespace" +name = "database_surrealdb_namespace" +nickel_path = ["database", "surrealdb_namespace"] +prompt = "Namespace" +type = "text" + +[[elements]] +default = "default" +help = "SurrealDB database name" +name = "database_surrealdb_database" +nickel_path = ["database", "surrealdb_database"] +prompt = "Database" +type = "text" + +[[elements]] +default = 10 +help = "Database connection pool size (range: 1-200)" +max = 200 +min = 1 +name = "database_pool_size" +nickel_path = ["database", "pool_size"] +prompt = "Connection Pool Size" +type = "number" + +[[elements]] +default = 30 +help = "Database operation timeout in seconds (range: 10-3600)" +max = 3600 +min = 10 +name = "database_timeout" +nickel_path = ["database", "timeout"] +prompt = "Timeout (seconds)" +type = "number" + +[[elements]] +default = 3 +help = "Number of retry attempts for failed operations (range: 0-10)" +max = 10 +min = 0 +name = "database_retry_attempts" +nickel_path = ["database", "retry_attempts"] +prompt = "Retry Attempts" +type = "number" + +[[elements]] +default = 100 +help = "Delay in milliseconds between retry attempts (range: 1000-60000)" +max = 60000 +min = 1000 +name = "database_retry_delay" +nickel_path = ["database", "retry_delay"] +prompt = "Retry Delay (ms)" +type = "number" diff --git a/.typedialog/platform/forms/fragments/deployment/database-backend-selection.toml b/.typedialog/platform/forms/fragments/deployment/database-backend-selection.toml new file mode 100644 index 0000000..21dfc67 --- /dev/null +++ b/.typedialog/platform/forms/fragments/deployment/database-backend-selection.toml @@ -0,0 +1,93 @@ +# 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 + +[[elements]] +border_top = true +border_bottom = false +name = "database_backend_selection_header" +title = "πŸ—„οΈ Database Backend Selection" +type = "section_header" + +[[elements]] +default = "rocksdb" +help = "Select the database backend for this service" +name = "database_backend_selection" +nickel_path = ["database", "backend_type"] +options = ["rocksdb", "surrealdb_embedded", "surrealdb_server", "postgresql"] +prompt = "Database Backend" +required = true +type = "select" + +# Backend Descriptions +[[elements]] +condition = "database_backend_selection == 'rocksdb'" +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" +type = "info" +prompt = "RocksDB Info" + +[[elements]] +condition = "database_backend_selection == 'surrealdb_embedded'" +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" +type = "info" +prompt = "SurrealDB Embedded Info" + +[[elements]] +condition = "database_backend_selection == 'surrealdb_server'" +default = false +help = "SurrealDB (Server): External SurrealDB server. Scalable multi-instance, HA ready, suitable for multiuser/enterprise modes." +name = "surrealdb_server_info" +type = "info" +prompt = "SurrealDB Server Info" + +[[elements]] +condition = "database_backend_selection == 'postgresql'" +default = false +help = "PostgreSQL: Traditional RDBMS. Proven stability, full ACID, complex queries, suitable for enterprise with HA via replication." +name = "postgresql_info" +type = "info" +prompt = "PostgreSQL Info" + +# Backend Selection Guidelines +[[elements]] +name = "backend_selection_guide" +type = "section_header" +title = "Backend Selection Guide" +border_top = true +border_bottom = true + +[[elements]] +condition = "deployment_mode == 'solo'" +default = false +help = "Recommended for Solo: RocksDB (simplest) or SurrealDB Embedded (more features, same simplicity)" +name = "solo_recommendation" +type = "info" +prompt = "Solo Recommendation" + +[[elements]] +condition = "deployment_mode == 'multiuser'" +default = false +help = "Recommended for MultiUser: SurrealDB Server (scalable, easy clustering) or PostgreSQL (if you need traditional RDBMS)" +name = "multiuser_recommendation" +type = "info" +prompt = "MultiUser Recommendation" + +[[elements]] +condition = "deployment_mode == 'cicd'" +default = false +help = "Recommended for CI/CD: SurrealDB Embedded (ephemeral, no external deps) or RocksDB (fastest)" +name = "cicd_recommendation" +type = "info" +prompt = "CI/CD Recommendation" + +[[elements]] +condition = "deployment_mode == 'enterprise'" +default = false +help = "Recommended for Enterprise: SurrealDB Server HA (native clustering) or PostgreSQL with replication + external backup service" +name = "enterprise_recommendation" +type = "info" +prompt = "Enterprise Recommendation" diff --git a/.typedialog/platform/forms/fragments/deployment/mode-selection.toml b/.typedialog/platform/forms/fragments/deployment/mode-selection.toml new file mode 100644 index 0000000..73d5e87 --- /dev/null +++ b/.typedialog/platform/forms/fragments/deployment/mode-selection.toml @@ -0,0 +1,95 @@ +# Deployment Mode Selection Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "deployment_mode_section_header" +title = "πŸš€ Deployment Mode" +type = "section_header" + +[[elements]] +default = "solo" +help = "Select deployment mode which determines resource allocation and feature set" +name = "deployment_mode" +nickel_path = ["deployment_mode"] +options = ["solo", "multiuser", "cicd", "enterprise"] +prompt = "Deployment Mode" +required = true +type = "select" + +# Mode Descriptions +[[elements]] +name = "mode_description" +type = "section_header" +title = "Mode Details" +border_top = false +border_bottom = true + +# Solo Mode Info (conditional) +[[elements]] +condition = "deployment_mode == 'solo'" +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" + +# MultiUser Mode Info (conditional) +[[elements]] +condition = "deployment_mode == 'multiuser'" +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" + +# CI/CD Mode Info (conditional) +[[elements]] +condition = "deployment_mode == 'cicd'" +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" + +# Enterprise Mode Info (conditional) +[[elements]] +condition = "deployment_mode == 'enterprise'" +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" + +# Mode-Specific Default Values (informational) +[[elements]] +condition = "deployment_mode == 'solo'" +default = false +help = "Resources: 2 CPU, 4GB RAM | Storage: 50GB | Database: Filesystem or RocksDB | Security: Optional | HA: None" +name = "solo_resources_info" +type = "text" +prompt = "Solo Resources" + +[[elements]] +condition = "deployment_mode == 'multiuser'" +default = false +help = "Resources: 4 CPU, 8GB RAM | Storage: 100GB | Database: PostgreSQL or SurrealDB | Security: RBAC | HA: Optional" +name = "multiuser_resources_info" +type = "text" +prompt = "MultiUser Resources" + +[[elements]] +condition = "deployment_mode == 'cicd'" +default = false +help = "Resources: 8 CPU, 16GB RAM | Storage: 200GB (ephemeral) | Database: Embedded | Security: API tokens | HA: None" +name = "cicd_resources_info" +type = "text" +prompt = "CI/CD Resources" + +[[elements]] +condition = "deployment_mode == 'enterprise'" +default = false +help = "Resources: 16+ CPU, 32+ GB RAM | Storage: 500GB+ | Database: SurrealDB Cluster HA | Security: MFA, Vault | HA: Full clustering" +name = "enterprise_resources_info" +type = "text" +prompt = "Enterprise Resources" diff --git a/.typedialog/platform/forms/fragments/extension-registry/auth.toml b/.typedialog/platform/forms/fragments/extension-registry/auth.toml new file mode 100644 index 0000000..ec5ecb3 --- /dev/null +++ b/.typedialog/platform/forms/fragments/extension-registry/auth.toml @@ -0,0 +1,35 @@ +# Extension Registry Authentication Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "registry_auth_header" +title = "πŸ” Authentication" +type = "section_header" + +[[elements]] +default = "" +help = "OCI registry username (optional)" +name = "registry_oci_username" +nickel_path = ["extension_registry", "oci", "username"] +prompt = "OCI Username" +required = false +type = "text" + +[[elements]] +default = "" +help = "OCI registry password (optional)" +name = "registry_oci_password" +nickel_path = ["extension_registry", "oci", "password"] +prompt = "OCI Password" +required = false +type = "password" + +[[elements]] +default = "" +help = "Gitea API token (optional)" +name = "registry_gitea_token" +nickel_path = ["extension_registry", "gitea", "token"] +prompt = "Gitea Token" +required = false +type = "password" diff --git a/.typedialog/platform/forms/fragments/extension-registry/cache.toml b/.typedialog/platform/forms/fragments/extension-registry/cache.toml new file mode 100644 index 0000000..f13ba30 --- /dev/null +++ b/.typedialog/platform/forms/fragments/extension-registry/cache.toml @@ -0,0 +1,44 @@ +# Extension Registry Cache Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "registry_cache_header" +title = "⚑ Cache Configuration" +type = "section_header" + +[[elements]] +default = 1000 +help = "Maximum cache entries (range: 10-100000)" +max = 100000 +min = 10 +name = "registry_cache_capacity" +nickel_path = ["extension_registry", "cache", "capacity"] +prompt = "Cache Capacity" +type = "number" + +[[elements]] +default = 300 +help = "Cache TTL in seconds (range: 30-3600)" +max = 3600 +min = 30 +name = "registry_cache_ttl" +nickel_path = ["extension_registry", "cache", "ttl"] +prompt = "Cache TTL (seconds)" +type = "number" + +[[elements]] +default = true +help = "Cache metadata responses" +name = "registry_cache_metadata_enabled" +nickel_path = ["extension_registry", "cache", "metadata_cache"] +prompt = "Cache Metadata" +type = "confirm" + +[[elements]] +default = true +help = "Cache list responses" +name = "registry_cache_list_enabled" +nickel_path = ["extension_registry", "cache", "list_cache"] +prompt = "Cache Lists" +type = "confirm" diff --git a/.typedialog/platform/forms/fragments/extension-registry/gitea.toml b/.typedialog/platform/forms/fragments/extension-registry/gitea.toml new file mode 100644 index 0000000..917b0b5 --- /dev/null +++ b/.typedialog/platform/forms/fragments/extension-registry/gitea.toml @@ -0,0 +1,56 @@ +# Extension Registry Gitea Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "registry_gitea_header" +title = "πŸ™ Gitea Configuration" +type = "section_header" + +[[elements]] +default = true +help = "Enable Gitea as extension source" +name = "registry_gitea_enabled" +nickel_path = ["extension_registry", "gitea", "enabled"] +prompt = "Enable Gitea" +type = "confirm" + +[[elements]] +condition = "registry_gitea_enabled == true" +default = "http://localhost:3000" +help = "Gitea server URL" +name = "registry_gitea_url" +nickel_path = ["extension_registry", "gitea", "url"] +prompt = "Gitea URL" +required = true +type = "text" + +[[elements]] +condition = "registry_gitea_enabled == true" +default = "provisioning" +help = "Gitea organization name" +name = "registry_gitea_org" +nickel_path = ["extension_registry", "gitea", "org"] +prompt = "Organization" +required = true +type = "text" + +[[elements]] +condition = "registry_gitea_enabled == true" +default = 60000 +help = "Request timeout in milliseconds" +max = 300000 +min = 5000 +name = "registry_gitea_timeout" +nickel_path = ["extension_registry", "gitea", "timeout"] +prompt = "Timeout (ms)" +type = "number" + +[[elements]] +condition = "registry_gitea_enabled == true" +default = false +help = "Verify SSL certificates" +name = "registry_gitea_verify_ssl" +nickel_path = ["extension_registry", "gitea", "verify_ssl"] +prompt = "Verify SSL" +type = "confirm" diff --git a/.typedialog/platform/forms/fragments/extension-registry/oci.toml b/.typedialog/platform/forms/fragments/extension-registry/oci.toml new file mode 100644 index 0000000..04d72b7 --- /dev/null +++ b/.typedialog/platform/forms/fragments/extension-registry/oci.toml @@ -0,0 +1,56 @@ +# Extension Registry OCI Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "registry_oci_header" +title = "πŸ“¦ OCI Registry Configuration" +type = "section_header" + +[[elements]] +default = false +help = "Enable OCI registry as extension source" +name = "registry_oci_enabled" +nickel_path = ["extension_registry", "oci", "enabled"] +prompt = "Enable OCI Registry" +type = "confirm" + +[[elements]] +condition = "registry_oci_enabled == true" +default = "registry.local:5000" +help = "OCI registry URL" +name = "registry_oci_registry" +nickel_path = ["extension_registry", "oci", "registry"] +prompt = "Registry URL" +required = true +type = "text" + +[[elements]] +condition = "registry_oci_enabled == true" +default = "provisioning" +help = "OCI registry namespace" +name = "registry_oci_namespace" +nickel_path = ["extension_registry", "oci", "namespace"] +prompt = "Namespace" +required = true +type = "text" + +[[elements]] +condition = "registry_oci_enabled == true" +default = 60000 +help = "Request timeout in milliseconds" +max = 300000 +min = 5000 +name = "registry_oci_timeout" +nickel_path = ["extension_registry", "oci", "timeout"] +prompt = "Timeout (ms)" +type = "number" + +[[elements]] +condition = "registry_oci_enabled == true" +default = false +help = "Verify SSL certificates" +name = "registry_oci_verify_ssl" +nickel_path = ["extension_registry", "oci", "verify_ssl"] +prompt = "Verify SSL" +type = "confirm" diff --git a/.typedialog/platform/forms/fragments/extension-registry/server.toml b/.typedialog/platform/forms/fragments/extension-registry/server.toml new file mode 100644 index 0000000..95bdac0 --- /dev/null +++ b/.typedialog/platform/forms/fragments/extension-registry/server.toml @@ -0,0 +1,55 @@ +# Extension Registry Server Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "registry_server_header" +title = "πŸ–₯️ Server Configuration" +type = "section_header" + +[[elements]] +default = "0.0.0.0" +help = "HTTP server bind address" +name = "registry_server_host" +nickel_path = ["extension_registry", "server", "host"] +prompt = "Server Host" +required = true +type = "text" + +[[elements]] +default = 8081 +help = "HTTP server port (range: 1024-65535)" +max = 65535 +min = 1024 +name = "registry_server_port" +nickel_path = ["extension_registry", "server", "port"] +prompt = "Server Port" +required = true +type = "number" + +[[elements]] +default = 4 +help = "Number of HTTP worker threads" +max = 32 +min = 1 +name = "registry_server_workers" +nickel_path = ["extension_registry", "server", "workers"] +prompt = "Worker Threads" +required = true +type = "number" + +[[elements]] +default = false +help = "Enable CORS for cross-origin requests" +name = "registry_server_cors_enabled" +nickel_path = ["extension_registry", "server", "cors_enabled"] +prompt = "Enable CORS" +type = "confirm" + +[[elements]] +default = true +help = "Enable response compression" +name = "registry_server_compression" +nickel_path = ["extension_registry", "server", "compression"] +prompt = "Enable Compression" +type = "confirm" diff --git a/.typedialog/platform/forms/fragments/installer/database-section.toml b/.typedialog/platform/forms/fragments/installer/database-section.toml new file mode 100644 index 0000000..b95a692 --- /dev/null +++ b/.typedialog/platform/forms/fragments/installer/database-section.toml @@ -0,0 +1,244 @@ +# Installer Database Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "database_section_header" +title = "πŸ—„οΈ Database Configuration" +type = "section_header" + +# Database Initialization +[[elements]] +default = true +help = "Automatically initialize databases during installation" +name = "auto_init_database" +nickel_path = ["installer", "database", "auto_init"] +prompt = "Auto-Initialize Database" +type = "confirm" + +[[elements]] +condition = "auto_init_database == true" +default = true +help = "Run migrations automatically during installation" +name = "auto_migrate" +nickel_path = ["installer", "database", "auto_migrate"] +prompt = "Auto-Migrate" +type = "confirm" + +[[elements]] +condition = "auto_init_database == true" +default = true +help = "Create default database schema and tables" +name = "create_schema" +nickel_path = ["installer", "database", "create_schema"] +prompt = "Create Schema" +type = "confirm" + +# Migration Settings +[[elements]] +condition = "auto_migrate == true" +default = "/var/lib/provisioning/migrations" +help = "Directory containing database migration files" +name = "migrations_directory" +nickel_path = ["installer", "database", "migrations", "directory"] +prompt = "Migrations Directory" +type = "text" + +[[elements]] +condition = "auto_migrate == true" +default = "auto" +help = "Migration version strategy" +name = "migration_strategy" +nickel_path = ["installer", "database", "migrations", "strategy"] +options = ["auto", "manual", "sequential"] +prompt = "Migration Strategy" +type = "select" + +[[elements]] +condition = "auto_migrate == true" +default = 300 +help = "Migration timeout in seconds" +min = 30 +name = "migration_timeout_seconds" +nickel_path = ["installer", "database", "migrations", "timeout_seconds"] +prompt = "Migration Timeout (seconds)" +type = "number" + +# Database Backup +[[elements]] +default = true +help = "Create database backup before installation/upgrade" +name = "backup_before_install" +nickel_path = ["installer", "database", "backup", "before_install"] +prompt = "Backup Before Install" +type = "confirm" + +[[elements]] +condition = "backup_before_install == true" +default = "/var/backups/provisioning" +help = "Directory for database backups" +name = "backup_directory" +nickel_path = ["installer", "database", "backup", "directory"] +prompt = "Backup Directory" +type = "text" + +[[elements]] +condition = "backup_before_install == true" +default = "full" +help = "Backup type" +name = "backup_type" +nickel_path = ["installer", "database", "backup", "type"] +options = ["full", "incremental", "differential"] +prompt = "Backup Type" +type = "select" + +[[elements]] +condition = "backup_before_install == true" +default = true +help = "Compress database backups" +name = "compress_backups" +nickel_path = ["installer", "database", "backup", "compress"] +prompt = "Compress Backups" +type = "confirm" + +[[elements]] +condition = "backup_before_install == true" +default = 7 +help = "Backup retention in days" +min = 1 +max = 365 +name = "backup_retention_days" +nickel_path = ["installer", "database", "backup", "retention_days"] +prompt = "Backup Retention (days)" +type = "number" + +# Database Verification +[[elements]] +default = true +help = "Verify database integrity after installation" +name = "verify_database" +nickel_path = ["installer", "database", "verification", "enabled"] +prompt = "Verify Database" +type = "confirm" + +[[elements]] +condition = "verify_database == true" +default = true +help = "Check database consistency" +name = "check_consistency" +nickel_path = ["installer", "database", "verification", "check_consistency"] +prompt = "Check Consistency" +type = "confirm" + +[[elements]] +condition = "verify_database == true" +default = true +help = "Check for missing indices" +name = "check_indices" +nickel_path = ["installer", "database", "verification", "check_indices"] +prompt = "Check Indices" +type = "confirm" + +[[elements]] +condition = "verify_database == true" +default = true +help = "Validate foreign key relationships" +name = "check_foreign_keys" +nickel_path = ["installer", "database", "verification", "check_foreign_keys"] +prompt = "Check Foreign Keys" +type = "confirm" + +# Data Seeding +[[elements]] +default = false +help = "Seed database with sample data" +name = "seed_database" +nickel_path = ["installer", "database", "seeding", "enabled"] +prompt = "Seed Database" +type = "confirm" + +[[elements]] +condition = "seed_database == true" +default = "minimal" +help = "Sample data size" +name = "seed_data_size" +nickel_path = ["installer", "database", "seeding", "data_size"] +options = ["minimal", "standard", "large"] +prompt = "Seed Data Size" +type = "select" + +[[elements]] +condition = "seed_database == true" +default = "seeding-data.sql" +help = "SQL file containing seed data" +name = "seed_data_file" +nickel_path = ["installer", "database", "seeding", "data_file"] +prompt = "Seed Data File" +type = "text" + +# Database Pooling +[[elements]] +default = 10 +help = "Database connection pool size (range: 1-100)" +max = 100 +min = 1 +name = "connection_pool_size" +nickel_path = ["installer", "database", "pool_size"] +prompt = "Connection Pool Size" +type = "number" + +[[elements]] +default = 300 +help = "Connection pool timeout in seconds (range: 10-3600)" +max = 3600 +min = 10 +name = "connection_pool_timeout" +nickel_path = ["installer", "database", "pool_timeout_seconds"] +prompt = "Pool Timeout (seconds)" +type = "number" + +[[elements]] +default = 3600 +help = "Connection idle timeout in seconds (range: 60-14400)" +max = 14400 +min = 60 +name = "connection_idle_timeout" +nickel_path = ["installer", "database", "idle_timeout_seconds"] +prompt = "Idle Timeout (seconds)" +type = "number" + +# Database Optimization +[[elements]] +default = false +help = "Optimize database after installation" +name = "optimize_database" +nickel_path = ["installer", "database", "optimization", "enabled"] +prompt = "Optimize Database" +type = "confirm" + +[[elements]] +condition = "optimize_database == true" +default = true +help = "Analyze query statistics" +name = "analyze_statistics" +nickel_path = ["installer", "database", "optimization", "analyze_statistics"] +prompt = "Analyze Statistics" +type = "confirm" + +[[elements]] +condition = "optimize_database == true" +default = true +help = "Rebuild indices" +name = "rebuild_indices" +nickel_path = ["installer", "database", "optimization", "rebuild_indices"] +prompt = "Rebuild Indices" +type = "confirm" + +[[elements]] +condition = "optimize_database == true" +default = true +help = "Vacuum database (reclaim space)" +name = "vacuum_database" +nickel_path = ["installer", "database", "optimization", "vacuum"] +prompt = "Vacuum Database" +type = "confirm" diff --git a/.typedialog/platform/forms/fragments/installer/ha-section.toml b/.typedialog/platform/forms/fragments/installer/ha-section.toml new file mode 100644 index 0000000..76ad966 --- /dev/null +++ b/.typedialog/platform/forms/fragments/installer/ha-section.toml @@ -0,0 +1,288 @@ +# Installer High Availability Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "ha_section_header" +title = "πŸ”„ High Availability" +type = "section_header" + +# HA Enablement +[[elements]] +default = false +help = "Enable high availability configuration" +name = "ha_enabled" +nickel_path = ["installer", "ha", "enabled"] +prompt = "Enable High Availability" +type = "confirm" + +# Cluster Configuration (conditional on HA enabled) +[[elements]] +condition = "ha_enabled == true" +default = 3 +help = "Number of nodes in the HA cluster" +min = 3 +max = 256 +name = "ha_cluster_size" +nickel_path = ["installer", "ha", "cluster_size"] +prompt = "Cluster Size" +type = "number" + +[[elements]] +condition = "ha_enabled == true" +default = "consul" +help = "Service discovery backend for cluster coordination" +name = "ha_discovery_backend" +nickel_path = ["installer", "ha", "discovery_backend"] +options = ["consul", "etcd", "zookeeper"] +prompt = "Discovery Backend" +type = "select" + +# Cluster Node Configuration (conditional) +[[elements]] +condition = "ha_enabled == true" +default = "replica" +help = "Role of this node in the cluster" +name = "ha_node_role" +nickel_path = ["installer", "ha", "node_role"] +options = ["primary", "replica", "observer"] +prompt = "Node Role" +type = "select" + +[[elements]] +condition = "ha_enabled == true" +default = "" +help = "Comma-separated list of other cluster node addresses" +name = "ha_cluster_nodes" +nickel_path = ["installer", "ha", "cluster_nodes"] +prompt = "Cluster Nodes" +type = "text" + +# Replication Configuration +[[elements]] +condition = "ha_enabled == true" +default = true +help = "Enable database replication between cluster nodes" +name = "ha_db_replication_enabled" +nickel_path = ["installer", "ha", "database", "replication_enabled"] +prompt = "Enable DB Replication" +type = "confirm" + +[[elements]] +condition = "ha_db_replication_enabled == true" +default = "synchronous" +help = "Database replication mode" +name = "ha_db_replication_mode" +nickel_path = ["installer", "ha", "database", "replication_mode"] +options = ["synchronous", "asynchronous", "semi_synchronous"] +prompt = "DB Replication Mode" +type = "select" + +[[elements]] +condition = "ha_enabled == true && ha_db_replication_enabled == true" +default = 3 +help = "Minimum quorum size for write operations (range: 1-256)" +max = 256 +min = 1 +name = "ha_db_quorum_size" +nickel_path = ["installer", "ha", "database", "quorum_size"] +prompt = "DB Quorum Size" +type = "number" + +# Health Checks +[[elements]] +condition = "ha_enabled == true" +default = true +help = "Enable automated health checks for cluster nodes" +name = "ha_health_checks_enabled" +nickel_path = ["installer", "ha", "health_checks", "enabled"] +prompt = "Enable Health Checks" +type = "confirm" + +[[elements]] +condition = "ha_health_checks_enabled == true" +default = 10 +help = "Health check interval in seconds" +min = 1 +max = 120 +name = "ha_health_check_interval" +nickel_path = ["installer", "ha", "health_checks", "interval_seconds"] +prompt = "Health Check Interval (seconds)" +type = "number" + +[[elements]] +condition = "ha_health_checks_enabled == true" +default = 30000 +help = "Health check timeout in milliseconds" +min = 1000 +max = 300000 +name = "ha_health_check_timeout" +nickel_path = ["installer", "ha", "health_checks", "timeout_ms"] +prompt = "Health Check Timeout (ms)" +type = "number" + +[[elements]] +condition = "ha_health_checks_enabled == true" +default = 3 +help = "Number of failed checks before marking node as unhealthy" +min = 1 +max = 10 +name = "ha_health_check_failure_threshold" +nickel_path = ["installer", "ha", "health_checks", "failure_threshold"] +prompt = "Failure Threshold" +type = "number" + +# Failover Configuration +[[elements]] +condition = "ha_enabled == true" +default = true +help = "Enable automatic failover to replica nodes" +name = "ha_failover_enabled" +nickel_path = ["installer", "ha", "failover", "enabled"] +prompt = "Enable Failover" +type = "confirm" + +[[elements]] +condition = "ha_failover_enabled == true" +default = "automatic" +help = "Failover strategy" +name = "ha_failover_strategy" +nickel_path = ["installer", "ha", "failover", "strategy"] +options = ["automatic", "manual", "priority_based"] +prompt = "Failover Strategy" +type = "select" + +[[elements]] +condition = "ha_failover_enabled == true" +default = 60 +help = "Failover delay in seconds (wait before failing over)" +min = 0 +max = 600 +name = "ha_failover_delay" +nickel_path = ["installer", "ha", "failover", "delay_seconds"] +prompt = "Failover Delay (seconds)" +type = "number" + +[[elements]] +condition = "ha_failover_enabled == true && ha_failover_strategy == 'priority_based'" +default = 100 +help = "Priority value for node selection in failover (higher = higher priority)" +min = 0 +max = 1000 +name = "ha_node_priority" +nickel_path = ["installer", "ha", "failover", "node_priority"] +prompt = "Node Priority" +type = "number" + +# Split Brain Prevention +[[elements]] +condition = "ha_enabled == true" +default = true +help = "Enable split-brain detection and prevention" +name = "ha_split_brain_enabled" +nickel_path = ["installer", "ha", "split_brain", "enabled"] +prompt = "Enable Split-Brain Prevention" +type = "confirm" + +[[elements]] +condition = "ha_split_brain_enabled == true" +default = 30 +help = "Timeout for detecting split-brain in seconds" +min = 5 +max = 300 +name = "ha_split_brain_timeout" +nickel_path = ["installer", "ha", "split_brain", "timeout_seconds"] +prompt = "Split-Brain Timeout (seconds)" +type = "number" + +[[elements]] +condition = "ha_split_brain_enabled == true" +default = "quorum_based" +help = "Split-brain resolution strategy" +name = "ha_split_brain_strategy" +nickel_path = ["installer", "ha", "split_brain", "strategy"] +options = ["quorum_based", "majority_wins", "freeze"] +prompt = "Split-Brain Strategy" +type = "select" + +# Backup and Recovery +[[elements]] +condition = "ha_enabled == true" +default = true +help = "Enable automated cluster state backups" +name = "ha_backup_enabled" +nickel_path = ["installer", "ha", "backup", "enabled"] +prompt = "Enable Backups" +type = "confirm" + +[[elements]] +condition = "ha_backup_enabled == true" +default = 3600 +help = "Backup interval in seconds (default: 1 hour, range: 300-86400)" +max = 86400 +min = 300 +name = "ha_backup_interval" +nickel_path = ["installer", "ha", "backup", "interval_seconds"] +prompt = "Backup Interval (seconds)" +type = "number" + +[[elements]] +condition = "ha_backup_enabled == true" +default = 7 +help = "Backup retention in days" +min = 1 +max = 365 +name = "ha_backup_retention_days" +nickel_path = ["installer", "ha", "backup", "retention_days"] +prompt = "Backup Retention (days)" +type = "number" + +[[elements]] +condition = "ha_backup_enabled == true" +default = "/var/backups/provisioning-ha" +help = "Directory for HA cluster backups" +name = "ha_backup_directory" +nickel_path = ["installer", "ha", "backup", "directory"] +prompt = "Backup Directory" +type = "text" + +# Load Distribution +[[elements]] +condition = "ha_enabled == true" +default = true +help = "Enable load distribution across cluster nodes" +name = "ha_load_distribution_enabled" +nickel_path = ["installer", "ha", "load_distribution", "enabled"] +prompt = "Enable Load Distribution" +type = "confirm" + +[[elements]] +condition = "ha_load_distribution_enabled == true" +default = "round_robin" +help = "Load distribution algorithm" +name = "ha_load_distribution_algorithm" +nickel_path = ["installer", "ha", "load_distribution", "algorithm"] +options = ["round_robin", "least_connections", "weighted", "ip_hash"] +prompt = "Load Distribution Algorithm" +type = "select" + +# Metrics and Monitoring +[[elements]] +condition = "ha_enabled == true" +default = true +help = "Enable detailed HA metrics collection" +name = "ha_metrics_enabled" +nickel_path = ["installer", "ha", "metrics", "enabled"] +prompt = "Enable Metrics" +type = "confirm" + +[[elements]] +condition = "ha_metrics_enabled == true" +default = 60 +help = "Metrics collection interval in seconds (range: 5-300)" +max = 300 +min = 5 +name = "ha_metrics_interval" +nickel_path = ["installer", "ha", "metrics", "interval_seconds"] +prompt = "Metrics Interval (seconds)" +type = "number" diff --git a/.typedialog/platform/forms/fragments/installer/installation-section.toml b/.typedialog/platform/forms/fragments/installer/installation-section.toml new file mode 100644 index 0000000..33ade42 --- /dev/null +++ b/.typedialog/platform/forms/fragments/installer/installation-section.toml @@ -0,0 +1,234 @@ +# Installer Installation Strategy Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "installation_section_header" +title = "πŸ”§ Installation Strategy" +type = "section_header" + +# Installation Mode +[[elements]] +default = "interactive" +help = "Installation mode and UI" +name = "installation_mode" +nickel_path = ["installer", "installation", "mode"] +options = ["interactive", "unattended", "api"] +prompt = "Installation Mode" +type = "select" + +# Parallel Service Installation +[[elements]] +default = 1 +help = "Number of services to install in parallel (range: 1-10, 1 = sequential)" +max = 10 +min = 1 +name = "parallel_services" +nickel_path = ["installer", "installation", "parallel_services"] +prompt = "Parallel Services" +type = "number" + +# Installation Timeout +[[elements]] +default = 1800 +help = "Installation timeout in seconds (range: 0-14400, 0 = no timeout)" +max = 14400 +min = 0 +name = "installation_timeout_seconds" +nickel_path = ["installer", "installation", "timeout_seconds"] +prompt = "Installation Timeout (seconds)" +type = "number" + +# Rollback Strategy +[[elements]] +default = true +help = "Automatically rollback on installation failure" +name = "rollback_on_failure" +nickel_path = ["installer", "installation", "rollback_on_failure"] +prompt = "Rollback on Failure" +type = "confirm" + +[[elements]] +condition = "rollback_on_failure == true" +default = "automatic" +help = "Rollback strategy when failure occurs" +name = "rollback_strategy" +nickel_path = ["installer", "installation", "rollback_strategy"] +options = ["automatic", "manual", "snapshot"] +prompt = "Rollback Strategy" +type = "select" + +[[elements]] +condition = "rollback_on_failure == true && rollback_strategy == 'snapshot'" +default = true +help = "Create system snapshot before installation for rollback" +name = "create_pre_install_snapshot" +nickel_path = ["installer", "installation", "create_snapshot"] +prompt = "Create Pre-Install Snapshot" +type = "confirm" + +# Installation Logging +[[elements]] +default = "info" +help = "Installation logging verbosity" +name = "log_level" +nickel_path = ["installer", "installation", "log_level"] +options = ["debug", "info", "warn", "error"] +prompt = "Log Level" +type = "select" + +[[elements]] +default = "/var/log/provisioning-installer" +help = "Directory for installation logs" +name = "log_directory" +nickel_path = ["installer", "installation", "log_directory"] +prompt = "Log Directory" +type = "text" + +[[elements]] +default = true +help = "Write installation logs to file" +name = "write_logs_to_file" +nickel_path = ["installer", "installation", "write_to_file"] +prompt = "Write Logs to File" +type = "confirm" + +[[elements]] +default = false +help = "Upload installation logs to remote server" +name = "upload_logs" +nickel_path = ["installer", "installation", "upload_logs", "enabled"] +prompt = "Upload Logs" +type = "confirm" + +[[elements]] +condition = "upload_logs == true" +default = "" +help = "Remote log server URL" +name = "log_server_url" +nickel_path = ["installer", "installation", "upload_logs", "server_url"] +prompt = "Log Server URL" +required = true +type = "text" + +# Artifact Handling +[[elements]] +default = false +help = "Keep temporary artifacts after installation completes" +name = "keep_artifacts" +nickel_path = ["installer", "installation", "keep_artifacts"] +prompt = "Keep Artifacts" +type = "confirm" + +[[elements]] +condition = "keep_artifacts == true" +default = "/var/tmp/provisioning-install-artifacts" +help = "Directory for keeping installation artifacts" +name = "artifacts_directory" +nickel_path = ["installer", "installation", "artifacts_directory"] +prompt = "Artifacts Directory" +type = "text" + +# Installation Hooks +[[elements]] +default = false +help = "Execute custom scripts during installation" +name = "enable_hooks" +nickel_path = ["installer", "installation", "hooks", "enabled"] +prompt = "Enable Installation Hooks" +type = "confirm" + +[[elements]] +condition = "enable_hooks == true" +default = "" +help = "Script to run before installation starts" +name = "pre_install_hook" +nickel_path = ["installer", "installation", "hooks", "pre_install_script"] +prompt = "Pre-Install Hook Script" +type = "text" + +[[elements]] +condition = "enable_hooks == true" +default = "" +help = "Script to run after installation completes successfully" +name = "post_install_hook" +nickel_path = ["installer", "installation", "hooks", "post_install_script"] +prompt = "Post-Install Hook Script" +type = "text" + +[[elements]] +condition = "enable_hooks == true" +default = "" +help = "Script to run on installation failure" +name = "on_failure_hook" +nickel_path = ["installer", "installation", "hooks", "on_failure_script"] +prompt = "On-Failure Hook Script" +type = "text" + +# Validation After Installation +[[elements]] +default = true +help = "Validate installation was successful" +name = "validate_installation" +nickel_path = ["installer", "installation", "validation", "enabled"] +prompt = "Validate Installation" +type = "confirm" + +[[elements]] +condition = "validate_installation == true" +default = 30000 +help = "Installation validation timeout in milliseconds (range: 5000-300000)" +max = 300000 +min = 5000 +name = "validation_timeout" +nickel_path = ["installer", "installation", "validation", "timeout_ms"] +prompt = "Validation Timeout (ms)" +type = "number" + +[[elements]] +condition = "validate_installation == true" +default = true +help = "Check all services are running" +name = "validate_services_running" +nickel_path = ["installer", "installation", "validation", "services_running"] +prompt = "Validate Services Running" +type = "confirm" + +[[elements]] +condition = "validate_installation == true" +default = true +help = "Validate network connectivity" +name = "validate_connectivity" +nickel_path = ["installer", "installation", "validation", "connectivity"] +prompt = "Validate Connectivity" +type = "confirm" + +# Auto-Recovery +[[elements]] +default = false +help = "Enable automatic recovery if services fail after installation" +name = "auto_recovery_enabled" +nickel_path = ["installer", "installation", "auto_recovery", "enabled"] +prompt = "Enable Auto-Recovery" +type = "confirm" + +[[elements]] +condition = "auto_recovery_enabled == true" +default = 3 +help = "Maximum number of recovery attempts" +min = 1 +max = 10 +name = "auto_recovery_max_attempts" +nickel_path = ["installer", "installation", "auto_recovery", "max_attempts"] +prompt = "Max Recovery Attempts" +type = "number" + +[[elements]] +condition = "auto_recovery_enabled == true" +default = 30 +help = "Delay in seconds before attempting recovery" +min = 5 +name = "auto_recovery_delay_seconds" +nickel_path = ["installer", "installation", "auto_recovery", "delay_seconds"] +prompt = "Recovery Delay (seconds)" +type = "number" diff --git a/.typedialog/platform/forms/fragments/installer/networking-section.toml b/.typedialog/platform/forms/fragments/installer/networking-section.toml new file mode 100644 index 0000000..477bbec --- /dev/null +++ b/.typedialog/platform/forms/fragments/installer/networking-section.toml @@ -0,0 +1,285 @@ +# Installer Networking Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "installer_networking_section_header" +title = "🌐 Networking Configuration" +type = "section_header" + +# Network Interface Configuration +[[elements]] +default = "0.0.0.0" +help = "Bind address for all services (0.0.0.0 = listen on all interfaces)" +name = "bind_address" +nickel_path = ["installer", "networking", "bind_address"] +prompt = "Bind Address" +required = true +type = "text" + +[[elements]] +default = "provisioning.local" +help = "Primary hostname for services" +name = "primary_hostname" +nickel_path = ["installer", "networking", "primary_hostname"] +prompt = "Primary Hostname" +required = true +type = "text" + +[[elements]] +default = "" +help = "Additional hostnames/aliases (comma-separated)" +name = "additional_hostnames" +nickel_path = ["installer", "networking", "additional_hostnames"] +prompt = "Additional Hostnames" +type = "text" + +# DNS Configuration +[[elements]] +default = true +help = "Configure DNS for provisioning services" +name = "configure_dns" +nickel_path = ["installer", "networking", "dns", "configure"] +prompt = "Configure DNS" +type = "confirm" + +[[elements]] +condition = "configure_dns == true" +default = "127.0.0.1" +help = "DNS server address" +name = "dns_server" +nickel_path = ["installer", "networking", "dns", "server"] +prompt = "DNS Server" +type = "text" + +[[elements]] +condition = "configure_dns == true" +default = 53 +help = "DNS server port" +min = 1 +max = 65535 +name = "dns_port" +nickel_path = ["installer", "networking", "dns", "port"] +prompt = "DNS Port" +type = "number" + +# TLS/HTTPS Configuration +[[elements]] +default = false +help = "Enable TLS/HTTPS for service communication" +name = "enable_tls" +nickel_path = ["installer", "networking", "tls", "enabled"] +prompt = "Enable TLS" +type = "confirm" + +[[elements]] +condition = "enable_tls == true" +default = "self_signed" +help = "TLS certificate source" +name = "tls_certificate_source" +nickel_path = ["installer", "networking", "tls", "certificate_source"] +options = ["self_signed", "letsencrypt", "vault", "provided"] +prompt = "TLS Certificate Source" +type = "select" + +[[elements]] +condition = "enable_tls == true && tls_certificate_source == 'letsencrypt'" +default = "" +help = "Let's Encrypt email for certificate registration" +name = "letsencrypt_email" +nickel_path = ["installer", "networking", "tls", "letsencrypt_email"] +prompt = "Let's Encrypt Email" +required = true +type = "text" + +[[elements]] +condition = "enable_tls == true && tls_certificate_source == 'provided'" +default = "/etc/provisioning/certs/server.crt" +help = "Path to provided certificate file" +name = "tls_certificate_path" +nickel_path = ["installer", "networking", "tls", "certificate_path"] +prompt = "Certificate Path" +type = "text" + +[[elements]] +condition = "enable_tls == true && tls_certificate_source == 'provided'" +default = "/etc/provisioning/certs/server.key" +help = "Path to provided private key file" +name = "tls_key_path" +nickel_path = ["installer", "networking", "tls", "key_path"] +prompt = "Private Key Path" +type = "text" + +# Firewall Configuration +[[elements]] +default = true +help = "Configure firewall rules for provisioning services" +name = "configure_firewall" +nickel_path = ["installer", "networking", "firewall", "configure"] +prompt = "Configure Firewall" +type = "confirm" + +[[elements]] +condition = "configure_firewall == true" +default = "iptables" +help = "Firewall backend" +name = "firewall_backend" +nickel_path = ["installer", "networking", "firewall", "backend"] +options = ["iptables", "firewalld", "ufw"] +prompt = "Firewall Backend" +type = "select" + +[[elements]] +condition = "configure_firewall == true" +default = true +help = "Enable inbound rate limiting" +name = "firewall_rate_limit_enabled" +nickel_path = ["installer", "networking", "firewall", "rate_limiting", "enabled"] +prompt = "Enable Rate Limiting" +type = "confirm" + +[[elements]] +condition = "firewall_rate_limit_enabled == true" +default = 100 +help = "Maximum requests per minute per IP" +min = 1 +name = "firewall_rate_limit_rpm" +nickel_path = ["installer", "networking", "firewall", "rate_limiting", "requests_per_minute"] +prompt = "Rate Limit (req/min)" +type = "number" + +# Load Balancer Configuration +[[elements]] +default = false +help = "Install and configure load balancer" +name = "install_load_balancer" +nickel_path = ["installer", "networking", "load_balancer", "enabled"] +prompt = "Install Load Balancer" +type = "confirm" + +[[elements]] +condition = "install_load_balancer == true" +default = "nginx" +help = "Load balancer software" +name = "load_balancer_type" +nickel_path = ["installer", "networking", "load_balancer", "type"] +options = ["nginx", "haproxy", "traefik"] +prompt = "Load Balancer Type" +type = "select" + +[[elements]] +condition = "install_load_balancer == true" +default = 80 +help = "Load balancer HTTP port (range: ${constraint.common.server.port.min}-${constraint.common.server.port.max})" +max = "${constraint.common.server.port.max}" +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" + +[[elements]] +condition = "install_load_balancer == true" +default = 443 +help = "Load balancer HTTPS port (range: ${constraint.common.server.port.min}-${constraint.common.server.port.max})" +max = "${constraint.common.server.port.max}" +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" + +[[elements]] +condition = "install_load_balancer == true" +default = "round_robin" +help = "Load balancing algorithm" +name = "load_balancer_algorithm" +nickel_path = ["installer", "networking", "load_balancer", "algorithm"] +options = ["round_robin", "least_connections", "ip_hash", "weighted"] +prompt = "Load Balancing Algorithm" +type = "select" + +# Ingress Configuration (for Kubernetes) +[[elements]] +default = false +help = "Configure Kubernetes Ingress" +name = "configure_ingress" +nickel_path = ["installer", "networking", "ingress", "configure"] +prompt = "Configure Ingress" +type = "confirm" + +[[elements]] +condition = "configure_ingress == true" +default = "nginx" +help = "Ingress controller type" +name = "ingress_controller" +nickel_path = ["installer", "networking", "ingress", "controller"] +options = ["nginx", "istio", "traefik"] +prompt = "Ingress Controller" +type = "select" + +[[elements]] +condition = "configure_ingress == true" +default = "" +help = "Ingress domain name" +name = "ingress_domain" +nickel_path = ["installer", "networking", "ingress", "domain"] +prompt = "Ingress Domain" +required = true +type = "text" + +# Proxy Configuration +[[elements]] +default = false +help = "Configure HTTP proxy for outbound connections" +name = "enable_http_proxy" +nickel_path = ["installer", "networking", "proxy", "enabled"] +prompt = "Enable HTTP Proxy" +type = "confirm" + +[[elements]] +condition = "enable_http_proxy == true" +default = "" +help = "HTTP proxy URL (e.g., http://proxy.example.com:3128)" +name = "http_proxy_url" +nickel_path = ["installer", "networking", "proxy", "http_url"] +prompt = "HTTP Proxy URL" +required = true +type = "text" + +[[elements]] +condition = "enable_http_proxy == true" +default = "" +help = "HTTPS proxy URL" +name = "https_proxy_url" +nickel_path = ["installer", "networking", "proxy", "https_url"] +prompt = "HTTPS Proxy URL" +type = "text" + +[[elements]] +condition = "enable_http_proxy == true" +default = "" +help = "No proxy list (hosts to bypass proxy, comma-separated)" +name = "no_proxy_list" +nickel_path = ["installer", "networking", "proxy", "no_proxy"] +prompt = "No Proxy List" +type = "text" + +# Network Monitoring +[[elements]] +default = false +help = "Enable network traffic monitoring" +name = "enable_traffic_monitoring" +nickel_path = ["installer", "networking", "monitoring", "enabled"] +prompt = "Enable Traffic Monitoring" +type = "confirm" + +[[elements]] +condition = "enable_traffic_monitoring == true" +default = 60 +help = "Traffic monitoring interval in seconds" +min = 5 +name = "traffic_monitoring_interval" +nickel_path = ["installer", "networking", "monitoring", "interval_seconds"] +prompt = "Monitoring Interval (seconds)" +type = "number" diff --git a/.typedialog/platform/forms/fragments/installer/post-install-section.toml b/.typedialog/platform/forms/fragments/installer/post-install-section.toml new file mode 100644 index 0000000..c097d76 --- /dev/null +++ b/.typedialog/platform/forms/fragments/installer/post-install-section.toml @@ -0,0 +1,317 @@ +# Installer Post-Installation Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "post_install_section_header" +title = "✨ Post-Installation" +type = "section_header" + +# Post-Installation Tasks +[[elements]] +default = true +help = "Execute post-installation tasks and configuration" +name = "run_post_install_tasks" +nickel_path = ["installer", "post_install", "enabled"] +prompt = "Run Post-Install Tasks" +type = "confirm" + +# Service Configuration +[[elements]] +condition = "run_post_install_tasks == true" +default = true +help = "Configure default admin user and initial policies" +name = "configure_defaults" +nickel_path = ["installer", "post_install", "configure_defaults"] +prompt = "Configure Defaults" +type = "confirm" + +[[elements]] +condition = "run_post_install_tasks == true && configure_defaults == true" +default = "admin" +help = "Default admin username" +name = "default_admin_user" +nickel_path = ["installer", "post_install", "default_admin_user"] +prompt = "Default Admin User" +type = "text" + +[[elements]] +condition = "run_post_install_tasks == true && configure_defaults == true" +default = "" +help = "Default admin password (leave empty to auto-generate)" +name = "default_admin_password" +nickel_path = ["installer", "post_install", "default_admin_password"] +prompt = "Default Admin Password" +type = "password" + +[[elements]] +condition = "run_post_install_tasks == true && configure_defaults == true" +default = "" +help = "Default admin email address" +name = "default_admin_email" +nickel_path = ["installer", "post_install", "default_admin_email"] +prompt = "Default Admin Email" +type = "text" + +# Initial Configuration +[[elements]] +condition = "run_post_install_tasks == true" +default = true +help = "Import initial workspace configuration" +name = "import_workspace_config" +nickel_path = ["installer", "post_install", "import_workspace_config"] +prompt = "Import Workspace Config" +type = "confirm" + +[[elements]] +condition = "import_workspace_config == true" +default = "/etc/provisioning/workspace-config.yaml" +help = "Path to workspace configuration file" +name = "workspace_config_path" +nickel_path = ["installer", "post_install", "workspace_config_path"] +prompt = "Workspace Config Path" +type = "text" + +# Extension Loading +[[elements]] +condition = "run_post_install_tasks == true" +default = false +help = "Load extensions from registry after installation" +name = "load_extensions_post_install" +nickel_path = ["installer", "post_install", "load_extensions"] +prompt = "Load Extensions" +type = "confirm" + +[[elements]] +condition = "load_extensions_post_install == true" +default = "" +help = "Comma-separated list of extension names to load" +name = "extensions_to_load" +nickel_path = ["installer", "post_install", "extensions_to_load"] +prompt = "Extensions to Load" +type = "text" + +# API Setup +[[elements]] +condition = "run_post_install_tasks == true" +default = false +help = "Configure API tokens and authentication" +name = "setup_api_auth" +nickel_path = ["installer", "post_install", "setup_api_auth"] +prompt = "Setup API Authentication" +type = "confirm" + +[[elements]] +condition = "setup_api_auth == true" +default = "jwt" +help = "API authentication method" +name = "api_auth_method" +nickel_path = ["installer", "post_install", "api_auth_method"] +options = ["jwt", "oauth2", "api_key"] +prompt = "API Auth Method" +type = "select" + +[[elements]] +condition = "setup_api_auth == true && api_auth_method == 'jwt'" +default = "" +help = "JWT issuer URL" +name = "jwt_issuer" +nickel_path = ["installer", "post_install", "jwt_issuer"] +prompt = "JWT Issuer" +type = "text" + +# Verification Tasks +[[elements]] +condition = "run_post_install_tasks == true" +default = true +help = "Run verification tests after installation" +name = "run_verification_tests" +nickel_path = ["installer", "post_install", "verification", "enabled"] +prompt = "Run Verification Tests" +type = "confirm" + +[[elements]] +condition = "run_verification_tests == true" +default = 300 +help = "Verification test timeout in seconds (range: 30-3600)" +max = 3600 +min = 30 +name = "verification_timeout" +nickel_path = ["installer", "post_install", "verification", "timeout_seconds"] +prompt = "Verification Timeout (seconds)" +type = "number" + +[[elements]] +condition = "run_verification_tests == true" +default = true +help = "Test API connectivity" +name = "test_api_connectivity" +nickel_path = ["installer", "post_install", "verification", "test_api_connectivity"] +prompt = "Test API Connectivity" +type = "confirm" + +[[elements]] +condition = "run_verification_tests == true" +default = true +help = "Test database connectivity" +name = "test_database_connectivity" +nickel_path = ["installer", "post_install", "verification", "test_database_connectivity"] +prompt = "Test Database Connectivity" +type = "confirm" + +[[elements]] +condition = "run_verification_tests == true" +default = true +help = "Test service health checks" +name = "test_service_health" +nickel_path = ["installer", "post_install", "verification", "test_service_health"] +prompt = "Test Service Health" +type = "confirm" + +[[elements]] +condition = "run_verification_tests == true" +default = false +help = "Run performance benchmarks" +name = "run_benchmarks" +nickel_path = ["installer", "post_install", "verification", "run_benchmarks"] +prompt = "Run Benchmarks" +type = "confirm" + +# Notification and Reporting +[[elements]] +condition = "run_post_install_tasks == true" +default = false +help = "Send installation completion notification" +name = "send_notification" +nickel_path = ["installer", "post_install", "notification", "enabled"] +prompt = "Send Notification" +type = "confirm" + +[[elements]] +condition = "send_notification == true" +default = "email" +help = "Notification method" +name = "notification_method" +nickel_path = ["installer", "post_install", "notification", "method"] +options = ["email", "webhook", "slack", "teams"] +prompt = "Notification Method" +type = "select" + +[[elements]] +condition = "send_notification == true && notification_method == 'email'" +default = "" +help = "Email address for completion notification" +name = "notification_email" +nickel_path = ["installer", "post_install", "notification", "email_address"] +prompt = "Notification Email" +type = "text" + +[[elements]] +condition = "send_notification == true && notification_method == 'webhook'" +default = "" +help = "Webhook URL for completion notification" +name = "notification_webhook_url" +nickel_path = ["installer", "post_install", "notification", "webhook_url"] +prompt = "Webhook URL" +type = "text" + +[[elements]] +condition = "send_notification == true && notification_method == 'slack'" +default = "" +help = "Slack webhook URL" +name = "notification_slack_webhook" +nickel_path = ["installer", "post_install", "notification", "slack_webhook_url"] +prompt = "Slack Webhook URL" +type = "password" + +[[elements]] +condition = "send_notification == true && notification_method == 'teams'" +default = "" +help = "Microsoft Teams webhook URL" +name = "notification_teams_webhook" +nickel_path = ["installer", "post_install", "notification", "teams_webhook_url"] +prompt = "Teams Webhook URL" +type = "password" + +# Documentation and Access Information +[[elements]] +condition = "run_post_install_tasks == true" +default = true +help = "Generate installation access information and documentation" +name = "generate_access_info" +nickel_path = ["installer", "post_install", "generate_access_info"] +prompt = "Generate Access Info" +type = "confirm" + +[[elements]] +condition = "generate_access_info == true" +default = "/var/provisioning/install-info.md" +help = "Path to save installation access information" +name = "access_info_path" +nickel_path = ["installer", "post_install", "access_info_path"] +prompt = "Access Info Path" +type = "text" + +[[elements]] +condition = "run_post_install_tasks == true" +default = false +help = "Create compressed archive of installation logs and configs" +name = "create_archive" +nickel_path = ["installer", "post_install", "create_archive"] +prompt = "Create Archive" +type = "confirm" + +[[elements]] +condition = "create_archive == true" +default = "/var/backups/provisioning-install-archive.tar.gz" +help = "Path for installation archive" +name = "archive_path" +nickel_path = ["installer", "post_install", "archive_path"] +prompt = "Archive Path" +type = "text" + +# Cleanup Tasks +[[elements]] +condition = "run_post_install_tasks == true" +default = true +help = "Clean up temporary installation files" +name = "cleanup_temp_files" +nickel_path = ["installer", "post_install", "cleanup", "remove_temp_files"] +prompt = "Cleanup Temp Files" +type = "confirm" + +[[elements]] +condition = "run_post_install_tasks == true" +default = false +help = "Remove installation artifacts (logs, scripts)" +name = "cleanup_artifacts" +nickel_path = ["installer", "post_install", "cleanup", "remove_artifacts"] +prompt = "Cleanup Artifacts" +type = "confirm" + +[[elements]] +condition = "run_post_install_tasks == true" +default = false +help = "Run security hardening after installation" +name = "run_security_hardening" +nickel_path = ["installer", "post_install", "security_hardening", "enabled"] +prompt = "Run Security Hardening" +type = "confirm" + +[[elements]] +condition = "run_security_hardening == true" +default = true +help = "Disable unnecessary services" +name = "disable_unnecessary_services" +nickel_path = ["installer", "post_install", "security_hardening", "disable_unnecessary_services"] +prompt = "Disable Unnecessary Services" +type = "confirm" + +[[elements]] +condition = "run_security_hardening == true" +default = true +help = "Apply security patches" +name = "apply_security_patches" +nickel_path = ["installer", "post_install", "security_hardening", "apply_patches"] +prompt = "Apply Security Patches" +type = "confirm" diff --git a/.typedialog/platform/forms/fragments/installer/preflight-section.toml b/.typedialog/platform/forms/fragments/installer/preflight-section.toml new file mode 100644 index 0000000..d70cc95 --- /dev/null +++ b/.typedialog/platform/forms/fragments/installer/preflight-section.toml @@ -0,0 +1,203 @@ +# Installer Preflight Checks Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "preflight_section_header" +title = "βœ… Preflight Checks" +type = "section_header" + +# Disk Space Check +[[elements]] +default = true +help = "Validate sufficient disk space before installation" +name = "check_disk_space" +nickel_path = ["installer", "preflight", "disk_space_check", "enabled"] +prompt = "Check Disk Space" +type = "confirm" + +[[elements]] +condition = "check_disk_space == true" +default = 50 +help = "Minimum required disk space in GB (range: 1-10000)" +max = 10000 +min = 1 +name = "min_disk_gb" +nickel_path = ["installer", "preflight", "disk_space_check", "min_disk_gb"] +prompt = "Min Disk Space (GB)" +type = "number" + +# Memory Check +[[elements]] +default = true +help = "Validate sufficient RAM before installation" +name = "check_memory" +nickel_path = ["installer", "preflight", "memory_check", "enabled"] +prompt = "Check Memory" +type = "confirm" + +[[elements]] +condition = "check_memory == true" +default = 4 +help = "Minimum required RAM in GB" +min = 1 +max = 512 +name = "min_memory_gb" +nickel_path = ["installer", "preflight", "memory_check", "min_memory_gb"] +prompt = "Min Memory (GB)" +type = "number" + +# CPU Check +[[elements]] +default = true +help = "Validate minimum CPU cores before installation" +name = "check_cpu" +nickel_path = ["installer", "preflight", "cpu_check", "enabled"] +prompt = "Check CPU Cores" +type = "confirm" + +[[elements]] +condition = "check_cpu == true" +default = 2 +help = "Minimum required CPU cores" +min = 1 +max = 128 +name = "min_cpu_cores" +nickel_path = ["installer", "preflight", "cpu_check", "min_cpu_cores"] +prompt = "Min CPU Cores" +type = "number" + +# Network Check +[[elements]] +default = true +help = "Validate network connectivity before installation" +name = "check_network" +nickel_path = ["installer", "preflight", "network_check", "enabled"] +prompt = "Check Network Connectivity" +type = "confirm" + +[[elements]] +condition = "check_network == true" +default = "" +help = "External host to ping for connectivity test (e.g., 8.8.8.8)" +name = "network_check_host" +nickel_path = ["installer", "preflight", "network_check", "test_host"] +prompt = "Network Test Host" +type = "text" + +# Dependency Check +[[elements]] +default = true +help = "Validate required system dependencies are available" +name = "check_dependencies" +nickel_path = ["installer", "preflight", "dependency_check", "enabled"] +prompt = "Check Dependencies" +type = "confirm" + +[[elements]] +condition = "check_dependencies == true" +default = true +help = "Check for required container runtime (docker/podman)" +name = "check_container_runtime" +nickel_path = ["installer", "preflight", "dependency_check", "container_runtime"] +prompt = "Check Container Runtime" +type = "confirm" + +[[elements]] +condition = "check_dependencies == true" +default = false +help = "Check for Kubernetes cluster connectivity" +name = "check_kubernetes" +nickel_path = ["installer", "preflight", "dependency_check", "kubernetes"] +prompt = "Check Kubernetes" +type = "confirm" + +[[elements]] +condition = "check_dependencies == true" +default = false +help = "Check for required Rust toolchain" +name = "check_rust" +nickel_path = ["installer", "preflight", "dependency_check", "rust_toolchain"] +prompt = "Check Rust Toolchain" +type = "confirm" + +[[elements]] +condition = "check_dependencies == true" +default = false +help = "Check for Nushell script engine" +name = "check_nushell" +nickel_path = ["installer", "preflight", "dependency_check", "nushell"] +prompt = "Check Nushell" +type = "confirm" + +# Port Availability Check +[[elements]] +default = false +help = "Validate that installation ports are available" +name = "check_ports" +nickel_path = ["installer", "preflight", "port_check", "enabled"] +prompt = "Check Port Availability" +type = "confirm" + +[[elements]] +condition = "check_ports == true" +default = "9090,8080,8000" +help = "Comma-separated list of ports to check (e.g., 9090,8080,8000)" +name = "ports_to_check" +nickel_path = ["installer", "preflight", "port_check", "ports"] +prompt = "Ports to Check" +type = "text" + +# Permissions Check +[[elements]] +default = true +help = "Validate user has necessary permissions for installation" +name = "check_permissions" +nickel_path = ["installer", "preflight", "permissions_check", "enabled"] +prompt = "Check Permissions" +type = "confirm" + +[[elements]] +condition = "check_permissions == true" +default = false +help = "Require root/admin permissions for installation" +name = "require_root" +nickel_path = ["installer", "preflight", "permissions_check", "require_root"] +prompt = "Require Root" +type = "confirm" + +# File System Check +[[elements]] +default = true +help = "Validate file system compatibility (must support extended attributes)" +name = "check_filesystem" +nickel_path = ["installer", "preflight", "filesystem_check", "enabled"] +prompt = "Check File System" +type = "confirm" + +[[elements]] +condition = "check_filesystem == true" +default = false +help = "Require SELinux support" +name = "require_selinux" +nickel_path = ["installer", "preflight", "filesystem_check", "require_selinux"] +prompt = "Require SELinux" +type = "confirm" + +# Preflight Check Behavior +[[elements]] +default = false +help = "Skip failed preflight checks and continue installation" +name = "ignore_preflight_failures" +nickel_path = ["installer", "preflight", "ignore_failures"] +prompt = "Ignore Preflight Failures" +type = "confirm" + +[[elements]] +default = "warn" +help = "How to handle preflight warnings" +name = "preflight_failure_mode" +nickel_path = ["installer", "preflight", "failure_mode"] +options = ["warn", "error", "fatal"] +prompt = "Failure Mode" +type = "select" diff --git a/.typedialog/platform/forms/fragments/installer/services-section.toml b/.typedialog/platform/forms/fragments/installer/services-section.toml new file mode 100644 index 0000000..e04a1c5 --- /dev/null +++ b/.typedialog/platform/forms/fragments/installer/services-section.toml @@ -0,0 +1,189 @@ +# Installer Services Selection Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "services_section_header" +title = "πŸš€ Services Selection" +type = "section_header" + +[[elements]] +default = true +help = "Install Orchestrator (workflow engine and task scheduling)" +name = "install_orchestrator" +nickel_path = ["installer", "services", "orchestrator", "enabled"] +prompt = "Install Orchestrator" +type = "confirm" + +[[elements]] +default = true +help = "Install Control Center (policy and RBAC management)" +name = "install_control_center" +nickel_path = ["installer", "services", "control_center", "enabled"] +prompt = "Install Control Center" +type = "confirm" + +[[elements]] +default = true +help = "Install MCP Server (Model Context Protocol interface)" +name = "install_mcp_server" +nickel_path = ["installer", "services", "mcp_server", "enabled"] +prompt = "Install MCP Server" +type = "confirm" + +[[elements]] +default = false +help = "Install AI Service (AI model integration and inference)" +name = "install_ai_service" +nickel_path = ["installer", "services", "ai_service", "enabled"] +prompt = "Install AI Service" +type = "confirm" + +[[elements]] +default = false +help = "Install Vault Service (secrets and KMS management)" +name = "install_vault_service" +nickel_path = ["installer", "services", "vault_service", "enabled"] +prompt = "Install Vault Service" +type = "confirm" + +[[elements]] +default = false +help = "Install RAG Service (retrieval-augmented generation)" +name = "install_rag_service" +nickel_path = ["installer", "services", "rag_service", "enabled"] +prompt = "Install RAG Service" +type = "confirm" + +[[elements]] +default = false +help = "Install Extension Registry (OCI registry for extensions)" +name = "install_extension_registry" +nickel_path = ["installer", "services", "extension_registry", "enabled"] +prompt = "Install Extension Registry" +type = "confirm" + +[[elements]] +default = false +help = "Install Detector Service (system monitoring and detection)" +name = "install_detector" +nickel_path = ["installer", "services", "detector", "enabled"] +prompt = "Install Detector" +type = "confirm" + +[[elements]] +default = false +help = "Install API Gateway (request routing and load balancing)" +name = "install_api_gateway" +nickel_path = ["installer", "services", "api_gateway", "enabled"] +prompt = "Install API Gateway" +type = "confirm" + +[[elements]] +default = false +help = "Install monitoring stack (Prometheus, Grafana, Loki)" +name = "install_monitoring_stack" +nickel_path = ["installer", "services", "monitoring_stack", "enabled"] +prompt = "Install Monitoring Stack" +type = "confirm" + +# Service Dependencies and Configuration +[[elements]] +condition = "install_orchestrator == true" +default = true +help = "Start Orchestrator immediately after installation" +name = "orchestrator_auto_start" +nickel_path = ["installer", "services", "orchestrator", "auto_start"] +prompt = "Orchestrator Auto-Start" +type = "confirm" + +[[elements]] +condition = "install_control_center == true" +default = true +help = "Start Control Center immediately after installation" +name = "control_center_auto_start" +nickel_path = ["installer", "services", "control_center", "auto_start"] +prompt = "Control Center Auto-Start" +type = "confirm" + +[[elements]] +condition = "install_mcp_server == true" +default = true +help = "Start MCP Server immediately after installation" +name = "mcp_server_auto_start" +nickel_path = ["installer", "services", "mcp_server", "auto_start"] +prompt = "MCP Server Auto-Start" +type = "confirm" + +# Service Ports Configuration +[[elements]] +condition = "install_orchestrator == true" +default = 9090 +help = "Port for Orchestrator service (range: ${constraint.common.server.port.min}-${constraint.common.server.port.max})" +max = "${constraint.common.server.port.max}" +min = "${constraint.common.server.port.min}" +name = "orchestrator_port" +nickel_path = ["installer", "services", "orchestrator", "port"] +prompt = "Orchestrator Port" +type = "number" + +[[elements]] +condition = "install_control_center == true" +default = 8080 +help = "Port for Control Center service (range: ${constraint.common.server.port.min}-${constraint.common.server.port.max})" +max = "${constraint.common.server.port.max}" +min = "${constraint.common.server.port.min}" +name = "control_center_port" +nickel_path = ["installer", "services", "control_center", "port"] +prompt = "Control Center Port" +type = "number" + +[[elements]] +condition = "install_mcp_server == true" +default = 8000 +help = "Port for MCP Server service (range: ${constraint.common.server.port.min}-${constraint.common.server.port.max})" +max = "${constraint.common.server.port.max}" +min = "${constraint.common.server.port.min}" +name = "mcp_server_port" +nickel_path = ["installer", "services", "mcp_server", "port"] +prompt = "MCP Server Port" +type = "number" + +[[elements]] +condition = "install_api_gateway == true" +default = 8443 +help = "Port for API Gateway service (range: ${constraint.common.server.port.min}-${constraint.common.server.port.max})" +max = "${constraint.common.server.port.max}" +min = "${constraint.common.server.port.min}" +name = "api_gateway_port" +nickel_path = ["installer", "services", "api_gateway", "port"] +prompt = "API Gateway Port" +type = "number" + +# Service Update Strategy +[[elements]] +default = "rolling" +help = "Strategy for updating services during installation" +name = "service_update_strategy" +nickel_path = ["installer", "services", "update_strategy"] +options = ["rolling", "blue_green", "canary"] +prompt = "Service Update Strategy" +type = "select" + +[[elements]] +default = false +help = "Enable health checks between service updates" +name = "enable_health_checks" +nickel_path = ["installer", "services", "health_checks", "enabled"] +prompt = "Enable Health Checks" +type = "confirm" + +[[elements]] +condition = "enable_health_checks == true" +default = 30 +help = "Health check interval in seconds" +min = 5 +name = "health_check_interval" +nickel_path = ["installer", "services", "health_checks", "interval_seconds"] +prompt = "Health Check Interval (seconds)" +type = "number" diff --git a/.typedialog/platform/forms/fragments/installer/storage-section.toml b/.typedialog/platform/forms/fragments/installer/storage-section.toml new file mode 100644 index 0000000..cbb7516 --- /dev/null +++ b/.typedialog/platform/forms/fragments/installer/storage-section.toml @@ -0,0 +1,236 @@ +# Installer Storage Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "installer_storage_section_header" +title = "πŸ’Ύ Storage Configuration" +type = "section_header" + +# Storage Location +[[elements]] +default = "/var/lib/provisioning" +help = "Root directory for provisioning data storage" +name = "storage_root_path" +nickel_path = ["installer", "storage", "root_path"] +prompt = "Storage Root Path" +required = true +type = "text" + +[[elements]] +default = 500 +help = "Allocated storage space in GB (range: 10-100000)" +max = 100000 +min = 10 +name = "storage_size_gb" +nickel_path = ["installer", "storage", "size_gb"] +prompt = "Storage Size (GB)" +type = "number" + +# Storage Backend Selection +[[elements]] +default = "filesystem" +help = "Storage backend type" +name = "installer_storage_backend" +nickel_path = ["installer", "storage", "backend"] +options = ["filesystem", "object_storage", "block_storage"] +prompt = "Storage Backend" +type = "select" + +# Filesystem Storage (conditional) +[[elements]] +condition = "installer_storage_backend == 'filesystem'" +default = "ext4" +help = "File system type" +name = "filesystem_type" +nickel_path = ["installer", "storage", "filesystem", "type"] +options = ["ext4", "xfs", "btrfs", "zfs"] +prompt = "File System Type" +type = "select" + +[[elements]] +condition = "installer_storage_backend == 'filesystem'" +default = true +help = "Enable file system snapshots" +name = "filesystem_snapshots_enabled" +nickel_path = ["installer", "storage", "filesystem", "snapshots", "enabled"] +prompt = "Enable Snapshots" +type = "confirm" + +# Object Storage (conditional) +[[elements]] +condition = "installer_storage_backend == 'object_storage'" +default = "s3" +help = "Object storage provider" +name = "object_storage_provider" +nickel_path = ["installer", "storage", "object_storage", "provider"] +options = ["s3", "gcs", "azure_blob", "minio"] +prompt = "Object Storage Provider" +type = "select" + +[[elements]] +condition = "installer_storage_backend == 'object_storage'" +default = "" +help = "Object storage endpoint URL" +name = "object_storage_endpoint" +nickel_path = ["installer", "storage", "object_storage", "endpoint"] +prompt = "Storage Endpoint" +required = true +type = "text" + +[[elements]] +condition = "installer_storage_backend == 'object_storage'" +default = "" +help = "Object storage bucket name" +name = "object_storage_bucket" +nickel_path = ["installer", "storage", "object_storage", "bucket"] +prompt = "Storage Bucket" +required = true +type = "text" + +[[elements]] +condition = "installer_storage_backend == 'object_storage'" +default = "" +help = "Object storage access key ID (will be encrypted)" +name = "object_storage_access_key" +nickel_path = ["installer", "storage", "object_storage", "access_key"] +prompt = "Access Key" +required = true +type = "password" + +[[elements]] +condition = "installer_storage_backend == 'object_storage'" +default = "" +help = "Object storage secret access key (will be encrypted)" +name = "object_storage_secret_key" +nickel_path = ["installer", "storage", "object_storage", "secret_key"] +prompt = "Secret Key" +required = true +type = "password" + +# Block Storage (conditional) +[[elements]] +condition = "installer_storage_backend == 'block_storage'" +default = "local" +help = "Block storage type" +name = "block_storage_type" +nickel_path = ["installer", "storage", "block_storage", "type"] +options = ["local", "san", "nas"] +prompt = "Block Storage Type" +type = "select" + +[[elements]] +condition = "installer_storage_backend == 'block_storage'" +default = "/dev/sdb" +help = "Block device path" +name = "block_device_path" +nickel_path = ["installer", "storage", "block_storage", "device_path"] +prompt = "Block Device Path" +type = "text" + +# Storage Compression and Encryption +[[elements]] +default = false +help = "Enable compression for stored data" +name = "storage_compression_enabled" +nickel_path = ["installer", "storage", "compression", "enabled"] +prompt = "Enable Compression" +type = "confirm" + +[[elements]] +condition = "storage_compression_enabled == true" +default = "zstd" +help = "Compression algorithm" +name = "storage_compression_algorithm" +nickel_path = ["installer", "storage", "compression", "algorithm"] +options = ["zstd", "gzip", "snappy"] +prompt = "Compression Algorithm" +type = "select" + +[[elements]] +default = true +help = "Enable encryption for stored data" +name = "storage_encryption_enabled" +nickel_path = ["installer", "storage", "encryption", "enabled"] +prompt = "Enable Encryption" +type = "confirm" + +[[elements]] +condition = "storage_encryption_enabled == true" +default = "aes256" +help = "Encryption algorithm" +name = "storage_encryption_algorithm" +nickel_path = ["installer", "storage", "encryption", "algorithm"] +options = ["aes256", "chacha20"] +prompt = "Encryption Algorithm" +type = "select" + +[[elements]] +condition = "storage_encryption_enabled == true" +default = "age" +help = "Key management system for encryption keys" +name = "storage_kms" +nickel_path = ["installer", "storage", "encryption", "kms"] +options = ["age", "sops", "vault", "kms"] +prompt = "Key Management" +type = "select" + +# Storage Replication +[[elements]] +default = false +help = "Enable storage replication for redundancy" +name = "storage_replication_enabled" +nickel_path = ["installer", "storage", "replication", "enabled"] +prompt = "Enable Replication" +type = "confirm" + +[[elements]] +condition = "storage_replication_enabled == true" +default = 3 +help = "Number of replicas (range: 2-10)" +max = 10 +min = 2 +name = "storage_replication_factor" +nickel_path = ["installer", "storage", "replication", "factor"] +prompt = "Replication Factor" +type = "number" + +[[elements]] +condition = "storage_replication_enabled == true" +default = "sync" +help = "Replication mode" +name = "storage_replication_mode" +nickel_path = ["installer", "storage", "replication", "mode"] +options = ["sync", "async", "hybrid"] +prompt = "Replication Mode" +type = "select" + +# Storage Cleanup +[[elements]] +default = true +help = "Enable automatic cleanup of old data" +name = "storage_cleanup_enabled" +nickel_path = ["installer", "storage", "cleanup", "enabled"] +prompt = "Enable Cleanup" +type = "confirm" + +[[elements]] +condition = "storage_cleanup_enabled == true" +default = 90 +help = "Retention period for archived data in days" +min = 7 +max = 3650 +name = "storage_cleanup_retention_days" +nickel_path = ["installer", "storage", "cleanup", "retention_days"] +prompt = "Retention Period (days)" +type = "number" + +[[elements]] +condition = "storage_cleanup_enabled == true" +default = "weekly" +help = "Cleanup schedule" +name = "storage_cleanup_schedule" +nickel_path = ["installer", "storage", "cleanup", "schedule"] +options = ["daily", "weekly", "monthly"] +prompt = "Cleanup Schedule" +type = "select" diff --git a/.typedialog/platform/forms/fragments/installer/target-section.toml b/.typedialog/platform/forms/fragments/installer/target-section.toml new file mode 100644 index 0000000..db33059 --- /dev/null +++ b/.typedialog/platform/forms/fragments/installer/target-section.toml @@ -0,0 +1,160 @@ +# Installer Target Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "target_section_header" +title = "🎯 Installation Target" +type = "section_header" + +# Target Type Selection +[[elements]] +default = "local" +help = "Target environment for installation" +name = "target_type" +nickel_path = ["installer", "target", "type"] +options = ["local", "remote", "kubernetes", "docker"] +prompt = "Target Type" +required = true +type = "select" + +# Local Installation (conditional) +[[elements]] +condition = "target_type == 'local'" +default = "/opt/provisioning" +help = "Installation directory for local deployment" +name = "local_install_path" +nickel_path = ["installer", "target", "local_path"] +prompt = "Installation Path" +required = true +type = "text" + +# Remote Installation (conditional) +[[elements]] +condition = "target_type == 'remote'" +default = "example.com" +help = "Hostname or IP address of remote host" +name = "remote_host" +nickel_path = ["installer", "target", "remote_host"] +prompt = "Remote Host" +required = true +type = "text" + +[[elements]] +condition = "target_type == 'remote'" +default = 22 +help = "SSH port for remote access (range: ${constraint.common.server.port.min}-${constraint.common.server.port.max})" +max = "${constraint.common.server.port.max}" +min = "${constraint.common.server.port.min}" +name = "remote_ssh_port" +nickel_path = ["installer", "target", "remote_ssh_port"] +prompt = "SSH Port" +type = "number" + +[[elements]] +condition = "target_type == 'remote'" +default = "ubuntu" +help = "SSH username for remote access" +name = "remote_ssh_user" +nickel_path = ["installer", "target", "remote_ssh_user"] +prompt = "SSH User" +required = true +type = "text" + +[[elements]] +condition = "target_type == 'remote'" +default = "" +help = "Path to SSH private key (leave empty to use ssh-agent)" +name = "remote_ssh_key_path" +nickel_path = ["installer", "target", "remote_ssh_key_path"] +prompt = "SSH Key Path" +type = "text" + +[[elements]] +condition = "target_type == 'remote'" +default = false +help = "Accept unknown SSH host keys" +name = "remote_ssh_insecure" +nickel_path = ["installer", "target", "remote_ssh_insecure"] +prompt = "Accept Unknown Keys" +type = "confirm" + +# Kubernetes Installation (conditional) +[[elements]] +condition = "target_type == 'kubernetes'" +default = "default" +help = "Kubernetes namespace for installation" +name = "k8s_namespace" +nickel_path = ["installer", "target", "k8s_namespace"] +prompt = "Kubernetes Namespace" +required = true +type = "text" + +[[elements]] +condition = "target_type == 'kubernetes'" +default = "provisioning" +help = "Kubernetes context to use" +name = "k8s_context" +nickel_path = ["installer", "target", "k8s_context"] +prompt = "Kubernetes Context" +type = "text" + +# Docker Installation (conditional) +[[elements]] +condition = "target_type == 'docker'" +default = "unix:///var/run/docker.sock" +help = "Docker daemon endpoint" +name = "docker_host" +nickel_path = ["installer", "target", "docker_host"] +prompt = "Docker Host" +required = true +type = "text" + +# Cloud Provider Configuration (for all types) +[[elements]] +default = "none" +help = "Cloud provider for monitoring and management APIs" +name = "cloud_provider" +nickel_path = ["installer", "target", "cloud_provider"] +options = ["none", "aws", "gcp", "azure", "digitalocean", "linode"] +prompt = "Cloud Provider" +type = "select" + +[[elements]] +condition = "cloud_provider != 'none'" +default = "" +help = "Cloud provider region" +name = "cloud_region" +nickel_path = ["installer", "target", "cloud_region"] +prompt = "Cloud Region" +required = true +type = "text" + +[[elements]] +condition = "cloud_provider != 'none'" +default = "" +help = "Cloud provider API key or credentials (will be encrypted)" +name = "cloud_credentials" +nickel_path = ["installer", "target", "cloud_credentials"] +prompt = "Cloud Credentials" +type = "password" + +# Operating System Detection +[[elements]] +default = "auto" +help = "Target operating system" +name = "target_os" +nickel_path = ["installer", "target", "os"] +options = ["auto", "linux", "macos", "windows"] +prompt = "Target OS" +type = "select" + +[[elements]] +condition = "target_os == 'linux'" +default = "auto" +help = "Linux distribution" +name = "target_linux_distro" +nickel_path = ["installer", "target", "linux_distro"] +options = ["auto", "ubuntu", "debian", "centos", "rhel", "alpine"] +prompt = "Linux Distribution" +type = "select" diff --git a/.typedialog/platform/forms/fragments/installer/upgrades-section.toml b/.typedialog/platform/forms/fragments/installer/upgrades-section.toml new file mode 100644 index 0000000..7373f80 --- /dev/null +++ b/.typedialog/platform/forms/fragments/installer/upgrades-section.toml @@ -0,0 +1,359 @@ +# Installer Upgrades Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "upgrades_section_header" +title = "πŸ“¦ Upgrades Configuration" +type = "section_header" + +# Auto-Upgrade Settings +[[elements]] +default = false +help = "Enable automatic system updates and upgrades" +name = "auto_upgrade_enabled" +nickel_path = ["installer", "upgrades", "auto_upgrade", "enabled"] +prompt = "Enable Auto-Upgrade" +type = "confirm" + +[[elements]] +condition = "auto_upgrade_enabled == true" +default = true +help = "Check for updates at startup" +name = "check_updates_on_startup" +nickel_path = ["installer", "upgrades", "auto_upgrade", "check_on_startup"] +prompt = "Check Updates on Startup" +type = "confirm" + +[[elements]] +condition = "auto_upgrade_enabled == true" +default = false +help = "Automatically apply patches without confirmation" +name = "auto_apply_patches" +nickel_path = ["installer", "upgrades", "auto_upgrade", "auto_apply_patches"] +prompt = "Auto-Apply Patches" +type = "confirm" + +# Update Channels +[[elements]] +default = "stable" +help = "Software update channel preference" +name = "update_channel" +nickel_path = ["installer", "upgrades", "update_channel"] +options = ["stable", "lts", "beta", "nightly"] +prompt = "Update Channel" +type = "select" + +# Upgrade Strategy +[[elements]] +default = "rolling" +help = "Strategy for applying upgrades" +name = "upgrade_strategy" +nickel_path = ["installer", "upgrades", "strategy"] +options = ["rolling", "blue_green", "canary", "maintenance_window"] +prompt = "Upgrade Strategy" +type = "select" + +[[elements]] +condition = "upgrade_strategy == 'rolling'" +default = 1 +help = "Number of services to upgrade in parallel" +min = 1 +max = 10 +name = "rolling_upgrade_parallel" +nickel_path = ["installer", "upgrades", "rolling", "parallel_services"] +prompt = "Parallel Services" +type = "number" + +[[elements]] +condition = "upgrade_strategy == 'canary'" +default = 10 +help = "Percentage of traffic to route to canary version" +min = 1 +max = 50 +name = "canary_percentage" +nickel_path = ["installer", "upgrades", "canary", "traffic_percentage"] +prompt = "Canary Traffic %" +type = "number" + +[[elements]] +condition = "upgrade_strategy == 'canary'" +default = 300 +help = "Canary test duration in seconds (range: 30-7200)" +max = 7200 +min = 30 +name = "canary_duration_seconds" +nickel_path = ["installer", "upgrades", "canary", "duration_seconds"] +prompt = "Canary Duration (seconds)" +type = "number" + +[[elements]] +condition = "upgrade_strategy == 'maintenance_window'" +default = "sunday" +help = "Day of week for maintenance window" +name = "maintenance_day" +nickel_path = ["installer", "upgrades", "maintenance_window", "day"] +options = ["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"] +prompt = "Maintenance Day" +type = "select" + +[[elements]] +condition = "upgrade_strategy == 'maintenance_window'" +default = "02:00" +help = "Time of day for maintenance window (HH:MM format, UTC)" +name = "maintenance_time" +nickel_path = ["installer", "upgrades", "maintenance_window", "time"] +prompt = "Maintenance Time (UTC)" +type = "text" + +[[elements]] +condition = "upgrade_strategy == 'maintenance_window'" +default = 3600 +help = "Maximum duration of maintenance window in seconds (range: 600-86400)" +max = 86400 +min = 600 +name = "maintenance_duration_seconds" +nickel_path = ["installer", "upgrades", "maintenance_window", "max_duration_seconds"] +prompt = "Max Duration (seconds)" +type = "number" + +# Pre-Upgrade Checks +[[elements]] +default = true +help = "Run checks before upgrading" +name = "pre_upgrade_checks_enabled" +nickel_path = ["installer", "upgrades", "pre_checks", "enabled"] +prompt = "Enable Pre-Upgrade Checks" +type = "confirm" + +[[elements]] +condition = "pre_upgrade_checks_enabled == true" +default = true +help = "Check disk space requirements" +name = "check_disk_space_for_upgrade" +nickel_path = ["installer", "upgrades", "pre_checks", "check_disk_space"] +prompt = "Check Disk Space" +type = "confirm" + +[[elements]] +condition = "pre_upgrade_checks_enabled == true" +default = true +help = "Check service health before upgrade" +name = "check_service_health_pre_upgrade" +nickel_path = ["installer", "upgrades", "pre_checks", "check_service_health"] +prompt = "Check Service Health" +type = "confirm" + +[[elements]] +condition = "pre_upgrade_checks_enabled == true" +default = true +help = "Check API/database connectivity" +name = "check_connectivity_pre_upgrade" +nickel_path = ["installer", "upgrades", "pre_checks", "check_connectivity"] +prompt = "Check Connectivity" +type = "confirm" + +[[elements]] +condition = "pre_upgrade_checks_enabled == true" +default = true +help = "Validate backup integrity" +name = "validate_backup_integrity" +nickel_path = ["installer", "upgrades", "pre_checks", "validate_backup_integrity"] +prompt = "Validate Backup Integrity" +type = "confirm" + +# Backup Before Upgrade +[[elements]] +default = true +help = "Create backup before upgrade" +name = "backup_before_upgrade" +nickel_path = ["installer", "upgrades", "backup_before_upgrade"] +prompt = "Backup Before Upgrade" +type = "confirm" + +[[elements]] +condition = "backup_before_upgrade == true" +default = "full" +help = "Type of backup to create" +name = "pre_upgrade_backup_type" +nickel_path = ["installer", "upgrades", "backup_type"] +options = ["full", "incremental", "snapshot"] +prompt = "Backup Type" +type = "select" + +[[elements]] +condition = "backup_before_upgrade == true" +default = 30 +help = "Backup timeout in minutes" +min = 5 +max = 1440 +name = "backup_timeout_minutes" +nickel_path = ["installer", "upgrades", "backup_timeout_minutes"] +prompt = "Backup Timeout (minutes)" +type = "number" + +# Upgrade Rollback +[[elements]] +default = true +help = "Enable automatic rollback on upgrade failure" +name = "enable_rollback_on_failure" +nickel_path = ["installer", "upgrades", "rollback", "enabled"] +prompt = "Enable Rollback" +type = "confirm" + +[[elements]] +condition = "enable_rollback_on_failure == true" +default = "automatic" +help = "Rollback strategy" +name = "rollback_on_failure_strategy" +nickel_path = ["installer", "upgrades", "rollback", "strategy"] +options = ["automatic", "manual", "data_aware"] +prompt = "Rollback Strategy" +type = "select" + +[[elements]] +condition = "enable_rollback_on_failure == true" +default = 300 +help = "Time to wait after upgrade before validating success (seconds, range: 30-1800)" +max = 1800 +min = 30 +name = "rollback_validation_delay" +nickel_path = ["installer", "upgrades", "rollback", "validation_delay_seconds"] +prompt = "Validation Delay (seconds)" +type = "number" + +[[elements]] +condition = "enable_rollback_on_failure == true" +default = true +help = "Perform database migrations rollback" +name = "rollback_database_migrations" +nickel_path = ["installer", "upgrades", "rollback", "database_migrations"] +prompt = "Rollback DB Migrations" +type = "confirm" + +# Service-Specific Upgrades +[[elements]] +default = true +help = "Upgrade Orchestrator service" +name = "upgrade_orchestrator" +nickel_path = ["installer", "upgrades", "services", "orchestrator"] +prompt = "Upgrade Orchestrator" +type = "confirm" + +[[elements]] +default = true +help = "Upgrade Control Center service" +name = "upgrade_control_center" +nickel_path = ["installer", "upgrades", "services", "control_center"] +prompt = "Upgrade Control Center" +type = "confirm" + +[[elements]] +default = true +help = "Upgrade MCP Server service" +name = "upgrade_mcp_server" +nickel_path = ["installer", "upgrades", "services", "mcp_server"] +prompt = "Upgrade MCP Server" +type = "confirm" + +[[elements]] +default = false +help = "Upgrade AI Service" +name = "upgrade_ai_service" +nickel_path = ["installer", "upgrades", "services", "ai_service"] +prompt = "Upgrade AI Service" +type = "confirm" + +[[elements]] +default = false +help = "Upgrade RAG Service" +name = "upgrade_rag_service" +nickel_path = ["installer", "upgrades", "services", "rag_service"] +prompt = "Upgrade RAG Service" +type = "confirm" + +# Health Checks After Upgrade +[[elements]] +default = true +help = "Run health checks after upgrade completes" +name = "health_checks_post_upgrade" +nickel_path = ["installer", "upgrades", "post_upgrade", "health_checks_enabled"] +prompt = "Health Checks After Upgrade" +type = "confirm" + +[[elements]] +condition = "health_checks_post_upgrade == true" +default = 60 +help = "Health check interval after upgrade in seconds (range: 5-300)" +max = 300 +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" + +[[elements]] +condition = "health_checks_post_upgrade == true" +default = 600 +help = "Duration to monitor health after upgrade in seconds (range: 60-86400)" +max = 86400 +min = 60 +name = "post_upgrade_monitoring_duration" +nickel_path = ["installer", "upgrades", "post_upgrade", "monitoring_duration_seconds"] +prompt = "Monitoring Duration (seconds)" +type = "number" + +# Version Constraints +[[elements]] +default = false +help = "Enforce version constraints for upgrades" +name = "enable_version_constraints" +nickel_path = ["installer", "upgrades", "version_constraints", "enabled"] +prompt = "Enable Version Constraints" +type = "confirm" + +[[elements]] +condition = "enable_version_constraints == true" +default = "compatible" +help = "Version compatibility mode" +name = "version_constraint_mode" +nickel_path = ["installer", "upgrades", "version_constraints", "mode"] +options = ["compatible", "minimum", "maximum", "exact"] +prompt = "Version Constraint Mode" +type = "select" + +[[elements]] +condition = "enable_version_constraints == true && version_constraint_mode == 'minimum'" +default = "" +help = "Minimum version to upgrade to (e.g., 3.1.0)" +name = "minimum_version" +nickel_path = ["installer", "upgrades", "version_constraints", "minimum_version"] +prompt = "Minimum Version" +type = "text" + +[[elements]] +condition = "enable_version_constraints == true && version_constraint_mode == 'maximum'" +default = "" +help = "Maximum version to upgrade to (e.g., 4.0.0)" +name = "maximum_version" +nickel_path = ["installer", "upgrades", "version_constraints", "maximum_version"] +prompt = "Maximum Version" +type = "text" + +# Notification +[[elements]] +default = false +help = "Send notification when upgrade completes" +name = "notify_on_upgrade_complete" +nickel_path = ["installer", "upgrades", "notification", "enabled"] +prompt = "Notify on Upgrade Complete" +type = "confirm" + +[[elements]] +condition = "notify_on_upgrade_complete == true" +default = "" +help = "Email address for upgrade completion notification" +name = "upgrade_notification_email" +nickel_path = ["installer", "upgrades", "notification", "email"] +prompt = "Notification Email" +type = "text" diff --git a/.typedialog/platform/forms/fragments/logging-section.toml b/.typedialog/platform/forms/fragments/logging-section.toml new file mode 100644 index 0000000..3cfa944 --- /dev/null +++ b/.typedialog/platform/forms/fragments/logging-section.toml @@ -0,0 +1,57 @@ +# Logging Configuration Fragment +# Optional for all services + +[[elements]] +border_top = true +border_bottom = false +name = "logging_section_header" +title = "πŸ“ Logging Configuration" +type = "section_header" + +[[elements]] +default = "info" +help = "Log level (debug, info, warn, error)" +name = "logging_level" +nickel_path = ["logging", "level"] +options = ["debug", "info", "warn", "error"] +prompt = "Log Level" +type = "select" + +[[elements]] +default = "text" +help = "Log format (text, json)" +name = "logging_format" +nickel_path = ["logging", "format"] +options = ["text", "json"] +prompt = "Log Format" +type = "select" + +[[elements]] +default = false +help = "Enable file-based logging with rotation" +name = "logging_file_enabled" +nickel_path = ["logging", "file", "enabled"] +prompt = "Enable File Logging" +type = "confirm" + +[[elements]] +condition = "logging_file_enabled == true" +default = 10485760 +help = "Maximum log file size in bytes before rotation (range: ${constraint.common.logging.max_file_size.min}-${constraint.common.logging.max_file_size.max})" +max = "${constraint.common.logging.max_file_size.max}" +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" + +[[elements]] +condition = "logging_file_enabled == true" +default = 10 +help = "Maximum number of backup log files to keep (range: ${constraint.common.logging.max_backups.min}-${constraint.common.logging.max_backups.max})" +max = "${constraint.common.logging.max_backups.max}" +min = "${constraint.common.logging.max_backups.min}" +name = "logging_max_backups" +nickel_path = ["logging", "file", "max_backups"] +prompt = "Max Backup Files" +type = "number" diff --git a/.typedialog/platform/forms/fragments/mcp-server/prompts-section.toml b/.typedialog/platform/forms/fragments/mcp-server/prompts-section.toml new file mode 100644 index 0000000..2d5f80c --- /dev/null +++ b/.typedialog/platform/forms/fragments/mcp-server/prompts-section.toml @@ -0,0 +1,67 @@ +# MCP Server Prompts Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "prompts_section_header" +title = "πŸ’¬ Prompts Configuration" +type = "section_header" + +[[elements]] +default = true +help = "Enable MCP prompts capability" +name = "prompts_enabled" +nickel_path = ["prompts", "enabled"] +prompt = "Enable Prompts" +type = "confirm" + +[[elements]] +condition = "prompts_enabled == true" +default = 100 +help = "Maximum custom prompt templates (range: ${constraint.mcp_server.prompts.max_templates.min}-${constraint.mcp_server.prompts.max_templates.max})" +max = "${constraint.mcp_server.prompts.max_templates.max}" +min = "${constraint.mcp_server.prompts.max_templates.min}" +name = "prompts_max_templates" +nickel_path = ["prompts", "max_templates"] +prompt = "Max Prompt Templates" +type = "number" + +[[elements]] +condition = "prompts_enabled == true" +default = true +help = "Enable prompt response caching" +name = "prompts_cache_enabled" +nickel_path = ["prompts", "cache", "enabled"] +prompt = "Enable Prompt Caching" +type = "confirm" + +[[elements]] +condition = "prompts_enabled == true && prompts_cache_enabled == true" +default = 3600 +help = "Prompt cache TTL in seconds (range: 60-86400)" +max = 86400 +min = 60 +name = "prompts_cache_ttl" +nickel_path = ["prompts", "cache", "ttl"] +prompt = "Cache TTL (seconds)" +type = "number" + +[[elements]] +condition = "prompts_enabled == true" +default = false +help = "Enable prompt versioning" +name = "prompts_versioning_enabled" +nickel_path = ["prompts", "versioning", "enabled"] +prompt = "Enable Prompt Versioning" +type = "confirm" + +[[elements]] +condition = "prompts_enabled == true && prompts_versioning_enabled == true" +default = 10 +help = "Maximum prompt versions to keep (range: 1-100)" +max = 100 +min = 1 +name = "prompts_versioning_max_versions" +nickel_path = ["prompts", "versioning", "max_versions"] +prompt = "Max Prompt Versions" +type = "number" diff --git a/.typedialog/platform/forms/fragments/mcp-server/resources-section.toml b/.typedialog/platform/forms/fragments/mcp-server/resources-section.toml new file mode 100644 index 0000000..cb252b0 --- /dev/null +++ b/.typedialog/platform/forms/fragments/mcp-server/resources-section.toml @@ -0,0 +1,78 @@ +# MCP Server Resources Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "resources_section_header" +title = "πŸ“¦ Resources Configuration" +type = "section_header" + +[[elements]] +default = true +help = "Enable MCP resources capability" +name = "resources_enabled" +nickel_path = ["resources", "enabled"] +prompt = "Enable Resources" +type = "confirm" + +[[elements]] +condition = "resources_enabled == true" +default = 104857600 +help = "Maximum resource size in bytes (range: ${constraint.mcp_server.resources.max_size.min}-${constraint.mcp_server.resources.max_size.max})" +max = "${constraint.mcp_server.resources.max_size.max}" +min = "${constraint.mcp_server.resources.max_size.min}" +name = "resources_max_size" +nickel_path = ["resources", "max_size"] +prompt = "Max Resource Size (bytes)" +type = "number" + +[[elements]] +condition = "resources_enabled == true" +default = true +help = "Enable resource caching" +name = "resources_cache_enabled" +nickel_path = ["resources", "cache", "enabled"] +prompt = "Enable Resource Caching" +type = "confirm" + +[[elements]] +condition = "resources_enabled == true && resources_cache_enabled == true" +default = 512 +help = "Maximum cache size in MB (range: 10-10240)" +max = 10240 +min = 10 +name = "resources_cache_max_size_mb" +nickel_path = ["resources", "cache", "max_size_mb"] +prompt = "Max Cache Size (MB)" +type = "number" + +[[elements]] +condition = "resources_enabled == true && resources_cache_enabled == true" +default = 3600 +help = "Resource cache TTL in seconds (range: ${constraint.mcp_server.resources.cache_ttl.min}-${constraint.mcp_server.resources.cache_ttl.max})" +max = "${constraint.mcp_server.resources.cache_ttl.max}" +min = "${constraint.mcp_server.resources.cache_ttl.min}" +name = "resources_cache_ttl" +nickel_path = ["resources", "cache", "ttl"] +prompt = "Cache TTL (seconds)" +type = "number" + +[[elements]] +condition = "resources_enabled == true" +default = true +help = "Enable resource validation" +name = "resources_validation_enabled" +nickel_path = ["resources", "validation", "enabled"] +prompt = "Enable Resource Validation" +type = "confirm" + +[[elements]] +condition = "resources_enabled == true && resources_validation_enabled == true" +default = 10 +help = "Maximum nesting depth for resources (range: 1-100)" +max = 100 +min = 1 +name = "resources_validation_max_depth" +nickel_path = ["resources", "validation", "max_depth"] +prompt = "Max Nesting Depth" +type = "number" diff --git a/.typedialog/platform/forms/fragments/mcp-server/sampling-section.toml b/.typedialog/platform/forms/fragments/mcp-server/sampling-section.toml new file mode 100644 index 0000000..4a6a7cd --- /dev/null +++ b/.typedialog/platform/forms/fragments/mcp-server/sampling-section.toml @@ -0,0 +1,67 @@ +# MCP Server Sampling Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "sampling_section_header" +title = "🎲 Sampling Configuration" +type = "section_header" + +[[elements]] +default = false +help = "Enable sampling capability for AI model inference" +name = "sampling_enabled" +nickel_path = ["sampling", "enabled"] +prompt = "Enable Sampling" +type = "confirm" + +[[elements]] +condition = "sampling_enabled == true" +default = 4096 +help = "Maximum tokens for sampling output (range: ${constraint.mcp_server.sampling.max_tokens.min}-${constraint.mcp_server.sampling.max_tokens.max})" +max = "${constraint.mcp_server.sampling.max_tokens.max}" +min = "${constraint.mcp_server.sampling.max_tokens.min}" +name = "sampling_max_tokens" +nickel_path = ["sampling", "max_tokens"] +prompt = "Max Tokens" +type = "number" + +[[elements]] +condition = "sampling_enabled == true" +help = "Sampling model to use (e.g., gpt-4, claude-3)" +name = "sampling_model" +nickel_path = ["sampling", "model"] +placeholder = "gpt-4" +prompt = "Sampling Model" +type = "text" + +[[elements]] +condition = "sampling_enabled == true" +default = 0.7 +help = "Temperature for sampling (0.0-2.0, higher = more creative)" +min = 0.0 +max = 2.0 +name = "sampling_temperature" +nickel_path = ["sampling", "temperature"] +prompt = "Temperature" +type = "number" + +[[elements]] +condition = "sampling_enabled == true" +default = true +help = "Enable sampling result caching" +name = "sampling_cache_enabled" +nickel_path = ["sampling", "cache", "enabled"] +prompt = "Enable Sampling Cache" +type = "confirm" + +[[elements]] +condition = "sampling_enabled == true && sampling_cache_enabled == true" +default = 3600 +help = "Sampling cache TTL in seconds (range: 60-3600)" +max = 3600 +min = 60 +name = "sampling_cache_ttl" +nickel_path = ["sampling", "cache", "ttl"] +prompt = "Cache TTL (seconds)" +type = "number" diff --git a/.typedialog/platform/forms/fragments/mcp-server/tools-section.toml b/.typedialog/platform/forms/fragments/mcp-server/tools-section.toml new file mode 100644 index 0000000..6102549 --- /dev/null +++ b/.typedialog/platform/forms/fragments/mcp-server/tools-section.toml @@ -0,0 +1,75 @@ +# MCP Server Tools Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "tools_section_header" +title = "πŸ”§ Tools Configuration" +type = "section_header" + +[[elements]] +default = true +help = "Enable MCP tools capability" +name = "tools_enabled" +nickel_path = ["tools", "enabled"] +prompt = "Enable Tools" +type = "confirm" + +[[elements]] +condition = "tools_enabled == true" +default = 5 +help = "Maximum concurrent tool executions (range: ${constraint.mcp_server.tools.max_concurrent.min}-${constraint.mcp_server.tools.max_concurrent.max})" +max = "${constraint.mcp_server.tools.max_concurrent.max}" +min = "${constraint.mcp_server.tools.max_concurrent.min}" +name = "tools_max_concurrent" +nickel_path = ["tools", "max_concurrent"] +prompt = "Max Concurrent Tools" +type = "number" + +[[elements]] +condition = "tools_enabled == true" +default = 30000 +help = "Tool execution timeout in milliseconds (range: ${constraint.mcp_server.tools.timeout.min}-${constraint.mcp_server.tools.timeout.max})" +min = "${constraint.mcp_server.tools.timeout.min}" +max = "${constraint.mcp_server.tools.timeout.max}" +name = "tools_timeout" +nickel_path = ["tools", "timeout"] +prompt = "Tool Timeout (ms)" +type = "number" + +[[elements]] +condition = "tools_enabled == true" +default = true +help = "Enable tool input validation" +name = "tools_validation_enabled" +nickel_path = ["tools", "validation", "enabled"] +prompt = "Enable Tool Validation" +type = "confirm" + +[[elements]] +condition = "tools_enabled == true && tools_validation_enabled == true" +default = false +help = "Enable strict validation mode" +name = "tools_validation_strict" +nickel_path = ["tools", "validation", "strict_mode"] +prompt = "Strict Validation Mode" +type = "confirm" + +[[elements]] +condition = "tools_enabled == true" +default = false +help = "Enable tool execution caching" +name = "tools_cache_enabled" +nickel_path = ["tools", "cache", "enabled"] +prompt = "Enable Tool Caching" +type = "confirm" + +[[elements]] +condition = "tools_enabled == true && tools_cache_enabled == true" +default = 3600 +help = "Tool cache TTL in seconds" +min = 60 +name = "tools_cache_ttl" +nickel_path = ["tools", "cache", "ttl"] +prompt = "Cache TTL (seconds)" +type = "number" diff --git a/.typedialog/platform/forms/fragments/monitoring-section.toml b/.typedialog/platform/forms/fragments/monitoring-section.toml new file mode 100644 index 0000000..0f1668b --- /dev/null +++ b/.typedialog/platform/forms/fragments/monitoring-section.toml @@ -0,0 +1,37 @@ +# Monitoring Configuration Fragment +# Optional for all services + +[[elements]] +border_top = true +border_bottom = false +name = "monitoring_section_header" +title = "πŸ“Š Monitoring Configuration" +type = "section_header" + +[[elements]] +default = false +help = "Enable monitoring and metrics collection" +name = "monitoring_enabled" +nickel_path = ["monitoring", "enabled"] +prompt = "Enable Monitoring" +type = "confirm" + +[[elements]] +condition = "monitoring_enabled == true" +default = true +help = "Enable metrics collection from this service" +name = "monitoring_metrics_enabled" +nickel_path = ["monitoring", "metrics", "enabled"] +prompt = "Enable Metrics Collection" +type = "confirm" + +[[elements]] +condition = "monitoring_enabled == true && monitoring_metrics_enabled == true" +default = 60 +help = "Metrics collection interval in seconds (range: ${constraint.common.monitoring.metrics_interval.min}-${constraint.common.monitoring.metrics_interval.max})" +min = "${constraint.common.monitoring.metrics_interval.min}" +max = "${constraint.common.monitoring.metrics_interval.max}" +name = "monitoring_metrics_interval" +nickel_path = ["monitoring", "metrics", "interval"] +prompt = "Metrics Collection Interval (seconds)" +type = "number" diff --git a/.typedialog/platform/forms/fragments/orchestrator/batch-section.toml b/.typedialog/platform/forms/fragments/orchestrator/batch-section.toml new file mode 100644 index 0000000..fefeeb6 --- /dev/null +++ b/.typedialog/platform/forms/fragments/orchestrator/batch-section.toml @@ -0,0 +1,93 @@ +# Orchestrator Batch Workflow Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "batch_section_header" +title = "πŸ”„ Batch Workflow Configuration" +type = "section_header" + +[[elements]] +default = 5 +help = "Parallel operation limit for batch jobs (range: ${constraint.orchestrator.batch.parallel_limit.min}-${constraint.orchestrator.batch.parallel_limit.max})" +max = "${constraint.orchestrator.batch.parallel_limit.max}" +min = "${constraint.orchestrator.batch.parallel_limit.min}" +name = "batch_parallel_limit" +nickel_path = ["batch", "parallel_limit"] +prompt = "Parallel Limit" +type = "number" + +[[elements]] +default = 1800000 +help = "Batch operation timeout in milliseconds (range: ${constraint.orchestrator.batch.operation_timeout.min}-${constraint.orchestrator.batch.operation_timeout.max})" +min = "${constraint.orchestrator.batch.operation_timeout.min}" +max = "${constraint.orchestrator.batch.operation_timeout.max}" +name = "batch_operation_timeout" +nickel_path = ["batch", "operation_timeout"] +prompt = "Operation Timeout (ms)" +type = "number" + +[[elements]] +default = true +help = "Enable checkpoint support for batch recovery" +name = "batch_checkpointing_enabled" +nickel_path = ["batch", "checkpointing", "enabled"] +prompt = "Enable Checkpointing" +type = "confirm" + +[[elements]] +condition = "batch_checkpointing_enabled == true" +default = 100 +help = "Checkpoint interval (number of operations before checkpoint)" +min = 10 +name = "batch_checkpoint_interval" +nickel_path = ["batch", "checkpointing", "interval"] +prompt = "Checkpoint Interval" +type = "number" + +[[elements]] +condition = "batch_checkpointing_enabled == true" +default = 10 +help = "Maximum number of checkpoints to keep" +min = 1 +name = "batch_checkpoint_max_checkpoints" +nickel_path = ["batch", "checkpointing", "max_checkpoints"] +prompt = "Max Checkpoints" +type = "number" + +[[elements]] +default = true +help = "Enable rollback strategy for failed batches" +name = "batch_rollback_enabled" +nickel_path = ["batch", "rollback", "enabled"] +prompt = "Enable Rollback" +type = "confirm" + +[[elements]] +condition = "batch_rollback_enabled == true" +default = "checkpoint_based" +help = "Rollback strategy (checkpoint_based, full, partial)" +name = "batch_rollback_strategy" +nickel_path = ["batch", "rollback", "strategy"] +options = ["checkpoint_based", "full", "partial"] +prompt = "Rollback Strategy" +type = "select" + +[[elements]] +condition = "batch_rollback_enabled == true" +default = 5 +help = "Maximum rollback depth" +max = 20 +min = 1 +name = "batch_rollback_max_depth" +nickel_path = ["batch", "rollback", "max_rollback_depth"] +prompt = "Max Rollback Depth" +type = "number" + +[[elements]] +default = false +help = "Enable batch operation metrics" +name = "batch_metrics" +nickel_path = ["batch", "metrics"] +prompt = "Batch Metrics" +type = "confirm" diff --git a/.typedialog/platform/forms/fragments/orchestrator/extensions-section.toml b/.typedialog/platform/forms/fragments/orchestrator/extensions-section.toml new file mode 100644 index 0000000..4e9335c --- /dev/null +++ b/.typedialog/platform/forms/fragments/orchestrator/extensions-section.toml @@ -0,0 +1,182 @@ +# Orchestrator Extensions Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "extensions_section_header" +title = "πŸ”Œ Extensions Configuration" +type = "section_header" + +# Extension Auto-Loading +[[elements]] +default = false +help = "Automatically load extensions from registry at startup" +name = "auto_load_extensions" +nickel_path = ["orchestrator", "extensions", "auto_load"] +prompt = "Auto-Load Extensions" +type = "confirm" + +# OCI Registry Configuration (conditional on auto-load) +[[elements]] +condition = "auto_load_extensions == true" +default = "http://localhost:5000" +help = "OCI registry URL for discovering extensions (e.g., http://harbor:5000)" +name = "oci_registry_url" +nickel_path = ["orchestrator", "extensions", "oci_registry_url"] +prompt = "OCI Registry URL" +required = true +type = "text" + +[[elements]] +condition = "auto_load_extensions == true" +default = "provisioning" +help = "Namespace/project in OCI registry for extensions" +name = "oci_namespace" +nickel_path = ["orchestrator", "extensions", "oci_namespace"] +prompt = "OCI Namespace" +required = true +type = "text" + +[[elements]] +condition = "auto_load_extensions == true" +default = "" +help = "OCI registry authentication username (leave empty for anonymous)" +name = "oci_registry_username" +nickel_path = ["orchestrator", "extensions", "oci_registry_username"] +prompt = "OCI Registry Username" +type = "text" + +[[elements]] +condition = "auto_load_extensions == true" +default = "" +help = "OCI registry authentication password (leave empty for anonymous)" +name = "oci_registry_password" +nickel_path = ["orchestrator", "extensions", "oci_registry_password"] +prompt = "OCI Registry Password" +type = "password" + +# Extension Discovery Configuration +[[elements]] +condition = "auto_load_extensions == true" +default = 3600 +help = "Extension discovery interval in seconds (range: 300-86400)" +max = 86400 +min = 300 +name = "extensions_discovery_interval" +nickel_path = ["orchestrator", "extensions", "discovery_interval_seconds"] +prompt = "Discovery Interval (seconds)" +type = "number" + +[[elements]] +condition = "auto_load_extensions == true" +default = 5 +help = "Maximum number of concurrent extension loads (range: ${constraint.orchestrator.extensions.max_concurrent.min}-${constraint.orchestrator.extensions.max_concurrent.max})" +max = "${constraint.orchestrator.extensions.max_concurrent.max}" +min = "${constraint.orchestrator.extensions.max_concurrent.min}" +name = "extensions_max_concurrent" +nickel_path = ["orchestrator", "extensions", "max_concurrent"] +prompt = "Max Concurrent Extensions" +type = "number" + +# Extension Execution Settings +[[elements]] +condition = "auto_load_extensions == true" +default = 30000 +help = "Timeout for extension initialization in milliseconds (range: 1000-300000)" +max = 300000 +min = 1000 +name = "extensions_init_timeout" +nickel_path = ["orchestrator", "extensions", "init_timeout_ms"] +prompt = "Init Timeout (ms)" +type = "number" + +[[elements]] +condition = "auto_load_extensions == true" +default = false +help = "Enable sandboxed execution for untrusted extensions" +name = "extensions_sandbox_enabled" +nickel_path = ["orchestrator", "extensions", "sandbox", "enabled"] +prompt = "Enable Sandbox Mode" +type = "confirm" + +[[elements]] +condition = "auto_load_extensions == true && extensions_sandbox_enabled == true" +default = true +help = "Restrict network access for sandboxed extensions" +name = "extensions_sandbox_restrict_network" +nickel_path = ["orchestrator", "extensions", "sandbox", "restrict_network"] +prompt = "Restrict Network Access" +type = "confirm" + +[[elements]] +condition = "auto_load_extensions == true && extensions_sandbox_enabled == true" +default = 512 +help = "Maximum memory for sandboxed extension in MB (range: 64-4096)" +max = 4096 +min = 64 +name = "extensions_sandbox_max_memory_mb" +nickel_path = ["orchestrator", "extensions", "sandbox", "max_memory_mb"] +prompt = "Max Memory (MB)" +type = "number" + +[[elements]] +condition = "auto_load_extensions == true && extensions_sandbox_enabled == true" +default = 1 +help = "Maximum CPU cores for sandboxed extension" +min = 0.1 +max = 8 +name = "extensions_sandbox_max_cpu" +nickel_path = ["orchestrator", "extensions", "sandbox", "max_cpu"] +prompt = "Max CPU Cores" +type = "number" + +# Extension Versioning and Compatibility +[[elements]] +condition = "auto_load_extensions == true" +default = true +help = "Enable version compatibility checking" +name = "extensions_version_check_enabled" +nickel_path = ["orchestrator", "extensions", "version_check", "enabled"] +prompt = "Enable Version Check" +type = "confirm" + +[[elements]] +condition = "auto_load_extensions == true" +default = false +help = "Allow prerelease/beta extension versions" +name = "extensions_allow_prerelease" +nickel_path = ["orchestrator", "extensions", "allow_prerelease"] +prompt = "Allow Prerelease Versions" +type = "confirm" + +# Extension Health Checking +[[elements]] +condition = "auto_load_extensions == true" +default = true +help = "Enable health checks for loaded extensions" +name = "extensions_health_check_enabled" +nickel_path = ["orchestrator", "extensions", "health_check", "enabled"] +prompt = "Enable Health Checks" +type = "confirm" + +[[elements]] +condition = "auto_load_extensions == true && extensions_health_check_enabled == true" +default = 30000 +help = "Health check interval in milliseconds (range: 5000-300000)" +max = 300000 +min = 5000 +name = "extensions_health_check_interval" +nickel_path = ["orchestrator", "extensions", "health_check", "interval_ms"] +prompt = "Health Check Interval (ms)" +type = "number" + +[[elements]] +condition = "auto_load_extensions == true && extensions_health_check_enabled == true" +default = 3 +help = "Number of failed health checks before unloading extension" +min = 1 +max = 10 +name = "extensions_health_check_failure_threshold" +nickel_path = ["orchestrator", "extensions", "health_check", "failure_threshold"] +prompt = "Failure Threshold" +type = "number" diff --git a/.typedialog/platform/forms/fragments/orchestrator/performance-section.toml b/.typedialog/platform/forms/fragments/orchestrator/performance-section.toml new file mode 100644 index 0000000..f7ba18f --- /dev/null +++ b/.typedialog/platform/forms/fragments/orchestrator/performance-section.toml @@ -0,0 +1,230 @@ +# Orchestrator Performance Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "performance_section_header" +title = "⚑ Performance Configuration" +type = "section_header" + +# CPU and Memory Settings +[[elements]] +default = false +help = "Enable CPU affinity binding for threads" +name = "cpu_affinity_enabled" +nickel_path = ["orchestrator", "performance", "cpu_affinity", "enabled"] +prompt = "Enable CPU Affinity" +type = "confirm" + +[[elements]] +condition = "cpu_affinity_enabled == true" +default = "round_robin" +help = "CPU core assignment strategy" +name = "cpu_affinity_strategy" +nickel_path = ["orchestrator", "performance", "cpu_affinity", "strategy"] +options = ["round_robin", "sequential", "interleave"] +prompt = "CPU Affinity Strategy" +type = "select" + +# Memory Configuration +[[elements]] +default = false +help = "Enable JVM-style memory limit enforcement" +name = "memory_limits_enabled" +nickel_path = ["orchestrator", "performance", "memory_limits", "enabled"] +prompt = "Enable Memory Limits" +type = "confirm" + +[[elements]] +condition = "memory_limits_enabled == true" +default = 4096 +help = "Maximum heap memory in MB" +min = 256 +max = 131072 +name = "memory_max_heap_mb" +nickel_path = ["orchestrator", "performance", "memory_limits", "max_heap_mb"] +prompt = "Max Heap Memory (MB)" +type = "number" + +[[elements]] +condition = "memory_limits_enabled == true" +default = 1024 +help = "Initial heap memory allocation in MB (range: 128-131072)" +max = 131072 +min = 128 +name = "memory_initial_heap_mb" +nickel_path = ["orchestrator", "performance", "memory_limits", "initial_heap_mb"] +prompt = "Initial Heap Memory (MB)" +type = "number" + +[[elements]] +condition = "memory_limits_enabled == true" +default = 80 +help = "Garbage collection trigger threshold (%)" +min = 50 +max = 95 +name = "memory_gc_threshold_percent" +nickel_path = ["orchestrator", "performance", "memory_limits", "gc_threshold_percent"] +prompt = "GC Threshold (%)" +type = "number" + +# Profiling Settings +[[elements]] +default = false +help = "Enable performance profiling (CPU, memory, I/O)" +name = "profiling_enabled" +nickel_path = ["orchestrator", "performance", "profiling", "enabled"] +prompt = "Enable Profiling" +type = "confirm" + +[[elements]] +condition = "profiling_enabled == true" +default = "sampling" +help = "Profiling mode (sampling = low overhead, instrumentation = detailed)" +name = "profiling_mode" +nickel_path = ["orchestrator", "performance", "profiling", "mode"] +options = ["sampling", "instrumentation"] +prompt = "Profiling Mode" +type = "select" + +[[elements]] +condition = "profiling_enabled == true" +default = 100 +help = "Profiling sampling rate in Hz (samples per second)" +min = 10 +max = 1000 +name = "profiling_sample_rate" +nickel_path = ["orchestrator", "performance", "profiling", "sample_rate_hz"] +prompt = "Sampling Rate (Hz)" +type = "number" + +[[elements]] +condition = "profiling_enabled == true" +default = "json" +help = "Profiling output format" +name = "profiling_format" +nickel_path = ["orchestrator", "performance", "profiling", "format"] +options = ["json", "protobuf", "pprof"] +prompt = "Profiling Format" +type = "select" + +[[elements]] +condition = "profiling_enabled == true" +default = "/var/lib/provisioning/orchestrator/profiles" +help = "Directory for profiling data output" +name = "profiling_output_path" +nickel_path = ["orchestrator", "performance", "profiling", "output_path"] +prompt = "Profiling Output Path" +type = "text" + +[[elements]] +condition = "profiling_enabled == true" +default = true +help = "Enable memory profiling (allocations, heap usage)" +name = "profiling_memory_enabled" +nickel_path = ["orchestrator", "performance", "profiling", "memory_profiling", "enabled"] +prompt = "Enable Memory Profiling" +type = "confirm" + +[[elements]] +condition = "profiling_enabled == true && profiling_memory_enabled == true" +default = 512 +help = "Minimum allocation size to profile in KB (range: 1-1048576)" +max = 1048576 +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" + +# Caching and Optimization +[[elements]] +default = true +help = "Enable inline caching for hot paths" +name = "inline_cache_enabled" +nickel_path = ["orchestrator", "performance", "inline_cache", "enabled"] +prompt = "Enable Inline Cache" +type = "confirm" + +[[elements]] +condition = "inline_cache_enabled == true" +default = 10000 +help = "Maximum inline cache entries (range: 1000-1000000)" +max = 1000000 +min = 1000 +name = "inline_cache_max_entries" +nickel_path = ["orchestrator", "performance", "inline_cache", "max_entries"] +prompt = "Max Cache Entries" +type = "number" + +[[elements]] +condition = "inline_cache_enabled == true" +default = 3600 +help = "Inline cache TTL in seconds (range: 60-86400)" +max = 86400 +min = 60 +name = "inline_cache_ttl" +nickel_path = ["orchestrator", "performance", "inline_cache", "ttl_seconds"] +prompt = "Cache TTL (seconds)" +type = "number" + +# Thread Pool Configuration +[[elements]] +default = 4 +help = "Number of worker threads for task execution" +min = 1 +max = 256 +name = "thread_pool_size" +nickel_path = ["orchestrator", "performance", "thread_pool", "size"] +prompt = "Thread Pool Size" +type = "number" + +[[elements]] +default = 128 +help = "Work queue size per worker thread" +min = 8 +max = 10000 +name = "thread_pool_queue_size" +nickel_path = ["orchestrator", "performance", "thread_pool", "queue_size"] +prompt = "Work Queue Size" +type = "number" + +[[elements]] +default = "work_stealing" +help = "Thread pool scheduling strategy" +name = "thread_pool_strategy" +nickel_path = ["orchestrator", "performance", "thread_pool", "strategy"] +options = ["work_stealing", "fifo", "priority"] +prompt = "Thread Pool Strategy" +type = "select" + +# I/O Optimization +[[elements]] +default = true +help = "Enable async I/O operations" +name = "async_io_enabled" +nickel_path = ["orchestrator", "performance", "async_io", "enabled"] +prompt = "Enable Async I/O" +type = "confirm" + +[[elements]] +condition = "async_io_enabled == true" +default = 4 +help = "Number of I/O worker threads" +min = 1 +max = 32 +name = "async_io_worker_threads" +nickel_path = ["orchestrator", "performance", "async_io", "worker_threads"] +prompt = "I/O Worker Threads" +type = "number" + +[[elements]] +condition = "async_io_enabled == true" +default = 65536 +help = "Maximum I/O operations in flight (range: 256-1048576)" +max = 1048576 +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" diff --git a/.typedialog/platform/forms/fragments/orchestrator/queue-section.toml b/.typedialog/platform/forms/fragments/orchestrator/queue-section.toml new file mode 100644 index 0000000..23e686a --- /dev/null +++ b/.typedialog/platform/forms/fragments/orchestrator/queue-section.toml @@ -0,0 +1,72 @@ +# Orchestrator Queue Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "queue_section_header" +title = "πŸ“¦ Queue Configuration" +type = "section_header" + +[[elements]] +default = 5 +help = "Maximum number of concurrent tasks running simultaneously (range: ${constraint.orchestrator.queue.concurrent_tasks.min}-${constraint.orchestrator.queue.concurrent_tasks.max})" +max = "${constraint.orchestrator.queue.concurrent_tasks.max}" +min = "${constraint.orchestrator.queue.concurrent_tasks.min}" +name = "queue_max_concurrent_tasks" +nickel_path = ["queue", "max_concurrent_tasks"] +prompt = "Max Concurrent Tasks" +type = "number" + +[[elements]] +default = 3 +help = "Number of retry attempts for failed tasks (range: ${constraint.orchestrator.queue.retry_attempts.min}-${constraint.orchestrator.queue.retry_attempts.max})" +min = "${constraint.orchestrator.queue.retry_attempts.min}" +max = "${constraint.orchestrator.queue.retry_attempts.max}" +name = "queue_retry_attempts" +nickel_path = ["queue", "retry_attempts"] +prompt = "Retry Attempts" +type = "number" + +[[elements]] +default = 5000 +help = "Delay in milliseconds between retry attempts (range: ${constraint.orchestrator.queue.retry_delay.min}-${constraint.orchestrator.queue.retry_delay.max})" +min = "${constraint.orchestrator.queue.retry_delay.min}" +max = "${constraint.orchestrator.queue.retry_delay.max}" +name = "queue_retry_delay" +nickel_path = ["queue", "retry_delay"] +prompt = "Retry Delay (ms)" +type = "number" + +[[elements]] +default = 3600000 +help = "Task timeout in milliseconds (range: ${constraint.orchestrator.queue.task_timeout.min}-${constraint.orchestrator.queue.task_timeout.max})" +min = "${constraint.orchestrator.queue.task_timeout.min}" +max = "${constraint.orchestrator.queue.task_timeout.max}" +name = "queue_task_timeout" +nickel_path = ["queue", "task_timeout"] +prompt = "Task Timeout (ms)" +type = "number" + +[[elements]] +default = true +help = "Enable persistent queue storage" +name = "queue_persist" +nickel_path = ["queue", "persist"] +prompt = "Persistent Queue" +type = "confirm" + +[[elements]] +default = false +help = "Enable priority queue support for task ordering" +name = "queue_priority_queue" +nickel_path = ["queue", "priority_queue"] +prompt = "Priority Queue" +type = "confirm" + +[[elements]] +default = false +help = "Enable queue metrics collection" +name = "queue_metrics" +nickel_path = ["queue", "metrics"] +prompt = "Queue Metrics" +type = "confirm" diff --git a/.typedialog/platform/forms/fragments/orchestrator/storage-section.toml b/.typedialog/platform/forms/fragments/orchestrator/storage-section.toml new file mode 100644 index 0000000..857742a --- /dev/null +++ b/.typedialog/platform/forms/fragments/orchestrator/storage-section.toml @@ -0,0 +1,173 @@ +# Orchestrator Storage Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "storage_section_header" +title = "πŸ’Ύ Storage Configuration" +type = "section_header" + +# Storage Backend Selection +[[elements]] +default = "filesystem" +help = "Storage backend for workflow state and artifacts" +name = "storage_backend" +nickel_path = ["orchestrator", "storage", "backend"] +options = ["filesystem", "surrealdb_embedded", "surrealdb_server"] +prompt = "Storage Backend" +type = "select" + +# Filesystem Storage (conditional) +[[elements]] +condition = "storage_backend == 'filesystem'" +default = "/var/lib/provisioning/orchestrator/data" +help = "Path for local filesystem storage (absolute path required)" +name = "storage_path" +nickel_path = ["orchestrator", "storage", "path"] +prompt = "Storage Path" +required = true +type = "text" + +# SurrealDB Embedded (conditional) +[[elements]] +condition = "storage_backend == 'surrealdb_embedded'" +default = "/var/lib/provisioning/orchestrator/surrealdb" +help = "Path for embedded SurrealDB data directory" +name = "surrealdb_embedded_path" +nickel_path = ["orchestrator", "storage", "path"] +prompt = "SurrealDB Data Path" +required = true +type = "text" + +# SurrealDB Server (conditional) +[[elements]] +condition = "storage_backend == 'surrealdb_server'" +default = "http://localhost:8000" +help = "URL for SurrealDB server (e.g., http://surrealdb:8000)" +name = "surrealdb_url" +nickel_path = ["orchestrator", "storage", "surrealdb_url"] +prompt = "SurrealDB URL" +required = true +type = "text" + +[[elements]] +condition = "storage_backend == 'surrealdb_server'" +default = "provisioning" +help = "SurrealDB namespace" +name = "surrealdb_namespace" +nickel_path = ["orchestrator", "storage", "surrealdb_namespace"] +prompt = "Namespace" +required = true +type = "text" + +[[elements]] +condition = "storage_backend == 'surrealdb_server'" +default = "orchestrator" +help = "SurrealDB database name" +name = "surrealdb_database" +nickel_path = ["orchestrator", "storage", "surrealdb_database"] +prompt = "Database" +required = true +type = "text" + +# Storage Cache Configuration +[[elements]] +default = false +help = "Enable storage caching for improved performance" +name = "storage_cache_enabled" +nickel_path = ["orchestrator", "storage", "cache", "enabled"] +prompt = "Enable Storage Cache" +type = "confirm" + +[[elements]] +condition = "storage_cache_enabled == true" +default = "lru" +help = "Cache eviction policy" +name = "storage_cache_eviction_policy" +nickel_path = ["orchestrator", "storage", "cache", "eviction_policy"] +options = ["lru", "lfu", "fifo"] +prompt = "Cache Eviction Policy" +type = "select" + +[[elements]] +condition = "storage_cache_enabled == true" +default = 3600 +help = "Cache TTL in seconds (range: 60-86400)" +max = 86400 +min = 60 +name = "storage_cache_ttl" +nickel_path = ["orchestrator", "storage", "cache", "ttl"] +prompt = "Cache TTL (seconds)" +type = "number" + +[[elements]] +condition = "storage_cache_enabled == true" +default = 1000 +help = "Maximum cache entries (range: 10-1000000)" +max = 1000000 +min = 10 +name = "storage_cache_max_entries" +nickel_path = ["orchestrator", "storage", "cache", "max_entries"] +prompt = "Max Cache Entries" +type = "number" + +# Storage Compression Configuration +[[elements]] +default = false +help = "Enable compression for stored data" +name = "storage_compression_enabled" +nickel_path = ["orchestrator", "storage", "compression", "enabled"] +prompt = "Enable Compression" +type = "confirm" + +[[elements]] +condition = "storage_compression_enabled == true" +default = "snappy" +help = "Compression algorithm" +name = "storage_compression_algorithm" +nickel_path = ["orchestrator", "storage", "compression", "algorithm"] +options = ["snappy", "zstd", "gzip"] +prompt = "Compression Algorithm" +type = "select" + +[[elements]] +condition = "storage_compression_enabled == true && storage_compression_algorithm == 'zstd'" +default = 3 +help = "Compression level (1-19, higher = better compression but slower)" +min = 1 +max = 19 +name = "storage_compression_level" +nickel_path = ["orchestrator", "storage", "compression", "level"] +prompt = "Compression Level" +type = "number" + +# Storage Garbage Collection +[[elements]] +default = true +help = "Enable automatic garbage collection of orphaned artifacts" +name = "storage_gc_enabled" +nickel_path = ["orchestrator", "storage", "gc", "enabled"] +prompt = "Enable Garbage Collection" +type = "confirm" + +[[elements]] +condition = "storage_gc_enabled == true" +default = 604800 +help = "Retention period for artifacts in seconds (default: 7 days, range: 3600-31536000)" +max = 31536000 +min = 3600 +name = "storage_gc_retention" +nickel_path = ["orchestrator", "storage", "gc", "retention_seconds"] +prompt = "GC Retention (seconds)" +type = "number" + +[[elements]] +condition = "storage_gc_enabled == true" +default = 3600 +help = "Garbage collection interval in seconds (default: 1 hour, range: 300-86400)" +max = 86400 +min = 300 +name = "storage_gc_interval" +nickel_path = ["orchestrator", "storage", "gc", "interval_seconds"] +prompt = "GC Interval (seconds)" +type = "number" diff --git a/.typedialog/platform/forms/fragments/provisioning-daemon/actions.toml b/.typedialog/platform/forms/fragments/provisioning-daemon/actions.toml new file mode 100644 index 0000000..9e00e42 --- /dev/null +++ b/.typedialog/platform/forms/fragments/provisioning-daemon/actions.toml @@ -0,0 +1,48 @@ +# Provisioning Daemon Actions Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "daemon_actions_header" +title = "βœ“ Actions Configuration" +type = "section_header" + +[[elements]] +default = true +help = "Auto-cleanup completed tasks" +name = "daemon_actions_auto_cleanup" +nickel_path = ["provisioning_daemon", "actions", "auto_cleanup"] +prompt = "Auto-cleanup" +type = "confirm" + +[[elements]] +default = false +help = "Auto-update provisioning system" +name = "daemon_actions_auto_update" +nickel_path = ["provisioning_daemon", "actions", "auto_update"] +prompt = "Auto-update" +type = "confirm" + +[[elements]] +default = true +help = "Sync workspace configuration" +name = "daemon_actions_workspace_sync" +nickel_path = ["provisioning_daemon", "actions", "workspace_sync"] +prompt = "Workspace Sync" +type = "confirm" + +[[elements]] +default = true +help = "Cleanup ephemeral resources" +name = "daemon_actions_ephemeral_cleanup" +nickel_path = ["provisioning_daemon", "actions", "ephemeral_cleanup"] +prompt = "Ephemeral Cleanup" +type = "confirm" + +[[elements]] +default = true +help = "Perform health checks" +name = "daemon_actions_health_checks" +nickel_path = ["provisioning_daemon", "actions", "health_checks"] +prompt = "Health Checks" +type = "confirm" diff --git a/.typedialog/platform/forms/fragments/provisioning-daemon/daemon.toml b/.typedialog/platform/forms/fragments/provisioning-daemon/daemon.toml new file mode 100644 index 0000000..ea28184 --- /dev/null +++ b/.typedialog/platform/forms/fragments/provisioning-daemon/daemon.toml @@ -0,0 +1,36 @@ +# Provisioning Daemon Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "daemon_config_header" +title = "βš™οΈ Daemon Configuration" +type = "section_header" + +[[elements]] +default = true +help = "Enable provisioning daemon" +name = "daemon_enabled" +nickel_path = ["provisioning_daemon", "daemon", "enabled"] +prompt = "Enable Daemon" +type = "confirm" + +[[elements]] +default = 30 +help = "Polling interval in seconds" +max = 3600 +min = 5 +name = "daemon_poll_interval" +nickel_path = ["provisioning_daemon", "daemon", "poll_interval"] +prompt = "Poll Interval (seconds)" +type = "number" + +[[elements]] +default = 4 +help = "Maximum worker threads" +max = 32 +min = 1 +name = "daemon_max_workers" +nickel_path = ["provisioning_daemon", "daemon", "max_workers"] +prompt = "Max Workers" +type = "number" diff --git a/.typedialog/platform/forms/fragments/provisioning-daemon/health.toml b/.typedialog/platform/forms/fragments/provisioning-daemon/health.toml new file mode 100644 index 0000000..f550931 --- /dev/null +++ b/.typedialog/platform/forms/fragments/provisioning-daemon/health.toml @@ -0,0 +1,38 @@ +# Provisioning Daemon Health Check Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "daemon_health_header" +title = "❀️ Health Check Configuration" +type = "section_header" + +[[elements]] +default = 60000 +help = "Health check interval in milliseconds" +max = 300000 +min = 5000 +name = "daemon_health_check_interval" +nickel_path = ["provisioning_daemon", "health", "check_interval"] +prompt = "Check Interval (ms)" +type = "number" + +[[elements]] +default = 30000 +help = "Health check timeout in milliseconds" +max = 60000 +min = 1000 +name = "daemon_health_check_timeout" +nickel_path = ["provisioning_daemon", "health", "timeout"] +prompt = "Timeout (ms)" +type = "number" + +[[elements]] +default = 3 +help = "Failure threshold before marking unhealthy" +max = 10 +min = 1 +name = "daemon_health_failure_threshold" +nickel_path = ["provisioning_daemon", "health", "failure_threshold"] +prompt = "Failure Threshold" +type = "number" diff --git a/.typedialog/platform/forms/fragments/provisioning-daemon/logging.toml b/.typedialog/platform/forms/fragments/provisioning-daemon/logging.toml new file mode 100644 index 0000000..4754f70 --- /dev/null +++ b/.typedialog/platform/forms/fragments/provisioning-daemon/logging.toml @@ -0,0 +1,43 @@ +# Provisioning Daemon Logging Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "daemon_logging_header" +title = "πŸ“ Logging Configuration" +type = "section_header" + +[[elements]] +default = "info" +help = "Logging level" +name = "daemon_logging_level" +nickel_path = ["provisioning_daemon", "logging", "level"] +options = ["trace", "debug", "info", "warn", "error"] +prompt = "Log Level" +type = "select" + +[[elements]] +default = "/var/log/provisioning/daemon.log" +help = "Log file path" +name = "daemon_logging_file" +nickel_path = ["provisioning_daemon", "logging", "file"] +prompt = "Log File" +required = true +type = "text" + +[[elements]] +default = "json" +help = "Log format" +name = "daemon_logging_format" +nickel_path = ["provisioning_daemon", "logging", "format"] +options = ["json", "text"] +prompt = "Log Format" +type = "select" + +[[elements]] +default = false +help = "Send logs to syslog" +name = "daemon_logging_syslog" +nickel_path = ["provisioning_daemon", "logging", "syslog"] +prompt = "Enable Syslog" +type = "confirm" diff --git a/.typedialog/platform/forms/fragments/provisioning-daemon/workers.toml b/.typedialog/platform/forms/fragments/provisioning-daemon/workers.toml new file mode 100644 index 0000000..2ba9994 --- /dev/null +++ b/.typedialog/platform/forms/fragments/provisioning-daemon/workers.toml @@ -0,0 +1,38 @@ +# Provisioning Daemon Worker Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "daemon_workers_header" +title = "πŸ‘· Worker Configuration" +type = "section_header" + +[[elements]] +default = 4 +help = "Worker pool size" +max = 32 +min = 1 +name = "daemon_worker_pool_size" +nickel_path = ["provisioning_daemon", "workers", "pool_size"] +prompt = "Pool Size" +type = "number" + +[[elements]] +default = 1000 +help = "Task queue capacity" +max = 100000 +min = 10 +name = "daemon_worker_task_queue_size" +nickel_path = ["provisioning_daemon", "workers", "task_queue_size"] +prompt = "Queue Size" +type = "number" + +[[elements]] +default = 300000 +help = "Worker timeout in milliseconds" +max = 3600000 +min = 10000 +name = "daemon_worker_timeout" +nickel_path = ["provisioning_daemon", "workers", "timeout"] +prompt = "Timeout (ms)" +type = "number" diff --git a/.typedialog/platform/forms/fragments/provisioning/.typedialog/provisioning/platform/scripts/README.md b/.typedialog/platform/forms/fragments/provisioning/.typedialog/provisioning/platform/scripts/README.md new file mode 100644 index 0000000..4cef4e3 --- /dev/null +++ b/.typedialog/platform/forms/fragments/provisioning/.typedialog/provisioning/platform/scripts/README.md @@ -0,0 +1,98 @@ +# TypeDialog + Nickel Configuration Scripts + +Phase 8 Nushell automation scripts for interactive configuration workflow, config generation, validation, and deployment. + +## Quick Start + +```bash +# 1. Interactive Configuration (TypeDialog) +nu scripts/configure.nu orchestrator solo + +# 2. Generate TOML configs +nu scripts/generate-configs.nu orchestrator solo + +# 3. Validate configuration +nu scripts/validate-config.nu provisioning/.typedialog/provisioning/platform/values/orchestrator.solo.ncl + +# 4. Render Docker Compose +nu scripts/render-docker-compose.nu solo + +# 5. Full deployment workflow +nu scripts/install-services.nu orchestrator solo --docker +``` + +## Scripts Overview + +### Shared Helpers +- **ansi.nu** - ANSI color and emoji output formatting +- **paths.nu** - Path validation and directory structure helpers +- **external.nu** - Safe external command execution with error handling + +### Core Configuration Scripts +- **configure.nu** - Interactive TypeDialog configuration wizard +- **generate-configs.nu** - Export Nickel configs to TOML +- **validate-config.nu** - Validate Nickel configuration + +### Rendering Scripts +- **render-docker-compose.nu** - Render Docker Compose from Nickel templates +- **render-kubernetes.nu** - Render Kubernetes manifests from Nickel templates + +### Deployment & Monitoring Scripts +- **install-services.nu** - Full deployment orchestration +- **detect-services.nu** - Auto-detect running services + +## Supported Services +- orchestrator (port 9090) +- control-center (port 8080) +- mcp-server (port 8888) +- installer (port 8000) + +## Supported Deployment Modes +- solo (2 CPU, 4GB RAM) +- multiuser (4 CPU, 8GB RAM) +- cicd (8 CPU, 16GB RAM) +- enterprise (16+ CPU, 32+ GB RAM) + +## Nushell Compliance +All scripts follow Nushell 0.109.0+ guidelines with proper type signatures, error handling, and no try-catch blocks. + +## Examples + +### Single Service Configuration +```bash +nu scripts/configure.nu orchestrator solo --backend web +nu scripts/validate-config.nu provisioning/.typedialog/provisioning/platform/values/orchestrator.solo.ncl +nu scripts/generate-configs.nu orchestrator solo +cargo run -p orchestrator -- --config provisioning/platform/config/orchestrator.solo.toml +``` + +### Docker Compose Deployment +```bash +nu scripts/generate-configs.nu orchestrator multiuser +nu scripts/render-docker-compose.nu multiuser +docker-compose -f provisioning/platform/infrastructure/docker/docker-compose.multiuser.yml up -d +``` + +### Kubernetes Deployment +```bash +nu scripts/generate-configs.nu orchestrator enterprise +nu scripts/render-kubernetes.nu enterprise --namespace production +nu scripts/install-services.nu all enterprise --kubernetes --namespace production +``` + +## Phase 8 Status + +βœ… Phase 8.A: Shared helper modules +βœ… Phase 8.B: Core configuration scripts +βœ… Phase 8.C: Rendering scripts +βœ… Phase 8.D: Deployment orchestration +βœ… Phase 8.E: Testing and documentation + +## Requirements + +- Nushell 0.109.1+ +- Nickel 1.15.1+ +- TypeDialog CLI +- yq v4.50.1+ +- Docker (optional) +- kubectl (optional) diff --git a/.typedialog/platform/forms/fragments/rag/embeddings.toml b/.typedialog/platform/forms/fragments/rag/embeddings.toml new file mode 100644 index 0000000..b3fe18a --- /dev/null +++ b/.typedialog/platform/forms/fragments/rag/embeddings.toml @@ -0,0 +1,56 @@ +# RAG Embeddings Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "rag_embeddings_header" +title = "🧠 Embeddings Configuration" +type = "section_header" + +[[elements]] +default = "local" +help = "Embedding model provider (openai, local, anthropic)" +name = "rag_embeddings_provider" +nickel_path = ["rag", "embeddings", "provider"] +options = ["openai", "local", "anthropic"] +prompt = "Provider" +required = true +type = "select" + +[[elements]] +default = "all-MiniLM-L6-v2" +help = "Embedding model name" +name = "rag_embeddings_model" +nickel_path = ["rag", "embeddings", "model"] +prompt = "Model" +required = true +type = "text" + +[[elements]] +default = 384 +help = "Embedding dimension (384, 768, 1536, 3072)" +name = "rag_embeddings_dimension" +nickel_path = ["rag", "embeddings", "dimension"] +options = [384, 768, 1536, 3072] +prompt = "Dimension" +type = "select" + +[[elements]] +default = 32 +help = "Batch size for embedding operations" +max = 1000 +min = 1 +name = "rag_embeddings_batch_size" +nickel_path = ["rag", "embeddings", "batch_size"] +prompt = "Batch Size" +type = "number" + +[[elements]] +condition = "rag_embeddings_provider != 'local'" +default = "" +help = "API key for embedding service" +name = "rag_embeddings_api_key" +nickel_path = ["rag", "embeddings", "api_key"] +prompt = "API Key" +required = false +type = "password" diff --git a/.typedialog/platform/forms/fragments/rag/ingestion.toml b/.typedialog/platform/forms/fragments/rag/ingestion.toml new file mode 100644 index 0000000..b332a06 --- /dev/null +++ b/.typedialog/platform/forms/fragments/rag/ingestion.toml @@ -0,0 +1,52 @@ +# RAG Document Ingestion Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "rag_ingestion_header" +title = "πŸ“„ Document Ingestion Configuration" +type = "section_header" + +[[elements]] +default = true +help = "Auto-ingest documents on startup" +name = "rag_ingestion_auto_ingest" +nickel_path = ["rag", "ingestion", "auto_ingest"] +prompt = "Auto-ingest" +type = "confirm" + +[[elements]] +default = false +help = "Watch for file changes and auto-ingest" +name = "rag_ingestion_watch_files" +nickel_path = ["rag", "ingestion", "watch_files"] +prompt = "Watch Files" +type = "confirm" + +[[elements]] +default = 512 +help = "Document chunk size in characters" +max = 4096 +min = 128 +name = "rag_ingestion_chunk_size" +nickel_path = ["rag", "ingestion", "chunk_size"] +prompt = "Chunk Size" +type = "number" + +[[elements]] +default = 50 +help = "Overlap between chunks in characters" +max = 1000 +min = 0 +name = "rag_ingestion_overlap" +nickel_path = ["rag", "ingestion", "overlap"] +prompt = "Chunk Overlap" +type = "number" + +[[elements]] +default = "md, txt, toml" +help = "Supported document types (comma-separated)" +name = "rag_ingestion_doc_types" +nickel_path = ["rag", "ingestion", "doc_types"] +prompt = "Document Types" +type = "text" diff --git a/.typedialog/platform/forms/fragments/rag/llm.toml b/.typedialog/platform/forms/fragments/rag/llm.toml new file mode 100644 index 0000000..e252be7 --- /dev/null +++ b/.typedialog/platform/forms/fragments/rag/llm.toml @@ -0,0 +1,67 @@ +# RAG Language Model Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "rag_llm_header" +title = "πŸ€– Language Model Configuration" +type = "section_header" + +[[elements]] +default = "anthropic" +help = "LLM provider (anthropic, openai, ollama)" +name = "rag_llm_provider" +nickel_path = ["rag", "llm", "provider"] +options = ["anthropic", "openai", "ollama"] +prompt = "Provider" +required = true +type = "select" + +[[elements]] +default = "claude-3-5-sonnet-20241022" +help = "Model name" +name = "rag_llm_model" +nickel_path = ["rag", "llm", "model"] +prompt = "Model" +required = true +type = "text" + +[[elements]] +condition = "rag_llm_provider != 'ollama'" +default = "" +help = "API key for LLM service" +name = "rag_llm_api_key" +nickel_path = ["rag", "llm", "api_key"] +prompt = "API Key" +required = false +type = "password" + +[[elements]] +condition = "rag_llm_provider == 'ollama'" +default = "http://localhost:11434" +help = "Ollama API URL" +name = "rag_llm_api_url" +nickel_path = ["rag", "llm", "api_url"] +prompt = "API URL" +required = false +type = "text" + +[[elements]] +default = 0.7 +help = "Model temperature (0.0-2.0)" +max = 2.0 +min = 0.0 +name = "rag_llm_temperature" +nickel_path = ["rag", "llm", "temperature"] +prompt = "Temperature" +type = "number" + +[[elements]] +default = 2048 +help = "Maximum tokens to generate" +max = 32768 +min = 1 +name = "rag_llm_max_tokens" +nickel_path = ["rag", "llm", "max_tokens"] +prompt = "Max Tokens" +type = "number" diff --git a/.typedialog/platform/forms/fragments/rag/retrieval.toml b/.typedialog/platform/forms/fragments/rag/retrieval.toml new file mode 100644 index 0000000..266434f --- /dev/null +++ b/.typedialog/platform/forms/fragments/rag/retrieval.toml @@ -0,0 +1,44 @@ +# RAG Retrieval Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "rag_retrieval_header" +title = "πŸ” Retrieval Configuration" +type = "section_header" + +[[elements]] +default = 5 +help = "Number of top results to return" +max = 100 +min = 1 +name = "rag_retrieval_top_k" +nickel_path = ["rag", "retrieval", "top_k"] +prompt = "Top K Results" +type = "number" + +[[elements]] +default = 0.75 +help = "Minimum similarity threshold (0.0-1.0)" +max = 1.0 +min = 0.0 +name = "rag_retrieval_similarity_threshold" +nickel_path = ["rag", "retrieval", "similarity_threshold"] +prompt = "Similarity Threshold" +type = "number" + +[[elements]] +default = false +help = "Enable re-ranking of results" +name = "rag_retrieval_reranking" +nickel_path = ["rag", "retrieval", "reranking"] +prompt = "Enable Re-ranking" +type = "confirm" + +[[elements]] +default = false +help = "Enable hybrid search (keyword + semantic)" +name = "rag_retrieval_hybrid" +nickel_path = ["rag", "retrieval", "hybrid"] +prompt = "Enable Hybrid Search" +type = "confirm" diff --git a/.typedialog/platform/forms/fragments/rag/vector-db.toml b/.typedialog/platform/forms/fragments/rag/vector-db.toml new file mode 100644 index 0000000..75151ec --- /dev/null +++ b/.typedialog/platform/forms/fragments/rag/vector-db.toml @@ -0,0 +1,47 @@ +# RAG Vector Database Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "rag_vector_db_header" +title = "πŸ—„οΈ Vector Database Configuration" +type = "section_header" + +[[elements]] +default = "memory" +help = "Vector database type (memory, surrealdb, qdrant, milvus)" +name = "rag_vector_db_type" +nickel_path = ["rag", "vector_db", "db_type"] +options = ["memory", "surrealdb", "qdrant", "milvus"] +prompt = "Database Type" +required = true +type = "select" + +[[elements]] +condition = "rag_vector_db_type != 'memory'" +default = "http://localhost:8000" +help = "Vector database URL" +name = "rag_vector_db_url" +nickel_path = ["rag", "vector_db", "url"] +prompt = "Database URL" +required = false +type = "text" + +[[elements]] +default = "provisioning" +help = "Vector database namespace" +name = "rag_vector_db_namespace" +nickel_path = ["rag", "vector_db", "namespace"] +prompt = "Namespace" +required = true +type = "text" + +[[elements]] +condition = "rag_vector_db_type == 'surrealdb'" +default = "rag" +help = "Database name" +name = "rag_vector_db_database" +nickel_path = ["rag", "vector_db", "database"] +prompt = "Database Name" +required = false +type = "text" diff --git a/.typedialog/platform/forms/fragments/server-section.toml b/.typedialog/platform/forms/fragments/server-section.toml new file mode 100644 index 0000000..b741578 --- /dev/null +++ b/.typedialog/platform/forms/fragments/server-section.toml @@ -0,0 +1,85 @@ +# HTTP Server Configuration Fragment +# Used by all services: orchestrator, control-center, mcp-server + +[[elements]] +border_top = true +border_bottom = false +name = "server_section_header" +title = "🌐 HTTP Server Configuration" +type = "section_header" + +[[elements]] +default = "127.0.0.1" +help = "Address to bind the HTTP server to (127.0.0.1=local, 0.0.0.0=all interfaces)" +name = "server_host" +nickel_path = ["server", "host"] +prompt = "Server Host/Address" +required = true +type = "text" + +[[elements]] +default = 9090 +help = "HTTP server port number (range: ${constraint.common.server.port.min}-${constraint.common.server.port.max})" +max = "${constraint.common.server.port.max}" +min = "${constraint.common.server.port.min}" +name = "server_port" +nickel_path = ["server", "port"] +prompt = "Server Port" +required = true +type = "number" + +[[elements]] +default = 4 +help = "Number of worker threads for HTTP server (range: ${constraint.common.server.workers.min}-${constraint.common.server.workers.max})" +min = "${constraint.common.server.workers.min}" +max = "${constraint.common.server.workers.max}" +name = "server_workers" +nickel_path = ["server", "workers"] +prompt = "Worker Threads" +type = "number" + +[[elements]] +default = 75 +help = "TCP keep-alive timeout in seconds (0 = disabled, range: ${constraint.common.server.keep_alive.min}-${constraint.common.server.keep_alive.max})" +min = "${constraint.common.server.keep_alive.min}" +max = "${constraint.common.server.keep_alive.max}" +name = "server_keep_alive" +nickel_path = ["server", "keep_alive"] +prompt = "Keep-Alive Timeout (seconds)" +type = "number" + +[[elements]] +default = 100 +help = "Maximum number of concurrent TCP connections (range: ${constraint.common.server.max_connections.min}-${constraint.common.server.max_connections.max})" +min = "${constraint.common.server.max_connections.min}" +max = "${constraint.common.server.max_connections.max}" +name = "server_max_connections" +nickel_path = ["server", "max_connections"] +prompt = "Max Connections" +type = "number" + +[[elements]] +default = 30000 +help = "Request timeout in milliseconds" +min = 1000 +name = "server_request_timeout" +nickel_path = ["server", "request_timeout"] +prompt = "Request Timeout (ms)" +type = "number" + +[[elements]] +default = true +help = "Enable graceful shutdown to allow in-flight requests to complete" +name = "server_graceful_shutdown" +nickel_path = ["server", "graceful_shutdown"] +prompt = "Graceful Shutdown" +type = "confirm" + +[[elements]] +default = 30 +help = "Graceful shutdown timeout in seconds" +min = 1 +name = "server_shutdown_timeout" +nickel_path = ["server", "shutdown_timeout"] +prompt = "Shutdown Timeout (seconds)" +type = "number" diff --git a/.typedialog/platform/forms/fragments/vault-service/ha.toml b/.typedialog/platform/forms/fragments/vault-service/ha.toml new file mode 100644 index 0000000..d699af6 --- /dev/null +++ b/.typedialog/platform/forms/fragments/vault-service/ha.toml @@ -0,0 +1,27 @@ +# Vault Service High Availability Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "vault_ha_header" +title = "πŸ”„ High Availability Configuration" +type = "section_header" + +[[elements]] +default = false +help = "Enable high availability mode with clustering" +name = "vault_ha_enabled" +nickel_path = ["vault_service", "deployment", "ha_enabled"] +prompt = "Enable HA Mode" +type = "confirm" + +[[elements]] +condition = "vault_ha_enabled == true" +default = "raft" +help = "HA cluster backend (Raft integrated or external Consul)" +name = "vault_ha_mode" +nickel_path = ["vault_service", "deployment", "ha_mode"] +options = ["raft", "consul"] +prompt = "HA Mode" +required = true +type = "select" diff --git a/.typedialog/platform/forms/fragments/vault-service/mount.toml b/.typedialog/platform/forms/fragments/vault-service/mount.toml new file mode 100644 index 0000000..54d3b75 --- /dev/null +++ b/.typedialog/platform/forms/fragments/vault-service/mount.toml @@ -0,0 +1,26 @@ +# Vault Service Mount Point Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "vault_mount_header" +title = "πŸ“ Mount Point Configuration" +type = "section_header" + +[[elements]] +default = "transit" +help = "Vault mount point path for secret engine" +name = "vault_mount_point" +nickel_path = ["vault_service", "mount", "path"] +prompt = "Mount Point" +required = true +type = "text" + +[[elements]] +default = "provisioning-master" +help = "Name of the encryption key to use" +name = "vault_mount_key_name" +nickel_path = ["vault_service", "mount", "key"] +prompt = "Key Name" +required = true +type = "text" diff --git a/.typedialog/platform/forms/fragments/vault-service/server.toml b/.typedialog/platform/forms/fragments/vault-service/server.toml new file mode 100644 index 0000000..af9aa60 --- /dev/null +++ b/.typedialog/platform/forms/fragments/vault-service/server.toml @@ -0,0 +1,28 @@ +# Vault Service Server Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "vault_server_header" +title = "πŸ–₯️ Server Configuration" +type = "section_header" + +[[elements]] +default = "127.0.0.1" +help = "HTTP server bind address (127.0.0.1 for local, 0.0.0.0 for all interfaces)" +name = "vault_server_host" +nickel_path = ["vault_service", "server", "host"] +prompt = "Server Host" +required = true +type = "text" + +[[elements]] +default = 8200 +help = "HTTP server port (range: 1024-65535)" +max = 65535 +min = 1024 +name = "vault_server_port" +nickel_path = ["vault_service", "server", "port"] +prompt = "Server Port" +required = true +type = "number" diff --git a/.typedialog/platform/forms/fragments/vault-service/storage.toml b/.typedialog/platform/forms/fragments/vault-service/storage.toml new file mode 100644 index 0000000..7fcd353 --- /dev/null +++ b/.typedialog/platform/forms/fragments/vault-service/storage.toml @@ -0,0 +1,37 @@ +# Vault Service Storage Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "vault_storage_header" +title = "πŸ’Ύ Storage Configuration" +type = "section_header" + +[[elements]] +default = "filesystem" +help = "Storage backend for secrets (filesystem, surrealdb, etcd, memory)" +name = "vault_storage_backend" +nickel_path = ["vault_service", "storage", "backend"] +options = ["filesystem", "memory", "surrealdb", "etcd", "postgresql"] +prompt = "Storage Backend" +required = true +type = "select" + +[[elements]] +condition = "vault_storage_backend == 'filesystem'" +default = "/var/lib/vault/data" +help = "Path for local filesystem storage (absolute path required)" +name = "vault_storage_path" +nickel_path = ["vault_service", "storage", "path"] +prompt = "Storage Path" +required = true +type = "text" + +[[elements]] +default = "" +help = "Encryption key for at-rest encryption (base64 encoded, optional)" +name = "vault_storage_encryption_key" +nickel_path = ["vault_service", "storage", "encryption_key"] +prompt = "Encryption Key (optional)" +required = false +type = "text" diff --git a/.typedialog/platform/forms/fragments/vault-service/tls.toml b/.typedialog/platform/forms/fragments/vault-service/tls.toml new file mode 100644 index 0000000..1506718 --- /dev/null +++ b/.typedialog/platform/forms/fragments/vault-service/tls.toml @@ -0,0 +1,46 @@ +# Vault Service TLS Configuration Fragment + +[[elements]] +border_top = true +border_bottom = false +name = "vault_tls_header" +title = "πŸ”’ TLS Configuration" +type = "section_header" + +[[elements]] +default = false +help = "Enable TLS certificate verification for secure connections" +name = "vault_tls_verify" +nickel_path = ["vault_service", "tls", "verify"] +prompt = "Verify TLS Certificates" +type = "confirm" + +[[elements]] +condition = "vault_tls_verify == true" +default = "" +help = "Path to CA certificate file for TLS verification" +name = "vault_tls_ca_cert_path" +nickel_path = ["vault_service", "tls", "ca_cert_path"] +prompt = "CA Certificate Path" +required = false +type = "text" + +[[elements]] +condition = "vault_tls_verify == true" +default = "" +help = "Path to client certificate file (optional)" +name = "vault_tls_client_cert_path" +nickel_path = ["vault_service", "tls", "client_cert_path"] +prompt = "Client Certificate Path (optional)" +required = false +type = "text" + +[[elements]] +condition = "vault_tls_verify == true" +default = "" +help = "Path to client key file (optional)" +name = "vault_tls_client_key_path" +nickel_path = ["vault_service", "tls", "client_key_path"] +prompt = "Client Key Path (optional)" +required = false +type = "text" diff --git a/.typedialog/platform/forms/fragments/workspace-section.toml b/.typedialog/platform/forms/fragments/workspace-section.toml new file mode 100644 index 0000000..8252da4 --- /dev/null +++ b/.typedialog/platform/forms/fragments/workspace-section.toml @@ -0,0 +1,36 @@ +# Workspace Configuration Fragment +# Used by all services: orchestrator, control-center, mcp-server, installer + +[[elements]] +help = "Name of the workspace this service will serve" +name = "workspace_name" +nickel_path = ["workspace", "name"] +placeholder = "default" +prompt = "Workspace Name" +required = true +type = "text" + +[[elements]] +help = "Absolute path to the workspace directory" +name = "workspace_path" +nickel_path = ["workspace", "path"] +placeholder = "/var/lib/provisioning/{service}" +prompt = "Workspace Path" +required = true +type = "text" + +[[elements]] +default = true +help = "Enable or disable this service for the workspace" +name = "workspace_enabled" +nickel_path = ["workspace", "enabled"] +prompt = "Enable Service" +type = "confirm" + +[[elements]] +default = false +help = "Allow this service instance to serve multiple workspaces" +name = "multi_workspace_mode" +nickel_path = ["workspace", "multi_workspace"] +prompt = "Multi-Workspace Mode" +type = "confirm" diff --git a/.typedialog/platform/forms/installer-form.toml b/.typedialog/platform/forms/installer-form.toml new file mode 100644 index 0000000..2487fc2 --- /dev/null +++ b/.typedialog/platform/forms/installer-form.toml @@ -0,0 +1,110 @@ +name = "installer_configuration" +description = "Interactive configuration for Provisioning Platform Installer (deployment and lifecycle management)" +display_mode = "complete" +fallback_locale = "en-US" + +# ============================================================================ +# INSTALLER SERVICE FORM - COMPOSED FROM FRAGMENTS +# ============================================================================ +# This form uses fragment composition pattern for modular configuration +# All fragments are located in ./fragments/ subdirectory +# ============================================================================ + +# DEPLOYMENT MODE SELECTION +# Determines deployment environment and service resources +[[items]] +name = "deployment_mode_group" +type = "group" +title = "Deployment Configuration" +description = "Select deployment mode and database backend for installed services" +includes = ["fragments/deployment/mode-selection.toml", "fragments/deployment/database-backend-selection.toml"] + +# INSTALLATION TARGET CONFIGURATION +# Target environment: local, remote, kubernetes, docker +[[items]] +name = "target_group" +type = "group" +title = "Installation Target" +description = "Configure target environment and connectivity" +includes = ["fragments/installer/target-section.toml"] + +# PREFLIGHT CHECKS CONFIGURATION +# Disk, memory, CPU, network, dependencies, ports validation +[[items]] +name = "preflight_group" +type = "group" +title = "Preflight Checks" +description = "Configure pre-installation validation checks" +includes = ["fragments/installer/preflight-section.toml"] + +# INSTALLATION STRATEGY CONFIGURATION +# Installation mode, parallelization, timeout, rollback, logging, hooks +[[items]] +name = "installation_group" +type = "group" +title = "Installation Strategy" +description = "Configure installation behavior and strategy" +includes = ["fragments/installer/installation-section.toml"] + +# SERVICES SELECTION CONFIGURATION +# Which services to install, ports, auto-start, health checks +[[items]] +name = "services_group" +type = "group" +title = "Services Selection" +description = "Select which services to install and configure their deployment" +includes = ["fragments/installer/services-section.toml"] + +# DATABASE CONFIGURATION +# Database initialization, migrations, backup, verification, optimization +[[items]] +name = "database_group" +type = "group" +title = "Database Configuration" +description = "Configure database initialization and management" +includes = ["fragments/installer/database-section.toml"] + +# STORAGE CONFIGURATION +# Storage location, backend, compression, encryption, replication, cleanup +[[items]] +name = "storage_group" +type = "group" +title = "Storage Configuration" +description = "Configure storage for provisioning data and artifacts" +includes = ["fragments/installer/storage-section.toml"] + +# NETWORKING CONFIGURATION +# Bind address, DNS, TLS, firewall, load balancer, ingress, proxy +[[items]] +name = "networking_group" +type = "group" +title = "Networking Configuration" +description = "Configure networking, DNS, TLS, and firewall" +includes = ["fragments/installer/networking-section.toml"] + +# HIGH AVAILABILITY CONFIGURATION +# Cluster setup, replication, health checks, failover, backup, load distribution +[[items]] +name = "ha_group" +type = "group" +title = "High Availability Configuration" +description = "Configure high availability and clustering" +includes = ["fragments/installer/ha-section.toml"] + +# POST-INSTALLATION CONFIGURATION +# Admin user, workspace config, extensions, API setup, verification, cleanup +[[items]] +name = "post_install_group" +type = "group" +title = "Post-Installation Configuration" +description = "Configure post-installation tasks and verification" +includes = ["fragments/installer/post-install-section.toml"] + +# UPGRADES CONFIGURATION +# Auto-upgrade, channels, strategies, pre-checks, backup, rollback, health monitoring +[[items]] +name = "upgrades_group" +type = "group" +title = "Upgrades Configuration" +description = "Configure automatic updates and upgrade strategies" +includes = ["fragments/installer/upgrades-section.toml"] diff --git a/.typedialog/platform/forms/mcp-server-form.toml b/.typedialog/platform/forms/mcp-server-form.toml new file mode 100644 index 0000000..e7c9e21 --- /dev/null +++ b/.typedialog/platform/forms/mcp-server-form.toml @@ -0,0 +1,118 @@ +name = "mcp_server_configuration" +description = "Interactive configuration for MCP Server service (Model Context Protocol interface)" +display_mode = "complete" +fallback_locale = "en-US" + +# ============================================================================ +# MCP SERVER SERVICE FORM - COMPOSED FROM FRAGMENTS +# ============================================================================ +# This form uses fragment composition pattern for modular configuration +# All fragments are located in ./fragments/ subdirectory +# ============================================================================ + +# DEPLOYMENT MODE SELECTION +# Determines service resources and feature set (solo/multiuser/cicd/enterprise) +[[items]] +name = "deployment_mode_group" +type = "group" +title = "Deployment Configuration" +description = "Select deployment mode and database backend" +includes = ["fragments/deployment/mode-selection.toml", "fragments/deployment/database-backend-selection.toml"] + +# WORKSPACE CONFIGURATION +# Workspace name, path, and context +[[items]] +name = "workspace_group" +type = "group" +title = "Workspace Settings" +description = "Configure workspace context for this MCP Server instance" +includes = ["fragments/workspace-section.toml"] + +# SERVER CONFIGURATION +# HTTP server settings (host, port, workers, connections) +[[items]] +name = "server_group" +type = "group" +title = "Server Settings" +description = "Configure HTTP server for MCP Server" +includes = ["fragments/server-section.toml"] + +# DATABASE BACKEND CONFIGURATION +# Conditional sections based on selected backend +[[items]] +name = "database_rocksdb_group" +type = "group" +title = "RocksDB Configuration" +description = "Configure RocksDB backend for MCP state" +condition = "database_backend_selection == 'rocksdb'" +includes = ["fragments/database-rocksdb-section.toml"] + +[[items]] +name = "database_surrealdb_group" +type = "group" +title = "SurrealDB Configuration" +description = "Configure SurrealDB backend for MCP state" +condition = "database_backend_selection == 'surrealdb_embedded' || database_backend_selection == 'surrealdb_server'" +includes = ["fragments/database-surrealdb-section.toml"] + +[[items]] +name = "database_postgres_group" +type = "group" +title = "PostgreSQL Configuration" +description = "Configure PostgreSQL backend for MCP state" +condition = "database_backend_selection == 'postgresql'" +includes = ["fragments/database-postgres-section.toml"] + +# MCP-SPECIFIC: TOOLS CONFIGURATION +# Tool management, validation, caching, concurrent execution +[[items]] +name = "tools_group" +type = "group" +title = "Tools Configuration" +description = "Configure MCP tools, execution, and caching" +includes = ["fragments/mcp-server/tools-section.toml"] + +# MCP-SPECIFIC: PROMPTS CONFIGURATION +# Custom prompt templates, versioning, caching +[[items]] +name = "prompts_group" +type = "group" +title = "Prompts Configuration" +description = "Configure custom prompt templates and management" +includes = ["fragments/mcp-server/prompts-section.toml"] + +# MCP-SPECIFIC: RESOURCES CONFIGURATION +# Resource management, max size, caching, validation +[[items]] +name = "resources_group" +type = "group" +title = "Resources Configuration" +description = "Configure MCP resources and resource management" +includes = ["fragments/mcp-server/resources-section.toml"] + +# MCP-SPECIFIC: SAMPLING CONFIGURATION +# AI model sampling, temperature, output tokens, caching +[[items]] +name = "sampling_group" +type = "group" +title = "Sampling Configuration" +description = "Configure AI model sampling and inference" +includes = ["fragments/mcp-server/sampling-section.toml"] + +# MONITORING CONFIGURATION +# Metrics collection, health checks +[[items]] +name = "monitoring_group" +type = "group" +title = "Monitoring Configuration" +description = "Configure metrics and health checks" +includes = ["fragments/monitoring-section.toml"] + +# LOGGING CONFIGURATION +# Log levels, formats, rotation +[[items]] +name = "logging_group" +type = "group" +title = "Logging Configuration" +description = "Configure logging behavior and output" +includes = ["fragments/logging-section.toml"] diff --git a/.typedialog/platform/forms/orchestrator-form.toml b/.typedialog/platform/forms/orchestrator-form.toml new file mode 100644 index 0000000..6ad2837 --- /dev/null +++ b/.typedialog/platform/forms/orchestrator-form.toml @@ -0,0 +1,127 @@ +name = "orchestrator_configuration" +description = "Interactive configuration for Orchestrator service (workflow engine and task scheduling)" +display_mode = "complete" +fallback_locale = "en-US" + +# ============================================================================ +# ORCHESTRATOR SERVICE FORM - COMPOSED FROM FRAGMENTS +# ============================================================================ +# This form uses fragment composition pattern for modular configuration +# All fragments are located in ./fragments/ subdirectory +# ============================================================================ + +# DEPLOYMENT MODE SELECTION +# Determines service resources and feature set (solo/multiuser/cicd/enterprise) +[[items]] +name = "deployment_mode_group" +type = "group" +title = "Deployment Configuration" +description = "Select deployment mode and database backend" +includes = ["fragments/deployment/mode-selection.toml", "fragments/deployment/database-backend-selection.toml"] + +# WORKSPACE CONFIGURATION +# Workspace name, path, and multi-workspace mode +[[items]] +name = "workspace_group" +type = "group" +title = "Workspace Settings" +description = "Configure workspace context for this Orchestrator instance" +includes = ["fragments/workspace-section.toml"] + +# SERVER CONFIGURATION +# HTTP server settings (host, port, workers, connections) +[[items]] +name = "server_group" +type = "group" +title = "Server Settings" +description = "Configure HTTP server for Orchestrator" +includes = ["fragments/server-section.toml"] + +# DATABASE BACKEND CONFIGURATION +# Conditional sections based on selected backend +[[items]] +name = "database_rocksdb_group" +type = "group" +title = "RocksDB Configuration" +description = "Configure RocksDB backend" +condition = "database_backend_selection == 'rocksdb'" +includes = ["fragments/database-rocksdb-section.toml"] + +[[items]] +name = "database_surrealdb_group" +type = "group" +title = "SurrealDB Configuration" +description = "Configure SurrealDB backend" +condition = "database_backend_selection == 'surrealdb_embedded' || database_backend_selection == 'surrealdb_server'" +includes = ["fragments/database-surrealdb-section.toml"] + +[[items]] +name = "database_postgres_group" +type = "group" +title = "PostgreSQL Configuration" +description = "Configure PostgreSQL backend" +condition = "database_backend_selection == 'postgresql'" +includes = ["fragments/database-postgres-section.toml"] + +# ORCHESTRATOR-SPECIFIC: STORAGE CONFIGURATION +# Storage backend, caching, compression, garbage collection +[[items]] +name = "storage_group" +type = "group" +title = "Storage Configuration" +description = "Configure storage backend for workflow state and artifacts" +includes = ["fragments/orchestrator/storage-section.toml"] + +# ORCHESTRATOR-SPECIFIC: QUEUE CONFIGURATION +# Task queue, concurrency, retries, timeouts +[[items]] +name = "queue_group" +type = "group" +title = "Task Queue Configuration" +description = "Configure task queue behavior and limits" +includes = ["fragments/orchestrator/queue-section.toml"] + +# ORCHESTRATOR-SPECIFIC: BATCH WORKFLOW CONFIGURATION +# Batch operations, parallel limits, checkpointing, rollback +[[items]] +name = "batch_group" +type = "group" +title = "Batch Workflow Configuration" +description = "Configure batch workflow execution and recovery" +includes = ["fragments/orchestrator/batch-section.toml"] + +# ORCHESTRATOR-SPECIFIC: EXTENSIONS CONFIGURATION +# Extension auto-loading, OCI registry, discovery, sandboxing +[[items]] +name = "extensions_group" +type = "group" +title = "Extensions Configuration" +description = "Configure extension management and auto-loading" +includes = ["fragments/orchestrator/extensions-section.toml"] + +# ORCHESTRATOR-SPECIFIC: PERFORMANCE CONFIGURATION +# CPU affinity, memory limits, profiling, caching, thread pools +[[items]] +name = "performance_group" +type = "group" +title = "Performance Configuration" +description = "Configure advanced performance settings" +includes = ["fragments/orchestrator/performance-section.toml"] + +# MONITORING CONFIGURATION +# Metrics collection, health checks +[[items]] +name = "monitoring_group" +type = "group" +title = "Monitoring Configuration" +description = "Configure metrics and health checks" +includes = ["fragments/monitoring-section.toml"] + +# LOGGING CONFIGURATION +# Log levels, formats, rotation +[[items]] +name = "logging_group" +type = "group" +title = "Logging Configuration" +description = "Configure logging behavior and output" +includes = ["fragments/logging-section.toml"] diff --git a/.typedialog/platform/forms/provisioning-daemon-form.toml b/.typedialog/platform/forms/provisioning-daemon-form.toml new file mode 100644 index 0000000..d811483 --- /dev/null +++ b/.typedialog/platform/forms/provisioning-daemon-form.toml @@ -0,0 +1,13 @@ +# Provisioning Daemon Configuration Form +# Sections for provisioning daemon background service + +title = "Provisioning Daemon Configuration" +description = "Configure background provisioning daemon service" + +sections = [ + { name = "daemon", label = "Daemon Control", description = "Daemon operation and polling configuration" }, + { name = "logging", label = "Logging", description = "Log output and verbosity settings" }, + { name = "actions", label = "Actions", description = "Automatic actions and cleanup policies" }, + { name = "workers", label = "Workers", description = "Worker thread and concurrency settings" }, + { name = "health", label = "Health", description = "Health checks and monitoring" } +] diff --git a/.typedialog/platform/forms/rag-form.toml b/.typedialog/platform/forms/rag-form.toml new file mode 100644 index 0000000..90cd54d --- /dev/null +++ b/.typedialog/platform/forms/rag-form.toml @@ -0,0 +1,23 @@ +[form] +name = "RAG System Configuration" +description = "Retrieval-Augmented Generation system" + +[[sections]] +name = "Embeddings" +includes = ["fragments/rag/embeddings.toml"] + +[[sections]] +name = "Vector Database" +includes = ["fragments/rag/vector-db.toml"] + +[[sections]] +name = "Language Model" +includes = ["fragments/rag/llm.toml"] + +[[sections]] +name = "Retrieval" +includes = ["fragments/rag/retrieval.toml"] + +[[sections]] +name = "Ingestion" +includes = ["fragments/rag/ingestion.toml"] diff --git a/.typedialog/platform/forms/vault-service-form.toml b/.typedialog/platform/forms/vault-service-form.toml new file mode 100644 index 0000000..7f748fe --- /dev/null +++ b/.typedialog/platform/forms/vault-service-form.toml @@ -0,0 +1,29 @@ +[form] +name = "Vault Service Configuration" +description = "Secrets management and encryption service configuration" +version = "1.0" + +[[sections]] +name = "Server" +description = "HTTP server configuration" +includes = ["fragments/vault-service/server.toml"] + +[[sections]] +name = "Storage" +description = "Storage backend configuration" +includes = ["fragments/vault-service/storage.toml"] + +[[sections]] +name = "TLS/SSL" +description = "TLS and security settings" +includes = ["fragments/vault-service/tls.toml"] + +[[sections]] +name = "Mount Point" +description = "Vault mount point and key configuration" +includes = ["fragments/vault-service/mount.toml"] + +[[sections]] +name = "High Availability" +description = "HA and clustering configuration" +includes = ["fragments/vault-service/ha.toml"] diff --git a/.typedialog/platform/scripts/README.md b/.typedialog/platform/scripts/README.md new file mode 100644 index 0000000..4540e04 --- /dev/null +++ b/.typedialog/platform/scripts/README.md @@ -0,0 +1,255 @@ +# Scripts + +Nushell orchestration scripts for configuration workflow automation (NuShell 0.109+). + +## Purpose + +Scripts provide: +- **Interactive configuration wizard** - TypeDialog with nickel-roundtrip +- **Configuration generation** - Nickel β†’ TOML export +- **Validation** - Nickel typecheck and constraint validation +- **Deployment** - Docker Compose, Kubernetes, service installation + +## Script Organization + +``` +scripts/ +β”œβ”€β”€ README.md # This file +β”œβ”€β”€ configure.nu # Interactive TypeDialog wizard +β”œβ”€β”€ generate-configs.nu # Nickel β†’ TOML export +β”œβ”€β”€ validate-config.nu # Nickel typecheck +β”œβ”€β”€ render-docker-compose.nu # Docker Compose generation +β”œβ”€β”€ render-kubernetes.nu # Kubernetes manifests generation +β”œβ”€β”€ install-services.nu # Deploy platform services +└── detect-services.nu # Auto-detect running services +``` + +## Scripts (Planned Implementation) + +### configure.nu +Interactive configuration wizard using TypeDialog nickel-roundtrip: + +```bash +nu provisioning/.typedialog/platform/scripts/configure.nu orchestrator solo --backend web +``` + +Workflow: +1. Loads existing config (if exists) as defaults +2. Launches TypeDialog form (web/tui/cli) +3. Shows form with validated constraints +4. User edits configuration +5. Generates updated Nickel config to `provisioning/schemas/platform/values/orchestrator.solo.ncl` + +Usage: +```bash +nu scripts/configure.nu [service] [mode] --backend [web|tui|cli] + service: orchestrator | control-center | mcp-server | vault-service | extension-registry | rag | ai-service | provisioning-daemon + mode: solo | multiuser | cicd | enterprise + backend: web (default) | tui | cli +``` + +### generate-configs.nu +Export Nickel configuration to TOML: + +```bash +nu provisioning/.typedialog/platform/scripts/generate-configs.nu orchestrator solo +``` + +Workflow: +1. Validates Nickel config (typecheck) +2. Exports to TOML format +3. Saves to `provisioning/config/runtime/generated/{service}.{mode}.toml` + +Usage: +```bash +nu scripts/generate-configs.nu [service] [mode] + service: orchestrator | control-center | mcp-server | vault-service | extension-registry | rag | ai-service | provisioning-daemon + mode: solo | multiuser | cicd | enterprise +``` + +### validate-config.nu +Typecheck Nickel configuration: + +```bash +nu provisioning/.typedialog/platform/scripts/validate-config.nu provisioning/schemas/platform/values/orchestrator.solo.ncl +``` + +Workflow: +1. Runs nickel typecheck +2. Reports errors (schema violations, constraint errors) +3. Exits with status + +Usage: +```bash +nu scripts/validate-config.nu [config_path] + config_path: Path to Nickel config file +``` + +### render-docker-compose.nu +Generate Docker Compose files from Nickel templates: + +```bash +nu provisioning/.typedialog/platform/scripts/render-docker-compose.nu solo +``` + +Workflow: +1. Evaluates Nickel template +2. Exports to JSON +3. Converts to YAML (via yq) +4. Saves to `provisioning/platform/infrastructure/docker/docker-compose.{mode}.yml` + +Usage: +```bash +nu scripts/render-docker-compose.nu [mode] + mode: solo | multiuser | cicd | enterprise +``` + +### render-kubernetes.nu +Generate Kubernetes manifests: + +```bash +nu scripts/render-kubernetes.nu solo +``` + +Workflow: +1. Evaluates Nickel templates +2. Exports to JSON +3. Converts to YAML +4. Saves to `provisioning/platform/infrastructure/kubernetes/` + +### install-services.nu +Deploy platform services: + +```bash +nu scripts/install-services.nu solo --backend docker +``` + +Workflow: +1. Generates all configs for mode +2. Renders deployment manifests +3. Deploys services (Docker Compose or Kubernetes) +4. Verifies service startup + +### detect-services.nu +Auto-detect running services: + +```bash +nu scripts/detect-services.nu +``` + +Outputs: +- Running service list +- Detected mode +- Port usage +- Container/pod status + +## Common Workflow + +```bash +# 1. Configure service +nu scripts/configure.nu orchestrator solo + +# 2. Validate configuration +nu scripts/validate-config.nu provisioning/schemas/platform/values/orchestrator.solo.ncl + +# 3. Generate TOML +nu scripts/generate-configs.nu orchestrator solo + +# 4. Review generated config +cat provisioning/config/runtime/generated/orchestrator.solo.toml + +# 5. Render Docker Compose +nu scripts/render-docker-compose.nu solo + +# 6. Deploy services +nu scripts/install-services.nu solo --backend docker + +# 7. Verify running services +nu scripts/detect-services.nu +``` + +## Guidelines + +All scripts follow @.claude/guidelines/nushell.md (NuShell 0.109+): + +- **Explicit type signatures** - Function parameters with type annotations +- **Colon notation** - Use `:` before input type, `->` before output type +- **Error handling** - Use `do { } | complete` pattern (not try-catch) +- **Pipeline operations** - Chain operations, avoid nested calls +- **No mutable variables** - Use reduce/recursion instead +- **External commands** - Use `^` prefix (`^nickel`, `^docker`, etc.) + +Example: +```nushell +export def main [ + service: string, # Type annotation + mode: string +]: nothing -> nothing { # Input/output types + let result = do { + ^nickel typecheck $config_path + } | complete + + if $result.exit_code == 0 { + print "βœ… Validation passed" + } else { + print $"❌ Validation failed: ($result.stderr)" + exit 1 + } +} +``` + +## Error Handling Pattern + +All scripts use `do { } | complete` for error handling: + +```nushell +let result = do { + ^some-command --flag value +} | complete + +if $result.exit_code != 0 { + error make { + msg: $"Command failed: ($result.stderr)" + } +} +``` + +**Never use try-catch** (not supported in 0.109+). + +## Script Dependencies + +All scripts assume: +- **NuShell 0.109+** - Modern shell +- **Nickel** (0.10+) - Configuration language +- **TypeDialog** - Interactive forms +- **Docker** or **kubectl** - Deployment backends +- **yq** - YAML/JSON conversion +- **jq** - JSON processing + +## Testing Scripts + +```bash +# Validate Nushell syntax +nu --version # Verify 0.109+ + +# Test script execution +nu scripts/validate-config.nu values/orchestrator.solo.ncl + +# Check script compliance +grep -r "try\|panic\|todo" scripts/ # Should be empty +``` + +## Adding a New Script + +1. **Create script file** (`scripts/{name}.nu`) +2. **Add @.claude/guidelines/nushell.md** compliance +3. **Define main function** with type signatures +4. **Use do { } | complete** for error handling +5. **Test execution**: `nu scripts/{name}.nu` +6. **Verify**: No try-catch, no mutable vars, no panic + +--- + +**Version**: 1.0.0 +**Last Updated**: 2025-01-05 +**Guideline**: @.claude/guidelines/nushell.md (NuShell 0.109+) diff --git a/.typedialog/platform/scripts/ansi.nu b/.typedialog/platform/scripts/ansi.nu new file mode 100644 index 0000000..47abc64 --- /dev/null +++ b/.typedialog/platform/scripts/ansi.nu @@ -0,0 +1,89 @@ +#!/usr/bin/env nu + +# ANSI Color and Emoji Output Helpers +# Provides consistent formatting for user-facing messages in Phase 8 scripts +# Usage: use ansi.nu; success "Operation completed" + +export def success [message: string]: nothing -> string { + $"βœ… ($message)" +} + +export def error [message: string]: nothing -> string { + $"❌ ($message)" +} + +export def warning [message: string]: nothing -> string { + $"⚠️ ($message)" +} + +export def info [message: string]: nothing -> string { + $"ℹ️ ($message)" +} + +export def progress [message: string]: nothing -> string { + $"πŸš€ ($message)" +} + +export def working [message: string]: nothing -> string { + $"πŸ”§ ($message)" +} + +export def validate [message: string]: nothing -> string { + $"πŸ” ($message)" +} + +export def docker [message: string]: nothing -> string { + $"🐳 ($message)" +} + +export def k8s [message: string]: nothing -> string { + $"☸️ ($message)" +} + +export def template [message: string]: nothing -> string { + $"πŸ“‹ ($message)" +} + +export def config [message: string]: nothing -> string { + $"βš™οΈ ($message)" +} + +export def print-success [message: string]: nothing -> nothing { + print (success $message) +} + +export def print-error [message: string]: nothing -> nothing { + print (error $message) +} + +export def print-warning [message: string]: nothing -> nothing { + print (warning $message) +} + +export def print-info [message: string]: nothing -> nothing { + print (info $message) +} + +export def print-progress [message: string]: nothing -> nothing { + print (progress $message) +} + +export def print-working [message: string]: nothing -> nothing { + print (working $message) +} + +export def print-validate [message: string]: nothing -> nothing { + print (validate $message) +} + +export def section [title: string]: nothing -> nothing { + print "" + print $"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + print $" ($title)" + print $"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + print "" +} + +export def next-step [step: string]: nothing -> nothing { + print $" β†’ ($step)" +} diff --git a/.typedialog/platform/scripts/configure.nu b/.typedialog/platform/scripts/configure.nu new file mode 100644 index 0000000..d1a2c94 --- /dev/null +++ b/.typedialog/platform/scripts/configure.nu @@ -0,0 +1,101 @@ +#!/usr/bin/env nu + +# Interactive Configuration Wizard +# Uses TypeDialog nickel-roundtrip pattern for interactive config editing +# Supports multiple backends: cli, tui, web +# Usage: nu configure.nu orchestrator solo +# Usage: nu configure.nu control-center multiuser --backend tui +# Usage: nu configure.nu mcp-server cicd --backend web + +use ansi.nu +use external.nu +use paths.nu + +export def main [ + service: string # Service: orchestrator | control-center | mcp-server | vault-service | extension-registry | rag | ai-service | provisioning-daemon + mode: string # Mode: solo | multiuser | cicd | enterprise + --backend: string = "web" # TypeDialog backend: cli | tui | web (default: web) +]: nothing -> nothing { + # Validate inputs + paths validate-service $service + paths validate-mode $mode + paths validate-backend $backend + + # Paths + let form_path: string = (paths get-form-path $service) + let config_path: string = (paths get-value-path $service $mode) + let template_path: string = (paths get-template-path ($service + "-config.ncl.j2")) + + # Verify form exists + paths assert-file-exists $form_path + + ansi print-progress $"Launching TypeDialog wizard for ($service) in ($mode) mode" + print $" Backend: ($backend)" + print $" Form: ($form_path)" + print $" Config: ($config_path)" + print $" Template: ($template_path)" + print "" + + # Check if config already exists (to load as defaults) + let config_exists: bool = (external file-exists $config_path) + + if $config_exists { + ansi print-info "Loading existing config as defaults" + } else { + ansi print-warning "No existing config, using form defaults" + } + + print "" + + # Ensure values directory exists + let values_dir: string = (paths ensure-dir (paths values-path)) + + # Build TypeDialog command with nickel-roundtrip pattern + let cmd_args: list = 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] + } else { + # Create new config from form with template + ["nickel-roundtrip", $form_path, "--output", $config_path, "--template", $template_path] + } + + ansi print-working "Starting TypeDialog editor (backend: $backend)..." + + # Launch TypeDialog + let result: record = (external run-typedialog $backend $cmd_args) + + if $result.exit_code != 0 { + ansi print-error "TypeDialog editor failed or was cancelled" + print $result.stderr + exit 1 + } + + # Verify config was created/updated + if not (external file-exists $config_path) { + ansi print-error "Config file was not created" + exit 1 + } + + ansi print-success $"Configuration saved: ($config_path)" + + # Validate the generated config + ansi print-validate "Validating generated Nickel config..." + let validate_result: record = (external run-cmd "nickel" ["typecheck", $config_path]) + + if $validate_result.exit_code != 0 { + ansi print-error "Generated config failed validation" + print $validate_result.stderr + print "" + ansi print-warning "Your edits may need adjustment. Edit manually at: ($config_path)" + exit 1 + } + + ansi print-success "Config validation passed" + + print "" + ansi section "Next Steps" + ansi next-step $"Validate: nu scripts/validate-config.nu ($config_path)" + ansi next-step $"Generate: nu scripts/generate-configs.nu ($service) ($mode)" + ansi next-step $"Build: cargo build -p ($service)" + ansi next-step $"Run: cargo run -p ($service) -- --config provisioning/config/runtime/generated/($service).($mode).toml" +} diff --git a/.typedialog/platform/scripts/detect-services.nu b/.typedialog/platform/scripts/detect-services.nu new file mode 100644 index 0000000..e43b874 --- /dev/null +++ b/.typedialog/platform/scripts/detect-services.nu @@ -0,0 +1,129 @@ +#!/usr/bin/env nu + +# Detect Running Platform Services +# Auto-detects which platform services are currently running +# Shows health status and connection info for each service +# Usage: nu detect-services.nu +# Usage: nu detect-services.nu --docker (detect in Docker) +# Usage: nu detect-services.nu --kubernetes (detect in Kubernetes) + +use ansi.nu +use external.nu + +export def main [ + --docker = false # Detect services in Docker + --kubernetes = false # Detect services in Kubernetes +]: nothing -> nothing { + print-info "Detecting platform services..." + print "" + + # If no option specified, detect locally + if not $docker and not $kubernetes { + detect-local-services + } else if $docker { + detect-docker-services + } else if $kubernetes { + detect-kubernetes-services + } +} + +def detect-local-services []: nothing -> nothing { + section "Local Services Detection" + + let services: list> = [ + { name: "Orchestrator", port: 9090, cmd: "orchestrator" } + { name: "Control Center", port: 8080, cmd: "control-center" } + { name: "MCP Server", port: 8888, cmd: "mcp-server" } + { name: "PostgreSQL", port: 5432, cmd: "postgres" } + { name: "Gitea", port: 3000, cmd: "gitea" } + ] + + for service in $services { + detect-local-service $service.name $service.port $service.cmd + } + + print "" +} + +def detect-local-service [name: string, port: int, cmd: string]: nothing -> nothing { + let port_check: record = do { + ^lsof -i -P -n | grep LISTEN | grep $"(:($port)|port $port)" + } | complete + + let process_check: record = do { + ^pgrep -f $cmd + } | complete + + if $port_check.exit_code == 0 or $process_check.exit_code == 0 { + print-success $"($name) is RUNNING" + print $" Port: ($port)" + + if $port_check.exit_code == 0 { + print " Status: βœ“ Listening" + } + } else { + print-warning $"($name) is NOT running" + print $" Expected port: ($port)" + } + + print "" +} + +def detect-docker-services []: nothing -> nothing { + section "Docker Services Detection" + + if not (external check-command-exists "docker") { + print-error "Docker not installed" + exit 1 + } + + let containers: record = (external run-cmd "docker" ["ps", "--filter", "label=app=provisioning", "--format", "table {{.Names}}\t{{.Ports}}\t{{.Status}}"]) + + if $containers.exit_code != 0 { + print-error "Failed to detect Docker services" + print $containers.stderr + exit 1 + } + + if ($containers.stdout | str length) == 0 { + print-warning "No provisioning services found in Docker" + } else { + print $containers.stdout + print-success "Found provisioning services in Docker" + } + + print "" +} + +def detect-kubernetes-services []: nothing -> nothing { + section "Kubernetes Services Detection" + + if not (external check-command-exists "kubectl") { + print-error "kubectl not installed" + exit 1 + } + + let namespaces: list = ["provisioning", "default"] + + for ns in $namespaces { + print-working $"Checking namespace: ($ns)" + + let deployments: record = (external run-cmd "kubectl" ["get", "deployments", "-n", $ns, "-l", "app=provisioning", "-o", "wide"]) + + if $deployments.exit_code == 0 and ($deployments.stdout | str length) > 0 { + print-success $"Found deployments in namespace: ($ns)" + print $deployments.stdout + print "" + } + + let services: record = (external run-cmd "kubectl" ["get", "svc", "-n", $ns, "-l", "app=provisioning", "-o", "wide"]) + + if $services.exit_code == 0 and ($services.stdout | str length) > 0 { + print-success $"Found services in namespace: ($ns)" + print $services.stdout + print "" + } + } + + print "" +} diff --git a/.typedialog/platform/scripts/export-toml.nu b/.typedialog/platform/scripts/export-toml.nu new file mode 100644 index 0000000..34d19d2 --- /dev/null +++ b/.typedialog/platform/scripts/export-toml.nu @@ -0,0 +1,113 @@ +#!/usr/bin/env nu +# Export Nickel configuration to TOML format +# +# Usage: +# ./export-toml.nu [mode] [output-dir] +# ./export-toml.nu orchestrator solo +# ./export-toml.nu orchestrator solo ./custom-output +# ./export-toml.nu orchestrator # Uses PROVISIONING_MODE env var +# +# Examples: +# # Export from examples +# ./export-toml.nu orchestrator solo +# # Output: provisioning/config/runtime/generated/orchestrator.solo.toml +# +# # Export from custom location +# ./export-toml.nu orchestrator solo ./workspace/config/runtime +# # Output: ./workspace/config/runtime/generated/orchestrator.solo.toml + +use std + +# Default paths relative to this script +let script_dir = (pwd) +let project_root = $script_dir | path dirname | path dirname | path dirname | path dirname +let provisioning = $env.PROVISIONING? // ($project_root / "provisioning") + +# Parse arguments +let service = ($in | get 0) +let mode = ($in | get 1?)? // ($env.PROVISIONING_MODE? // "solo") +let output_base = ($in | get 2?)? // ($provisioning / "config" / "runtime") + +# Validate service name +let valid_services = [ + "orchestrator" + "control-center" + "vault-service" + "mcp-server" + "installer" + "extension-registry" + "rag" + "ai-service" +] + +if ($service not-in $valid_services) { + print $"Error: Invalid service '$service'" + print $"Valid services: ($valid_services | str join ', ')" + exit 1 +} + +# Validate mode +let valid_modes = ["solo" "multiuser" "cicd" "enterprise"] +if ($mode not-in $valid_modes) { + print $"Error: Invalid mode '$mode'" + print $"Valid modes: ($valid_modes | str join ', ')" + exit 1 +} + +# Input file: config/runtime/{service}.{mode}.ncl +let input_file = $provisioning / "config" / "runtime" / $"($service).($mode).ncl" + +# Ensure output directory exists +let output_dir = $output_base / "generated" +mkdir -p $output_dir + +# Output file: {output_dir}/{service}.{mode}.toml +let output_file = $output_dir / $"($service).($mode).toml" + +# Check if input file exists +if not ($input_file | path exists) { + print $"Error: Input file not found: $input_file" + print "" + print "Available options:" + print "1. Copy example and customize:" + print $" cp ($provisioning)/config/examples/($service).($mode).example.ncl ($input_file)" + print $" # Then customize as needed" + print "" + print "2. Or use generate-configs.nu to create from defaults" + exit 1 +} + +# Export NCL to TOML +print $"Exporting: ($input_file) β†’ ($output_file)" + +# Set NICKEL_IMPORT_PATH for import resolution +let nickel_path = if ($env.NICKEL_IMPORT_PATH? == "") { + $"($provisioning):." +} else { + $env.NICKEL_IMPORT_PATH +} + +try { + # Export to TOML + let export_result = ( + with-env { NICKEL_IMPORT_PATH: $nickel_path } { + nickel export --format toml $input_file + } + ) + + # Write to output file + $export_result | save --raw $output_file + + print $"βœ… Success: Exported to ($output_file)" + print "" + print "Config summary:" + print $" Service: ($service)" + print $" Mode: ($mode)" + print $" Source: ($input_file)" + print $" Output: ($output_file)" + print $" Size: (($output_file | stat).size | into string) bytes" +} catch { |err| + print $"❌ Error: Failed to export TOML" + print $"Error details: ($err.msg)" + exit 1 +} diff --git a/.typedialog/platform/scripts/external.nu b/.typedialog/platform/scripts/external.nu new file mode 100644 index 0000000..ac84a2a --- /dev/null +++ b/.typedialog/platform/scripts/external.nu @@ -0,0 +1,117 @@ +#!/usr/bin/env nu + +# External Command Execution Helpers +# Provides safe command execution with error handling (no try-catch, use do-complete) +# Usage: use external.nu; run-cmd "nickel" ["typecheck", "file.ncl"] + +export def run-cmd [cmd: string, args: list]: nothing -> record { + let result = do { + ^$cmd ...$args + } | complete + + $result +} + +export def run-cmd-or-fail [cmd: string, args: list, error_msg: string]: nothing -> string { + let result = (run-cmd $cmd $args) + + if $result.exit_code != 0 { + error make { + msg: $"($error_msg): ($result.stderr)" + } + } + + $result.stdout +} + +export def check-command-exists [cmd: string]: string -> bool { + let result = do { + which $cmd + } | complete + + $result.exit_code == 0 +} + +export def assert-command-exists [cmd: string]: nothing -> nothing { + if not (check-command-exists $cmd) { + error make { + msg: $"Required command not found: ($cmd)" + } + } +} + +export def run-nickel-typecheck [path: string]: nothing -> nothing { + assert-command-exists "nickel" + + let result = (run-cmd "nickel" ["typecheck", $path]) + + if $result.exit_code != 0 { + error make { + msg: $"Nickel typecheck failed for ($path): ($result.stderr)" + } + } +} + +export def run-nickel-export [path: string, format: string]: nothing -> string { + assert-command-exists "nickel" + + (run-cmd-or-fail "nickel" ["export", "--format", $format, $path] $"Nickel export failed for ($path)") +} + +export def run-yq-convert [input: string, output_format: string]: nothing -> string { + assert-command-exists "yq" + + let result = do { + echo $input | ^yq $"-P" + } | complete + + if $result.exit_code != 0 { + error make { + msg: $"yq conversion failed: ($result.stderr)" + } + } + + $result.stdout +} + +export def run-typedialog [backend: string, args: list]: nothing -> record { + assert-command-exists "typedialog" + + let cmd_args = [$backend] | append $args + + (run-cmd "typedialog" $cmd_args) +} + +export def run-typedialog-or-fail [backend: string, args: list, error_msg: string]: nothing -> nothing { + let result = (run-typedialog $backend $args) + + if $result.exit_code != 0 { + error make { + msg: $"($error_msg): ($result.stderr)" + } + } +} + +export def run-docker [args: list]: nothing -> record { + assert-command-exists "docker" + + (run-cmd "docker" $args) +} + +export def run-kubectl [args: list]: nothing -> record { + assert-command-exists "kubectl" + + (run-cmd "kubectl" $args) +} + +export def pipe-to-file [content: string, path: string]: string -> nothing { + $content | save --force $path +} + +export def file-exists [path: string]: string -> bool { + ($path | path exists) +} + +export def dir-exists [path: string]: string -> bool { + ($path | path exists) and (($path | path type) == "dir") +} diff --git a/.typedialog/platform/scripts/generate-configs.nu b/.typedialog/platform/scripts/generate-configs.nu new file mode 100644 index 0000000..6b14e13 --- /dev/null +++ b/.typedialog/platform/scripts/generate-configs.nu @@ -0,0 +1,61 @@ +#!/usr/bin/env nu + +# Generate TOML configs from Nickel sources +# Exports Nickel configs to TOML format for use by Rust services +# Usage: nu generate-configs.nu orchestrator solo +# Usage: nu generate-configs.nu control-center multiuser + +use ansi.nu +use external.nu +use paths.nu + +export def main [ + service: string # Service: orchestrator | control-center | mcp-server | vault-service | extension-registry | rag | ai-service | provisioning-daemon + mode: string # Mode: solo | multiuser | cicd | enterprise +]: nothing -> nothing { + # Validate inputs + paths validate-service $service + paths validate-mode $mode + + let nickel_path: string = (paths get-config-path $service $mode) + let toml_path: string = (paths get-output-config-path $service $mode) + + ansi print-working $"Generating TOML config for ($service) in ($mode) mode" + print $" From: ($nickel_path)" + print $" To: ($toml_path)" + + # Validate Nickel file first + paths assert-file-exists $nickel_path + + ansi print-validate "Checking Nickel syntax..." + let validate_result: record = (external run-cmd "nickel" ["typecheck", $nickel_path]) + + if $validate_result.exit_code != 0 { + ansi print-error "Nickel validation failed" + print $validate_result.stderr + exit 1 + } + + ansi print-success "Nickel syntax valid" + + # Export to TOML + ansi print-working "Exporting to TOML format..." + let export_result: record = (external run-cmd "nickel" ["export", "--format", "toml", $nickel_path]) + + if $export_result.exit_code != 0 { + ansi print-error "Nickel export failed" + print $export_result.stderr + exit 1 + } + + # Create output directory if needed + let output_dir: string = ($toml_path | path dirname) + let _ = (paths ensure-dir $output_dir) + + # Save TOML + (external pipe-to-file $export_result.stdout $toml_path) + + ansi print-success $"TOML config generated: ($toml_path)" + print "" + print $" File size: ((($toml_path) | path exists) and ((^wc -c < $toml_path | str trim) + ' bytes') or 'N/A')" +} diff --git a/.typedialog/platform/scripts/install-services.nu b/.typedialog/platform/scripts/install-services.nu new file mode 100644 index 0000000..f3f9e27 --- /dev/null +++ b/.typedialog/platform/scripts/install-services.nu @@ -0,0 +1,217 @@ +#!/usr/bin/env nu + +# Install and Deploy Platform Services +# Orchestrates full deployment workflow: config generation β†’ validation β†’ deployment +# Supports multiple backends: local, docker, kubernetes +# Usage: nu install-services.nu orchestrator solo +# Usage: nu install-services.nu all multiuser --docker +# Usage: nu install-services.nu all enterprise --kubernetes --namespace prod + +use ansi.nu +use external.nu +use paths.nu + +export def main [ + service: string # Service: orchestrator | control-center | mcp-server | vault-service | extension-registry | rag | ai-service | provisioning-daemon | all + mode: string # Mode: solo | multiuser | cicd | enterprise + --docker = false # Deploy to Docker + --kubernetes = false # Deploy to Kubernetes + --namespace: string = "provisioning" # Kubernetes namespace + --skip-config = false # Skip config generation + --skip-validation = false # Skip validation + --no-compose = false # Don't render Docker Compose +]: nothing -> nothing { + # Validate mode + paths validate-mode $mode + + # Determine services to install + let services_to_install: list = if $service == "all" { + ["orchestrator", "control-center", "mcp-server", "vault-service", "extension-registry", "rag", "ai-service", "provisioning-daemon"] + } else { + paths validate-service $service + [$service] + } + + section "Platform Services Deployment" + print $"Mode: ($mode)" + print $"Services: ($services_to_install | str join ', ')" + print $"Docker: ($docker)" + print $"K8s: ($kubernetes)" + print $"Namespace: ($namespace)" + print "" + + # Phase 1: Configuration Generation + if not $skip_config { + section "Phase 1: Configuration Generation" + + for svc in $services_to_install { + print "" + print-working $"Generating config for ($svc)..." + + let result: record = do { + ^nu (paths scripts-path) / "generate-configs.nu" $svc $mode + } | complete + + if $result.exit_code != 0 { + print-error $"Failed to generate config for ($svc)" + print $result.stderr + exit 1 + } + + print-success $"Config generated for ($svc)" + } + + print "" + } + + # Phase 2: Validation + if not $skip_validation { + section "Phase 2: Configuration Validation" + + for svc in $services_to_install { + let config_path: string = (paths get-output-config-path $svc $mode) + + if not (external file-exists $config_path) { + print-warning $"Config not found: ($config_path)" + continue + } + + print-validate $"Validating ($svc)..." + + let result: record = do { + ^nu (paths scripts-path) / "validate-config.nu" $config_path + } | complete + + if $result.exit_code != 0 { + print-error $"Validation failed for ($svc)" + print $result.stderr + exit 1 + } + } + + print "" + } + + # Phase 3: Rendering Deployment Artifacts + section "Phase 3: Rendering Deployment Artifacts" + + if $docker and not $no_compose { + print-docker "Rendering Docker Compose..." + + let result: record = do { + ^nu (paths scripts-path) / "render-docker-compose.nu" $mode + } | complete + + if $result.exit_code != 0 { + print-error "Failed to render Docker Compose" + print $result.stderr + # Continue anyway, Docker rendering is optional + } + } + + if $kubernetes { + print-k8s "Rendering Kubernetes manifests..." + + let result: record = do { + ^nu (paths scripts-path) / "render-kubernetes.nu" $mode --namespace $namespace + } | complete + + if $result.exit_code != 0 { + print-error "Failed to render Kubernetes manifests" + print $result.stderr + # Continue anyway, K8s rendering is optional + } + } + + print "" + + # Phase 4: Deployment (if requested) + if $docker { + deploy-docker $mode + } else if $kubernetes { + deploy-kubernetes $mode $namespace + } + + print "" + section "Installation Summary" + print-success "Phase 8 deployment workflow completed" + print "" + print "Generated configurations are ready for use:" + for svc in $services_to_install { + let config_path: string = (paths get-output-config-path $svc $mode) + next-step $config_path + } + + print "" + section "Next Steps" + next-step "Test configuration: cargo run -p orchestrator -- --config provisioning/config/runtime/generated/orchestrator.($mode).toml" + next-step "Full deployment: See provisioning/platform/infrastructure/ for Docker Compose and Kubernetes manifests" +} + +def deploy-docker [mode: string]: nothing -> nothing { + section "Phase 4: Docker Deployment" + + let compose_file: string = "provisioning/platform/infrastructure/docker/docker-compose." + $mode + ".yml" + + if not (external file-exists $compose_file) { + print-warning $"Docker Compose file not found: ($compose_file)" + print-info "Run with --docker flag to render Compose files first" + return + } + + print-docker $"Deploying with Docker Compose: ($compose_file)" + + let result: record = (external run-cmd "docker-compose" ["-f", $compose_file, "up", "-d"]) + + if $result.exit_code != 0 { + print-error "Docker Compose deployment failed" + print $result.stderr + exit 1 + } + + print-success "Docker Compose deployment completed" + + print "" + next-step "View logs: docker-compose -f ($compose_file) logs -f" + next-step "Stop services: docker-compose -f ($compose_file) down" + next-step "Status: docker-compose -f ($compose_file) ps" +} + +def deploy-kubernetes [mode: string, namespace: string]: nothing -> nothing { + section "Phase 4: Kubernetes Deployment" + + let manifest_dir: string = "provisioning/platform/infrastructure/kubernetes/" + $mode + + if not (external dir-exists $manifest_dir) { + print-warning $"Kubernetes manifest directory not found: ($manifest_dir)" + print-info "Run with --kubernetes flag to render manifests first" + return + } + + print-k8s $"Creating namespace: ($namespace)" + + let ns_result: record = (external run-cmd "kubectl" ["create", "namespace", $namespace]) + + # Namespace may already exist, that's ok + if $ns_result.exit_code != 0 and not ($ns_result.stderr | str contains "already exists") { + print-warning $"Namespace creation: ($ns_result.stderr)" + } + + print-k8s $"Deploying Kubernetes manifests from: ($manifest_dir)" + + let deploy_result: record = (external run-cmd "kubectl" ["apply", "-f", $manifest_dir, "-n", $namespace]) + + if $deploy_result.exit_code != 0 { + print-error "Kubernetes deployment failed" + print $deploy_result.stderr + exit 1 + } + + print-success "Kubernetes deployment completed" + + print "" + next-step "View deployments: kubectl get deployments -n ($namespace)" + next-step "View services: kubectl get svc -n ($namespace)" + next-step "View pods: kubectl get pods -n ($namespace)" + next-step "View logs: kubectl logs -n ($namespace) -l app=orchestrator -f" +} diff --git a/.typedialog/platform/scripts/paths.nu b/.typedialog/platform/scripts/paths.nu new file mode 100644 index 0000000..64e919a --- /dev/null +++ b/.typedialog/platform/scripts/paths.nu @@ -0,0 +1,143 @@ +#!/usr/bin/env nu + +# Path Management and Validation Helpers +# Provides consistent path handling for Phase 8 scripts +# Usage: use paths.nu; assert-file-exists "/some/file" + +export def assert-file-exists [path: string]: nothing -> nothing { + if not ($path | path exists) { + error make { + msg: $"File not found: ($path)" + } + } +} + +export def assert-dir-exists [path: string]: nothing -> nothing { + let path_obj = $path | path expand + + if not ($path_obj | path exists) { + error make { + msg: $"Directory not found: ($path_obj)" + } + } + + if not ($path_obj | path type) == "dir" { + error make { + msg: $"Path exists but is not a directory: ($path_obj)" + } + } +} + +export def ensure-dir [path: string]: string -> string { + let expanded = $path | path expand + + if not ($expanded | path exists) { + ^mkdir -p $expanded + } + + $expanded +} + +export def resolve-relative [path: string]: string -> string { + if ($path | str starts-with "/") { + $path + } else if ($path | str starts-with "~/") { + $path | path expand + } else { + (pwd) / $path | path expand + } +} + +export def typedialog-base-path []: nothing -> string { + "provisioning/.typedialog/platform" +} + +export def schemas-base-path []: nothing -> string { + "provisioning/schemas/platform" +} + +export def forms-path []: nothing -> string { + (typedialog-base-path) + "/forms" +} + +export def fragments-path []: nothing -> string { + (forms-path) + "/fragments" +} + +export def schemas-path []: nothing -> string { + (schemas-base-path) + "/schemas" +} + +export def defaults-path []: nothing -> string { + (schemas-base-path) + "/defaults" +} + +export def validators-path []: nothing -> string { + (schemas-base-path) + "/validators" +} + +export def configs-path []: nothing -> string { + (schemas-base-path) + "/configs" +} + +export def templates-path []: nothing -> string { + (schemas-base-path) + "/templates" +} + +export def values-path []: nothing -> string { + (schemas-base-path) + "/values" +} + +export def constraints-path []: nothing -> string { + (schemas-base-path) + "/constraints" +} + +export def get-form-path [service: string]: string -> string { + (forms-path) + "/" + $service + "-form.toml" +} + +export def get-config-path [service: string, mode: string]: string -> string { + (configs-path) + "/" + $service + "." + $mode + ".ncl" +} + +export def get-value-path [service: string, mode: string]: string -> string { + (values-path) + "/" + $service + "." + $mode + ".ncl" +} + +export def get-template-path [template_name: string]: string -> string { + (templates-path) + "/" + $template_name +} + +export def get-output-config-path [service: string, mode: string]: string -> string { + "provisioning/config/runtime/generated/" + $service + "." + $mode + ".toml" +} + +export def validate-service [service: string]: nothing -> nothing { + let valid_services = ["orchestrator", "control-center", "mcp-server", "vault-service", "extension-registry", "rag", "ai-service", "provisioning-daemon"] + + if $service not-in $valid_services { + error make { + msg: $"Invalid service: ($service). Valid options: ($valid_services | str join ', ')" + } + } +} + +export def validate-mode [mode: string]: nothing -> nothing { + let valid_modes = ["solo", "multiuser", "cicd", "enterprise"] + + if $mode not-in $valid_modes { + error make { + msg: $"Invalid deployment mode: ($mode). Valid options: ($valid_modes | str join ', ')" + } + } +} + +export def validate-backend [backend: string]: nothing -> nothing { + let valid_backends = ["cli", "tui", "web"] + + if $backend not-in $valid_backends { + error make { + msg: $"Invalid TypeDialog backend: ($backend). Valid options: ($valid_backends | str join ', ')" + } + } +} diff --git a/.typedialog/platform/scripts/render-docker-compose.nu b/.typedialog/platform/scripts/render-docker-compose.nu new file mode 100644 index 0000000..dd67588 --- /dev/null +++ b/.typedialog/platform/scripts/render-docker-compose.nu @@ -0,0 +1,82 @@ +#!/usr/bin/env nu + +# Render Docker Compose Files from Nickel Templates +# Exports Nickel templates to YAML Docker Compose format +# Usage: nu render-docker-compose.nu solo +# Usage: nu render-docker-compose.nu enterprise --output custom-compose.yml + +use ansi.nu +use external.nu +use paths.nu + +export def main [ + mode: string # Mode: solo | multiuser | cicd | enterprise + --template: string = "platform-stack.yml.ncl" # Template file name (default: platform-stack.yml.ncl) + --output: string = "" # Output path (default: infrastructure/docker/docker-compose.{mode}.yml) +]: nothing -> nothing { + # Validate inputs + paths validate-mode $mode + + # Paths + let template_path: string = (paths get-template-path ("docker-compose/" + $template)) + let default_output: string = "provisioning/platform/infrastructure/docker/docker-compose." + $mode + ".yml" + let output_path: string = if ($output | str length) > 0 { $output } else { $default_output } + + # Verify template exists + if not (external file-exists $template_path) { + print-warning $"Using default template since custom not found: ($template)" + # For now, we'll document this as a template that needs to be created + print-info "Template creation deferred to Phase 9 (Nickel Templates)" + print "" + print-info "Placeholder: Would render ($template_path) β†’ ($output_path)" + exit 0 + } + + print-docker $"Rendering Docker Compose for ($mode) mode" + print $" Template: ($template_path)" + print $" Output: ($output_path)" + print "" + + print-working "Exporting Nickel template to JSON..." + + # Export Nickel template to JSON + let json_result: record = (external run-cmd "nickel" ["export", "--format", "json", $template_path]) + + if $json_result.exit_code != 0 { + print-error "Nickel export failed" + print $json_result.stderr + exit 1 + } + + print-success "Nickel exported to JSON" + + print-working "Converting JSON to YAML..." + + # Convert JSON to YAML using yq + let yaml_result: record = do { + echo $json_result.stdout | ^yq -P + } | complete + + if $yaml_result.exit_code != 0 { + print-error "YAML conversion failed" + print $yaml_result.stderr + exit 1 + } + + print-success "JSON converted to YAML" + + # Create output directory + let output_dir: string = ($output_path | path dirname) + let _ = (paths ensure-dir $output_dir) + + # Save YAML to file + (external pipe-to-file $yaml_result.stdout $output_path) + + print-success $"Docker Compose generated: ($output_path)" + + print "" + section "Next Steps" + next-step "Validate: docker-compose -f ($output_path) config" + next-step "Deploy: docker-compose -f ($output_path) up -d" + next-step "Status: docker-compose -f ($output_path) ps" +} diff --git a/.typedialog/platform/scripts/render-kubernetes.nu b/.typedialog/platform/scripts/render-kubernetes.nu new file mode 100644 index 0000000..3409e23 --- /dev/null +++ b/.typedialog/platform/scripts/render-kubernetes.nu @@ -0,0 +1,96 @@ +#!/usr/bin/env nu + +# Render Kubernetes Manifests from Nickel Templates +# Exports Nickel templates to YAML Kubernetes manifest format +# Usage: nu render-kubernetes.nu solo +# Usage: nu render-kubernetes.nu enterprise --namespace production + +use ansi.nu +use external.nu +use paths.nu + +export def main [ + mode: string # Mode: solo | multiuser | cicd | enterprise + --namespace: string = "provisioning" # Kubernetes namespace (default: provisioning) + --output-dir: string = "" # Output directory (default: infrastructure/kubernetes/{mode}) +]: nothing -> nothing { + # Validate inputs + paths validate-mode $mode + + # Paths + let default_output_dir: string = "provisioning/platform/infrastructure/kubernetes/" + $mode + let output_path: string = if ($output_dir | str length) > 0 { $output_dir } else { $default_output_dir } + + print-k8s $"Rendering Kubernetes manifests for ($mode) mode" + print $" Namespace: ($namespace)" + print $" Output Dir: ($output_path)" + print "" + + # Ensure output directory exists + let _ = (paths ensure-dir $output_path) + + # List of Kubernetes manifests to render + let manifests: list = [ + "orchestrator-deployment.yaml.ncl" + "orchestrator-service.yaml.ncl" + "control-center-deployment.yaml.ncl" + "control-center-service.yaml.ncl" + "mcp-server-deployment.yaml.ncl" + "platform-ingress.yaml.ncl" + ] + + print-working $"Processing ($manifests | length) Kubernetes manifests..." + print "" + + let templates_path: string = (paths templates-path) + + # For each manifest template, render and save + for manifest in $manifests { + let template_path: string = $templates_path + "/kubernetes/" + $manifest + let output_file: string = ($manifest | str replace ".ncl" "") + let output_file_path: string = $output_path + "/" + $output_file + + if not (external file-exists $template_path) { + print-warning $"Template not found (will be created in Phase 9): ($manifest)" + continue + } + + print-working $"Rendering ($manifest)..." + + # Export Nickel template to JSON + let json_result: record = (external run-cmd "nickel" ["export", "--format", "json", $template_path]) + + if $json_result.exit_code != 0 { + print-error $"Failed to export ($manifest): ($json_result.stderr)" + continue + } + + # Convert JSON to YAML + let yaml_result: record = do { + echo $json_result.stdout | ^yq -P + } | complete + + if $yaml_result.exit_code != 0 { + print-error $"Failed to convert ($manifest) to YAML: ($yaml_result.stderr)" + continue + } + + # Inject namespace if applicable + let yaml_with_namespace: string = ($yaml_result.stdout | str replace "namespace: default" $"namespace: ($namespace)") + + # Save YAML + (external pipe-to-file $yaml_with_namespace $output_file_path) + + print-success $" β†’ ($output_file)" + } + + print "" + print-success $"Kubernetes manifests rendered to: ($output_path)" + + print "" + section "Next Steps" + next-step "Validate: kubectl apply -f ($output_path) --dry-run=client" + next-step "Deploy: kubectl apply -f ($output_path) --namespace ($namespace)" + next-step "Status: kubectl get deployments -n ($namespace)" + next-step "Logs: kubectl logs -n ($namespace) -l app=orchestrator -f" +} diff --git a/.typedialog/platform/scripts/test-phase9-templates.nu b/.typedialog/platform/scripts/test-phase9-templates.nu new file mode 100644 index 0000000..86c229a --- /dev/null +++ b/.typedialog/platform/scripts/test-phase9-templates.nu @@ -0,0 +1,152 @@ +#!/usr/bin/env nu + +# Test all Phase 9 templates (Docker Compose, Kubernetes, Configs) +# Validates Nickel syntax and exports to JSON/YAML/TOML +# +# Usage: nu test-phase9-templates.nu [--output-dir ./test-output] + +export def main [ + --output_dir: string = "./test-output" +]: nothing -> nothing { + let green = (ansi green) + let red = (ansi red) + let yellow = (ansi yellow) + let blue = (ansi blue) + let reset = (ansi reset) + + print $"($blue)╔════════════════════════════════════════════════════════╗($reset)" + print $"($blue)β•‘ Phase 9: Template Testing & Validation Suite β•‘($reset)" + print $"($blue)β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•($reset)" + print "" + + # Create output directory + do { ^mkdir -p $output_dir } | complete | ignore + + # ======================================================================== + # Phase 9.A: Docker Compose Templates + # ======================================================================== + print $"($yellow)Phase 9.A: Docker Compose Templates($reset)" + print "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + + [ + "platform-stack.solo.yml.ncl", + "platform-stack.multiuser.yml.ncl", + "platform-stack.cicd.yml.ncl", + "platform-stack.enterprise.yml.ncl", + ] | each { |template| + let template_path = $"provisioning/schemas/platform/templates/docker-compose/($template)" + let output_path = $"($output_dir)/($template | str replace '.ncl' '.json')" + + let test_result = do { + ^nickel export --format json $template_path | save --force $output_path + } | complete + + if $test_result.exit_code == 0 { + print $" ($green)βœ“($reset) ($template)" + } else { + print $" ($red)βœ—($reset) ($template)" + } + } + + print "" + + # ======================================================================== + # Phase 9.B: Kubernetes Deployment Templates + # ======================================================================== + print $"($yellow)Phase 9.B: Kubernetes Deployment Templates($reset)" + print "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + + [ + "orchestrator-deployment.yaml.ncl", + "orchestrator-service.yaml.ncl", + "control-center-deployment.yaml.ncl", + "control-center-service.yaml.ncl", + "mcp-server-deployment.yaml.ncl", + "mcp-server-service.yaml.ncl", + "platform-ingress.yaml.ncl", + ] | each { |template| + let template_path = $"provisioning/schemas/platform/templates/kubernetes/($template)" + let output_path = $"($output_dir)/($template | str replace '.ncl' '.yaml')" + + let test_result = do { + ^nickel export --format json $template_path | ^yq -P | save --force $output_path + } | complete + + if $test_result.exit_code == 0 { + print $" ($green)βœ“($reset) ($template)" + } else { + print $" ($red)βœ—($reset) ($template)" + } + } + + print "" + + # ======================================================================== + # Phase 9.C: Kubernetes Namespace/Configuration Templates + # ======================================================================== + print $"($yellow)Phase 9.C: Kubernetes Namespace & Configuration($reset)" + print "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + + [ + "namespace.yaml.ncl", + "resource-quota.yaml.ncl", + "network-policy.yaml.ncl", + "rbac.yaml.ncl", + ] | each { |template| + let template_path = $"provisioning/schemas/platform/templates/kubernetes/($template)" + let output_path = $"($output_dir)/($template | str replace '.ncl' '.yaml')" + + let test_result = do { + ^nickel export --format json $template_path | ^yq -P | save --force $output_path + } | complete + + if $test_result.exit_code == 0 { + print $" ($green)βœ“($reset) ($template)" + } else { + print $" ($red)βœ—($reset) ($template)" + } + } + + print "" + + # ======================================================================== + # Phase 9.D: Service Configuration Templates + # ======================================================================== + print $"($yellow)Phase 9.D: Service Configuration Templates (TOML)($reset)" + print "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + + [ + "orchestrator-config.toml.ncl", + "control-center-config.toml.ncl", + "mcp-server-config.toml.ncl", + ] | each { |template| + let template_path = $"provisioning/schemas/platform/templates/configs/($template)" + let output_path = $"($output_dir)/($template | str replace '.ncl' '')" + + let test_result = do { + ^nickel export --format toml $template_path | save --force $output_path + } | complete + + if $test_result.exit_code == 0 { + print $" ($green)βœ“($reset) ($template)" + } else { + print $" ($red)βœ—($reset) ($template)" + } + } + + print "" + + # ======================================================================== + # Test Summary + # ======================================================================== + print $"($blue)═══════════════════════════════════════════════════════($reset)" + print $"($green)βœ“ Phase 9 Template Testing Complete!($reset)" + print "" + print $"Generated files in: ($output_dir)" + print "" + print "Files created:" + print " - Docker Compose: 4 templates (solo, multiuser, cicd, enterprise)" + print " - Kubernetes: 11 templates (deployments, services, ingress, namespace, RBAC, policies)" + print " - Service Configs: 3 templates (TOML format)" + print "" +} diff --git a/.typedialog/platform/scripts/validate-config.nu b/.typedialog/platform/scripts/validate-config.nu new file mode 100644 index 0000000..7192db3 --- /dev/null +++ b/.typedialog/platform/scripts/validate-config.nu @@ -0,0 +1,29 @@ +#!/usr/bin/env nu + +# Validate Nickel Configuration +# Validates Nickel config files using typecheck +# Usage: nu validate-config.nu /path/to/config.ncl + +use ansi.nu +use external.nu +use paths.nu + +export def main [ + config_path: string # Path to Nickel config file +]: nothing -> nothing { + let expanded_path: string = (paths ensure-dir (config_path | path expand | path dirname)) + "/" + ($config_path | path basename) + + paths assert-file-exists $expanded_path + + ansi print-validate $"Validating ($expanded_path)" + + let result: record = (external run-cmd "nickel" ["typecheck", $expanded_path]) + + if $result.exit_code != 0 { + ansi print-error "Validation failed" + print $result.stderr + exit 1 + } + + ansi print-success $"Validation passed: ($expanded_path)" +} diff --git a/.typedialog/provisioning/config.ncl b/.typedialog/provisioning/config.ncl new file mode 100644 index 0000000..f1aef07 --- /dev/null +++ b/.typedialog/provisioning/config.ncl @@ -0,0 +1,79 @@ +# Example: Simple API with SQLite database +# Scenario: Development/Testing environment +# Deployment: Docker Compose +# Version: 1.0.0 + +{ + provisioning = { + project = { + name = "simple-api", + version = "0.1.0", + description = "Simple REST API with SQLite database", + tags = ["api", "sqlite", "development"], + }, + + services = { + api = { + type = 'api, + image = { + name = "simple-api", + tag = "latest", + build_context = ".", + dockerfile = "Dockerfile", + }, + ports = [{ + container_port = 8080, + host_port = 8080, + protocol = 'tcp, + }], + environment = { + LOG_LEVEL = "debug", + DATABASE_PATH = "./data/app.db", + SERVER_HOST = "0.0.0.0", + SERVER_PORT = "8080", + }, + healthcheck = { + enabled = true, + endpoint = "/health", + interval = 30, + timeout = 10, + retries = 3, + start_period = 10, + }, + volumes = ["./data:/app/data"], + restart_policy = 'unless-stopped, + replicas = 1, + }, + }, + + database = { + type = 'sqlite, + sqlite = { + database_path = "./data/app.db", + journal_mode = 'WAL, + synchronous = 'NORMAL, + cache_size = -2000, + foreign_keys = true, + }, + migrations_path = "./migrations", + auto_migrate = false, + }, + + deployment = { + target = 'docker, + docker_compose = { + enabled = true, + version = 'v3_8, + env_file = ".env", + }, + }, + + network = {}, + storage = {}, + monitoring = {}, + security = { + tls = {enabled = false}, + auth = {method = 'none}, + }, + }, +} diff --git a/.typedialog/provisioning/configure.nu b/.typedialog/provisioning/configure.nu new file mode 100755 index 0000000..d885553 --- /dev/null +++ b/.typedialog/provisioning/configure.nu @@ -0,0 +1,175 @@ +#!/usr/bin/env nu +# Provisioning Configuration Script +# Version: 1.0.0 +# Guidelines: NuShell 0.109.0+ (@.claude/guidelines/nushell.md applied) +# +# Interactive configuration for provisioning using TypeDialog. +# Updates existing config.ncl in place with Nickel roundtrip. +# Loads environment from .typedialog/provisioning/envrc (like CI does) +# +# Usage: +# nu configure.nu [web|tui|cli] [--project /path] [--port 9000] [--host localhost] + +# Load environment variables from envrc (bash-compatible format) +def load_envrc [envrc_path: path] { + if not ($envrc_path | path exists) { + return {} + } + + let envrc_content = (open $envrc_path) + let lines = ($envrc_content | split row "\n") + + mut result = {} + for line in $lines { + if ($line | str starts-with "export ") { + let var_expr = ($line | str replace "export " "" | str trim) + if ($var_expr | str contains "=") { + let parts = ($var_expr | split row "=" | take 2) + if ($parts | length) >= 2 { + let key = ($parts.0 | str replace '"' "" | str trim) + let value = ($parts.1 | str replace '"' "" | str replace "'" "" | str trim) + $result = ($result | insert $key $value) + } + } + } + } + $result +} + +def main [ + --backend: string = "web" # TypeDialog backend: web, tui, cli + --project: string = "" # Project path (default: current directory) + --port: int = 9000 # Web server port (web backend only) + --host: string = "localhost" # Web server host (web backend only) +] { + print "πŸ”§ Provisioning Configuration" + print "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + print "" + + # Validate backend + if $backend not-in ["web", "tui", "cli"] { + print "❌ Invalid backend: $backend" + print "" + print "Usage: nu configure.nu [web|tui|cli] [--project /path]" + print "" + print "Backends:" + print " web - Web server (browser-based) [default]" + print " tui - Terminal UI (interactive panels)" + print " cli - Command-line interface (simple prompts)" + return + } + + # 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 prov_dir = ($project_path | path join ".typedialog" "provisioning") + + # Verify provisioning is installed + if not ($prov_dir | path exists) { + print "❌ Error: Provisioning not installed in this project" + print $" Expected: ($prov_dir)" + print "" + print "Run this first:" + print $" nu ($tools_path)/dev-system/provisioning/install.nu --project ($project_path) --interactive" + return + } + + let form_path = ($prov_dir | path join "form.toml") + let config_path = ($prov_dir | path join "config.ncl") + let envrc_path = ($prov_dir | path join "envrc") + + # Verify form exists + if not ($form_path | path exists) { + print "❌ Error: Form file not found" + print $" Expected: ($form_path)" + return + } + + # Verify config exists (configure.nu is for updates, not initial creation) + if not ($config_path | path exists) { + print "❌ Error: Configuration file not found" + print $" Expected: ($config_path)" + print "" + print "Configuration must be created first via install.nu." + print "Run this:" + print $" nu ($tools_path)/dev-system/provisioning/install.nu --project ($project_path) --interactive --backend ($backend)" + return + } + + # Create backup (config.ncl is guaranteed to exist at this point) + let timestamp = (date now | format date "%Y%m%d_%H%M%S") + let backup_path = $"($config_path).($timestamp).bak" + cp $config_path $backup_path + let backup_name = (basename $backup_path) + print ("ℹ️ Backed up existing config to: .typedialog/provisioning/" + $backup_name) + + # Load environment from envrc (like CI's configure.sh does) + let env_from_file = (load_envrc $envrc_path) + + print ("πŸ”§ Launching TypeDialog " + $backend + " backend...") + print "ℹ️ Environment loaded from: .typedialog/provisioning/envrc" + print "" + + # Show web server info if using web backend + if $backend == "web" { + let stored_host = ($env_from_file.TYPEDIALOG_HOST? | default $host) + let stored_port = ($env_from_file.TYPEDIALOG_PORT? | default ($port | into string)) + print ("🌐 Web server will start on: http://" + $stored_host + ":" + $stored_port) + print " (Override: TYPEDIALOG_PORT=8080 TYPEDIALOG_HOST=0.0.0.0 nu configure.nu)" + print "" + } + + # Launch TypeDialog with nickel-roundtrip + let typedialog_cmd = match $backend { + "cli" => "typedialog" + "tui" => "typedialog-tui" + "web" => "typedialog-web" + _ => { + print "❌ Invalid backend" + return + } + } + + # Override port/host from command-line args if provided + let env_for_typedialog = ( + $env_from_file + | upsert TYPEDIALOG_PORT ($port | into string) + | upsert TYPEDIALOG_HOST $host + ) + + print ("Running: " + $typedialog_cmd + " nickel-roundtrip " + $config_path + " " + $form_path + " --output " + $config_path) + + let result = (with-env $env_for_typedialog { + do { + ^$typedialog_cmd nickel-roundtrip $config_path $form_path --output $config_path + } | complete + }) + + if $result.exit_code == 0 { + print "" + print "βœ… Configuration saved to: .typedialog/provisioning/config.ncl" + print "" + print "Next steps:" + print " - Review the configuration: cat .typedialog/provisioning/config.ncl" + print " - Generate manifests: nu generate.nu" + print " - Deploy: docker-compose up -d (or kubectl apply -f k8s/)" + print "" + print "To reconfigure anytime: nu configure.nu" + } else { + print "" + let msg = "❌ Configuration cancelled or failed (exit code: " + ($result.exit_code | into string) + ")" + print $msg + print "" + if ($result.stderr | str length) > 0 { + print "Error details:" + print $result.stderr + } + if ($result.stdout | str length) > 0 { + print "Output:" + print $result.stdout + } + print "" + let bak_name = (basename $backup_path) + print (" Previous config preserved in backup: " + $bak_name) + } +} diff --git a/.typedialog/provisioning/constraints.toml b/.typedialog/provisioning/constraints.toml new file mode 100644 index 0000000..3694f80 --- /dev/null +++ b/.typedialog/provisioning/constraints.toml @@ -0,0 +1,156 @@ +# Provisioning Constraints - Single Source of Truth +# Used by: Forms (validation), Nickel validators (contracts), Templates (limits) +# Version: 1.0.0 + +[project] +name_min_length = 1 +name_max_length = 64 +name_pattern = "^[a-z0-9-]+$" +version_pattern = "^[0-9]+\\.[0-9]+\\.[0-9]+$" +description_max_length = 500 + +[service] +# Service type must be one of these +allowed_types = ["api", "worker", "scheduler", "frontend", "backend", "database", "cache", "queue"] +name_min_length = 1 +name_max_length = 32 +name_pattern = "^[a-z0-9-]+$" +replicas_min = 1 +replicas_max = 100 +healthcheck_interval_min = 5 +healthcheck_interval_max = 300 +healthcheck_timeout_min = 1 +healthcheck_timeout_max = 60 +healthcheck_retries_min = 1 +healthcheck_retries_max = 10 + +[service.image] +name_min_length = 1 +name_max_length = 256 +tag_max_length = 128 +tag_pattern = "^[a-zA-Z0-9._-]+$" + +[service.ports] +container_port_min = 1 +container_port_max = 65535 +host_port_min = 1024 +host_port_max = 65535 +protocol_allowed = ["tcp", "udp", "sctp"] + +[service.resources] +# CPU limits in millicores or cores (e.g., "100m", "1.5") +cpu_limit_pattern = "^[0-9]+(\\.[0-9]+)?[m]?$" +cpu_request_pattern = "^[0-9]+(\\.[0-9]+)?[m]?$" +# Memory limits (e.g., "128Mi", "1Gi", "512M") +memory_limit_pattern = "^[0-9]+(Mi|Gi|M|G|Ki|K)$" +memory_request_pattern = "^[0-9]+(Mi|Gi|M|G|Ki|K)$" + +[database] +allowed_types = ["sqlite", "postgres", "mysql", "surrealdb", "none"] +name_pattern = "^[a-zA-Z0-9_]+$" +name_max_length = 64 + +[database.sqlite] +database_path_max_length = 256 + +[database.postgres] +host_max_length = 256 +port_min = 1024 +port_max = 65535 +database_name_max_length = 64 +username_max_length = 64 +password_min_length = 8 +password_max_length = 128 +pool_size_min = 1 +pool_size_max = 1000 +connection_timeout_min = 1 +connection_timeout_max = 300 +idle_timeout_min = 60 +idle_timeout_max = 3600 +max_lifetime_min = 300 +max_lifetime_max = 86400 + +[database.mysql] +host_max_length = 256 +port_min = 1024 +port_max = 65535 +database_name_max_length = 64 +username_max_length = 32 +password_min_length = 8 +password_max_length = 128 +pool_size_min = 1 +pool_size_max = 1000 +connection_timeout_min = 1 +connection_timeout_max = 300 + +[database.surrealdb] +host_max_length = 256 +port_min = 1024 +port_max = 65535 +namespace_max_length = 64 +database_name_max_length = 64 +username_max_length = 64 +password_min_length = 8 +password_max_length = 128 + +[deployment.docker_compose] +version_allowed = ["3.8", "3.9"] +restart_policy_allowed = ["no", "always", "on-failure", "unless-stopped"] + +[deployment.kubernetes] +namespace_pattern = "^[a-z0-9-]+$" +namespace_max_length = 63 +api_version_allowed = ["v1", "apps/v1", "networking.k8s.io/v1"] + +[deployment.kubernetes.ingress] +path_type_allowed = ["Prefix", "Exact", "ImplementationSpecific"] +class_name_max_length = 64 + +[network] +network_name_pattern = "^[a-z0-9-]+$" +network_name_max_length = 64 +driver_allowed = ["bridge", "host", "overlay", "macvlan", "none"] +subnet_pattern = "^([0-9]{1,3}\\.){3}[0-9]{1,3}/[0-9]{1,2}$" + +[storage] +volume_name_pattern = "^[a-z0-9-]+$" +volume_name_max_length = 64 +driver_allowed = ["local", "nfs", "cifs"] +mount_path_max_length = 256 +size_pattern = "^[0-9]+(Mi|Gi|Ti|M|G|T)$" + +[monitoring.prometheus] +port_min = 1024 +port_max = 65535 +scrape_interval_min = 5 +scrape_interval_max = 300 +evaluation_interval_min = 5 +evaluation_interval_max = 300 +retention_pattern = "^[0-9]+(d|h|m)$" + +[monitoring.grafana] +port_min = 1024 +port_max = 65535 +admin_password_min_length = 8 +admin_password_max_length = 128 + +[security.tls] +cert_path_max_length = 256 +key_path_max_length = 256 +ca_path_max_length = 256 + +[security.secrets] +secret_name_pattern = "^[a-z0-9-]+$" +secret_name_max_length = 64 +secret_key_max_length = 64 + +[security.auth] +allowed_methods = ["none", "basic", "bearer", "oauth2", "jwt", "api_key"] +token_expiry_min = 300 +token_expiry_max = 86400 + +[environment] +# Environment variable constraints +var_name_pattern = "^[A-Z_][A-Z0-9_]*$" +var_name_max_length = 128 +var_value_max_length = 4096 diff --git a/.typedialog/provisioning/defaults/api-service-defaults.ncl b/.typedialog/provisioning/defaults/api-service-defaults.ncl new file mode 100644 index 0000000..ce5aa6c --- /dev/null +++ b/.typedialog/provisioning/defaults/api-service-defaults.ncl @@ -0,0 +1,121 @@ +# API Service Defaults - Moderate complexity: API service with SQLite database +# Version: 1.0.0 +# +# Scenario: Single API service with SQLite database, Docker Compose deployment +# Use case: Simple APIs, MVPs, development environments + +let Service = import "../schemas/service.ncl" in +let Database = import "../schemas/database.ncl" in +let Deployment = import "../schemas/deployment.ncl" in + +{ + api_service_defaults = { + project = { + name = "api-service", + version = "0.1.0", + description = "API service with SQLite database", + tags = ["api", "sqlite", "docker"], + }, + + services = { + api = { + type = 'api, + image = { + name = "api-service", + tag = "latest", + build_context = ".", + dockerfile = "Dockerfile", + }, + ports = [{ + container_port = 8080, + host_port = 8080, + protocol = 'tcp, + }], + environment = { + LOG_LEVEL = "info", + DATABASE_PATH = "./data/app.db", + SERVER_HOST = "0.0.0.0", + SERVER_PORT = "8080", + }, + healthcheck = { + enabled = true, + endpoint = "/health", + interval = 30, + timeout = 10, + retries = 3, + start_period = 10, + }, + volumes = [ + "./data:/app/data", + ], + restart_policy = 'unless-stopped, + replicas = 1, + }, + }, + + database = { + type = 'sqlite, + sqlite = { + database_path = "./data/app.db", + journal_mode = 'WAL, + synchronous = 'NORMAL, + cache_size = -2000, + foreign_keys = true, + }, + migrations_path = "./migrations", + auto_migrate = false, + }, + + deployment = { + target = 'docker, + docker_compose = { + enabled = true, + version = '3.8, + env_file = ".env", + }, + }, + + storage = { + docker_volumes = { + data = { + name = "app-data", + driver = 'local, + external = false, + }, + }, + }, + + network = { + docker_networks = { + app_network = { + name = "app-network", + driver = 'bridge, + internal = false, + }, + }, + }, + + monitoring = { + prometheus = { + enabled = false, + }, + grafana = { + enabled = false, + }, + }, + + security = { + tls = { + enabled = false, + auto_generate = true, + }, + auth = { + method = 'api_key, + api_key = { + header_name = "X-API-Key", + keys = [], + }, + }, + }, + }, +} diff --git a/.typedialog/provisioning/defaults/docker-compose-defaults.ncl b/.typedialog/provisioning/defaults/docker-compose-defaults.ncl new file mode 100644 index 0000000..a68d080 --- /dev/null +++ b/.typedialog/provisioning/defaults/docker-compose-defaults.ncl @@ -0,0 +1,74 @@ +# Docker Compose Defaults - Docker Compose deployment configuration +# Version: 1.0.0 +# +# Scenario: Docker Compose specific defaults and best practices +# Use case: Local development, testing, small deployments + +{ + docker_compose_defaults = { + deployment = { + target = 'docker, + docker_compose = { + enabled = true, + version = '3.8, + env_file = ".env", + profiles = [], + }, + }, + + # Common Docker Compose network setup + network = { + docker_networks = { + frontend = { + name = "frontend-network", + driver = 'bridge, + internal = false, + attachable = true, + }, + backend = { + name = "backend-network", + driver = 'bridge, + internal = true, + attachable = false, + }, + }, + }, + + # Common Docker Compose volume setup + storage = { + docker_volumes = { + data = { + name = "app-data", + driver = 'local, + external = false, + labels = { + "com.docker.compose.project" = "app", + }, + }, + logs = { + name = "app-logs", + driver = 'local, + external = false, + labels = { + "com.docker.compose.project" = "app", + }, + }, + }, + }, + + # Service template with common Docker Compose settings + service_template = { + restart_policy = 'unless-stopped, + healthcheck = { + enabled = true, + interval = 30, + timeout = 10, + retries = 3, + start_period = 10, + }, + labels = { + "com.docker.compose.service" = "app", + }, + }, + }, +} diff --git a/.typedialog/provisioning/defaults/kubernetes-defaults.ncl b/.typedialog/provisioning/defaults/kubernetes-defaults.ncl new file mode 100644 index 0000000..6a9ecd3 --- /dev/null +++ b/.typedialog/provisioning/defaults/kubernetes-defaults.ncl @@ -0,0 +1,444 @@ +# Kubernetes Defaults - Complex: Multi-service Kubernetes deployment +# Version: 1.0.0 +# +# Scenario: Multi-service application with PostgreSQL, Kubernetes deployment, +# Ingress, monitoring, autoscaling +# Use case: Production deployments, cloud-native applications + +{ + kubernetes_defaults = { + project = { + name = "k8s-platform", + version = "1.0.0", + description = "Multi-service platform on Kubernetes", + tags = ["kubernetes", "postgres", "production", "microservices"], + }, + + services = { + api = { + type = 'api, + image = { + name = "platform-api", + tag = "1.0.0", + }, + ports = [{ + container_port = 8080, + host_port = 8080, + protocol = 'tcp, + }], + environment = { + LOG_LEVEL = "info", + DATABASE_URL = "postgresql://postgres:postgres@postgres-service:5432/platform", + SERVER_HOST = "0.0.0.0", + SERVER_PORT = "8080", + REDIS_URL = "redis://cache-service:6379", + }, + healthcheck = { + enabled = true, + endpoint = "/health", + interval = 30, + timeout = 10, + retries = 3, + start_period = 30, + }, + resources = { + cpu_limit = "1000m", + cpu_request = "500m", + memory_limit = "512Mi", + memory_request = "256Mi", + }, + depends_on = ["postgres", "cache"], + replicas = 3, + }, + + worker = { + type = 'worker, + image = { + name = "platform-worker", + tag = "1.0.0", + }, + ports = [], + environment = { + LOG_LEVEL = "info", + DATABASE_URL = "postgresql://postgres:postgres@postgres-service:5432/platform", + REDIS_URL = "redis://cache-service:6379", + WORKER_QUEUE = "default", + }, + healthcheck = { + enabled = false, + }, + resources = { + cpu_limit = "500m", + cpu_request = "250m", + memory_limit = "256Mi", + memory_request = "128Mi", + }, + depends_on = ["postgres", "cache"], + replicas = 2, + }, + + postgres = { + type = 'database, + image = { + name = "postgres", + tag = "15-alpine", + }, + ports = [{ + container_port = 5432, + host_port = 5432, + protocol = 'tcp, + }], + environment = { + POSTGRES_USER = "postgres", + POSTGRES_PASSWORD = "postgres", + POSTGRES_DB = "platform", + PGDATA = "/var/lib/postgresql/data/pgdata", + }, + healthcheck = { + enabled = true, + endpoint = "", + interval = 10, + timeout = 5, + retries = 5, + }, + resources = { + cpu_limit = "1000m", + cpu_request = "500m", + memory_limit = "1Gi", + memory_request = "512Mi", + }, + volumes = [ + "postgres-data:/var/lib/postgresql/data", + ], + replicas = 1, + }, + + cache = { + type = 'cache, + image = { + name = "redis", + tag = "7-alpine", + }, + ports = [{ + container_port = 6379, + host_port = 6379, + protocol = 'tcp, + }], + environment = {}, + healthcheck = { + enabled = true, + endpoint = "", + interval = 10, + timeout = 5, + retries = 3, + }, + resources = { + cpu_limit = "500m", + cpu_request = "250m", + memory_limit = "512Mi", + memory_request = "256Mi", + }, + volumes = [ + "redis-data:/data", + ], + replicas = 1, + }, + }, + + database = { + type = 'postgres, + postgres = { + host = "postgres-service", + port = 5432, + database = "platform", + username = "postgres", + password = "postgres", + pool_size = 20, + connection_timeout = 30, + idle_timeout = 600, + max_lifetime = 3600, + ssl_mode = 'prefer, + }, + migrations_path = "./migrations", + auto_migrate = false, + }, + + deployment = { + target = 'kubernetes, + kubernetes = { + enabled = true, + namespace = "production", + create_namespace = true, + namespace_config = { + name = "production", + labels = { + environment = "production", + project = "platform", + }, + }, + service = { + type = 'ClusterIP, + session_affinity = 'ClientIP, + annotations = {}, + }, + ingress = { + enabled = true, + name = "platform-ingress", + class_name = "nginx", + rules = [{ + host = "api.example.com", + http = { + paths = [{ + path = "/", + path_type = 'Prefix, + backend = { + service = { + name = "api", + port = { + number = 8080, + }, + }, + }, + }], + }, + }], + tls = [{ + hosts = ["api.example.com"], + secret_name = "platform-tls", + }], + annotations = { + "cert-manager.io/cluster-issuer" = "letsencrypt-prod", + "nginx.ingress.kubernetes.io/rate-limit" = "100", + }, + }, + deployment_strategy = { + type = 'RollingUpdate, + rolling_update = { + max_surge = "25%", + max_unavailable = "25%", + }, + }, + hpa = { + enabled = true, + min_replicas = 3, + max_replicas = 10, + target_cpu_utilization = 70, + target_memory_utilization = 80, + }, + configmaps = [{ + name = "app-config", + data = { + LOG_FORMAT = "json", + ENVIRONMENT = "production", + }, + }], + pod_annotations = { + "prometheus.io/scrape" = "true", + "prometheus.io/port" = "9090", + "prometheus.io/path" = "/metrics", + }, + pod_labels = { + app = "platform", + environment = "production", + }, + image_pull_secrets = ["registry-credentials"], + node_selector = { + "kubernetes.io/os" = "linux", + }, + tolerations = [], + }, + }, + + storage = { + kubernetes_pvcs = [ + { + name = "postgres-pvc", + access_modes = ['ReadWriteOnce], + resources = { + requests = { + storage = "20Gi", + }, + }, + storage_class_name = "fast-ssd", + }, + { + name = "redis-pvc", + access_modes = ['ReadWriteOnce], + resources = { + requests = { + storage = "5Gi", + }, + }, + storage_class_name = "fast-ssd", + }, + ], + backup_config = { + enabled = true, + schedule = "0 2 * * *", + retention_days = 30, + destination = "s3://backups/platform", + }, + }, + + network = { + kubernetes_policies = [{ + name = "api-network-policy", + pod_selector = { + matchLabels = { + app = "platform", + component = "api", + }, + }, + policy_types = ['Ingress, 'Egress], + ingress = [{ + from = [{ + pod_selector = { + matchLabels = { + app = "ingress-nginx", + }, + }, + }], + ports = [{ + port = 8080, + protocol = 'TCP, + }], + }], + egress = [{ + to = [{ + pod_selector = { + matchLabels = { + app = "platform", + component = "postgres", + }, + }, + }], + ports = [{ + port = 5432, + protocol = 'TCP, + }], + }], + }], + }, + + monitoring = { + prometheus = { + enabled = true, + port = 9090, + image = "prom/prometheus:latest", + scrape_interval = "15s", + evaluation_interval = "15s", + retention = "30d", + scrape_configs = [{ + job_name = "platform-services", + static_configs = [{ + targets = ["api:8080", "worker:9090"], + labels = { + environment = "production", + }, + }], + }], + storage_path = "/prometheus", + }, + grafana = { + enabled = true, + port = 3000, + image = "grafana/grafana:latest", + admin_user = "admin", + admin_password = "changeme", + datasources = [{ + name = "Prometheus", + type = 'prometheus, + access = 'proxy, + url = "http://prometheus:9090", + is_default = true, + }], + plugins = [ + "grafana-piechart-panel", + "grafana-clock-panel", + ], + }, + loki = { + enabled = true, + port = 3100, + image = "grafana/loki:latest", + storage_path = "/loki", + retention_period = "30d", + }, + jaeger = { + enabled = true, + collector_port = 14268, + query_port = 16686, + image = "jaegertracing/all-in-one:latest", + sampling_strategy = 'probabilistic, + sampling_param = 0.1, + }, + }, + + security = { + tls = { + enabled = true, + min_version = 'TLSv1.2, + max_version = 'TLSv1.3, + verify_client = false, + }, + kubernetes_secrets = [{ + name = "db-credentials", + type = 'Opaque, + string_data = { + POSTGRES_USER = "postgres", + POSTGRES_PASSWORD = "postgres", + }, + }], + auth = { + method = 'jwt, + jwt = { + secret = "changeme-secret-key", + algorithm = 'HS256, + expiry_seconds = 3600, + issuer = "platform-api", + audience = ["platform-web", "platform-mobile"], + }, + }, + rbac = { + roles = [ + { + name = "admin", + permissions = ["*"], + resources = ["*"], + actions = ['create, 'read, 'update, 'delete, 'list], + }, + { + name = "user", + permissions = ["read:own", "write:own"], + resources = ["users", "posts"], + actions = ['read, 'update], + }, + ], + default_role = "user", + admin_role = "admin", + }, + security_headers = { + enable_hsts = true, + hsts_max_age = 31536000, + enable_csp = true, + csp_policy = "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'", + enable_xss_protection = true, + enable_frame_options = true, + frame_options_value = 'DENY, + }, + cors = { + enabled = true, + allowed_origins = ["https://example.com", "https://www.example.com"], + allowed_methods = ["GET", "POST", "PUT", "DELETE", "OPTIONS"], + allowed_headers = ["Content-Type", "Authorization"], + allow_credentials = true, + }, + rate_limiting = { + enabled = true, + requests_per_second = 1000, + burst_size = 2000, + strategy = 'user, + }, + }, + }, +} diff --git a/.typedialog/provisioning/defaults/monitoring-defaults.ncl b/.typedialog/provisioning/defaults/monitoring-defaults.ncl new file mode 100644 index 0000000..27e8f47 --- /dev/null +++ b/.typedialog/provisioning/defaults/monitoring-defaults.ncl @@ -0,0 +1,303 @@ +# Monitoring Defaults - Monitoring stack configuration +# Version: 1.0.0 +# +# Scenario: Complete monitoring stack with Prometheus, Grafana, Loki, Jaeger +# Use case: Production observability, performance monitoring + +{ + monitoring_defaults = { + monitoring = { + prometheus = { + enabled = true, + port = 9090, + image = "prom/prometheus:latest", + scrape_interval = "15s", + evaluation_interval = "15s", + retention = "30d", + scrape_configs = [ + { + job_name = "prometheus", + static_configs = [{ + targets = ["localhost:9090"], + }], + }, + { + job_name = "node-exporter", + static_configs = [{ + targets = ["node-exporter:9100"], + }], + }, + ], + storage_path = "/prometheus", + external_labels = { + cluster = "main", + environment = "production", + }, + }, + + grafana = { + enabled = true, + port = 3000, + image = "grafana/grafana:latest", + admin_user = "admin", + admin_password = "changeme", + datasources = [ + { + name = "Prometheus", + type = 'prometheus, + access = 'proxy, + url = "http://prometheus:9090", + is_default = true, + basic_auth = false, + }, + { + name = "Loki", + type = 'loki, + access = 'proxy, + url = "http://loki:3100", + is_default = false, + basic_auth = false, + }, + { + name = "Jaeger", + type = 'jaeger, + access = 'proxy, + url = "http://jaeger:16686", + is_default = false, + basic_auth = false, + }, + ], + dashboards_path = "/etc/grafana/dashboards", + plugins = [ + "grafana-piechart-panel", + "grafana-clock-panel", + "grafana-polystat-panel", + ], + environment = { + GF_SECURITY_ADMIN_PASSWORD = "changeme", + GF_INSTALL_PLUGINS = "grafana-piechart-panel,grafana-clock-panel", + GF_SERVER_ROOT_URL = "http://localhost:3000", + }, + anonymous_access = false, + serve_from_sub_path = false, + }, + + loki = { + enabled = true, + port = 3100, + image = "grafana/loki:latest", + storage_path = "/loki", + retention_period = "30d", + }, + + jaeger = { + enabled = true, + collector_port = 14268, + query_port = 16686, + image = "jaegertracing/all-in-one:latest", + sampling_strategy = 'probabilistic, + sampling_param = 0.1, + }, + + alerts_path = "./alerts", + dashboard_refresh_interval = "30s", + }, + + # Monitoring services + services = { + prometheus = { + type = 'backend, + image = { + name = "prom/prometheus", + tag = "latest", + }, + ports = [{ + container_port = 9090, + host_port = 9090, + protocol = 'tcp, + }], + environment = {}, + volumes = [ + "./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro", + "./prometheus/alerts:/etc/prometheus/alerts:ro", + "prometheus-data:/prometheus", + ], + command = [ + "--config.file=/etc/prometheus/prometheus.yml", + "--storage.tsdb.path=/prometheus", + "--web.console.libraries=/usr/share/prometheus/console_libraries", + "--web.console.templates=/usr/share/prometheus/consoles", + "--storage.tsdb.retention.time=30d", + ], + restart_policy = 'unless-stopped, + }, + + grafana = { + type = 'backend, + image = { + name = "grafana/grafana", + tag = "latest", + }, + ports = [{ + container_port = 3000, + host_port = 3000, + protocol = 'tcp, + }], + environment = { + GF_SECURITY_ADMIN_PASSWORD = "changeme", + GF_INSTALL_PLUGINS = "grafana-piechart-panel,grafana-clock-panel", + }, + volumes = [ + "./grafana/provisioning:/etc/grafana/provisioning:ro", + "./grafana/dashboards:/etc/grafana/dashboards:ro", + "grafana-data:/var/lib/grafana", + ], + restart_policy = 'unless-stopped, + depends_on = ["prometheus"], + }, + + loki = { + type = 'backend, + image = { + name = "grafana/loki", + tag = "latest", + }, + ports = [{ + container_port = 3100, + host_port = 3100, + protocol = 'tcp, + }], + environment = {}, + volumes = [ + "./loki/loki-config.yml:/etc/loki/local-config.yaml:ro", + "loki-data:/loki", + ], + command = [ + "-config.file=/etc/loki/local-config.yaml", + ], + restart_policy = 'unless-stopped, + }, + + promtail = { + type = 'backend, + image = { + name = "grafana/promtail", + tag = "latest", + }, + ports = [], + environment = {}, + volumes = [ + "./promtail/promtail-config.yml:/etc/promtail/config.yml:ro", + "/var/log:/var/log:ro", + "/var/lib/docker/containers:/var/lib/docker/containers:ro", + ], + command = [ + "-config.file=/etc/promtail/config.yml", + ], + restart_policy = 'unless-stopped, + depends_on = ["loki"], + }, + + jaeger = { + type = 'backend, + image = { + name = "jaegertracing/all-in-one", + tag = "latest", + }, + ports = [ + { + container_port = 5775, + host_port = 5775, + protocol = 'udp, + }, + { + container_port = 6831, + host_port = 6831, + protocol = 'udp, + }, + { + container_port = 6832, + host_port = 6832, + protocol = 'udp, + }, + { + container_port = 5778, + host_port = 5778, + protocol = 'tcp, + }, + { + container_port = 16686, + host_port = 16686, + protocol = 'tcp, + }, + { + container_port = 14268, + host_port = 14268, + protocol = 'tcp, + }, + ], + environment = { + COLLECTOR_ZIPKIN_HTTP_PORT = "9411", + }, + restart_policy = 'unless-stopped, + }, + + "node-exporter" = { + type = 'backend, + image = { + name = "prom/node-exporter", + tag = "latest", + }, + ports = [{ + container_port = 9100, + host_port = 9100, + protocol = 'tcp, + }], + environment = {}, + volumes = [ + "/proc:/host/proc:ro", + "/sys:/host/sys:ro", + "/:/rootfs:ro", + ], + command = [ + "--path.procfs=/host/proc", + "--path.sysfs=/host/sys", + "--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)", + ], + restart_policy = 'unless-stopped, + }, + }, + + # Storage for monitoring + storage = { + docker_volumes = { + "prometheus-data" = { + name = "prometheus-data", + driver = 'local, + external = false, + }, + "grafana-data" = { + name = "grafana-data", + driver = 'local, + external = false, + }, + "loki-data" = { + name = "loki-data", + driver = 'local, + external = false, + }, + }, + }, + + # Network for monitoring + network = { + docker_networks = { + monitoring = { + name = "monitoring-network", + driver = 'bridge, + internal = false, + }, + }, + }, + }, +} diff --git a/.typedialog/provisioning/defaults/network-defaults.ncl b/.typedialog/provisioning/defaults/network-defaults.ncl new file mode 100644 index 0000000..194303a --- /dev/null +++ b/.typedialog/provisioning/defaults/network-defaults.ncl @@ -0,0 +1,170 @@ +# Network Defaults - Network configuration defaults +# Version: 1.0.0 +# +# Scenario: Network configuration best practices +# Use case: Multi-tier network architecture + +{ + network_defaults = { + network = { + docker_networks = { + frontend = { + name = "frontend-network", + driver = 'bridge, + driver_opts = { + "com.docker.network.bridge.name" = "br-frontend", + "com.docker.network.bridge.enable_icc" = "true", + "com.docker.network.bridge.enable_ip_masquerade" = "true", + }, + ipam = { + driver = "default", + config = [{ + subnet = "172.20.0.0/16", + gateway = "172.20.0.1", + ip_range = "172.20.0.0/24", + }], + }, + internal = false, + attachable = true, + enable_ipv6 = false, + labels = { + "com.docker.network.tier" = "frontend", + }, + }, + + backend = { + name = "backend-network", + driver = 'bridge, + driver_opts = { + "com.docker.network.bridge.name" = "br-backend", + "com.docker.network.bridge.enable_icc" = "true", + "com.docker.network.bridge.enable_ip_masquerade" = "true", + }, + ipam = { + driver = "default", + config = [{ + subnet = "172.21.0.0/16", + gateway = "172.21.0.1", + ip_range = "172.21.0.0/24", + }], + }, + internal = true, + attachable = false, + enable_ipv6 = false, + labels = { + "com.docker.network.tier" = "backend", + }, + }, + + database = { + name = "database-network", + driver = 'bridge, + driver_opts = { + "com.docker.network.bridge.name" = "br-database", + "com.docker.network.bridge.enable_icc" = "true", + "com.docker.network.bridge.enable_ip_masquerade" = "false", + }, + ipam = { + driver = "default", + config = [{ + subnet = "172.22.0.0/16", + gateway = "172.22.0.1", + ip_range = "172.22.0.0/24", + }], + }, + internal = true, + attachable = false, + enable_ipv6 = false, + labels = { + "com.docker.network.tier" = "database", + }, + }, + }, + + kubernetes_policies = [ + { + name = "default-deny-all", + pod_selector = { + matchLabels = {}, + }, + policy_types = ['Ingress, 'Egress], + ingress = [], + egress = [], + }, + { + name = "allow-dns", + pod_selector = { + matchLabels = {}, + }, + policy_types = ['Egress], + egress = [{ + to = [{ + namespace_selector = { + matchLabels = { + "kubernetes.io/metadata.name" = "kube-system", + }, + }, + }], + ports = [ + { + port = 53, + protocol = 'UDP, + }, + { + port = 53, + protocol = 'TCP, + }, + ], + }], + }, + { + name = "allow-frontend-to-backend", + pod_selector = { + matchLabels = { + tier = "frontend", + }, + }, + policy_types = ['Egress], + egress = [{ + to = [{ + pod_selector = { + matchLabels = { + tier = "backend", + }, + }, + }], + ports = [{ + port = 8080, + protocol = 'TCP, + }], + }], + }, + { + name = "allow-backend-to-database", + pod_selector = { + matchLabels = { + tier = "backend", + }, + }, + policy_types = ['Egress], + egress = [{ + to = [{ + pod_selector = { + matchLabels = { + tier = "database", + }, + }, + }], + ports = [{ + port = 5432, + protocol = 'TCP, + }], + }], + }, + ], + + dns_servers = ["1.1.1.1", "8.8.8.8"], + dns_search = ["example.com", "internal.example.com"], + }, + }, +} diff --git a/.typedialog/provisioning/defaults/provisioning-defaults.ncl b/.typedialog/provisioning/defaults/provisioning-defaults.ncl new file mode 100644 index 0000000..550efb7 --- /dev/null +++ b/.typedialog/provisioning/defaults/provisioning-defaults.ncl @@ -0,0 +1,196 @@ +# Provisioning Defaults - General default values for all provisioning configs +# Version: 1.0.0 +# +# These defaults can be merged with user configurations using std.record.merge +# or by using the default operator in schemas + +{ + provisioning_defaults = { + # Project defaults + project = { + version = "0.1.0", + tags = [], + }, + + # Service defaults (applied to all services) + service_defaults = { + replicas = 1, + restart_policy = 'unless-stopped, + healthcheck = { + enabled = true, + endpoint = "/health", + interval = 30, + timeout = 10, + retries = 3, + start_period = 0, + }, + environment = {}, + env_file = [], + depends_on = [], + volumes = [], + networks = [], + labels = {}, + }, + + # Database defaults + database = { + type = 'none, + migrations_path = "./migrations", + auto_migrate = false, + }, + + # Network defaults + network = { + docker_networks = {}, + kubernetes_policies = [], + dns_servers = [], + dns_search = [], + }, + + # Storage defaults + storage = { + docker_volumes = {}, + volume_mounts = [], + kubernetes_pvs = [], + kubernetes_pvcs = [], + }, + + # Deployment defaults + deployment = { + target = 'docker, + docker_compose = { + enabled = true, + version = '3.8, + env_file = ".env", + profiles = [], + }, + kubernetes = { + enabled = false, + namespace = "default", + create_namespace = false, + service = { + type = 'ClusterIP, + annotations = {}, + }, + deployment_strategy = { + type = 'RollingUpdate, + rolling_update = { + max_surge = "25%", + max_unavailable = "25%", + }, + }, + hpa = { + enabled = false, + min_replicas = 1, + max_replicas = 10, + target_cpu_utilization = 80, + }, + pod_annotations = {}, + pod_labels = {}, + image_pull_secrets = [], + node_selector = {}, + tolerations = [], + }, + }, + + # Monitoring defaults + monitoring = { + prometheus = { + enabled = false, + port = 9090, + image = "prom/prometheus:latest", + scrape_interval = "15s", + evaluation_interval = "15s", + retention = "15d", + storage_path = "/prometheus", + scrape_configs = [], + rule_files = [], + external_labels = {}, + }, + grafana = { + enabled = false, + port = 3000, + image = "grafana/grafana:latest", + admin_user = "admin", + datasources = [], + dashboards_path = "/etc/grafana/dashboards", + plugins = [], + environment = {}, + anonymous_access = false, + serve_from_sub_path = false, + }, + loki = { + enabled = false, + port = 3100, + image = "grafana/loki:latest", + storage_path = "/loki", + retention_period = "7d", + }, + jaeger = { + enabled = false, + collector_port = 14268, + query_port = 16686, + image = "jaegertracing/all-in-one:latest", + sampling_strategy = 'const, + sampling_param = 1.0, + }, + alerts_path = "./alerts", + dashboard_refresh_interval = "30s", + }, + + # Security defaults + security = { + tls = { + enabled = false, + min_version = 'TLSv1.2, + max_version = 'TLSv1.3, + cipher_suites = [], + verify_client = false, + auto_generate = false, + }, + docker_secrets = [], + kubernetes_secrets = [], + auth = { + method = 'none, + }, + security_headers = { + enable_hsts = true, + hsts_max_age = 31536000, + hsts_include_subdomains = true, + enable_csp = true, + csp_policy = "default-src 'self'", + enable_xss_protection = true, + enable_frame_options = true, + frame_options_value = 'DENY, + enable_content_type_nosniff = true, + enable_referrer_policy = true, + referrer_policy_value = 'strict-origin-when-cross-origin, + custom_headers = {}, + }, + cors = { + enabled = false, + allowed_origins = ["*"], + allowed_methods = ["GET", "POST", "PUT", "DELETE", "OPTIONS"], + allowed_headers = ["*"], + expose_headers = [], + allow_credentials = false, + max_age = 86400, + }, + rate_limiting = { + enabled = false, + requests_per_second = 100, + burst_size = 200, + strategy = 'ip, + }, + }, + + # Global environment variables + environment = {}, + + # Metadata + metadata = { + schema_version = "1.0.0", + custom = {}, + }, + }, +} diff --git a/.typedialog/provisioning/defaults/security-defaults.ncl b/.typedialog/provisioning/defaults/security-defaults.ncl new file mode 100644 index 0000000..9ff7c5f --- /dev/null +++ b/.typedialog/provisioning/defaults/security-defaults.ncl @@ -0,0 +1,115 @@ +# Security Defaults - Security configuration defaults +# Version: 1.0.0 +# +# Scenario: Security best practices and defaults +# Use case: Production-grade security configuration + +{ + security_defaults = { + security = { + tls = { + enabled = true, + min_version = 'TLSv1.2, + max_version = 'TLSv1.3, + cipher_suites = [ + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", + "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", + ], + verify_client = false, + auto_generate = false, + }, + + auth = { + method = 'jwt, + jwt = { + secret = "changeme-use-strong-random-secret", + algorithm = 'HS256, + expiry_seconds = 3600, + issuer = "api-service", + audience = ["web-client", "mobile-client"], + }, + }, + + rbac = { + roles = [ + { + name = "admin", + permissions = ["*"], + resources = ["*"], + actions = ['create, 'read, 'update, 'delete, 'list], + }, + { + name = "user", + permissions = ["read:own", "write:own"], + resources = ["users", "profiles"], + actions = ['read, 'update], + }, + { + name = "guest", + permissions = ["read:public"], + resources = ["public"], + actions = ['read], + }, + ], + default_role = "user", + admin_role = "admin", + }, + + security_headers = { + enable_hsts = true, + hsts_max_age = 31536000, + hsts_include_subdomains = true, + enable_csp = true, + csp_policy = "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self'", + enable_xss_protection = true, + enable_frame_options = true, + frame_options_value = 'DENY, + enable_content_type_nosniff = true, + enable_referrer_policy = true, + referrer_policy_value = 'strict-origin-when-cross-origin, + custom_headers = { + "Permissions-Policy" = "geolocation=(), microphone=(), camera=()", + "X-Permitted-Cross-Domain-Policies" = "none", + }, + }, + + cors = { + enabled = true, + allowed_origins = ["https://example.com"], + allowed_methods = ["GET", "POST", "PUT", "DELETE", "OPTIONS"], + allowed_headers = ["Content-Type", "Authorization", "X-Requested-With"], + expose_headers = ["Content-Length", "X-Request-Id"], + allow_credentials = true, + max_age = 86400, + }, + + rate_limiting = { + enabled = true, + requests_per_second = 100, + burst_size = 200, + strategy = 'ip, + }, + + docker_secrets = [], + kubernetes_secrets = [ + { + name = "jwt-secret", + type = 'Opaque, + string_data = { + JWT_SECRET = "changeme-use-strong-random-secret", + }, + }, + { + name = "tls-cert", + type = 'kubernetes.io/tls, + string_data = { + "tls.crt" = "", + "tls.key" = "", + }, + }, + ], + }, + }, +} diff --git a/.typedialog/provisioning/envrc b/.typedialog/provisioning/envrc new file mode 100644 index 0000000..bf4913b --- /dev/null +++ b/.typedialog/provisioning/envrc @@ -0,0 +1,10 @@ +# Provisioning environment configuration +# Source this file: source .typedialog/provisioning/envrc + +export NICKEL_IMPORT_PATH="/Users/Akasha/Tools/dev-system/provisioning/schemas:/Users/Akasha/Tools/dev-system/provisioning/validators:/Users/Akasha/Tools/dev-system/provisioning/defaults:/Users/Akasha/project-provisioning/provisioning/.typedialog/provisioning/schemas:/Users/Akasha/project-provisioning/provisioning/.typedialog/provisioning/validators:/Users/Akasha/project-provisioning/provisioning/.typedialog/provisioning/defaults" +export TYPEDIALOG_FRAGMENT_PATH=".typedialog/provisioning/fragments:/Users/Akasha/Tools/dev-system/provisioning/forms/fragments" + +# TypeDialog configuration (can be overridden) +export TYPEDIALOG_PORT="${TYPEDIALOG_PORT:-9000}" +export TYPEDIALOG_HOST="${TYPEDIALOG_HOST:-localhost}" +export TYPEDIALOG_LANG="${TYPEDIALOG_LANG:-${LANG:-en_US.UTF-8}}" diff --git a/.typedialog/provisioning/form.toml b/.typedialog/provisioning/form.toml new file mode 100644 index 0000000..e61be24 --- /dev/null +++ b/.typedialog/provisioning/form.toml @@ -0,0 +1,252 @@ +# Base form for Provisioning system configuration +# Uses fragments for modular, conditional provisioning configuration +# Location: .typedialog/provisioning/form.toml (generated per project) + +description = "Interactive configuration for deployment provisioning (Docker Compose, Kubernetes, databases, monitoring)" +display_mode = "complete" +locales_path = "" +name = "Provisioning Configuration Form" + +# ============================================================================ +# PROJECT INFORMATION (Always shown) +# ============================================================================ + +[[elements]] +border_bottom = true +border_top = true +name = "project_header" +title = "πŸ“¦ Project Information" +type = "section_header" + +[[elements]] +help = "Project name (lowercase alphanumeric with hyphens)" +name = "project_name" +nickel_path = ["provisioning", "project", "name"] +placeholder = "my-app" +prompt = "Project name" +required = true +type = "text" +validation_pattern = "^[a-z0-9-]+$" + +[[elements]] +help = "Semantic version (X.Y.Z)" +name = "project_version" +nickel_path = ["provisioning", "project", "version"] +placeholder = "0.1.0" +prompt = "Project version" +required = true +type = "text" +default = "0.1.0" +validation_pattern = "^[0-9]+\\.[0-9]+\\.[0-9]+$" + +[[elements]] +help = "Brief description of the project" +name = "project_description" +nickel_path = ["provisioning", "project", "description"] +placeholder = "API service for managing resources" +prompt = "Project description" +required = false +type = "text" + +# ============================================================================ +# DATABASE SELECTION (Always shown) +# ============================================================================ + +[[elements]] +border_bottom = true +border_top = true +name = "database_header" +title = "πŸ’Ύ Database Configuration" +type = "section_header" + +[[elements]] +help = "Select the database type for your application" +name = "database_type" +nickel_path = ["provisioning", "database", "type"] +prompt = "Database type" +required = true +type = "select" +options = ["none", "sqlite", "postgres", "mysql", "surrealdb"] +default = "sqlite" + +# Load database-specific fragments (conditional) +load_fragments = [ + "fragments/database-sqlite.toml", + "fragments/database-postgres.toml", + "fragments/database-mysql.toml", + "fragments/database-surrealdb.toml" +] + +# ============================================================================ +# API SERVICE CONFIGURATION (Always shown) +# ============================================================================ + +[[elements]] +border_bottom = true +border_top = true +name = "service_header" +title = "πŸš€ Service Configuration" +type = "section_header" + +[[elements]] +help = "Name of the main API service" +name = "api_service_name" +nickel_path = ["provisioning", "services", "api", "name"] +placeholder = "api" +prompt = "API service name" +required = true +type = "text" +default = "api" + +[[elements]] +help = "Container port for the API service" +name = "api_container_port" +nickel_path = ["provisioning", "services", "api", "ports", "0", "container_port"] +prompt = "Container port" +required = true +type = "custom" +custom_type = "u16" +default = "8080" +minimum = "1" +maximum = "65535" + +[[elements]] +help = "Host port to expose the API service" +name = "api_host_port" +nickel_path = ["provisioning", "services", "api", "ports", "0", "host_port"] +prompt = "Host port" +required = true +type = "custom" +custom_type = "u16" +default = "8080" +minimum = "1024" +maximum = "65535" + +[[elements]] +help = "Health check endpoint for the API" +name = "api_healthcheck_endpoint" +nickel_path = ["provisioning", "services", "api", "healthcheck", "endpoint"] +placeholder = "/health" +prompt = "Health check endpoint" +required = true +type = "text" +default = "/health" + +[[elements]] +help = "Number of service replicas" +name = "api_replicas" +nickel_path = ["provisioning", "services", "api", "replicas"] +prompt = "Number of replicas" +required = true +type = "custom" +custom_type = "u16" +default = "1" +minimum = "1" +maximum = "100" + +# ============================================================================ +# DEPLOYMENT TARGET (Always shown) +# ============================================================================ + +[[elements]] +border_bottom = true +border_top = true +name = "deployment_header" +title = "🚒 Deployment Target" +type = "section_header" + +[[elements]] +help = "Select the deployment platform" +name = "deployment_target" +nickel_path = ["provisioning", "deployment", "target"] +prompt = "Deployment target" +required = true +type = "select" +options = ["docker", "kubernetes", "both"] +default = "docker" + +# Load deployment-specific fragments (conditional) +load_fragments = [ + "fragments/deployment-docker.toml", + "fragments/deployment-k8s.toml" +] + +# ============================================================================ +# MONITORING (Optional) +# ============================================================================ + +[[elements]] +border_bottom = true +border_top = true +name = "monitoring_header" +title = "πŸ“Š Monitoring & Observability" +type = "section_header" + +[[elements]] +help = "Enable monitoring stack (Prometheus, Grafana)" +name = "enable_monitoring" +nickel_path = ["provisioning", "monitoring", "enabled"] +prompt = "Enable monitoring?" +required = true +type = "confirm" +default = false + +# Load monitoring fragment (conditional) +load_fragments = [ + "fragments/monitoring.toml" +] + +# ============================================================================ +# SECURITY (Optional) +# ============================================================================ + +[[elements]] +border_bottom = true +border_top = true +name = "security_header" +title = "πŸ”’ Security Configuration" +type = "section_header" + +[[elements]] +help = "Enable TLS/SSL for services" +name = "enable_tls" +nickel_path = ["provisioning", "security", "tls", "enabled"] +prompt = "Enable TLS/SSL?" +required = true +type = "confirm" +default = false + +[[elements]] +help = "Authentication method" +name = "auth_method" +nickel_path = ["provisioning", "security", "auth", "method"] +prompt = "Authentication method" +required = true +type = "select" +options = ["none", "basic", "bearer", "oauth2", "jwt", "api_key"] +default = "none" + +# Load security fragments (conditional) +load_fragments = [ + "fragments/auth-jwt.toml", + "fragments/auth-api-key.toml" +] + +# ============================================================================ +# CONFIRMATION (Always shown) +# ============================================================================ + +[[elements]] +border_bottom = true +border_top = true +name = "confirmation_header" +title = "βœ… Confirmation" +type = "section_header" + +[[elements]] +help = "Review your configuration and confirm to generate" +name = "confirm_generation" +prompt = "Generate provisioning configuration?" +required = true +type = "confirm" +default = true diff --git a/.typedialog/provisioning/fragments/auth-api-key.toml b/.typedialog/provisioning/fragments/auth-api-key.toml new file mode 100644 index 0000000..1dda10d --- /dev/null +++ b/.typedialog/provisioning/fragments/auth-api-key.toml @@ -0,0 +1,31 @@ +# API Key authentication configuration fragment +# Conditional: when auth_method == "api_key" + +[[elements]] +type = "text" +name = "api_key_header_name" +prompt = "API key header name" +help = "HTTP header name for API key (e.g., 'X-API-Key', 'Authorization')" +default = "X-API-Key" +nickel_path = ["provisioning", "security", "auth", "api_key", "header_name"] +required = true +when = "auth_method == api_key" + +[[elements]] +type = "text" +name = "api_key_query_param" +prompt = "API key query parameter (optional)" +help = "Query parameter name for API key (e.g., 'api_key'). Leave empty to disable." +placeholder = "api_key" +nickel_path = ["provisioning", "security", "auth", "api_key", "query_param"] +required = false +when = "auth_method == api_key" + +[[elements]] +type = "section_header" +name = "api_key_note" +title = "ℹ️ API Keys Configuration" +border_top = true +border_bottom = true +help = "API keys will need to be manually configured in the generated config file" +when = "auth_method == api_key" diff --git a/.typedialog/provisioning/fragments/auth-jwt.toml b/.typedialog/provisioning/fragments/auth-jwt.toml new file mode 100644 index 0000000..ea10785 --- /dev/null +++ b/.typedialog/provisioning/fragments/auth-jwt.toml @@ -0,0 +1,46 @@ +# JWT authentication configuration fragment +# Conditional: when auth_method == "jwt" + +[[elements]] +type = "password" +name = "jwt_secret" +prompt = "JWT secret key" +help = "Secret key for signing JWT tokens (min 8 characters, use strong random string)" +placeholder = "your-secret-key-here" +nickel_path = ["provisioning", "security", "auth", "jwt", "secret"] +required = true +when = "auth_method == jwt" + +[[elements]] +type = "select" +name = "jwt_algorithm" +prompt = "JWT signing algorithm" +help = "Algorithm for signing JWT tokens" +options = ["HS256", "HS384", "HS512", "RS256", "RS384", "RS512"] +default = "HS256" +nickel_path = ["provisioning", "security", "auth", "jwt", "algorithm"] +required = true +when = "auth_method == jwt" + +[[elements]] +type = "custom" +custom_type = "u32" +name = "jwt_expiry_seconds" +prompt = "Token expiry (seconds)" +help = "JWT token expiration time in seconds (300-86400)" +default = "3600" +minimum = "300" +maximum = "86400" +nickel_path = ["provisioning", "security", "auth", "jwt", "expiry_seconds"] +required = true +when = "auth_method == jwt" + +[[elements]] +type = "text" +name = "jwt_issuer" +prompt = "JWT issuer" +help = "Issuer claim for JWT tokens (e.g., 'my-api')" +placeholder = "my-api" +nickel_path = ["provisioning", "security", "auth", "jwt", "issuer"] +required = false +when = "auth_method == jwt" diff --git a/.typedialog/provisioning/fragments/database-mysql.toml b/.typedialog/provisioning/fragments/database-mysql.toml new file mode 100644 index 0000000..addfc85 --- /dev/null +++ b/.typedialog/provisioning/fragments/database-mysql.toml @@ -0,0 +1,88 @@ +# MySQL database configuration fragment +# Conditional: when database_type == "mysql" + +[[elements]] +type = "text" +name = "mysql_host" +prompt = "MySQL host" +help = "Hostname or IP address of MySQL server" +default = "localhost" +nickel_path = ["provisioning", "database", "mysql", "host"] +required = true +when = "database_type == mysql" + +[[elements]] +type = "custom" +custom_type = "u16" +name = "mysql_port" +prompt = "MySQL port" +help = "Port number for MySQL server" +default = "3306" +minimum = "1024" +maximum = "65535" +nickel_path = ["provisioning", "database", "mysql", "port"] +required = true +when = "database_type == mysql" + +[[elements]] +type = "text" +name = "mysql_database" +prompt = "Database name" +help = "MySQL database name" +placeholder = "myapp" +nickel_path = ["provisioning", "database", "mysql", "database"] +required = true +when = "database_type == mysql" +validation_pattern = "^[a-zA-Z0-9_]+$" + +[[elements]] +type = "text" +name = "mysql_username" +prompt = "Database username" +help = "MySQL username for authentication" +default = "root" +nickel_path = ["provisioning", "database", "mysql", "username"] +required = true +when = "database_type == mysql" + +[[elements]] +type = "password" +name = "mysql_password" +prompt = "Database password" +help = "MySQL password (min 8 characters)" +nickel_path = ["provisioning", "database", "mysql", "password"] +required = true +when = "database_type == mysql" + +[[elements]] +type = "custom" +custom_type = "u16" +name = "mysql_pool_size" +prompt = "Connection pool size" +help = "Maximum number of database connections (1-1000)" +default = "10" +minimum = "1" +maximum = "1000" +nickel_path = ["provisioning", "database", "mysql", "pool_size"] +required = true +when = "database_type == mysql" + +[[elements]] +type = "text" +name = "mysql_charset" +prompt = "Character set" +help = "MySQL character set" +default = "utf8mb4" +nickel_path = ["provisioning", "database", "mysql", "charset"] +required = true +when = "database_type == mysql" + +[[elements]] +type = "text" +name = "mysql_collation" +prompt = "Collation" +help = "MySQL collation" +default = "utf8mb4_unicode_ci" +nickel_path = ["provisioning", "database", "mysql", "collation"] +required = true +when = "database_type == mysql" diff --git a/.typedialog/provisioning/fragments/database-postgres.toml b/.typedialog/provisioning/fragments/database-postgres.toml new file mode 100644 index 0000000..d5fc098 --- /dev/null +++ b/.typedialog/provisioning/fragments/database-postgres.toml @@ -0,0 +1,92 @@ +# PostgreSQL database configuration fragment +# Conditional: when database_type == "postgres" + +[[elements]] +type = "text" +name = "postgres_host" +prompt = "PostgreSQL host" +help = "Hostname or IP address of PostgreSQL server" +default = "localhost" +nickel_path = ["provisioning", "database", "postgres", "host"] +required = true +when = "database_type == postgres" + +[[elements]] +type = "custom" +custom_type = "u16" +name = "postgres_port" +prompt = "PostgreSQL port" +help = "Port number for PostgreSQL server" +default = "5432" +minimum = "1024" +maximum = "65535" +nickel_path = ["provisioning", "database", "postgres", "port"] +required = true +when = "database_type == postgres" + +[[elements]] +type = "text" +name = "postgres_database" +prompt = "Database name" +help = "PostgreSQL database name" +placeholder = "myapp" +nickel_path = ["provisioning", "database", "postgres", "database"] +required = true +when = "database_type == postgres" +validation_pattern = "^[a-zA-Z0-9_]+$" + +[[elements]] +type = "text" +name = "postgres_username" +prompt = "Database username" +help = "PostgreSQL username for authentication" +default = "postgres" +nickel_path = ["provisioning", "database", "postgres", "username"] +required = true +when = "database_type == postgres" + +[[elements]] +type = "password" +name = "postgres_password" +prompt = "Database password" +help = "PostgreSQL password (min 8 characters)" +nickel_path = ["provisioning", "database", "postgres", "password"] +required = true +when = "database_type == postgres" + +[[elements]] +type = "custom" +custom_type = "u16" +name = "postgres_pool_size" +prompt = "Connection pool size" +help = "Maximum number of database connections (1-1000)" +default = "10" +minimum = "1" +maximum = "1000" +nickel_path = ["provisioning", "database", "postgres", "pool_size"] +required = true +when = "database_type == postgres" + +[[elements]] +type = "custom" +custom_type = "u16" +name = "postgres_connection_timeout" +prompt = "Connection timeout (seconds)" +help = "Timeout for establishing database connections (1-300)" +default = "30" +minimum = "1" +maximum = "300" +nickel_path = ["provisioning", "database", "postgres", "connection_timeout"] +required = true +when = "database_type == postgres" + +[[elements]] +type = "select" +name = "postgres_ssl_mode" +prompt = "SSL mode" +help = "PostgreSQL SSL connection mode" +options = ["disable", "allow", "prefer", "require", "verify-ca", "verify-full"] +default = "prefer" +nickel_path = ["provisioning", "database", "postgres", "ssl_mode"] +required = true +when = "database_type == postgres" diff --git a/.typedialog/provisioning/fragments/database-sqlite.toml b/.typedialog/provisioning/fragments/database-sqlite.toml new file mode 100644 index 0000000..181390c --- /dev/null +++ b/.typedialog/provisioning/fragments/database-sqlite.toml @@ -0,0 +1,44 @@ +# SQLite database configuration fragment +# Conditional: when database_type == "sqlite" + +[[elements]] +type = "text" +name = "sqlite_database_path" +prompt = "Database file path" +help = "Path to SQLite database file (will be created if it doesn't exist)" +default = "./data/app.db" +nickel_path = ["provisioning", "database", "sqlite", "database_path"] +required = true +when = "database_type == sqlite" + +[[elements]] +type = "select" +name = "sqlite_journal_mode" +prompt = "Journal mode" +help = "SQLite journaling mode (WAL is recommended for concurrency)" +options = ["WAL", "DELETE", "TRUNCATE", "PERSIST", "MEMORY"] +default = "WAL" +nickel_path = ["provisioning", "database", "sqlite", "journal_mode"] +required = true +when = "database_type == sqlite" + +[[elements]] +type = "select" +name = "sqlite_synchronous" +prompt = "Synchronous mode" +help = "SQLite synchronous mode (NORMAL balances safety and speed)" +options = ["OFF", "NORMAL", "FULL", "EXTRA"] +default = "NORMAL" +nickel_path = ["provisioning", "database", "sqlite", "synchronous"] +required = true +when = "database_type == sqlite" + +[[elements]] +type = "confirm" +name = "sqlite_foreign_keys" +prompt = "Enable foreign key constraints?" +help = "Enable SQLite foreign key enforcement" +default = true +nickel_path = ["provisioning", "database", "sqlite", "foreign_keys"] +required = true +when = "database_type == sqlite" diff --git a/.typedialog/provisioning/fragments/database-surrealdb.toml b/.typedialog/provisioning/fragments/database-surrealdb.toml new file mode 100644 index 0000000..6f3249d --- /dev/null +++ b/.typedialog/provisioning/fragments/database-surrealdb.toml @@ -0,0 +1,75 @@ +# SurrealDB database configuration fragment +# Conditional: when database_type == "surrealdb" + +[[elements]] +type = "text" +name = "surrealdb_host" +prompt = "SurrealDB host" +help = "Hostname or IP address of SurrealDB server" +default = "localhost" +nickel_path = ["provisioning", "database", "surrealdb", "host"] +required = true +when = "database_type == surrealdb" + +[[elements]] +type = "custom" +custom_type = "u16" +name = "surrealdb_port" +prompt = "SurrealDB port" +help = "Port number for SurrealDB server" +default = "8000" +minimum = "1024" +maximum = "65535" +nickel_path = ["provisioning", "database", "surrealdb", "port"] +required = true +when = "database_type == surrealdb" + +[[elements]] +type = "text" +name = "surrealdb_namespace" +prompt = "Namespace" +help = "SurrealDB namespace" +placeholder = "myapp" +nickel_path = ["provisioning", "database", "surrealdb", "namespace"] +required = true +when = "database_type == surrealdb" + +[[elements]] +type = "text" +name = "surrealdb_database" +prompt = "Database name" +help = "SurrealDB database name" +placeholder = "main" +nickel_path = ["provisioning", "database", "surrealdb", "database"] +required = true +when = "database_type == surrealdb" + +[[elements]] +type = "text" +name = "surrealdb_username" +prompt = "Database username" +help = "SurrealDB username for authentication" +default = "root" +nickel_path = ["provisioning", "database", "surrealdb", "username"] +required = true +when = "database_type == surrealdb" + +[[elements]] +type = "password" +name = "surrealdb_password" +prompt = "Database password" +help = "SurrealDB password (min 8 characters)" +nickel_path = ["provisioning", "database", "surrealdb", "password"] +required = true +when = "database_type == surrealdb" + +[[elements]] +type = "select" +name = "surrealdb_protocol" +prompt = "Connection protocol" +help = "Protocol for connecting to SurrealDB" +options = ["http", "https", "ws", "wss"] +default = "http" +nickel_path = ["provisioning", "database", "surrealdb", "protocol"] +required = true +when = "database_type == surrealdb" diff --git a/.typedialog/provisioning/fragments/deployment-docker.toml b/.typedialog/provisioning/fragments/deployment-docker.toml new file mode 100644 index 0000000..84aaa7a --- /dev/null +++ b/.typedialog/provisioning/fragments/deployment-docker.toml @@ -0,0 +1,44 @@ +# Docker Compose deployment configuration fragment +# Conditional: when deployment_target == "docker" or deployment_target == "both" + +[[elements]] +type = "select" +name = "docker_compose_version" +prompt = "Docker Compose version" +help = "Docker Compose file format version" +options = ["3.8", "3.9"] +default = "3.8" +nickel_path = ["provisioning", "deployment", "docker_compose", "version"] +required = true +when = "deployment_target == docker || deployment_target == both" + +[[elements]] +type = "text" +name = "docker_project_name" +prompt = "Docker Compose project name" +help = "Project name for Docker Compose (optional, uses directory name if not set)" +placeholder = "my-app" +nickel_path = ["provisioning", "deployment", "docker_compose", "project_name"] +required = false +when = "deployment_target == docker || deployment_target == both" + +[[elements]] +type = "text" +name = "docker_env_file" +prompt = "Environment file path" +help = "Path to .env file for environment variables" +default = ".env" +nickel_path = ["provisioning", "deployment", "docker_compose", "env_file"] +required = true +when = "deployment_target == docker || deployment_target == both" + +[[elements]] +type = "select" +name = "restart_policy" +prompt = "Container restart policy" +help = "Restart policy for containers" +options = ["no", "always", "on-failure", "unless-stopped"] +default = "unless-stopped" +nickel_path = ["provisioning", "services", "api", "restart_policy"] +required = true +when = "deployment_target == docker || deployment_target == both" diff --git a/.typedialog/provisioning/fragments/deployment-k8s.toml b/.typedialog/provisioning/fragments/deployment-k8s.toml new file mode 100644 index 0000000..7434675 --- /dev/null +++ b/.typedialog/provisioning/fragments/deployment-k8s.toml @@ -0,0 +1,153 @@ +# Kubernetes deployment configuration fragment +# Conditional: when deployment_target == "kubernetes" or deployment_target == "both" + +[[elements]] +type = "text" +name = "k8s_namespace" +prompt = "Kubernetes namespace" +help = "Namespace for deploying resources" +default = "default" +nickel_path = ["provisioning", "deployment", "kubernetes", "namespace"] +required = true +when = "deployment_target == kubernetes || deployment_target == both" +validation_pattern = "^[a-z0-9-]+$" + +[[elements]] +type = "confirm" +name = "k8s_create_namespace" +prompt = "Create namespace if it doesn't exist?" +help = "Automatically create the namespace during deployment" +default = false +nickel_path = ["provisioning", "deployment", "kubernetes", "create_namespace"] +required = true +when = "deployment_target == kubernetes || deployment_target == both" + +[[elements]] +type = "select" +name = "k8s_service_type" +prompt = "Service type" +help = "Kubernetes Service type" +options = ["ClusterIP", "NodePort", "LoadBalancer"] +default = "ClusterIP" +nickel_path = ["provisioning", "deployment", "kubernetes", "service", "type"] +required = true +when = "deployment_target == kubernetes || deployment_target == both" + +[[elements]] +type = "confirm" +name = "k8s_enable_ingress" +prompt = "Enable Ingress?" +help = "Create an Ingress resource for external access" +default = false +nickel_path = ["provisioning", "deployment", "kubernetes", "ingress", "enabled"] +required = true +when = "deployment_target == kubernetes || deployment_target == both" + +[[elements]] +type = "text" +name = "k8s_ingress_class" +prompt = "Ingress class name" +help = "Ingress controller class (e.g., nginx, traefik)" +default = "nginx" +nickel_path = ["provisioning", "deployment", "kubernetes", "ingress", "class_name"] +required = true +when = "(deployment_target == kubernetes || deployment_target == both) && k8s_enable_ingress == true" + +[[elements]] +type = "text" +name = "k8s_ingress_host" +prompt = "Ingress hostname" +help = "Hostname for Ingress (e.g., api.example.com)" +placeholder = "api.example.com" +nickel_path = ["provisioning", "deployment", "kubernetes", "ingress", "rules", 0, "host"] +required = true +when = "(deployment_target == kubernetes || deployment_target == both) && k8s_enable_ingress == true" + +[[elements]] +type = "confirm" +name = "k8s_enable_hpa" +prompt = "Enable Horizontal Pod Autoscaler?" +help = "Automatically scale pods based on CPU/memory usage" +default = false +nickel_path = ["provisioning", "deployment", "kubernetes", "hpa", "enabled"] +required = true +when = "deployment_target == kubernetes || deployment_target == both" + +[[elements]] +type = "custom" +custom_type = "u16" +name = "k8s_hpa_min_replicas" +prompt = "Minimum replicas" +help = "Minimum number of pods (1-100)" +default = "1" +minimum = "1" +maximum = "100" +nickel_path = ["provisioning", "deployment", "kubernetes", "hpa", "min_replicas"] +required = true +when = "(deployment_target == kubernetes || deployment_target == both) && k8s_enable_hpa == true" + +[[elements]] +type = "custom" +custom_type = "u16" +name = "k8s_hpa_max_replicas" +prompt = "Maximum replicas" +help = "Maximum number of pods (1-100)" +default = "10" +minimum = "1" +maximum = "100" +nickel_path = ["provisioning", "deployment", "kubernetes", "hpa", "max_replicas"] +required = true +when = "(deployment_target == kubernetes || deployment_target == both) && k8s_enable_hpa == true" + +[[elements]] +type = "custom" +custom_type = "u16" +name = "k8s_hpa_cpu_target" +prompt = "Target CPU utilization (%)" +help = "Target CPU utilization percentage (1-100)" +default = "80" +minimum = "1" +maximum = "100" +nickel_path = ["provisioning", "deployment", "kubernetes", "hpa", "target_cpu_utilization"] +required = true +when = "(deployment_target == kubernetes || deployment_target == both) && k8s_enable_hpa == true" + +[[elements]] +type = "text" +name = "k8s_cpu_request" +prompt = "CPU request" +help = "CPU request (e.g., '100m', '1')" +default = "100m" +nickel_path = ["provisioning", "services", "api", "resources", "cpu_request"] +required = false +when = "deployment_target == kubernetes || deployment_target == both" + +[[elements]] +type = "text" +name = "k8s_cpu_limit" +prompt = "CPU limit" +help = "CPU limit (e.g., '500m', '2')" +default = "500m" +nickel_path = ["provisioning", "services", "api", "resources", "cpu_limit"] +required = false +when = "deployment_target == kubernetes || deployment_target == both" + +[[elements]] +type = "text" +name = "k8s_memory_request" +prompt = "Memory request" +help = "Memory request (e.g., '128Mi', '1Gi')" +default = "128Mi" +nickel_path = ["provisioning", "services", "api", "resources", "memory_request"] +required = false +when = "deployment_target == kubernetes || deployment_target == both" + +[[elements]] +type = "text" +name = "k8s_memory_limit" +prompt = "Memory limit" +help = "Memory limit (e.g., '512Mi', '2Gi')" +default = "512Mi" +nickel_path = ["provisioning", "services", "api", "resources", "memory_limit"] +required = false +when = "deployment_target == kubernetes || deployment_target == both" diff --git a/.typedialog/provisioning/fragments/monitoring.toml b/.typedialog/provisioning/fragments/monitoring.toml new file mode 100644 index 0000000..4fead0d --- /dev/null +++ b/.typedialog/provisioning/fragments/monitoring.toml @@ -0,0 +1,98 @@ +# Monitoring configuration fragment +# Conditional: when enable_monitoring == true + +[[elements]] +type = "confirm" +name = "enable_prometheus" +prompt = "Enable Prometheus?" +help = "Enable Prometheus for metrics collection" +default = true +nickel_path = ["provisioning", "monitoring", "prometheus", "enabled"] +required = true +when = "enable_monitoring == true" + +[[elements]] +type = "custom" +custom_type = "u16" +name = "prometheus_port" +prompt = "Prometheus port" +help = "Port for Prometheus web UI" +default = "9090" +minimum = "1024" +maximum = "65535" +nickel_path = ["provisioning", "monitoring", "prometheus", "port"] +required = true +when = "enable_monitoring == true && enable_prometheus == true" + +[[elements]] +type = "text" +name = "prometheus_retention" +prompt = "Data retention period" +help = "How long to keep metrics (e.g., '15d', '30d')" +default = "15d" +nickel_path = ["provisioning", "monitoring", "prometheus", "retention"] +required = true +when = "enable_monitoring == true && enable_prometheus == true" + +[[elements]] +type = "confirm" +name = "enable_grafana" +prompt = "Enable Grafana?" +help = "Enable Grafana for visualizing metrics" +default = true +nickel_path = ["provisioning", "monitoring", "grafana", "enabled"] +required = true +when = "enable_monitoring == true" + +[[elements]] +type = "custom" +custom_type = "u16" +name = "grafana_port" +prompt = "Grafana port" +help = "Port for Grafana web UI" +default = "3000" +minimum = "1024" +maximum = "65535" +nickel_path = ["provisioning", "monitoring", "grafana", "port"] +required = true +when = "enable_monitoring == true && enable_grafana == true" + +[[elements]] +type = "text" +name = "grafana_admin_user" +prompt = "Grafana admin username" +help = "Admin username for Grafana" +default = "admin" +nickel_path = ["provisioning", "monitoring", "grafana", "admin_user"] +required = true +when = "enable_monitoring == true && enable_grafana == true" + +[[elements]] +type = "password" +name = "grafana_admin_password" +prompt = "Grafana admin password" +help = "Admin password for Grafana (min 8 characters)" +default = "changeme" +nickel_path = ["provisioning", "monitoring", "grafana", "admin_password"] +required = true +when = "enable_monitoring == true && enable_grafana == true" + +[[elements]] +type = "confirm" +name = "enable_loki" +prompt = "Enable Loki?" +help = "Enable Loki for log aggregation" +default = false +nickel_path = ["provisioning", "monitoring", "loki", "enabled"] +required = true +when = "enable_monitoring == true" + +[[elements]] +type = "confirm" +name = "enable_jaeger" +prompt = "Enable Jaeger?" +help = "Enable Jaeger for distributed tracing" +default = false +nickel_path = ["provisioning", "monitoring", "jaeger", "enabled"] +required = true +when = "enable_monitoring == true" diff --git a/.typedialog/provisioning/schemas/database.ncl b/.typedialog/provisioning/schemas/database.ncl new file mode 100644 index 0000000..03cb431 --- /dev/null +++ b/.typedialog/provisioning/schemas/database.ncl @@ -0,0 +1,299 @@ +# Database Schema - Database configurations for provisioning +# Version: 1.0.0 + +{ + # SQLite configuration + SqliteConfig = { + database_path + | String + | doc "Path to SQLite database file" + | { + label = "valid path", + predicate = fun s => std.string.length s >= 1 && std.string.length s <= 256 + } + | default = "./data/app.db", + + journal_mode + | [| 'WAL, 'DELETE, 'TRUNCATE, 'PERSIST, 'MEMORY |] + | doc "SQLite journal mode" + | default = 'WAL, + + synchronous + | [| 'OFF, 'NORMAL, 'FULL, 'EXTRA |] + | doc "SQLite synchronous mode" + | default = 'NORMAL, + + cache_size + | Number + | doc "Cache size in pages (negative for KB)" + | default = -2000, + + foreign_keys + | Bool + | doc "Enable foreign key constraints" + | default = true, + }, + + # PostgreSQL configuration + PostgresConfig = { + host + | String + | doc "PostgreSQL server hostname" + | { + label = "valid hostname", + predicate = fun s => std.string.length s >= 1 && std.string.length s <= 256 + } + | default = "localhost", + + port + | Number + | doc "PostgreSQL server port (1024-65535)" + | { + label = "valid port", + predicate = fun p => p >= 1024 && p <= 65535 + } + | default = 5432, + + database + | String + | doc "Database name" + | { + label = "valid database name", + predicate = fun s => + std.string.is_match "^[a-zA-Z0-9_]+$" s && + std.string.length s >= 1 && std.string.length s <= 64 + }, + + username + | String + | doc "Database username" + | { + label = "valid username", + predicate = fun s => std.string.length s >= 1 && std.string.length s <= 64 + }, + + password + | String + | doc "Database password (8-128 characters)" + | { + label = "valid password", + predicate = fun s => std.string.length s >= 8 && std.string.length s <= 128 + }, + + pool_size + | Number + | doc "Connection pool size (1-1000)" + | { + label = "valid pool size", + predicate = fun n => n >= 1 && n <= 1000 + } + | default = 10, + + connection_timeout + | Number + | doc "Connection timeout in seconds (1-300)" + | { + label = "valid timeout", + predicate = fun n => n >= 1 && n <= 300 + } + | default = 30, + + idle_timeout + | Number + | doc "Idle connection timeout in seconds (60-3600)" + | { + label = "valid idle timeout", + predicate = fun n => n >= 60 && n <= 3600 + } + | default = 600, + + max_lifetime + | Number + | doc "Maximum connection lifetime in seconds (300-86400)" + | { + label = "valid max lifetime", + predicate = fun n => n >= 300 && n <= 86400 + } + | default = 3600, + + ssl_mode + | [| 'disable, 'allow, 'prefer, 'require, 'verify-ca, 'verify-full |] + | doc "SSL mode for connections" + | default = 'prefer, + + application_name + | String + | doc "Application name for connection tracking" + | optional, + }, + + # MySQL configuration + MysqlConfig = { + host + | String + | doc "MySQL server hostname" + | { + label = "valid hostname", + predicate = fun s => std.string.length s >= 1 && std.string.length s <= 256 + } + | default = "localhost", + + port + | Number + | doc "MySQL server port (1024-65535)" + | { + label = "valid port", + predicate = fun p => p >= 1024 && p <= 65535 + } + | default = 3306, + + database + | String + | doc "Database name" + | { + label = "valid database name", + predicate = fun s => + std.string.is_match "^[a-zA-Z0-9_]+$" s && + std.string.length s >= 1 && std.string.length s <= 64 + }, + + username + | String + | doc "Database username" + | { + label = "valid username", + predicate = fun s => std.string.length s >= 1 && std.string.length s <= 32 + }, + + password + | String + | doc "Database password (8-128 characters)" + | { + label = "valid password", + predicate = fun s => std.string.length s >= 8 && std.string.length s <= 128 + }, + + pool_size + | Number + | doc "Connection pool size (1-1000)" + | { + label = "valid pool size", + predicate = fun n => n >= 1 && n <= 1000 + } + | default = 10, + + connection_timeout + | Number + | doc "Connection timeout in seconds (1-300)" + | { + label = "valid timeout", + predicate = fun n => n >= 1 && n <= 300 + } + | default = 30, + + charset + | String + | doc "Character set for connections" + | default = "utf8mb4", + + collation + | String + | doc "Collation for connections" + | default = "utf8mb4_unicode_ci", + }, + + # SurrealDB configuration + SurrealdbConfig = { + host + | String + | doc "SurrealDB server hostname" + | { + label = "valid hostname", + predicate = fun s => std.string.length s >= 1 && std.string.length s <= 256 + } + | default = "localhost", + + port + | Number + | doc "SurrealDB server port (1024-65535)" + | { + label = "valid port", + predicate = fun p => p >= 1024 && p <= 65535 + } + | default = 8000, + + namespace + | String + | doc "SurrealDB namespace" + | { + label = "valid namespace", + predicate = fun s => std.string.length s >= 1 && std.string.length s <= 64 + }, + + database + | String + | doc "Database name" + | { + label = "valid database name", + predicate = fun s => std.string.length s >= 1 && std.string.length s <= 64 + }, + + username + | String + | doc "Database username" + | { + label = "valid username", + predicate = fun s => std.string.length s >= 1 && std.string.length s <= 64 + }, + + password + | String + | doc "Database password (8-128 characters)" + | { + label = "valid password", + predicate = fun s => std.string.length s >= 8 && std.string.length s <= 128 + }, + + protocol + | [| 'http, 'https, 'ws, 'wss |] + | doc "Connection protocol" + | default = 'http, + }, + + # Main database configuration + DatabaseConfig = { + type + | [| 'sqlite, 'postgres, 'mysql, 'surrealdb, 'none |] + | doc "Database type to use", + + sqlite + | SqliteConfig + | doc "SQLite configuration" + | optional, + + postgres + | PostgresConfig + | doc "PostgreSQL configuration" + | optional, + + mysql + | MysqlConfig + | doc "MySQL configuration" + | optional, + + surrealdb + | SurrealdbConfig + | doc "SurrealDB configuration" + | optional, + + migrations_path + | String + | doc "Path to database migrations directory" + | default = "./migrations", + + auto_migrate + | Bool + | doc "Automatically run migrations on startup" + | default = false, + }, +} diff --git a/.typedialog/provisioning/schemas/deployment.ncl b/.typedialog/provisioning/schemas/deployment.ncl new file mode 100644 index 0000000..60dc168 --- /dev/null +++ b/.typedialog/provisioning/schemas/deployment.ncl @@ -0,0 +1,468 @@ +# Deployment Schema - Docker Compose and Kubernetes deployment configurations +# Version: 1.0.0 + +{ + # Docker Compose configuration + DockerComposeConfig = { + enabled + | Bool + | doc "Enable Docker Compose deployment" + | default = true, + + version + | [| 'v3_8, 'v3_9 |] + | doc "Docker Compose file format version (v3_8 = 3.8, v3_9 = 3.9)" + | default = 'v3_8, + + project_name + | String + | doc "Docker Compose project name" + | optional, + + env_file + | String + | doc "Path to environment file" + | default = ".env", + + profiles + | Array String + | doc "Docker Compose profiles to enable" + | default = [], + + extends + | { + file + | String + | doc "Path to base compose file", + + service + | String + | doc "Service to extend", + } + | doc "Extend from another compose file" + | optional, + }, + + # Kubernetes namespace configuration + KubernetesNamespace = { + name + | String + | doc "Namespace name" + | { + label = "valid namespace", + predicate = fun s => + std.string.is_match "^[a-z0-9-]+$" s && + std.string.length s >= 1 && std.string.length s <= 63 + }, + + labels + | {_: String} + | doc "Namespace labels" + | default = {}, + + annotations + | {_: String} + | doc "Namespace annotations" + | default = {}, + }, + + # Kubernetes Ingress configuration + IngressRule = { + host + | String + | doc "Hostname for the rule" + | optional, + + http + | { + paths + | Array { + path + | String + | doc "URL path pattern", + + path_type + | [| 'Prefix, 'Exact, 'ImplementationSpecific |] + | doc "Path matching type" + | default = 'Prefix, + + backend + | { + service + | { + name + | String + | doc "Service name", + + port + | { + number + | Number + | doc "Service port number" + | optional, + + name + | String + | doc "Service port name" + | optional, + } + | doc "Service port", + } + | doc "Service backend", + } + | doc "Backend configuration", + } + | doc "HTTP path rules", + } + | doc "HTTP routing rules", + }, + + IngressConfig = { + enabled + | Bool + | doc "Enable Ingress resource" + | default = false, + + name + | String + | doc "Ingress name" + | { + label = "valid name", + predicate = fun s => + std.string.is_match "^[a-z0-9-]+$" s && + std.string.length s >= 1 && std.string.length s <= 63 + } + | optional, + + class_name + | String + | doc "Ingress class name (e.g., 'nginx', 'traefik')" + | default = "nginx", + + rules + | Array IngressRule + | doc "Ingress routing rules" + | default = [], + + tls + | Array { + hosts + | Array String + | doc "Hosts covered by TLS certificate", + + secret_name + | String + | doc "Name of secret containing TLS cert/key" + | optional, + } + | doc "TLS configuration" + | default = [], + + annotations + | {_: String} + | doc "Ingress annotations" + | default = {}, + }, + + # Kubernetes Service configuration + KubernetesServiceConfig = { + type + | [| 'ClusterIP, 'NodePort, 'LoadBalancer, 'ExternalName |] + | doc "Kubernetes Service type" + | default = 'ClusterIP, + + cluster_ip + | String + | doc "Cluster IP address (for ClusterIP type)" + | optional, + + external_ips + | Array String + | doc "External IP addresses" + | default = [], + + load_balancer_ip + | String + | doc "LoadBalancer IP address" + | optional, + + load_balancer_source_ranges + | Array String + | doc "Allowed source IP ranges for LoadBalancer" + | default = [], + + external_traffic_policy + | [| 'Cluster, 'Local |] + | doc "External traffic policy" + | optional, + + session_affinity + | [| 'None, 'ClientIP |] + | doc "Session affinity" + | default = 'None, + + annotations + | {_: String} + | doc "Service annotations" + | default = {}, + }, + + # Kubernetes Deployment strategy + DeploymentStrategy = { + type + | [| 'RollingUpdate, 'Recreate |] + | doc "Deployment strategy type" + | default = 'RollingUpdate, + + rolling_update + | { + max_surge + | String + | doc "Max additional pods during update (number or percentage)" + | default = "25%", + + max_unavailable + | String + | doc "Max unavailable pods during update (number or percentage)" + | default = "25%", + } + | doc "Rolling update strategy parameters" + | optional, + }, + + # Kubernetes HorizontalPodAutoscaler + HpaConfig = { + enabled + | Bool + | doc "Enable Horizontal Pod Autoscaler" + | default = false, + + min_replicas + | Number + | doc "Minimum number of replicas" + | { + label = "valid min replicas", + predicate = fun n => n >= 1 && n <= 100 + } + | default = 1, + + max_replicas + | Number + | doc "Maximum number of replicas" + | { + label = "valid max replicas", + predicate = fun n => n >= 1 && n <= 100 + } + | default = 10, + + target_cpu_utilization + | Number + | doc "Target CPU utilization percentage (0-100)" + | { + label = "valid CPU utilization", + predicate = fun n => n > 0 && n <= 100 + } + | default = 80, + + target_memory_utilization + | Number + | doc "Target memory utilization percentage (0-100)" + | { + label = "valid memory utilization", + predicate = fun n => n > 0 && n <= 100 + } + | optional, + + custom_metrics + | Array { + type + | [| 'Pods, 'Object, 'External |] + | doc "Metric type", + + metric_name + | String + | doc "Metric name", + + target_value + | String + | doc "Target value for the metric", + } + | doc "Custom metrics for autoscaling" + | default = [], + }, + + # Kubernetes ConfigMap + ConfigMapConfig = { + name + | String + | doc "ConfigMap name" + | { + label = "valid name", + predicate = fun s => + std.string.is_match "^[a-z0-9-]+$" s && + std.string.length s >= 1 && std.string.length s <= 63 + }, + + data + | {_: String} + | doc "Configuration data as key-value pairs" + | default = {}, + + binary_data + | {_: String} + | doc "Binary data (base64 encoded)" + | default = {}, + + from_files + | Array String + | doc "Paths to files to include in ConfigMap" + | default = [], + }, + + # Main Kubernetes configuration + KubernetesConfig = { + enabled + | Bool + | doc "Enable Kubernetes deployment" + | default = false, + + namespace + | String + | doc "Target namespace for deployments" + | { + label = "valid namespace", + predicate = fun s => + std.string.is_match "^[a-z0-9-]+$" s && + std.string.length s >= 1 && std.string.length s <= 63 + } + | default = "default", + + create_namespace + | Bool + | doc "Create namespace if it doesn't exist" + | default = false, + + namespace_config + | KubernetesNamespace + | doc "Namespace configuration" + | optional, + + service + | KubernetesServiceConfig + | doc "Kubernetes Service configuration" + | default = {type = 'ClusterIP}, + + ingress + | IngressConfig + | doc "Ingress configuration" + | default = {enabled = false}, + + deployment_strategy + | DeploymentStrategy + | doc "Deployment strategy" + | default = {type = 'RollingUpdate}, + + hpa + | HpaConfig + | doc "Horizontal Pod Autoscaler configuration" + | default = {enabled = false}, + + configmaps + | Array ConfigMapConfig + | doc "ConfigMaps to create" + | default = [], + + pod_annotations + | {_: String} + | doc "Annotations for pod template" + | default = {}, + + pod_labels + | {_: String} + | doc "Labels for pod template" + | default = {}, + + service_account + | String + | doc "Service account name for pods" + | optional, + + image_pull_secrets + | Array String + | doc "Names of secrets for pulling images" + | default = [], + + node_selector + | {_: String} + | doc "Node selector for pod scheduling" + | default = {}, + + tolerations + | Array { + key + | String + | doc "Toleration key" + | optional, + + operator + | [| 'Exists, 'Equal |] + | doc "Toleration operator" + | default = 'Equal, + + value + | String + | doc "Toleration value" + | optional, + + effect + | [| 'NoSchedule, 'PreferNoSchedule, 'NoExecute |] + | doc "Toleration effect" + | optional, + + toleration_seconds + | Number + | doc "Seconds before eviction (for NoExecute)" + | optional, + } + | doc "Pod tolerations" + | default = [], + + affinity + | { + node_affinity + | {_: _} + | doc "Node affinity rules" + | optional, + + pod_affinity + | {_: _} + | doc "Pod affinity rules" + | optional, + + pod_anti_affinity + | {_: _} + | doc "Pod anti-affinity rules" + | optional, + } + | doc "Pod affinity/anti-affinity" + | optional, + }, + + # Main deployment configuration + DeploymentConfig = { + docker_compose + | DockerComposeConfig + | doc "Docker Compose deployment configuration" + | optional, + + kubernetes + | KubernetesConfig + | doc "Kubernetes deployment configuration" + | optional, + + target + | [| 'docker, 'kubernetes, 'both |] + | doc "Deployment target platform" + | default = 'docker, + }, +} diff --git a/.typedialog/provisioning/schemas/monitoring.ncl b/.typedialog/provisioning/schemas/monitoring.ncl new file mode 100644 index 0000000..608819c --- /dev/null +++ b/.typedialog/provisioning/schemas/monitoring.ncl @@ -0,0 +1,371 @@ +# Monitoring Schema - Monitoring configurations (Prometheus, Grafana, etc.) +# Version: 1.0.0 + +{ + # Prometheus scrape configuration + PrometheusScrapeConfig = { + job_name + | String + | doc "Job name for the scrape target", + + scrape_interval + | String + | doc "Scrape interval (e.g., '30s', '1m')" + | default = "30s", + + scrape_timeout + | String + | doc "Scrape timeout (e.g., '10s')" + | default = "10s", + + metrics_path + | String + | doc "HTTP path to scrape metrics from" + | default = "/metrics", + + scheme + | [| 'http, 'https |] + | doc "HTTP scheme" + | default = 'http, + + static_configs + | Array { + targets + | Array String + | doc "List of targets (e.g., ['localhost:9090'])", + + labels + | {_: String} + | doc "Labels to attach to scraped metrics" + | default = {}, + } + | doc "Static target configurations" + | default = [], + + relabel_configs + | Array { + source_labels + | Array String + | doc "Source labels" + | optional, + + target_label + | String + | doc "Target label" + | optional, + + regex + | String + | doc "Regex pattern" + | optional, + + replacement + | String + | doc "Replacement value" + | optional, + + action + | [| 'replace, 'keep, 'drop, 'hashmod, 'labelmap, 'labeldrop, 'labelkeep |] + | doc "Relabeling action" + | default = 'replace, + } + | doc "Relabeling configurations" + | default = [], + }, + + # Prometheus configuration + PrometheusConfig = { + enabled + | Bool + | doc "Enable Prometheus monitoring" + | default = true, + + port + | Number + | doc "Prometheus server port (1024-65535)" + | { + label = "valid port", + predicate = fun p => p >= 1024 && p <= 65535 + } + | default = 9090, + + image + | String + | doc "Prometheus Docker image" + | default = "prom/prometheus:latest", + + scrape_interval + | String + | doc "Global scrape interval (e.g., '15s', '1m')" + | default = "15s", + + evaluation_interval + | String + | doc "Rule evaluation interval (e.g., '15s')" + | default = "15s", + + retention + | String + | doc "Data retention period (e.g., '15d', '30d')" + | default = "15d", + + scrape_configs + | Array PrometheusScrapeConfig + | doc "Scrape configurations for targets" + | default = [], + + alerting + | { + alertmanagers + | Array { + static_configs + | Array { + targets + | Array String + | doc "Alertmanager targets", + } + | doc "Static alertmanager configs", + } + | doc "Alertmanager configurations" + | default = [], + } + | doc "Alerting configuration" + | optional, + + rule_files + | Array String + | doc "Paths to alert/recording rule files" + | default = [], + + storage_path + | String + | doc "Path to store Prometheus data" + | default = "/prometheus", + + external_labels + | {_: String} + | doc "External labels to attach to all metrics" + | default = {}, + }, + + # Grafana datasource configuration + GrafanaDatasource = { + name + | String + | doc "Datasource name", + + type + | [| 'prometheus, 'loki, 'jaeger, 'tempo, 'influxdb, 'elasticsearch |] + | doc "Datasource type", + + access + | [| 'proxy, 'direct |] + | doc "Access mode" + | default = 'proxy, + + url + | String + | doc "Datasource URL", + + is_default + | Bool + | doc "Set as default datasource" + | default = false, + + basic_auth + | Bool + | doc "Enable basic authentication" + | default = false, + + basic_auth_user + | String + | doc "Basic auth username" + | optional, + + basic_auth_password + | String + | doc "Basic auth password" + | optional, + + json_data + | {_: _} + | doc "Additional JSON configuration" + | default = {}, + }, + + # Grafana configuration + GrafanaConfig = { + enabled + | Bool + | doc "Enable Grafana dashboards" + | default = true, + + port + | Number + | doc "Grafana server port (1024-65535)" + | { + label = "valid port", + predicate = fun p => p >= 1024 && p <= 65535 + } + | default = 3000, + + image + | String + | doc "Grafana Docker image" + | default = "grafana/grafana:latest", + + admin_user + | String + | doc "Admin username" + | default = "admin", + + admin_password + | String + | doc "Admin password (8-128 characters)" + | { + label = "valid password", + predicate = fun s => std.string.length s >= 8 && std.string.length s <= 128 + }, + + datasources + | Array GrafanaDatasource + | doc "Datasource configurations" + | default = [], + + dashboards_path + | String + | doc "Path to dashboard JSON files" + | default = "/etc/grafana/dashboards", + + plugins + | Array String + | doc "Grafana plugins to install" + | default = [], + + environment + | {_: String} + | doc "Additional environment variables" + | default = {}, + + anonymous_access + | Bool + | doc "Enable anonymous access" + | default = false, + + serve_from_sub_path + | Bool + | doc "Serve Grafana from a sub-path" + | default = false, + + root_url + | String + | doc "Full public-facing URL" + | optional, + }, + + # Loki configuration + LokiConfig = { + enabled + | Bool + | doc "Enable Loki log aggregation" + | default = false, + + port + | Number + | doc "Loki server port (1024-65535)" + | { + label = "valid port", + predicate = fun p => p >= 1024 && p <= 65535 + } + | default = 3100, + + image + | String + | doc "Loki Docker image" + | default = "grafana/loki:latest", + + storage_path + | String + | doc "Path to store Loki data" + | default = "/loki", + + retention_period + | String + | doc "Log retention period (e.g., '7d', '30d')" + | default = "7d", + }, + + # Jaeger tracing configuration + JaegerConfig = { + enabled + | Bool + | doc "Enable Jaeger distributed tracing" + | default = false, + + collector_port + | Number + | doc "Jaeger collector port (1024-65535)" + | { + label = "valid port", + predicate = fun p => p >= 1024 && p <= 65535 + } + | default = 14268, + + query_port + | Number + | doc "Jaeger query UI port (1024-65535)" + | { + label = "valid port", + predicate = fun p => p >= 1024 && p <= 65535 + } + | default = 16686, + + image + | String + | doc "Jaeger all-in-one Docker image" + | default = "jaegertracing/all-in-one:latest", + + sampling_strategy + | [| 'const, 'probabilistic, 'ratelimiting, 'remote |] + | doc "Sampling strategy" + | default = 'const, + + sampling_param + | Number + | doc "Sampling parameter (0.0-1.0 for probabilistic)" + | default = 1.0, + }, + + # Main monitoring configuration + MonitoringConfig = { + prometheus + | PrometheusConfig + | doc "Prometheus configuration" + | optional, + + grafana + | GrafanaConfig + | doc "Grafana configuration" + | optional, + + loki + | LokiConfig + | doc "Loki configuration" + | optional, + + jaeger + | JaegerConfig + | doc "Jaeger configuration" + | optional, + + alerts_path + | String + | doc "Path to alert rule files" + | default = "./alerts", + + dashboard_refresh_interval + | String + | doc "Default dashboard refresh interval (e.g., '5s', '30s')" + | default = "30s", + }, +} diff --git a/.typedialog/provisioning/schemas/network.ncl b/.typedialog/provisioning/schemas/network.ncl new file mode 100644 index 0000000..2003f08 --- /dev/null +++ b/.typedialog/provisioning/schemas/network.ncl @@ -0,0 +1,242 @@ +# Network Schema - Network configurations for provisioning +# Version: 1.0.0 + +{ + # IPAM (IP Address Management) configuration + IpamConfig = { + subnet + | String + | doc "Subnet in CIDR notation (e.g., '172.28.0.0/16')" + | { + label = "valid subnet", + predicate = fun s => + std.string.is_match "^([0-9]{1,3}\\.){3}[0-9]{1,3}/[0-9]{1,2}$" s + }, + + gateway + | String + | doc "Gateway IP address (e.g., '172.28.0.1')" + | { + label = "valid IP", + predicate = fun s => + std.string.is_match "^([0-9]{1,3}\\.){3}[0-9]{1,3}$" s + } + | optional, + + ip_range + | String + | doc "IP range in CIDR notation" + | { + label = "valid IP range", + predicate = fun s => + std.string.is_match "^([0-9]{1,3}\\.){3}[0-9]{1,3}/[0-9]{1,2}$" s + } + | optional, + + aux_addresses + | {_: String} + | doc "Auxiliary IPv4 or IPv6 addresses" + | default = {}, + }, + + # Docker network configuration + DockerNetwork = { + name + | String + | doc "Network name" + | { + label = "valid network name", + predicate = fun s => + std.string.is_match "^[a-z0-9-]+$" s && + std.string.length s >= 1 && std.string.length s <= 64 + }, + + driver + | [| 'bridge, 'host, 'overlay, 'macvlan, 'none |] + | doc "Network driver type" + | default = 'bridge, + + driver_opts + | {_: String} + | doc "Driver-specific options" + | default = {}, + + ipam + | { + driver + | String + | doc "IPAM driver name" + | default = "default", + + config + | Array IpamConfig + | doc "IPAM configuration" + | default = [], + } + | doc "IP Address Management configuration" + | optional, + + internal + | Bool + | doc "Restrict external access to network" + | default = false, + + attachable + | Bool + | doc "Enable manual container attachment" + | default = false, + + enable_ipv6 + | Bool + | doc "Enable IPv6 networking" + | default = false, + + labels + | {_: String} + | doc "Network labels for metadata" + | default = {}, + }, + + # Kubernetes network policy + NetworkPolicyPort = { + port + | Number + | doc "Port number" + | { + label = "valid port", + predicate = fun p => p >= 1 && p <= 65535 + }, + + protocol + | [| 'TCP, 'UDP, 'SCTP |] + | doc "Protocol" + | default = 'TCP, + }, + + NetworkPolicyPeer = { + pod_selector + | { + matchLabels + | {_: String} + | doc "Label selector for pods" + | optional, + + matchExpressions + | Array { + key | String, + operator | [| 'In, 'NotIn, 'Exists, 'DoesNotExist |], + values | Array String | optional, + } + | doc "Label selector expressions" + | optional, + } + | doc "Pod selector" + | optional, + + namespace_selector + | { + matchLabels + | {_: String} + | doc "Label selector for namespaces" + | optional, + } + | doc "Namespace selector" + | optional, + + ip_block + | { + cidr + | String + | doc "CIDR block (e.g., '172.17.0.0/16')", + + except + | Array String + | doc "Exceptions to the CIDR block" + | default = [], + } + | doc "IP block selector" + | optional, + }, + + NetworkPolicyIngressRule = { + from + | Array NetworkPolicyPeer + | doc "Sources from which traffic is allowed" + | default = [], + + ports + | Array NetworkPolicyPort + | doc "Ports on which traffic is allowed" + | default = [], + }, + + NetworkPolicyEgressRule = { + to + | Array NetworkPolicyPeer + | doc "Destinations to which traffic is allowed" + | default = [], + + ports + | Array NetworkPolicyPort + | doc "Ports on which traffic is allowed" + | default = [], + }, + + KubernetesNetworkPolicy = { + name + | String + | doc "Network policy name" + | { + label = "valid name", + predicate = fun s => + std.string.is_match "^[a-z0-9-]+$" s && + std.string.length s >= 1 && std.string.length s <= 64 + }, + + pod_selector + | { + matchLabels + | {_: String} + | doc "Label selector for pods" + } + | doc "Selector for pods to which this policy applies", + + policy_types + | Array ([| 'Ingress, 'Egress |]) + | doc "Types of traffic this policy affects" + | default = ['Ingress], + + ingress + | Array NetworkPolicyIngressRule + | doc "Ingress rules" + | default = [], + + egress + | Array NetworkPolicyEgressRule + | doc "Egress rules" + | default = [], + }, + + # Main network configuration + NetworkConfig = { + docker_networks + | {_: DockerNetwork} + | doc "Docker networks definition" + | default = {}, + + kubernetes_policies + | Array KubernetesNetworkPolicy + | doc "Kubernetes network policies" + | default = [], + + dns_servers + | Array String + | doc "Custom DNS servers" + | default = [], + + dns_search + | Array String + | doc "DNS search domains" + | default = [], + }, +} diff --git a/.typedialog/provisioning/schemas/provisioning-config.ncl b/.typedialog/provisioning/schemas/provisioning-config.ncl new file mode 100644 index 0000000..cb964b3 --- /dev/null +++ b/.typedialog/provisioning/schemas/provisioning-config.ncl @@ -0,0 +1,146 @@ +# Provisioning Config Schema - Main configuration schema +# Version: 1.0.0 +# +# This is the top-level schema that defines the complete provisioning configuration +# structure. It imports all other schemas and combines them into a unified config. + +let Service = import "service.ncl" in +let Database = import "database.ncl" in +let Network = import "network.ncl" in +let Storage = import "storage.ncl" in +let Monitoring = import "monitoring.ncl" in +let Security = import "security.ncl" in +let Deployment = import "deployment.ncl" in + +{ + # Project metadata + Project = { + name + | String + | doc "Project name (lowercase alphanumeric with hyphens)" + | { + label = "valid project name", + predicate = fun s => + std.string.is_match "^[a-z0-9-]+$" s && + std.string.length s >= 1 && std.string.length s <= 64 + }, + + version + | String + | doc "Project version (semantic versioning: X.Y.Z)" + | { + label = "valid version", + predicate = fun s => + std.string.is_match "^[0-9]+\\.[0-9]+\\.[0-9]+$" s + } + | default = "0.1.0", + + description + | String + | doc "Project description" + | { + label = "valid description", + predicate = fun s => std.string.length s <= 500 + } + | optional, + + author + | String + | doc "Project author" + | optional, + + license + | String + | doc "Project license (e.g., 'MIT', 'Apache-2.0')" + | optional, + + repository + | String + | doc "Repository URL" + | optional, + + tags + | Array String + | doc "Project tags for categorization" + | default = [], + }, + + # Main provisioning configuration + ProvisioningConfig = { + project + | Project + | doc "Project metadata and information", + + services + | {_: Service.Service} + | doc "Service definitions (key: service name, value: service config)" + | { + label = "valid services", + predicate = fun services => + std.record.length services > 0 + }, + + database + | Database.DatabaseConfig + | doc "Database configuration" + | default = {type = 'none}, + + network + | Network.NetworkConfig + | doc "Network configuration" + | default = {}, + + storage + | Storage.StorageConfig + | doc "Storage and volume configuration" + | default = {}, + + deployment + | Deployment.DeploymentConfig + | doc "Deployment configuration (Docker Compose, Kubernetes)" + | default = {target = 'docker}, + + monitoring + | Monitoring.MonitoringConfig + | doc "Monitoring configuration (Prometheus, Grafana, etc.)" + | default = {}, + + security + | Security.SecurityConfig + | doc "Security configuration (TLS, secrets, auth)" + | default = {}, + + environment + | {_: String} + | doc "Global environment variables for all services" + | default = {}, + + metadata + | { + generated_at + | String + | doc "Timestamp when config was generated" + | optional, + + generated_by + | String + | doc "Tool/user that generated the config" + | optional, + + schema_version + | String + | doc "Schema version used" + | default = "1.0.0", + + custom + | {_: _} + | doc "Custom metadata fields" + | default = {}, + } + | doc "Configuration metadata" + | default = {}, + }, + + # Export the main schema + export = ProvisioningConfig, +} diff --git a/.typedialog/provisioning/schemas/security.ncl b/.typedialog/provisioning/schemas/security.ncl new file mode 100644 index 0000000..fd49293 --- /dev/null +++ b/.typedialog/provisioning/schemas/security.ncl @@ -0,0 +1,487 @@ +# Security Schema - Security configurations (TLS, secrets, auth) +# Version: 1.0.0 + +{ + # TLS/SSL configuration + TlsConfig = { + enabled + | Bool + | doc "Enable TLS/SSL" + | default = false, + + cert_path + | String + | doc "Path to TLS certificate file" + | { + label = "valid path", + predicate = fun s => std.string.length s >= 1 && std.string.length s <= 256 + } + | optional, + + key_path + | String + | doc "Path to TLS private key file" + | { + label = "valid path", + predicate = fun s => std.string.length s >= 1 && std.string.length s <= 256 + } + | optional, + + ca_path + | String + | doc "Path to CA certificate file" + | { + label = "valid path", + predicate = fun s => std.string.length s >= 1 && std.string.length s <= 256 + } + | optional, + + min_version + | [| 'TLSv1.0, 'TLSv1.1, 'TLSv1.2, 'TLSv1.3 |] + | doc "Minimum TLS version" + | default = 'TLSv1.2, + + max_version + | [| 'TLSv1.2, 'TLSv1.3 |] + | doc "Maximum TLS version" + | default = 'TLSv1.3, + + cipher_suites + | Array String + | doc "Allowed cipher suites" + | default = [], + + verify_client + | Bool + | doc "Require client certificate verification" + | default = false, + + auto_generate + | Bool + | doc "Auto-generate self-signed certificates for development" + | default = false, + }, + + # Secret definition + SecretDefinition = { + name + | String + | doc "Secret name" + | { + label = "valid secret name", + predicate = fun s => + std.string.is_match "^[a-z0-9-]+$" s && + std.string.length s >= 1 && std.string.length s <= 64 + }, + + type + | [| 'Opaque, 'kubernetes.io/tls, 'kubernetes.io/dockerconfigjson, 'kubernetes.io/basic-auth, 'kubernetes.io/ssh-auth |] + | doc "Secret type" + | default = 'Opaque, + + data + | {_: String} + | doc "Secret data (key-value pairs, values will be base64 encoded)" + | default = {}, + + string_data + | {_: String} + | doc "Secret data as plain strings (will be auto-encoded)" + | default = {}, + + external + | Bool + | doc "Reference to external secret (managed outside provisioning)" + | default = false, + + labels + | {_: String} + | doc "Secret labels" + | default = {}, + }, + + # Docker secret configuration + DockerSecret = { + name + | String + | doc "Secret name" + | { + label = "valid secret name", + predicate = fun s => + std.string.is_match "^[a-z0-9-]+$" s && + std.string.length s >= 1 && std.string.length s <= 64 + }, + + file + | String + | doc "Path to secret file" + | optional, + + external + | Bool + | doc "Reference to external secret" + | default = false, + + labels + | {_: String} + | doc "Secret labels" + | default = {}, + }, + + # Authentication configuration + AuthConfig = { + method + | [| 'none, 'basic, 'bearer, 'oauth2, 'jwt, 'api_key |] + | doc "Authentication method" + | default = 'none, + + basic + | { + username + | String + | doc "Basic auth username", + + password + | String + | doc "Basic auth password" + | { + label = "valid password", + predicate = fun s => std.string.length s >= 8 && std.string.length s <= 128 + }, + + realm + | String + | doc "Authentication realm" + | default = "Restricted", + } + | doc "Basic authentication configuration" + | optional, + + bearer + | { + token + | String + | doc "Bearer token", + + token_type + | String + | doc "Token type (e.g., 'Bearer')" + | default = "Bearer", + } + | doc "Bearer token authentication configuration" + | optional, + + oauth2 + | { + provider + | [| 'google, 'github, 'gitlab, 'azure, 'okta, 'custom |] + | doc "OAuth2 provider", + + client_id + | String + | doc "OAuth2 client ID", + + client_secret + | String + | doc "OAuth2 client secret", + + auth_url + | String + | doc "Authorization URL" + | optional, + + token_url + | String + | doc "Token URL" + | optional, + + redirect_uri + | String + | doc "Redirect URI after authentication", + + scopes + | Array String + | doc "OAuth2 scopes to request" + | default = [], + } + | doc "OAuth2 authentication configuration" + | optional, + + jwt + | { + secret + | String + | doc "JWT signing secret", + + algorithm + | [| 'HS256, 'HS384, 'HS512, 'RS256, 'RS384, 'RS512, 'ES256, 'ES384, 'ES512 |] + | doc "JWT signing algorithm" + | default = 'HS256, + + issuer + | String + | doc "JWT issuer" + | optional, + + audience + | Array String + | doc "JWT audience" + | default = [], + + expiry_seconds + | Number + | doc "Token expiry in seconds (300-86400)" + | { + label = "valid expiry", + predicate = fun n => n >= 300 && n <= 86400 + } + | default = 3600, + + public_key_path + | String + | doc "Path to public key for RS/ES algorithms" + | optional, + + private_key_path + | String + | doc "Path to private key for RS/ES algorithms" + | optional, + } + | doc "JWT authentication configuration" + | optional, + + api_key + | { + header_name + | String + | doc "HTTP header name for API key" + | default = "X-API-Key", + + query_param + | String + | doc "Query parameter name for API key" + | optional, + + keys + | Array { + key + | String + | doc "API key value", + + name + | String + | doc "Key name/identifier" + | optional, + + permissions + | Array String + | doc "Permissions granted to this key" + | default = [], + } + | doc "List of valid API keys" + | default = [], + } + | doc "API key authentication configuration" + | optional, + }, + + # RBAC (Role-Based Access Control) configuration + RbacRole = { + name + | String + | doc "Role name", + + permissions + | Array String + | doc "List of permissions (e.g., ['read:users', 'write:posts'])" + | default = [], + + resources + | Array String + | doc "Resources this role can access" + | default = [], + + actions + | Array ([| 'create, 'read, 'update, 'delete, 'list |]) + | doc "Allowed actions" + | default = [], + }, + + RbacPolicy = { + roles + | Array RbacRole + | doc "Role definitions" + | default = [], + + default_role + | String + | doc "Default role for authenticated users" + | default = "user", + + admin_role + | String + | doc "Administrator role name" + | default = "admin", + }, + + # Security headers configuration + SecurityHeaders = { + enable_hsts + | Bool + | doc "Enable HTTP Strict Transport Security" + | default = true, + + hsts_max_age + | Number + | doc "HSTS max age in seconds" + | default = 31536000, + + hsts_include_subdomains + | Bool + | doc "Include subdomains in HSTS" + | default = true, + + enable_csp + | Bool + | doc "Enable Content Security Policy" + | default = true, + + csp_policy + | String + | doc "Content Security Policy directives" + | default = "default-src 'self'", + + enable_xss_protection + | Bool + | doc "Enable X-XSS-Protection header" + | default = true, + + enable_frame_options + | Bool + | doc "Enable X-Frame-Options header" + | default = true, + + frame_options_value + | [| 'DENY, 'SAMEORIGIN |] + | doc "X-Frame-Options value" + | default = 'DENY, + + enable_content_type_nosniff + | Bool + | doc "Enable X-Content-Type-Options: nosniff" + | default = true, + + enable_referrer_policy + | Bool + | doc "Enable Referrer-Policy header" + | default = true, + + referrer_policy_value + | [| 'no-referrer, 'no-referrer-when-downgrade, 'same-origin, 'origin, 'strict-origin, 'origin-when-cross-origin, 'strict-origin-when-cross-origin, 'unsafe-url |] + | doc "Referrer-Policy value" + | default = 'strict-origin-when-cross-origin, + + custom_headers + | {_: String} + | doc "Additional custom security headers" + | default = {}, + }, + + # Main security configuration + SecurityConfig = { + tls + | TlsConfig + | doc "TLS/SSL configuration" + | default = {enabled = false}, + + docker_secrets + | Array DockerSecret + | doc "Docker secrets" + | default = [], + + kubernetes_secrets + | Array SecretDefinition + | doc "Kubernetes secrets" + | default = [], + + auth + | AuthConfig + | doc "Authentication configuration" + | default = {method = 'none}, + + rbac + | RbacPolicy + | doc "Role-Based Access Control configuration" + | optional, + + security_headers + | SecurityHeaders + | doc "Security headers configuration" + | default = {}, + + cors + | { + enabled + | Bool + | doc "Enable CORS" + | default = false, + + allowed_origins + | Array String + | doc "Allowed origins for CORS" + | default = ["*"], + + allowed_methods + | Array String + | doc "Allowed HTTP methods" + | default = ["GET", "POST", "PUT", "DELETE", "OPTIONS"], + + allowed_headers + | Array String + | doc "Allowed headers" + | default = ["*"], + + expose_headers + | Array String + | doc "Headers to expose to the client" + | default = [], + + allow_credentials + | Bool + | doc "Allow credentials in CORS requests" + | default = false, + + max_age + | Number + | doc "Preflight cache duration in seconds" + | default = 86400, + } + | doc "CORS configuration" + | optional, + + rate_limiting + | { + enabled + | Bool + | doc "Enable rate limiting" + | default = false, + + requests_per_second + | Number + | doc "Maximum requests per second" + | default = 100, + + burst_size + | Number + | doc "Burst size for rate limiter" + | default = 200, + + strategy + | [| 'ip, 'user, 'api_key |] + | doc "Rate limiting strategy" + | default = 'ip, + } + | doc "Rate limiting configuration" + | optional, + }, +} diff --git a/.typedialog/provisioning/schemas/service.ncl b/.typedialog/provisioning/schemas/service.ncl new file mode 100644 index 0000000..e1241d3 --- /dev/null +++ b/.typedialog/provisioning/schemas/service.ncl @@ -0,0 +1,249 @@ +# Service Schema - Service definitions for provisioning +# Version: 1.0.0 + +{ + # Port configuration for service containers + Port = { + container_port + | Number + | doc "Port number inside the container" + | { + label = "valid port", + predicate = fun p => p >= 1 && p <= 65535 + }, + + host_port + | Number + | doc "Port number on the host machine (1024-65535 for non-root)" + | { + label = "valid host port", + predicate = fun p => p >= 1024 && p <= 65535 + }, + + protocol + | [| 'tcp, 'udp, 'sctp |] + | doc "Network protocol" + | default = 'tcp, + }, + + # Resource limits and requests + Resources = { + cpu_limit + | String + | doc "CPU limit (e.g., '1000m' for 1 core, '500m' for 0.5 cores)" + | { + label = "valid CPU limit", + predicate = fun s => + std.string.is_match "^[0-9]+(\\.[0-9]+)?m?$" s + } + | optional, + + cpu_request + | String + | doc "CPU request (guaranteed CPU allocation)" + | { + label = "valid CPU request", + predicate = fun s => + std.string.is_match "^[0-9]+(\\.[0-9]+)?m?$" s + } + | optional, + + memory_limit + | String + | doc "Memory limit (e.g., '512Mi', '1Gi')" + | { + label = "valid memory limit", + predicate = fun s => + std.string.is_match "^[0-9]+(Mi|Gi|M|G|Ki|K)$" s + } + | optional, + + memory_request + | String + | doc "Memory request (guaranteed memory allocation)" + | { + label = "valid memory request", + predicate = fun s => + std.string.is_match "^[0-9]+(Mi|Gi|M|G|Ki|K)$" s + } + | optional, + }, + + # Container image configuration + Image = { + name + | String + | doc "Image name (e.g., 'nginx', 'my-app')" + | { + label = "valid image name", + predicate = fun s => + std.string.length s >= 1 && std.string.length s <= 256 + }, + + tag + | String + | doc "Image tag (e.g., 'latest', '1.0.0', 'v2.3-alpine')" + | { + label = "valid image tag", + predicate = fun s => + std.string.is_match "^[a-zA-Z0-9._-]+$" s + } + | default = "latest", + + build_context + | String + | doc "Build context path for building from Dockerfile" + | optional, + + dockerfile + | String + | doc "Path to Dockerfile (relative to build_context)" + | default = "Dockerfile", + }, + + # Health check configuration + Healthcheck = { + enabled + | Bool + | doc "Enable health check monitoring" + | default = true, + + endpoint + | String + | doc "HTTP endpoint for health checks (e.g., '/health', '/api/v1/health')" + | default = "/health", + + interval + | Number + | doc "Interval between health checks in seconds (5-300)" + | { + label = "valid interval", + predicate = fun n => n >= 5 && n <= 300 + } + | default = 30, + + timeout + | Number + | doc "Health check timeout in seconds (1-60)" + | { + label = "valid timeout", + predicate = fun n => n >= 1 && n <= 60 + } + | default = 10, + + retries + | Number + | doc "Number of consecutive failures before marking unhealthy (1-10)" + | { + label = "valid retries", + predicate = fun n => n >= 1 && n <= 10 + } + | default = 3, + + start_period + | Number + | doc "Grace period in seconds before health checks start (0-300)" + | { + label = "valid start period", + predicate = fun n => n >= 0 && n <= 300 + } + | default = 0, + }, + + # Main service definition + Service = { + type + | [| 'api, 'worker, 'scheduler, 'frontend, 'backend, 'database, 'cache, 'queue |] + | doc "Service type determining deployment characteristics", + + image + | Image + | doc "Container image configuration", + + ports + | Array Port + | doc "Port mappings for the service" + | default = [], + + environment + | {_: String} + | doc "Environment variables as key-value pairs" + | default = {}, + + env_file + | Array String + | doc "Paths to environment files" + | default = [], + + healthcheck + | Healthcheck + | doc "Health check configuration" + | default = {enabled = true, endpoint = "/health"}, + + resources + | Resources + | doc "Resource limits and requests" + | optional, + + depends_on + | Array String + | doc "Service dependencies (names of other services)" + | { + label = "valid dependencies", + predicate = fun deps => + std.array.all (fun s => + std.string.is_match "^[a-z0-9-]+$" s + ) deps + } + | default = [], + + replicas + | Number + | doc "Number of service replicas to run (1-100)" + | { + label = "valid replica count", + predicate = fun n => n >= 1 && n <= 100 + } + | default = 1, + + restart_policy + | [| 'no, 'always, 'on-failure, 'unless-stopped |] + | doc "Container restart policy" + | default = 'unless-stopped, + + command + | Array String + | doc "Override container command" + | optional, + + entrypoint + | Array String + | doc "Override container entrypoint" + | optional, + + working_dir + | String + | doc "Working directory inside container" + | optional, + + user + | String + | doc "User to run container as (UID:GID or username)" + | optional, + + volumes + | Array String + | doc "Volume mounts (format: 'host_path:container_path[:options]')" + | default = [], + + networks + | Array String + | doc "Networks to attach the service to" + | default = [], + + labels + | {_: String} + | doc "Container labels for metadata" + | default = {}, + }, +} diff --git a/.typedialog/provisioning/schemas/storage.ncl b/.typedialog/provisioning/schemas/storage.ncl new file mode 100644 index 0000000..a5515e6 --- /dev/null +++ b/.typedialog/provisioning/schemas/storage.ncl @@ -0,0 +1,321 @@ +# Storage Schema - Volume and storage configurations for provisioning +# Version: 1.0.0 + +{ + # Docker volume configuration + DockerVolume = { + name + | String + | doc "Volume name" + | { + label = "valid volume name", + predicate = fun s => + std.string.is_match "^[a-z0-9-]+$" s && + std.string.length s >= 1 && std.string.length s <= 64 + }, + + driver + | [| 'local, 'nfs, 'cifs |] + | doc "Volume driver" + | default = 'local, + + driver_opts + | {_: String} + | doc "Driver-specific options" + | default = {}, + + external + | Bool + | doc "Use existing external volume" + | default = false, + + labels + | {_: String} + | doc "Volume labels for metadata" + | default = {}, + }, + + # Volume mount configuration + VolumeMount = { + source + | String + | doc "Source volume or host path", + + target + | String + | doc "Target path in container" + | { + label = "valid path", + predicate = fun s => std.string.length s >= 1 && std.string.length s <= 256 + }, + + type + | [| 'volume, 'bind, 'tmpfs |] + | doc "Mount type" + | default = 'volume, + + read_only + | Bool + | doc "Mount as read-only" + | default = false, + + volume_options + | { + nocopy + | Bool + | doc "Disable copying data from container to volume" + | default = false, + + labels + | {_: String} + | doc "Labels for the volume" + | default = {}, + } + | doc "Volume-specific options" + | optional, + + bind_options + | { + propagation + | [| 'private, 'rprivate, 'shared, 'rshared, 'slave, 'rslave |] + | doc "Bind propagation mode" + | default = 'rprivate, + + create_host_path + | Bool + | doc "Create host path if it doesn't exist" + | default = false, + } + | doc "Bind mount-specific options" + | optional, + + tmpfs_options + | { + size + | String + | doc "Size of tmpfs mount (e.g., '100Mi')" + | { + label = "valid size", + predicate = fun s => + std.string.is_match "^[0-9]+(Mi|Gi|M|G|Ki|K)$" s + } + | optional, + + mode + | Number + | doc "File mode in octal (e.g., 1777)" + | optional, + } + | doc "Tmpfs mount-specific options" + | optional, + }, + + # Kubernetes PersistentVolume configuration + KubernetesPersistentVolume = { + name + | String + | doc "PersistentVolume name" + | { + label = "valid name", + predicate = fun s => + std.string.is_match "^[a-z0-9-]+$" s && + std.string.length s >= 1 && std.string.length s <= 64 + }, + + capacity + | String + | doc "Storage capacity (e.g., '10Gi')" + | { + label = "valid capacity", + predicate = fun s => + std.string.is_match "^[0-9]+(Mi|Gi|Ti|M|G|T)$" s + }, + + access_modes + | Array ([| 'ReadWriteOnce, 'ReadOnlyMany, 'ReadWriteMany, 'ReadWriteOncePod |]) + | doc "Access modes for the volume", + + reclaim_policy + | [| 'Retain, 'Recycle, 'Delete |] + | doc "Reclaim policy when PVC is deleted" + | default = 'Retain, + + storage_class_name + | String + | doc "Storage class name" + | optional, + + host_path + | { + path + | String + | doc "Path on the host node", + + type + | [| 'DirectoryOrCreate, 'Directory, 'FileOrCreate, 'File, 'Socket, 'CharDevice, 'BlockDevice |] + | doc "Type of host path" + | default = 'DirectoryOrCreate, + } + | doc "Host path configuration" + | optional, + + nfs + | { + server + | String + | doc "NFS server hostname or IP", + + path + | String + | doc "Exported NFS path", + + read_only + | Bool + | doc "Mount as read-only" + | default = false, + } + | doc "NFS volume configuration" + | optional, + + local + | { + path + | String + | doc "Local path on the node", + } + | doc "Local volume configuration" + | optional, + + mount_options + | Array String + | doc "Mount options for the volume" + | default = [], + + labels + | {_: String} + | doc "Volume labels" + | default = {}, + }, + + # Kubernetes PersistentVolumeClaim configuration + KubernetesPersistentVolumeClaim = { + name + | String + | doc "PersistentVolumeClaim name" + | { + label = "valid name", + predicate = fun s => + std.string.is_match "^[a-z0-9-]+$" s && + std.string.length s >= 1 && std.string.length s <= 64 + }, + + storage_class_name + | String + | doc "Storage class name" + | optional, + + access_modes + | Array ([| 'ReadWriteOnce, 'ReadOnlyMany, 'ReadWriteMany, 'ReadWriteOncePod |]) + | doc "Access modes for the volume", + + resources + | { + requests + | { + storage + | String + | doc "Requested storage size (e.g., '10Gi')" + | { + label = "valid size", + predicate = fun s => + std.string.is_match "^[0-9]+(Mi|Gi|Ti|M|G|T)$" s + }, + } + | doc "Resource requests", + + limits + | { + storage + | String + | doc "Storage limit (e.g., '20Gi')" + | { + label = "valid size", + predicate = fun s => + std.string.is_match "^[0-9]+(Mi|Gi|Ti|M|G|T)$" s + } + | optional, + } + | doc "Resource limits" + | optional, + } + | doc "Resource requirements", + + volume_name + | String + | doc "Name of specific PV to bind to" + | optional, + + selector + | { + matchLabels + | {_: String} + | doc "Label selector" + | optional, + } + | doc "Label selector for binding to PV" + | optional, + + volume_mode + | [| 'Filesystem, 'Block |] + | doc "Volume mode" + | default = 'Filesystem, + }, + + # Main storage configuration + StorageConfig = { + docker_volumes + | {_: DockerVolume} + | doc "Docker volumes definition" + | default = {}, + + volume_mounts + | Array VolumeMount + | doc "Volume mounts for services" + | default = [], + + kubernetes_pvs + | Array KubernetesPersistentVolume + | doc "Kubernetes PersistentVolumes" + | default = [], + + kubernetes_pvcs + | Array KubernetesPersistentVolumeClaim + | doc "Kubernetes PersistentVolumeClaims" + | default = [], + + backup_config + | { + enabled + | Bool + | doc "Enable automated backups" + | default = false, + + schedule + | String + | doc "Backup schedule in cron format" + | optional, + + retention_days + | Number + | doc "Number of days to retain backups" + | default = 7, + + destination + | String + | doc "Backup destination path or URL" + | optional, + } + | doc "Backup configuration" + | optional, + }, +} diff --git a/.typedialog/provisioning/validators/common-validator.ncl b/.typedialog/provisioning/validators/common-validator.ncl new file mode 100644 index 0000000..53dbe4d --- /dev/null +++ b/.typedialog/provisioning/validators/common-validator.ncl @@ -0,0 +1,137 @@ +# Common Validator - Shared validation functions +# Version: 1.0.0 +# +# Provides reusable validation predicates and helpers + +{ + # Validate string length is within range + validate_string_length = fun min max => + fun s => + let len = std.string.length s in + len >= min && len <= max, + + # Validate string matches pattern + validate_pattern = fun pattern => + fun s => + std.string.is_match pattern s, + + # Validate number is within range + validate_number_range = fun min max => + fun n => + n >= min && n <= max, + + # Validate port number + validate_port = fun p => + p >= 1 && p <= 65535, + + # Validate host port (non-root range) + validate_host_port = fun p => + p >= 1024 && p <= 65535, + + # Validate project name (lowercase alphanumeric with hyphens) + validate_project_name = fun s => + std.string.is_match "^[a-z0-9-]+$" s && + std.string.length s >= 1 && std.string.length s <= 64, + + # Validate semantic version + validate_semver = fun s => + std.string.is_match "^[0-9]+\\.[0-9]+\\.[0-9]+$" s, + + # Validate IP address (IPv4) + validate_ipv4 = fun s => + std.string.is_match "^([0-9]{1,3}\\.){3}[0-9]{1,3}$" s, + + # Validate CIDR notation + validate_cidr = fun s => + std.string.is_match "^([0-9]{1,3}\\.){3}[0-9]{1,3}/[0-9]{1,2}$" s, + + # Validate CPU limit format (e.g., "1000m", "1.5") + validate_cpu_limit = fun s => + std.string.is_match "^[0-9]+(\\.[0-9]+)?m?$" s, + + # Validate memory limit format (e.g., "512Mi", "1Gi") + validate_memory_limit = fun s => + std.string.is_match "^[0-9]+(Mi|Gi|M|G|Ki|K|Ti|T)$" s, + + # Validate storage size format + validate_storage_size = fun s => + std.string.is_match "^[0-9]+(Mi|Gi|Ti|M|G|T)$" s, + + # Validate duration format (e.g., "30s", "5m", "2h", "7d") + validate_duration = fun s => + std.string.is_match "^[0-9]+(s|m|h|d)$" s, + + # Validate percentage format (e.g., "25%", "50%") + validate_percentage = fun s => + std.string.is_match "^[0-9]+(\\.[0-9]+)?%?$" s, + + # Validate Kubernetes name (RFC 1123 subdomain) + validate_k8s_name = fun s => + std.string.is_match "^[a-z0-9]([-a-z0-9]*[a-z0-9])?$" s && + std.string.length s >= 1 && std.string.length s <= 63, + + # Validate Docker image name + validate_image_name = fun s => + std.string.length s >= 1 && std.string.length s <= 256, + + # Validate image tag + validate_image_tag = fun s => + std.string.is_match "^[a-zA-Z0-9._-]+$" s && + std.string.length s <= 128, + + # Validate URL + validate_url = fun s => + std.string.is_match "^https?://.*" s || + std.string.is_match "^wss?://.*" s, + + # Validate email address (basic validation) + validate_email = fun s => + std.string.is_match "^[^@]+@[^@]+\\.[^@]+$" s, + + # Validate password strength (min 8 chars, max 128 chars) + validate_password = fun s => + std.string.length s >= 8 && std.string.length s <= 128, + + # Validate array is not empty + validate_not_empty_array = fun arr => + std.array.length arr > 0, + + # Validate record is not empty + validate_not_empty_record = fun rec => + std.record.length rec > 0, + + # Validate all array elements match predicate + validate_all = fun predicate => + fun arr => + std.array.all predicate arr, + + # Validate at least one array element matches predicate + validate_any = fun predicate => + fun arr => + std.array.any predicate arr, + + # Validate value is one of allowed values + validate_one_of = fun allowed => + fun value => + std.array.any (fun x => x == value) allowed, + + # Compose multiple validators (all must pass) + validate_and = fun validators => + fun value => + std.array.all (fun validator => validator value) validators, + + # Compose multiple validators (at least one must pass) + validate_or = fun validators => + fun value => + std.array.any (fun validator => validator value) validators, + + # Negate validator result + validate_not = fun validator => + fun value => + !(validator value), + + # Conditional validator (if condition is true, apply validator) + validate_if = fun condition validator => + fun value => + if condition value then validator value else true, +} diff --git a/.typedialog/provisioning/validators/database-validator.ncl b/.typedialog/provisioning/validators/database-validator.ncl new file mode 100644 index 0000000..8323a6f --- /dev/null +++ b/.typedialog/provisioning/validators/database-validator.ncl @@ -0,0 +1,279 @@ +# Database Validator - Database configuration validation +# Version: 1.0.0 +# +# Validates database configurations against constraints + +let Common = import "common-validator.ncl" in + +{ + # Validate database type + validate_database_type = fun db_type => + Common.validate_one_of ['sqlite, 'postgres, 'mysql, 'surrealdb, 'none] db_type, + + # Validate database name (alphanumeric + underscore) + validate_database_name = fun name => + Common.validate_pattern "^[a-zA-Z0-9_]+$" name && + Common.validate_string_length 1 64 name, + + # Validate hostname + validate_hostname = fun host => + Common.validate_string_length 1 256 host, + + # Validate password + validate_password = fun password => + Common.validate_password password, + + # Validate connection pool size + validate_pool_size = fun size => + Common.validate_number_range 1 1000 size, + + # Validate timeout + validate_timeout = fun timeout => + Common.validate_number_range 1 300 timeout, + + # SQLite validation + validate_sqlite = { + database_path + | String + | { + label = "valid path", + predicate = Common.validate_string_length 1 256 + }, + + journal_mode + | [| 'WAL, 'DELETE, 'TRUNCATE, 'PERSIST, 'MEMORY |] + | default = 'WAL, + + synchronous + | [| 'OFF, 'NORMAL, 'FULL, 'EXTRA |] + | default = 'NORMAL, + + cache_size | Number | default = -2000, + + foreign_keys | Bool | default = true, + }, + + # PostgreSQL validation + validate_postgres = { + host + | String + | { + label = "valid hostname", + predicate = validate_hostname + } + | default = "localhost", + + port + | Number + | { + label = "valid port", + predicate = Common.validate_host_port + } + | default = 5432, + + database + | String + | { + label = "valid database name", + predicate = validate_database_name + }, + + username + | String + | { + label = "valid username", + predicate = Common.validate_string_length 1 64 + }, + + password + | String + | { + label = "valid password", + predicate = validate_password + }, + + pool_size + | Number + | { + label = "valid pool size", + predicate = validate_pool_size + } + | default = 10, + + connection_timeout + | Number + | { + label = "valid timeout", + predicate = validate_timeout + } + | default = 30, + + idle_timeout + | Number + | { + label = "valid idle timeout", + predicate = Common.validate_number_range 60 3600 + } + | default = 600, + + max_lifetime + | Number + | { + label = "valid max lifetime", + predicate = Common.validate_number_range 300 86400 + } + | default = 3600, + + ssl_mode + | [| 'disable, 'allow, 'prefer, 'require, 'verify-ca, 'verify-full |] + | default = 'prefer, + + application_name + | String + | optional, + }, + + # MySQL validation + validate_mysql = { + host + | String + | { + label = "valid hostname", + predicate = validate_hostname + } + | default = "localhost", + + port + | Number + | { + label = "valid port", + predicate = Common.validate_host_port + } + | default = 3306, + + database + | String + | { + label = "valid database name", + predicate = validate_database_name + }, + + username + | String + | { + label = "valid username", + predicate = Common.validate_string_length 1 32 + }, + + password + | String + | { + label = "valid password", + predicate = validate_password + }, + + pool_size + | Number + | { + label = "valid pool size", + predicate = validate_pool_size + } + | default = 10, + + connection_timeout + | Number + | { + label = "valid timeout", + predicate = validate_timeout + } + | default = 30, + + charset | String | default = "utf8mb4", + + collation | String | default = "utf8mb4_unicode_ci", + }, + + # SurrealDB validation + validate_surrealdb = { + host + | String + | { + label = "valid hostname", + predicate = validate_hostname + } + | default = "localhost", + + port + | Number + | { + label = "valid port", + predicate = Common.validate_host_port + } + | default = 8000, + + namespace + | String + | { + label = "valid namespace", + predicate = Common.validate_string_length 1 64 + }, + + database + | String + | { + label = "valid database name", + predicate = Common.validate_string_length 1 64 + }, + + username + | String + | { + label = "valid username", + predicate = Common.validate_string_length 1 64 + }, + + password + | String + | { + label = "valid password", + predicate = validate_password + }, + + protocol + | [| 'http, 'https, 'ws, 'wss |] + | default = 'http, + }, + + # Complete database configuration validation + validate_database_config = { + type + | { + label = "valid database type", + predicate = validate_database_type + }, + + sqlite + | validate_sqlite + | optional, + + postgres + | validate_postgres + | optional, + + mysql + | validate_mysql + | optional, + + surrealdb + | validate_surrealdb + | optional, + + migrations_path + | String + | default = "./migrations", + + auto_migrate + | Bool + | default = false, + }, +} diff --git a/.typedialog/provisioning/validators/deployment-validator.ncl b/.typedialog/provisioning/validators/deployment-validator.ncl new file mode 100644 index 0000000..f11817d --- /dev/null +++ b/.typedialog/provisioning/validators/deployment-validator.ncl @@ -0,0 +1,349 @@ +# Deployment Validator - Deployment configuration validation +# Version: 1.0.0 +# +# Validates Docker Compose and Kubernetes deployment configurations + +let Common = import "common-validator.ncl" in + +{ + # Validate Docker Compose version + validate_compose_version = fun version => + Common.validate_one_of ['3.8, '3.9] version, + + # Validate restart policy + validate_restart_policy = fun policy => + Common.validate_one_of ['no, 'always, 'on-failure, 'unless-stopped] policy, + + # Docker Compose configuration validation + validate_docker_compose = { + enabled | Bool | default = true, + + version + | { + label = "valid version", + predicate = validate_compose_version + } + | default = '3.8, + + project_name + | String + | optional, + + env_file + | String + | default = ".env", + + profiles + | Array String + | default = [], + + extends + | { + file | String, + service | String, + } + | optional, + }, + + # Validate Kubernetes namespace + validate_k8s_namespace = { + name + | String + | { + label = "valid namespace", + predicate = fun s => + Common.validate_k8s_name s && + std.string.length s <= 63 + }, + + labels + | {_: String} + | default = {}, + + annotations + | {_: String} + | default = {}, + }, + + # Validate Ingress path type + validate_path_type = fun path_type => + Common.validate_one_of ['Prefix, 'Exact, 'ImplementationSpecific] path_type, + + # Validate Ingress rule + validate_ingress_rule = { + host + | String + | optional, + + http + | { + paths + | Array { + path | String, + path_type + | { + label = "valid path type", + predicate = validate_path_type + } + | default = 'Prefix, + backend | { + service | { + name | String, + port | { + number | Number | optional, + name | String | optional, + }, + }, + }, + }, + }, + }, + + # Validate Ingress configuration + validate_ingress = { + enabled | Bool | default = false, + + name + | String + | { + label = "valid name", + predicate = Common.validate_k8s_name + } + | optional, + + class_name + | String + | default = "nginx", + + rules + | Array validate_ingress_rule + | default = [], + + tls + | Array { + hosts | Array String, + secret_name | String | optional, + } + | default = [], + + annotations + | {_: String} + | default = {}, + }, + + # Validate Service type + validate_service_type = fun svc_type => + Common.validate_one_of ['ClusterIP, 'NodePort, 'LoadBalancer, 'ExternalName] svc_type, + + # Validate Kubernetes Service configuration + validate_k8s_service = { + type + | { + label = "valid service type", + predicate = validate_service_type + } + | default = 'ClusterIP, + + cluster_ip + | String + | optional, + + external_ips + | Array String + | default = [], + + load_balancer_ip + | String + | optional, + + load_balancer_source_ranges + | Array String + | default = [], + + external_traffic_policy + | [| 'Cluster, 'Local |] + | optional, + + session_affinity + | [| 'None, 'ClientIP |] + | default = 'None, + + annotations + | {_: String} + | default = {}, + }, + + # Validate deployment strategy type + validate_strategy_type = fun strategy => + Common.validate_one_of ['RollingUpdate, 'Recreate] strategy, + + # Validate deployment strategy + validate_deployment_strategy = { + type + | { + label = "valid strategy type", + predicate = validate_strategy_type + } + | default = 'RollingUpdate, + + rolling_update + | { + max_surge + | String + | { + label = "valid surge", + predicate = Common.validate_percentage + } + | default = "25%", + + max_unavailable + | String + | { + label = "valid unavailable", + predicate = Common.validate_percentage + } + | default = "25%", + } + | optional, + }, + + # Validate ConfigMap + validate_configmap = { + name + | String + | { + label = "valid name", + predicate = Common.validate_k8s_name + }, + + data + | {_: String} + | default = {}, + + binary_data + | {_: String} + | default = {}, + + from_files + | Array String + | default = [], + }, + + # Validate toleration + validate_toleration = { + key | String | optional, + + operator + | [| 'Exists, 'Equal |] + | default = 'Equal, + + value | String | optional, + + effect + | [| 'NoSchedule, 'PreferNoSchedule, 'NoExecute |] + | optional, + + toleration_seconds | Number | optional, + }, + + # Kubernetes configuration validation + validate_kubernetes = { + enabled | Bool | default = false, + + namespace + | String + | { + label = "valid namespace", + predicate = fun s => + Common.validate_k8s_name s && + std.string.length s <= 63 + } + | default = "default", + + create_namespace | Bool | default = false, + + namespace_config + | validate_k8s_namespace + | optional, + + service + | validate_k8s_service + | default = {type = 'ClusterIP}, + + ingress + | validate_ingress + | default = {enabled = false}, + + deployment_strategy + | validate_deployment_strategy + | default = {type = 'RollingUpdate}, + + hpa + | { + enabled | Bool | default = false, + min_replicas | Number | default = 1, + max_replicas | Number | default = 10, + target_cpu_utilization | Number | default = 80, + target_memory_utilization | Number | optional, + } + | default = {enabled = false}, + + configmaps + | Array validate_configmap + | default = [], + + pod_annotations + | {_: String} + | default = {}, + + pod_labels + | {_: String} + | default = {}, + + service_account + | String + | optional, + + image_pull_secrets + | Array String + | default = [], + + node_selector + | {_: String} + | default = {}, + + tolerations + | Array validate_toleration + | default = [], + + affinity + | { + node_affinity | {_: _} | optional, + pod_affinity | {_: _} | optional, + pod_anti_affinity | {_: _} | optional, + } + | optional, + }, + + # Validate deployment target + validate_deployment_target = fun target => + Common.validate_one_of ['docker, 'kubernetes, 'both] target, + + # Complete deployment configuration validation + validate_deployment_config = { + docker_compose + | validate_docker_compose + | optional, + + kubernetes + | validate_kubernetes + | optional, + + target + | { + label = "valid deployment target", + predicate = validate_deployment_target + } + | default = 'docker, + }, +} diff --git a/.typedialog/provisioning/validators/network-validator.ncl b/.typedialog/provisioning/validators/network-validator.ncl new file mode 100644 index 0000000..8a2df8a --- /dev/null +++ b/.typedialog/provisioning/validators/network-validator.ncl @@ -0,0 +1,207 @@ +# Network Validator - Network configuration validation +# Version: 1.0.0 +# +# Validates network, IPAM, and network policy configurations + +let Common = import "common-validator.ncl" in + +{ + # Validate network name + validate_network_name = fun name => + Common.validate_pattern "^[a-z0-9-]+$" name && + Common.validate_string_length 1 64 name, + + # Validate network driver + validate_network_driver = fun driver => + Common.validate_one_of ['bridge, 'host, 'overlay, 'macvlan, 'none] driver, + + # Validate CIDR notation + validate_cidr = fun cidr => + Common.validate_cidr cidr, + + # Validate IP address + validate_ip = fun ip => + Common.validate_ipv4 ip, + + # IPAM configuration validation + validate_ipam_config = { + subnet + | String + | { + label = "valid subnet", + predicate = validate_cidr + }, + + gateway + | String + | { + label = "valid IP", + predicate = validate_ip + } + | optional, + + ip_range + | String + | { + label = "valid IP range", + predicate = validate_cidr + } + | optional, + + aux_addresses + | {_: String} + | default = {}, + }, + + # Docker network validation + validate_docker_network = { + name + | String + | { + label = "valid network name", + predicate = validate_network_name + }, + + driver + | { + label = "valid driver", + predicate = validate_network_driver + } + | default = 'bridge, + + driver_opts + | {_: String} + | default = {}, + + ipam + | { + driver | String | default = "default", + config | Array validate_ipam_config | default = [], + } + | optional, + + internal | Bool | default = false, + + attachable | Bool | default = false, + + enable_ipv6 | Bool | default = false, + + labels + | {_: String} + | default = {}, + }, + + # Network policy port validation + validate_network_policy_port = { + port + | Number + | { + label = "valid port", + predicate = Common.validate_port + }, + + protocol + | [| 'TCP, 'UDP, 'SCTP |] + | default = 'TCP, + }, + + # Network policy peer validation + validate_network_policy_peer = { + pod_selector + | { + matchLabels | {_: String} | optional, + matchExpressions | Array { + key | String, + operator | [| 'In, 'NotIn, 'Exists, 'DoesNotExist |], + values | Array String | optional, + } | optional, + } + | optional, + + namespace_selector + | { + matchLabels | {_: String} | optional, + } + | optional, + + ip_block + | { + cidr + | String + | { + label = "valid CIDR", + predicate = validate_cidr + }, + except | Array String | default = [], + } + | optional, + }, + + # Network policy ingress rule validation + validate_ingress_rule = { + from + | Array validate_network_policy_peer + | default = [], + + ports + | Array validate_network_policy_port + | default = [], + }, + + # Network policy egress rule validation + validate_egress_rule = { + to + | Array validate_network_policy_peer + | default = [], + + ports + | Array validate_network_policy_port + | default = [], + }, + + # Kubernetes network policy validation + validate_k8s_network_policy = { + name + | String + | { + label = "valid name", + predicate = Common.validate_k8s_name + }, + + pod_selector + | { + matchLabels | {_: String} + }, + + policy_types + | Array ([| 'Ingress, 'Egress |]) + | default = ['Ingress], + + ingress + | Array validate_ingress_rule + | default = [], + + egress + | Array validate_egress_rule + | default = [], + }, + + # Complete network configuration validation + validate_network_config = { + docker_networks + | {_: validate_docker_network} + | default = {}, + + kubernetes_policies + | Array validate_k8s_network_policy + | default = [], + + dns_servers + | Array String + | default = [], + + dns_search + | Array String + | default = [], + }, +} diff --git a/.typedialog/provisioning/validators/resource-validator.ncl b/.typedialog/provisioning/validators/resource-validator.ncl new file mode 100644 index 0000000..06de23b --- /dev/null +++ b/.typedialog/provisioning/validators/resource-validator.ncl @@ -0,0 +1,136 @@ +# Resource Validator - Resource limits and requests validation +# Version: 1.0.0 +# +# Validates CPU, memory, and storage resource configurations + +let Common = import "common-validator.ncl" in + +{ + # Validate CPU limit format and value + validate_cpu_limit = fun cpu => + Common.validate_cpu_limit cpu, + + # Validate memory limit format and value + validate_memory_limit = fun memory => + Common.validate_memory_limit memory, + + # Validate storage size format and value + validate_storage_size = fun storage => + Common.validate_storage_size storage, + + # Validate resource requests are less than or equal to limits + validate_resource_limits = fun resources => + let + parse_cpu = fun s => + if std.string.ends_with "m" s then + std.string.to_number (std.string.substring 0 (std.string.length s - 1) s) + else + std.string.to_number s * 1000, + + parse_memory_unit = fun s => + if std.string.ends_with "Ki" s then 1024 + else if std.string.ends_with "Mi" s then 1048576 + else if std.string.ends_with "Gi" s then 1073741824 + else if std.string.ends_with "Ti" s then 1099511627776 + else if std.string.ends_with "K" s then 1000 + else if std.string.ends_with "M" s then 1000000 + else if std.string.ends_with "G" s then 1000000000 + else if std.string.ends_with "T" s then 1000000000000 + else 1, + + cpu_limit_valid = + if std.record.has_field "cpu_limit" resources && std.record.has_field "cpu_request" resources then + (parse_cpu resources.cpu_limit) >= (parse_cpu resources.cpu_request) + else + true, + + memory_limit_valid = + if std.record.has_field "memory_limit" resources && std.record.has_field "memory_request" resources then + true + else + true + in + cpu_limit_valid && memory_limit_valid, + + # Complete resource validation contract + validate_resources = { + cpu_limit + | String + | { + label = "valid CPU limit", + predicate = validate_cpu_limit + } + | optional, + + cpu_request + | String + | { + label = "valid CPU request", + predicate = validate_cpu_limit + } + | optional, + + memory_limit + | String + | { + label = "valid memory limit", + predicate = validate_memory_limit + } + | optional, + + memory_request + | String + | { + label = "valid memory request", + predicate = validate_memory_limit + } + | optional, + }, + + # Validate HPA (Horizontal Pod Autoscaler) configuration + validate_hpa = { + enabled | Bool | default = false, + + min_replicas + | Number + | { + label = "valid min replicas", + predicate = Common.validate_number_range 1 100 + } + | default = 1, + + max_replicas + | Number + | { + label = "valid max replicas", + predicate = Common.validate_number_range 1 100 + } + | default = 10, + + target_cpu_utilization + | Number + | { + label = "valid CPU utilization", + predicate = Common.validate_number_range 1 100 + } + | default = 80, + + target_memory_utilization + | Number + | { + label = "valid memory utilization", + predicate = Common.validate_number_range 1 100 + } + | optional, + }, + + # Validate PV/PVC storage requirements + validate_storage_requirements = { + storage + | String + | { + label = "valid storage size", + predicate = validate_storage_size + }, + }, +} diff --git a/.typedialog/provisioning/validators/service-validator.ncl b/.typedialog/provisioning/validators/service-validator.ncl new file mode 100644 index 0000000..ea1536d --- /dev/null +++ b/.typedialog/provisioning/validators/service-validator.ncl @@ -0,0 +1,265 @@ +# Service Validator - Service configuration validation +# Version: 1.0.0 +# +# Validates service definitions against constraints + +let Common = import "common-validator.ncl" in + +{ + # Validate service type is allowed + validate_service_type = fun service_type => + Common.validate_one_of ['api, 'worker, 'scheduler, 'frontend, 'backend, 'database, 'cache, 'queue] service_type, + + # Validate service name + validate_service_name = fun name => + Common.validate_pattern "^[a-z0-9-]+$" name && + Common.validate_string_length 1 32 name, + + # Validate replica count + validate_replicas = fun replicas => + Common.validate_number_range 1 100 replicas, + + # Validate port configuration + validate_port = { + container_port + | { + label = "valid container port", + predicate = Common.validate_port + }, + + host_port + | { + label = "valid host port", + predicate = Common.validate_host_port + }, + + protocol + | { + label = "valid protocol", + predicate = Common.validate_one_of ['tcp, 'udp, 'sctp] + }, + }, + + # Validate health check configuration + validate_healthcheck = { + enabled | Bool, + + endpoint + | String + | { + label = "valid endpoint", + predicate = fun s => std.string.starts_with "/" s + } + | optional, + + interval + | Number + | { + label = "valid interval", + predicate = Common.validate_number_range 5 300 + }, + + timeout + | Number + | { + label = "valid timeout", + predicate = Common.validate_number_range 1 60 + }, + + retries + | Number + | { + label = "valid retries", + predicate = Common.validate_number_range 1 10 + }, + + start_period + | Number + | { + label = "valid start period", + predicate = Common.validate_number_range 0 300 + }, + }, + + # Validate image configuration + validate_image = { + name + | String + | { + label = "valid image name", + predicate = Common.validate_image_name + }, + + tag + | String + | { + label = "valid image tag", + predicate = Common.validate_image_tag + }, + + build_context + | String + | optional, + + dockerfile + | String + | optional, + }, + + # Validate resource configuration + validate_resources = { + cpu_limit + | String + | { + label = "valid CPU limit", + predicate = Common.validate_cpu_limit + } + | optional, + + cpu_request + | String + | { + label = "valid CPU request", + predicate = Common.validate_cpu_limit + } + | optional, + + memory_limit + | String + | { + label = "valid memory limit", + predicate = Common.validate_memory_limit + } + | optional, + + memory_request + | String + | { + label = "valid memory request", + predicate = Common.validate_memory_limit + } + | optional, + }, + + # Validate restart policy + validate_restart_policy = fun policy => + Common.validate_one_of ['no, 'always, 'on-failure, 'unless-stopped] policy, + + # Validate environment variables + validate_environment = fun env => + std.record.values env + |> std.array.all (fun v => std.is_string v && std.string.length v <= 4096), + + # Validate depends_on array + validate_depends_on = fun deps => + std.array.all (fun s => + Common.validate_pattern "^[a-z0-9-]+$" s + ) deps, + + # Validate volume mounts + validate_volumes = fun volumes => + std.array.all (fun v => + std.is_string v && + std.string.length v >= 3 + ) volumes, + + # Validate networks + validate_networks = fun networks => + std.array.all (fun n => + Common.validate_pattern "^[a-z0-9-]+$" n + ) networks, + + # Complete service validation + validate_service = { + type + | { + label = "valid service type", + predicate = validate_service_type + }, + + image | validate_image, + + ports + | Array validate_port + | default = [], + + environment + | {_: String} + | { + label = "valid environment", + predicate = validate_environment + } + | default = {}, + + env_file + | Array String + | default = [], + + healthcheck + | validate_healthcheck + | default = {enabled = true}, + + resources + | validate_resources + | optional, + + depends_on + | Array String + | { + label = "valid dependencies", + predicate = validate_depends_on + } + | default = [], + + replicas + | Number + | { + label = "valid replica count", + predicate = validate_replicas + } + | default = 1, + + restart_policy + | { + label = "valid restart policy", + predicate = validate_restart_policy + } + | default = 'unless-stopped, + + command + | Array String + | optional, + + entrypoint + | Array String + | optional, + + working_dir + | String + | optional, + + user + | String + | optional, + + volumes + | Array String + | { + label = "valid volumes", + predicate = validate_volumes + } + | default = [], + + networks + | Array String + | { + label = "valid networks", + predicate = validate_networks + } + | default = [], + + labels + | {_: String} + | default = {}, + }, +} diff --git a/.vale.ini b/.vale.ini new file mode 100644 index 0000000..f1f7c7b --- /dev/null +++ b/.vale.ini @@ -0,0 +1,43 @@ +# Vale configuration for TypeDialog documentation +# https://vale.sh/docs/topics/config/ + +StylesPath = .vale/styles +MinAlertLevel = warning +# Vocab = TypeDialog # Disabled: vocabulary directory structure mismatch + +# Global settings +[*] +Packages = Google, write-good + +# Markdown files: docs/**/*.md and root *.md (excluding .claude, .coder, CLAUDE.md) +[*.md] +BasedOnStyles = write-good, Google + +# Ignore code blocks and specific patterns +TokenIgnores = (\$\{[^\}]+\}), (`[^`]+`), (\*\*[^\*]+\*\*) + +# Disable noisy rules for technical documentation +Google.Headings = NO +Google.Parens = NO +Google.Acronyms = NO +Google.Passive = NO +Google.We = NO +Google.Will = NO +Google.WordList = NO +Google.Colons = NO + +write-good.E-Prime = NO +write-good.TooWordy = NO +write-good.Passive = NO + +Vale.Spelling = NO +Google.Ellipses = NO +Google.OxfordComma = NO + +# Keep enabled (useful for technical docs): +# - write-good.Weasel (vague words like "various") +# - Google.Contractions (maintain formal tone) +# - Google.FirstPerson (avoid "we/our") +# - Google.Exclamation +# - Google.Slang +# - Google.Units diff --git a/.vale/Vocab/TypeDialog/accept.txt b/.vale/Vocab/TypeDialog/accept.txt new file mode 100644 index 0000000..ffc7ad8 --- /dev/null +++ b/.vale/Vocab/TypeDialog/accept.txt @@ -0,0 +1,25 @@ +# TypeDialog accepted terms (case-insensitive) +# Technical acronyms and abbreviations +API +CLI +TUI +JSON +YAML +TOML +REST +HTTP +HTTPS +TLS +SSL +CORS +URL +URI +NPM +SDK +HTML +CSS +JWT +WASM +WebAssembly +README +CHANGELOG diff --git a/.vale/Vocab/TypeDialog/reject.txt b/.vale/Vocab/TypeDialog/reject.txt new file mode 100644 index 0000000..a7f5a8f --- /dev/null +++ b/.vale/Vocab/TypeDialog/reject.txt @@ -0,0 +1,2 @@ +# TypeDialog rejected terms +# Add terms that should never be used diff --git a/.vale/styles/Google/AMPM.yml b/.vale/styles/Google/AMPM.yml new file mode 100644 index 0000000..37b49ed --- /dev/null +++ b/.vale/styles/Google/AMPM.yml @@ -0,0 +1,9 @@ +extends: existence +message: "Use 'AM' or 'PM' (preceded by a space)." +link: "https://developers.google.com/style/word-list" +level: error +nonword: true +tokens: + - '\d{1,2}[AP]M\b' + - '\d{1,2} ?[ap]m\b' + - '\d{1,2} ?[aApP]\.[mM]\.' diff --git a/.vale/styles/Google/Acronyms.yml b/.vale/styles/Google/Acronyms.yml new file mode 100644 index 0000000..f41af01 --- /dev/null +++ b/.vale/styles/Google/Acronyms.yml @@ -0,0 +1,64 @@ +extends: conditional +message: "Spell out '%s', if it's unfamiliar to the audience." +link: 'https://developers.google.com/style/abbreviations' +level: suggestion +ignorecase: false +# Ensures that the existence of 'first' implies the existence of 'second'. +first: '\b([A-Z]{3,5})\b' +second: '(?:\b[A-Z][a-z]+ )+\(([A-Z]{3,5})\)' +# ... with the exception of these: +exceptions: + - API + - ASP + - CLI + - CPU + - CSS + - CSV + - DEBUG + - DOM + - DPI + - FAQ + - GCC + - GDB + - GET + - GPU + - GTK + - GUI + - HTML + - HTTP + - HTTPS + - IDE + - JAR + - JSON + - JSX + - LESS + - LLDB + - NET + - NOTE + - NVDA + - OSS + - PATH + - PDF + - PHP + - POST + - RAM + - REPL + - RSA + - SCM + - SCSS + - SDK + - SQL + - SSH + - SSL + - SVG + - TBD + - TCP + - TODO + - URI + - URL + - USB + - UTF + - XML + - XSS + - YAML + - ZIP diff --git a/.vale/styles/Google/Colons.yml b/.vale/styles/Google/Colons.yml new file mode 100644 index 0000000..4a027c3 --- /dev/null +++ b/.vale/styles/Google/Colons.yml @@ -0,0 +1,8 @@ +extends: existence +message: "'%s' should be in lowercase." +link: 'https://developers.google.com/style/colons' +nonword: true +level: warning +scope: sentence +tokens: + - '(?=1.0.0" +} diff --git a/.vale/styles/Google/vocab.txt b/.vale/styles/Google/vocab.txt new file mode 100644 index 0000000..e69de29 diff --git a/.vale/styles/write-good/Cliches.yml b/.vale/styles/write-good/Cliches.yml new file mode 100644 index 0000000..c953143 --- /dev/null +++ b/.vale/styles/write-good/Cliches.yml @@ -0,0 +1,702 @@ +extends: existence +message: "Try to avoid using clichΓ©s like '%s'." +ignorecase: true +level: warning +tokens: + - a chip off the old block + - a clean slate + - a dark and stormy night + - a far cry + - a fine kettle of fish + - a loose cannon + - a penny saved is a penny earned + - a tough row to hoe + - a word to the wise + - ace in the hole + - acid test + - add insult to injury + - against all odds + - air your dirty laundry + - all fun and games + - all in a day's work + - all talk, no action + - all thumbs + - all your eggs in one basket + - all's fair in love and war + - all's well that ends well + - almighty dollar + - American as apple pie + - an axe to grind + - another day, another dollar + - armed to the teeth + - as luck would have it + - as old as time + - as the crow flies + - at loose ends + - at my wits end + - avoid like the plague + - babe in the woods + - back against the wall + - back in the saddle + - back to square one + - back to the drawing board + - bad to the bone + - badge of honor + - bald faced liar + - ballpark figure + - banging your head against a brick wall + - baptism by fire + - barking up the wrong tree + - bat out of hell + - be all and end all + - beat a dead horse + - beat around the bush + - been there, done that + - beggars can't be choosers + - behind the eight ball + - bend over backwards + - benefit of the doubt + - bent out of shape + - best thing since sliced bread + - bet your bottom dollar + - better half + - better late than never + - better mousetrap + - better safe than sorry + - between a rock and a hard place + - beyond the pale + - bide your time + - big as life + - big cheese + - big fish in a small pond + - big man on campus + - bigger they are the harder they fall + - bird in the hand + - bird's eye view + - birds and the bees + - birds of a feather flock together + - bit the hand that feeds you + - bite the bullet + - bite the dust + - bitten off more than he can chew + - black as coal + - black as pitch + - black as the ace of spades + - blast from the past + - bleeding heart + - blessing in disguise + - blind ambition + - blind as a bat + - blind leading the blind + - blood is thicker than water + - blood sweat and tears + - blow off steam + - blow your own horn + - blushing bride + - boils down to + - bolt from the blue + - bone to pick + - bored stiff + - bored to tears + - bottomless pit + - boys will be boys + - bright and early + - brings home the bacon + - broad across the beam + - broken record + - brought back to reality + - bull by the horns + - bull in a china shop + - burn the midnight oil + - burning question + - burning the candle at both ends + - burst your bubble + - bury the hatchet + - busy as a bee + - by hook or by crook + - call a spade a spade + - called onto the carpet + - calm before the storm + - can of worms + - can't cut the mustard + - can't hold a candle to + - case of mistaken identity + - cat got your tongue + - cat's meow + - caught in the crossfire + - caught red-handed + - checkered past + - chomping at the bit + - cleanliness is next to godliness + - clear as a bell + - clear as mud + - close to the vest + - cock and bull story + - cold shoulder + - come hell or high water + - cool as a cucumber + - cool, calm, and collected + - cost a king's ransom + - count your blessings + - crack of dawn + - crash course + - creature comforts + - cross that bridge when you come to it + - crushing blow + - cry like a baby + - cry me a river + - cry over spilt milk + - crystal clear + - curiosity killed the cat + - cut and dried + - cut through the red tape + - cut to the chase + - cute as a bugs ear + - cute as a button + - cute as a puppy + - cuts to the quick + - dark before the dawn + - day in, day out + - dead as a doornail + - devil is in the details + - dime a dozen + - divide and conquer + - dog and pony show + - dog days + - dog eat dog + - dog tired + - don't burn your bridges + - don't count your chickens + - don't look a gift horse in the mouth + - don't rock the boat + - don't step on anyone's toes + - don't take any wooden nickels + - down and out + - down at the heels + - down in the dumps + - down the hatch + - down to earth + - draw the line + - dressed to kill + - dressed to the nines + - drives me up the wall + - dull as dishwater + - dyed in the wool + - eagle eye + - ear to the ground + - early bird catches the worm + - easier said than done + - easy as pie + - eat your heart out + - eat your words + - eleventh hour + - even the playing field + - every dog has its day + - every fiber of my being + - everything but the kitchen sink + - eye for an eye + - face the music + - facts of life + - fair weather friend + - fall by the wayside + - fan the flames + - feast or famine + - feather your nest + - feathered friends + - few and far between + - fifteen minutes of fame + - filthy vermin + - fine kettle of fish + - fish out of water + - fishing for a compliment + - fit as a fiddle + - fit the bill + - fit to be tied + - flash in the pan + - flat as a pancake + - flip your lid + - flog a dead horse + - fly by night + - fly the coop + - follow your heart + - for all intents and purposes + - for the birds + - for what it's worth + - force of nature + - force to be reckoned with + - forgive and forget + - fox in the henhouse + - free and easy + - free as a bird + - fresh as a daisy + - full steam ahead + - fun in the sun + - garbage in, garbage out + - gentle as a lamb + - get a kick out of + - get a leg up + - get down and dirty + - get the lead out + - get to the bottom of + - get your feet wet + - gets my goat + - gilding the lily + - give and take + - go against the grain + - go at it tooth and nail + - go for broke + - go him one better + - go the extra mile + - go with the flow + - goes without saying + - good as gold + - good deed for the day + - good things come to those who wait + - good time was had by all + - good times were had by all + - greased lightning + - greek to me + - green thumb + - green-eyed monster + - grist for the mill + - growing like a weed + - hair of the dog + - hand to mouth + - happy as a clam + - happy as a lark + - hasn't a clue + - have a nice day + - have high hopes + - have the last laugh + - haven't got a row to hoe + - head honcho + - head over heels + - hear a pin drop + - heard it through the grapevine + - heart's content + - heavy as lead + - hem and haw + - high and dry + - high and mighty + - high as a kite + - hit paydirt + - hold your head up high + - hold your horses + - hold your own + - hold your tongue + - honest as the day is long + - horns of a dilemma + - horse of a different color + - hot under the collar + - hour of need + - I beg to differ + - icing on the cake + - if the shoe fits + - if the shoe were on the other foot + - in a jam + - in a jiffy + - in a nutshell + - in a pig's eye + - in a pinch + - in a word + - in hot water + - in the gutter + - in the nick of time + - in the thick of it + - in your dreams + - it ain't over till the fat lady sings + - it goes without saying + - it takes all kinds + - it takes one to know one + - it's a small world + - it's only a matter of time + - ivory tower + - Jack of all trades + - jockey for position + - jog your memory + - joined at the hip + - judge a book by its cover + - jump down your throat + - jump in with both feet + - jump on the bandwagon + - jump the gun + - jump to conclusions + - just a hop, skip, and a jump + - just the ticket + - justice is blind + - keep a stiff upper lip + - keep an eye on + - keep it simple, stupid + - keep the home fires burning + - keep up with the Joneses + - keep your chin up + - keep your fingers crossed + - kick the bucket + - kick up your heels + - kick your feet up + - kid in a candy store + - kill two birds with one stone + - kiss of death + - knock it out of the park + - knock on wood + - knock your socks off + - know him from Adam + - know the ropes + - know the score + - knuckle down + - knuckle sandwich + - knuckle under + - labor of love + - ladder of success + - land on your feet + - lap of luxury + - last but not least + - last hurrah + - last-ditch effort + - law of the jungle + - law of the land + - lay down the law + - leaps and bounds + - let sleeping dogs lie + - let the cat out of the bag + - let the good times roll + - let your hair down + - let's talk turkey + - letter perfect + - lick your wounds + - lies like a rug + - life's a bitch + - life's a grind + - light at the end of the tunnel + - lighter than a feather + - lighter than air + - like clockwork + - like father like son + - like taking candy from a baby + - like there's no tomorrow + - lion's share + - live and learn + - live and let live + - long and short of it + - long lost love + - look before you leap + - look down your nose + - look what the cat dragged in + - looking a gift horse in the mouth + - looks like death warmed over + - loose cannon + - lose your head + - lose your temper + - loud as a horn + - lounge lizard + - loved and lost + - low man on the totem pole + - luck of the draw + - luck of the Irish + - make hay while the sun shines + - make money hand over fist + - make my day + - make the best of a bad situation + - make the best of it + - make your blood boil + - man of few words + - man's best friend + - mark my words + - meaningful dialogue + - missed the boat on that one + - moment in the sun + - moment of glory + - moment of truth + - money to burn + - more power to you + - more than one way to skin a cat + - movers and shakers + - moving experience + - naked as a jaybird + - naked truth + - neat as a pin + - needle in a haystack + - needless to say + - neither here nor there + - never look back + - never say never + - nip and tuck + - nip it in the bud + - no guts, no glory + - no love lost + - no pain, no gain + - no skin off my back + - no stone unturned + - no time like the present + - no use crying over spilled milk + - nose to the grindstone + - not a hope in hell + - not a minute's peace + - not in my backyard + - not playing with a full deck + - not the end of the world + - not written in stone + - nothing to sneeze at + - nothing ventured nothing gained + - now we're cooking + - off the top of my head + - off the wagon + - off the wall + - old hat + - older and wiser + - older than dirt + - older than Methuselah + - on a roll + - on cloud nine + - on pins and needles + - on the bandwagon + - on the money + - on the nose + - on the rocks + - on the spot + - on the tip of my tongue + - on the wagon + - on thin ice + - once bitten, twice shy + - one bad apple doesn't spoil the bushel + - one born every minute + - one brick short + - one foot in the grave + - one in a million + - one red cent + - only game in town + - open a can of worms + - open and shut case + - open the flood gates + - opportunity doesn't knock twice + - out of pocket + - out of sight, out of mind + - out of the frying pan into the fire + - out of the woods + - out on a limb + - over a barrel + - over the hump + - pain and suffering + - pain in the + - panic button + - par for the course + - part and parcel + - party pooper + - pass the buck + - patience is a virtue + - pay through the nose + - penny pincher + - perfect storm + - pig in a poke + - pile it on + - pillar of the community + - pin your hopes on + - pitter patter of little feet + - plain as day + - plain as the nose on your face + - play by the rules + - play your cards right + - playing the field + - playing with fire + - pleased as punch + - plenty of fish in the sea + - point with pride + - poor as a church mouse + - pot calling the kettle black + - pretty as a picture + - pull a fast one + - pull your punches + - pulling your leg + - pure as the driven snow + - put it in a nutshell + - put one over on you + - put the cart before the horse + - put the pedal to the metal + - put your best foot forward + - put your foot down + - quick as a bunny + - quick as a lick + - quick as a wink + - quick as lightning + - quiet as a dormouse + - rags to riches + - raining buckets + - raining cats and dogs + - rank and file + - rat race + - reap what you sow + - red as a beet + - red herring + - reinvent the wheel + - rich and famous + - rings a bell + - ripe old age + - ripped me off + - rise and shine + - road to hell is paved with good intentions + - rob Peter to pay Paul + - roll over in the grave + - rub the wrong way + - ruled the roost + - running in circles + - sad but true + - sadder but wiser + - salt of the earth + - scared stiff + - scared to death + - sealed with a kiss + - second to none + - see eye to eye + - seen the light + - seize the day + - set the record straight + - set the world on fire + - set your teeth on edge + - sharp as a tack + - shoot for the moon + - shoot the breeze + - shot in the dark + - shoulder to the wheel + - sick as a dog + - sigh of relief + - signed, sealed, and delivered + - sink or swim + - six of one, half a dozen of another + - skating on thin ice + - slept like a log + - slinging mud + - slippery as an eel + - slow as molasses + - smart as a whip + - smooth as a baby's bottom + - sneaking suspicion + - snug as a bug in a rug + - sow wild oats + - spare the rod, spoil the child + - speak of the devil + - spilled the beans + - spinning your wheels + - spitting image of + - spoke with relish + - spread like wildfire + - spring to life + - squeaky wheel gets the grease + - stands out like a sore thumb + - start from scratch + - stick in the mud + - still waters run deep + - stitch in time + - stop and smell the roses + - straight as an arrow + - straw that broke the camel's back + - strong as an ox + - stubborn as a mule + - stuff that dreams are made of + - stuffed shirt + - sweating blood + - sweating bullets + - take a load off + - take one for the team + - take the bait + - take the bull by the horns + - take the plunge + - takes one to know one + - takes two to tango + - the more the merrier + - the real deal + - the real McCoy + - the red carpet treatment + - the same old story + - there is no accounting for taste + - thick as a brick + - thick as thieves + - thin as a rail + - think outside of the box + - third time's the charm + - this day and age + - this hurts me worse than it hurts you + - this point in time + - three sheets to the wind + - through thick and thin + - throw in the towel + - tie one on + - tighter than a drum + - time and time again + - time is of the essence + - tip of the iceberg + - tired but happy + - to coin a phrase + - to each his own + - to make a long story short + - to the best of my knowledge + - toe the line + - tongue in cheek + - too good to be true + - too hot to handle + - too numerous to mention + - touch with a ten foot pole + - tough as nails + - trial and error + - trials and tribulations + - tried and true + - trip down memory lane + - twist of fate + - two cents worth + - two peas in a pod + - ugly as sin + - under the counter + - under the gun + - under the same roof + - under the weather + - until the cows come home + - unvarnished truth + - up the creek + - uphill battle + - upper crust + - upset the applecart + - vain attempt + - vain effort + - vanquish the enemy + - vested interest + - waiting for the other shoe to drop + - wakeup call + - warm welcome + - watch your p's and q's + - watch your tongue + - watching the clock + - water under the bridge + - weather the storm + - weed them out + - week of Sundays + - went belly up + - wet behind the ears + - what goes around comes around + - what you see is what you get + - when it rains, it pours + - when push comes to shove + - when the cat's away + - when the going gets tough, the tough get going + - white as a sheet + - whole ball of wax + - whole hog + - whole nine yards + - wild goose chase + - will wonders never cease? + - wisdom of the ages + - wise as an owl + - wolf at the door + - words fail me + - work like a dog + - world weary + - worst nightmare + - worth its weight in gold + - wrong side of the bed + - yanking your chain + - yappy as a dog + - years young + - you are what you eat + - you can run but you can't hide + - you only live once + - you're the boss + - young and foolish + - young and vibrant diff --git a/.vale/styles/write-good/E-Prime.yml b/.vale/styles/write-good/E-Prime.yml new file mode 100644 index 0000000..074a102 --- /dev/null +++ b/.vale/styles/write-good/E-Prime.yml @@ -0,0 +1,32 @@ +extends: existence +message: "Try to avoid using '%s'." +ignorecase: true +level: suggestion +tokens: + - am + - are + - aren't + - be + - been + - being + - he's + - here's + - here's + - how's + - i'm + - is + - isn't + - it's + - she's + - that's + - there's + - they're + - was + - wasn't + - we're + - were + - weren't + - what's + - where's + - who's + - you're diff --git a/.vale/styles/write-good/Illusions.yml b/.vale/styles/write-good/Illusions.yml new file mode 100644 index 0000000..b4f1321 --- /dev/null +++ b/.vale/styles/write-good/Illusions.yml @@ -0,0 +1,11 @@ +extends: repetition +message: "'%s' is repeated!" +level: warning +alpha: true +action: + name: edit + params: + - truncate + - " " +tokens: + - '[^\s]+' diff --git a/.vale/styles/write-good/Passive.yml b/.vale/styles/write-good/Passive.yml new file mode 100644 index 0000000..f472cb9 --- /dev/null +++ b/.vale/styles/write-good/Passive.yml @@ -0,0 +1,183 @@ +extends: existence +message: "'%s' may be passive voice. Use active voice if you can." +ignorecase: true +level: warning +raw: + - \b(am|are|were|being|is|been|was|be)\b\s* +tokens: + - '[\w]+ed' + - awoken + - beat + - become + - been + - begun + - bent + - beset + - bet + - bid + - bidden + - bitten + - bled + - blown + - born + - bought + - bound + - bred + - broadcast + - broken + - brought + - built + - burnt + - burst + - cast + - caught + - chosen + - clung + - come + - cost + - crept + - cut + - dealt + - dived + - done + - drawn + - dreamt + - driven + - drunk + - dug + - eaten + - fallen + - fed + - felt + - fit + - fled + - flown + - flung + - forbidden + - foregone + - forgiven + - forgotten + - forsaken + - fought + - found + - frozen + - given + - gone + - gotten + - ground + - grown + - heard + - held + - hidden + - hit + - hung + - hurt + - kept + - knelt + - knit + - known + - laid + - lain + - leapt + - learnt + - led + - left + - lent + - let + - lighted + - lost + - made + - meant + - met + - misspelt + - mistaken + - mown + - overcome + - overdone + - overtaken + - overthrown + - paid + - pled + - proven + - put + - quit + - read + - rid + - ridden + - risen + - run + - rung + - said + - sat + - sawn + - seen + - sent + - set + - sewn + - shaken + - shaven + - shed + - shod + - shone + - shorn + - shot + - shown + - shrunk + - shut + - slain + - slept + - slid + - slit + - slung + - smitten + - sold + - sought + - sown + - sped + - spent + - spilt + - spit + - split + - spoken + - spread + - sprung + - spun + - stolen + - stood + - stridden + - striven + - struck + - strung + - stuck + - stung + - stunk + - sung + - sunk + - swept + - swollen + - sworn + - swum + - swung + - taken + - taught + - thought + - thrived + - thrown + - thrust + - told + - torn + - trodden + - understood + - upheld + - upset + - wed + - wept + - withheld + - withstood + - woken + - won + - worn + - wound + - woven + - written + - wrung diff --git a/.vale/styles/write-good/README.md b/.vale/styles/write-good/README.md new file mode 100644 index 0000000..fe806cb --- /dev/null +++ b/.vale/styles/write-good/README.md @@ -0,0 +1,27 @@ +Based on [write-good](https://github.com/btford/write-good). + +> Naive linter for English prose for developers who can't write good and wanna learn to do other stuff good too. + +```plaintext +The MIT License (MIT) + +Copyright (c) 2014 Brian Ford + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +```plaintext diff --git a/.vale/styles/write-good/So.yml b/.vale/styles/write-good/So.yml new file mode 100644 index 0000000..e57f099 --- /dev/null +++ b/.vale/styles/write-good/So.yml @@ -0,0 +1,5 @@ +extends: existence +message: "Don't start a sentence with '%s'." +level: error +raw: + - '(?:[;-]\s)so[\s,]|\bSo[\s,]' diff --git a/.vale/styles/write-good/ThereIs.yml b/.vale/styles/write-good/ThereIs.yml new file mode 100644 index 0000000..8b82e8f --- /dev/null +++ b/.vale/styles/write-good/ThereIs.yml @@ -0,0 +1,6 @@ +extends: existence +message: "Don't start a sentence with '%s'." +ignorecase: false +level: error +raw: + - '(?:[;-]\s)There\s(is|are)|\bThere\s(is|are)\b' diff --git a/.vale/styles/write-good/TooWordy.yml b/.vale/styles/write-good/TooWordy.yml new file mode 100644 index 0000000..275701b --- /dev/null +++ b/.vale/styles/write-good/TooWordy.yml @@ -0,0 +1,221 @@ +extends: existence +message: "'%s' is too wordy." +ignorecase: true +level: warning +tokens: + - a number of + - abundance + - accede to + - accelerate + - accentuate + - accompany + - accomplish + - accorded + - accrue + - acquiesce + - acquire + - additional + - adjacent to + - adjustment + - admissible + - advantageous + - adversely impact + - advise + - aforementioned + - aggregate + - aircraft + - all of + - all things considered + - alleviate + - allocate + - along the lines of + - already existing + - alternatively + - amazing + - ameliorate + - anticipate + - apparent + - appreciable + - as a matter of fact + - as a means of + - as far as I'm concerned + - as of yet + - as to + - as yet + - ascertain + - assistance + - at the present time + - at this time + - attain + - attributable to + - authorize + - because of the fact that + - belated + - benefit from + - bestow + - by means of + - by virtue of + - by virtue of the fact that + - cease + - close proximity + - commence + - comply with + - concerning + - consequently + - consolidate + - constitutes + - demonstrate + - depart + - designate + - discontinue + - due to the fact that + - each and every + - economical + - eliminate + - elucidate + - employ + - endeavor + - enumerate + - equitable + - equivalent + - evaluate + - evidenced + - exclusively + - expedite + - expend + - expiration + - facilitate + - factual evidence + - feasible + - finalize + - first and foremost + - for all intents and purposes + - for the most part + - for the purpose of + - forfeit + - formulate + - have a tendency to + - honest truth + - however + - if and when + - impacted + - implement + - in a manner of speaking + - in a timely manner + - in a very real sense + - in accordance with + - in addition + - in all likelihood + - in an effort to + - in between + - in excess of + - in lieu of + - in light of the fact that + - in many cases + - in my opinion + - in order to + - in regard to + - in some instances + - in terms of + - in the case of + - in the event that + - in the final analysis + - in the nature of + - in the near future + - in the process of + - inception + - incumbent upon + - indicate + - indication + - initiate + - irregardless + - is applicable to + - is authorized to + - is responsible for + - it is + - it is essential + - it seems that + - it was + - magnitude + - maximum + - methodology + - minimize + - minimum + - modify + - monitor + - multiple + - necessitate + - nevertheless + - not certain + - not many + - not often + - not unless + - not unlike + - notwithstanding + - null and void + - numerous + - objective + - obligate + - obtain + - on the contrary + - on the other hand + - one particular + - optimum + - overall + - owing to the fact that + - participate + - particulars + - pass away + - pertaining to + - point in time + - portion + - possess + - preclude + - previously + - prior to + - prioritize + - procure + - proficiency + - provided that + - purchase + - put simply + - readily apparent + - refer back + - regarding + - relocate + - remainder + - remuneration + - requirement + - reside + - residence + - retain + - satisfy + - shall + - should you wish + - similar to + - solicit + - span across + - strategize + - subsequent + - substantial + - successfully complete + - sufficient + - terminate + - the month of + - the point I am trying to make + - therefore + - time period + - took advantage of + - transmit + - transpire + - type of + - until such time as + - utilization + - utilize + - validate + - various different + - what I mean to say is + - whether or not + - with respect to + - with the exception of + - witnessed diff --git a/.vale/styles/write-good/Weasel.yml b/.vale/styles/write-good/Weasel.yml new file mode 100644 index 0000000..d1d90a7 --- /dev/null +++ b/.vale/styles/write-good/Weasel.yml @@ -0,0 +1,29 @@ +extends: existence +message: "'%s' is a weasel word!" +ignorecase: true +level: warning +tokens: + - clearly + - completely + - exceedingly + - excellent + - extremely + - fairly + - huge + - interestingly + - is a number + - largely + - mostly + - obviously + - quite + - relatively + - remarkably + - several + - significantly + - substantially + - surprisingly + - tiny + - usually + - various + - vast + - very diff --git a/.vale/styles/write-good/meta.json b/.vale/styles/write-good/meta.json new file mode 100644 index 0000000..a115d28 --- /dev/null +++ b/.vale/styles/write-good/meta.json @@ -0,0 +1,4 @@ +{ + "feed": "https://github.com/errata-ai/write-good/releases.atom", + "vale_version": ">=1.0.0" +} diff --git a/.woodpecker/Dockerfile b/.woodpecker/Dockerfile new file mode 100644 index 0000000..5086c87 --- /dev/null +++ b/.woodpecker/Dockerfile @@ -0,0 +1,45 @@ +# Custom Docker image for Woodpecker CI +# Pre-installs common tools to speed up CI runs +# +# Build: docker build -t your-registry/ci:latest -f .woodpecker/Dockerfile . +# Push: docker push your-registry/ci:latest +# +# Then update .woodpecker/ci.yml to use: image: your-registry/ci:latest + +FROM rust:latest + +# Install system dependencies +RUN apt-get update && apt-get install -y \ + shellcheck \ + curl \ + git \ + && rm -rf /var/lib/apt/lists/* + +# Install just +RUN curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to /usr/local/bin + +# Install Rust components +RUN rustup component add clippy rustfmt + +# Install Rust tools (pre-compiled to speed up CI) +RUN cargo install \ + cargo-audit \ + cargo-deny \ + cargo-sbom \ + nickel-lang-cli \ + nu \ + --locked + +# Set working directory +WORKDIR /workspace + +# Verify installations +RUN just --version && \ + cargo --version && \ + cargo audit --version && \ + cargo deny --version && \ + cargo sbom --version && \ + nickel --version && \ + nu --version + +CMD ["/bin/bash"] diff --git a/.woodpecker/Dockerfile.cross b/.woodpecker/Dockerfile.cross new file mode 100644 index 0000000..2b56cd8 --- /dev/null +++ b/.woodpecker/Dockerfile.cross @@ -0,0 +1,42 @@ +# Dockerfile for cross-platform compilation +# Supports building for multiple targets using docker + +FROM ubuntu:22.04 + +# Install build essentials +RUN apt-get update && apt-get install -y \ + build-essential \ + curl \ + git \ + pkg-config \ + && rm -rf /var/lib/apt/lists/* + +# Install Rust +RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable +ENV PATH="/root/.cargo/bin:${PATH}" + +# Install cross tool for cross-compilation +RUN cargo install cross --locked + +# Create workspace directory +WORKDIR /workspace + +# Copy entire project +COPY . . + +# Default build target +ARG TARGET=x86_64-unknown-linux-gnu +ENV BUILD_TARGET="${TARGET}" + +# Build command +RUN cross build --target "${BUILD_TARGET}" --release + +# Extract binaries to output directory +RUN mkdir -p /output/bin && \ + find target/"${BUILD_TARGET}"/release -maxdepth 1 -type f -executable -exec cp {} /output/bin/ \; + +# Create manifest +RUN echo "{ \"target\": \"${BUILD_TARGET}\", \"built\": \"$(date -u +'%Y-%m-%dT%H:%M:%SZ')\" }" > /output/BUILD_INFO.json + +# Default command +CMD ["/bin/bash"] diff --git a/.woodpecker/README.md b/.woodpecker/README.md new file mode 100644 index 0000000..ef0b6c6 --- /dev/null +++ b/.woodpecker/README.md @@ -0,0 +1,79 @@ +# Woodpecker CI Configuration + +Pipelines for Gitea/Forgejo + Woodpecker CI. + +## Files + +- **`ci.yml`** - Main CI pipeline (push, pull requests) +- **`Dockerfile`** - Custom CI image with pre-installed tools +- **`Dockerfile.cross`** - Cross-compilation image for multi-platform builds + +## Setup + +### 1. Activate Woodpecker CI + +Enable Woodpecker CI in your Gitea/Forgejo repository settings. + +### 2. (Optional) Build Custom Image + +Speeds up CI by pre-installing tools (~5 min faster per run). + +```bash +# Build CI image +docker build -t your-registry/ci:latest -f .woodpecker/Dockerfile . + +# Push to your registry +docker push your-registry/ci:latest + +# Update .woodpecker/ci.yml +# Change: image: rust:latest +# To: image: your-registry/ci:latest +``` + +### 3. Cross-Compilation Setup + +For multi-platform builds: + +```bash +# Build cross-compilation image +docker build -t your-registry/ci-cross:latest -f .woodpecker/Dockerfile.cross . + +# Push to registry +docker push your-registry/ci-cross:latest +``` + +## CI Pipeline (`ci.yml`) + +**Triggers**: Push to `main`/`develop`, Pull Requests + +**Jobs**: + +1. Lint (Rust, Bash, Nickel, Nushell, Markdown) - Parallel +2. Test (all features) +3. Build (release) +4. Security audit +5. License compliance check + +**Duration**: ~15-20 minutes (without custom image), ~10-15 minutes (with custom image) + +## Triggering Pipelines + +```bash +# CI pipeline (automatic on push/PR) +git push origin main +``` + +## Viewing Results + +- **Gitea/Forgejo**: Repository β†’ Actions β†’ Pipeline runs +- **Woodpecker UI**: + +## Differences from GitHub Actions + +| Feature | GitHub Actions | Woodpecker CI | +|---------|---------------|---------------| +| Matrix builds | βœ… 3 OS | ❌ Linux only* | +| Caching | βœ… Built-in | ⚠️ Server-side** | + +\* Multi-OS builds require multiple Woodpecker agents +\*\* Configure in Woodpecker server settings diff --git a/.woodpecker/ci-advanced.yml b/.woodpecker/ci-advanced.yml new file mode 100644 index 0000000..3bda3c4 --- /dev/null +++ b/.woodpecker/ci-advanced.yml @@ -0,0 +1,168 @@ +# Woodpecker CI - Advanced Pipeline +# Multi-platform builds, coverage, benchmarks, and security scanning + +when: + event: [push, pull_request, manual] + branch: + - main + - develop + +matrix: + PLATFORM: + - linux/amd64 + - linux/arm64 + +steps: + # === LINTING (Parallel) === + + lint-rust: + 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 rustfmt + - cargo fmt --all -- --check + - cargo clippy --all-targets --all-features -- -D warnings + environment: + CARGO_TERM_COLOR: always + + 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: + image: rust:latest + commands: + - cargo install nickel-lang-cli --locked + - find . -name '*.ncl' -type f ! -path './target/*' -exec nickel typecheck {} \; + + lint-nushell: + image: rust:latest + commands: + - cargo install nu --locked + - find . -name '*.nu' -type f ! -path './target/*' -exec nu --ide-check 100 {} \; + + lint-markdown: + image: node:alpine + commands: + - npm install -g markdownlint-cli2 + - markdownlint-cli2 '**/*.md' '#node_modules' '#target' + + # === TESTING === + + test: + image: rust:latest + commands: + - cargo test --workspace --all-features --no-fail-fast + depends_on: + - lint-rust + - lint-bash + - lint-nickel + - lint-nushell + - lint-markdown + environment: + RUST_BACKTRACE: 1 + + # === CODE COVERAGE === + + coverage: + image: rust:latest + commands: + - cargo install cargo-tarpaulin --locked + - cargo tarpaulin --workspace --all-features --out Xml --output-dir coverage + - | + if [ -f coverage/cobertura.xml ]; then + echo "Coverage report generated successfully" + fi + depends_on: + - test + when: + event: [push, pull_request] + branch: [main, develop] + + # === BUILD (Multi-platform) === + + build-native: + image: rust:latest + commands: + - cargo build --release --workspace + - ls -lh target/release/ + depends_on: + - test + + build-cross: + image: rust:latest + commands: + - cargo install cross --locked + - cross build --target x86_64-unknown-linux-musl --release + - cross build --target aarch64-unknown-linux-musl --release + depends_on: + - test + when: + matrix: + PLATFORM: linux/amd64 + + # === BENCHMARKS === + + benchmark: + image: rust:latest + commands: + - rustup toolchain install nightly + - cargo +nightly bench --workspace --no-fail-fast + - | + if [ -d target/criterion ]; then + echo "Benchmark results available in target/criterion" + fi + depends_on: + - build-native + when: + event: pull_request + + # === SECURITY AUDITS === + + security-audit: + image: rust:latest + commands: + - cargo install cargo-audit --locked + - cargo audit --deny warnings --deny unmaintained --deny unsound + depends_on: + - lint-rust + + license-check: + image: rust:latest + commands: + - cargo install cargo-deny --locked + - cargo deny check licenses advisories sources bans + depends_on: + - lint-rust + + dependency-check: + image: rust:latest + commands: + - cargo install cargo-outdated --locked + - cargo outdated --exit-code 1 --root-deps-only + depends_on: + - lint-rust + when: + event: manual + + # === SONARQUBE ANALYSIS === + + sonarqube: + image: sonarsource/sonar-scanner-cli:latest + commands: + - | + sonar-scanner \ + -Dsonar.projectKey=${CI_REPO_NAME} \ + -Dsonar.sources=. \ + -Dsonar.host.url=${SONAR_HOST_URL} \ + -Dsonar.token=${SONAR_TOKEN} \ + -Dsonar.rust.clippy.reportPaths=clippy-report.json \ + -Dsonar.coverageReportPaths=coverage/cobertura.xml + depends_on: + - coverage + secrets: [sonar_host_url, sonar_token] + when: + event: [push, pull_request] + branch: [main, develop] diff --git a/.woodpecker/ci.yml b/.woodpecker/ci.yml new file mode 100644 index 0000000..be8aba9 --- /dev/null +++ b/.woodpecker/ci.yml @@ -0,0 +1,84 @@ +# Woodpecker CI Pipeline +# Equivalent to GitHub Actions CI workflow +# Generated by dev-system/ci + +when: + event: [push, pull_request, manual] + branch: + - main + - develop + +steps: + # === LINTING === + + lint-rust: + 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 + + 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: + image: rust:latest + commands: + - cargo install nickel-lang-cli --locked + - find . -name '*.ncl' -type f ! -path './target/*' -exec nickel typecheck {} \; + + lint-nushell: + image: rust:latest + commands: + - cargo install nu --locked + - find . -name '*.nu' -type f ! -path './target/*' -exec nu --ide-check 100 {} \; + + lint-markdown: + image: node:alpine + commands: + - npm install -g markdownlint-cli2 + - markdownlint-cli2 '**/*.md' '#node_modules' '#target' + + # === TESTING === + + test: + image: rust:latest + commands: + - cargo test --workspace --all-features + depends_on: + - lint-rust + - lint-bash + - lint-nickel + - lint-nushell + - lint-markdown + + # === 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: + image: rust:latest + commands: + - cargo install cargo-deny --locked + - cargo deny check licenses advisories + depends_on: + - lint-rust diff --git a/.yamllint-ci.yml b/.yamllint-ci.yml new file mode 100644 index 0000000..3575afe --- /dev/null +++ b/.yamllint-ci.yml @@ -0,0 +1,18 @@ +extends: default + +rules: + line-length: + max: 200 # More reasonable for infrastructure code + comments: + min-spaces-from-content: 1 # Allow single space before comments + document-start: disable # Cloud-init files don't need --- start + truthy: + allowed-values: ["true", "false", "yes", "no", "on", "off"] # Allow cloud-init and GitHub Actions common values + +# Ignore cloud-init files for comment spacing since #cloud-config is a special directive +# Ignore directories with generated/runtime files +ignore: | + **/cloud-init.yml + build/** + data/** + envs/** diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..8e1cabd --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,131 @@ +# Provisioning Repository - Changes + +**Date**: 2026-01-08 +**Repository**: provisioning (standalone, nickel branch) +**Changes**: Nickel IaC migration complete - Legacy KCL and config cleanup + +--- + +## πŸ“‹ 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. + +--- + +## πŸ“ Changes by Directory + +### βœ… REMOVED (Legacy KCL Ecosystem) + +- **config/** - Deprecated TOML configs (config.defaults.toml, kms.toml, plugins.toml, etc.) +- **config/cedar-policies/** - Legacy Cedar policies (moved to Nickel schemas) +- **config/templates/** - Old Jinja2 templates (replaced by Nickel generator/) +- **config/installer-examples/** - KCL-based examples +- **docs/src/** - Legacy documentation (full migration to provisioning/docs/src/) +- **kcl/** - Complete removal (all workspaces migrated to Nickel) +- **tools/kcl-packager.nu** - KCL packaging system + +### βœ… ADDED (Nickel IaC & New Structure) + +- **.cargo/** - Rust build configuration (clippy settings, rustfmt.toml) +- **.github/** - GitHub Actions CI/CD workflows +- **schemas/** - Nickel schema definitions (primary IaC format) + - main.ncl, provider-aws.ncl, provider-local.ncl, provider-upcloud.ncl + - Infrastructure, deployment, services, operations schemas +- **docs/src/architecture/adr/** - ADR updates for Nickel migration + - adr-010-configuration-format-strategy.md + - adr-011-nickel-migration.md + - adr-012-nushell-nickel-plugin-cli-wrapper.md + +### πŸ“ UPDATED (Core System) + +- **provisioning/docs/src/** - Comprehensive product documentation + - API reference, architecture, guides, operations, security, testing + - Nickel configuration guide with examples + - Migrated from legacy KCL documentation + +- **core/** - Updated with Nickel integration + - Scripts, plugins, CLI updated for Nickel schema parsing + +- **justfiles/** - Added ci.just for Nickel-aware CI/CD +- **README.md** - Complete restructure for Nickel-first approach +- **.gitignore** - Updated to ignore Nickel build artifacts + +--- + +## πŸ“Š Change Statistics + +| Category | Removed | Added | Modified | +|----------|---------|-------|----------| +| Configuration | 50+ | 10+ | 3 | +| Documentation | 150+ | 200+ | 40+ | +| Infrastructure | 1 (kcl/) | - | - | +| Plugins | 1 | - | 5+ | +| Build System | 5 | 8+ | 3 | +| **Total** | **~220 files** | **~250 files** | **50+ files** | + +## ⚠️ Breaking Changes + +1. **KCL Sunset**: All KCL infrastructure code removed. Migrate workspaces using `nickel-kcl-bridge` or rewrite directly in Nickel. +2. **Config Format**: TOML configuration files moved to schema-driven Nickel system. Legacy config loading deprecated. +3. **Documentation**: Old KCL/legacy docs removed. Use `provisioning/docs/` for current product documentation. +4. **Plugin System**: Updated to Nickel-aware plugin API. Legacy Nushell plugins require recompilation. + +## πŸ”§ Migration Path + +```bash +# For existing workspaces: +provisioning workspace migrate --from-kcl + +# For custom configs: +nickel eval --format json | jq '.' +``` + +## ✨ Key Features + +- **Type-Safe**: Nickel schemas eliminate silent config errors +- **Composable**: Modular infrastructure definitions with lazy evaluation +- **Documented**: Schema validation built-in, IDE support via LSP +- **Validated**: All imports pre-checked, circular dependencies prevented +- **Bridge Available**: `nickel-kcl-bridge` for gradual KCLβ†’Nickel migration + +--- + +## πŸ“ Implementation Details + +### Nickel Schema System + +- **Three-tier architecture**: infrastructure, operations, deployment +- **Lazy evaluation**: Efficient resource binding and composition +- **Record merging**: Clean override patterns without duplication +- **Type validation**: LSP-aware with IDE auto-completion +- **Generator system**: Nickel-based dynamic configuration at runtime + +### Documentation Reorganization + +- **provisioning/docs/src/** (200+ files) - Customer-facing product docs +- **docs/src/** (20-30 files) - Architecture and development guidelines +- **.coder/** - Session files and implementation records +- Separation of concerns: Product docs isolated from session artifacts + +### CI/CD Integration + +- GitHub Actions workflows for Rust, Nickel, Nushell +- Automated schema validation pre-commit +- Cross-platform testing (Linux, macOS) +- Build artifact caching for fast iteration + +--- + +## ⚠️ Compatibility Notes + +**Breaking**: KCL workspaces require migration to Nickel. Use schema-aware tooling for validation. + +**Migration support**: `nickel-kcl-bridge` tool and guides available in `provisioning/docs/src/development/`. + +**Legacy configs**: Old TOML files no longer loaded. Migrate to Nickel schema format via CLI tool. + +--- + +**Status**: Nickel migration complete. System is production-ready. +**Date**: 2026-01-08 +**Branch**: nickel diff --git a/README.md b/README.md index b9e4b56..7ffc5de 100644 --- a/README.md +++ b/README.md @@ -37,26 +37,26 @@ Declarative Infrastructure as Code (IaC) platform providing: - **Modular, extensible architecture**: cloud providers, task services, clusters, workspaces - **Multi-cloud abstraction layer** with unified API (UpCloud, AWS, local infrastructure) - **High-performance state management**: - - Graph database backend for complex relationships - - Real-time state tracking and queries - - Multi-model data storage (document, graph, relational) + - Graph database backend for complex relationships + - Real-time state tracking and queries + - Multi-model data storage (document, graph, relational) - **Enterprise security stack**: - - Encrypted configuration and secrets management - - Cosmian KMS integration for confidential key management - - Cedar policy engine for fine-grained access control - - Authorization and permissions control via platform services - - Compliance checking and policy enforcement - - Anomaly detection for security monitoring - - Audit logging and compliance tracking + - Encrypted configuration and secrets management + - Cosmian KMS integration for confidential key management + - Cedar policy engine for fine-grained access control + - Authorization and permissions control via platform services + - Compliance checking and policy enforcement + - Anomaly detection for security monitoring + - Audit logging and compliance tracking - **Hybrid orchestration**: Rust-based performance layer + scripting flexibility - **Production-ready features**: - - Batch workflows with dependency resolution - - Checkpoint recovery and automatic rollback - - Parallel execution with state management + - Batch workflows with dependency resolution + - Checkpoint recovery and automatic rollback + - Parallel execution with state management - **Adaptable deployment modes**: - - Interactive TUI for guided setup - - Headless CLI for scripted automation - - Unattended mode for CI/CD pipelines + - Interactive TUI for guided setup + - Headless CLI for scripted automation + - Unattended mode for CI/CD pipelines - **Hierarchical configuration system** with inheritance and overrides ### What It Does @@ -80,14 +80,18 @@ Declarative Infrastructure as Code (IaC) platform providing: **Problem**: Each cloud provider has different APIs, tools, and workflows. -**Solution**: Unified abstraction layer with provider-agnostic interfaces. Write configuration once, deploy anywhere. +**Solution**: Unified abstraction layer with provider-agnostic interfaces. Write configuration once, deploy anywhere using Nickel schemas. -```kcl +```nickel # Same configuration works on UpCloud, AWS, or local infrastructure -server: Server { - name = "web-01" - plan = "medium" # Abstract size, provider-specific translation - provider = "upcloud" # Switch to "aws" or "local" as needed +{ + servers = [ + { + name = "web-01" + plan = "medium" # Abstract size, provider-specific translation + provider = "upcloud" # Switch to "aws" or "local" as needed + } + ] } ``` @@ -95,11 +99,13 @@ server: Server { **Problem**: Infrastructure components have complex dependencies (Kubernetes needs containerd, Cilium needs Kubernetes, etc.). -**Solution**: Automatic dependency resolution with topological sorting and health checks. +**Solution**: Automatic dependency resolution with topological sorting and health checks via Nickel schemas. -```kcl +```nickel # Provisioning resolves: containerd β†’ etcd β†’ kubernetes β†’ cilium -taskservs = ["cilium"] # Automatically installs all dependencies +{ + taskservs = ["cilium"] # Automatically installs all dependencies +} ``` #### 3. **Configuration Sprawl** @@ -108,21 +114,22 @@ taskservs = ["cilium"] # Automatically installs all dependencies **Solution**: Hierarchical configuration system with 476+ config accessors replacing 200+ ENV variables. -``` +```plaintext Defaults β†’ User β†’ Project β†’ Infrastructure β†’ Environment β†’ Runtime -``` +```plaintext #### 4. **Imperative Scripts** **Problem**: Brittle shell scripts that don't handle failures, don't support rollback, hard to maintain. -**Solution**: Declarative KCL configurations with validation, type safety, and automatic rollback. +**Solution**: Declarative Nickel configurations with validation, type safety, lazy evaluation, and automatic rollback. #### 5. **Lack of Visibility** **Problem**: No insight into what's happening during deployment, hard to debug failures. **Solution**: + - Real-time workflow monitoring - Comprehensive logging system - Web-based control center @@ -153,6 +160,7 @@ Providers implement a common interface, making infrastructure code portable. Reusable infrastructure components that can be installed on servers. **Categories**: + - **Container Runtimes** - containerd, Docker, Podman, crun, runc, youki - **Orchestration** - Kubernetes, etcd, CoreDNS - **Networking** - Cilium, Flannel, Calico, ip-aliases @@ -163,6 +171,7 @@ Reusable infrastructure components that can be installed on servers. - **Development** - Gitea, Radicle, ORAS Each task service includes: + - Version management - Dependency declarations - Health checks @@ -174,11 +183,13 @@ Each task service includes: Complete infrastructure deployments combining servers and task services. **Examples**: + - **Kubernetes Cluster** - HA control plane + worker nodes + CNI + storage - **Database Cluster** - Replicated PostgreSQL with backup - **Build Infrastructure** - BuildKit + container registry + CI/CD Clusters handle: + - Multi-node coordination - Service distribution - High availability @@ -188,7 +199,7 @@ Clusters handle: Isolated environments for different projects or deployment stages. -``` +```plaintext workspace_librecloud/ # Production workspace β”œβ”€β”€ infra/ # Infrastructure definitions β”œβ”€β”€ config/ # Workspace configuration @@ -198,24 +209,27 @@ workspace_librecloud/ # Production workspace workspace_dev/ # Development workspace β”œβ”€β”€ infra/ └── config/ -``` +```plaintext Switch between workspaces with single command: + ```bash provisioning workspace switch librecloud -``` +```plaintext ### 5. **Workflows** Coordinated sequences of operations with dependency management. **Types**: + - **Server Workflows** - Create/delete/update servers - **TaskServ Workflows** - Install/remove infrastructure services - **Cluster Workflows** - Deploy/scale complete clusters - **Batch Workflows** - Multi-cloud parallel operations **Features**: + - Dependency resolution - Parallel execution - Checkpoint recovery @@ -228,7 +242,7 @@ Coordinated sequences of operations with dependency management. ### System Components -``` +```plaintext β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ User Interface Layer β”‚ β”‚ β€’ CLI (provisioning command) β”‚ @@ -266,17 +280,17 @@ Coordinated sequences of operations with dependency management. β”‚ β€’ Kubernetes Clusters β”‚ β”‚ β€’ Running Services β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ -``` +```plaintext ### Directory Structure -``` +```plaintext project-provisioning/ β”œβ”€β”€ provisioning/ # Core provisioning system β”‚ β”œβ”€β”€ core/ # Core engine and libraries β”‚ β”‚ β”œβ”€β”€ cli/ # Command-line interface β”‚ β”‚ β”œβ”€β”€ nulib/ # Core Nushell libraries -β”‚ β”‚ β”œβ”€β”€ plugins/ # System plugins +β”‚ β”‚ β”œβ”€β”€ plugins/ # System plugins (Rust native) β”‚ β”‚ └── scripts/ # Utility scripts β”‚ β”‚ β”‚ β”œβ”€β”€ extensions/ # Extensible components @@ -293,10 +307,19 @@ project-provisioning/ β”‚ β”‚ β”œβ”€β”€ oci-registry/ # OCI registry for extensions β”‚ β”‚ └── installer/ # Platform installer (TUI + CLI) β”‚ β”‚ -β”‚ β”œβ”€β”€ kcl/ # KCL configuration schemas -β”‚ β”œβ”€β”€ config/ # Configuration files -β”‚ β”œβ”€β”€ templates/ # Template files -β”‚ └── tools/ # Build and distribution tools +β”‚ β”œβ”€β”€ schemas/ # Nickel schema definitions (PRIMARY IaC) +β”‚ β”‚ β”œβ”€β”€ main.ncl # Main infrastructure schema +β”‚ β”‚ β”œβ”€β”€ providers/ # Provider-specific schemas +β”‚ β”‚ β”œβ”€β”€ infrastructure/ # Infra definitions +β”‚ β”‚ β”œβ”€β”€ deployment/ # Deployment schemas +β”‚ β”‚ β”œβ”€β”€ services/ # Service schemas +β”‚ β”‚ β”œβ”€β”€ operations/ # Operations schemas +β”‚ β”‚ └── generator/ # Runtime schema generation +β”‚ β”‚ +β”‚ β”œβ”€β”€ docs/ # Product documentation (mdBook) +β”‚ β”œβ”€β”€ config/ # Configuration examples +β”‚ β”œβ”€β”€ tools/ # Build and distribution tools +β”‚ └── justfiles/ # Just recipes for common tasks β”‚ β”œβ”€β”€ workspace/ # User workspaces and data β”‚ β”œβ”€β”€ infra/ # Infrastructure definitions @@ -304,58 +327,64 @@ project-provisioning/ β”‚ β”œβ”€β”€ extensions/ # User extensions β”‚ └── runtime/ # Runtime data and state β”‚ -└── docs/ # Documentation - β”œβ”€β”€ user/ # User guides - β”œβ”€β”€ api/ # API documentation - β”œβ”€β”€ architecture/ # Architecture docs - └── development/ # Development guides +β”œβ”€β”€ docs/ # Architecture & Development docs +β”‚ β”œβ”€β”€ architecture/ # System design and ADRs +β”‚ └── development/ # Development guidelines +β”‚ +└── .github/ # CI/CD workflows + └── workflows/ # GitHub Actions (Rust, Nickel, Nushell) ``` ### Platform Services #### 1. **Orchestrator** (`platform/orchestrator/`) + - **Language**: Rust + Nushell - **Purpose**: Workflow execution, task scheduling, state management - **Features**: - - File-based persistence - - Priority processing - - Retry logic with exponential backoff - - Checkpoint-based recovery - - REST API endpoints + - File-based persistence + - Priority processing + - Retry logic with exponential backoff + - Checkpoint-based recovery + - REST API endpoints #### 2. **Control Center** (`platform/control-center/`) + - **Language**: Web UI + Backend API - **Purpose**: Web-based infrastructure management - **Features**: - - Dashboard views - - Real-time monitoring - - Interactive deployments - - Log viewing + - Dashboard views + - Real-time monitoring + - Interactive deployments + - Log viewing #### 3. **MCP Server** (`platform/mcp-server/`) + - **Language**: Nushell - **Purpose**: Model Context Protocol integration for AI assistance - **Features**: - - 7 AI-powered settings tools - - Intelligent config completion - - Natural language infrastructure queries + - 7 AI-powered settings tools + - Intelligent config completion + - Natural language infrastructure queries #### 4. **OCI Registry** (`platform/oci-registry/`) + - **Purpose**: Extension distribution and versioning - **Features**: - - Task service packages - - Provider packages - - Cluster templates - - Workflow definitions + - Task service packages + - Provider packages + - Cluster templates + - Workflow definitions #### 5. **Installer** (`platform/installer/`) + - **Language**: Rust (Ratatui TUI) + Nushell - **Purpose**: Platform installation and setup - **Features**: - - Interactive TUI mode - - Headless CLI mode - - Unattended CI/CD mode - - Configuration generation + - Interactive TUI mode + - Headless CLI mode + - Unattended CI/CD mode + - Configuration generation --- @@ -442,9 +471,9 @@ Three native Rust plugins providing 10-50x performance improvements over HTTP AP - **Three Native Plugins**: auth, KMS, orchestrator - **Performance Gains**: - - KMS operations: ~5ms vs ~50ms (10x faster) - - Orchestrator queries: ~1ms vs ~30ms (30x faster) - - Auth verification: ~10ms vs ~50ms (5x faster) + - KMS operations: ~5ms vs ~50ms (10x faster) + - Orchestrator queries: ~1ms vs ~30ms (30x faster) + - Auth verification: ~10ms vs ~50ms (5x faster) - **OS-Native Keyring**: macOS Keychain, Linux Secret Service, Windows Credential Manager - **KMS Backends**: RustyVault, Age, AWS KMS, Vault, Cosmian - **Graceful Fallback**: Automatic fallback to HTTP if plugins not installed @@ -459,13 +488,13 @@ Enterprise-grade security with 39,699 lines across 12 components. - **API**: 83+ REST endpoints, 111+ CLI commands - **Standards**: GDPR, SOC2, ISO 27001 compliance - **Key Features**: - - RS256 authentication with Argon2id hashing - - Policy-as-code with hot reload - - Multi-factor authentication (TOTP + WebAuthn/FIDO2) - - Dynamic secrets (AWS STS, SSH keys) with TTL - - 5 KMS backends with envelope encryption - - 7-year audit retention with 5 export formats - - Multi-party break-glass approval + - RS256 authentication with Argon2id hashing + - Policy-as-code with hot reload + - Multi-factor authentication (TOTP + WebAuthn/FIDO2) + - Dynamic secrets (AWS STS, SSH keys) with TTL + - 5 KMS backends with envelope encryption + - 7-year audit retention with 5 export formats + - Multi-party break-glass approval --- @@ -475,10 +504,10 @@ Enterprise-grade security with 39,699 lines across 12 components. | Technology | Version | Purpose | Why | |------------|---------|---------|-----| -| **Nushell** | 0.109.0+ | Primary shell and scripting language | Structured data pipelines, cross-platform, modern built-in parsers (JSON/YAML/TOML) | -| **KCL** | 0.11.3+ | Configuration language | Type safety, schema validation, immutability, constraint checking | +| **Nickel** | Latest | PRIMARY - Infrastructure-as-code language | Type-safe schemas, lazy evaluation, LSP support, composable records, gradual validation | +| **Nushell** | 0.109.0+ | Scripting and task automation | Structured data pipelines, cross-platform, modern built-in parsers (JSON/YAML/TOML) | | **Rust** | Latest | Platform services (orchestrator, control-center, installer) | Performance, memory safety, concurrency, reliability | -| **Tera** | Latest | Template engine | Jinja2-like syntax, configuration file rendering, variable interpolation, filters and functions | +| **KCL** | DEPRECATED | Legacy configuration (fully replaced by Nickel) | Migration bridge available; use Nickel for new work | ### Data & State Management @@ -528,49 +557,54 @@ Enterprise-grade security with 39,699 lines across 12 components. ### Data Flow -``` -1. User defines infrastructure in KCL +```plaintext +1. User defines infrastructure in Nickel schemas ↓ -2. CLI loads configuration (hierarchical) +2. Nickel evaluates with type validation and lazy evaluation ↓ -3. Configuration validated against schemas +3. CLI loads configuration (hierarchical merging) ↓ -4. Workflow created with operations +4. Configuration validated against provider schemas ↓ -5. Orchestrator receives workflow +5. Workflow created with operations ↓ -6. Dependencies resolved (topological sort) +6. Orchestrator receives workflow ↓ -7. Operations executed in order +7. Dependencies resolved (topological sort) ↓ -8. Providers handle cloud operations +8. Operations executed in order (parallel where possible) ↓ -9. Task services installed on servers +9. Providers handle cloud operations ↓ -10. State persisted and monitored +10. Task services installed on servers + ↓ +11. State persisted and monitored ``` ### Example Workflow: Deploy Kubernetes Cluster -**Step 1**: Define infrastructure in KCL +**Step 1**: Define infrastructure in Nickel -```kcl -# infra/my-cluster.k -import provisioning.settings as cfg - -settings: cfg.Settings = { - infra = { - name = "my-cluster" - provider = "upcloud" - } +```nickel +# schemas/my-cluster.ncl +{ + metadata = { + name = "my-cluster" + provider = "upcloud" + environment = "production" + } + infrastructure = { servers = [ - {name = "control-01", plan = "medium", role = "control"} - {name = "worker-01", plan = "large", role = "worker"} - {name = "worker-02", plan = "large", role = "worker"} + {name = "control-01", plan = "medium", role = "control"} + {name = "worker-01", plan = "large", role = "worker"} + {name = "worker-02", plan = "large", role = "worker"} ] + } + services = { taskservs = ["kubernetes", "cilium", "rook-ceph"] + } } ``` @@ -578,11 +612,11 @@ settings: cfg.Settings = { ```bash provisioning server create --infra my-cluster -``` +```plaintext **Step 3**: Provisioning executes workflow -``` +```plaintext 1. Create workflow: "deploy-my-cluster" 2. Resolve dependencies: - containerd (required by kubernetes) @@ -603,19 +637,19 @@ provisioning server create --infra my-cluster 4. Checkpoint after each step 5. Monitor health checks 6. Report completion -``` +```plaintext **Step 4**: Verify deployment ```bash provisioning cluster status my-cluster -``` +```plaintext ### Configuration Hierarchy Configuration values are resolved through a hierarchy: -``` +```plaintext 1. System Defaults (provisioning/config/config.defaults.toml) ↓ (overridden by) 2. User Preferences (~/.config/provisioning/user_config.yaml) @@ -627,7 +661,7 @@ Configuration values are resolved through a hierarchy: 5. Environment Config (workspace/config/prod-defaults.toml) ↓ (overridden by) 6. Runtime Flags (--flag value) -``` +```plaintext **Example**: @@ -646,7 +680,7 @@ default_plan = "large" # Overrides user preference # Runtime provisioning server create --plan xlarge # Overrides everything -``` +```plaintext --- @@ -662,7 +696,7 @@ provisioning cluster create k8s-prod --provider upcloud # AWS cluster (same config) provisioning cluster create k8s-prod --provider aws -``` +```plaintext ### 2. **Development β†’ Staging β†’ Production Pipeline** @@ -680,7 +714,7 @@ provisioning cluster create app-stack # Production (HA, larger resources) provisioning workspace switch prod provisioning cluster create app-stack -``` +```plaintext ### 3. **Infrastructure as Code Testing** @@ -696,41 +730,43 @@ provisioning test env run # Cleanup provisioning test env cleanup -``` +```plaintext ### 4. **Batch Multi-Region Deployment** -Deploy to multiple regions in parallel. +Deploy to multiple regions in parallel using Nickel batch workflows. -```kcl -# workflows/multi-region.k -batch_workflow: BatchWorkflow = { +```nickel +# schemas/batch/multi-region.ncl +{ + batch_workflow = { operations = [ - { - id = "eu-cluster" - type = "cluster" - region = "eu-west-1" - cluster = "app-stack" - } - { - id = "us-cluster" - type = "cluster" - region = "us-east-1" - cluster = "app-stack" - } - { - id = "asia-cluster" - type = "cluster" - region = "ap-south-1" - cluster = "app-stack" - } + { + id = "eu-cluster" + type = "cluster" + region = "eu-west-1" + cluster = "app-stack" + } + { + id = "us-cluster" + type = "cluster" + region = "us-east-1" + cluster = "app-stack" + } + { + id = "asia-cluster" + type = "cluster" + region = "ap-south-1" + cluster = "app-stack" + } ] parallel_limit = 3 # All at once + } } ``` ```bash -provisioning batch submit workflows/multi-region.k +provisioning batch submit schemas/batch/multi-region.ncl provisioning batch monitor ``` @@ -746,7 +782,7 @@ provisioning workspace switch prod provisioning cluster create --infra backup-restore --wait # All services restored with same configuration -``` +```plaintext ### 6. **CI/CD Integration** @@ -770,7 +806,7 @@ deploy-production: script: - provisioning workspace switch prod - provisioning cluster create app-stack --yes -``` +```plaintext --- @@ -779,35 +815,56 @@ deploy-production: ### Quick Start 1. **Install Prerequisites** + ```bash - # Install Nushell + # Install Nushell (0.109.0+) brew install nushell # macOS - # Install KCL - brew install kcl-lang/tap/kcl # macOS + # Install Nickel (required for IaC) + brew install nickel # macOS or from source - # Install SOPS (optional, for secrets) + # Install SOPS (optional, for encrypted secrets) brew install sops ``` 2. **Add CLI to PATH** + ```bash ln -sf "$(pwd)/provisioning/core/cli/provisioning" /usr/local/bin/provisioning ``` 3. **Initialize Workspace** + ```bash provisioning workspace init my-project + cd my-project ``` -4. **Configure Provider** +4. **Define Infrastructure (Nickel)** + ```bash - # Edit workspace config - provisioning sops workspace/config/provisioning.yaml + # Create workspace infrastructure schema + cat > workspace/infra/my-cluster.ncl <<'EOF' + { + metadata.name = "my-cluster" + metadata.provider = "upcloud" + + infrastructure.servers = [ + {name = "control-01", plan = "medium"} + {name = "worker-01", plan = "large"} + ] + + services.taskservs = ["kubernetes", "cilium"] + } + EOF ``` 5. **Deploy Infrastructure** + ```bash + # Validate configuration + provisioning config validate + # Check what will be created provisioning server create --check @@ -821,12 +878,14 @@ deploy-production: ### Learning Path 1. **Start with Guides** + ```bash provisioning sc # Quick reference provisioning guide from-scratch # Complete walkthrough ``` 2. **Explore Examples** + ```bash ls provisioning/examples/ ``` @@ -838,6 +897,7 @@ deploy-production: - [Batch Workflows](.claude/features/batch-workflow-system.md) 4. **Try Test Environments** + ```bash provisioning test quick kubernetes provisioning test quick postgres @@ -852,72 +912,76 @@ deploy-production: ## Documentation Index -### User Documentation -- **[Quick Start Guide](docs/user/quickstart.md)** - Get started in 10 minutes -- **[Command Reference](docs/user/command-reference.md)** - Complete CLI reference -- **[Configuration Guide](docs/user/configuration.md)** - Configuration system details -- **[Workspace Guide](docs/user/workspace-guide.md)** - Workspace management -- **[Test Environment Guide](docs/user/test-environment-guide.md)** - Testing infrastructure -- **[Plugin Integration Guide](docs/user/PLUGIN_INTEGRATION_GUIDE.md)** - Native plugins setup and usage -- **[Authentication Guide](docs/user/AUTHENTICATION_LAYER_GUIDE.md)** - JWT authentication and MFA -- **[Config Encryption Guide](docs/user/CONFIG_ENCRYPTION_GUIDE.md)** - KMS and secrets management +### User & Operations Guides -### Architecture Documentation -- **[Core Engine](provisioning/core/README.md)** - Core component overview -- **[CLI Architecture](.claude/features/cli-architecture.md)** - CLI design and shortcuts -- **[Configuration System](.claude/features/configuration-system.md)** - Config hierarchy -- **[Batch Workflows](.claude/features/batch-workflow-system.md)** - Batch operations -- **[Orchestrator](.claude/features/orchestrator-architecture.md)** - Workflow execution -- **[Workspace Switching](.claude/features/workspace-switching.md)** - Multi-workspace -- **[Security System](.claude/features/security-system.md)** - Enterprise security architecture -- **[Nushell Plugins](.claude/features/nushell-plugins.md)** - Plugin integration and performance +See **[provisioning/docs/src/](provisioning/docs/src/)** for comprehensive documentation: -### Development Documentation -- **[Contributing Guide](docs/development/CONTRIBUTING.md)** - How to contribute -- **[Nushell Patterns](.claude/best_nushell_code.md)** - Nushell best practices -- **[KCL Patterns](.claude/kcl_idiomatic_patterns.md)** - KCL idiomatic code -- **[Extension Development](docs/development/extensions.md)** - Create extensions +- **Quick Start** - Get started in 10 minutes +- **Command Reference** - Complete CLI command reference +- **Nickel Configuration Guide** - IaC language and patterns +- **Workspace Management** - Multi-workspace guide +- **Test Environment Guide** - Testing infrastructure with containers +- **Plugin Integration** - Native Rust plugins (10-50x faster) +- **Security System** - Authentication, MFA, KMS, Cedar policies +- **Operations** - Deployment, monitoring, incident response -### API Documentation -- **[REST API](docs/api/rest-api.md)** - HTTP endpoints -- **[Nushell API](docs/api/nushell-api.md)** - Library functions -- **[Provider API](docs/api/provider-api.md)** - Provider interface +### Architecture & Design Decisions + +See **[docs/src/architecture/](docs/src/architecture/)** for design patterns: + +- **System Architecture** - Multi-layer design +- **ADRs (Architecture Decision Records)** - Major decisions including: + - ADR-011: Nickel Migration (from KCL) + - ADR-012: Nushell + Nickel plugin wrapper + - ADR-010: Configuration format strategy +- **Multi-Repo Strategy** - Repository organization +- **Integration Patterns** - How components interact + +### Development Guidelines + +- **[Repository Structure](docs/src/development/)** - Codebase organization +- **[Contributing Guide](CONTRIBUTING.md)** - How to contribute +- **[Nushell Guidelines](.claude/guidelines/nushell/)** - Best practices +- **[Nickel Guidelines](.claude/guidelines/nickel.md)** - IaC patterns +- **[Rust Guidelines](.claude/guidelines/rust/)** - Rust conventions + +### API Reference + +- **REST API** - HTTP endpoints in `provisioning/docs/src/api-reference/` +- **Nushell API** - Library functions and modules +- **Provider API** - Cloud provider interface specification --- ## Project Status -**Current Version**: Active Development (2025-10-07) +**Current Version**: v5.0.0-nickel (Production Ready) | **Date**: 2026-01-08 -### Recent Milestones +### Completed Milestones + +- βœ… **v5.0.0** (2026-01-08) - **Nickel IaC Migration Complete** + - Full KCLβ†’Nickel migration + - Schema-driven configuration system + - Type-safe lazy evaluation + - ~220 legacy files removed, ~250 new schema files added - βœ… **v4.0.0** (2025-10-09) - Complete Security System (12 components, 39,699 lines) -- βœ… **v1.0.0** (2025-10-09) - Nushell Plugins Integration (10-50x performance) -- βœ… **v2.0.5** (2025-10-06) - Platform Installer with TUI and CI/CD modes -- βœ… **v2.0.4** (2025-10-06) - Test Environment Service with container management -- βœ… **v2.0.3** (2025-09-30) - Interactive Guides system -- βœ… **v2.0.2** (2025-09-30) - Modular CLI Architecture (84% code reduction) -- βœ… **v2.0.2** (2025-09-25) - Batch Workflow System (85-90% token efficiency) -- βœ… **v2.0.1** (2025-09-25) - Hybrid Orchestrator (Rust/Nushell) -- βœ… **v2.0.1** (2025-10-02) - Workspace Switching system +- βœ… **v3.5.0** (2025-10-07) - Platform Installer with TUI and CI/CD modes +- βœ… **v3.4.0** (2025-10-06) - Test Environment Service with container management +- βœ… **v3.3.0** (2025-09-30) - Interactive Guides system +- βœ… **v3.2.0** (2025-09-30) - Modular CLI Architecture (84% code reduction) +- βœ… **v3.1.0** (2025-09-25) - Batch Workflow System (85-90% token efficiency) +- βœ… **v3.0.0** (2025-09-25) - Hybrid Orchestrator (Rust/Nushell) +- βœ… **v2.0.5** (2025-10-02) - Workspace Switching system - βœ… **v2.0.0** (2025-09-23) - Configuration System (476+ accessors) +- βœ… **v1.0.0** (2025-10-09) - Nushell Plugins Integration (10-50x performance) -### Roadmap +### Current Focus -- **Platform Services** - - [ ] Web Control Center UI completion - - [ ] API Gateway implementation - - [ ] Enhanced MCP server capabilities - -- **Extension Ecosystem** - - [ ] OCI registry for extension distribution - - [ ] Community task service marketplace - - [ ] Cluster template library - -- **Enterprise Features** - - [ ] Multi-tenancy support - - [ ] RBAC and audit logging - - [ ] Cost tracking and optimization +- **Nickel Ecosystem** - IDE support, LSP integration, schema libraries +- **Platform Consolidation** - GitHub Actions CI/CD, cross-platform testing +- **Extension Registry** - OCI-based distribution for task services and providers +- **Documentation** - Complete Nickel migration guides, ADR updates --- @@ -934,6 +998,7 @@ deploy-production: Contributions are welcome! See [CONTRIBUTING.md](docs/development/CONTRIBUTING.md) for guidelines. **Key areas for contribution**: + - New task service definitions - Cloud provider implementations - Cluster templates @@ -949,5 +1014,6 @@ See [LICENSE](LICENSE) file in project root. --- **Maintained By**: Architecture Team -**Last Updated**: 2025-10-07 +**Last Updated**: 2026-01-08 (Nickel v5.0.0 Migration) +**Current Branch**: nickel **Project Home**: [provisioning/](provisioning/)