block / block/buzz

Expose typed channel lifecycle (active | archived) on channel reads, not only as a write error

Open
#5,669 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
32.7k
Forks
4.3k
Avg merge
1d 13h
Merged PRs (30d)
253

Description

## Ask

Expose a typed channel lifecycle fact — `active | archived` — on the channel **read** surface (`buzz channels get` and `buzz channels list`, and the underlying API), so a consumer can know a channel is archived without attempting a write.

## Why this is a contract gap rather than a nice-to-have

Today the only way to learn that a channel is archived is to write to it and read the error:

```
$ buzz channels add-member --channel 49bb9526-... --pubkey a9f344c3...
400: invalid: channel is archived
```

`buzz channels get` and `buzz channels list` return the same shape for an archived channel as for an active one, with no flag distinguishing them. That has two consequences we hit in production today:

1. **A write-probe is the only classifier, and it is not a safe one.** The archive check fires *before* the permission check, so `400: invalid: channel is archived` and an authorization failure are indistinguishable from the error alone — and both are indistinguishable from a transport failure once a client collapses the call to a boolean. Classifying on that string means misclassifying authorization and transport problems as "archived".
2. **An enumerating service cannot avoid doomed writes.** `buzz channels list` includes archived channels with no way to filter them, so any service that reconciles state across the channel inventory will attempt writes it can never complete.

## What it cost us

`BuzzObserverd` maintains a compact workflow register in each work channel's name. On a deploy today it reconciled its full channel inventory and quarantined 15 lanes with `channel name update failed`. On probing, **12 of the 15 were simply archived channels** — finished work that will never accept a write again — and only 2 were a genuine authorization gap. The service had no way to tell those apart, so it retried and quarantined finished lanes permanently and reported itself `degraded` on the strength of it.

Our design owner ruled that we may not work around this client-side: inferring "archived" from a failed write or from a generic falsy update result conflates it with authorization and transport failure, so the correct shape is expand-then-migrate — the read contract exposes the lifecycle fact first, consumers carry it, and only then may an archived channel be excluded from write paths. That leaves the workaround-free path blocked on this read contract.

## Shape we would consume

Either is fine; the first is smaller:

- A `lifecycle` (or `archived`) field on the channel object returned by `channels get` / `channels list`.
- Optionally a filter on `channels list` (`--lifecycle active`) so an enumerating consumer does not have to page archived channels at all.

What matters is that it is a **typed fact on a read**, not an error string on a write, and that it is present on both the single-channel read and the inventory listing.

## Notes

- Archived channels remain listed by `channels list` today, which is what makes the inventory case unavoidable rather than a client bug.
- We are not asking for any change to archive semantics, permissions, or write behaviour — only for the existing state to be observable on the read path.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.