{"protocol":"clank-doc/1","frameworkVersion":"0.24.0","slug":"release-channels","title":"Persistent release channels","description":"A release channel such as stable or beta pins an exact, successfully activated upload in an environment family. Its immutable entries retain source environment, project, release ID and SHA 256. Pinning changes the channel's current target; ","group":{"id":"deploy","title":"Deploy and operate"},"url":"https://docs.clank.run/docs/release-channels","source":"docs/release-channels.md","headings":["Pin, inspect and promote","Roll back without rewriting history","Failure, interruption and recovery","Retention and retirement","HTTP and consumer types"],"tableOfContents":[{"id":"pin-inspect-and-promote","title":"Pin, inspect and promote","level":2},{"id":"roll-back-without-rewriting-history","title":"Roll back without rewriting history","level":2},{"id":"failure-interruption-and-recovery","title":"Failure, interruption and recovery","level":2},{"id":"retention-and-retirement","title":"Retention and retirement","level":2},{"id":"http-and-consumer-types","title":"HTTP and consumer types","level":2}],"markdown":"# Persistent release channels\n\nA release channel such as `stable` or `beta` pins an exact, successfully activated upload in an\n[environment family](environment-promotions.md). Its immutable entries retain source environment,\nproject, release ID and SHA-256. Pinning changes the channel's current target; it does not deploy\nan application. Promotion and rollback are explicit actions that use the existing environment\nactivation, permission, migration, attestation and host-certification boundaries.\n\nUse **Project → Environments → Release channels** or `clank channel` in a directory linked to\nthe family root. Names begin with a lowercase letter and contain at most 64 lowercase letters,\ndigits or hyphens. Each family retains at most 100 names and 1,000 immutable entries. Retirement\nfrees history capacity and keeps a versioned name tombstone; it does not free the name slot.\n\n## Pin, inspect and promote\n\nInspect the source project's retained releases and choose the exact upload:\n\n```sh\nclank channel list --json\nclank channel pin stable --from=development --release=SOURCE_RELEASE \\\n  --digest=EXACT_SHA256 --expected-version=0 --json\nclank channel get stable --json\nclank channel history stable --json\n```\n\nVersion zero creates a previously unused name. An existing or retired name requires its exact\ncurrent version. A successful pin increments that version and appends an immutable entry. A\nstale request fails with `CHANNEL_VERSION_STALE`; it cannot overwrite a newer pin. If a pin's\nresponse is lost, inspect the channel before retrying or reviewing another update. A retry of\nthe old expected version fails rather than creating another entry.\n\nPromotion captures both the channel version and the target environment binding version, the\nexpected active target release and an exact request key:\n\n```sh\nclank environment list --json\nclank channel promote stable --to=staging --expected-version=1 \\\n  --environment-version=1 --expected-active=TARGET_RELEASE \\\n  --key=channel_promotion_0001 --json\nclank channel actions stable --json\n```\n\nAn uninitialized `apply-safe` target requires `--expected-active=none`. An initialized\n`code-only` target requires its exact active release. The platform sends the original compressed\nupload bytes without rebuilding, while resolving the target's current secrets, database,\nnamespace, quotas and migration policy. The source environment must still bind the pinned\nsource project. Production requires a workspace owner/admin. Provider targets must satisfy\n[certified promotion admission](environment-promotions.md); a channel cannot relax it.\n\nSigned-release installations require `--attestation=target-attestation.json`. The bounded JSON\nmust authorize the target project and unchanged digest. The dashboard accepts the same file\nwhen reviewing promotion or rollback.\n\nThe dashboard's **Review channel action** captures these exact values before enabling\n**Apply reviewed action**. Editing fields invalidates the review. Pending requests stay in that\nbrowser session when navigating between projects; **Retry exact channel request** sends the\noriginal request, including its key and attestation. Reloading requires reviewing again.\nSigning out clears drafts and visible history.\n\n## Roll back without rewriting history\n\nRollback selects an older immutable entry and explicitly activates it on a target environment:\n\n```sh\nclank channel history stable --version=1 --json\nclank channel rollback stable --from-version=1 --to=staging \\\n  --expected-version=2 --environment-version=1 \\\n  --expected-active=TARGET_RELEASE --key=channel_rollback_0001 --json\n```\n\nOnly verified target activation publishes the new current channel version. For example,\nrolling back channel version 2 to entry 1 appends version 3 referencing entry 1's original\nsource release and digest. Entries 1 and 2 remain unchanged. Target application data stays\nindependent; channel rollback does not restore source data or copy source secrets. The target's\nmigration policy still applies, including rejection of changed or pending migrations under\n`code-only`.\n\nAn accepted action's identical replay returns its original receipt and target release, even\nwhen the channel has since advanced. It does not reactivate that old release, append history\nagain or reinterpret a newer pin. Changed fields under an existing action key fail with\n`CHANNEL_RETRY_CHANGED` or `PROMOTION_RETRY_CHANGED`. Current permission and environment checks\nstill apply to replay; receipts cannot restore revoked authority.\n\nHistory and action lists expose the newest 100 authorized rows. The exact history read and\nnumeric historical version in the dashboard can inspect any retained authorized entry,\nincluding one outside that list. Lists omit entries whose source is no longer readable and\nactions whose source or target is no longer readable.\n\n## Failure, interruption and recovery\n\nFailed health, migration or authority checks restore the prior target through the environment\npromotion path. A failed rollback does not advance the channel. Provider compensation restores the prior active\ngeneration’s frozen environment so newly edited secrets cannot also break its prior code. Pending, staging and\n`recovery-required` actions prevent repinning or retirement until activation or verified\nrecovery finishes. Pending rollback also reserves its future entry slot, so another channel\ncannot consume that capacity before acceptance.\n\nChannel action history links to the target's promotion history. Inspect and recover the\nunderlying exact promotion key there, or use:\n\n```sh\nclank environment history staging --json\nclank environment recover staging UNDERLYING_PROMOTION_KEY \\\n  --confirm='recover-promotion TARGET_SLUG UNDERLYING_PROMOTION_KEY' --json\n```\n\nRecovery verifies candidate cleanup before restoring or admitting the prior writer. It marks\nthe interrupted action failed and leaves the channel pin unchanged. Review a new action with\na new key after recovery. A new key cannot bypass an unresolved target fence.\n\n## Retention and retirement\n\nEvery retained channel entry protects its original source upload against artifact cleanup and\nsource-project deletion. Older entries remain pinned after a new pin or rollback. Uploads\ncontinue to count against the source project's existing storage limits. The Deployments tab\nshows **Channel pinned** where cleanup is blocked; explicitly allowing immediate rollback loss\ndoes not bypass a channel pin.\n\nAn owner/admin, subject to the platform's configured recent-authentication policy, may retire a channel after reviewing its current\nversion and exact confirmation:\n\n```sh\nclank channel retire stable --expected-version=3 \\\n  --confirm='retire-channel FAMILY_ROOT_SLUG stable' --json\n```\n\nRetirement clears that channel's entries, pins and channel action metadata. It retains a name\ntombstone at the next version and preserves uploads, application data, running releases,\nunderlying promotion receipts and audit history. Retirement of version 3 leaves version 4 with\n`current: null`. Its identical retry returns that tombstone. Recreating `stable` requires\n`--expected-version=4` and publishes version 5; stale pin, retirement and activation requests\ncannot affect the recreated channel. Other channels may still retain the same upload.\n\n## HTTP and consumer types\n\nAll routes below are under `/api/projects/:root/channels`. Writes use the same current session\nor bearer-token authority as environment promotion; browser writes also require CSRF protection.\n\n| Method and suffix | Contract |\n| --- | --- |\n| `GET /` | Up to 100 currently authorized names and retired tombstones. |\n| `GET /:name` | Current version, exact current entry or `current: null` when retired. |\n| `PUT /:name` | `sourceEnvironment`, `releaseId`, `digest`, `expectedVersion`. |\n| `GET /:name/history` | Newest 100 authorized immutable entries. |\n| `GET /:name/history/:version` | One exact authorized immutable entry; absent or retired returns 404. |\n| `GET /:name/actions` | Newest 100 authorized action receipts. |\n| `POST /:name/promote` | `targetEnvironment`, `expectedVersion`, `expectedEnvironmentVersion`, `expectedActiveReleaseId`, `idempotencyKey`. |\n| `POST /:name/rollback` | Promotion fields plus historical `fromVersion`. |\n| `DELETE /:name` | `expectedVersion`, exact `confirmation`; owner/admin and the configured recent-authentication policy. |\n\n`POST` actions accept the optional `x-clank-release-attestation` header and return the underlying\npromotion, target release and channel action. A pin requires root deploy and source read\npermission. Activation additionally requires current target deploy permission. Retirement\nrequires root token-administration permission, workspace administration and any configured\nrecent passkey/MFA verification policy. Retained source\nuploads and current bindings are verified again during asynchronous work and at acceptance.\n\nImport `PlatformReleaseChannelEntry`, `PlatformReleaseChannel`, `PlatformChannelPinRequest`,\n`PlatformChannelActivationRequest`, `PlatformChannelRollbackRequest` and `PlatformChannelAction`\nfrom `@clank.run/framework/platform`. Observation types are readonly. Rollback's historical\nversion and activation's nullable active-release expectation are required.\n\nThe additive SQLite migration does not rewrite existing releases or environment receipt\nfingerprints. Channel receipt acceptance, target activation and rollback pointer publication\nshare one transaction. Older controllers do not enforce channel pins. Before reverting to a controller without\nchannel support, finish or recover pending actions and retire retained channels with the\ncompatible controller. Otherwise older cleanup or project deletion can remove their retained\nuploads. Preserve the control store and uploads together when taking a recovery backup.\n"}