-- v1.1.6: Explicit registration for externally-subscribable topics. -- -- Internal-only topics remain implicit per the §5 design-notes -- decision: anyone can publish_durable("any.topic", msg) and triggers -- can subscribe without a row here. This table only holds topics that -- have been explicitly externalized — external SSE subscribers can -- only subscribe to topics with a row here AND external_subscribable -- = TRUE. -- -- The publish path (v1.1.5's publish_durable) does NOT consult this -- table: publishing to a topic with no row still fans out to triggers -- and to any in-process external subscribers (none exist for an -- unregistered topic, since external subscribers can't subscribe to -- one). The topics table is read by the SSE subscribe path only. -- -- auth_mode values: 'public' + 'token' in v1.1.6. 'session' arrives in -- v1.1.8 (users-SDK); 'script' arrives in v1.2 (script-mediated auth). -- The CHECK constraint extends in those releases. CREATE TABLE topics ( app_id UUID NOT NULL REFERENCES apps(id) ON DELETE CASCADE, name TEXT NOT NULL, external_subscribable BOOL NOT NULL DEFAULT FALSE, auth_mode TEXT NOT NULL DEFAULT 'public' CHECK (auth_mode IN ('public', 'token')), created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), PRIMARY KEY (app_id, name) ); -- Hot lookup: "is topic T in app X externally subscribable?" The PK -- (app_id, name) already covers this; an explicit index is redundant.