feat: add leader AgentBus task summaries
This commit is contained in:
1 parent
f4664997a8
commit
1a3ab63700
18 files changed
+2158
-19
No files matched your search
@@ -0,0 +1,131 @@
|
||||
-- Default-off, organization-wide task-summary subscriptions for team leads.
|
||||
-- This is a read-only projection: it never grants task mutation or ERP
|
||||
-- execution authority and it does not reuse employee AgentBus reply rows.
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS user_channels_organization_id_id_notification_idx
|
||||
ON user_channels (organization_id, id);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS tasks_organization_id_id_notification_idx
|
||||
ON tasks (organization_id, id);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS outbox_events_leader_summary_projection_idx
|
||||
ON outbox_events (organization_id, aggregate_id, created_at DESC)
|
||||
WHERE topic = 'task.updated' AND aggregate_type = 'task';
|
||||
|
||||
CREATE INDEX IF NOT EXISTS tasks_leader_summary_projection_idx
|
||||
ON tasks (organization_id, source, status, assigned_user_id, id)
|
||||
WHERE assigned_user_id IS NOT NULL;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS leader_task_summary_subscriptions (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
organization_id uuid NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
||||
leader_user_id uuid NOT NULL,
|
||||
channel_id uuid NOT NULL,
|
||||
scope text NOT NULL DEFAULT 'organization',
|
||||
include_manual boolean NOT NULL DEFAULT true,
|
||||
include_agentbus boolean NOT NULL DEFAULT true,
|
||||
enabled boolean NOT NULL DEFAULT false,
|
||||
starts_at timestamptz NOT NULL DEFAULT now(),
|
||||
revision integer NOT NULL DEFAULT 0,
|
||||
recipient_address_ciphertext text NOT NULL,
|
||||
recipient_address_fingerprint text NOT NULL,
|
||||
conversation_id_ciphertext text NOT NULL,
|
||||
conversation_id_fingerprint text NOT NULL,
|
||||
target_verified_at timestamptz,
|
||||
target_verified_by uuid REFERENCES users(id) ON DELETE SET NULL,
|
||||
created_by uuid REFERENCES users(id) ON DELETE SET NULL,
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
updated_at timestamptz NOT NULL DEFAULT now(),
|
||||
CONSTRAINT leader_task_summary_subscriptions_scope_check
|
||||
CHECK (scope = 'organization'),
|
||||
CONSTRAINT leader_task_summary_subscriptions_sources_check
|
||||
CHECK (include_manual OR include_agentbus),
|
||||
CONSTRAINT leader_task_summary_subscriptions_revision_check
|
||||
CHECK (revision >= 0),
|
||||
CONSTRAINT leader_task_summary_subscriptions_recipient_fingerprint_check
|
||||
CHECK (recipient_address_fingerprint ~ '^[a-f0-9]{64}$'),
|
||||
CONSTRAINT leader_task_summary_subscriptions_conversation_fingerprint_check
|
||||
CHECK (conversation_id_fingerprint ~ '^[a-f0-9]{64}$'),
|
||||
CONSTRAINT leader_task_summary_subscriptions_leader_scope_fkey
|
||||
FOREIGN KEY (organization_id, leader_user_id)
|
||||
REFERENCES users (organization_id, id)
|
||||
ON DELETE CASCADE,
|
||||
CONSTRAINT leader_task_summary_subscriptions_channel_scope_fkey
|
||||
FOREIGN KEY (organization_id, channel_id)
|
||||
REFERENCES user_channels (organization_id, id)
|
||||
ON DELETE CASCADE,
|
||||
UNIQUE (organization_id, leader_user_id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS leader_task_summary_subscriptions_active_idx
|
||||
ON leader_task_summary_subscriptions
|
||||
(organization_id, enabled, starts_at, channel_id)
|
||||
WHERE enabled = true;
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS leader_task_summary_subscriptions_organization_id_id_idx
|
||||
ON leader_task_summary_subscriptions (organization_id, id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS leader_task_summary_deliveries (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
organization_id uuid NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
||||
subscription_id uuid NOT NULL,
|
||||
subscription_revision integer NOT NULL,
|
||||
task_id uuid NOT NULL,
|
||||
leader_user_id uuid NOT NULL,
|
||||
channel_id uuid NOT NULL,
|
||||
source_outbox_event_id bigint NOT NULL,
|
||||
milestone text NOT NULL,
|
||||
recipient_address_ciphertext text NOT NULL,
|
||||
recipient_address_fingerprint text NOT NULL,
|
||||
conversation_id_ciphertext text NOT NULL,
|
||||
conversation_id_fingerprint text NOT NULL,
|
||||
payload_ciphertext text NOT NULL,
|
||||
payload_fingerprint text NOT NULL,
|
||||
delivery_status text NOT NULL DEFAULT 'pending',
|
||||
attempt_count integer NOT NULL DEFAULT 0,
|
||||
next_attempt_at timestamptz NOT NULL DEFAULT now(),
|
||||
last_error text,
|
||||
delivered_at timestamptz,
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
updated_at timestamptz NOT NULL DEFAULT now(),
|
||||
CONSTRAINT leader_task_summary_deliveries_milestone_check
|
||||
CHECK (milestone IN ('final', 'needs_review', 'resolved')),
|
||||
CONSTRAINT leader_task_summary_deliveries_status_check
|
||||
CHECK (delivery_status IN ('pending', 'sending', 'delivered', 'failed', 'cancelled')),
|
||||
CONSTRAINT leader_task_summary_deliveries_attempt_check
|
||||
CHECK (attempt_count >= 0),
|
||||
CONSTRAINT leader_task_summary_deliveries_revision_check
|
||||
CHECK (subscription_revision >= 0),
|
||||
CONSTRAINT leader_task_summary_deliveries_payload_fingerprint_check
|
||||
CHECK (payload_fingerprint ~ '^[a-f0-9]{64}$'),
|
||||
CONSTRAINT leader_task_summary_deliveries_recipient_fingerprint_check
|
||||
CHECK (recipient_address_fingerprint ~ '^[a-f0-9]{64}$'),
|
||||
CONSTRAINT leader_task_summary_deliveries_conversation_fingerprint_check
|
||||
CHECK (conversation_id_fingerprint ~ '^[a-f0-9]{64}$'),
|
||||
CONSTRAINT leader_task_summary_deliveries_subscription_scope_fkey
|
||||
FOREIGN KEY (organization_id, subscription_id)
|
||||
REFERENCES leader_task_summary_subscriptions (organization_id, id)
|
||||
ON DELETE CASCADE,
|
||||
CONSTRAINT leader_task_summary_deliveries_task_scope_fkey
|
||||
FOREIGN KEY (organization_id, task_id)
|
||||
REFERENCES tasks (organization_id, id)
|
||||
ON DELETE CASCADE,
|
||||
CONSTRAINT leader_task_summary_deliveries_leader_scope_fkey
|
||||
FOREIGN KEY (organization_id, leader_user_id)
|
||||
REFERENCES users (organization_id, id)
|
||||
ON DELETE CASCADE,
|
||||
CONSTRAINT leader_task_summary_deliveries_channel_scope_fkey
|
||||
FOREIGN KEY (organization_id, channel_id)
|
||||
REFERENCES user_channels (organization_id, id)
|
||||
ON DELETE CASCADE,
|
||||
UNIQUE (subscription_id, subscription_revision, task_id, milestone)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS leader_task_summary_deliveries_pending_idx
|
||||
ON leader_task_summary_deliveries
|
||||
(channel_id, delivery_status, next_attempt_at, created_at, id)
|
||||
WHERE delivery_status IN ('pending', 'sending', 'failed');
|
||||
|
||||
CREATE INDEX IF NOT EXISTS leader_task_summary_deliveries_task_idx
|
||||
ON leader_task_summary_deliveries
|
||||
(organization_id, task_id, leader_user_id, created_at DESC);
|
||||
Reference in new issue
Block a user