thinkwork-cli 0.13.0 → 0.13.2
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-JUBCQQDF.js → api-client-JYZXYQJR.js} +3 -1
- package/dist/bowser-6Z6JFAIR.js +2822 -0
- package/dist/chunk-DV3MRBR5.js +43 -0
- package/dist/chunk-DVPBI5HM.js +1728 -0
- package/dist/chunk-EI5ZX7CN.js +522 -0
- package/dist/chunk-EUJ7X6YD.js +126 -0
- package/dist/chunk-GG5WKBOX.js +436 -0
- package/dist/chunk-I64EZSU5.js +358 -0
- package/dist/chunk-ILZKG5WV.js +6151 -0
- package/dist/chunk-KMIJ5KGT.js +128 -0
- package/dist/chunk-OCPHU34C.js +996 -0
- package/dist/chunk-QOERT44A.js +3286 -0
- package/dist/chunk-XYM7PE2A.js +2264 -0
- package/dist/{chunk-STY44FQO.js → chunk-Z2F6RJFR.js} +12 -18
- package/dist/cli.js +72564 -18884
- package/dist/dist-es-CRV46D5B.js +315 -0
- package/dist/dist-es-DCY4IC3Y.js +2000 -0
- package/dist/dist-es-ENBUC3JP.js +14726 -0
- package/dist/dist-es-G54LBMRN.js +48 -0
- package/dist/dist-es-G7PTG75M.js +176 -0
- package/dist/dist-es-GKDBE7E6.js +88 -0
- package/dist/dist-es-HY3535OI.js +70 -0
- package/dist/dist-es-KL7Y5NB2.js +377 -0
- package/dist/dist-es-LDE437AM.js +170 -0
- package/dist/dist-es-P26FWFLT.js +485 -0
- package/dist/dist-es-Q57SZXZ7.js +70 -0
- package/dist/dist-es-R7FGL2IB.js +88 -0
- package/dist/dist-es-USORBXZ5.js +318 -0
- package/dist/dist-es-ZKC2QKD2.js +377 -0
- package/dist/drizzle/0076_scheduled_jobs_marco_backfill.sql +2 -1
- package/dist/drizzle/0079_seed_tenant_customize_catalog.sql +1 -0
- package/dist/drizzle/0090_brain_schema_extraction.sql +10 -0
- package/dist/drizzle/0132_drop_computer_tables.sql +3 -0
- package/dist/drizzle/0160_compliance_event_types_plugins.sql +2 -0
- package/dist/drizzle/0214_think137_drop_judge_evidence_roi.sql +1 -0
- package/dist/drizzle/0216_drop_agent_loop_versions_goal_worker_policy.sql +1 -0
- package/dist/drizzle/0227_analyst_reader_role.sql +106 -38
- package/dist/drizzle/0230_analyst_rls.sql +192 -66
- package/dist/drizzle/0232_memory_source_thin_ledger.sql +176 -0
- package/dist/drizzle/0232_message_source_event_id.sql +9 -0
- package/dist/drizzle/0233_msteams_install_and_links.sql +151 -0
- package/dist/drizzle/0233_workflow_memory_stage_tokens.sql +20 -0
- package/dist/drizzle/0234_memory_claim_lifecycle.sql +160 -0
- package/dist/drizzle/0235_workflow_token_execution_claim.sql +34 -0
- package/dist/drizzle/0236_memory_retraction_fencing.sql +50 -0
- package/dist/drizzle/0237_memory_claims_active_value_uidx.sql +172 -0
- package/dist/drizzle/0238_memory_erase_generation_fence.sql +97 -0
- package/dist/drizzle/0239_canonical_entity_identity.sql +257 -0
- package/dist/drizzle/0240_memory_personal_scope.sql +45 -0
- package/dist/drizzle/0241_knowledge_base_document_manifest.sql +67 -0
- package/dist/drizzle/0242_search_queries.sql +28 -0
- package/dist/drizzle/0243_section_sources_thread_refs.sql +12 -0
- package/dist/drizzle/0244_system_automations_and_memory_stage_overrides.sql +45 -0
- package/dist/drizzle/0245_wiki_page_render.sql +21 -0
- package/dist/drizzle/0246_automation_workflow_ownership.sql +30 -0
- package/dist/drizzle/0247_capability_runtime.sql +402 -0
- package/dist/drizzle/0248_capability_private_interpreter.sql +13 -0
- package/dist/drizzle/0249_capability_headless_execution_evidence.sql +40 -0
- package/dist/drizzle/0250_kg_schema_extraction.sql +576 -0
- package/dist/drizzle/0251_agents_json_render_ui.sql +25 -0
- package/dist/drizzle/0251_brain_stragglers.sql +263 -0
- package/dist/drizzle/0252_drop_kg_and_straggler_compat_views.sql +100 -0
- package/dist/drizzle/0253_drop_brain_substrate.sql +93 -0
- package/dist/drizzle/0254_capability_autonomous_admission.sql +29 -0
- package/dist/drizzle/0255_capability_autonomous_approval_mode.sql +16 -0
- package/dist/drizzle/0256_agent_profile_manifest_authority.sql +18 -0
- package/dist/drizzle/0257_agents_runtime_allow_harness.sql +24 -0
- package/dist/drizzle/0257_capability_approvals.sql +53 -0
- package/dist/drizzle/0258_pending_tool_approvals.sql +84 -0
- package/dist/drizzle/0259_tenant_capability_registry_trust.sql +19 -0
- package/dist/drizzle/0260_scheduled_jobs_run_as_user.sql +20 -0
- package/dist/drizzle/0261_managed_harness_multiplayer.sql +313 -0
- package/dist/drizzle/0261_native_auth_control_plane.sql +328 -0
- package/dist/drizzle/0262_auth_subscription_tickets.sql +59 -0
- package/dist/drizzle/0262_parallel_harness_threads.sql +9 -0
- package/dist/drizzle/0263_agentcore_runtime_identifier.sql +69 -0
- package/dist/drizzle/0263_drop_workos_auth_runtime.sql +236 -0
- package/dist/drizzle/0264_auth_enrollment_attempt_limits.sql +15 -0
- package/dist/drizzle/0264_harness_tool_execution_ledger.sql +113 -0
- package/dist/drizzle/0265_eval_runs_requester_identity.sql +28 -0
- package/dist/drizzle/0265_require_fully_valid_auth_publication.sql +27 -0
- package/dist/drizzle/0266_auth_identity_recovery_grants.sql +9 -0
- package/dist/drizzle/0266_eval_profiles_runtime_type.sql +12 -0
- package/dist/drizzle/0267_ontology_candidate_rejections.sql +53 -0
- package/dist/drizzle/0268_identity_crosswalk_routing.sql +182 -0
- package/dist/drizzle/0269_ontology_system_map.sql +31 -0
- package/dist/event-streams-7JNLJEEL.js +894 -0
- package/dist/event-streams-KDF5RWR6.js +1515 -0
- package/dist/loadSso-DJVB7BXE.js +576 -0
- package/dist/loadSso-JAMNA3WY.js +583 -0
- package/dist/plugins/catalog/package.json +1 -2
- package/dist/plugins/catalog/src/__tests__/build-catalog.test.ts +0 -1
- package/dist/plugins/catalog/src/__tests__/contracts.test.ts +0 -69
- 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 +2 -179
- package/dist/plugins/catalog/src/registry/generated-first-party.ts +0 -6
- package/dist/signin-UGDWTGS4.js +821 -0
- package/dist/sso-oidc-Q4VXANXY.js +837 -0
- package/dist/sts-CWLSE3GH.js +1241 -0
- package/dist/sts-DNZLNVOV.js +1245 -0
- package/dist/terraform/examples/greenfield/main.tf +247 -50
- package/dist/terraform/examples/greenfield/terraform.tfvars.example +15 -1
- package/dist/terraform/modules/app/agentcore-admin/main.tf +341 -0
- package/dist/terraform/modules/app/agentcore-admin/outputs.tf +20 -0
- package/dist/terraform/modules/app/agentcore-code-interpreter/main.tf +61 -0
- package/dist/terraform/modules/app/agentcore-gateway/main.tf +305 -0
- package/dist/terraform/modules/app/agentcore-gateway/outputs.tf +44 -0
- package/dist/terraform/modules/app/agentcore-gateway/scripts/delete_gateway.sh +93 -0
- package/dist/terraform/modules/app/agentcore-gateway/scripts/read_gateway.sh +33 -0
- package/dist/terraform/modules/app/agentcore-gateway/scripts/reconcile_gateway.sh +543 -0
- package/dist/terraform/modules/app/agentcore-gateway/variables.tf +70 -0
- package/dist/terraform/modules/app/agentcore-harness/main.tf +330 -0
- package/dist/terraform/modules/app/agentcore-harness/outputs.tf +72 -0
- package/dist/terraform/modules/app/agentcore-harness/scripts/delete_harness.sh +5 -0
- package/dist/terraform/modules/app/agentcore-harness/scripts/harness-lifecycle.mjs +430 -0
- package/dist/terraform/modules/app/agentcore-harness/scripts/harness-readback.mjs +180 -0
- package/dist/terraform/modules/app/agentcore-harness/scripts/harness-tool-contract.mjs +193 -0
- package/dist/terraform/modules/app/agentcore-harness/scripts/prune_harness.sh +5 -0
- package/dist/terraform/modules/app/agentcore-harness/scripts/read_harness.sh +5 -0
- package/dist/terraform/modules/app/agentcore-harness/scripts/reconcile_harness.sh +5 -0
- package/dist/terraform/modules/app/agentcore-harness/variables.tf +96 -0
- package/dist/terraform/modules/app/agentcore-identity/main.tf +173 -0
- package/dist/terraform/modules/app/agentcore-identity/outputs.tf +51 -0
- package/dist/terraform/modules/app/agentcore-identity/scripts/bootstrap_twenty_oauth_client.sh +122 -0
- package/dist/terraform/modules/app/agentcore-identity/scripts/delete_identity.sh +25 -0
- package/dist/terraform/modules/app/agentcore-identity/scripts/delete_twenty_identity.sh +16 -0
- package/dist/terraform/modules/app/agentcore-identity/scripts/read_identity.sh +40 -0
- package/dist/terraform/modules/app/agentcore-identity/scripts/reconcile_identity.sh +73 -0
- package/dist/terraform/modules/app/agentcore-identity/scripts/reconcile_twenty_identity.sh +74 -0
- package/dist/terraform/modules/app/agentcore-identity/scripts/reconcile_twenty_provider.mjs +61 -0
- package/dist/terraform/modules/app/agentcore-identity/variables.tf +54 -0
- package/dist/terraform/modules/app/agentcore-pi/main.tf +7 -0
- package/dist/terraform/modules/app/appsync-subscriptions/main.tf +127 -21
- package/dist/terraform/modules/app/appsync-subscriptions/outputs.tf +0 -6
- package/dist/terraform/modules/app/appsync-subscriptions/variables.tf +5 -0
- package/dist/terraform/modules/app/capability-broker/main.tf +393 -0
- package/dist/terraform/modules/app/capability-broker/outputs.tf +54 -0
- package/dist/terraform/modules/app/capability-broker/variables.tf +98 -0
- package/dist/terraform/modules/app/deployment-control-plane/runner.py +1011 -31
- package/dist/terraform/modules/app/deployment-control-plane/test_runner_bundle.py +655 -2
- package/dist/terraform/modules/app/lambda-api/agentcore-harness-alarms.tf +88 -0
- package/dist/terraform/modules/app/lambda-api/agentcore-identity-alarms.tf +91 -0
- package/dist/terraform/modules/app/lambda-api/capability-search-alarms.tf +60 -0
- package/dist/terraform/modules/app/lambda-api/handlers.tf +606 -37
- package/dist/terraform/modules/app/lambda-api/iam-grouped.tf +192 -21
- package/dist/terraform/modules/app/lambda-api/main.tf +35 -0
- package/dist/terraform/modules/app/lambda-api/mcp-oauth.tf +181 -4
- package/dist/terraform/modules/app/lambda-api/memory-alarms.tf +92 -0
- package/dist/terraform/modules/app/lambda-api/msteams-app-secrets.tf +46 -0
- package/dist/terraform/modules/app/lambda-api/outputs.tf +35 -0
- package/dist/terraform/modules/app/lambda-api/runtime-config.tf +3 -21
- package/dist/terraform/modules/app/lambda-api/variables.tf +188 -3
- package/dist/terraform/modules/app/workflow-interpreter-stepfunctions/alarms.tf +47 -0
- package/dist/terraform/modules/app/workflow-interpreter-stepfunctions/main.tf +43 -2
- package/dist/terraform/modules/foundation/cognito/main.tf +319 -73
- package/dist/terraform/modules/foundation/cognito/outputs.tf +42 -0
- package/dist/terraform/modules/foundation/cognito/variables.tf +124 -2
- package/dist/terraform/modules/foundation/vpc/outputs.tf +5 -0
- package/dist/terraform/modules/thinkwork/main.tf +396 -26
- package/dist/terraform/modules/thinkwork/outputs.tf +188 -5
- package/dist/terraform/modules/thinkwork/variables.tf +154 -5
- package/dist/terraform/schema.graphql +69 -36
- package/dist/workspace-defaults/files/TOOLS.md +39 -0
- package/dist/workspace-defaults/files/USER.md +1 -0
- package/dist/workspace-defaults/files/agents/analyst/INSTRUCTIONS.md +18 -0
- package/dist/workspace-defaults/files/agents/coding/INSTRUCTIONS.md +11 -0
- package/dist/workspace-defaults/files/agents/research/INSTRUCTIONS.md +12 -0
- package/dist/workspace-defaults/files/agents/reviewer/INSTRUCTIONS.md +15 -0
- package/dist/workspace-defaults/files/skills/document-composer/SKILL.md +6 -2
- package/package.json +6 -3
- package/dist/plugins/workos-auth/package.json +0 -22
- package/dist/plugins/workos-auth/src/index.ts +0 -30
- package/dist/plugins/workos-auth/src/manifest.ts +0 -40
- package/dist/plugins/workos-auth/src/provider-contract.ts +0 -39
- package/dist/plugins/workos-auth/test/manifest.test.ts +0 -94
- package/dist/plugins/workos-auth/tsconfig.json +0 -8
- /package/dist/workspace-defaults/files/{AGENTS.md → INSTRUCTIONS.md} +0 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
-- THINK-302 U11: pending_tool_approvals — parked-turn HITL ledger.
|
|
2
|
+
--
|
|
3
|
+
-- A distinct pending kind from pending_user_questions (KTD-5): a gated tool
|
|
4
|
+
-- call parks the turn and this row is the recoverable ledger. Two partial
|
|
5
|
+
-- unique indexes drizzle-kit cannot express live here:
|
|
6
|
+
-- * one `pending` approval per thread (the one-slot invariant, R32) — so
|
|
7
|
+
-- an approval can COEXIST with a pending question (separate tables/slots),
|
|
8
|
+
-- and the intake endpoint returns 409 on a second concurrent park.
|
|
9
|
+
-- * resume-replay uniqueness (thread_turn_id, tool_call_id, manifest
|
|
10
|
+
-- fingerprint) — a stale approval cannot authorize a drifted definition
|
|
11
|
+
-- and a retried intake is idempotent.
|
|
12
|
+
--
|
|
13
|
+
-- Ships INERT: no writer touches this table until U11b; U12 consumes it.
|
|
14
|
+
--
|
|
15
|
+
-- Hand-rolled (partial indices, CHECK constraints); not in meta/_journal.json.
|
|
16
|
+
-- Apply manually:
|
|
17
|
+
-- psql "$DATABASE_URL" -v ON_ERROR_STOP=1 -f drizzle/0258_pending_tool_approvals.sql
|
|
18
|
+
-- creates: public.pending_tool_approvals
|
|
19
|
+
-- creates: public.pending_tool_approvals_one_pending_per_thread
|
|
20
|
+
-- creates: public.pending_tool_approvals_resume_identity
|
|
21
|
+
-- creates: public.idx_pending_tool_approvals_tenant
|
|
22
|
+
-- creates: public.idx_pending_tool_approvals_thread_status
|
|
23
|
+
-- creates: public.idx_pending_tool_approvals_message
|
|
24
|
+
-- creates: public.idx_pending_tool_approvals_purge
|
|
25
|
+
|
|
26
|
+
\set ON_ERROR_STOP on
|
|
27
|
+
|
|
28
|
+
SET lock_timeout = '5s';
|
|
29
|
+
SET statement_timeout = '15min';
|
|
30
|
+
|
|
31
|
+
SELECT pg_advisory_lock(hashtext('migration:0258_pending_tool_approvals'));
|
|
32
|
+
|
|
33
|
+
CREATE TABLE IF NOT EXISTS public.pending_tool_approvals (
|
|
34
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
35
|
+
tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
|
|
36
|
+
thread_id uuid NOT NULL REFERENCES public.threads(id) ON DELETE CASCADE,
|
|
37
|
+
thread_turn_id uuid NOT NULL REFERENCES public.thread_turns(id),
|
|
38
|
+
message_id uuid NOT NULL REFERENCES public.messages(id) ON DELETE CASCADE,
|
|
39
|
+
manifest_fingerprint text NOT NULL,
|
|
40
|
+
tool_call_id text NOT NULL,
|
|
41
|
+
class text NOT NULL,
|
|
42
|
+
slug text NOT NULL,
|
|
43
|
+
marker_sha text NOT NULL,
|
|
44
|
+
status text NOT NULL DEFAULT 'pending',
|
|
45
|
+
requesting_user_id uuid REFERENCES public.users(id) ON DELETE SET NULL,
|
|
46
|
+
encrypted_payload text,
|
|
47
|
+
display_summary jsonb NOT NULL,
|
|
48
|
+
approved_by uuid REFERENCES public.users(id) ON DELETE SET NULL,
|
|
49
|
+
answered_via text,
|
|
50
|
+
answered_at timestamptz,
|
|
51
|
+
payload_purged_at timestamptz,
|
|
52
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
53
|
+
CONSTRAINT pending_tool_approvals_status_allowed
|
|
54
|
+
CHECK (status IN ('pending','approved','denied','cancelled')),
|
|
55
|
+
CONSTRAINT pending_tool_approvals_answered_via_allowed
|
|
56
|
+
CHECK (answered_via IS NULL OR answered_via IN ('card','slack','governance','archive','reaper')),
|
|
57
|
+
CONSTRAINT pending_tool_approvals_terminal_consistency
|
|
58
|
+
CHECK ((status = 'pending') = (answered_at IS NULL))
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
-- One pending approval per thread (the one-slot invariant). Partial so
|
|
62
|
+
-- terminal rows never block a new park, and so it is INDEPENDENT of the
|
|
63
|
+
-- pending_user_questions slot (an approval + a question can both be pending).
|
|
64
|
+
CREATE UNIQUE INDEX IF NOT EXISTS pending_tool_approvals_one_pending_per_thread
|
|
65
|
+
ON public.pending_tool_approvals (thread_id)
|
|
66
|
+
WHERE status = 'pending';
|
|
67
|
+
|
|
68
|
+
-- Resume-replay identity: a park is unique per (turn, tool call, pinned
|
|
69
|
+
-- manifest) so a retried intake is idempotent and a stale approval cannot
|
|
70
|
+
-- authorize a drifted definition.
|
|
71
|
+
CREATE UNIQUE INDEX IF NOT EXISTS pending_tool_approvals_resume_identity
|
|
72
|
+
ON public.pending_tool_approvals (thread_turn_id, tool_call_id, manifest_fingerprint);
|
|
73
|
+
|
|
74
|
+
CREATE INDEX IF NOT EXISTS idx_pending_tool_approvals_tenant
|
|
75
|
+
ON public.pending_tool_approvals (tenant_id);
|
|
76
|
+
CREATE INDEX IF NOT EXISTS idx_pending_tool_approvals_thread_status
|
|
77
|
+
ON public.pending_tool_approvals (thread_id, status);
|
|
78
|
+
CREATE INDEX IF NOT EXISTS idx_pending_tool_approvals_message
|
|
79
|
+
ON public.pending_tool_approvals (message_id);
|
|
80
|
+
-- Reaper scan: terminal rows whose payload is not yet purged, by age.
|
|
81
|
+
CREATE INDEX IF NOT EXISTS idx_pending_tool_approvals_purge
|
|
82
|
+
ON public.pending_tool_approvals (status, payload_purged_at);
|
|
83
|
+
|
|
84
|
+
SELECT pg_advisory_unlock(hashtext('migration:0258_pending_tool_approvals'));
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
-- THINK-302 U3b: per-tenant capability registry-trust gate (KTD-8).
|
|
2
|
+
--
|
|
3
|
+
-- Off for every tenant at migration time; flipped on per tenant
|
|
4
|
+
-- (dev → TEI → McPherson) as the capability approval registry replaces
|
|
5
|
+
-- per-folder sidecar signatures. Read by the workspace renderer
|
|
6
|
+
-- (compose-tuple) to decide registry-trust vs legacy sidecar admission.
|
|
7
|
+
--
|
|
8
|
+
-- Additive, idempotent column add. Hand-rolled only so it carries a
|
|
9
|
+
-- drift-gate marker alongside the sibling hand-rolled capability migrations;
|
|
10
|
+
-- db:push would also add it from the ORM definition.
|
|
11
|
+
--
|
|
12
|
+
-- Apply manually:
|
|
13
|
+
-- psql "$DATABASE_URL" -v ON_ERROR_STOP=1 -f drizzle/0259_tenant_capability_registry_trust.sql
|
|
14
|
+
-- creates-column: public.tenants.capability_registry_trust
|
|
15
|
+
|
|
16
|
+
\set ON_ERROR_STOP on
|
|
17
|
+
|
|
18
|
+
ALTER TABLE public.tenants
|
|
19
|
+
ADD COLUMN IF NOT EXISTS capability_registry_trust boolean NOT NULL DEFAULT false;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
-- THINK-302 U7 (R28/KTD-14): run-as identity for wakeup/scheduled turns.
|
|
2
|
+
--
|
|
3
|
+
-- The user a scheduled/wakeup turn runs AS, so it composes that user's +
|
|
4
|
+
-- the run-in-space's capability scopes. A job with no run_as_user_id
|
|
5
|
+
-- compiles root + sub-agent only — it NEVER inherits the creator's grants.
|
|
6
|
+
-- Set/cleared only through an authorized surface (KTD-14 save-time authz);
|
|
7
|
+
-- dispatch-time revalidation drops stale grants.
|
|
8
|
+
--
|
|
9
|
+
-- Additive, idempotent nullable-FK column add (ON DELETE SET NULL so a
|
|
10
|
+
-- deactivated user's jobs degrade to root-only rather than break).
|
|
11
|
+
-- Hand-rolled only to carry the drift-gate marker; db:push would also add it.
|
|
12
|
+
--
|
|
13
|
+
-- Apply manually:
|
|
14
|
+
-- psql "$DATABASE_URL" -v ON_ERROR_STOP=1 -f drizzle/0260_scheduled_jobs_run_as_user.sql
|
|
15
|
+
-- creates-column: public.scheduled_jobs.run_as_user_id
|
|
16
|
+
|
|
17
|
+
\set ON_ERROR_STOP on
|
|
18
|
+
|
|
19
|
+
ALTER TABLE public.scheduled_jobs
|
|
20
|
+
ADD COLUMN IF NOT EXISTS run_as_user_id uuid REFERENCES public.users(id) ON DELETE SET NULL;
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
-- creates: public.harness_managed_thread_enrollments
|
|
2
|
+
-- creates: public.thread_public_events
|
|
3
|
+
-- creates: public.harness_participant_sessions
|
|
4
|
+
-- creates: public.harness_participant_session_events
|
|
5
|
+
-- creates: public.harness_governed_tool_executions
|
|
6
|
+
-- creates: public.harness_disclosure_decisions
|
|
7
|
+
-- creates-function: public.capture_harness_message_public_event
|
|
8
|
+
-- creates-function: public.capture_harness_artifact_public_event
|
|
9
|
+
-- creates-trigger: public.messages.trg_capture_harness_message_public_event
|
|
10
|
+
-- creates-trigger: public.message_artifacts.trg_capture_harness_artifact_public_event
|
|
11
|
+
-- Managed multiplayer Harness proof ledger. Hand-rolled because this migration
|
|
12
|
+
-- also installs admission triggers over existing canonical message tables.
|
|
13
|
+
|
|
14
|
+
CREATE TABLE IF NOT EXISTS public.harness_managed_thread_enrollments (
|
|
15
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
16
|
+
tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
|
|
17
|
+
thread_id uuid NOT NULL REFERENCES public.threads(id) ON DELETE CASCADE,
|
|
18
|
+
logical_agent_id uuid NOT NULL REFERENCES public.agents(id),
|
|
19
|
+
trust_profile text NOT NULL,
|
|
20
|
+
harness_arn text NOT NULL,
|
|
21
|
+
qualifier text NOT NULL,
|
|
22
|
+
resolved_version text NOT NULL,
|
|
23
|
+
session_strategy text NOT NULL DEFAULT 'fresh'
|
|
24
|
+
CHECK (session_strategy = 'fresh'),
|
|
25
|
+
prior_runtime text NOT NULL,
|
|
26
|
+
status text NOT NULL DEFAULT 'active'
|
|
27
|
+
CHECK (status IN ('active', 'restoring', 'restored', 'failed')),
|
|
28
|
+
enrolled_by_user_id uuid NOT NULL REFERENCES public.users(id),
|
|
29
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
30
|
+
restored_at timestamptz,
|
|
31
|
+
UNIQUE (tenant_id, thread_id)
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
CREATE UNIQUE INDEX IF NOT EXISTS uq_harness_enrollment_active_profile
|
|
35
|
+
ON public.harness_managed_thread_enrollments (tenant_id, trust_profile)
|
|
36
|
+
WHERE status = 'active';
|
|
37
|
+
|
|
38
|
+
CREATE TABLE IF NOT EXISTS public.thread_public_events (
|
|
39
|
+
id bigserial PRIMARY KEY,
|
|
40
|
+
tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
|
|
41
|
+
thread_id uuid NOT NULL REFERENCES public.threads(id) ON DELETE CASCADE,
|
|
42
|
+
source_kind text NOT NULL CHECK (source_kind IN ('message', 'message_artifact')),
|
|
43
|
+
source_id uuid NOT NULL,
|
|
44
|
+
source_version text NOT NULL,
|
|
45
|
+
event_kind text NOT NULL CHECK (event_kind IN ('insert', 'invalidate')),
|
|
46
|
+
canonical_digest text NOT NULL,
|
|
47
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
48
|
+
UNIQUE (tenant_id, thread_id, source_kind, source_id, source_version)
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
CREATE INDEX IF NOT EXISTS idx_thread_public_events_prefix
|
|
52
|
+
ON public.thread_public_events (tenant_id, thread_id, id);
|
|
53
|
+
|
|
54
|
+
CREATE TABLE IF NOT EXISTS public.harness_participant_sessions (
|
|
55
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
56
|
+
tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
|
|
57
|
+
enrollment_id uuid NOT NULL REFERENCES public.harness_managed_thread_enrollments(id) ON DELETE CASCADE,
|
|
58
|
+
thread_id uuid NOT NULL REFERENCES public.threads(id) ON DELETE CASCADE,
|
|
59
|
+
participant_user_id uuid NOT NULL REFERENCES public.users(id),
|
|
60
|
+
turn_id uuid NOT NULL REFERENCES public.thread_turns(id) ON DELETE CASCADE,
|
|
61
|
+
runtime_session_id text NOT NULL UNIQUE,
|
|
62
|
+
generation integer NOT NULL DEFAULT 1 CHECK (generation = 1),
|
|
63
|
+
captured_high_water bigint NOT NULL,
|
|
64
|
+
applied_high_water bigint,
|
|
65
|
+
qualifier text NOT NULL,
|
|
66
|
+
resolved_version text NOT NULL,
|
|
67
|
+
base_fingerprint text NOT NULL,
|
|
68
|
+
participant_fingerprint text NOT NULL,
|
|
69
|
+
state text NOT NULL DEFAULT 'allocated'
|
|
70
|
+
CHECK (state IN ('allocated', 'running', 'finalizing', 'completed', 'abandoned')),
|
|
71
|
+
failure_reason text,
|
|
72
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
73
|
+
started_at timestamptz,
|
|
74
|
+
finished_at timestamptz,
|
|
75
|
+
UNIQUE (tenant_id, turn_id),
|
|
76
|
+
CHECK (
|
|
77
|
+
(state IN ('completed', 'abandoned') AND finished_at IS NOT NULL)
|
|
78
|
+
OR (state NOT IN ('completed', 'abandoned') AND finished_at IS NULL)
|
|
79
|
+
)
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
CREATE INDEX IF NOT EXISTS idx_harness_participant_sessions_thread
|
|
83
|
+
ON public.harness_participant_sessions
|
|
84
|
+
(tenant_id, thread_id, participant_user_id, created_at);
|
|
85
|
+
|
|
86
|
+
CREATE TABLE IF NOT EXISTS public.harness_participant_session_events (
|
|
87
|
+
id bigserial PRIMARY KEY,
|
|
88
|
+
tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
|
|
89
|
+
session_id uuid NOT NULL REFERENCES public.harness_participant_sessions(id) ON DELETE CASCADE,
|
|
90
|
+
turn_id uuid NOT NULL REFERENCES public.thread_turns(id) ON DELETE CASCADE,
|
|
91
|
+
event_type text NOT NULL,
|
|
92
|
+
from_state text,
|
|
93
|
+
to_state text NOT NULL
|
|
94
|
+
CHECK (to_state IN ('allocated', 'running', 'finalizing', 'completed', 'abandoned')),
|
|
95
|
+
reason_code text,
|
|
96
|
+
applied_high_water bigint,
|
|
97
|
+
evidence jsonb,
|
|
98
|
+
created_at timestamptz NOT NULL DEFAULT now()
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
CREATE INDEX IF NOT EXISTS idx_harness_session_events_session
|
|
102
|
+
ON public.harness_participant_session_events (session_id, id);
|
|
103
|
+
|
|
104
|
+
CREATE TABLE IF NOT EXISTS public.harness_governed_tool_executions (
|
|
105
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
106
|
+
tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
|
|
107
|
+
turn_id uuid NOT NULL REFERENCES public.thread_turns(id) ON DELETE CASCADE,
|
|
108
|
+
participant_user_id uuid NOT NULL REFERENCES public.users(id),
|
|
109
|
+
session_id uuid NOT NULL REFERENCES public.harness_participant_sessions(id) ON DELETE CASCADE,
|
|
110
|
+
idempotency_key text NOT NULL,
|
|
111
|
+
audience text NOT NULL,
|
|
112
|
+
operation text NOT NULL,
|
|
113
|
+
tool_use_id text NOT NULL,
|
|
114
|
+
input_digest text NOT NULL,
|
|
115
|
+
state text NOT NULL DEFAULT 'claimed'
|
|
116
|
+
CHECK (state IN ('claimed', 'completed', 'failed', 'ambiguous')),
|
|
117
|
+
policy_decision_id text,
|
|
118
|
+
credential_owner_alias text,
|
|
119
|
+
sanitized_result jsonb,
|
|
120
|
+
failure_reason text,
|
|
121
|
+
claimed_at timestamptz NOT NULL DEFAULT now(),
|
|
122
|
+
completed_at timestamptz,
|
|
123
|
+
UNIQUE (tenant_id, idempotency_key)
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
CREATE INDEX IF NOT EXISTS idx_harness_governed_tool_turn
|
|
127
|
+
ON public.harness_governed_tool_executions (turn_id);
|
|
128
|
+
|
|
129
|
+
CREATE TABLE IF NOT EXISTS public.harness_disclosure_decisions (
|
|
130
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
131
|
+
tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
|
|
132
|
+
participant_user_id uuid NOT NULL REFERENCES public.users(id),
|
|
133
|
+
thread_id uuid NOT NULL REFERENCES public.threads(id) ON DELETE CASCADE,
|
|
134
|
+
turn_id uuid NOT NULL REFERENCES public.thread_turns(id) ON DELETE CASCADE,
|
|
135
|
+
session_id uuid NOT NULL REFERENCES public.harness_participant_sessions(id) ON DELETE CASCADE,
|
|
136
|
+
operation text NOT NULL,
|
|
137
|
+
projection_digest text NOT NULL,
|
|
138
|
+
status text NOT NULL
|
|
139
|
+
CHECK (status IN ('published', 'withheld', 'confirmation_required')),
|
|
140
|
+
reason_code text NOT NULL,
|
|
141
|
+
expires_at timestamptz NOT NULL,
|
|
142
|
+
created_at timestamptz NOT NULL DEFAULT now()
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
CREATE INDEX IF NOT EXISTS idx_harness_disclosure_turn
|
|
146
|
+
ON public.harness_disclosure_decisions (turn_id);
|
|
147
|
+
|
|
148
|
+
CREATE OR REPLACE FUNCTION public.capture_harness_message_public_event()
|
|
149
|
+
RETURNS trigger
|
|
150
|
+
LANGUAGE plpgsql
|
|
151
|
+
AS $$
|
|
152
|
+
DECLARE
|
|
153
|
+
digest_value text;
|
|
154
|
+
version_value text;
|
|
155
|
+
event_value text;
|
|
156
|
+
admitted_before boolean;
|
|
157
|
+
admitted_now boolean;
|
|
158
|
+
BEGIN
|
|
159
|
+
IF TG_OP = 'DELETE' THEN
|
|
160
|
+
IF NOT EXISTS (
|
|
161
|
+
SELECT 1 FROM public.thread_public_events e
|
|
162
|
+
WHERE e.tenant_id = OLD.tenant_id
|
|
163
|
+
AND e.thread_id = OLD.thread_id
|
|
164
|
+
AND e.source_kind = 'message'
|
|
165
|
+
AND e.source_id = OLD.id
|
|
166
|
+
) THEN
|
|
167
|
+
RETURN OLD;
|
|
168
|
+
END IF;
|
|
169
|
+
digest_value := encode(digest(concat_ws('|', OLD.role, coalesce(OLD.content, ''), coalesce(OLD.parts::text, ''), coalesce(OLD.metadata::text, '')), 'sha256'), 'hex');
|
|
170
|
+
version_value := 'delete:' || digest_value;
|
|
171
|
+
event_value := 'invalidate';
|
|
172
|
+
INSERT INTO public.thread_public_events (
|
|
173
|
+
tenant_id, thread_id, source_kind, source_id, source_version,
|
|
174
|
+
event_kind, canonical_digest
|
|
175
|
+
) VALUES (
|
|
176
|
+
OLD.tenant_id, OLD.thread_id, 'message', OLD.id,
|
|
177
|
+
version_value, event_value, digest_value
|
|
178
|
+
) ON CONFLICT DO NOTHING;
|
|
179
|
+
RETURN OLD;
|
|
180
|
+
END IF;
|
|
181
|
+
|
|
182
|
+
admitted_now := NEW.role IN ('user', 'assistant')
|
|
183
|
+
AND coalesce(NEW.metadata->>'visibility', 'public') = 'public'
|
|
184
|
+
AND coalesce(NEW.metadata->>'disclosure_status', 'published') NOT IN ('withheld', 'confirmation_required')
|
|
185
|
+
AND EXISTS (
|
|
186
|
+
SELECT 1 FROM public.harness_managed_thread_enrollments e
|
|
187
|
+
WHERE e.tenant_id = NEW.tenant_id
|
|
188
|
+
AND e.thread_id = NEW.thread_id
|
|
189
|
+
AND e.status = 'active'
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
IF TG_OP = 'UPDATE' THEN
|
|
193
|
+
admitted_before := EXISTS (
|
|
194
|
+
SELECT 1 FROM public.thread_public_events e
|
|
195
|
+
WHERE e.tenant_id = OLD.tenant_id
|
|
196
|
+
AND e.thread_id = OLD.thread_id
|
|
197
|
+
AND e.source_kind = 'message'
|
|
198
|
+
AND e.source_id = OLD.id
|
|
199
|
+
);
|
|
200
|
+
IF admitted_before THEN
|
|
201
|
+
digest_value := encode(digest(concat_ws('|', OLD.role, coalesce(OLD.content, ''), coalesce(OLD.parts::text, ''), coalesce(OLD.metadata::text, '')), 'sha256'), 'hex');
|
|
202
|
+
version_value := 'invalidate:update:' || encode(digest(concat_ws('|', NEW.role, coalesce(NEW.content, ''), coalesce(NEW.parts::text, ''), coalesce(NEW.metadata::text, '')), 'sha256'), 'hex');
|
|
203
|
+
INSERT INTO public.thread_public_events (
|
|
204
|
+
tenant_id, thread_id, source_kind, source_id, source_version,
|
|
205
|
+
event_kind, canonical_digest
|
|
206
|
+
) VALUES (
|
|
207
|
+
OLD.tenant_id, OLD.thread_id, 'message', OLD.id,
|
|
208
|
+
version_value, 'invalidate', digest_value
|
|
209
|
+
) ON CONFLICT DO NOTHING;
|
|
210
|
+
END IF;
|
|
211
|
+
END IF;
|
|
212
|
+
|
|
213
|
+
IF NOT admitted_now THEN
|
|
214
|
+
RETURN NEW;
|
|
215
|
+
END IF;
|
|
216
|
+
|
|
217
|
+
digest_value := encode(digest(concat_ws('|', NEW.role, coalesce(NEW.content, ''), coalesce(NEW.parts::text, '')), 'sha256'), 'hex');
|
|
218
|
+
version_value := lower(TG_OP) || ':' || digest_value || ':' || encode(digest(coalesce(NEW.metadata::text, ''), 'sha256'), 'hex');
|
|
219
|
+
INSERT INTO public.thread_public_events (
|
|
220
|
+
tenant_id, thread_id, source_kind, source_id, source_version,
|
|
221
|
+
event_kind, canonical_digest
|
|
222
|
+
) VALUES (
|
|
223
|
+
NEW.tenant_id, NEW.thread_id, 'message', NEW.id,
|
|
224
|
+
version_value, 'insert', digest_value
|
|
225
|
+
) ON CONFLICT DO NOTHING;
|
|
226
|
+
RETURN NEW;
|
|
227
|
+
END;
|
|
228
|
+
$$;
|
|
229
|
+
|
|
230
|
+
DROP TRIGGER IF EXISTS trg_capture_harness_message_public_event ON public.messages;
|
|
231
|
+
CREATE TRIGGER trg_capture_harness_message_public_event
|
|
232
|
+
AFTER INSERT OR UPDATE OR DELETE ON public.messages
|
|
233
|
+
FOR EACH ROW EXECUTE FUNCTION public.capture_harness_message_public_event();
|
|
234
|
+
|
|
235
|
+
CREATE OR REPLACE FUNCTION public.capture_harness_artifact_public_event()
|
|
236
|
+
RETURNS trigger
|
|
237
|
+
LANGUAGE plpgsql
|
|
238
|
+
AS $$
|
|
239
|
+
DECLARE
|
|
240
|
+
digest_value text;
|
|
241
|
+
version_value text;
|
|
242
|
+
admitted_before boolean;
|
|
243
|
+
admitted_now boolean;
|
|
244
|
+
BEGIN
|
|
245
|
+
IF TG_OP = 'DELETE' THEN
|
|
246
|
+
IF NOT EXISTS (
|
|
247
|
+
SELECT 1 FROM public.thread_public_events e
|
|
248
|
+
WHERE e.tenant_id = OLD.tenant_id
|
|
249
|
+
AND e.thread_id = OLD.thread_id
|
|
250
|
+
AND e.source_kind = 'message_artifact'
|
|
251
|
+
AND e.source_id = OLD.id
|
|
252
|
+
) THEN
|
|
253
|
+
RETURN OLD;
|
|
254
|
+
END IF;
|
|
255
|
+
digest_value := encode(digest(concat_ws('|', OLD.artifact_type, coalesce(OLD.name, ''), coalesce(OLD.artifact_id::text, ''), coalesce(OLD.metadata::text, '')), 'sha256'), 'hex');
|
|
256
|
+
INSERT INTO public.thread_public_events (
|
|
257
|
+
tenant_id, thread_id, source_kind, source_id, source_version,
|
|
258
|
+
event_kind, canonical_digest
|
|
259
|
+
) VALUES (
|
|
260
|
+
OLD.tenant_id, OLD.thread_id, 'message_artifact', OLD.id,
|
|
261
|
+
'delete:' || digest_value, 'invalidate', digest_value
|
|
262
|
+
) ON CONFLICT DO NOTHING;
|
|
263
|
+
RETURN OLD;
|
|
264
|
+
END IF;
|
|
265
|
+
|
|
266
|
+
admitted_now := EXISTS (
|
|
267
|
+
SELECT 1 FROM public.harness_managed_thread_enrollments e
|
|
268
|
+
WHERE e.tenant_id = NEW.tenant_id
|
|
269
|
+
AND e.thread_id = NEW.thread_id
|
|
270
|
+
AND e.status = 'active'
|
|
271
|
+
) AND coalesce(NEW.metadata->>'access_state', 'public') = 'public';
|
|
272
|
+
|
|
273
|
+
IF TG_OP = 'UPDATE' THEN
|
|
274
|
+
admitted_before := EXISTS (
|
|
275
|
+
SELECT 1 FROM public.thread_public_events e
|
|
276
|
+
WHERE e.tenant_id = OLD.tenant_id
|
|
277
|
+
AND e.thread_id = OLD.thread_id
|
|
278
|
+
AND e.source_kind = 'message_artifact'
|
|
279
|
+
AND e.source_id = OLD.id
|
|
280
|
+
);
|
|
281
|
+
IF admitted_before THEN
|
|
282
|
+
digest_value := encode(digest(concat_ws('|', OLD.artifact_type, coalesce(OLD.name, ''), coalesce(OLD.artifact_id::text, ''), coalesce(OLD.metadata::text, '')), 'sha256'), 'hex');
|
|
283
|
+
version_value := 'invalidate:update:' || encode(digest(concat_ws('|', NEW.artifact_type, coalesce(NEW.name, ''), coalesce(NEW.artifact_id::text, ''), coalesce(NEW.metadata::text, '')), 'sha256'), 'hex');
|
|
284
|
+
INSERT INTO public.thread_public_events (
|
|
285
|
+
tenant_id, thread_id, source_kind, source_id, source_version,
|
|
286
|
+
event_kind, canonical_digest
|
|
287
|
+
) VALUES (
|
|
288
|
+
OLD.tenant_id, OLD.thread_id, 'message_artifact', OLD.id,
|
|
289
|
+
version_value, 'invalidate', digest_value
|
|
290
|
+
) ON CONFLICT DO NOTHING;
|
|
291
|
+
END IF;
|
|
292
|
+
END IF;
|
|
293
|
+
|
|
294
|
+
IF NOT admitted_now THEN
|
|
295
|
+
RETURN NEW;
|
|
296
|
+
END IF;
|
|
297
|
+
|
|
298
|
+
digest_value := encode(digest(concat_ws('|', NEW.artifact_type, coalesce(NEW.name, ''), coalesce(NEW.artifact_id::text, ''), coalesce(NEW.metadata::text, '')), 'sha256'), 'hex');
|
|
299
|
+
INSERT INTO public.thread_public_events (
|
|
300
|
+
tenant_id, thread_id, source_kind, source_id, source_version,
|
|
301
|
+
event_kind, canonical_digest
|
|
302
|
+
) VALUES (
|
|
303
|
+
NEW.tenant_id, NEW.thread_id, 'message_artifact', NEW.id,
|
|
304
|
+
lower(TG_OP) || ':' || digest_value, 'insert', digest_value
|
|
305
|
+
) ON CONFLICT DO NOTHING;
|
|
306
|
+
RETURN NEW;
|
|
307
|
+
END;
|
|
308
|
+
$$;
|
|
309
|
+
|
|
310
|
+
DROP TRIGGER IF EXISTS trg_capture_harness_artifact_public_event ON public.message_artifacts;
|
|
311
|
+
CREATE TRIGGER trg_capture_harness_artifact_public_event
|
|
312
|
+
AFTER INSERT OR UPDATE OR DELETE ON public.message_artifacts
|
|
313
|
+
FOR EACH ROW EXECUTE FUNCTION public.capture_harness_artifact_public_event();
|