environment-promotion — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited environment-promotion (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Tool availability: some MCP tools named here live in thefulltoolset profile — if one is not advertised on this connection, tell the user to reconnect the MCP server with?toolsets=full(or use thecplnCLI fallback). Reads and deletes work on every profile via the genericlist_resources/get_resource/delete_resourcetools.
Control Plane has no built-in promote or rollback primitive — promotion is applying the same artifacts (image + manifests) to the next environment. Two topologies exist: org-per-environment (the documented best practice) and GVC-per-environment. The recurring failure is image access: a staging/prod org cannot pull the dev org's images until you either copy the image or wire up a cross-org pull secret.
| Topology | Isolation | Image sharing | Best for |
|---|---|---|---|
| Org per environment (recommended) | Strongest — policies, secrets, users, audit fully separate | cpln image copy or cross-org pull secret | Production, compliance-sensitive teams |
| GVC per environment (one org) | Weak — shared org policies and access | Same org registry; no pull secret needed | Small teams, rapid iteration |
With org-per-environment, GVCs and workloads keep identical names in every org, so the same manifests apply unchanged — no environment suffixes in resource names. Org creation is account-level: Console, or cpln org create --accountId ID --invitee EMAIL.
Keep manifests in git and apply them per environment — cpln apply is idempotent (PUT upsert) and resolves resource ordering:
cpln apply --file ./manifests/ --org my-org-staging --gvc my-gvc --ready # org-per-env: same files, next org
cpln apply --file ./manifests/ --org my-org --gvc staging-gvc --ready # gvc-per-env: same files, next GVCcpln <resource> get REF -o yaml-slim (plain yaml output breaks apply).mcp__cpln__update_workload / mcp__cpln__update_gvc (both PATCH semantics).mcp__cpln__export_terraform (one self link, or bulk by path depth — a whole GVC or org), mcp__cpln__export_terraform_batch (full profile, up to 100 explicit links), mcp__cpln__convert_to_terraform (manifest to HCL, dry-run validated). An unsupported kind is rejected with the supported list.cpln image copy my-app:abc1234 --to-org my-org-prod # same credentials for both orgs
cpln image copy my-app:abc1234 --to-org my-org-prod --to-profile prod-profile --cleanupCLI-only (no MCP tool); requires a running Docker daemon — it docker-logins both registries, then pulls, tags, pushes. --to-name renames during copy; --cleanup removes the local images (use in CI). Needs pull permission on the source image and create on images in the target org. After the copy the target references it as //image/my-app:abc1234 — no pull secret.
The target org pulls directly from the source org's registry. Four steps:
mcp__cpln__add_key_to_service_account (creates the service account if missing; the key is shown once).mcp__cpln__create_policy with targetKind: image, targetAll: true (or targetQuery by repository), addPermissions: ["pull"], addServiceAccounts: [LINK] — bindings go in the create call.mcp__cpln__create_secret_docker with dockerConfigJson — the username is the literal string `<token>` (the registry rejects anything else; the password is the service-account key):{ "auths": { "my-org-dev.registry.cpln.io": { "username": "<token>", "password": "SERVICE_ACCOUNT_KEY" } } }mcp__cpln__update_gvc with pullSecretLinks: ["//secret/dev-registry-pull"] (merged with existing), then reference the image by its full registry hostname in the workload spec:spec:
containers:
- name: main
image: my-org-dev.registry.cpln.io/my-app:abc1234CLI fallback for the same four steps:
cpln serviceaccount create --name image-puller --org my-org-dev # CLI does NOT auto-create on add-key
cpln serviceaccount add-key image-puller --description "cross-org pull" --org my-org-dev # save the key
cpln policy create --name image-pull --target-kind image --all --org my-org-dev
cpln policy add-binding image-pull --serviceaccount image-puller --permission pull --org my-org-dev
cpln secret create-docker --name dev-registry-pull --file docker-config.json --org my-org-prod
cpln gvc update my-gvc --set 'spec.pullSecretLinks+=//secret/dev-registry-pull' --org my-org-prodSame-org images never need a pull secret — the platform injects a default registry credential for the org's own registry automatically.
my-app:abc1234 or semver my-app:v1.2.3) — promote the exact artifact you tested; mutable tags (latest, staging) make rollback unreliable. Digest pins (my-app@sha256:...) are maximally reproducible.false): redeploys the workload automatically when a tag's underlying digest changes (within ~5 minutes) — useful for dev environments on mutable tags, wrong for production promotion.The CLI is the primary interface in pipelines; CPLN_TOKEN alone is enough (no profile needed — see the cpln skill). The shape that works:
# Build once in dev, then per stage: copy the image + apply the manifests
- run: cpln image build --name my-app:${{ github.sha }} --push # CPLN_TOKEN + CPLN_ORG=my-org-dev
- run: cpln apply --file ./manifests/ --gvc my-gvc --ready
# staging / prod stages (gate each with environment approvals):
- run: cpln image copy my-app:${{ github.sha }} --to-org my-org-prod --cleanup # dev-org token
- run: cpln apply --file ./manifests/ --gvc my-gvc --org my-org-prod --ready # prod-org token--to-profile (or pre-run cpln image docker-login) for the target.@controlplane/cli), runners: gitops-cicd skill.There is no deployment-history rollback — rolling back means re-pointing the workload at the previous known-good image (keep the previous tag in git history or your pipeline metadata):
cpln workload update my-app --set spec.containers.main.image=//image/my-app:v1.1.0 --gvc my-gvc --org my-org
cpln workload get-deployments my-app --gvc my-gvc --org my-org # verify every location reports readymcp__cpln__get_resource (kind="workload") to record the current image, mcp__cpln__update_workload (containers: [{name, image}] — merged by container name), then poll mcp__cpln__list_deployments until ready.mcp__cpln__list_resources kind="image") — it may only have been copied forward once.cpln workload force-redeployment my-app --gvc GVC — it PATCHes a cpln/deployTimestamp tag with the current time, producing a rolling restart. No MCP equivalent; mcp__cpln__update_workload setting that same tag replicates it.cpln helm rollback RELEASE [REVISION].| Tool | Purpose |
|---|---|
mcp__cpln__create_gvc / mcp__cpln__create_workload | Stand up the target environment |
mcp__cpln__update_workload / mcp__cpln__update_gvc | Patch image, env, scaling, pullSecretLinks (PATCH semantics) |
mcp__cpln__add_key_to_service_account | Puller credentials in the source org (auto-creates the SA; key shown once) |
mcp__cpln__create_policy | Grant pull on images, binding included in the create call |
mcp__cpln__create_secret_docker | Docker secret from dockerConfigJson (username <token>) |
mcp__cpln__list_deployments | Verify a promotion or rollback is ready per location |
mcp__cpln__export_terraform / _batch / mcp__cpln__convert_to_terraform | Export live environments to IaC |
CLI fallback (read the cpln skill first; CI/CD uses CPLN_TOKEN + cpln apply --ready): cpln image copy and cpln image build --push are CLI-only — no MCP equivalent.
| Need | Skill |
|---|---|
| Image building, registries, pull-secret detail | image |
| Pipeline setup, runners, service-account auth | gitops-cicd |
| Terraform / Pulumi promotion | iac-terraform-pulumi |
| Per-environment secrets and RBAC | access-control |
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.