thinkwork-cli 0.12.15 → 0.12.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{api-client-4VT3FWOH.js → api-client-JUBCQQDF.js} +1 -1
- package/dist/{chunk-H7AB42ES.js → chunk-STY44FQO.js} +13 -0
- package/dist/cli.js +1107 -10225
- package/dist/commands/enterprise/templates/deploy-repo/docs/runbook.md +3 -8
- package/dist/commands/enterprise/templates/deploy-repo/terraform/main.tf +1 -184
- package/dist/drizzle/0050_brain_v0_entity_subtype.sql +2 -2
- package/dist/drizzle/0051_brain_v0_tenant_entity_pages.sql +6 -6
- package/dist/drizzle/0052_brain_v0_external_refs.sql +2 -2
- package/dist/drizzle/0053_brain_v0_unresolved_mentions_subtype.sql +2 -2
- package/dist/drizzle/0145_knowledge_graph_thread_ingest.sql +14 -14
- package/dist/drizzle/0146_knowledge_graph_source_scope.sql +1 -1
- package/dist/drizzle/0157_knowledge_graph_observations_source.sql +2 -2
- package/dist/drizzle/0158_wiki_tenant_scope.sql +1 -1
- package/dist/drizzle/0165_plugin_premium_entitlements.sql +2 -2
- package/dist/drizzle/{0166_company_brain_substrate_contract.sql → 0166_brain_substrate_contract.sql} +9 -9
- package/dist/drizzle/{0167_company_brain_artifact_manifest_runtime.sql → 0167_brain_artifact_manifest_runtime.sql} +5 -5
- package/dist/drizzle/0168_eval_skill_gate.sql +1 -1
- package/dist/drizzle/0183_okf_artifact_manifests.sql +1 -1
- package/dist/drizzle/0197_rcm_context_columns.sql +28 -0
- package/dist/drizzle/0200_eval_results_execution_tier.sql +40 -0
- package/dist/drizzle/0201_brain_dream_runs.sql +72 -0
- package/dist/drizzle/0202_backfill_thread_participants_from_senders.sql +110 -0
- package/dist/drizzle/0203_threads_mode_override.sql +61 -0
- package/dist/drizzle/0204_thread_turns_triggering_message_id.sql +48 -0
- package/dist/drizzle/0205_routines_git_python.sql +185 -0
- package/dist/drizzle/0206_agent_loop_versions_routine_actions.sql +40 -0
- package/dist/drizzle/0207_tenant_credentials_github_repo_kind.sql +52 -0
- package/dist/drizzle/0208_knowledge_graph_neutral_identifiers.sql +253 -0
- package/dist/drizzle/0209_living_artifacts_schema.sql +109 -0
- package/dist/drizzle/0210_think137_automations_additive_schema.sql +113 -0
- package/dist/drizzle/0211_backfill_agent_loop_versions_target_spec.sql +120 -0
- package/dist/drizzle/0212_fold_webhooks_into_automations.sql +312 -0
- package/dist/drizzle/0213_agent_loop_versions_judge_evidence_nullable.sql +63 -0
- package/dist/drizzle/0214_think137_drop_judge_evidence_roi.sql +99 -0
- package/dist/drizzle/0215_agent_loop_versions_goal_worker_policy_nullable.sql +70 -0
- package/dist/drizzle/0216_drop_agent_loop_versions_goal_worker_policy.sql +81 -0
- package/dist/drizzle/0217_agents_capability_folder_dispatch.sql +12 -0
- package/dist/drizzle/0218_document_plates.sql +30 -0
- package/dist/drizzle/0219_document_section_waivers.sql +29 -0
- package/dist/drizzle/0220_artifacts_created_by_user.sql +21 -0
- package/dist/drizzle/0221_artifact_shares.sql +29 -0
- package/dist/drizzle/0221_workflow_interpreter_thin_slice.sql +71 -0
- package/dist/drizzle/0222_compliance_drainer_select_audit_events.sql +21 -0
- package/dist/drizzle/0223_document_conformance_reports.sql +38 -0
- package/dist/drizzle/0224_artifact_refresh_state.sql +11 -0
- package/dist/drizzle/0225_think216_agent_loop_convergence.sql +21 -0
- package/dist/drizzle/0226_drop_n8n_agent_step_runs.sql +6 -0
- package/dist/drizzle/0227_analyst_reader_role.sql +1055 -0
- package/dist/drizzle/0228_tenant_credentials_rds_iam_kind.sql +62 -0
- package/dist/drizzle/0229_analyst_reader_rds_iam_grant.sql +79 -0
- package/dist/drizzle/0230_analyst_rls.sql +1613 -0
- package/dist/drizzle/0231_cost_events_cache_write_enforcement_exempt.sql +11 -0
- package/dist/plugins/catalog/package.json +0 -1
- package/dist/plugins/catalog/src/__tests__/build-catalog.test.ts +0 -1
- package/dist/plugins/catalog/src/__tests__/catalog.test.ts +16 -8
- package/dist/plugins/catalog/src/__tests__/contracts.test.ts +56 -0
- package/dist/plugins/catalog/src/__tests__/plugin-package.test.ts +0 -2
- package/dist/plugins/catalog/src/__tests__/plugin-registry.test.ts +0 -5
- package/dist/plugins/catalog/src/contracts.ts +112 -0
- package/dist/plugins/catalog/src/registry/generated-first-party.ts +0 -6
- package/dist/plugins/n8n/README.md +4 -36
- package/dist/plugins/n8n/src/deployment/managed-app.ts +0 -17
- package/dist/plugins/n8n/src/manifest.ts +0 -5
- package/dist/plugins/n8n/terraform/n8n/main.tf +0 -26
- package/dist/plugins/n8n/terraform/n8n/outputs.tf +0 -5
- package/dist/plugins/n8n/terraform/n8n/variables.tf +0 -6
- package/dist/plugins/n8n/test/manifest.test.ts +0 -1
- package/dist/plugins/twenty/package.json +5 -0
- package/dist/plugins/twenty/scripts/lib/__tests__/load-records.test.ts +232 -0
- package/dist/plugins/twenty/scripts/lib/__tests__/mappers.test.ts +489 -0
- package/dist/plugins/twenty/scripts/lib/__tests__/members-ensure.test.ts +199 -0
- package/dist/plugins/twenty/scripts/lib/__tests__/provision-members-db.test.ts +43 -0
- package/dist/plugins/twenty/scripts/lib/__tests__/schema-ensure.test.ts +230 -0
- package/dist/plugins/twenty/scripts/lib/__tests__/twenty-client.test.ts +207 -0
- package/dist/plugins/twenty/scripts/lib/lastmile-reader.ts +282 -0
- package/dist/plugins/twenty/scripts/lib/load-attachments.ts +220 -0
- package/dist/plugins/twenty/scripts/lib/load-records.ts +680 -0
- package/dist/plugins/twenty/scripts/lib/mappers.ts +559 -0
- package/dist/plugins/twenty/scripts/lib/members-ensure.ts +381 -0
- package/dist/plugins/twenty/scripts/lib/provision-members-db.ts +191 -0
- package/dist/plugins/twenty/scripts/lib/schema-ensure.ts +425 -0
- package/dist/plugins/twenty/scripts/lib/twenty-client.ts +246 -0
- package/dist/plugins/twenty/scripts/migrate-lastmile.ts +610 -0
- package/dist/plugins/twenty/scripts/provision-twenty-members.ts +214 -0
- package/dist/plugins/twenty/src/manifest.ts +99 -0
- package/dist/plugins/twenty/terraform/twenty/README.md +1 -1
- package/dist/plugins/twenty/test/manifest.test.ts +12 -2
- package/dist/terraform/examples/greenfield/main.tf +90 -380
- package/dist/terraform/examples/greenfield/terraform.tfvars.example +0 -1
- package/dist/terraform/modules/app/agentcore-pi/README.md +1 -3
- package/dist/terraform/modules/app/agentcore-pi/main.tf +36 -32
- package/dist/terraform/modules/app/agentcore-pi/variables.tf +23 -15
- package/dist/terraform/modules/app/agentcore-runtime/main.tf +3 -3
- package/dist/terraform/modules/app/customer-domain/main.tf +16 -2
- package/dist/terraform/modules/app/deployment-control-plane/main.tf +5 -0
- package/dist/terraform/modules/app/deployment-control-plane/runner.py +85 -207
- package/dist/terraform/modules/app/deployment-control-plane/test_runner_bundle.py +56 -2
- package/dist/terraform/modules/app/hindsight-memory/main.tf +52 -4
- package/dist/terraform/modules/app/lambda-api/eval-fanout.tf +7 -0
- package/dist/terraform/modules/app/lambda-api/handlers.tf +493 -89
- package/dist/terraform/modules/app/lambda-api/iam-grouped.tf +215 -96
- package/dist/terraform/modules/app/lambda-api/main.tf +24 -5
- package/dist/terraform/modules/app/lambda-api/outputs.tf +19 -11
- package/dist/terraform/modules/app/lambda-api/variables.tf +94 -67
- package/dist/terraform/modules/app/ses-email/main.tf +14 -2
- package/dist/terraform/modules/app/workflow-interpreter-stepfunctions/main.tf +493 -0
- package/dist/terraform/modules/app/workflow-interpreter-stepfunctions/outputs.tf +34 -0
- package/dist/terraform/modules/app/workflow-interpreter-stepfunctions/variables.tf +32 -0
- package/dist/terraform/modules/data/aurora-postgres/main.tf +55 -0
- package/dist/terraform/modules/data/aurora-postgres/outputs.tf +15 -0
- package/dist/terraform/modules/data/s3-buckets/main.tf +26 -0
- package/dist/terraform/modules/thinkwork/README.md +0 -1
- package/dist/terraform/modules/thinkwork/main.tf +167 -446
- package/dist/terraform/modules/thinkwork/outputs.tf +2 -142
- package/dist/terraform/modules/thinkwork/variables.tf +55 -309
- package/dist/terraform/schema.graphql +4 -0
- package/dist/workspace-defaults/files/AGENTS.md +45 -31
- package/dist/workspace-defaults/files/CONTEXT.md +48 -4
- package/dist/workspace-defaults/files/GUARDRAILS.md +18 -0
- package/dist/workspace-defaults/files/MEMORY_GUIDE.md +32 -4
- package/dist/workspace-defaults/files/SPACE.md +34 -19
- package/dist/workspace-defaults/files/TOOLS.md +30 -0
- package/dist/workspace-defaults/files/skills/document-composer/SKILL.md +154 -0
- package/dist/workspace-defaults/files/skills/document-composer/references/authoring-rules.md +101 -0
- package/package.json +2 -1
- package/dist/plugins/company-brain/README.md +0 -37
- package/dist/plugins/company-brain/package.json +0 -33
- package/dist/plugins/company-brain/runtime/cognee/Dockerfile +0 -11
- package/dist/plugins/company-brain/smoke/cognee-managed-app-smoke.mjs +0 -458
- package/dist/plugins/company-brain/smoke/cognee-memory-cutover-smoke.mjs +0 -539
- package/dist/plugins/company-brain/smoke/company-brain-context-engine-smoke.mjs +0 -312
- package/dist/plugins/company-brain/smoke/company-brain-operations-smoke.mjs +0 -449
- package/dist/plugins/company-brain/smoke/company-brain-plugin-smoke.mjs +0 -655
- package/dist/plugins/company-brain/smoke/hindsight-memory-isolation-smoke.mjs +0 -474
- package/dist/plugins/company-brain/src/api/cognee-client.ts +0 -896
- package/dist/plugins/company-brain/src/api/cognee-cluster-identity.ts +0 -49
- package/dist/plugins/company-brain/src/api/cognee-memory-scope.ts +0 -84
- package/dist/plugins/company-brain/src/api/context-engine-provider.ts +0 -888
- package/dist/plugins/company-brain/src/api/migration.ts +0 -665
- package/dist/plugins/company-brain/src/deployment/cognee-managed-app.ts +0 -396
- package/dist/plugins/company-brain/src/index.ts +0 -62
- package/dist/plugins/company-brain/src/manifest.ts +0 -112
- package/dist/plugins/company-brain/terraform/cognee/README.md +0 -263
- package/dist/plugins/company-brain/terraform/cognee/main.tf +0 -766
- package/dist/plugins/company-brain/terraform/cognee/outputs.tf +0 -144
- package/dist/plugins/company-brain/terraform/cognee/variables.tf +0 -402
- package/dist/plugins/company-brain/test/api/cognee-client.test.ts +0 -562
- package/dist/plugins/company-brain/test/api/cognee-memory-scope.test.ts +0 -74
- package/dist/plugins/company-brain/test/api/context-engine-provider.test.ts +0 -447
- package/dist/plugins/company-brain/test/api/migration.test.ts +0 -465
- package/dist/plugins/company-brain/test/manifest.test.ts +0 -95
- package/dist/plugins/company-brain/tsconfig.json +0 -8
|
@@ -0,0 +1,1055 @@
|
|
|
1
|
+
-- 0227_analyst_reader_role.sql
|
|
2
|
+
--
|
|
3
|
+
-- THINK-228 U2: the ThinkWork Analyst read-only Aurora role.
|
|
4
|
+
--
|
|
5
|
+
-- Provisions `analyst_reader`, the least-privilege role the analyst
|
|
6
|
+
-- query-broker Lambda uses to execute model-authored SQL against the dev
|
|
7
|
+
-- Postgres. Unlike compliance_reader (threat-modeled for a trusted
|
|
8
|
+
-- backend), this role's query author is an LLM, so the migration applies
|
|
9
|
+
-- the KTD7 adversarial-author hardening:
|
|
10
|
+
--
|
|
11
|
+
-- - NOSUPERUSER NOCREATEDB NOCREATEROLE NOINHERIT NOBYPASSRLS
|
|
12
|
+
-- NOREPLICATION, and no role memberships (blocks SET ROLE /
|
|
13
|
+
-- SET SESSION AUTHORIZATION escalation).
|
|
14
|
+
-- - Read-only default transaction mode, statement timeout, search_path,
|
|
15
|
+
-- and idle-in-transaction timeout at role level. Defense-in-depth: the
|
|
16
|
+
-- hard write barrier is the grant surface (SELECT only, no
|
|
17
|
+
-- INSERT/UPDATE/DELETE anywhere).
|
|
18
|
+
-- - REVOKE CREATE ON SCHEMA public FROM PUBLIC (blocks CREATE TABLE)
|
|
19
|
+
-- and REVOKE TEMP ON DATABASE FROM PUBLIC (blocks CREATE TEMP TABLE).
|
|
20
|
+
-- These mutate database-wide ACLs: every non-owner role loses them.
|
|
21
|
+
-- Audited dependents: the compliance_* roles never CREATE objects or
|
|
22
|
+
-- TEMP tables (their grant surface is compliance.* DML only — see
|
|
23
|
+
-- drizzle/0070), so no grant-backs are required. On PostgreSQL >= 15
|
|
24
|
+
-- the CREATE revoke is already the default and this is a no-op.
|
|
25
|
+
-- - SECURITY DEFINER audit: every SECURITY DEFINER function in schema
|
|
26
|
+
-- public loses PUBLIC EXECUTE (a definer function can flip read-only
|
|
27
|
+
-- inside its own body); EXECUTE is granted back to the enumerated
|
|
28
|
+
-- compliance_* roles so their query surface is unchanged. Ordinary
|
|
29
|
+
-- (invoker) functions — including the recreated pg_trgm extension
|
|
30
|
+
-- functions — keep their PUBLIC EXECUTE grants untouched.
|
|
31
|
+
-- - Explicit per-table SELECT grants generated from the U1 semantic
|
|
32
|
+
-- model denylist (packages/database-pg/src/analyst/semantic-model.ts).
|
|
33
|
+
-- Secret-bearing tables are never granted; mixed tables get
|
|
34
|
+
-- column-level SELECT. Fail-closed: a table added after this apply is
|
|
35
|
+
-- unreadable until the generated section is regenerated and re-applied
|
|
36
|
+
-- (the staleness test in __tests__/analyst-semantic-model.test.ts
|
|
37
|
+
-- fails on any schema change until the regen runs).
|
|
38
|
+
--
|
|
39
|
+
-- Plan reference:
|
|
40
|
+
-- docs/plans/2026-07-08-001-feat-thinkwork-analyst-plan.md (U2, KTD7)
|
|
41
|
+
--
|
|
42
|
+
-- Apply manually (hand-rolled — NOT in meta/_journal.json):
|
|
43
|
+
-- The bootstrap helper wraps this file with psql variable substitution +
|
|
44
|
+
-- Secrets Manager population:
|
|
45
|
+
-- STAGE=dev bash scripts/bootstrap-analyst-roles.sh
|
|
46
|
+
-- Direct apply (advanced — must supply the password):
|
|
47
|
+
-- psql "$DATABASE_URL" \
|
|
48
|
+
-- -v reader_pass="$ANALYST_READER_PASS" \
|
|
49
|
+
-- -f packages/database-pg/drizzle/0227_analyst_reader_role.sql
|
|
50
|
+
--
|
|
51
|
+
-- Re-running is idempotent: the DO block ALTERs the password when the role
|
|
52
|
+
-- exists; GRANT/REVOKE are inherently idempotent.
|
|
53
|
+
--
|
|
54
|
+
-- Markers (consumed by scripts/db-migrate-manual.sh as the drift gate):
|
|
55
|
+
--
|
|
56
|
+
-- creates-role: analyst_reader
|
|
57
|
+
|
|
58
|
+
\set ON_ERROR_STOP on
|
|
59
|
+
|
|
60
|
+
BEGIN;
|
|
61
|
+
|
|
62
|
+
SET LOCAL lock_timeout = '5s';
|
|
63
|
+
SET LOCAL statement_timeout = '120s';
|
|
64
|
+
|
|
65
|
+
-- The reader password is OPTIONAL. Supplied (-v reader_pass=...) it is used
|
|
66
|
+
-- verbatim (dev bootstrap path, which also stores it in Secrets Manager).
|
|
67
|
+
-- Absent — the customer deployment runner's migration sweep passes only
|
|
68
|
+
-- `stage` — a random throwaway password is generated instead: since
|
|
69
|
+
-- THINK-229 the broker authenticates via RDS IAM tokens (0229 grants
|
|
70
|
+
-- rds_iam), the password is a dormant fallback, and operator provisioning
|
|
71
|
+
-- (`provisionAnalystConnector`) rotates it with a stored value on demand.
|
|
72
|
+
\if :{?reader_pass}
|
|
73
|
+
SET LOCAL "thinkwork.analyst_reader_pass" = :'reader_pass';
|
|
74
|
+
\else
|
|
75
|
+
-- DO block so the generated value never echoes into psql output (runner
|
|
76
|
+
-- stdout is shipped to CloudWatch).
|
|
77
|
+
DO $$
|
|
78
|
+
BEGIN
|
|
79
|
+
PERFORM set_config('thinkwork.analyst_reader_pass',
|
|
80
|
+
md5(random()::text) || md5(random()::text), true);
|
|
81
|
+
END $$;
|
|
82
|
+
\endif
|
|
83
|
+
|
|
84
|
+
-- Refuse to apply against an unexpected DB (stale DATABASE_URL guard).
|
|
85
|
+
DO $$
|
|
86
|
+
BEGIN
|
|
87
|
+
IF current_database() != 'thinkwork' THEN
|
|
88
|
+
RAISE EXCEPTION 'wrong database: %, expected thinkwork', current_database();
|
|
89
|
+
END IF;
|
|
90
|
+
END $$;
|
|
91
|
+
|
|
92
|
+
-- ---------------------------------------------------------------------------
|
|
93
|
+
-- Role creation (idempotent) + KTD7 attribute hardening
|
|
94
|
+
-- ---------------------------------------------------------------------------
|
|
95
|
+
|
|
96
|
+
DO $$
|
|
97
|
+
BEGIN
|
|
98
|
+
IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = 'analyst_reader') THEN
|
|
99
|
+
EXECUTE format(
|
|
100
|
+
'CREATE ROLE analyst_reader WITH LOGIN PASSWORD %L NOSUPERUSER NOCREATEDB NOCREATEROLE NOINHERIT NOBYPASSRLS NOREPLICATION',
|
|
101
|
+
current_setting('thinkwork.analyst_reader_pass'));
|
|
102
|
+
ELSE
|
|
103
|
+
-- Re-run path: rotate the password only. On RDS the master user is
|
|
104
|
+
-- rds_superuser, NOT superuser, and an ALTER ROLE that mentions any
|
|
105
|
+
-- superuser-class attribute (even the no-op NOSUPERUSER / NOBYPASSRLS /
|
|
106
|
+
-- NOREPLICATION) fails with "must be superuser to alter superuser
|
|
107
|
+
-- roles" — attributes are pinned at creation and asserted below.
|
|
108
|
+
EXECUTE format(
|
|
109
|
+
'ALTER ROLE analyst_reader WITH LOGIN PASSWORD %L',
|
|
110
|
+
current_setting('thinkwork.analyst_reader_pass'));
|
|
111
|
+
END IF;
|
|
112
|
+
END $$;
|
|
113
|
+
|
|
114
|
+
-- Assert the creation-time attribute hardening actually holds (covers the
|
|
115
|
+
-- re-run path, where ALTER no longer re-asserts attributes, and any
|
|
116
|
+
-- out-of-band mutation).
|
|
117
|
+
DO $$
|
|
118
|
+
DECLARE
|
|
119
|
+
r pg_roles%ROWTYPE;
|
|
120
|
+
BEGIN
|
|
121
|
+
SELECT * INTO r FROM pg_roles WHERE rolname = 'analyst_reader';
|
|
122
|
+
IF r.rolsuper OR r.rolcreatedb OR r.rolcreaterole OR r.rolinherit
|
|
123
|
+
OR r.rolbypassrls OR r.rolreplication THEN
|
|
124
|
+
RAISE EXCEPTION 'analyst_reader attribute hardening violated: super=% createdb=% createrole=% inherit=% bypassrls=% replication=%',
|
|
125
|
+
r.rolsuper, r.rolcreatedb, r.rolcreaterole, r.rolinherit, r.rolbypassrls, r.rolreplication;
|
|
126
|
+
END IF;
|
|
127
|
+
END $$;
|
|
128
|
+
|
|
129
|
+
-- Role-level session defaults. USERSET GUCs are resettable within a
|
|
130
|
+
-- session, so the broker issues DISCARD ALL before every query (KTD7);
|
|
131
|
+
-- these are defense-in-depth behind the SELECT-only grant surface.
|
|
132
|
+
ALTER ROLE analyst_reader SET default_transaction_read_only = on;
|
|
133
|
+
ALTER ROLE analyst_reader SET statement_timeout = '15s';
|
|
134
|
+
ALTER ROLE analyst_reader SET idle_in_transaction_session_timeout = '30s';
|
|
135
|
+
ALTER ROLE analyst_reader SET search_path = public;
|
|
136
|
+
|
|
137
|
+
-- Assert the role holds no memberships beyond the allowlist (SET ROLE
|
|
138
|
+
-- escalation surface). This migration never grants any; the single
|
|
139
|
+
-- allowlisted membership is rds_iam (THINK-229 U1, granted by
|
|
140
|
+
-- drizzle/0229_analyst_reader_rds_iam_grant.sql — a marker role that
|
|
141
|
+
-- flips the login path to IAM tokens and carries no privileges to
|
|
142
|
+
-- inherit). Anything else appearing out-of-band fails the apply loudly
|
|
143
|
+
-- rather than proceeding with a widened surface.
|
|
144
|
+
DO $$
|
|
145
|
+
DECLARE
|
|
146
|
+
membership text;
|
|
147
|
+
BEGIN
|
|
148
|
+
SELECT string_agg(r.rolname, ', ') INTO membership
|
|
149
|
+
FROM pg_auth_members m
|
|
150
|
+
JOIN pg_roles r ON r.oid = m.roleid
|
|
151
|
+
JOIN pg_roles member ON member.oid = m.member
|
|
152
|
+
WHERE member.rolname = 'analyst_reader'
|
|
153
|
+
AND r.rolname <> 'rds_iam';
|
|
154
|
+
IF membership IS NOT NULL THEN
|
|
155
|
+
RAISE EXCEPTION 'analyst_reader unexpectedly holds role memberships: %', membership;
|
|
156
|
+
END IF;
|
|
157
|
+
END $$;
|
|
158
|
+
|
|
159
|
+
-- ---------------------------------------------------------------------------
|
|
160
|
+
-- Schema-level lockdown (database-wide ACL changes — see header audit)
|
|
161
|
+
-- ---------------------------------------------------------------------------
|
|
162
|
+
|
|
163
|
+
REVOKE CREATE ON SCHEMA public FROM PUBLIC;
|
|
164
|
+
REVOKE TEMP ON DATABASE thinkwork FROM PUBLIC;
|
|
165
|
+
|
|
166
|
+
-- SECURITY DEFINER audit: strip PUBLIC EXECUTE from definer functions in
|
|
167
|
+
-- public, granting back to the enumerated compliance_* roles. Emits a
|
|
168
|
+
-- NOTICE per affected function so the operator sees exactly what changed.
|
|
169
|
+
DO $$
|
|
170
|
+
DECLARE
|
|
171
|
+
fn record;
|
|
172
|
+
grantees text;
|
|
173
|
+
BEGIN
|
|
174
|
+
-- Grant back only to compliance roles that exist on this stage (a fresh
|
|
175
|
+
-- stage may not have run the compliance bootstrap yet).
|
|
176
|
+
SELECT string_agg(quote_ident(rolname), ', ') INTO grantees
|
|
177
|
+
FROM pg_roles
|
|
178
|
+
WHERE rolname IN ('compliance_writer', 'compliance_drainer', 'compliance_reader');
|
|
179
|
+
FOR fn IN
|
|
180
|
+
SELECT p.oid::regprocedure AS signature
|
|
181
|
+
FROM pg_proc p
|
|
182
|
+
JOIN pg_namespace n ON n.oid = p.pronamespace
|
|
183
|
+
WHERE n.nspname = 'public' AND p.prosecdef
|
|
184
|
+
LOOP
|
|
185
|
+
EXECUTE format('REVOKE EXECUTE ON FUNCTION %s FROM PUBLIC', fn.signature);
|
|
186
|
+
IF grantees IS NOT NULL THEN
|
|
187
|
+
EXECUTE format('GRANT EXECUTE ON FUNCTION %s TO %s', fn.signature, grantees);
|
|
188
|
+
END IF;
|
|
189
|
+
RAISE NOTICE 'SECURITY DEFINER hardened: % (PUBLIC EXECUTE revoked; granted back to: %)',
|
|
190
|
+
fn.signature, coalesce(grantees, '<none>');
|
|
191
|
+
END LOOP;
|
|
192
|
+
END $$;
|
|
193
|
+
|
|
194
|
+
-- ---------------------------------------------------------------------------
|
|
195
|
+
-- SELECT grant surface (generated — do not edit by hand)
|
|
196
|
+
--
|
|
197
|
+
-- Regenerate: npx tsx scripts/generate-analyst-schema.ts
|
|
198
|
+
-- Source of truth: packages/database-pg/src/analyst/semantic-model.ts
|
|
199
|
+
-- ---------------------------------------------------------------------------
|
|
200
|
+
|
|
201
|
+
GRANT USAGE ON SCHEMA public TO analyst_reader;
|
|
202
|
+
|
|
203
|
+
-- BEGIN GENERATED ANALYST GRANTS
|
|
204
|
+
DO $$
|
|
205
|
+
DECLARE
|
|
206
|
+
missing text[] := '{}';
|
|
207
|
+
BEGIN
|
|
208
|
+
IF to_regclass('public.activity_log') IS NOT NULL THEN
|
|
209
|
+
GRANT SELECT ON public.activity_log TO analyst_reader;
|
|
210
|
+
ELSE
|
|
211
|
+
missing := missing || 'activity_log'::text;
|
|
212
|
+
END IF;
|
|
213
|
+
IF to_regclass('public.agent_capabilities') IS NOT NULL THEN
|
|
214
|
+
GRANT SELECT ON public.agent_capabilities TO analyst_reader;
|
|
215
|
+
ELSE
|
|
216
|
+
missing := missing || 'agent_capabilities'::text;
|
|
217
|
+
END IF;
|
|
218
|
+
IF to_regclass('public.agent_knowledge_bases') IS NOT NULL THEN
|
|
219
|
+
GRANT SELECT ON public.agent_knowledge_bases TO analyst_reader;
|
|
220
|
+
ELSE
|
|
221
|
+
missing := missing || 'agent_knowledge_bases'::text;
|
|
222
|
+
END IF;
|
|
223
|
+
IF to_regclass('public.agent_loop_iterations') IS NOT NULL THEN
|
|
224
|
+
GRANT SELECT ON public.agent_loop_iterations TO analyst_reader;
|
|
225
|
+
ELSE
|
|
226
|
+
missing := missing || 'agent_loop_iterations'::text;
|
|
227
|
+
END IF;
|
|
228
|
+
IF to_regclass('public.agent_loop_runs') IS NOT NULL THEN
|
|
229
|
+
GRANT SELECT ON public.agent_loop_runs TO analyst_reader;
|
|
230
|
+
ELSE
|
|
231
|
+
missing := missing || 'agent_loop_runs'::text;
|
|
232
|
+
END IF;
|
|
233
|
+
IF to_regclass('public.agent_loop_versions') IS NOT NULL THEN
|
|
234
|
+
GRANT SELECT ON public.agent_loop_versions TO analyst_reader;
|
|
235
|
+
ELSE
|
|
236
|
+
missing := missing || 'agent_loop_versions'::text;
|
|
237
|
+
END IF;
|
|
238
|
+
IF to_regclass('public.agent_loops') IS NOT NULL THEN
|
|
239
|
+
GRANT SELECT ON public.agent_loops TO analyst_reader;
|
|
240
|
+
ELSE
|
|
241
|
+
missing := missing || 'agent_loops'::text;
|
|
242
|
+
END IF;
|
|
243
|
+
IF to_regclass('public.agent_mcp_servers') IS NOT NULL THEN
|
|
244
|
+
GRANT SELECT ON public.agent_mcp_servers TO analyst_reader;
|
|
245
|
+
ELSE
|
|
246
|
+
missing := missing || 'agent_mcp_servers'::text;
|
|
247
|
+
END IF;
|
|
248
|
+
IF to_regclass('public.agent_operation_leases') IS NOT NULL THEN
|
|
249
|
+
GRANT SELECT ON public.agent_operation_leases TO analyst_reader;
|
|
250
|
+
ELSE
|
|
251
|
+
missing := missing || 'agent_operation_leases'::text;
|
|
252
|
+
END IF;
|
|
253
|
+
IF to_regclass('public.agent_profile_space_assignments') IS NOT NULL THEN
|
|
254
|
+
GRANT SELECT ON public.agent_profile_space_assignments TO analyst_reader;
|
|
255
|
+
ELSE
|
|
256
|
+
missing := missing || 'agent_profile_space_assignments'::text;
|
|
257
|
+
END IF;
|
|
258
|
+
IF to_regclass('public.agent_profiles') IS NOT NULL THEN
|
|
259
|
+
GRANT SELECT ON public.agent_profiles TO analyst_reader;
|
|
260
|
+
ELSE
|
|
261
|
+
missing := missing || 'agent_profiles'::text;
|
|
262
|
+
END IF;
|
|
263
|
+
IF to_regclass('public.agent_skills') IS NOT NULL THEN
|
|
264
|
+
GRANT SELECT ON public.agent_skills TO analyst_reader;
|
|
265
|
+
ELSE
|
|
266
|
+
missing := missing || 'agent_skills'::text;
|
|
267
|
+
END IF;
|
|
268
|
+
IF to_regclass('public.agent_template_mcp_servers') IS NOT NULL THEN
|
|
269
|
+
GRANT SELECT ON public.agent_template_mcp_servers TO analyst_reader;
|
|
270
|
+
ELSE
|
|
271
|
+
missing := missing || 'agent_template_mcp_servers'::text;
|
|
272
|
+
END IF;
|
|
273
|
+
IF to_regclass('public.agent_templates') IS NOT NULL THEN
|
|
274
|
+
GRANT SELECT ON public.agent_templates TO analyst_reader;
|
|
275
|
+
ELSE
|
|
276
|
+
missing := missing || 'agent_templates'::text;
|
|
277
|
+
END IF;
|
|
278
|
+
IF to_regclass('public.agent_versions') IS NOT NULL THEN
|
|
279
|
+
GRANT SELECT ON public.agent_versions TO analyst_reader;
|
|
280
|
+
ELSE
|
|
281
|
+
missing := missing || 'agent_versions'::text;
|
|
282
|
+
END IF;
|
|
283
|
+
IF to_regclass('public.agent_wakeup_requests') IS NOT NULL THEN
|
|
284
|
+
GRANT SELECT ON public.agent_wakeup_requests TO analyst_reader;
|
|
285
|
+
ELSE
|
|
286
|
+
missing := missing || 'agent_wakeup_requests'::text;
|
|
287
|
+
END IF;
|
|
288
|
+
IF to_regclass('public.agent_workspace_events') IS NOT NULL THEN
|
|
289
|
+
GRANT SELECT ON public.agent_workspace_events TO analyst_reader;
|
|
290
|
+
ELSE
|
|
291
|
+
missing := missing || 'agent_workspace_events'::text;
|
|
292
|
+
END IF;
|
|
293
|
+
IF to_regclass('public.agent_workspace_runs') IS NOT NULL THEN
|
|
294
|
+
GRANT SELECT ON public.agent_workspace_runs TO analyst_reader;
|
|
295
|
+
ELSE
|
|
296
|
+
missing := missing || 'agent_workspace_runs'::text;
|
|
297
|
+
END IF;
|
|
298
|
+
IF to_regclass('public.agents') IS NOT NULL THEN
|
|
299
|
+
GRANT SELECT ON public.agents TO analyst_reader;
|
|
300
|
+
ELSE
|
|
301
|
+
missing := missing || 'agents'::text;
|
|
302
|
+
END IF;
|
|
303
|
+
IF to_regclass('public.artifact_data_bindings') IS NOT NULL THEN
|
|
304
|
+
GRANT SELECT ON public.artifact_data_bindings TO analyst_reader;
|
|
305
|
+
ELSE
|
|
306
|
+
missing := missing || 'artifact_data_bindings'::text;
|
|
307
|
+
END IF;
|
|
308
|
+
IF to_regclass('public.artifact_shares') IS NOT NULL THEN
|
|
309
|
+
GRANT SELECT ON public.artifact_shares TO analyst_reader;
|
|
310
|
+
ELSE
|
|
311
|
+
missing := missing || 'artifact_shares'::text;
|
|
312
|
+
END IF;
|
|
313
|
+
IF to_regclass('public.artifact_versions') IS NOT NULL THEN
|
|
314
|
+
GRANT SELECT ON public.artifact_versions TO analyst_reader;
|
|
315
|
+
ELSE
|
|
316
|
+
missing := missing || 'artifact_versions'::text;
|
|
317
|
+
END IF;
|
|
318
|
+
IF to_regclass('public.artifacts') IS NOT NULL THEN
|
|
319
|
+
GRANT SELECT ON public.artifacts TO analyst_reader;
|
|
320
|
+
ELSE
|
|
321
|
+
missing := missing || 'artifacts'::text;
|
|
322
|
+
END IF;
|
|
323
|
+
IF to_regclass('public.billing_export_line_items') IS NOT NULL THEN
|
|
324
|
+
GRANT SELECT ON public.billing_export_line_items TO analyst_reader;
|
|
325
|
+
ELSE
|
|
326
|
+
missing := missing || 'billing_export_line_items'::text;
|
|
327
|
+
END IF;
|
|
328
|
+
IF to_regclass('public.brain_dream_actions') IS NOT NULL THEN
|
|
329
|
+
GRANT SELECT ON public.brain_dream_actions TO analyst_reader;
|
|
330
|
+
ELSE
|
|
331
|
+
missing := missing || 'brain_dream_actions'::text;
|
|
332
|
+
END IF;
|
|
333
|
+
IF to_regclass('public.brain_dream_runs') IS NOT NULL THEN
|
|
334
|
+
GRANT SELECT ON public.brain_dream_runs TO analyst_reader;
|
|
335
|
+
ELSE
|
|
336
|
+
missing := missing || 'brain_dream_runs'::text;
|
|
337
|
+
END IF;
|
|
338
|
+
IF to_regclass('public.budget_policies') IS NOT NULL THEN
|
|
339
|
+
GRANT SELECT ON public.budget_policies TO analyst_reader;
|
|
340
|
+
ELSE
|
|
341
|
+
missing := missing || 'budget_policies'::text;
|
|
342
|
+
END IF;
|
|
343
|
+
IF to_regclass('public.capability_catalog') IS NOT NULL THEN
|
|
344
|
+
GRANT SELECT ON public.capability_catalog TO analyst_reader;
|
|
345
|
+
ELSE
|
|
346
|
+
missing := missing || 'capability_catalog'::text;
|
|
347
|
+
END IF;
|
|
348
|
+
IF to_regclass('public.connections') IS NOT NULL THEN
|
|
349
|
+
GRANT SELECT ON public.connections TO analyst_reader;
|
|
350
|
+
ELSE
|
|
351
|
+
missing := missing || 'connections'::text;
|
|
352
|
+
END IF;
|
|
353
|
+
IF to_regclass('public.cost_events') IS NOT NULL THEN
|
|
354
|
+
GRANT SELECT ON public.cost_events TO analyst_reader;
|
|
355
|
+
ELSE
|
|
356
|
+
missing := missing || 'cost_events'::text;
|
|
357
|
+
END IF;
|
|
358
|
+
IF to_regclass('public.crm_work_links') IS NOT NULL THEN
|
|
359
|
+
GRANT SELECT ON public.crm_work_links TO analyst_reader;
|
|
360
|
+
ELSE
|
|
361
|
+
missing := missing || 'crm_work_links'::text;
|
|
362
|
+
END IF;
|
|
363
|
+
IF to_regclass('public.document_conformance_reports') IS NOT NULL THEN
|
|
364
|
+
GRANT SELECT ON public.document_conformance_reports TO analyst_reader;
|
|
365
|
+
ELSE
|
|
366
|
+
missing := missing || 'document_conformance_reports'::text;
|
|
367
|
+
END IF;
|
|
368
|
+
IF to_regclass('public.document_plates') IS NOT NULL THEN
|
|
369
|
+
GRANT SELECT ON public.document_plates TO analyst_reader;
|
|
370
|
+
ELSE
|
|
371
|
+
missing := missing || 'document_plates'::text;
|
|
372
|
+
END IF;
|
|
373
|
+
IF to_regclass('public.document_section_waivers') IS NOT NULL THEN
|
|
374
|
+
GRANT SELECT ON public.document_section_waivers TO analyst_reader;
|
|
375
|
+
ELSE
|
|
376
|
+
missing := missing || 'document_section_waivers'::text;
|
|
377
|
+
END IF;
|
|
378
|
+
IF to_regclass('public.documents') IS NOT NULL THEN
|
|
379
|
+
GRANT SELECT ON public.documents TO analyst_reader;
|
|
380
|
+
ELSE
|
|
381
|
+
missing := missing || 'documents'::text;
|
|
382
|
+
END IF;
|
|
383
|
+
IF to_regclass('public.email_body_objects') IS NOT NULL THEN
|
|
384
|
+
GRANT SELECT ON public.email_body_objects TO analyst_reader;
|
|
385
|
+
ELSE
|
|
386
|
+
missing := missing || 'email_body_objects'::text;
|
|
387
|
+
END IF;
|
|
388
|
+
IF to_regclass('public.email_conversations') IS NOT NULL THEN
|
|
389
|
+
GRANT SELECT ON public.email_conversations TO analyst_reader;
|
|
390
|
+
ELSE
|
|
391
|
+
missing := missing || 'email_conversations'::text;
|
|
392
|
+
END IF;
|
|
393
|
+
IF to_regclass('public.email_domains') IS NOT NULL THEN
|
|
394
|
+
GRANT SELECT ON public.email_domains TO analyst_reader;
|
|
395
|
+
ELSE
|
|
396
|
+
missing := missing || 'email_domains'::text;
|
|
397
|
+
END IF;
|
|
398
|
+
IF to_regclass('public.email_ledger_events') IS NOT NULL THEN
|
|
399
|
+
GRANT SELECT ON public.email_ledger_events TO analyst_reader;
|
|
400
|
+
ELSE
|
|
401
|
+
missing := missing || 'email_ledger_events'::text;
|
|
402
|
+
END IF;
|
|
403
|
+
IF to_regclass('public.email_provider_events') IS NOT NULL THEN
|
|
404
|
+
GRANT SELECT ON public.email_provider_events TO analyst_reader;
|
|
405
|
+
ELSE
|
|
406
|
+
missing := missing || 'email_provider_events'::text;
|
|
407
|
+
END IF;
|
|
408
|
+
IF to_regclass('public.email_readiness_checks') IS NOT NULL THEN
|
|
409
|
+
GRANT SELECT ON public.email_readiness_checks TO analyst_reader;
|
|
410
|
+
ELSE
|
|
411
|
+
missing := missing || 'email_readiness_checks'::text;
|
|
412
|
+
END IF;
|
|
413
|
+
IF to_regclass('public.email_ses_compatibility_mappings') IS NOT NULL THEN
|
|
414
|
+
GRANT SELECT ON public.email_ses_compatibility_mappings TO analyst_reader;
|
|
415
|
+
ELSE
|
|
416
|
+
missing := missing || 'email_ses_compatibility_mappings'::text;
|
|
417
|
+
END IF;
|
|
418
|
+
IF to_regclass('public.email_space_policies') IS NOT NULL THEN
|
|
419
|
+
GRANT SELECT ON public.email_space_policies TO analyst_reader;
|
|
420
|
+
ELSE
|
|
421
|
+
missing := missing || 'email_space_policies'::text;
|
|
422
|
+
END IF;
|
|
423
|
+
IF to_regclass('public.email_space_sender_allowlists') IS NOT NULL THEN
|
|
424
|
+
GRANT SELECT ON public.email_space_sender_allowlists TO analyst_reader;
|
|
425
|
+
ELSE
|
|
426
|
+
missing := missing || 'email_space_sender_allowlists'::text;
|
|
427
|
+
END IF;
|
|
428
|
+
IF to_regclass('public.eval_case_overrides') IS NOT NULL THEN
|
|
429
|
+
GRANT SELECT ON public.eval_case_overrides TO analyst_reader;
|
|
430
|
+
ELSE
|
|
431
|
+
missing := missing || 'eval_case_overrides'::text;
|
|
432
|
+
END IF;
|
|
433
|
+
IF to_regclass('public.eval_datasets') IS NOT NULL THEN
|
|
434
|
+
GRANT SELECT ON public.eval_datasets TO analyst_reader;
|
|
435
|
+
ELSE
|
|
436
|
+
missing := missing || 'eval_datasets'::text;
|
|
437
|
+
END IF;
|
|
438
|
+
IF to_regclass('public.eval_profiles') IS NOT NULL THEN
|
|
439
|
+
GRANT SELECT ON public.eval_profiles TO analyst_reader;
|
|
440
|
+
ELSE
|
|
441
|
+
missing := missing || 'eval_profiles'::text;
|
|
442
|
+
END IF;
|
|
443
|
+
IF to_regclass('public.eval_replay_tool_allowlist') IS NOT NULL THEN
|
|
444
|
+
GRANT SELECT ON public.eval_replay_tool_allowlist TO analyst_reader;
|
|
445
|
+
ELSE
|
|
446
|
+
missing := missing || 'eval_replay_tool_allowlist'::text;
|
|
447
|
+
END IF;
|
|
448
|
+
IF to_regclass('public.eval_results') IS NOT NULL THEN
|
|
449
|
+
GRANT SELECT ON public.eval_results TO analyst_reader;
|
|
450
|
+
ELSE
|
|
451
|
+
missing := missing || 'eval_results'::text;
|
|
452
|
+
END IF;
|
|
453
|
+
IF to_regclass('public.eval_runs') IS NOT NULL THEN
|
|
454
|
+
GRANT SELECT ON public.eval_runs TO analyst_reader;
|
|
455
|
+
ELSE
|
|
456
|
+
missing := missing || 'eval_runs'::text;
|
|
457
|
+
END IF;
|
|
458
|
+
IF to_regclass('public.eval_skill_gate') IS NOT NULL THEN
|
|
459
|
+
GRANT SELECT ON public.eval_skill_gate TO analyst_reader;
|
|
460
|
+
ELSE
|
|
461
|
+
missing := missing || 'eval_skill_gate'::text;
|
|
462
|
+
END IF;
|
|
463
|
+
IF to_regclass('public.eval_test_cases') IS NOT NULL THEN
|
|
464
|
+
GRANT SELECT ON public.eval_test_cases TO analyst_reader;
|
|
465
|
+
ELSE
|
|
466
|
+
missing := missing || 'eval_test_cases'::text;
|
|
467
|
+
END IF;
|
|
468
|
+
IF to_regclass('public.folder_bundle_import_rate_limits') IS NOT NULL THEN
|
|
469
|
+
GRANT SELECT ON public.folder_bundle_import_rate_limits TO analyst_reader;
|
|
470
|
+
ELSE
|
|
471
|
+
missing := missing || 'folder_bundle_import_rate_limits'::text;
|
|
472
|
+
END IF;
|
|
473
|
+
IF to_regclass('public.github_app_installations') IS NOT NULL THEN
|
|
474
|
+
GRANT SELECT ON public.github_app_installations TO analyst_reader;
|
|
475
|
+
ELSE
|
|
476
|
+
missing := missing || 'github_app_installations'::text;
|
|
477
|
+
END IF;
|
|
478
|
+
IF to_regclass('public.github_webhook_deliveries') IS NOT NULL THEN
|
|
479
|
+
GRANT SELECT ON public.github_webhook_deliveries TO analyst_reader;
|
|
480
|
+
ELSE
|
|
481
|
+
missing := missing || 'github_webhook_deliveries'::text;
|
|
482
|
+
END IF;
|
|
483
|
+
IF to_regclass('public.goals') IS NOT NULL THEN
|
|
484
|
+
GRANT SELECT ON public.goals TO analyst_reader;
|
|
485
|
+
ELSE
|
|
486
|
+
missing := missing || 'goals'::text;
|
|
487
|
+
END IF;
|
|
488
|
+
IF to_regclass('public.guardrail_blocks') IS NOT NULL THEN
|
|
489
|
+
GRANT SELECT ON public.guardrail_blocks TO analyst_reader;
|
|
490
|
+
ELSE
|
|
491
|
+
missing := missing || 'guardrail_blocks'::text;
|
|
492
|
+
END IF;
|
|
493
|
+
IF to_regclass('public.guardrails') IS NOT NULL THEN
|
|
494
|
+
GRANT SELECT ON public.guardrails TO analyst_reader;
|
|
495
|
+
ELSE
|
|
496
|
+
missing := missing || 'guardrails'::text;
|
|
497
|
+
END IF;
|
|
498
|
+
IF to_regclass('public.inbox_item_comments') IS NOT NULL THEN
|
|
499
|
+
GRANT SELECT ON public.inbox_item_comments TO analyst_reader;
|
|
500
|
+
ELSE
|
|
501
|
+
missing := missing || 'inbox_item_comments'::text;
|
|
502
|
+
END IF;
|
|
503
|
+
IF to_regclass('public.inbox_item_links') IS NOT NULL THEN
|
|
504
|
+
GRANT SELECT ON public.inbox_item_links TO analyst_reader;
|
|
505
|
+
ELSE
|
|
506
|
+
missing := missing || 'inbox_item_links'::text;
|
|
507
|
+
END IF;
|
|
508
|
+
IF to_regclass('public.inbox_items') IS NOT NULL THEN
|
|
509
|
+
GRANT SELECT ON public.inbox_items TO analyst_reader;
|
|
510
|
+
ELSE
|
|
511
|
+
missing := missing || 'inbox_items'::text;
|
|
512
|
+
END IF;
|
|
513
|
+
IF to_regclass('public.knowledge_bases') IS NOT NULL THEN
|
|
514
|
+
GRANT SELECT ON public.knowledge_bases TO analyst_reader;
|
|
515
|
+
ELSE
|
|
516
|
+
missing := missing || 'knowledge_bases'::text;
|
|
517
|
+
END IF;
|
|
518
|
+
IF to_regclass('public.knowledge_graph_entities') IS NOT NULL THEN
|
|
519
|
+
GRANT SELECT ON public.knowledge_graph_entities TO analyst_reader;
|
|
520
|
+
ELSE
|
|
521
|
+
missing := missing || 'knowledge_graph_entities'::text;
|
|
522
|
+
END IF;
|
|
523
|
+
IF to_regclass('public.knowledge_graph_evidence') IS NOT NULL THEN
|
|
524
|
+
GRANT SELECT ON public.knowledge_graph_evidence TO analyst_reader;
|
|
525
|
+
ELSE
|
|
526
|
+
missing := missing || 'knowledge_graph_evidence'::text;
|
|
527
|
+
END IF;
|
|
528
|
+
IF to_regclass('public.knowledge_graph_ingest_runs') IS NOT NULL THEN
|
|
529
|
+
GRANT SELECT ON public.knowledge_graph_ingest_runs TO analyst_reader;
|
|
530
|
+
ELSE
|
|
531
|
+
missing := missing || 'knowledge_graph_ingest_runs'::text;
|
|
532
|
+
END IF;
|
|
533
|
+
IF to_regclass('public.knowledge_graph_observation_cursors') IS NOT NULL THEN
|
|
534
|
+
GRANT SELECT ON public.knowledge_graph_observation_cursors TO analyst_reader;
|
|
535
|
+
ELSE
|
|
536
|
+
missing := missing || 'knowledge_graph_observation_cursors'::text;
|
|
537
|
+
END IF;
|
|
538
|
+
IF to_regclass('public.knowledge_graph_relationships') IS NOT NULL THEN
|
|
539
|
+
GRANT SELECT ON public.knowledge_graph_relationships TO analyst_reader;
|
|
540
|
+
ELSE
|
|
541
|
+
missing := missing || 'knowledge_graph_relationships'::text;
|
|
542
|
+
END IF;
|
|
543
|
+
IF to_regclass('public.linked_task_events') IS NOT NULL THEN
|
|
544
|
+
GRANT SELECT ON public.linked_task_events TO analyst_reader;
|
|
545
|
+
ELSE
|
|
546
|
+
missing := missing || 'linked_task_events'::text;
|
|
547
|
+
END IF;
|
|
548
|
+
IF to_regclass('public.linked_tasks') IS NOT NULL THEN
|
|
549
|
+
GRANT SELECT ON public.linked_tasks TO analyst_reader;
|
|
550
|
+
ELSE
|
|
551
|
+
missing := missing || 'linked_tasks'::text;
|
|
552
|
+
END IF;
|
|
553
|
+
IF to_regclass('public.managed_application_deployment_events') IS NOT NULL THEN
|
|
554
|
+
GRANT SELECT ON public.managed_application_deployment_events TO analyst_reader;
|
|
555
|
+
ELSE
|
|
556
|
+
missing := missing || 'managed_application_deployment_events'::text;
|
|
557
|
+
END IF;
|
|
558
|
+
IF to_regclass('public.managed_application_deployment_jobs') IS NOT NULL THEN
|
|
559
|
+
GRANT SELECT ON public.managed_application_deployment_jobs TO analyst_reader;
|
|
560
|
+
ELSE
|
|
561
|
+
missing := missing || 'managed_application_deployment_jobs'::text;
|
|
562
|
+
END IF;
|
|
563
|
+
IF to_regclass('public.managed_applications') IS NOT NULL THEN
|
|
564
|
+
GRANT SELECT ON public.managed_applications TO analyst_reader;
|
|
565
|
+
ELSE
|
|
566
|
+
missing := missing || 'managed_applications'::text;
|
|
567
|
+
END IF;
|
|
568
|
+
IF to_regclass('public.memory_retain_attempts') IS NOT NULL THEN
|
|
569
|
+
GRANT SELECT ON public.memory_retain_attempts TO analyst_reader;
|
|
570
|
+
ELSE
|
|
571
|
+
missing := missing || 'memory_retain_attempts'::text;
|
|
572
|
+
END IF;
|
|
573
|
+
IF to_regclass('public.message_artifacts') IS NOT NULL THEN
|
|
574
|
+
GRANT SELECT ON public.message_artifacts TO analyst_reader;
|
|
575
|
+
ELSE
|
|
576
|
+
missing := missing || 'message_artifacts'::text;
|
|
577
|
+
END IF;
|
|
578
|
+
IF to_regclass('public.message_mentions') IS NOT NULL THEN
|
|
579
|
+
GRANT SELECT ON public.message_mentions TO analyst_reader;
|
|
580
|
+
ELSE
|
|
581
|
+
missing := missing || 'message_mentions'::text;
|
|
582
|
+
END IF;
|
|
583
|
+
IF to_regclass('public.messages') IS NOT NULL THEN
|
|
584
|
+
GRANT SELECT ON public.messages TO analyst_reader;
|
|
585
|
+
ELSE
|
|
586
|
+
missing := missing || 'messages'::text;
|
|
587
|
+
END IF;
|
|
588
|
+
IF to_regclass('public.model_catalog') IS NOT NULL THEN
|
|
589
|
+
GRANT SELECT ON public.model_catalog TO analyst_reader;
|
|
590
|
+
ELSE
|
|
591
|
+
missing := missing || 'model_catalog'::text;
|
|
592
|
+
END IF;
|
|
593
|
+
IF to_regclass('public.mutation_idempotency') IS NOT NULL THEN
|
|
594
|
+
GRANT SELECT ON public.mutation_idempotency TO analyst_reader;
|
|
595
|
+
ELSE
|
|
596
|
+
missing := missing || 'mutation_idempotency'::text;
|
|
597
|
+
END IF;
|
|
598
|
+
IF to_regclass('public.pending_user_questions') IS NOT NULL THEN
|
|
599
|
+
GRANT SELECT ON public.pending_user_questions TO analyst_reader;
|
|
600
|
+
ELSE
|
|
601
|
+
missing := missing || 'pending_user_questions'::text;
|
|
602
|
+
END IF;
|
|
603
|
+
IF to_regclass('public.pi_extension_assignments') IS NOT NULL THEN
|
|
604
|
+
GRANT SELECT ON public.pi_extension_assignments TO analyst_reader;
|
|
605
|
+
ELSE
|
|
606
|
+
missing := missing || 'pi_extension_assignments'::text;
|
|
607
|
+
END IF;
|
|
608
|
+
IF to_regclass('public.pi_extension_sources') IS NOT NULL THEN
|
|
609
|
+
GRANT SELECT ON public.pi_extension_sources TO analyst_reader;
|
|
610
|
+
ELSE
|
|
611
|
+
missing := missing || 'pi_extension_sources'::text;
|
|
612
|
+
END IF;
|
|
613
|
+
IF to_regclass('public.pi_extension_versions') IS NOT NULL THEN
|
|
614
|
+
GRANT SELECT ON public.pi_extension_versions TO analyst_reader;
|
|
615
|
+
ELSE
|
|
616
|
+
missing := missing || 'pi_extension_versions'::text;
|
|
617
|
+
END IF;
|
|
618
|
+
IF to_regclass('public.plugin_app_overlays') IS NOT NULL THEN
|
|
619
|
+
GRANT SELECT ON public.plugin_app_overlays TO analyst_reader;
|
|
620
|
+
ELSE
|
|
621
|
+
missing := missing || 'plugin_app_overlays'::text;
|
|
622
|
+
END IF;
|
|
623
|
+
IF to_regclass('public.plugin_components') IS NOT NULL THEN
|
|
624
|
+
GRANT SELECT ON public.plugin_components TO analyst_reader;
|
|
625
|
+
ELSE
|
|
626
|
+
missing := missing || 'plugin_components'::text;
|
|
627
|
+
END IF;
|
|
628
|
+
IF to_regclass('public.plugin_entitlements') IS NOT NULL THEN
|
|
629
|
+
GRANT SELECT ON public.plugin_entitlements TO analyst_reader;
|
|
630
|
+
ELSE
|
|
631
|
+
missing := missing || 'plugin_entitlements'::text;
|
|
632
|
+
END IF;
|
|
633
|
+
IF to_regclass('public.plugin_installs') IS NOT NULL THEN
|
|
634
|
+
GRANT SELECT ON public.plugin_installs TO analyst_reader;
|
|
635
|
+
ELSE
|
|
636
|
+
missing := missing || 'plugin_installs'::text;
|
|
637
|
+
END IF;
|
|
638
|
+
IF to_regclass('public.plugin_uploads') IS NOT NULL THEN
|
|
639
|
+
GRANT SELECT ON public.plugin_uploads TO analyst_reader;
|
|
640
|
+
ELSE
|
|
641
|
+
missing := missing || 'plugin_uploads'::text;
|
|
642
|
+
END IF;
|
|
643
|
+
IF to_regclass('public.principal_permission_grants') IS NOT NULL THEN
|
|
644
|
+
GRANT SELECT ON public.principal_permission_grants TO analyst_reader;
|
|
645
|
+
ELSE
|
|
646
|
+
missing := missing || 'principal_permission_grants'::text;
|
|
647
|
+
END IF;
|
|
648
|
+
IF to_regclass('public.recipes') IS NOT NULL THEN
|
|
649
|
+
GRANT SELECT ON public.recipes TO analyst_reader;
|
|
650
|
+
ELSE
|
|
651
|
+
missing := missing || 'recipes'::text;
|
|
652
|
+
END IF;
|
|
653
|
+
IF to_regclass('public.release_update_events') IS NOT NULL THEN
|
|
654
|
+
GRANT SELECT ON public.release_update_events TO analyst_reader;
|
|
655
|
+
ELSE
|
|
656
|
+
missing := missing || 'release_update_events'::text;
|
|
657
|
+
END IF;
|
|
658
|
+
IF to_regclass('public.release_update_jobs') IS NOT NULL THEN
|
|
659
|
+
GRANT SELECT ON public.release_update_jobs TO analyst_reader;
|
|
660
|
+
ELSE
|
|
661
|
+
missing := missing || 'release_update_jobs'::text;
|
|
662
|
+
END IF;
|
|
663
|
+
IF to_regclass('public.resolved_capability_manifests') IS NOT NULL THEN
|
|
664
|
+
GRANT SELECT ON public.resolved_capability_manifests TO analyst_reader;
|
|
665
|
+
ELSE
|
|
666
|
+
missing := missing || 'resolved_capability_manifests'::text;
|
|
667
|
+
END IF;
|
|
668
|
+
IF to_regclass('public.retry_queue') IS NOT NULL THEN
|
|
669
|
+
GRANT SELECT ON public.retry_queue TO analyst_reader;
|
|
670
|
+
ELSE
|
|
671
|
+
missing := missing || 'retry_queue'::text;
|
|
672
|
+
END IF;
|
|
673
|
+
IF to_regclass('public.routine_asl_versions') IS NOT NULL THEN
|
|
674
|
+
GRANT SELECT ON public.routine_asl_versions TO analyst_reader;
|
|
675
|
+
ELSE
|
|
676
|
+
missing := missing || 'routine_asl_versions'::text;
|
|
677
|
+
END IF;
|
|
678
|
+
IF to_regclass('public.routine_code_cache') IS NOT NULL THEN
|
|
679
|
+
GRANT SELECT ON public.routine_code_cache TO analyst_reader;
|
|
680
|
+
ELSE
|
|
681
|
+
missing := missing || 'routine_code_cache'::text;
|
|
682
|
+
END IF;
|
|
683
|
+
IF to_regclass('public.routine_executions') IS NOT NULL THEN
|
|
684
|
+
GRANT SELECT ON public.routine_executions TO analyst_reader;
|
|
685
|
+
ELSE
|
|
686
|
+
missing := missing || 'routine_executions'::text;
|
|
687
|
+
END IF;
|
|
688
|
+
IF to_regclass('public.routine_repair_events') IS NOT NULL THEN
|
|
689
|
+
GRANT SELECT ON public.routine_repair_events TO analyst_reader;
|
|
690
|
+
ELSE
|
|
691
|
+
missing := missing || 'routine_repair_events'::text;
|
|
692
|
+
END IF;
|
|
693
|
+
IF to_regclass('public.routine_step_events') IS NOT NULL THEN
|
|
694
|
+
GRANT SELECT ON public.routine_step_events TO analyst_reader;
|
|
695
|
+
ELSE
|
|
696
|
+
missing := missing || 'routine_step_events'::text;
|
|
697
|
+
END IF;
|
|
698
|
+
IF to_regclass('public.routines') IS NOT NULL THEN
|
|
699
|
+
REVOKE ALL PRIVILEGES ON public.routines FROM analyst_reader;
|
|
700
|
+
GRANT SELECT (agent_id, catalog_slug, config, created_at, current_version, description, disabled_reason, documentation_md, engine, fixture_paths, id, last_run_at, module_path, name, next_run_at, owning_agent_id, schedule, state_machine_alias_arn, state_machine_arn, status, tenant_id, type, updated_at, validated_sha, visibility) ON public.routines TO analyst_reader;
|
|
701
|
+
ELSE
|
|
702
|
+
missing := missing || 'routines'::text;
|
|
703
|
+
END IF;
|
|
704
|
+
IF to_regclass('public.sandbox_agent_hourly_counters') IS NOT NULL THEN
|
|
705
|
+
GRANT SELECT ON public.sandbox_agent_hourly_counters TO analyst_reader;
|
|
706
|
+
ELSE
|
|
707
|
+
missing := missing || 'sandbox_agent_hourly_counters'::text;
|
|
708
|
+
END IF;
|
|
709
|
+
IF to_regclass('public.sandbox_invocations') IS NOT NULL THEN
|
|
710
|
+
GRANT SELECT ON public.sandbox_invocations TO analyst_reader;
|
|
711
|
+
ELSE
|
|
712
|
+
missing := missing || 'sandbox_invocations'::text;
|
|
713
|
+
END IF;
|
|
714
|
+
IF to_regclass('public.sandbox_tenant_daily_counters') IS NOT NULL THEN
|
|
715
|
+
GRANT SELECT ON public.sandbox_tenant_daily_counters TO analyst_reader;
|
|
716
|
+
ELSE
|
|
717
|
+
missing := missing || 'sandbox_tenant_daily_counters'::text;
|
|
718
|
+
END IF;
|
|
719
|
+
IF to_regclass('public.scheduled_jobs') IS NOT NULL THEN
|
|
720
|
+
GRANT SELECT ON public.scheduled_jobs TO analyst_reader;
|
|
721
|
+
ELSE
|
|
722
|
+
missing := missing || 'scheduled_jobs'::text;
|
|
723
|
+
END IF;
|
|
724
|
+
IF to_regclass('public.skill_catalog') IS NOT NULL THEN
|
|
725
|
+
REVOKE ALL PRIVILEGES ON public.skill_catalog FROM analyst_reader;
|
|
726
|
+
GRANT SELECT (category, content_sha, created_at, description, display_name, icon, id, signature_status, signed_at, signed_by_user_id, signed_content_sha, signed_payload_hash, slug, tags, tenant_id, trust_report, trust_report_content_sha, trust_report_pipeline_version, trust_report_updated_at, updated_at) ON public.skill_catalog TO analyst_reader;
|
|
727
|
+
ELSE
|
|
728
|
+
missing := missing || 'skill_catalog'::text;
|
|
729
|
+
END IF;
|
|
730
|
+
IF to_regclass('public.skill_draft_events') IS NOT NULL THEN
|
|
731
|
+
GRANT SELECT ON public.skill_draft_events TO analyst_reader;
|
|
732
|
+
ELSE
|
|
733
|
+
missing := missing || 'skill_draft_events'::text;
|
|
734
|
+
END IF;
|
|
735
|
+
IF to_regclass('public.skill_drafts') IS NOT NULL THEN
|
|
736
|
+
GRANT SELECT ON public.skill_drafts TO analyst_reader;
|
|
737
|
+
ELSE
|
|
738
|
+
missing := missing || 'skill_drafts'::text;
|
|
739
|
+
END IF;
|
|
740
|
+
IF to_regclass('public.skill_runs') IS NOT NULL THEN
|
|
741
|
+
REVOKE ALL PRIVILEGES ON public.skill_runs FROM analyst_reader;
|
|
742
|
+
GRANT SELECT (agent_id, created_at, delete_at, delivered_artifact_ref, delivery_channels, failure_reason, feedback_note, feedback_signal, finished_at, id, inputs, invocation_source, invoker_user_id, resolved_inputs, resolved_inputs_hash, skill_id, skill_version, started_at, status, tenant_id, triggered_by_run_id, updated_at) ON public.skill_runs TO analyst_reader;
|
|
743
|
+
ELSE
|
|
744
|
+
missing := missing || 'skill_runs'::text;
|
|
745
|
+
END IF;
|
|
746
|
+
IF to_regclass('public.slack_threads') IS NOT NULL THEN
|
|
747
|
+
GRANT SELECT ON public.slack_threads TO analyst_reader;
|
|
748
|
+
ELSE
|
|
749
|
+
missing := missing || 'slack_threads'::text;
|
|
750
|
+
END IF;
|
|
751
|
+
IF to_regclass('public.slack_user_links') IS NOT NULL THEN
|
|
752
|
+
GRANT SELECT ON public.slack_user_links TO analyst_reader;
|
|
753
|
+
ELSE
|
|
754
|
+
missing := missing || 'slack_user_links'::text;
|
|
755
|
+
END IF;
|
|
756
|
+
IF to_regclass('public.space_checklist_items') IS NOT NULL THEN
|
|
757
|
+
GRANT SELECT ON public.space_checklist_items TO analyst_reader;
|
|
758
|
+
ELSE
|
|
759
|
+
missing := missing || 'space_checklist_items'::text;
|
|
760
|
+
END IF;
|
|
761
|
+
IF to_regclass('public.space_checklist_templates') IS NOT NULL THEN
|
|
762
|
+
GRANT SELECT ON public.space_checklist_templates TO analyst_reader;
|
|
763
|
+
ELSE
|
|
764
|
+
missing := missing || 'space_checklist_templates'::text;
|
|
765
|
+
END IF;
|
|
766
|
+
IF to_regclass('public.space_integrations') IS NOT NULL THEN
|
|
767
|
+
GRANT SELECT ON public.space_integrations TO analyst_reader;
|
|
768
|
+
ELSE
|
|
769
|
+
missing := missing || 'space_integrations'::text;
|
|
770
|
+
END IF;
|
|
771
|
+
IF to_regclass('public.space_knowledge_bases') IS NOT NULL THEN
|
|
772
|
+
GRANT SELECT ON public.space_knowledge_bases TO analyst_reader;
|
|
773
|
+
ELSE
|
|
774
|
+
missing := missing || 'space_knowledge_bases'::text;
|
|
775
|
+
END IF;
|
|
776
|
+
IF to_regclass('public.space_mcp_servers') IS NOT NULL THEN
|
|
777
|
+
GRANT SELECT ON public.space_mcp_servers TO analyst_reader;
|
|
778
|
+
ELSE
|
|
779
|
+
missing := missing || 'space_mcp_servers'::text;
|
|
780
|
+
END IF;
|
|
781
|
+
IF to_regclass('public.space_members') IS NOT NULL THEN
|
|
782
|
+
GRANT SELECT ON public.space_members TO analyst_reader;
|
|
783
|
+
ELSE
|
|
784
|
+
missing := missing || 'space_members'::text;
|
|
785
|
+
END IF;
|
|
786
|
+
IF to_regclass('public.spaces') IS NOT NULL THEN
|
|
787
|
+
GRANT SELECT ON public.spaces TO analyst_reader;
|
|
788
|
+
ELSE
|
|
789
|
+
missing := missing || 'spaces'::text;
|
|
790
|
+
END IF;
|
|
791
|
+
IF to_regclass('public.stripe_customers') IS NOT NULL THEN
|
|
792
|
+
GRANT SELECT ON public.stripe_customers TO analyst_reader;
|
|
793
|
+
ELSE
|
|
794
|
+
missing := missing || 'stripe_customers'::text;
|
|
795
|
+
END IF;
|
|
796
|
+
IF to_regclass('public.stripe_subscriptions') IS NOT NULL THEN
|
|
797
|
+
GRANT SELECT ON public.stripe_subscriptions TO analyst_reader;
|
|
798
|
+
ELSE
|
|
799
|
+
missing := missing || 'stripe_subscriptions'::text;
|
|
800
|
+
END IF;
|
|
801
|
+
IF to_regclass('public.tenant_builtin_tools') IS NOT NULL THEN
|
|
802
|
+
REVOKE ALL PRIVILEGES ON public.tenant_builtin_tools FROM analyst_reader;
|
|
803
|
+
GRANT SELECT (config, created_at, enabled, id, last_tested_at, provider, tenant_id, tool_slug, updated_at) ON public.tenant_builtin_tools TO analyst_reader;
|
|
804
|
+
ELSE
|
|
805
|
+
missing := missing || 'tenant_builtin_tools'::text;
|
|
806
|
+
END IF;
|
|
807
|
+
IF to_regclass('public.tenant_context_provider_settings') IS NOT NULL THEN
|
|
808
|
+
GRANT SELECT ON public.tenant_context_provider_settings TO analyst_reader;
|
|
809
|
+
ELSE
|
|
810
|
+
missing := missing || 'tenant_context_provider_settings'::text;
|
|
811
|
+
END IF;
|
|
812
|
+
IF to_regclass('public.tenant_mcp_context_tools') IS NOT NULL THEN
|
|
813
|
+
GRANT SELECT ON public.tenant_mcp_context_tools TO analyst_reader;
|
|
814
|
+
ELSE
|
|
815
|
+
missing := missing || 'tenant_mcp_context_tools'::text;
|
|
816
|
+
END IF;
|
|
817
|
+
IF to_regclass('public.tenant_mcp_servers') IS NOT NULL THEN
|
|
818
|
+
REVOKE ALL PRIVILEGES ON public.tenant_mcp_servers FROM analyst_reader;
|
|
819
|
+
GRANT SELECT (approved_at, approved_by, auth_type, created_at, enabled, id, managed_application_key, management_source, name, oauth_provider, plugin_install_id, runtime_metadata, slug, status, tenant_id, tools, transport, updated_at, url, url_hash) ON public.tenant_mcp_servers TO analyst_reader;
|
|
820
|
+
ELSE
|
|
821
|
+
missing := missing || 'tenant_mcp_servers'::text;
|
|
822
|
+
END IF;
|
|
823
|
+
IF to_regclass('public.tenant_members') IS NOT NULL THEN
|
|
824
|
+
GRANT SELECT ON public.tenant_members TO analyst_reader;
|
|
825
|
+
ELSE
|
|
826
|
+
missing := missing || 'tenant_members'::text;
|
|
827
|
+
END IF;
|
|
828
|
+
IF to_regclass('public.tenant_model_catalog') IS NOT NULL THEN
|
|
829
|
+
GRANT SELECT ON public.tenant_model_catalog TO analyst_reader;
|
|
830
|
+
ELSE
|
|
831
|
+
missing := missing || 'tenant_model_catalog'::text;
|
|
832
|
+
END IF;
|
|
833
|
+
IF to_regclass('public.tenant_policy_events') IS NOT NULL THEN
|
|
834
|
+
GRANT SELECT ON public.tenant_policy_events TO analyst_reader;
|
|
835
|
+
ELSE
|
|
836
|
+
missing := missing || 'tenant_policy_events'::text;
|
|
837
|
+
END IF;
|
|
838
|
+
IF to_regclass('public.tenant_settings') IS NOT NULL THEN
|
|
839
|
+
GRANT SELECT ON public.tenant_settings TO analyst_reader;
|
|
840
|
+
ELSE
|
|
841
|
+
missing := missing || 'tenant_settings'::text;
|
|
842
|
+
END IF;
|
|
843
|
+
IF to_regclass('public.tenant_system_users') IS NOT NULL THEN
|
|
844
|
+
GRANT SELECT ON public.tenant_system_users TO analyst_reader;
|
|
845
|
+
ELSE
|
|
846
|
+
missing := missing || 'tenant_system_users'::text;
|
|
847
|
+
END IF;
|
|
848
|
+
IF to_regclass('public.tenant_workflow_catalog') IS NOT NULL THEN
|
|
849
|
+
GRANT SELECT ON public.tenant_workflow_catalog TO analyst_reader;
|
|
850
|
+
ELSE
|
|
851
|
+
missing := missing || 'tenant_workflow_catalog'::text;
|
|
852
|
+
END IF;
|
|
853
|
+
IF to_regclass('public.tenants') IS NOT NULL THEN
|
|
854
|
+
GRANT SELECT ON public.tenants TO analyst_reader;
|
|
855
|
+
ELSE
|
|
856
|
+
missing := missing || 'tenants'::text;
|
|
857
|
+
END IF;
|
|
858
|
+
IF to_regclass('public.thread_attachments') IS NOT NULL THEN
|
|
859
|
+
GRANT SELECT ON public.thread_attachments TO analyst_reader;
|
|
860
|
+
ELSE
|
|
861
|
+
missing := missing || 'thread_attachments'::text;
|
|
862
|
+
END IF;
|
|
863
|
+
IF to_regclass('public.thread_dependencies') IS NOT NULL THEN
|
|
864
|
+
GRANT SELECT ON public.thread_dependencies TO analyst_reader;
|
|
865
|
+
ELSE
|
|
866
|
+
missing := missing || 'thread_dependencies'::text;
|
|
867
|
+
END IF;
|
|
868
|
+
IF to_regclass('public.thread_idle_learning_runs') IS NOT NULL THEN
|
|
869
|
+
GRANT SELECT ON public.thread_idle_learning_runs TO analyst_reader;
|
|
870
|
+
ELSE
|
|
871
|
+
missing := missing || 'thread_idle_learning_runs'::text;
|
|
872
|
+
END IF;
|
|
873
|
+
IF to_regclass('public.thread_idle_learning_state') IS NOT NULL THEN
|
|
874
|
+
GRANT SELECT ON public.thread_idle_learning_state TO analyst_reader;
|
|
875
|
+
ELSE
|
|
876
|
+
missing := missing || 'thread_idle_learning_state'::text;
|
|
877
|
+
END IF;
|
|
878
|
+
IF to_regclass('public.thread_label_assignments') IS NOT NULL THEN
|
|
879
|
+
GRANT SELECT ON public.thread_label_assignments TO analyst_reader;
|
|
880
|
+
ELSE
|
|
881
|
+
missing := missing || 'thread_label_assignments'::text;
|
|
882
|
+
END IF;
|
|
883
|
+
IF to_regclass('public.thread_labels') IS NOT NULL THEN
|
|
884
|
+
GRANT SELECT ON public.thread_labels TO analyst_reader;
|
|
885
|
+
ELSE
|
|
886
|
+
missing := missing || 'thread_labels'::text;
|
|
887
|
+
END IF;
|
|
888
|
+
IF to_regclass('public.thread_participants') IS NOT NULL THEN
|
|
889
|
+
GRANT SELECT ON public.thread_participants TO analyst_reader;
|
|
890
|
+
ELSE
|
|
891
|
+
missing := missing || 'thread_participants'::text;
|
|
892
|
+
END IF;
|
|
893
|
+
IF to_regclass('public.thread_turn_events') IS NOT NULL THEN
|
|
894
|
+
GRANT SELECT ON public.thread_turn_events TO analyst_reader;
|
|
895
|
+
ELSE
|
|
896
|
+
missing := missing || 'thread_turn_events'::text;
|
|
897
|
+
END IF;
|
|
898
|
+
IF to_regclass('public.thread_turns') IS NOT NULL THEN
|
|
899
|
+
GRANT SELECT ON public.thread_turns TO analyst_reader;
|
|
900
|
+
ELSE
|
|
901
|
+
missing := missing || 'thread_turns'::text;
|
|
902
|
+
END IF;
|
|
903
|
+
IF to_regclass('public.threads') IS NOT NULL THEN
|
|
904
|
+
GRANT SELECT ON public.threads TO analyst_reader;
|
|
905
|
+
ELSE
|
|
906
|
+
missing := missing || 'threads'::text;
|
|
907
|
+
END IF;
|
|
908
|
+
IF to_regclass('public.trace_cost_reconciliation_facts') IS NOT NULL THEN
|
|
909
|
+
GRANT SELECT ON public.trace_cost_reconciliation_facts TO analyst_reader;
|
|
910
|
+
ELSE
|
|
911
|
+
missing := missing || 'trace_cost_reconciliation_facts'::text;
|
|
912
|
+
END IF;
|
|
913
|
+
IF to_regclass('public.trace_events') IS NOT NULL THEN
|
|
914
|
+
GRANT SELECT ON public.trace_events TO analyst_reader;
|
|
915
|
+
ELSE
|
|
916
|
+
missing := missing || 'trace_events'::text;
|
|
917
|
+
END IF;
|
|
918
|
+
IF to_regclass('public.trace_runs') IS NOT NULL THEN
|
|
919
|
+
GRANT SELECT ON public.trace_runs TO analyst_reader;
|
|
920
|
+
ELSE
|
|
921
|
+
missing := missing || 'trace_runs'::text;
|
|
922
|
+
END IF;
|
|
923
|
+
IF to_regclass('public.trace_source_evidence') IS NOT NULL THEN
|
|
924
|
+
GRANT SELECT ON public.trace_source_evidence TO analyst_reader;
|
|
925
|
+
ELSE
|
|
926
|
+
missing := missing || 'trace_source_evidence'::text;
|
|
927
|
+
END IF;
|
|
928
|
+
IF to_regclass('public.user_model_approvals') IS NOT NULL THEN
|
|
929
|
+
GRANT SELECT ON public.user_model_approvals TO analyst_reader;
|
|
930
|
+
ELSE
|
|
931
|
+
missing := missing || 'user_model_approvals'::text;
|
|
932
|
+
END IF;
|
|
933
|
+
IF to_regclass('public.user_plugin_activations') IS NOT NULL THEN
|
|
934
|
+
GRANT SELECT ON public.user_plugin_activations TO analyst_reader;
|
|
935
|
+
ELSE
|
|
936
|
+
missing := missing || 'user_plugin_activations'::text;
|
|
937
|
+
END IF;
|
|
938
|
+
IF to_regclass('public.user_profiles') IS NOT NULL THEN
|
|
939
|
+
GRANT SELECT ON public.user_profiles TO analyst_reader;
|
|
940
|
+
ELSE
|
|
941
|
+
missing := missing || 'user_profiles'::text;
|
|
942
|
+
END IF;
|
|
943
|
+
IF to_regclass('public.user_quick_actions') IS NOT NULL THEN
|
|
944
|
+
GRANT SELECT ON public.user_quick_actions TO analyst_reader;
|
|
945
|
+
ELSE
|
|
946
|
+
missing := missing || 'user_quick_actions'::text;
|
|
947
|
+
END IF;
|
|
948
|
+
IF to_regclass('public.users') IS NOT NULL THEN
|
|
949
|
+
REVOKE ALL PRIVILEGES ON public.users FROM analyst_reader;
|
|
950
|
+
GRANT SELECT (cognito_sub, created_at, email, email_verified_at, id, image, name, phone, phone_verified_at, tenant_id, updated_at, wiki_compile_external_enabled, workspace_folder_name) ON public.users TO analyst_reader;
|
|
951
|
+
ELSE
|
|
952
|
+
missing := missing || 'users'::text;
|
|
953
|
+
END IF;
|
|
954
|
+
IF to_regclass('public.wakeup_requests') IS NOT NULL THEN
|
|
955
|
+
GRANT SELECT ON public.wakeup_requests TO analyst_reader;
|
|
956
|
+
ELSE
|
|
957
|
+
missing := missing || 'wakeup_requests'::text;
|
|
958
|
+
END IF;
|
|
959
|
+
IF to_regclass('public.work_item_comments') IS NOT NULL THEN
|
|
960
|
+
GRANT SELECT ON public.work_item_comments TO analyst_reader;
|
|
961
|
+
ELSE
|
|
962
|
+
missing := missing || 'work_item_comments'::text;
|
|
963
|
+
END IF;
|
|
964
|
+
IF to_regclass('public.work_item_documents') IS NOT NULL THEN
|
|
965
|
+
GRANT SELECT ON public.work_item_documents TO analyst_reader;
|
|
966
|
+
ELSE
|
|
967
|
+
missing := missing || 'work_item_documents'::text;
|
|
968
|
+
END IF;
|
|
969
|
+
IF to_regclass('public.work_item_events') IS NOT NULL THEN
|
|
970
|
+
GRANT SELECT ON public.work_item_events TO analyst_reader;
|
|
971
|
+
ELSE
|
|
972
|
+
missing := missing || 'work_item_events'::text;
|
|
973
|
+
END IF;
|
|
974
|
+
IF to_regclass('public.work_item_external_refs') IS NOT NULL THEN
|
|
975
|
+
GRANT SELECT ON public.work_item_external_refs TO analyst_reader;
|
|
976
|
+
ELSE
|
|
977
|
+
missing := missing || 'work_item_external_refs'::text;
|
|
978
|
+
END IF;
|
|
979
|
+
IF to_regclass('public.work_item_label_assignments') IS NOT NULL THEN
|
|
980
|
+
GRANT SELECT ON public.work_item_label_assignments TO analyst_reader;
|
|
981
|
+
ELSE
|
|
982
|
+
missing := missing || 'work_item_label_assignments'::text;
|
|
983
|
+
END IF;
|
|
984
|
+
IF to_regclass('public.work_item_labels') IS NOT NULL THEN
|
|
985
|
+
GRANT SELECT ON public.work_item_labels TO analyst_reader;
|
|
986
|
+
ELSE
|
|
987
|
+
missing := missing || 'work_item_labels'::text;
|
|
988
|
+
END IF;
|
|
989
|
+
IF to_regclass('public.work_item_saved_views') IS NOT NULL THEN
|
|
990
|
+
GRANT SELECT ON public.work_item_saved_views TO analyst_reader;
|
|
991
|
+
ELSE
|
|
992
|
+
missing := missing || 'work_item_saved_views'::text;
|
|
993
|
+
END IF;
|
|
994
|
+
IF to_regclass('public.work_item_statuses') IS NOT NULL THEN
|
|
995
|
+
GRANT SELECT ON public.work_item_statuses TO analyst_reader;
|
|
996
|
+
ELSE
|
|
997
|
+
missing := missing || 'work_item_statuses'::text;
|
|
998
|
+
END IF;
|
|
999
|
+
IF to_regclass('public.work_item_thread_links') IS NOT NULL THEN
|
|
1000
|
+
GRANT SELECT ON public.work_item_thread_links TO analyst_reader;
|
|
1001
|
+
ELSE
|
|
1002
|
+
missing := missing || 'work_item_thread_links'::text;
|
|
1003
|
+
END IF;
|
|
1004
|
+
IF to_regclass('public.work_items') IS NOT NULL THEN
|
|
1005
|
+
GRANT SELECT ON public.work_items TO analyst_reader;
|
|
1006
|
+
ELSE
|
|
1007
|
+
missing := missing || 'work_items'::text;
|
|
1008
|
+
END IF;
|
|
1009
|
+
IF to_regclass('public.workflow_configs') IS NOT NULL THEN
|
|
1010
|
+
GRANT SELECT ON public.workflow_configs TO analyst_reader;
|
|
1011
|
+
ELSE
|
|
1012
|
+
missing := missing || 'workflow_configs'::text;
|
|
1013
|
+
END IF;
|
|
1014
|
+
IF to_regclass('public.workflow_engine_bindings') IS NOT NULL THEN
|
|
1015
|
+
GRANT SELECT ON public.workflow_engine_bindings TO analyst_reader;
|
|
1016
|
+
ELSE
|
|
1017
|
+
missing := missing || 'workflow_engine_bindings'::text;
|
|
1018
|
+
END IF;
|
|
1019
|
+
IF to_regclass('public.workflow_evidence') IS NOT NULL THEN
|
|
1020
|
+
GRANT SELECT ON public.workflow_evidence TO analyst_reader;
|
|
1021
|
+
ELSE
|
|
1022
|
+
missing := missing || 'workflow_evidence'::text;
|
|
1023
|
+
END IF;
|
|
1024
|
+
IF to_regclass('public.workflow_run_events') IS NOT NULL THEN
|
|
1025
|
+
GRANT SELECT ON public.workflow_run_events TO analyst_reader;
|
|
1026
|
+
ELSE
|
|
1027
|
+
missing := missing || 'workflow_run_events'::text;
|
|
1028
|
+
END IF;
|
|
1029
|
+
IF to_regclass('public.workflow_runs') IS NOT NULL THEN
|
|
1030
|
+
GRANT SELECT ON public.workflow_runs TO analyst_reader;
|
|
1031
|
+
ELSE
|
|
1032
|
+
missing := missing || 'workflow_runs'::text;
|
|
1033
|
+
END IF;
|
|
1034
|
+
IF to_regclass('public.workflow_triggers') IS NOT NULL THEN
|
|
1035
|
+
GRANT SELECT ON public.workflow_triggers TO analyst_reader;
|
|
1036
|
+
ELSE
|
|
1037
|
+
missing := missing || 'workflow_triggers'::text;
|
|
1038
|
+
END IF;
|
|
1039
|
+
IF to_regclass('public.workflow_versions') IS NOT NULL THEN
|
|
1040
|
+
GRANT SELECT ON public.workflow_versions TO analyst_reader;
|
|
1041
|
+
ELSE
|
|
1042
|
+
missing := missing || 'workflow_versions'::text;
|
|
1043
|
+
END IF;
|
|
1044
|
+
IF to_regclass('public.workflows') IS NOT NULL THEN
|
|
1045
|
+
GRANT SELECT ON public.workflows TO analyst_reader;
|
|
1046
|
+
ELSE
|
|
1047
|
+
missing := missing || 'workflows'::text;
|
|
1048
|
+
END IF;
|
|
1049
|
+
IF array_length(missing, 1) > 0 THEN
|
|
1050
|
+
RAISE WARNING 'analyst grants skipped for tables missing on this database: %', missing;
|
|
1051
|
+
END IF;
|
|
1052
|
+
END $$;
|
|
1053
|
+
-- END GENERATED ANALYST GRANTS
|
|
1054
|
+
|
|
1055
|
+
COMMIT;
|