import { Column, CreateDateColumn, Entity, Index, PrimaryGeneratedColumn } from 'typeorm'; @Entity('channels') @Index(['guildId', 'createdAt']) export class Channel { @PrimaryGeneratedColumn('uuid') id!: string; @Index() @Column({ type: 'char', length: 36 }) guildId!: string; @Column({ type: 'varchar', length: 120 }) name!: string; @Column({ name: 'x_type', type: 'enum', enum: ['general', 'work', 'report', 'discuss', 'triage', 'custom', 'dm', 'announce'], }) xType!: 'general' | 'work' | 'report' | 'discuss' | 'triage' | 'custom' | 'dm' | 'announce'; @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; // public channels are visible to every guild member (including those who // join after the channel was created); default off (unchecked) @Column({ type: 'boolean', default: false }) isPublic!: boolean; // closed (e.g. discussion-complete): history readable, new posts rejected @Column({ type: 'boolean', default: false }) closed!: boolean; @Index() @Column({ default: 0 }) lastSeq!: number; @CreateDateColumn() @Index() createdAt!: Date; }