Phase 0 ✓ A1 ✓ A2 ✓ A3 ✓ A4 – A10 pending

Greentic next-gen deployment — what's built, what works today

We're rebuilding how Greentic apps get deployed: instead of "stuff that runs on AWS", a deployment is now a named Environment that owns its config, its secrets, its bundles, its revisions, and how traffic is split between them.

As of 2026-05-19. Plan: plans/next-gen-deployment.md.

The big picture

Greentic apps already follow a layered model: small WASM Components are wired into Flows, packaged into Packs, composed into Bundles, and run by a Runner. The redesign adds an explicit Environment layer between Bundle and Runner — so the same bundle can be deployed to local, staging, or customer-X-prod without rewriting it.

Component WASM module Flow .ygtc graph Pack .gtpack Bundle .gtbundle NEW Environment host + setup + runtime config revisions, traffic Runner executes flows

Why this matters: today "deploy" silently means "AWS, with config baked into secrets, revisions you can't roll back". After this redesign, every deploy is a named environment with explicit revisions, traffic splits, and one-step rollback — and the same machinery works for a laptop demo, a customer pilot, and a production cluster.

What's landed so far

Phase 0 — security hotfix done 2026-05-18

Four targeted security gates landed before the redesign started, so the rewrite doesn't sit on a leaky foundation:

  • P0.1 — secret values no longer leak into bundle archives
  • P0.2 — symlink-TOCTOU class fixed across three repos with a shared helper family
  • P0.3 — extraction tests harden malicious-path / symlink-escape paths
  • P0.4 — once-per-process deprecation warnings instead of silent fallthrough

A1 — the shared spec crate done 2026-05-18

New crate greentic-deploy-spec owns the types every other crate now agrees on: Environment, Revision, TrafficSplit, BundleDeployment, Credentials. JSON-schema-derivable. 70 unit tests green.

A2 — the on-disk store done 2026-05-18

EnvironmentStore trait + LocalFsStore implementation. Per-env file lock, atomic writes, local backups, ULID generation. The whole read-modify-write cycle now runs inside transact() so two parallel op commands can't clobber each other. 113 tests green across the surface.

A3 — the op CLI surface done 2026-05-19

The actual command set users type. Eight nouns, each with their own verbs:

NounVerbsWhat it manages
envcreate · update · list · show · doctor · destroyenvironments themselves
env-packsadd · update · remove · rollback · listwhich packs (deployer/secrets/state/…) provide which capability
bundlesadd · update · remove · listapp bundles deployed into an env
revisionsstage · warm · drain · archive · listversions of a bundle, with a real lifecycle
trafficset · show · rollbackweighted traffic between revisions; one-step rollback
configshow · sethost config + per-slot answer presence
credentialsrequirements · bootstrap · rotatepreconditions enforced; heavy logic deferred to A5/Phase D
secretslist · put · get · rotatepreconditions enforced; backend dispatch deferred to A9

Every output goes through a single JSON envelope — {op, noun, result} on success, {op, noun, error: {kind, message}} on failure — so scripts get a stable contract regardless of which binary they invoked it through (gtc op …, greentic-operator op …, or greentic-deployer op …).

Five PRs merged: greentic-deployer#200, greentic-operator#71, greentic#220, greentic-deployer#201, greentic-operator#72. 543 tests green workspace-wide.

A4 — local environment auto-create next

First gtc setup on a clean machine will write a default local env with sensible bindings (local-process deployer, dev-store secrets, stdout telemetry, in-memory sessions + state). After this, gtc start ./my-bundle.gtbundle just works.

What you can do today

Heads up: the A3 op surface lives on the dev publishing lane (binary-bifurcated as gtc-dev / greentic-deployer-dev). Your locally installed gtc 1.0.x is the stable lane and doesn't have it yet. To play with A3, install the dev binary alongside.

Stable lane (gtc 1.0.x)

What you already had:

  • gtc setup — bundle setup wizard
  • gtc start — local runner (legacy orchestration)
  • gtc admin … — admin verbs (now require explicit --target aws|azure|gcp instead of silently defaulting to aws)

No behaviour change except the --target tightening.

Dev lane (gtc-dev 1.1.0-dev.*)

What A3 just unlocked:

  • The full op surface — all 8 nouns above
  • --schema flag on every verb (machine-readable input schemas)
  • --answers file.json for non-interactive runs
  • JSON envelopes for both success and failure (scriptable)
  • One-step rollback for env-pack bindings and traffic splits
  • Idempotent traffic set with replay protection

Concrete use cases that work right now

What it does not do yet: actually bring up a runtime. op revisions warm flips a state field; it doesn't launch a process. That's gated on A5 (lifecycle execution) and Phase D (deployer env-packs). For "I want my bundle running", keep using gtc start on the stable lane until A4 lands.

Try it now

1. Install the dev binary

cargo binstall greentic-deployer-dev
# or, for the full gtc with `gtc op …` passthrough:
cargo binstall gtc-dev

2. Discover the surface

greentic-deployer op --help
greentic-deployer op env --help
greentic-deployer op revisions --help

3. Create an env, list it, show it

STORE=$(mktemp -d)

greentic-deployer op env create \
  --store-root "$STORE" \
  --answers <(echo '{"name":"sandbox","description":"a play env"}')

greentic-deployer op env list  --store-root "$STORE"
greentic-deployer op env show  --store-root "$STORE" --answers <(echo '{"name":"sandbox"}')

4. See the JSON envelope contract

# success → stdout has {op, noun, result}
greentic-deployer op env list --store-root "$STORE" | jq .

# failure → stderr has {op, noun, error:{kind,message}}, exit non-zero
greentic-deployer op env show --store-root "$STORE" \
  --answers <(echo '{"name":"does-not-exist"}') 2>&1 1>/dev/null | jq .

5. Dump a verb's input schema (for tooling/LLMs)

greentic-deployer op env-packs add --schema | jq .
greentic-deployer op traffic set    --schema | jq .

6. Once you have gtc-dev, the same surface via passthrough

gtc op --help            # shells out to the operator binary
gtc op env list
gtc op revisions list sandbox

What's still ahead

GateWhat it addsWhen you'll feel it
A4auto-create local env on first setupgtc setup just works on a clean machine
A5real revision lifecycle executionop revisions warm actually warms a runner
A7audit-event log for every mutationcompliance / post-incident timelines
A8remote EnvironmentStore + CASmulti-operator setups stop clobbering each other
A9env-pack registry + secrets backendsop secrets put/get/rotate hits real vaults
A10wizards become env-scopedsame wizard, different secrets per env
Phase Bmulti-bundle envs, in-process traffic splittertwo revisions of one customer side-by-side
Phase Ccredentials channel, runtime config channelsecrets and config stop sharing one pipe
Phase DAWS + K8s env-packs ship"deploy to AWS" without bespoke scripts