···
avatar_cid TEXT, -- CID of avatar image blob
banner_cid TEXT, -- CID of banner image blob
17
-
-- Ownership & hosting
18
-
owner_did TEXT NOT NULL, -- DID of community owner (instance in V1)
17
+
-- Ownership & hosting (V2: community owns its own repo)
18
+
owner_did TEXT NOT NULL, -- V1: instance DID, V2: same as did (self-owned)
created_by_did TEXT NOT NULL, -- DID of user who created community
hosted_by_did TEXT NOT NULL, -- DID of hosting instance
22
+
-- V2: PDS Account Credentials (community has its own PDS account)
23
+
pds_email TEXT, -- System email for community PDS account
24
+
pds_password_hash TEXT, -- bcrypt hash for re-authentication
25
+
pds_access_token TEXT, -- JWT for API calls (expires)
26
+
pds_refresh_token TEXT, -- For refreshing sessions
27
+
pds_url TEXT DEFAULT 'http://localhost:2583', -- PDS hosting this community's repo
-- Visibility & federation
visibility TEXT NOT NULL DEFAULT 'public' CHECK (visibility IN ('public', 'unlisted', 'private')),
···
CREATE INDEX idx_communities_created_at ON communities(created_at);
CREATE INDEX idx_communities_name_trgm ON communities USING gin(name gin_trgm_ops); -- For fuzzy search
CREATE INDEX idx_communities_description_trgm ON communities USING gin(description gin_trgm_ops);
63
+
CREATE INDEX idx_communities_pds_email ON communities(pds_email); -- V2: For credential lookups
65
+
-- Security comments for V2 credentials
66
+
COMMENT ON COLUMN communities.pds_password_hash IS 'V2: bcrypt hash - NEVER return in API responses';
67
+
COMMENT ON COLUMN communities.pds_access_token IS 'V2: JWT - rotate frequently, NEVER log';
68
+
COMMENT ON COLUMN communities.pds_refresh_token IS 'V2: Refresh token - NEVER log or expose in APIs';
-- Subscriptions table: lightweight feed following
CREATE TABLE community_subscriptions (
···
CREATE INDEX idx_moderation_created_at ON community_moderation(created_at);
136
+
-- Drop security comments
137
+
COMMENT ON COLUMN communities.pds_refresh_token IS NULL;
138
+
COMMENT ON COLUMN communities.pds_access_token IS NULL;
139
+
COMMENT ON COLUMN communities.pds_password_hash IS NULL;
141
+
DROP INDEX IF EXISTS idx_communities_pds_email;
DROP INDEX IF EXISTS idx_moderation_created_at;
DROP INDEX IF EXISTS idx_moderation_action;
DROP INDEX IF EXISTS idx_moderation_instance;