Unified · Split
| @@ -1,5 +1,26 @@ | ||
| 1 | 1 | import type { Id } from "@executor/database/convex/_generated/dataModel"; |
| 2 | 2 | import type { |
| 3 | + ApprovalStatus as CoreApprovalStatus, | |
| 4 | + ArgumentConditionOperator as CoreArgumentConditionOperator, | |
| 5 | + CredentialProvider as CoreCredentialProvider, | |
| 6 | + CredentialScope as CoreCredentialScope, | |
| 7 | + CredentialScopeType as CoreCredentialScopeType, | |
| 8 | + PolicyApprovalMode as CorePolicyApprovalMode, | |
| 9 | + PolicyDecision as CorePolicyDecision, | |
| 10 | + PolicyEffect as CorePolicyEffect, | |
| 11 | + PolicyMatchType as CorePolicyMatchType, | |
| 12 | + PolicyScopeType as CorePolicyScopeType, | |
| 13 | + SourceAuthType as CoreSourceAuthType, | |
| 14 | + StorageDurability as CoreStorageDurability, | |
| 15 | + StorageInstanceStatus as CoreStorageInstanceStatus, | |
| 16 | + StorageProvider as CoreStorageProvider, | |
| 17 | + StorageScopeType as CoreStorageScopeType, | |
| 18 | + TaskStatus as CoreTaskStatus, | |
| 19 | + ToolApprovalMode as CoreToolApprovalMode, | |
| 20 | + ToolRoleBindingStatus as CoreToolRoleBindingStatus, | |
| 21 | + ToolRoleSelectorType as CoreToolRoleSelectorType, | |
| 22 | + ToolSourceScopeType as CoreToolSourceScopeType, | |
| 23 | + ToolSourceType as CoreToolSourceType, | |
| 3 | 24 | ToolPolicyRecord as CoreToolPolicyRecord, |
| 4 | 25 | ToolPolicyAssignmentRecord as CoreToolPolicyAssignmentRecord, |
| 5 | 26 | ToolPolicySetRecord as CoreToolPolicySetRecord, |
| @@ -8,34 +29,34 @@ import type { · 2 unmodified lines | ||
| 8 | 29 | |
| 9 | 30 | // ── Shared types (inlined from @executor/contracts) ────────────────────────── |
| 10 | 31 | |
| 11 | −export type TaskStatus = "queued" | "running" | "completed" | "failed" | "timed_out" | "denied"; | |
| 12 | −export type ApprovalStatus = "pending" | "approved" | "denied"; | |
| 13 | −export type PolicyDecision = "allow" | "require_approval" | "deny"; | |
| 14 | −export type PolicyScopeType = "account" | "organization" | "workspace"; | |
| 15 | −export type PolicyMatchType = "glob" | "exact"; | |
| 16 | −export type PolicyEffect = "allow" | "deny"; | |
| 17 | −export type PolicyApprovalMode = "inherit" | "auto" | "required"; | |
| 18 | −export type ToolRoleSelectorType = "all" | "source" | "namespace" | "tool_path"; | |
| 19 | −export type ToolRoleBindingStatus = "active" | "disabled"; | |
| 20 | −export type ArgumentConditionOperator = "equals" | "contains" | "starts_with" | "not_equals"; | |
| 32 | +export type TaskStatus = CoreTaskStatus; | |
| 33 | +export type ApprovalStatus = CoreApprovalStatus; | |
| 34 | +export type PolicyDecision = CorePolicyDecision; | |
| 35 | +export type PolicyScopeType = CorePolicyScopeType; | |
| 36 | +export type PolicyMatchType = CorePolicyMatchType; | |
| 37 | +export type PolicyEffect = CorePolicyEffect; | |
| 38 | +export type PolicyApprovalMode = CorePolicyApprovalMode; | |
| 39 | +export type ToolRoleSelectorType = CoreToolRoleSelectorType; | |
| 40 | +export type ToolRoleBindingStatus = CoreToolRoleBindingStatus; | |
| 41 | +export type ArgumentConditionOperator = CoreArgumentConditionOperator; | |
| 21 | 42 | |
| 22 | 43 | export interface ArgumentCondition { |
| 23 | 44 | key: string; |
| 24 | 45 | operator: ArgumentConditionOperator; |
| 25 | 46 | value: string; |
| 26 | 47 | } |
| 27 | −export type CredentialScope = "account" | "organization" | "workspace"; | |
| 28 | −export type CredentialProvider = "local-convex" | "workos-vault"; | |
| 29 | −export type ToolSourceScopeType = "organization" | "workspace"; | |
| 30 | −export type CredentialScopeType = "account" | "organization" | "workspace"; | |
| 31 | −export type ToolApprovalMode = "auto" | "required"; | |
| 32 | −export type ToolSourceType = "mcp" | "openapi" | "graphql"; | |
| 33 | −export type StorageScopeType = "scratch" | "account" | "workspace" | "organization"; | |
| 34 | −export type StorageDurability = "ephemeral" | "durable"; | |
| 35 | −export type StorageInstanceStatus = "active" | "closed" | "deleted"; | |
| 36 | −export type StorageProvider = "agentfs-local" | "agentfs-cloudflare"; | |
| 37 | − | |
| 38 | −export type SourceAuthType = "none" | "bearer" | "apiKey" | "basic" | "mixed"; | |
| 48 | +export type CredentialScope = CoreCredentialScope; | |
| 49 | +export type CredentialProvider = CoreCredentialProvider; | |
| 50 | +export type ToolSourceScopeType = CoreToolSourceScopeType; | |
| 51 | +export type CredentialScopeType = CoreCredentialScopeType; | |
| 52 | +export type ToolApprovalMode = CoreToolApprovalMode; | |
| 53 | +export type ToolSourceType = CoreToolSourceType; | |
| 54 | +export type StorageScopeType = CoreStorageScopeType; | |
| 55 | +export type StorageDurability = CoreStorageDurability; | |
| 56 | +export type StorageInstanceStatus = CoreStorageInstanceStatus; | |
| 57 | +export type StorageProvider = CoreStorageProvider; | |
| 58 | + | |
| 59 | +export type SourceAuthType = CoreSourceAuthType; | |
| 39 | 60 | |
| 40 | 61 | export interface SourceAuthProfile { |
| 41 | 62 | type: SourceAuthType; |
| @@ -2,29 +2,103 @@ · 1 unmodified line | ||
| 2 | 2 | |
| 3 | 3 | import type { Id } from "../../database/convex/_generated/dataModel.d.ts"; |
| 4 | 4 | |
| 5 | −export type TaskStatus = "queued" | "running" | "completed" | "failed" | "timed_out" | "denied"; | |
| 6 | −export type ApprovalStatus = "pending" | "approved" | "denied"; | |
| 7 | −export type ToolCallStatus = "requested" | "pending_approval" | "completed" | "failed" | "denied"; | |
| 5 | +export const ACCOUNT_PROVIDERS = ["workos", "anonymous"] as const; | |
| 6 | +export type AccountProvider = (typeof ACCOUNT_PROVIDERS)[number]; | |
| 7 | + | |
| 8 | +export const ACCOUNT_STATUSES = ["active", "deleted"] as const; | |
| 9 | +export type AccountStatus = (typeof ACCOUNT_STATUSES)[number]; | |
| 10 | + | |
| 11 | +export const ORGANIZATION_STATUSES = ["active", "deleted"] as const; | |
| 12 | +export type OrganizationStatus = (typeof ORGANIZATION_STATUSES)[number]; | |
| 13 | + | |
| 14 | +export const ORGANIZATION_ROLES = ["owner", "admin", "member", "billing_admin"] as const; | |
| 15 | +export type OrganizationRole = (typeof ORGANIZATION_ROLES)[number]; | |
| 16 | + | |
| 17 | +export const ORGANIZATION_MEMBER_STATUSES = ["active", "pending", "removed"] as const; | |
| 18 | +export type OrganizationMemberStatus = (typeof ORGANIZATION_MEMBER_STATUSES)[number]; | |
| 19 | + | |
| 20 | +export const BILLING_SUBSCRIPTION_STATUSES = [ | |
| 21 | + "incomplete", | |
| 22 | + "incomplete_expired", | |
| 23 | + "trialing", | |
| 24 | + "active", | |
| 25 | + "past_due", | |
| 26 | + "canceled", | |
| 27 | + "unpaid", | |
| 28 | + "paused", | |
| 29 | +] as const; | |
| 30 | +export type BillingSubscriptionStatus = (typeof BILLING_SUBSCRIPTION_STATUSES)[number]; | |
| 31 | + | |
| 32 | +export const INVITE_STATUSES = ["pending", "accepted", "expired", "revoked", "failed"] as const; | |
| 33 | +export type InviteStatus = (typeof INVITE_STATUSES)[number]; | |
| 34 | + | |
| 35 | +export const TASK_STATUSES = ["queued", "running", "completed", "failed", "timed_out", "denied"] as const; | |
| 36 | +export type TaskStatus = (typeof TASK_STATUSES)[number]; | |
| 37 | + | |
| 38 | +export const COMPLETED_TASK_STATUSES = ["completed", "failed", "timed_out", "denied"] as const; | |
| 39 | +export type CompletedTaskStatus = (typeof COMPLETED_TASK_STATUSES)[number]; | |
| 40 | + | |
| 41 | +export const APPROVAL_STATUSES = ["pending", "approved", "denied"] as const; | |
| 42 | +export type ApprovalStatus = (typeof APPROVAL_STATUSES)[number]; | |
| 43 | + | |
| 44 | +export const TOOL_CALL_STATUSES = ["requested", "pending_approval", "completed", "failed", "denied"] as const; | |
| 45 | +export type ToolCallStatus = (typeof TOOL_CALL_STATUSES)[number]; | |
| 46 | + | |
| 47 | +export const TERMINAL_TOOL_CALL_STATUSES = ["completed", "failed", "denied"] as const; | |
| 48 | +export type TerminalToolCallStatus = (typeof TERMINAL_TOOL_CALL_STATUSES)[number]; | |
| 49 | + | |
| 8 | 50 | export type PolicyDecision = "allow" | "require_approval" | "deny"; |
| 9 | −export type PolicyScopeType = "account" | "organization" | "workspace"; | |
| 10 | −export type PolicyMatchType = "glob" | "exact"; | |
| 11 | −export type PolicyEffect = "allow" | "deny"; | |
| 12 | −export type PolicyApprovalMode = "inherit" | "auto" | "required"; | |
| 13 | −export type PolicyResourceType = "all_tools" | "source" | "namespace" | "tool_path"; | |
| 14 | −export type ToolSourceScopeType = "organization" | "workspace"; | |
| 15 | −export type CredentialScopeType = "account" | "organization" | "workspace"; | |
| 51 | + | |
| 52 | +export const POLICY_SCOPE_TYPES = ["account", "organization", "workspace"] as const; | |
| 53 | +export type PolicyScopeType = (typeof POLICY_SCOPE_TYPES)[number]; | |
| 54 | + | |
| 55 | +export const POLICY_MATCH_TYPES = ["glob", "exact"] as const; | |
| 56 | +export type PolicyMatchType = (typeof POLICY_MATCH_TYPES)[number]; | |
| 57 | + | |
| 58 | +export const POLICY_EFFECTS = ["allow", "deny"] as const; | |
| 59 | +export type PolicyEffect = (typeof POLICY_EFFECTS)[number]; | |
| 60 | + | |
| 61 | +export const POLICY_APPROVAL_MODES = ["inherit", "auto", "required"] as const; | |
| 62 | +export type PolicyApprovalMode = (typeof POLICY_APPROVAL_MODES)[number]; | |
| 63 | + | |
| 64 | +export const POLICY_RESOURCE_TYPES = ["all_tools", "source", "namespace", "tool_path"] as const; | |
| 65 | +export type PolicyResourceType = (typeof POLICY_RESOURCE_TYPES)[number]; | |
| 66 | + | |
| 67 | +export const TOOL_SOURCE_SCOPE_TYPES = ["organization", "workspace"] as const; | |
| 68 | +export type ToolSourceScopeType = (typeof TOOL_SOURCE_SCOPE_TYPES)[number]; | |
| 69 | + | |
| 70 | +export const CREDENTIAL_SCOPE_TYPES = ["account", "organization", "workspace"] as const; | |
| 71 | +export type CredentialScopeType = (typeof CREDENTIAL_SCOPE_TYPES)[number]; | |
| 16 | 72 | export type CredentialScope = CredentialScopeType; |
| 17 | −export type CredentialProvider = "local-convex" | "workos-vault"; | |
| 18 | −export type ToolApprovalMode = "auto" | "required"; | |
| 19 | −export type ToolSourceType = "mcp" | "openapi" | "graphql"; | |
| 20 | −export type StorageScopeType = "scratch" | "account" | "workspace" | "organization"; | |
| 21 | −export type StorageDurability = "ephemeral" | "durable"; | |
| 22 | −export type StorageInstanceStatus = "active" | "closed" | "deleted"; | |
| 23 | −export type StorageProvider = "agentfs-local" | "agentfs-cloudflare"; | |
| 73 | + | |
| 74 | +export const CREDENTIAL_PROVIDERS = ["local-convex", "workos-vault"] as const; | |
| 75 | +export type CredentialProvider = (typeof CREDENTIAL_PROVIDERS)[number]; | |
| 76 | + | |
| 77 | +export const TOOL_APPROVAL_MODES = ["auto", "required"] as const; | |
| 78 | +export type ToolApprovalMode = (typeof TOOL_APPROVAL_MODES)[number]; | |
| 79 | + | |
| 80 | +export const TOOL_SOURCE_TYPES = ["mcp", "openapi", "graphql"] as const; | |
| 81 | +export type ToolSourceType = (typeof TOOL_SOURCE_TYPES)[number]; | |
| 82 | + | |
| 83 | +export const STORAGE_SCOPE_TYPES = ["scratch", "account", "workspace", "organization"] as const; | |
| 84 | +export type StorageScopeType = (typeof STORAGE_SCOPE_TYPES)[number]; | |
| 85 | + | |
| 86 | +export const STORAGE_DURABILITIES = ["ephemeral", "durable"] as const; | |
| 87 | +export type StorageDurability = (typeof STORAGE_DURABILITIES)[number]; | |
| 88 | + | |
| 89 | +export const STORAGE_INSTANCE_STATUSES = ["active", "closed", "deleted"] as const; | |
| 90 | +export type StorageInstanceStatus = (typeof STORAGE_INSTANCE_STATUSES)[number]; | |
| 91 | + | |
| 92 | +export const STORAGE_PROVIDERS = ["agentfs-local", "agentfs-cloudflare"] as const; | |
| 93 | +export type StorageProvider = (typeof STORAGE_PROVIDERS)[number]; | |
| 94 | + | |
| 95 | +export const STORAGE_ACCESS_TYPES = ["opened", "provided", "accessed"] as const; | |
| 96 | +export type StorageAccessType = (typeof STORAGE_ACCESS_TYPES)[number]; | |
| 24 | 97 | |
| 25 | 98 | export type JsonSchema = Record<string, unknown>; |
| 26 | 99 | |
| 27 | −export type SourceAuthType = "none" | "bearer" | "apiKey" | "basic" | "mixed"; | |
| 100 | +export const SOURCE_AUTH_TYPES = ["none", "bearer", "apiKey", "basic", "mixed"] as const; | |
| 101 | +export type SourceAuthType = (typeof SOURCE_AUTH_TYPES)[number]; | |
| 28 | 102 | |
| 29 | 103 | export interface SourceAuthProfile { |
| 30 | 104 | type: SourceAuthType; |
| @@ -96,7 +170,8 @@ export interface ToolCallRecord { · 65 unmodified lines | ||
| 96 | 170 | completedAt?: number; |
| 97 | 171 | } |
| 98 | 172 | |
| 99 | −export type ArgumentConditionOperator = "equals" | "contains" | "starts_with" | "not_equals"; | |
| 173 | +export const ARGUMENT_CONDITION_OPERATORS = ["equals", "contains", "starts_with", "not_equals"] as const; | |
| 174 | +export type ArgumentConditionOperator = (typeof ARGUMENT_CONDITION_OPERATORS)[number]; | |
| 100 | 175 | |
| 101 | 176 | export interface ArgumentCondition { |
| 102 | 177 | key: string; |
| @@ -125,7 +200,11 @@ export interface ToolPolicyRecord { · 22 unmodified lines | ||
| 125 | 200 | updatedAt: number; |
| 126 | 201 | } |
| 127 | 202 | |
| 128 | −export type ToolRoleSelectorType = "all" | "source" | "namespace" | "tool_path"; | |
| 203 | +export const TOOL_ROLE_SELECTOR_TYPES = ["all", "source", "namespace", "tool_path"] as const; | |
| 204 | +export type ToolRoleSelectorType = (typeof TOOL_ROLE_SELECTOR_TYPES)[number]; | |
| 205 | + | |
| 206 | +export const TOOL_ROLE_BINDING_STATUSES = ["active", "disabled"] as const; | |
| 207 | +export type ToolRoleBindingStatus = (typeof TOOL_ROLE_BINDING_STATUSES)[number]; | |
| 129 | 208 | |
| 130 | 209 | export interface ToolPolicySetRecord { |
| 131 | 210 | id: string; |
| @@ -162,7 +241,7 @@ export interface ToolPolicyAssignmentRecord { · 30 unmodified lines | ||
| 162 | 241 | workspaceId?: Id<"workspaces">; |
| 163 | 242 | targetAccountId?: Id<"accounts">; |
| 164 | 243 | clientId?: string; |
| 165 | − status: "active" | "disabled"; | |
| 244 | + status: ToolRoleBindingStatus; | |
| 166 | 245 | expiresAt?: number; |
| 167 | 246 | createdAt: number; |
| 168 | 247 | updatedAt: number; |
| @@ -315,7 +394,8 @@ export interface SandboxRuntime { · 146 unmodified lines | ||
| 315 | 394 | ): Promise<SandboxExecutionResult>; |
| 316 | 395 | } |
| 317 | 396 | |
| 318 | −export type ToolCredentialAuthType = "bearer" | "apiKey" | "basic"; | |
| 397 | +export const TOOL_CREDENTIAL_AUTH_TYPES = ["bearer", "apiKey", "basic"] as const; | |
| 398 | +export type ToolCredentialAuthType = (typeof TOOL_CREDENTIAL_AUTH_TYPES)[number]; | |
| 319 | 399 | |
| 320 | 400 | export interface ToolCredentialSpec { |
| 321 | 401 | sourceKey: string; |
| @@ -1,5 +1,34 @@ | ||
| 1 | 1 | import { defineSchema, defineTable } from "convex/server"; |
| 2 | 2 | import { v } from "convex/values"; |
| 3 | +import { | |
| 4 | + argumentConditionValidator, | |
| 5 | + accountProviderValidator, | |
| 6 | + accountStatusValidator, | |
| 7 | + approvalStatusValidator, | |
| 8 | + billingSubscriptionStatusValidator, | |
| 9 | + credentialProviderValidator, | |
| 10 | + credentialScopeTypeValidator, | |
| 11 | + inviteStatusValidator, | |
| 12 | + jsonObjectValidator, | |
| 13 | + orgMemberStatusValidator, | |
| 14 | + organizationStatusValidator, | |
| 15 | + orgRoleValidator, | |
| 16 | + policyApprovalModeValidator, | |
| 17 | + policyEffectValidator, | |
| 18 | + policyMatchTypeValidator, | |
| 19 | + policyScopeTypeValidator, | |
| 20 | + storageDurabilityValidator, | |
| 21 | + storageInstanceStatusValidator, | |
| 22 | + storageProviderValidator, | |
| 23 | + storageScopeTypeValidator, | |
| 24 | + taskStatusValidator, | |
| 25 | + toolApprovalModeValidator, | |
| 26 | + toolCallStatusValidator, | |
| 27 | + toolRoleBindingStatusValidator, | |
| 28 | + toolRoleSelectorTypeValidator, | |
| 29 | + toolSourceScopeTypeValidator, | |
| 30 | + toolSourceTypeValidator, | |
| 31 | +} from "../src/database/validators"; | |
| 3 | 32 | |
| 4 | 33 | // Convex database schema. |
| 5 | 34 | // |
| @@ -10,87 +39,20 @@ import { v } from "convex/values"; · 4 unmodified lines | ||
| 10 | 39 | // systems and in logs; `_id` stays internal to Convex. |
| 11 | 40 | // - `accountId` links rows to `accounts` where identity context is needed. |
| 12 | 41 | // |
| 13 | −// The small validators below act like enums for schema fields. | |
| 14 | −// Note: Some of these are duplicated as request validators under `executor/packages/database/convex/database/validators.ts` | |
| 15 | −// and in a few feature modules. Keep the literal sets aligned to avoid drift. | |
| 16 | − | |
| 17 | −const accountProvider = v.union(v.literal("workos"), v.literal("anonymous")); | |
| 18 | −const accountStatus = v.union(v.literal("active"), v.literal("deleted")); | |
| 19 | −const organizationStatus = v.union(v.literal("active"), v.literal("deleted")); | |
| 20 | −const orgRole = v.union(v.literal("owner"), v.literal("admin"), v.literal("member"), v.literal("billing_admin")); | |
| 21 | −const orgMemberStatus = v.union(v.literal("active"), v.literal("pending"), v.literal("removed")); | |
| 22 | −const billingSubscriptionStatus = v.union( | |
| 23 | − v.literal("incomplete"), | |
| 24 | − v.literal("incomplete_expired"), | |
| 25 | − v.literal("trialing"), | |
| 26 | − v.literal("active"), | |
| 27 | − v.literal("past_due"), | |
| 28 | − v.literal("canceled"), | |
| 29 | − v.literal("unpaid"), | |
| 30 | − v.literal("paused"), | |
| 31 | −); | |
| 32 | −const inviteStatus = v.union( | |
| 33 | − v.literal("pending"), | |
| 34 | − v.literal("accepted"), | |
| 35 | − v.literal("expired"), | |
| 36 | − v.literal("revoked"), | |
| 37 | − v.literal("failed"), | |
| 38 | −); | |
| 39 | −const taskStatus = v.union( | |
| 40 | − v.literal("queued"), | |
| 41 | − v.literal("running"), | |
| 42 | − v.literal("completed"), | |
| 43 | − v.literal("failed"), | |
| 44 | − v.literal("timed_out"), | |
| 45 | − v.literal("denied"), | |
| 46 | −); | |
| 47 | −const approvalStatus = v.union(v.literal("pending"), v.literal("approved"), v.literal("denied")); | |
| 48 | −const toolCallStatus = v.union( | |
| 49 | − v.literal("requested"), | |
| 50 | − v.literal("pending_approval"), | |
| 51 | − v.literal("completed"), | |
| 52 | − v.literal("failed"), | |
| 53 | − v.literal("denied"), | |
| 54 | −); | |
| 55 | −const toolApprovalMode = v.union(v.literal("auto"), v.literal("required")); | |
| 56 | −const policyScopeType = v.union(v.literal("account"), v.literal("organization"), v.literal("workspace")); | |
| 57 | −const policyMatchType = v.union(v.literal("glob"), v.literal("exact")); | |
| 58 | −const policyEffect = v.union(v.literal("allow"), v.literal("deny")); | |
| 59 | −const policyApprovalMode = v.union(v.literal("inherit"), v.literal("auto"), v.literal("required")); | |
| 60 | −const toolRoleSelectorType = v.union( | |
| 61 | − v.literal("all"), | |
| 62 | − v.literal("source"), | |
| 63 | − v.literal("namespace"), | |
| 64 | − v.literal("tool_path"), | |
| 65 | −); | |
| 66 | −const toolRoleBindingStatus = v.union(v.literal("active"), v.literal("disabled")); | |
| 67 | −const toolSourceScopeType = v.union(v.literal("organization"), v.literal("workspace")); | |
| 68 | −const credentialScopeType = v.union(v.literal("account"), v.literal("organization"), v.literal("workspace")); | |
| 69 | −const storageScopeType = v.union(v.literal("scratch"), v.literal("account"), v.literal("workspace"), v.literal("organization")); | |
| 70 | −const storageDurability = v.union(v.literal("ephemeral"), v.literal("durable")); | |
| 71 | −const storageInstanceStatus = v.union(v.literal("active"), v.literal("closed"), v.literal("deleted")); | |
| 72 | −const storageProvider = v.union(v.literal("agentfs-local"), v.literal("agentfs-cloudflare")); | |
| 73 | −const credentialProvider = v.union( | |
| 74 | − v.literal("local-convex"), | |
| 75 | − v.literal("workos-vault"), | |
| 76 | −); | |
| 77 | −const toolSourceType = v.union(v.literal("mcp"), v.literal("openapi"), v.literal("graphql")); | |
| 78 | −const jsonObject = v.record(v.string(), v.any()); | |
| 79 | − | |
| 80 | 42 | export default defineSchema({ |
| 81 | 43 | // User identities (WorkOS-backed or anonymous). |
| 82 | 44 | // |
| 83 | 45 | // Primary access patterns: |
| 84 | 46 | // - Lookup by provider + providerAccountId (WorkOS user id / anon id). |
| 85 | 47 | accounts: defineTable({ |
| 86 | − provider: accountProvider, | |
| 48 | + provider: accountProviderValidator, | |
| 87 | 49 | providerAccountId: v.string(), // WorkOS user ID or anon_* UUID |
| 88 | 50 | email: v.optional(v.string()), |
| 89 | 51 | name: v.string(), |
| 90 | 52 | firstName: v.optional(v.string()), |
| 91 | 53 | lastName: v.optional(v.string()), |
| 92 | 54 | avatarUrl: v.optional(v.string()), |
| 93 | − status: accountStatus, | |
| 55 | + status: accountStatusValidator, | |
| 94 | 56 | createdAt: v.number(), |
| 95 | 57 | updatedAt: v.number(), |
| 96 | 58 | lastLoginAt: v.optional(v.number()), |
| @@ -128,7 +90,7 @@ export default defineSchema({ · 31 unmodified lines | ||
| 128 | 90 | workosOrgId: v.optional(v.string()), // external WorkOS org ID |
| 129 | 91 | slug: v.string(), |
| 130 | 92 | name: v.string(), |
| 131 | − status: organizationStatus, | |
| 93 | + status: organizationStatusValidator, | |
| 132 | 94 | createdByAccountId: v.optional(v.id("accounts")), |
| 133 | 95 | createdAt: v.number(), |
| 134 | 96 | updatedAt: v.number(), |
| @@ -148,8 +110,8 @@ export default defineSchema({ · 13 unmodified lines | ||
| 148 | 110 | organizationMembers: defineTable({ |
| 149 | 111 | organizationId: v.id("organizations"), |
| 150 | 112 | accountId: v.id("accounts"), |
| 151 | − role: orgRole, | |
| 152 | − status: orgMemberStatus, | |
| 113 | + role: orgRoleValidator, | |
| 114 | + status: orgMemberStatusValidator, | |
| 153 | 115 | billable: v.boolean(), |
| 154 | 116 | invitedByAccountId: v.optional(v.id("accounts")), |
| 155 | 117 | joinedAt: v.optional(v.number()), |
| @@ -171,8 +133,8 @@ export default defineSchema({ · 15 unmodified lines | ||
| 171 | 133 | organizationId: v.id("organizations"), |
| 172 | 134 | workspaceId: v.optional(v.id("workspaces")), |
| 173 | 135 | email: v.string(), |
| 174 | − role: orgRole, | |
| 175 | − status: inviteStatus, | |
| 136 | + role: orgRoleValidator, | |
| 137 | + status: inviteStatusValidator, | |
| 176 | 138 | providerInviteId: v.optional(v.string()), // external WorkOS invite ID |
| 177 | 139 | invitedByAccountId: v.id("accounts"), |
| 178 | 140 | expiresAt: v.number(), |
| @@ -215,7 +177,7 @@ export default defineSchema({ · 36 unmodified lines | ||
| 215 | 177 | organizationId: v.id("organizations"), |
| 216 | 178 | stripeSubscriptionId: v.string(), // external Stripe subscription ID |
| 217 | 179 | stripePriceId: v.string(), // external Stripe price ID |
| 218 | − status: billingSubscriptionStatus, | |
| 180 | + status: billingSubscriptionStatusValidator, | |
| 219 | 181 | currentPeriodStart: v.optional(v.number()), |
| 220 | 182 | currentPeriodEnd: v.optional(v.number()), |
| 221 | 183 | cancelAtPeriodEnd: v.boolean(), |
| @@ -251,9 +213,9 @@ export default defineSchema({ · 29 unmodified lines | ||
| 251 | 213 | workspaceId: v.id("workspaces"), |
| 252 | 214 | accountId: v.optional(v.id("accounts")), |
| 253 | 215 | clientId: v.optional(v.string()), // client label: "web", "mcp", etc. |
| 254 | − status: taskStatus, | |
| 216 | + status: taskStatusValidator, | |
| 255 | 217 | timeoutMs: v.number(), |
| 256 | − metadata: jsonObject, | |
| 218 | + metadata: jsonObjectValidator, | |
| 257 | 219 | nextEventSequence: v.optional(v.number()), |
| 258 | 220 | error: v.optional(v.string()), |
| 259 | 221 | stdout: v.optional(v.string()), |
| @@ -279,8 +241,8 @@ export default defineSchema({ · 19 unmodified lines | ||
| 279 | 241 | taskId: v.string(), // references tasks.taskId (not tasks._id) |
| 280 | 242 | workspaceId: v.id("workspaces"), |
| 281 | 243 | toolPath: v.string(), |
| 282 | − input: jsonObject, | |
| 283 | − status: approvalStatus, | |
| 244 | + input: jsonObjectValidator, | |
| 245 | + status: approvalStatusValidator, | |
| 284 | 246 | reason: v.optional(v.string()), |
| 285 | 247 | reviewerId: v.optional(v.string()), // account._id or anon_<uuid> |
| 286 | 248 | createdAt: v.number(), |
| @@ -300,7 +262,7 @@ export default defineSchema({ · 13 unmodified lines | ||
| 300 | 262 | callId: v.string(), |
| 301 | 263 | workspaceId: v.id("workspaces"), |
| 302 | 264 | toolPath: v.string(), |
| 303 | − status: toolCallStatus, | |
| 265 | + status: toolCallStatusValidator, | |
| 304 | 266 | approvalId: v.optional(v.string()), |
| 305 | 267 | error: v.optional(v.string()), |
| 306 | 268 | createdAt: v.number(), |
| @@ -318,7 +280,7 @@ export default defineSchema({ · 11 unmodified lines | ||
| 318 | 280 | taskId: v.string(), // references tasks.taskId (not tasks._id) |
| 319 | 281 | eventName: v.string(), |
| 320 | 282 | type: v.string(), |
| 321 | − payload: jsonObject, | |
| 283 | + payload: jsonObjectValidator, | |
| 322 | 284 | createdAt: v.number(), |
| 323 | 285 | }) |
| 324 | 286 | .index("by_task_sequence", ["taskId", "sequence"]), |
| @@ -342,18 +304,14 @@ export default defineSchema({ · 17 unmodified lines | ||
| 342 | 304 | ruleId: v.string(), // domain ID: trule_<uuid> |
| 343 | 305 | roleId: v.string(), |
| 344 | 306 | organizationId: v.id("organizations"), |
| 345 | − selectorType: toolRoleSelectorType, | |
| 307 | + selectorType: toolRoleSelectorTypeValidator, | |
| 346 | 308 | sourceKey: v.optional(v.string()), |
| 347 | 309 | namespacePattern: v.optional(v.string()), |
| 348 | 310 | toolPathPattern: v.optional(v.string()), |
| 349 | − matchType: policyMatchType, | |
| 350 | − effect: policyEffect, | |
| 351 | − approvalMode: policyApprovalMode, | |
| 352 | − argumentConditions: v.optional(v.array(v.object({ | |
| 353 | − key: v.string(), | |
| 354 | − operator: v.union(v.literal("equals"), v.literal("contains"), v.literal("starts_with"), v.literal("not_equals")), | |
| 355 | − value: v.string(), | |
| 356 | − }))), | |
| 311 | + matchType: policyMatchTypeValidator, | |
| 312 | + effect: policyEffectValidator, | |
| 313 | + approvalMode: policyApprovalModeValidator, | |
| 314 | + argumentConditions: v.optional(v.array(argumentConditionValidator)), | |
| 357 | 315 | priority: v.number(), |
| 358 | 316 | createdAt: v.number(), |
| 359 | 317 | updatedAt: v.number(), |
| @@ -367,11 +325,11 @@ export default defineSchema({ · 7 unmodified lines | ||
| 367 | 325 | bindingId: v.string(), // domain ID: trbind_<uuid> |
| 368 | 326 | roleId: v.string(), |
| 369 | 327 | organizationId: v.id("organizations"), |
| 370 | − scopeType: policyScopeType, | |
| 328 | + scopeType: policyScopeTypeValidator, | |
| 371 | 329 | workspaceId: v.optional(v.id("workspaces")), |
| 372 | 330 | targetAccountId: v.optional(v.id("accounts")), |
| 373 | 331 | clientId: v.optional(v.string()), |
| 374 | − status: toolRoleBindingStatus, | |
| 332 | + status: toolRoleBindingStatusValidator, | |
| 375 | 333 | expiresAt: v.optional(v.number()), |
| 376 | 334 | createdAt: v.number(), |
| 377 | 335 | updatedAt: v.number(), |
| @@ -396,14 +354,14 @@ export default defineSchema({ · 18 unmodified lines | ||
| 396 | 354 | sourceCredentials: defineTable({ |
| 397 | 355 | bindingId: v.string(), // domain ID: bind_<uuid> |
| 398 | 356 | credentialId: v.string(), // domain ID: conn_<uuid> |
| 399 | − scopeType: credentialScopeType, | |
| 357 | + scopeType: credentialScopeTypeValidator, | |
| 400 | 358 | accountId: v.optional(v.id("accounts")), |
| 401 | 359 | organizationId: v.id("organizations"), |
| 402 | 360 | workspaceId: v.optional(v.id("workspaces")), |
| 403 | 361 | sourceKey: v.string(), |
| 404 | − provider: credentialProvider, | |
| 405 | − secretJson: jsonObject, | |
| 406 | − overridesJson: v.optional(jsonObject), | |
| 362 | + provider: credentialProviderValidator, | |
| 363 | + secretJson: jsonObjectValidator, | |
| 364 | + overridesJson: v.optional(jsonObjectValidator), | |
| 407 | 365 | boundAuthFingerprint: v.optional(v.string()), |
| 408 | 366 | createdAt: v.number(), |
| 409 | 367 | updatedAt: v.number(), |
| @@ -430,13 +388,13 @@ export default defineSchema({ · 20 unmodified lines | ||
| 430 | 388 | // - Enforce name uniqueness per owner scope. |
| 431 | 389 | toolSources: defineTable({ |
| 432 | 390 | sourceId: v.string(), // domain ID: src_<uuid> |
| 433 | − scopeType: toolSourceScopeType, | |
| 391 | + scopeType: toolSourceScopeTypeValidator, | |
| 434 | 392 | organizationId: v.id("organizations"), |
| 435 | 393 | workspaceId: v.optional(v.id("workspaces")), |
| 436 | 394 | name: v.string(), |
| 437 | − type: toolSourceType, | |
| 395 | + type: toolSourceTypeValidator, | |
| 438 | 396 | configVersion: v.number(), |
| 439 | − config: jsonObject, | |
| 397 | + config: jsonObjectValidator, | |
| 440 | 398 | specHash: v.optional(v.string()), |
| 441 | 399 | authFingerprint: v.optional(v.string()), |
| 442 | 400 | enabled: v.boolean(), |
| @@ -527,7 +485,7 @@ export default defineSchema({ · 84 unmodified lines | ||
| 527 | 485 | normalizedPath: v.string(), |
| 528 | 486 | aliases: v.array(v.string()), |
| 529 | 487 | description: v.string(), |
| 530 | − approval: toolApprovalMode, | |
| 488 | + approval: toolApprovalModeValidator, | |
| 531 | 489 | source: v.optional(v.string()), |
| 532 | 490 | searchText: v.string(), |
| 533 | 491 | displayInput: v.optional(v.string()), |
| @@ -577,10 +535,10 @@ export default defineSchema({ · 43 unmodified lines | ||
| 577 | 535 | // Rows are scope-aware and can be shared across account/workspace/org contexts. |
| 578 | 536 | storageInstances: defineTable({ |
| 579 | 537 | instanceId: v.string(), |
| 580 | − scopeType: storageScopeType, | |
| 581 | − durability: storageDurability, | |
| 582 | − status: storageInstanceStatus, | |
| 583 | − provider: storageProvider, | |
| 538 | + scopeType: storageScopeTypeValidator, | |
| 539 | + durability: storageDurabilityValidator, | |
| 540 | + status: storageInstanceStatusValidator, | |
| 541 | + provider: storageProviderValidator, | |
| 584 | 542 | backendKey: v.string(), |
| 585 | 543 | organizationId: v.id("organizations"), |
| 586 | 544 | workspaceId: v.optional(v.id("workspaces")), |
| @@ -626,8 +584,8 @@ export default defineSchema({ · 39 unmodified lines | ||
| 626 | 584 | accountLinks: defineTable({ |
| 627 | 585 | sourceAccountId: v.id("accounts"), |
| 628 | 586 | targetAccountId: v.id("accounts"), |
| 629 | − sourceProvider: accountProvider, | |
| 630 | − targetProvider: accountProvider, | |
| 587 | + sourceProvider: accountProviderValidator, | |
| 588 | + targetProvider: accountProviderValidator, | |
| 631 | 589 | linkReason: v.union(v.literal("anonymous_claim")), |
| 632 | 590 | createdAt: v.number(), |
| 633 | 591 | updatedAt: v.number(), |
| @@ -10,6 +10,7 @@ · 9 unmodified lines | ||
| 10 | 10 | "dependencies": { |
| 11 | 11 | "@convex-dev/rate-limiter": "^0.3.2", |
| 12 | 12 | "convex": "^1.31.7", |
| 13 | + "convex-helpers": "^0.1.111", | |
| 13 | 14 | "sql.js": "^1.14.0" |
| 14 | 15 | }, |
| 15 | 16 | "main": "./convex/_generated/api.js", |
| @@ -1,70 +1,89 @@ | ||
| 1 | 1 | import { v } from "convex/values"; |
| 2 | +import { literals } from "convex-helpers/validators"; | |
| 3 | +import { | |
| 4 | + ACCOUNT_PROVIDERS, | |
| 5 | + ACCOUNT_STATUSES, | |
| 6 | + APPROVAL_STATUSES, | |
| 7 | + ARGUMENT_CONDITION_OPERATORS, | |
| 8 | + BILLING_SUBSCRIPTION_STATUSES, | |
| 9 | + COMPLETED_TASK_STATUSES, | |
| 10 | + CREDENTIAL_PROVIDERS, | |
| 11 | + CREDENTIAL_SCOPE_TYPES, | |
| 12 | + INVITE_STATUSES, | |
| 13 | + ORGANIZATION_MEMBER_STATUSES, | |
| 14 | + ORGANIZATION_ROLES, | |
| 15 | + ORGANIZATION_STATUSES, | |
| 16 | + POLICY_APPROVAL_MODES, | |
| 17 | + POLICY_EFFECTS, | |
| 18 | + POLICY_MATCH_TYPES, | |
| 19 | + POLICY_RESOURCE_TYPES, | |
| 20 | + POLICY_SCOPE_TYPES, | |
| 21 | + STORAGE_ACCESS_TYPES, | |
| 22 | + STORAGE_DURABILITIES, | |
| 23 | + STORAGE_INSTANCE_STATUSES, | |
| 24 | + STORAGE_PROVIDERS, | |
| 25 | + STORAGE_SCOPE_TYPES, | |
| 26 | + TASK_STATUSES, | |
| 27 | + TERMINAL_TOOL_CALL_STATUSES, | |
| 28 | + TOOL_APPROVAL_MODES, | |
| 29 | + TOOL_CALL_STATUSES, | |
| 30 | + TOOL_ROLE_BINDING_STATUSES, | |
| 31 | + TOOL_ROLE_SELECTOR_TYPES, | |
| 32 | + TOOL_SOURCE_SCOPE_TYPES, | |
| 33 | + TOOL_SOURCE_TYPES, | |
| 34 | +} from "../../../core/src/types"; | |
| 35 | + | |
| 36 | +// Core enum validators shared by Convex schema and function args. | |
| 37 | +export const accountProviderValidator = literals(...ACCOUNT_PROVIDERS); | |
| 38 | +export const accountStatusValidator = literals(...ACCOUNT_STATUSES); | |
| 39 | +export const organizationStatusValidator = literals(...ORGANIZATION_STATUSES); | |
| 40 | +export const orgRoleValidator = literals(...ORGANIZATION_ROLES); | |
| 41 | +export const orgMemberStatusValidator = literals(...ORGANIZATION_MEMBER_STATUSES); | |
| 42 | + | |
| 43 | +export const billingSubscriptionStatusValidator = literals(...BILLING_SUBSCRIPTION_STATUSES); | |
| 44 | + | |
| 45 | +export const inviteStatusValidator = literals(...INVITE_STATUSES); | |
| 46 | + | |
| 47 | +export const taskStatusValidator = literals(...TASK_STATUSES); | |
| 2 | 48 | |
| 3 | 49 | export const jsonObjectValidator = v.record(v.string(), v.any()); |
| 4 | 50 | |
| 5 | −export const completedTaskStatusValidator = v.union( | |
| 6 | − v.literal("completed"), | |
| 7 | − v.literal("failed"), | |
| 8 | − v.literal("timed_out"), | |
| 9 | − v.literal("denied"), | |
| 10 | −); | |
| 11 | − | |
| 12 | −export const approvalStatusValidator = v.union(v.literal("pending"), v.literal("approved"), v.literal("denied")); | |
| 13 | − | |
| 14 | −export const terminalToolCallStatusValidator = v.union( | |
| 15 | − v.literal("completed"), | |
| 16 | − v.literal("failed"), | |
| 17 | − v.literal("denied"), | |
| 18 | −); | |
| 19 | − | |
| 20 | −export const policyScopeTypeValidator = v.union(v.literal("account"), v.literal("organization"), v.literal("workspace")); | |
| 21 | −export const policyResourceTypeValidator = v.union( | |
| 22 | − v.literal("all_tools"), | |
| 23 | − v.literal("source"), | |
| 24 | − v.literal("namespace"), | |
| 25 | − v.literal("tool_path"), | |
| 26 | −); | |
| 27 | −export const policyMatchTypeValidator = v.union(v.literal("glob"), v.literal("exact")); | |
| 28 | −export const policyEffectValidator = v.union(v.literal("allow"), v.literal("deny")); | |
| 29 | −export const policyApprovalModeValidator = v.union(v.literal("inherit"), v.literal("auto"), v.literal("required")); | |
| 30 | −export const toolRoleSelectorTypeValidator = v.union( | |
| 31 | − v.literal("all"), | |
| 32 | − v.literal("source"), | |
| 33 | − v.literal("namespace"), | |
| 34 | − v.literal("tool_path"), | |
| 35 | −); | |
| 36 | −export const toolRoleBindingStatusValidator = v.union(v.literal("active"), v.literal("disabled")); | |
| 37 | −export const argumentConditionOperatorValidator = v.union(v.literal("equals"), v.literal("contains"), v.literal("starts_with"), v.literal("not_equals")); | |
| 51 | +export const completedTaskStatusValidator = literals(...COMPLETED_TASK_STATUSES); | |
| 52 | + | |
| 53 | +export const approvalStatusValidator = literals(...APPROVAL_STATUSES); | |
| 54 | + | |
| 55 | +export const toolCallStatusValidator = literals(...TOOL_CALL_STATUSES); | |
| 56 | + | |
| 57 | +export const toolApprovalModeValidator = literals(...TOOL_APPROVAL_MODES); | |
| 58 | + | |
| 59 | +export const terminalToolCallStatusValidator = literals(...TERMINAL_TOOL_CALL_STATUSES); | |
| 60 | + | |
| 61 | +export const policyScopeTypeValidator = literals(...POLICY_SCOPE_TYPES); | |
| 62 | +export const policyResourceTypeValidator = literals(...POLICY_RESOURCE_TYPES); | |
| 63 | +export const policyMatchTypeValidator = literals(...POLICY_MATCH_TYPES); | |
| 64 | +export const policyEffectValidator = literals(...POLICY_EFFECTS); | |
| 65 | +export const policyApprovalModeValidator = literals(...POLICY_APPROVAL_MODES); | |
| 66 | +export const toolRoleSelectorTypeValidator = literals(...TOOL_ROLE_SELECTOR_TYPES); | |
| 67 | +export const toolRoleBindingStatusValidator = literals(...TOOL_ROLE_BINDING_STATUSES); | |
| 68 | +export const argumentConditionOperatorValidator = literals(...ARGUMENT_CONDITION_OPERATORS); | |
| 38 | 69 | export const argumentConditionValidator = v.object({ |
| 39 | 70 | key: v.string(), |
| 40 | 71 | operator: argumentConditionOperatorValidator, |
| 41 | 72 | value: v.string(), |
| 42 | 73 | }); |
| 43 | −export const toolSourceScopeTypeValidator = v.union(v.literal("organization"), v.literal("workspace")); | |
| 44 | −export const credentialScopeTypeValidator = v.union(v.literal("account"), v.literal("organization"), v.literal("workspace")); | |
| 74 | +export const toolSourceScopeTypeValidator = literals(...TOOL_SOURCE_SCOPE_TYPES); | |
| 75 | +export const credentialScopeTypeValidator = literals(...CREDENTIAL_SCOPE_TYPES); | |
| 45 | 76 | |
| 46 | −export const credentialProviderValidator = v.union( | |
| 47 | − v.literal("local-convex"), | |
| 48 | − v.literal("workos-vault"), | |
| 49 | −); | |
| 77 | +export const credentialProviderValidator = literals(...CREDENTIAL_PROVIDERS); | |
| 50 | 78 | |
| 51 | −export const toolSourceTypeValidator = v.union(v.literal("mcp"), v.literal("openapi"), v.literal("graphql")); | |
| 79 | +export const toolSourceTypeValidator = literals(...TOOL_SOURCE_TYPES); | |
| 52 | 80 | |
| 53 | −export const storageScopeTypeValidator = v.union( | |
| 54 | − v.literal("scratch"), | |
| 55 | − v.literal("account"), | |
| 56 | − v.literal("workspace"), | |
| 57 | − v.literal("organization"), | |
| 58 | −); | |
| 81 | +export const storageScopeTypeValidator = literals(...STORAGE_SCOPE_TYPES); | |
| 59 | 82 | |
| 60 | −export const storageDurabilityValidator = v.union(v.literal("ephemeral"), v.literal("durable")); | |
| 83 | +export const storageDurabilityValidator = literals(...STORAGE_DURABILITIES); | |
| 61 | 84 | |
| 62 | −export const storageInstanceStatusValidator = v.union(v.literal("active"), v.literal("closed"), v.literal("deleted")); | |
| 85 | +export const storageInstanceStatusValidator = literals(...STORAGE_INSTANCE_STATUSES); | |
| 63 | 86 | |
| 64 | −export const storageProviderValidator = v.union(v.literal("agentfs-local"), v.literal("agentfs-cloudflare")); | |
| 87 | +export const storageProviderValidator = literals(...STORAGE_PROVIDERS); | |
| 65 | 88 | |
| 66 | −export const storageAccessTypeValidator = v.union( | |
| 67 | − v.literal("opened"), | |
| 68 | − v.literal("provided"), | |
| 69 | − v.literal("accessed"), | |
| 70 | −); | |
| 89 | +export const storageAccessTypeValidator = literals(...STORAGE_ACCESS_TYPES); | |
| @@ -1,9 +1,11 @@ | ||
| 1 | −import type { TaskStatus } from "../../../core/src/types"; | |
| 1 | +import { COMPLETED_TASK_STATUSES, type CompletedTaskStatus, type TaskStatus } from "../../../core/src/types"; | |
| 2 | 2 | |
| 3 | −type TerminalTaskStatus = Extract<TaskStatus, "completed" | "failed" | "timed_out" | "denied">; | |
| 3 | +type TerminalTaskStatus = CompletedTaskStatus; | |
| 4 | + | |
| 5 | +const TERMINAL_TASK_STATUS_SET = new Set<TaskStatus>(COMPLETED_TASK_STATUSES); | |
| 4 | 6 | |
| 5 | 7 | export function isTerminalTaskStatus(status: TaskStatus): status is TerminalTaskStatus { |
| 6 | − return status === "completed" || status === "failed" || status === "timed_out" || status === "denied"; | |
| 8 | + return TERMINAL_TASK_STATUS_SET.has(status); | |
| 7 | 9 | } |
| 8 | 10 | |
| 9 | 11 | export function taskTerminalEventType(status: TerminalTaskStatus): "task.completed" | "task.failed" | "task.timed_out" | "task.denied" { |