# Private Cloud Delivery

> Use when selling or shipping the SaaS as a self-hosted, customer-deployed edition. The vendor-pushes-images / customer-runs-everything responsibility split, the per-client registry, the vendor push-and-stop workflow, the IaC handed over, upgrades and rollback, the one-flag product switch, and the commercial artifacts. A fifth deployment shape alongside the Fly guide's four, with no fork and no vendor production access.

- Skill: `konradcinkusz/private-cloud-delivery` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add konradcinkusz/private-cloud-delivery`
- Raw SKILL.md: https://api.skillmd.com/api/skills/konradcinkusz/private-cloud-delivery/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: konradcinkusz (https://skillmd.com/u/konradcinkusz)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/konradcinkusz/private-cloud-delivery

---


# Private-cloud delivery: selling the SaaS as self-hosted

**Read [`references/PRIVATE-CLOUD-DELIVERY.md`](references/PRIVATE-CLOUD-DELIVERY.md) before applying any of this.**
That file is the standard; everything below it is a summary to help you decide
whether this skill applies and to check your work afterwards.

## What this standard covers

- The model in one paragraph
- The responsibility split
- The per-client registry
- The vendor workflow: push and stop
- The IaC you hand over
- Upgrades and rollback
- The product switch
- Commercial artifacts
- A fifth shape: public registry, one-command run

## Failure modes

| Symptom | Cause |
|---|---|
| Vendor workflow fails for one client only | Client JSON missing/null fields, or the same-named GitHub Environment lacks the secrets — the error message should already be saying which |
| Vendor "just fixes it" in the customer's cloud | Scope creep past the push-only credential; the split in §2 is the contract, decline in writing |
| Customer deploy pulls unauthorized | Registry referenced as created-here instead of `existing` + pull grant |
| Upgrade works, rollback corrupts | Release contained migrations; rollback was not coordinated (§6) |
| Customer environment drifts from the template | Customer edited resources in the portal; the re-run-with-tag lifecycle only holds if the template stays authoritative — say so in the handover doc |
| Enterprise features half-enabled | `TenantMode` implemented per-service instead of at token issuance |
| Secrets in the client JSON | Sensitivity split violated; only DNS-shaped values belong in the committed file |

## Checklist

- [ ] Responsibility split written; share/do-not-share lists explicit
- [ ] Per-client committed JSON (non-sensitive only) + same-named GitHub Environment (secrets); `_template.json`; validating workflow whose errors are runbooks
- [ ] Push workflow: client registry login, matrix push `:tag` + `:latest`, handover summary printed; provisioning/deploy/migrations/secrets explicitly out of scope
- [ ] Vendor credential is push-only to one registry
- [ ] Handed-over IaC: subscription-scope, `imageTag`-parameterized, `@secure()` params, generic app module, registry as `existing`, edition stamped in tags
- [ ] Rollback caveat (migrations) and version-support policy in the handover doc
- [ ] `TenantMode` at token issuance only; no enterprise fork
- [ ] IT one-pager (with RTO/RPO table), SOW skeleton, objection table maintained

---

Generated from [`docs/guides/PRIVATE-CLOUD-DELIVERY.md`](https://github.com/konradcinkusz/architecture-standards/blob/main/docs/guides/PRIVATE-CLOUD-DELIVERY.md) by `scripts/build-marketplace.mjs`. Do not edit this file: change the source document, or its entry in `catalog/marketplace.catalog.json`, and re-run the generator.

