Skip to content

0020 — A channel defined twice is held, not taken over

Status: Accepted; refines 0019 Date: 2026-10-01

Context

v1.47.0 added Take over from git: a console record with supersedes_policy: true covered a policy channel, the controller reconciled the record and reported the policy entry as superseded. It was meant as a migration aid with no unmanaged gap. It also made one channel two definitions at once, one of them reported as superseded, and it needed a status state (superseded) that existed only to describe that. It contradicts a rule the rest of the design keeps: a channel is managed one way.

Decision

The feature is removed (v1.48.0). The rule is the plain one: a channel defined both in the policy and as a console record is held on both sides and nothing on it changes until one definition is removed. The console refuses to create or update a record for a channel git defines (by name or adopted id), and the server refuses the same. To move a channel from git to the console: remove it from the policy, then Manage it from Discovered.

A stored record that still has supersedes_policy: true keeps loading with the field ignored, is never written with it again, and is a plain console channel once git no longer defines the channel. This is an exception to 0007's "refuse removed configuration": the field is in a record the service itself wrote, not in configuration someone reviewed, so refusing it would make an installed record unreadable. The audit catalogue keeps the reason data field (version 1.3.0 declared it and an installation holds that version); nothing emits a value.

Consequences

A migration has a short window in which the channel is managed by neither (git entry removed, record not yet created) rather than by both; the channel stays as it is in Slack and adds and removes nothing in that window.

Alternatives considered

Keep the take-over. Rejected: it contradicts "a channel is managed one way".

Last writer wins. Rejected: silent, and the loser is whoever did not notice.