thinkwork-cli 0.12.16 → 0.13.0

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.
Files changed (149) hide show
  1. package/dist/cli.js +517 -10403
  2. package/dist/commands/enterprise/templates/deploy-repo/docs/runbook.md +3 -8
  3. package/dist/commands/enterprise/templates/deploy-repo/terraform/main.tf +1 -184
  4. package/dist/drizzle/0050_brain_v0_entity_subtype.sql +2 -2
  5. package/dist/drizzle/0051_brain_v0_tenant_entity_pages.sql +6 -6
  6. package/dist/drizzle/0052_brain_v0_external_refs.sql +2 -2
  7. package/dist/drizzle/0053_brain_v0_unresolved_mentions_subtype.sql +2 -2
  8. package/dist/drizzle/0145_knowledge_graph_thread_ingest.sql +14 -14
  9. package/dist/drizzle/0146_knowledge_graph_source_scope.sql +1 -1
  10. package/dist/drizzle/0157_knowledge_graph_observations_source.sql +2 -2
  11. package/dist/drizzle/0158_wiki_tenant_scope.sql +1 -1
  12. package/dist/drizzle/0165_plugin_premium_entitlements.sql +2 -2
  13. package/dist/drizzle/{0166_company_brain_substrate_contract.sql → 0166_brain_substrate_contract.sql} +9 -9
  14. package/dist/drizzle/{0167_company_brain_artifact_manifest_runtime.sql → 0167_brain_artifact_manifest_runtime.sql} +5 -5
  15. package/dist/drizzle/0168_eval_skill_gate.sql +1 -1
  16. package/dist/drizzle/0183_okf_artifact_manifests.sql +1 -1
  17. package/dist/drizzle/0200_eval_results_execution_tier.sql +40 -0
  18. package/dist/drizzle/0201_brain_dream_runs.sql +72 -0
  19. package/dist/drizzle/0202_backfill_thread_participants_from_senders.sql +110 -0
  20. package/dist/drizzle/0203_threads_mode_override.sql +61 -0
  21. package/dist/drizzle/0204_thread_turns_triggering_message_id.sql +48 -0
  22. package/dist/drizzle/0205_routines_git_python.sql +185 -0
  23. package/dist/drizzle/0206_agent_loop_versions_routine_actions.sql +40 -0
  24. package/dist/drizzle/0207_tenant_credentials_github_repo_kind.sql +52 -0
  25. package/dist/drizzle/0208_knowledge_graph_neutral_identifiers.sql +253 -0
  26. package/dist/drizzle/0209_living_artifacts_schema.sql +109 -0
  27. package/dist/drizzle/0210_think137_automations_additive_schema.sql +113 -0
  28. package/dist/drizzle/0211_backfill_agent_loop_versions_target_spec.sql +120 -0
  29. package/dist/drizzle/0212_fold_webhooks_into_automations.sql +312 -0
  30. package/dist/drizzle/0213_agent_loop_versions_judge_evidence_nullable.sql +63 -0
  31. package/dist/drizzle/0214_think137_drop_judge_evidence_roi.sql +99 -0
  32. package/dist/drizzle/0215_agent_loop_versions_goal_worker_policy_nullable.sql +70 -0
  33. package/dist/drizzle/0216_drop_agent_loop_versions_goal_worker_policy.sql +81 -0
  34. package/dist/drizzle/0217_agents_capability_folder_dispatch.sql +12 -0
  35. package/dist/drizzle/0218_document_plates.sql +30 -0
  36. package/dist/drizzle/0219_document_section_waivers.sql +29 -0
  37. package/dist/drizzle/0220_artifacts_created_by_user.sql +21 -0
  38. package/dist/drizzle/0221_artifact_shares.sql +29 -0
  39. package/dist/drizzle/0221_workflow_interpreter_thin_slice.sql +71 -0
  40. package/dist/drizzle/0222_compliance_drainer_select_audit_events.sql +21 -0
  41. package/dist/drizzle/0223_document_conformance_reports.sql +38 -0
  42. package/dist/drizzle/0224_artifact_refresh_state.sql +11 -0
  43. package/dist/drizzle/0225_think216_agent_loop_convergence.sql +21 -0
  44. package/dist/drizzle/0226_drop_n8n_agent_step_runs.sql +6 -0
  45. package/dist/drizzle/0227_analyst_reader_role.sql +1055 -0
  46. package/dist/drizzle/0228_tenant_credentials_rds_iam_kind.sql +62 -0
  47. package/dist/drizzle/0229_analyst_reader_rds_iam_grant.sql +79 -0
  48. package/dist/drizzle/0230_analyst_rls.sql +1613 -0
  49. package/dist/drizzle/0231_cost_events_cache_write_enforcement_exempt.sql +11 -0
  50. package/dist/plugins/catalog/package.json +0 -1
  51. package/dist/plugins/catalog/src/__tests__/build-catalog.test.ts +0 -1
  52. package/dist/plugins/catalog/src/__tests__/catalog.test.ts +16 -8
  53. package/dist/plugins/catalog/src/__tests__/contracts.test.ts +56 -0
  54. package/dist/plugins/catalog/src/__tests__/plugin-package.test.ts +0 -2
  55. package/dist/plugins/catalog/src/__tests__/plugin-registry.test.ts +0 -5
  56. package/dist/plugins/catalog/src/contracts.ts +112 -0
  57. package/dist/plugins/catalog/src/registry/generated-first-party.ts +0 -6
  58. package/dist/plugins/n8n/README.md +4 -36
  59. package/dist/plugins/n8n/src/deployment/managed-app.ts +0 -17
  60. package/dist/plugins/n8n/src/manifest.ts +0 -5
  61. package/dist/plugins/n8n/terraform/n8n/main.tf +0 -26
  62. package/dist/plugins/n8n/terraform/n8n/outputs.tf +0 -5
  63. package/dist/plugins/n8n/terraform/n8n/variables.tf +0 -6
  64. package/dist/plugins/n8n/test/manifest.test.ts +0 -1
  65. package/dist/plugins/twenty/package.json +5 -0
  66. package/dist/plugins/twenty/scripts/lib/__tests__/load-records.test.ts +232 -0
  67. package/dist/plugins/twenty/scripts/lib/__tests__/mappers.test.ts +489 -0
  68. package/dist/plugins/twenty/scripts/lib/__tests__/members-ensure.test.ts +199 -0
  69. package/dist/plugins/twenty/scripts/lib/__tests__/provision-members-db.test.ts +43 -0
  70. package/dist/plugins/twenty/scripts/lib/__tests__/schema-ensure.test.ts +230 -0
  71. package/dist/plugins/twenty/scripts/lib/__tests__/twenty-client.test.ts +207 -0
  72. package/dist/plugins/twenty/scripts/lib/lastmile-reader.ts +282 -0
  73. package/dist/plugins/twenty/scripts/lib/load-attachments.ts +220 -0
  74. package/dist/plugins/twenty/scripts/lib/load-records.ts +680 -0
  75. package/dist/plugins/twenty/scripts/lib/mappers.ts +559 -0
  76. package/dist/plugins/twenty/scripts/lib/members-ensure.ts +381 -0
  77. package/dist/plugins/twenty/scripts/lib/provision-members-db.ts +191 -0
  78. package/dist/plugins/twenty/scripts/lib/schema-ensure.ts +425 -0
  79. package/dist/plugins/twenty/scripts/lib/twenty-client.ts +246 -0
  80. package/dist/plugins/twenty/scripts/migrate-lastmile.ts +610 -0
  81. package/dist/plugins/twenty/scripts/provision-twenty-members.ts +214 -0
  82. package/dist/plugins/twenty/src/manifest.ts +99 -0
  83. package/dist/plugins/twenty/terraform/twenty/README.md +1 -1
  84. package/dist/plugins/twenty/test/manifest.test.ts +12 -2
  85. package/dist/terraform/examples/greenfield/main.tf +90 -380
  86. package/dist/terraform/examples/greenfield/terraform.tfvars.example +0 -1
  87. package/dist/terraform/modules/app/agentcore-pi/README.md +1 -3
  88. package/dist/terraform/modules/app/agentcore-pi/main.tf +29 -38
  89. package/dist/terraform/modules/app/agentcore-pi/variables.tf +23 -15
  90. package/dist/terraform/modules/app/agentcore-runtime/main.tf +3 -3
  91. package/dist/terraform/modules/app/customer-domain/main.tf +16 -2
  92. package/dist/terraform/modules/app/deployment-control-plane/main.tf +5 -0
  93. package/dist/terraform/modules/app/deployment-control-plane/runner.py +85 -207
  94. package/dist/terraform/modules/app/deployment-control-plane/test_runner_bundle.py +56 -2
  95. package/dist/terraform/modules/app/hindsight-memory/main.tf +52 -4
  96. package/dist/terraform/modules/app/lambda-api/eval-fanout.tf +7 -0
  97. package/dist/terraform/modules/app/lambda-api/handlers.tf +493 -89
  98. package/dist/terraform/modules/app/lambda-api/iam-grouped.tf +215 -96
  99. package/dist/terraform/modules/app/lambda-api/main.tf +24 -5
  100. package/dist/terraform/modules/app/lambda-api/outputs.tf +19 -11
  101. package/dist/terraform/modules/app/lambda-api/variables.tf +94 -67
  102. package/dist/terraform/modules/app/ses-email/main.tf +14 -2
  103. package/dist/terraform/modules/app/workflow-interpreter-stepfunctions/main.tf +493 -0
  104. package/dist/terraform/modules/app/workflow-interpreter-stepfunctions/outputs.tf +34 -0
  105. package/dist/terraform/modules/app/workflow-interpreter-stepfunctions/variables.tf +32 -0
  106. package/dist/terraform/modules/data/aurora-postgres/main.tf +55 -0
  107. package/dist/terraform/modules/data/aurora-postgres/outputs.tf +15 -0
  108. package/dist/terraform/modules/data/s3-buckets/main.tf +26 -0
  109. package/dist/terraform/modules/thinkwork/README.md +0 -1
  110. package/dist/terraform/modules/thinkwork/main.tf +167 -446
  111. package/dist/terraform/modules/thinkwork/outputs.tf +2 -142
  112. package/dist/terraform/modules/thinkwork/variables.tf +55 -309
  113. package/dist/terraform/schema.graphql +4 -0
  114. package/dist/workspace-defaults/files/AGENTS.md +45 -31
  115. package/dist/workspace-defaults/files/CONTEXT.md +48 -4
  116. package/dist/workspace-defaults/files/GUARDRAILS.md +18 -0
  117. package/dist/workspace-defaults/files/MEMORY_GUIDE.md +32 -4
  118. package/dist/workspace-defaults/files/SPACE.md +34 -19
  119. package/dist/workspace-defaults/files/TOOLS.md +30 -0
  120. package/dist/workspace-defaults/files/skills/document-composer/SKILL.md +154 -0
  121. package/dist/workspace-defaults/files/skills/document-composer/references/authoring-rules.md +101 -0
  122. package/package.json +1 -1
  123. package/dist/plugins/company-brain/README.md +0 -37
  124. package/dist/plugins/company-brain/package.json +0 -33
  125. package/dist/plugins/company-brain/runtime/cognee/Dockerfile +0 -11
  126. package/dist/plugins/company-brain/smoke/cognee-managed-app-smoke.mjs +0 -458
  127. package/dist/plugins/company-brain/smoke/cognee-memory-cutover-smoke.mjs +0 -539
  128. package/dist/plugins/company-brain/smoke/company-brain-context-engine-smoke.mjs +0 -312
  129. package/dist/plugins/company-brain/smoke/company-brain-operations-smoke.mjs +0 -449
  130. package/dist/plugins/company-brain/smoke/company-brain-plugin-smoke.mjs +0 -655
  131. package/dist/plugins/company-brain/smoke/hindsight-memory-isolation-smoke.mjs +0 -474
  132. package/dist/plugins/company-brain/src/api/cognee-client.ts +0 -896
  133. package/dist/plugins/company-brain/src/api/cognee-cluster-identity.ts +0 -49
  134. package/dist/plugins/company-brain/src/api/cognee-memory-scope.ts +0 -84
  135. package/dist/plugins/company-brain/src/api/context-engine-provider.ts +0 -888
  136. package/dist/plugins/company-brain/src/api/migration.ts +0 -665
  137. package/dist/plugins/company-brain/src/deployment/cognee-managed-app.ts +0 -396
  138. package/dist/plugins/company-brain/src/index.ts +0 -62
  139. package/dist/plugins/company-brain/src/manifest.ts +0 -112
  140. package/dist/plugins/company-brain/terraform/cognee/README.md +0 -263
  141. package/dist/plugins/company-brain/terraform/cognee/main.tf +0 -766
  142. package/dist/plugins/company-brain/terraform/cognee/outputs.tf +0 -144
  143. package/dist/plugins/company-brain/terraform/cognee/variables.tf +0 -402
  144. package/dist/plugins/company-brain/test/api/cognee-client.test.ts +0 -562
  145. package/dist/plugins/company-brain/test/api/cognee-memory-scope.test.ts +0 -74
  146. package/dist/plugins/company-brain/test/api/context-engine-provider.test.ts +0 -447
  147. package/dist/plugins/company-brain/test/api/migration.test.ts +0 -465
  148. package/dist/plugins/company-brain/test/manifest.test.ts +0 -95
  149. 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;