forked from sagnik/Project_Velocity
237 lines
11 KiB
SQL
237 lines
11 KiB
SQL
-- Oracle Canvas Schema — Section 16.4 of the Oracle Architecture Document v1.0
|
|
-- Run this against your PostgreSQL database to create the Oracle persistence layer.
|
|
-- Requires: UUID extension, JSONB support (PostgreSQL 14+)
|
|
|
|
-- ── Prerequisites ─────────────────────────────────────────────────────────────
|
|
|
|
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
|
|
|
|
-- ── Core tables ───────────────────────────────────────────────────────────────
|
|
|
|
CREATE TABLE IF NOT EXISTS oracle_canvas_pages (
|
|
page_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id TEXT NOT NULL,
|
|
owner_id TEXT NOT NULL,
|
|
branch_id TEXT NOT NULL,
|
|
branch_name TEXT NOT NULL DEFAULT 'main',
|
|
page_type TEXT NOT NULL DEFAULT 'main' CHECK (page_type IN ('main', 'fork')),
|
|
title TEXT NOT NULL DEFAULT 'Untitled Canvas',
|
|
is_shared BOOLEAN NOT NULL DEFAULT FALSE,
|
|
head_revision INTEGER NOT NULL DEFAULT 0,
|
|
base_revision INTEGER NOT NULL DEFAULT 0,
|
|
sharing_policy JSONB NOT NULL DEFAULT '{"shareMode":"direct_fork_only","allowReshare":false,"defaultForkVisibility":"private"}'::JSONB,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS oracle_canvas_page_revisions (
|
|
revision_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
page_id UUID NOT NULL REFERENCES oracle_canvas_pages(page_id) ON DELETE CASCADE,
|
|
tenant_id TEXT NOT NULL,
|
|
revision_number INTEGER NOT NULL,
|
|
commit_kind TEXT NOT NULL CHECK (commit_kind IN ('prompt', 'merge', 'rollback', 'manual_edit')),
|
|
commit_summary TEXT,
|
|
actor_id TEXT NOT NULL,
|
|
execution_id UUID,
|
|
merge_request_id UUID,
|
|
components_snapshot JSONB NOT NULL DEFAULT '[]'::JSONB,
|
|
idempotency_key TEXT UNIQUE,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
UNIQUE (page_id, revision_number)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS oracle_canvas_components (
|
|
component_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
page_id UUID NOT NULL REFERENCES oracle_canvas_pages(page_id) ON DELETE CASCADE,
|
|
tenant_id TEXT NOT NULL,
|
|
type TEXT NOT NULL,
|
|
title TEXT NOT NULL,
|
|
description TEXT,
|
|
version INTEGER NOT NULL DEFAULT 1,
|
|
lifecycle_state TEXT NOT NULL DEFAULT 'active' CHECK (lifecycle_state IN ('draft','active','superseded','archived','revoked')),
|
|
data_source_descriptor JSONB NOT NULL,
|
|
data_rows JSONB NOT NULL DEFAULT '[]'::JSONB,
|
|
visualization_parameters JSONB NOT NULL DEFAULT '{}'::JSONB,
|
|
data_bindings JSONB NOT NULL DEFAULT '{}'::JSONB,
|
|
provenance JSONB NOT NULL,
|
|
rendering_hints JSONB NOT NULL,
|
|
layout JSONB NOT NULL,
|
|
access_controls JSONB NOT NULL,
|
|
style_signature JSONB NOT NULL DEFAULT '{}'::JSONB,
|
|
validation_state JSONB NOT NULL DEFAULT '{}'::JSONB,
|
|
audit_log TEXT[] NOT NULL DEFAULT '{}',
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
ALTER TABLE oracle_canvas_components
|
|
ADD COLUMN IF NOT EXISTS data_rows JSONB NOT NULL DEFAULT '[]'::JSONB;
|
|
|
|
WITH latest_revisions AS (
|
|
SELECT DISTINCT ON (page_id, tenant_id)
|
|
page_id,
|
|
tenant_id,
|
|
components_snapshot
|
|
FROM oracle_canvas_page_revisions
|
|
ORDER BY page_id, tenant_id, revision_number DESC
|
|
),
|
|
snapshot_components AS (
|
|
SELECT
|
|
latest_revisions.page_id,
|
|
latest_revisions.tenant_id,
|
|
component->>'componentId' AS component_id,
|
|
COALESCE(component->'dataRows', '[]'::jsonb) AS data_rows
|
|
FROM latest_revisions,
|
|
jsonb_array_elements(latest_revisions.components_snapshot) AS component
|
|
)
|
|
UPDATE oracle_canvas_components occ
|
|
SET data_rows = snapshot_components.data_rows
|
|
FROM snapshot_components
|
|
WHERE occ.page_id = snapshot_components.page_id
|
|
AND occ.tenant_id = snapshot_components.tenant_id
|
|
AND occ.component_id::text = snapshot_components.component_id
|
|
AND occ.data_rows = '[]'::jsonb
|
|
AND snapshot_components.data_rows <> '[]'::jsonb;
|
|
|
|
CREATE TABLE IF NOT EXISTS oracle_prompt_executions (
|
|
execution_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id TEXT NOT NULL,
|
|
page_id UUID NOT NULL REFERENCES oracle_canvas_pages(page_id) ON DELETE CASCADE,
|
|
branch_id TEXT NOT NULL,
|
|
actor_id TEXT NOT NULL,
|
|
prompt TEXT NOT NULL,
|
|
intent_class TEXT NOT NULL DEFAULT 'analytical',
|
|
status TEXT NOT NULL DEFAULT 'received',
|
|
model_runtime TEXT NOT NULL DEFAULT 'nemoclaw_hosted',
|
|
semantic_model_version TEXT NOT NULL DEFAULT 'oracle_semantic_v1',
|
|
retrieval_plan JSONB,
|
|
visualization_plan JSONB,
|
|
warnings TEXT[] NOT NULL DEFAULT '{}',
|
|
summary TEXT,
|
|
components_created TEXT[] NOT NULL DEFAULT '{}',
|
|
client_request_id TEXT UNIQUE,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
completed_at TIMESTAMPTZ
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS oracle_component_templates (
|
|
template_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id TEXT NOT NULL,
|
|
name TEXT NOT NULL,
|
|
category TEXT NOT NULL,
|
|
status TEXT NOT NULL DEFAULT 'catalog_active',
|
|
origin TEXT NOT NULL DEFAULT 'premade',
|
|
version TEXT NOT NULL DEFAULT '1.0.0',
|
|
accepted_shapes TEXT[] NOT NULL DEFAULT '{}',
|
|
style_signature JSONB DEFAULT NULL,
|
|
validation_state JSONB DEFAULT NULL,
|
|
provenance JSONB DEFAULT NULL,
|
|
use_count INTEGER NOT NULL DEFAULT 0,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS oracle_forks (
|
|
fork_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
source_page_id UUID NOT NULL REFERENCES oracle_canvas_pages(page_id),
|
|
source_branch_id TEXT NOT NULL,
|
|
source_revision INTEGER NOT NULL,
|
|
fork_page_id UUID NOT NULL REFERENCES oracle_canvas_pages(page_id),
|
|
fork_branch_id TEXT NOT NULL,
|
|
recipient_user_id TEXT NOT NULL,
|
|
created_by TEXT NOT NULL,
|
|
status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active','merged','closed')),
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS oracle_merge_requests (
|
|
merge_request_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id TEXT NOT NULL,
|
|
source_page_id UUID NOT NULL REFERENCES oracle_canvas_pages(page_id),
|
|
source_branch_id TEXT NOT NULL,
|
|
source_head_revision INTEGER NOT NULL,
|
|
target_page_id UUID NOT NULL REFERENCES oracle_canvas_pages(page_id),
|
|
target_branch_id TEXT NOT NULL,
|
|
target_base_revision INTEGER NOT NULL,
|
|
title TEXT NOT NULL,
|
|
description TEXT,
|
|
status TEXT NOT NULL DEFAULT 'open' CHECK (status IN ('open','changes_requested','approved','merged','closed')),
|
|
conflicts JSONB NOT NULL DEFAULT '[]'::JSONB,
|
|
diff_summary JSONB DEFAULT NULL,
|
|
resolutions JSONB DEFAULT NULL,
|
|
created_by TEXT NOT NULL,
|
|
reviewed_by TEXT,
|
|
reviewer_comment TEXT,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS oracle_lineage_records (
|
|
lineage_record_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id TEXT NOT NULL,
|
|
source_kind TEXT NOT NULL,
|
|
source_id TEXT NOT NULL,
|
|
transformation_type TEXT NOT NULL,
|
|
transformation_spec_hash TEXT,
|
|
produced_kind TEXT NOT NULL,
|
|
produced_id TEXT NOT NULL,
|
|
policy_snapshot_id TEXT,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS oracle_audit_events (
|
|
audit_event_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id TEXT NOT NULL,
|
|
entity_type TEXT NOT NULL,
|
|
entity_id TEXT NOT NULL,
|
|
action TEXT NOT NULL,
|
|
actor_id TEXT NOT NULL,
|
|
actor_type TEXT NOT NULL DEFAULT 'user',
|
|
correlation_id TEXT NOT NULL,
|
|
execution_id UUID,
|
|
details JSONB NOT NULL DEFAULT '{}'::JSONB,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
-- ── Indexes ───────────────────────────────────────────────────────────────────
|
|
|
|
-- Canvas pages: tenant lookup, branch lookup
|
|
CREATE INDEX IF NOT EXISTS idx_oracle_pages_tenant ON oracle_canvas_pages(tenant_id);
|
|
CREATE INDEX IF NOT EXISTS idx_oracle_pages_owner ON oracle_canvas_pages(owner_id);
|
|
CREATE INDEX IF NOT EXISTS idx_oracle_pages_branch ON oracle_canvas_pages(branch_id);
|
|
|
|
-- Revisions: page-scoped revision queries
|
|
CREATE INDEX IF NOT EXISTS idx_oracle_revisions_page ON oracle_canvas_page_revisions(page_id, revision_number DESC);
|
|
CREATE INDEX IF NOT EXISTS idx_oracle_revisions_tenant ON oracle_canvas_page_revisions(tenant_id);
|
|
CREATE INDEX IF NOT EXISTS idx_oracle_revisions_execution ON oracle_canvas_page_revisions(execution_id);
|
|
|
|
-- Components: page-scoped, lifecycle
|
|
CREATE INDEX IF NOT EXISTS idx_oracle_components_page ON oracle_canvas_components(page_id, lifecycle_state);
|
|
CREATE INDEX IF NOT EXISTS idx_oracle_components_tenant ON oracle_canvas_components(tenant_id);
|
|
|
|
-- Prompt executions: page/actor lookup
|
|
CREATE INDEX IF NOT EXISTS idx_oracle_executions_page ON oracle_prompt_executions(page_id, created_at DESC);
|
|
CREATE INDEX IF NOT EXISTS idx_oracle_executions_actor ON oracle_prompt_executions(actor_id, created_at DESC);
|
|
|
|
-- Templates: tenant + category + status
|
|
CREATE INDEX IF NOT EXISTS idx_oracle_templates_tenant_cat ON oracle_component_templates(tenant_id, category, status);
|
|
|
|
-- Forks: source and recipient lookup
|
|
CREATE INDEX IF NOT EXISTS idx_oracle_forks_source ON oracle_forks(source_page_id);
|
|
CREATE INDEX IF NOT EXISTS idx_oracle_forks_recipient ON oracle_forks(recipient_user_id);
|
|
|
|
-- Merge requests: target/source page, status
|
|
CREATE INDEX IF NOT EXISTS idx_oracle_mrs_target ON oracle_merge_requests(target_page_id, status);
|
|
CREATE INDEX IF NOT EXISTS idx_oracle_mrs_source ON oracle_merge_requests(source_page_id, status);
|
|
CREATE INDEX IF NOT EXISTS idx_oracle_mrs_tenant ON oracle_merge_requests(tenant_id, status);
|
|
|
|
-- Lineage: source/produced lookups
|
|
CREATE INDEX IF NOT EXISTS idx_oracle_lineage_source ON oracle_lineage_records(source_kind, source_id);
|
|
CREATE INDEX IF NOT EXISTS idx_oracle_lineage_produced ON oracle_lineage_records(produced_kind, produced_id);
|
|
CREATE INDEX IF NOT EXISTS idx_oracle_lineage_tenant ON oracle_lineage_records(tenant_id);
|
|
|
|
-- Audit: entity lookup, correlation lookup
|
|
CREATE INDEX IF NOT EXISTS idx_oracle_audit_entity ON oracle_audit_events(entity_type, entity_id, created_at DESC);
|
|
CREATE INDEX IF NOT EXISTS idx_oracle_audit_correlation ON oracle_audit_events(correlation_id);
|
|
CREATE INDEX IF NOT EXISTS idx_oracle_audit_tenant ON oracle_audit_events(tenant_id, created_at DESC);
|