greentic-setup
End-to-end bundle setup engine for the Greentic platform.
Provides a library and CLI for discovering, configuring, and deploying Greentic bundles — including pack resolution, QA-driven setup (via greentic-qa), secrets persistence, webhook registration, admin API types, hot reload, and adaptive card setup flows.
Dual-mode:
- Library — core APIs for programmatic use by greentic-operator, runner, and other tools
- CLI binary —
greentic-setup bundle ...commands for bundle lifecycle management (invoked viagtc setuppassthrough)
Features
- Setup engine — plan and execute create/update/remove workflows for bundles
- Pack discovery — scan bundle directories for
.gtpackfiles, read CBOR/JSON manifests - QA-driven configuration — interactive CLI prompts and adaptive card rendering (via greentic-qa FormSpec)
- Conditional questions —
visible_ifexpressions for dynamic form flows (powered by qa-specExprevaluation) - Secrets management — persist secrets and config to dev store for all pack types
- Admin API types — mTLS-secured request/response types for runtime bundle lifecycle management
- Hot reload — diff-based bundle change detection and reload planning
- Adaptive card setup — session management and link generation for card-based onboarding
- Full i18n — all user-facing strings via greentic-i18n
Architecture
greentic-setup
├── bin/
│ └── greentic_setup CLI binary (simple mode + bundle subcommands)
├── cli_i18n CLI localization helper (CliI18n wrapper)
├── engine SetupEngine: plan → execute orchestration
├── plan SetupPlan, SetupStep, SetupMode, metadata types
├── bundle Bundle directory creation, gmap paths, provider registry
├── bundle_source Pack source resolution (file://, oci://, path)
├── discovery Pack discovery from .gtpack files (CBOR + JSON manifests)
├── gtbundle Portable .gtbundle archive format (zip/squashfs)
├── qa/
│ ├── bridge Provider QA JSON → FormSpec conversion (+ visible_if)
│ ├── wizard Interactive wizard, validation, card rendering
│ └── persist Secrets + config persistence to dev store
├── secrets Dev store path resolution, SecretsSetup
├── setup_input Setup answers loading from JSON/YAML files
├── setup_to_formspec Legacy setup.yaml → FormSpec conversion
├── secret_name Canonical secret name/URI normalization
├── admin/
│ ├── tls AdminTlsConfig for mTLS endpoint
│ └── routes Admin API request/response types
├── reload BundleDiff, ReloadPlan, ReloadAction
├── card_setup CardSetupSession, SetupLinkConfig
└── webhook Webhook URL validation helpers
Previously embedded in greentic-operator (~5,000 lines). Extracted as a standalone library so it can be reused by the operator, runner, CLI tools, and admin APIs.
Usage
Simple Mode (recommended)
The simplest way to use greentic-setup — just point it at a bundle:
# Interactive wizard - prompts for all configuration
# Preview what will happen (dry-run)
# Generate answers template file
# Apply answers from file (non-interactive)
# Works with .gtbundle archives too
Options:
| Flag | Description |
|---|---|
--dry-run |
Preview setup plan without executing |
--emit-answers <FILE> |
Generate answers template to file |
-a, --answers <FILE> |
Apply answers from file |
-t, --tenant <TENANT> |
Tenant identifier (default: demo) |
--team <TEAM> |
Team identifier |
-e, --env <ENV> |
Environment: dev/staging/prod (default: dev) |
Via gtc passthrough
Advanced: Bundle Subcommands
For fine-grained control over bundle lifecycle:
# Initialize a new bundle
# Add a pack to the bundle
# Interactive setup (wizard mode)
# Setup with answers file
# Generate answers template
# Setup specific provider
# Update provider configuration
# Remove a provider
# Build portable bundle (.gtbundle archive)
# List packs in bundle
# Show bundle status
As a library
use ;
use ;
use TenantSelection;
use PathBuf;
let config = SetupConfig ;
let engine = new;
let request = SetupRequest ;
let plan = engine.plan.unwrap;
engine.print_plan;
QA-driven setup
use run_qa_setup;
use Path;
let = run_qa_setup.unwrap;
Bundle-level static hosting policy
Answers files can now carry bundle/platform static hosting policy separately from provider answers:
bundle_source: ./my-bundle
env: dev
tenant: demo
platform_setup:
static_routes:
public_web_enabled: false
public_surface_policy: disabled
default_route_prefix_policy: pack_declared
tenant_path_policy: pack_declared
setup_answers:
messaging-telegram:
bot_token: "your-bot-token"
When setup executes, it persists the normalized bundle-level artifact to
state/config/platform/static-routes.json.
Pack discovery
use discovery;
use Path;
let result = discover.unwrap;
println!;
for p in &result.providers
Hot reload diffing
use ;
use Path;
let prev = discover.unwrap;
let curr = discover.unwrap;
let diff = diff_discoveries;
if !diff.is_empty
Admin API types
use ;
let tls = AdminTlsConfig ;
tls.validate.unwrap;
From CLI (via greentic-operator)
# Interactive setup
# Automated setup from answers file
# QA setup wizard
Modules
| Module | Description |
|---|---|
engine |
SetupEngine — orchestrates plan building for create/update/remove |
plan |
Plan types: SetupPlan, SetupStep, SetupMode, metadata |
bundle |
Bundle directory structure creation and management |
bundle_source |
Pack source resolution (file://, oci://, path) |
discovery |
Pack discovery from .gtpack files (CBOR + JSON manifests) |
gtbundle |
Portable .gtbundle archive format (zip/squashfs) |
cli_i18n |
CLI localization helper for user-facing messages |
qa::bridge |
Provider QA JSON → FormSpec conversion with visible_if support |
qa::wizard |
Interactive wizard, validation, card rendering, visibility evaluation |
qa::persist |
Secrets + config persistence (visibility-aware) |
secrets |
Dev store path resolution, SecretsSetup |
setup_input |
Setup answers loading from JSON/YAML |
setup_to_formspec |
Legacy setup.yaml → FormSpec conversion |
secret_name |
Canonical secret name normalization |
admin::tls |
AdminTlsConfig for mTLS endpoints |
admin::routes |
Admin API request/response types |
reload |
BundleDiff, ReloadPlan, ReloadAction for hot reload |
card_setup |
CardSetupSession, SetupLinkConfig for adaptive card flows |
webhook |
Webhook URL validation helpers |
Secret URI Format
secrets://{env}/{tenant}/{team}/{provider_id}/{key}
dev demo _ messaging-telegram bot_token
- Team:
None/"default"/ empty →"_"(wildcard) - Key: normalized via
canonical_secret_name()(lowercase, underscores, collapsed)
Conditional Questions (visible_if)
Provider QA specs can include visible_if expressions:
Supported formats:
{"field": "q1", "eq": "value"}— equality check{"field": "q1"}— truthy check- Full qa-spec
ExprJSON (And/Or/Not/Eq/Ne/Lt/Gt/IsSet)
Invisible questions are:
- Skipped during interactive prompts
- Skipped during validation (required check)
- Not persisted as secrets
CI and Releases
Local checks
Runs: fmt → clippy → test → build → doc → package dry-run.
Cutting a release
- Bump version in
Cargo.toml - Commit and tag:
git tag v0.4.x - Push tag:
git push origin v0.4.x publish.ymlworkflow triggers → publishes to crates.io
Required GitHub secrets: CARGO_REGISTRY_TOKEN
i18n
Requires greentic-i18n repo at ../greentic-i18n/.
Documentation
| Document | Description |
|---|---|
| Demo Guide | Complete guide for creating and running bundles |
| Admin API Reference | Full admin endpoint documentation with examples |
| Adaptive Cards Guide | Card-based setup flow with security details |
| mTLS Setup Guide | Certificate generation and configuration |
| Demo Features | Advanced features demo (conditional QA, secrets, hot reload) |
| Manual Testing | Step-by-step testing guide for all features |
API Reference (rustdoc)
License
MIT