feat(channel-discovery): add purpose column + PATCH /api/channels/:id

Adds a free-form 'purpose' text field on Channel so agents (or anyone
creating a channel via API) can describe what the channel is for —
'debate broadcasts', 'security alerts', etc. — and other agents can
later find the right channel by intent rather than channel id.

Wire:
  - Channel.purpose (text, nullable; TypeORM synchronize auto-adds)
  - POST /api/channels accepts optional 'purpose' in body
  - GET /api/channels returns purpose on every row (already returns the
    full entity via {...c})
  - PATCH /api/channels/:id { purpose } — member-or-public auth (mirrors
    the close() rule). Today only 'purpose' is patchable; other fields
    would get their own typed branch.

Frontend create form continues to omit the field — purpose stays optional.
This pairs with Fabric.OpenclawPlugin's fabric-channel-set-purpose tool +
fabric-channel-list returning purpose, so agent workflows can say 'find
an announce channel about X' instead of pinning a UUID.
This commit is contained in:
h z
2026-05-23 19:22:00 +01:00
parent 985b06a886
commit cb7b3bb5fe
3 changed files with 62 additions and 1 deletions

View File

@@ -23,6 +23,16 @@ export class Channel {
@Column({ type: 'varchar', length: 16, default: 'text' })
kind!: 'text' | 'announcement';
// Free-form description of what this channel is for — what topics get
// posted, who participates, why it exists. Surfaced via GET /api/channels
// so agents can pick a channel by intent ("which announce channel is for
// debate broadcasts?") without channel id hard-coded into workflows.
// Any channel member can set it via PATCH /api/channels/:id (writes
// require membership the same way moveToBypass / close do). The frontend
// create form does NOT post this today — purpose stays optional.
@Column({ type: 'text', nullable: true })
purpose!: string | null;
@Column({ type: 'boolean', default: false })
isPrivate!: boolean;