mirror of
https://codeberg.org/likwid/likwid.git
synced 2026-02-10 05:23:09 +00:00
347 lines
12 KiB
MySQL
347 lines
12 KiB
MySQL
|
|
-- ============================================================================
|
||
|
|
-- MULTI-COMMUNITY FEDERATION PLUGIN
|
||
|
|
-- Cross-instance collaboration, federated decisions, shared governance
|
||
|
|
-- ============================================================================
|
||
|
|
|
||
|
|
CREATE TYPE federation_status AS ENUM ('pending', 'active', 'suspended', 'revoked');
|
||
|
|
CREATE TYPE sync_direction AS ENUM ('push', 'pull', 'bidirectional');
|
||
|
|
|
||
|
|
-- ============================================================================
|
||
|
|
-- FEDERATED INSTANCES
|
||
|
|
-- Known remote Likwid instances
|
||
|
|
-- ============================================================================
|
||
|
|
|
||
|
|
CREATE TABLE federated_instances (
|
||
|
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||
|
|
instance_url VARCHAR(500) NOT NULL UNIQUE,
|
||
|
|
instance_name VARCHAR(200) NOT NULL,
|
||
|
|
instance_description TEXT,
|
||
|
|
|
||
|
|
-- Trust & verification
|
||
|
|
public_key TEXT,
|
||
|
|
is_verified BOOLEAN NOT NULL DEFAULT FALSE,
|
||
|
|
verified_at TIMESTAMPTZ,
|
||
|
|
trust_level INT NOT NULL DEFAULT 1, -- 1-5
|
||
|
|
|
||
|
|
-- Status
|
||
|
|
status federation_status NOT NULL DEFAULT 'pending',
|
||
|
|
|
||
|
|
-- Capabilities
|
||
|
|
supported_features VARCHAR(100)[] DEFAULT '{}',
|
||
|
|
protocol_version VARCHAR(20) NOT NULL DEFAULT '1.0',
|
||
|
|
|
||
|
|
-- Statistics
|
||
|
|
last_sync_at TIMESTAMPTZ,
|
||
|
|
sync_failures INT NOT NULL DEFAULT 0,
|
||
|
|
total_syncs INT NOT NULL DEFAULT 0,
|
||
|
|
|
||
|
|
-- Metadata
|
||
|
|
admin_contact VARCHAR(300),
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX idx_federated_instances_status ON federated_instances(status);
|
||
|
|
CREATE INDEX idx_federated_instances_url ON federated_instances(instance_url);
|
||
|
|
|
||
|
|
-- ============================================================================
|
||
|
|
-- COMMUNITY FEDERATIONS
|
||
|
|
-- Links between local and remote communities
|
||
|
|
-- ============================================================================
|
||
|
|
|
||
|
|
CREATE TABLE community_federations (
|
||
|
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||
|
|
local_community_id UUID NOT NULL REFERENCES communities(id) ON DELETE CASCADE,
|
||
|
|
remote_instance_id UUID NOT NULL REFERENCES federated_instances(id) ON DELETE CASCADE,
|
||
|
|
remote_community_id UUID NOT NULL,
|
||
|
|
remote_community_name VARCHAR(200),
|
||
|
|
|
||
|
|
-- Configuration
|
||
|
|
sync_direction sync_direction NOT NULL DEFAULT 'bidirectional',
|
||
|
|
sync_proposals BOOLEAN NOT NULL DEFAULT TRUE,
|
||
|
|
sync_votes BOOLEAN NOT NULL DEFAULT FALSE,
|
||
|
|
sync_comments BOOLEAN NOT NULL DEFAULT FALSE,
|
||
|
|
sync_decisions BOOLEAN NOT NULL DEFAULT TRUE,
|
||
|
|
|
||
|
|
-- Status
|
||
|
|
status federation_status NOT NULL DEFAULT 'pending',
|
||
|
|
approved_locally BOOLEAN NOT NULL DEFAULT FALSE,
|
||
|
|
approved_remotely BOOLEAN NOT NULL DEFAULT FALSE,
|
||
|
|
|
||
|
|
-- Mapping
|
||
|
|
member_mapping JSONB DEFAULT '{}',
|
||
|
|
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||
|
|
UNIQUE(local_community_id, remote_instance_id, remote_community_id)
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX idx_community_federations_local ON community_federations(local_community_id);
|
||
|
|
CREATE INDEX idx_community_federations_remote ON community_federations(remote_instance_id);
|
||
|
|
|
||
|
|
-- ============================================================================
|
||
|
|
-- FEDERATED PROPOSALS
|
||
|
|
-- Proposals shared across federated communities
|
||
|
|
-- ============================================================================
|
||
|
|
|
||
|
|
CREATE TABLE federated_proposals (
|
||
|
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||
|
|
federation_id UUID NOT NULL REFERENCES community_federations(id) ON DELETE CASCADE,
|
||
|
|
|
||
|
|
-- Local reference
|
||
|
|
local_proposal_id UUID REFERENCES proposals(id) ON DELETE SET NULL,
|
||
|
|
|
||
|
|
-- Remote reference
|
||
|
|
remote_proposal_id UUID NOT NULL,
|
||
|
|
remote_url VARCHAR(500),
|
||
|
|
|
||
|
|
-- Sync metadata
|
||
|
|
is_origin_local BOOLEAN NOT NULL,
|
||
|
|
last_synced_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||
|
|
sync_hash VARCHAR(64),
|
||
|
|
|
||
|
|
-- Status
|
||
|
|
sync_status VARCHAR(50) NOT NULL DEFAULT 'synced',
|
||
|
|
conflict_detected BOOLEAN NOT NULL DEFAULT FALSE,
|
||
|
|
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX idx_federated_proposals_federation ON federated_proposals(federation_id);
|
||
|
|
CREATE INDEX idx_federated_proposals_local ON federated_proposals(local_proposal_id);
|
||
|
|
|
||
|
|
-- ============================================================================
|
||
|
|
-- FEDERATED DECISIONS
|
||
|
|
-- Cross-community voting results
|
||
|
|
-- ============================================================================
|
||
|
|
|
||
|
|
CREATE TABLE federated_decisions (
|
||
|
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||
|
|
federated_proposal_id UUID NOT NULL REFERENCES federated_proposals(id) ON DELETE CASCADE,
|
||
|
|
|
||
|
|
-- Decision details
|
||
|
|
decision_type VARCHAR(50) NOT NULL,
|
||
|
|
outcome VARCHAR(50) NOT NULL,
|
||
|
|
|
||
|
|
-- Aggregated results (no individual votes)
|
||
|
|
participating_communities INT NOT NULL DEFAULT 1,
|
||
|
|
total_votes INT NOT NULL DEFAULT 0,
|
||
|
|
approval_percentage DECIMAL(5,2),
|
||
|
|
|
||
|
|
-- Per-community breakdown
|
||
|
|
community_results JSONB NOT NULL DEFAULT '[]',
|
||
|
|
|
||
|
|
-- Finalization
|
||
|
|
is_final BOOLEAN NOT NULL DEFAULT FALSE,
|
||
|
|
finalized_at TIMESTAMPTZ,
|
||
|
|
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX idx_federated_decisions_proposal ON federated_decisions(federated_proposal_id);
|
||
|
|
|
||
|
|
-- ============================================================================
|
||
|
|
-- SYNC LOG
|
||
|
|
-- Track all federation sync operations
|
||
|
|
-- ============================================================================
|
||
|
|
|
||
|
|
CREATE TABLE federation_sync_log (
|
||
|
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||
|
|
federation_id UUID REFERENCES community_federations(id) ON DELETE SET NULL,
|
||
|
|
instance_id UUID REFERENCES federated_instances(id) ON DELETE SET NULL,
|
||
|
|
|
||
|
|
-- Operation
|
||
|
|
operation_type VARCHAR(50) NOT NULL,
|
||
|
|
direction sync_direction NOT NULL,
|
||
|
|
|
||
|
|
-- Results
|
||
|
|
records_sent INT NOT NULL DEFAULT 0,
|
||
|
|
records_received INT NOT NULL DEFAULT 0,
|
||
|
|
conflicts_detected INT NOT NULL DEFAULT 0,
|
||
|
|
|
||
|
|
-- Status
|
||
|
|
success BOOLEAN NOT NULL,
|
||
|
|
error_message TEXT,
|
||
|
|
duration_ms INT,
|
||
|
|
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX idx_sync_log_federation ON federation_sync_log(federation_id);
|
||
|
|
CREATE INDEX idx_sync_log_time ON federation_sync_log(created_at);
|
||
|
|
|
||
|
|
-- ============================================================================
|
||
|
|
-- FEDERATION REQUESTS
|
||
|
|
-- Pending federation requests
|
||
|
|
-- ============================================================================
|
||
|
|
|
||
|
|
CREATE TABLE federation_requests (
|
||
|
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||
|
|
|
||
|
|
-- Request details
|
||
|
|
from_instance_url VARCHAR(500) NOT NULL,
|
||
|
|
from_community_name VARCHAR(200),
|
||
|
|
to_community_id UUID REFERENCES communities(id) ON DELETE CASCADE,
|
||
|
|
|
||
|
|
-- Message
|
||
|
|
request_message TEXT,
|
||
|
|
proposed_config JSONB,
|
||
|
|
|
||
|
|
-- Status
|
||
|
|
status VARCHAR(50) NOT NULL DEFAULT 'pending',
|
||
|
|
reviewed_by UUID REFERENCES users(id),
|
||
|
|
reviewed_at TIMESTAMPTZ,
|
||
|
|
review_notes TEXT,
|
||
|
|
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||
|
|
expires_at TIMESTAMPTZ DEFAULT NOW() + INTERVAL '30 days'
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX idx_federation_requests_community ON federation_requests(to_community_id);
|
||
|
|
CREATE INDEX idx_federation_requests_pending ON federation_requests(status) WHERE status = 'pending';
|
||
|
|
|
||
|
|
-- ============================================================================
|
||
|
|
-- HELPER FUNCTIONS
|
||
|
|
-- ============================================================================
|
||
|
|
|
||
|
|
CREATE OR REPLACE FUNCTION register_federated_instance(
|
||
|
|
p_url VARCHAR(500),
|
||
|
|
p_name VARCHAR(200),
|
||
|
|
p_description TEXT DEFAULT NULL,
|
||
|
|
p_public_key TEXT DEFAULT NULL
|
||
|
|
) RETURNS UUID AS $$
|
||
|
|
DECLARE
|
||
|
|
v_instance_id UUID;
|
||
|
|
BEGIN
|
||
|
|
INSERT INTO federated_instances (instance_url, instance_name, instance_description, public_key)
|
||
|
|
VALUES (p_url, p_name, p_description, p_public_key)
|
||
|
|
ON CONFLICT (instance_url) DO UPDATE SET
|
||
|
|
instance_name = p_name,
|
||
|
|
instance_description = COALESCE(p_description, federated_instances.instance_description),
|
||
|
|
public_key = COALESCE(p_public_key, federated_instances.public_key),
|
||
|
|
updated_at = NOW()
|
||
|
|
RETURNING id INTO v_instance_id;
|
||
|
|
|
||
|
|
RETURN v_instance_id;
|
||
|
|
END;
|
||
|
|
$$ LANGUAGE plpgsql;
|
||
|
|
|
||
|
|
CREATE OR REPLACE FUNCTION create_community_federation(
|
||
|
|
p_local_community_id UUID,
|
||
|
|
p_remote_instance_id UUID,
|
||
|
|
p_remote_community_id UUID,
|
||
|
|
p_remote_community_name VARCHAR(200),
|
||
|
|
p_sync_direction sync_direction DEFAULT 'bidirectional'
|
||
|
|
) RETURNS UUID AS $$
|
||
|
|
DECLARE
|
||
|
|
v_federation_id UUID;
|
||
|
|
BEGIN
|
||
|
|
INSERT INTO community_federations (
|
||
|
|
local_community_id, remote_instance_id, remote_community_id,
|
||
|
|
remote_community_name, sync_direction
|
||
|
|
) VALUES (
|
||
|
|
p_local_community_id, p_remote_instance_id, p_remote_community_id,
|
||
|
|
p_remote_community_name, p_sync_direction
|
||
|
|
)
|
||
|
|
ON CONFLICT (local_community_id, remote_instance_id, remote_community_id) DO UPDATE SET
|
||
|
|
remote_community_name = p_remote_community_name,
|
||
|
|
sync_direction = p_sync_direction,
|
||
|
|
updated_at = NOW()
|
||
|
|
RETURNING id INTO v_federation_id;
|
||
|
|
|
||
|
|
RETURN v_federation_id;
|
||
|
|
END;
|
||
|
|
$$ LANGUAGE plpgsql;
|
||
|
|
|
||
|
|
CREATE OR REPLACE FUNCTION get_federation_stats(p_community_id UUID)
|
||
|
|
RETURNS TABLE (
|
||
|
|
total_federations BIGINT,
|
||
|
|
active_federations BIGINT,
|
||
|
|
federated_proposals BIGINT,
|
||
|
|
total_syncs BIGINT,
|
||
|
|
last_sync TIMESTAMPTZ
|
||
|
|
) AS $$
|
||
|
|
BEGIN
|
||
|
|
RETURN QUERY
|
||
|
|
SELECT
|
||
|
|
COUNT(DISTINCT cf.id)::BIGINT,
|
||
|
|
COUNT(DISTINCT cf.id) FILTER (WHERE cf.status = 'active')::BIGINT,
|
||
|
|
COUNT(DISTINCT fp.id)::BIGINT,
|
||
|
|
SUM(fi.total_syncs)::BIGINT,
|
||
|
|
MAX(fi.last_sync_at)
|
||
|
|
FROM community_federations cf
|
||
|
|
LEFT JOIN federated_instances fi ON fi.id = cf.remote_instance_id
|
||
|
|
LEFT JOIN federated_proposals fp ON fp.federation_id = cf.id
|
||
|
|
WHERE cf.local_community_id = p_community_id;
|
||
|
|
END;
|
||
|
|
$$ LANGUAGE plpgsql;
|
||
|
|
|
||
|
|
-- ============================================================================
|
||
|
|
-- VIEWS
|
||
|
|
-- ============================================================================
|
||
|
|
|
||
|
|
CREATE OR REPLACE VIEW active_federations AS
|
||
|
|
SELECT
|
||
|
|
cf.id,
|
||
|
|
cf.local_community_id,
|
||
|
|
lc.name AS local_community_name,
|
||
|
|
fi.instance_url,
|
||
|
|
fi.instance_name,
|
||
|
|
cf.remote_community_id,
|
||
|
|
cf.remote_community_name,
|
||
|
|
cf.sync_direction::text,
|
||
|
|
cf.status::text,
|
||
|
|
fi.last_sync_at,
|
||
|
|
COUNT(fp.id) AS shared_proposals
|
||
|
|
FROM community_federations cf
|
||
|
|
JOIN communities lc ON lc.id = cf.local_community_id
|
||
|
|
JOIN federated_instances fi ON fi.id = cf.remote_instance_id
|
||
|
|
LEFT JOIN federated_proposals fp ON fp.federation_id = cf.id
|
||
|
|
WHERE cf.status = 'active'
|
||
|
|
GROUP BY cf.id, cf.local_community_id, lc.name, fi.instance_url, fi.instance_name,
|
||
|
|
cf.remote_community_id, cf.remote_community_name, cf.sync_direction, cf.status, fi.last_sync_at;
|
||
|
|
|
||
|
|
CREATE OR REPLACE VIEW federation_health AS
|
||
|
|
SELECT
|
||
|
|
fi.id AS instance_id,
|
||
|
|
fi.instance_url,
|
||
|
|
fi.instance_name,
|
||
|
|
fi.status::text,
|
||
|
|
fi.trust_level,
|
||
|
|
fi.last_sync_at,
|
||
|
|
fi.sync_failures,
|
||
|
|
fi.total_syncs,
|
||
|
|
CASE
|
||
|
|
WHEN fi.total_syncs = 0 THEN 0
|
||
|
|
ELSE ((fi.total_syncs - fi.sync_failures)::DECIMAL / fi.total_syncs * 100)
|
||
|
|
END AS success_rate,
|
||
|
|
COUNT(cf.id) AS community_count
|
||
|
|
FROM federated_instances fi
|
||
|
|
LEFT JOIN community_federations cf ON cf.remote_instance_id = fi.id AND cf.status = 'active'
|
||
|
|
GROUP BY fi.id, fi.instance_url, fi.instance_name, fi.status, fi.trust_level,
|
||
|
|
fi.last_sync_at, fi.sync_failures, fi.total_syncs;
|
||
|
|
|
||
|
|
-- ============================================================================
|
||
|
|
-- PLUGIN REGISTRATION
|
||
|
|
-- ============================================================================
|
||
|
|
|
||
|
|
INSERT INTO plugins (name, description, version, is_core, is_active, settings_schema)
|
||
|
|
VALUES (
|
||
|
|
'federation',
|
||
|
|
'Multi-community federation enabling cross-instance collaboration, shared proposals, and federated decision-making.',
|
||
|
|
'1.0.0',
|
||
|
|
false,
|
||
|
|
true,
|
||
|
|
jsonb_build_object(
|
||
|
|
'type', 'object',
|
||
|
|
'properties', jsonb_build_object(
|
||
|
|
'allow_incoming_requests', jsonb_build_object('type', 'boolean', 'default', true),
|
||
|
|
'auto_approve_verified', jsonb_build_object('type', 'boolean', 'default', false),
|
||
|
|
'min_trust_level', jsonb_build_object('type', 'integer', 'default', 2, 'minimum', 1, 'maximum', 5),
|
||
|
|
'sync_interval_minutes', jsonb_build_object('type', 'integer', 'default', 15),
|
||
|
|
'share_vote_counts', jsonb_build_object('type', 'boolean', 'default', true),
|
||
|
|
'share_individual_votes', jsonb_build_object('type', 'boolean', 'default', false)
|
||
|
|
)
|
||
|
|
)
|
||
|
|
) ON CONFLICT (name) DO UPDATE SET version = EXCLUDED.version;
|