Files
zopu-code/packages/backend/convex/schema.ts
2026-08-04 17:37:50 +05:30

535 lines
16 KiB
TypeScript

import { defineSchema, defineTable } from "convex/server";
import { v } from "convex/values";
/* eslint-disable sort-keys */
export default defineSchema({
organizations: defineTable({
createdAt: v.number(),
createdBy: v.string(),
kind: v.union(v.literal("personal"), v.literal("team")),
name: v.string(),
}).index("by_createdBy_and_kind", ["createdBy", "kind"]),
organizationMembers: defineTable({
createdAt: v.number(),
organizationId: v.id("organizations"),
role: v.union(v.literal("owner"), v.literal("member")),
userId: v.string(),
})
.index("by_userId", ["userId"])
.index("by_organizationId", ["organizationId"])
.index("by_organizationId_and_userId", ["organizationId", "userId"]),
gitProviderAccounts: defineTable({
createdAt: v.number(),
externalAccountId: v.string(),
externalEmail: v.optional(v.string()),
externalUsername: v.string(),
organizationId: v.id("organizations"),
provider: v.union(v.literal("github"), v.literal("gitea")),
serverUrl: v.string(),
status: v.union(
v.literal("pending-auth"),
v.literal("active"),
v.literal("reauth-required"),
v.literal("revoked"),
v.literal("unavailable")
),
updatedAt: v.number(),
userId: v.string(),
})
.index("by_userId_and_provider_and_serverUrl", [
"userId",
"provider",
"serverUrl",
])
.index("by_organizationId", ["organizationId"]),
gitConnections: defineTable({
connectedAt: v.number(),
creatorUserId: v.optional(v.string()),
credentialCiphertext: v.string(),
credentialIv: v.string(),
credentialKind: v.union(v.literal("oauth"), v.literal("token")),
gitProviderAccountId: v.optional(v.id("gitProviderAccounts")),
grantedScopesJson: v.optional(v.string()),
lastError: v.optional(v.string()),
lastVerifiedAt: v.optional(v.number()),
organizationId: v.id("organizations"),
provider: v.union(v.literal("github"), v.literal("gitea")),
reauthRequiredAt: v.optional(v.number()),
serverUrl: v.string(),
state: v.optional(
v.union(
v.literal("pending-auth"),
v.literal("active"),
v.literal("reauth-required"),
v.literal("revoked"),
v.literal("unavailable")
)
),
updatedAt: v.number(),
username: v.optional(v.string()),
})
.index("by_organizationId", ["organizationId"])
.index("by_gitProviderAccountId", ["gitProviderAccountId"]),
gitProviderOrganizations: defineTable({
createdAt: v.number(),
displayName: v.optional(v.string()),
externalId: v.string(),
externalSlug: v.string(),
gitProviderAccountId: v.id("gitProviderAccounts"),
organizationId: v.id("organizations"),
serverUrl: v.string(),
updatedAt: v.number(),
verificationState: v.union(
v.literal("unverified"),
v.literal("verified"),
v.literal("stale")
),
visibility: v.union(v.literal("public"), v.literal("private")),
})
.index("by_gitProviderAccountId", ["gitProviderAccountId"])
.index("by_organizationId", ["organizationId"]),
gitRepositories: defineTable({
cloneUrl: v.string(),
createdAt: v.number(),
defaultBranch: v.string(),
fullName: v.string(),
gitProviderAccountId: v.id("gitProviderAccounts"),
gitProviderOrganizationId: v.optional(v.id("gitProviderOrganizations")),
lfsCapability: v.union(
v.literal("unknown"),
v.literal("supported"),
v.literal("unsupported")
),
name: v.string(),
organizationId: v.id("organizations"),
owner: v.string(),
permissionsAdmin: v.boolean(),
permissionsMaintain: v.boolean(),
permissionsPull: v.boolean(),
permissionsPush: v.boolean(),
permissionsTriage: v.boolean(),
privacy: v.union(v.literal("public"), v.literal("private")),
provider: v.union(v.literal("github"), v.literal("gitea")),
providerRepositoryId: v.string(),
serverUrl: v.string(),
sourceMigrationId: v.optional(v.id("gitMigrations")),
updatedAt: v.number(),
webUrl: v.string(),
webhookState: v.union(
v.literal("none"),
v.literal("pending"),
v.literal("active"),
v.literal("failed")
),
})
.index("by_provider_and_serverUrl_and_externalRepositoryId", [
"provider",
"serverUrl",
"providerRepositoryId",
])
.index("by_organizationId", ["organizationId"]),
gitMigrations: defineTable({
createdAt: v.number(),
failureReason: v.optional(v.string()),
githubConnectionId: v.id("gitConnections"),
idempotencyKey: v.string(),
includeLfs: v.boolean(),
organizationId: v.id("organizations"),
puterConnectionId: v.id("gitConnections"),
resultingRepositoryId: v.optional(v.id("gitRepositories")),
sourceIsPrivate: v.boolean(),
sourceRepositoryUrl: v.string(),
status: v.union(
v.literal("queued"),
v.literal("running"),
v.literal("succeeded"),
v.literal("failed"),
v.literal("cancelled")
),
targetOwner: v.string(),
targetRepositoryName: v.string(),
updatedAt: v.number(),
})
.index("by_organizationId", ["organizationId"])
.index("by_idempotencyKey", ["idempotencyKey"]),
gitWebhookDeliveries: defineTable({
createdAt: v.number(),
deliveryId: v.string(),
error: v.optional(v.string()),
event: v.string(),
externalRepositoryId: v.optional(v.string()),
payloadHash: v.string(),
processingState: v.union(
v.literal("received"),
v.literal("processing"),
v.literal("processed"),
v.literal("ignored"),
v.literal("failed"),
v.literal("duplicate")
),
provider: v.union(v.literal("github"), v.literal("gitea")),
repositoryRef: v.optional(v.id("gitRepositories")),
updatedAt: v.number(),
})
.index("by_provider_and_deliveryId", ["provider", "deliveryId"])
.index("by_processingState", ["processingState"]),
projects: defineTable({
createdAt: v.number(),
defaultBranch: v.optional(v.string()),
description: v.optional(v.string()),
gitConnectionId: v.optional(v.id("gitConnections")),
gitRepositoryId: v.optional(v.id("gitRepositories")),
instructions: v.optional(v.string()),
name: v.string(),
normalizedSourceUrl: v.string(),
organizationId: v.id("organizations"),
repositoryPath: v.string(),
sourceHost: v.string(),
sourceUrl: v.string(),
updatedAt: v.number(),
})
.index("by_organizationId_and_createdAt", ["organizationId", "createdAt"])
.index("by_organizationId_and_normalizedSourceUrl", [
"organizationId",
"normalizedSourceUrl",
]),
projectContextDocuments: defineTable({
content: v.string(),
createdAt: v.number(),
kind: v.union(
v.literal("readme"),
v.literal("agents"),
v.literal("product"),
v.literal("business"),
v.literal("design"),
v.literal("tech")
),
origin: v.literal("repository"),
path: v.string(),
projectId: v.id("projects"),
sourceUrl: v.string(),
updatedAt: v.number(),
}).index("by_projectId_and_path", ["projectId", "path"]),
projectEnvironmentVariables: defineTable({
category: v.union(
v.literal("required"),
v.literal("integration"),
v.literal("optional")
),
description: v.optional(v.string()),
name: v.string(),
organizationId: v.id("organizations"),
projectId: v.id("projects"),
secretReference: v.optional(v.string()),
source: v.union(
v.literal("detected"),
v.literal("user"),
v.literal("system")
),
status: v.union(
v.literal("missing"),
v.literal("configured"),
v.literal("invalid")
),
updatedAt: v.number(),
})
.index("by_projectId", ["projectId"])
.index("by_projectId_and_name", ["projectId", "name"]),
works: defineTable({
createdAt: v.number(),
createdBy: v.string(),
createdFromEventId: v.id("events"),
organizationId: v.id("organizations"),
primaryProjectId: v.optional(v.id("projects")),
summary: v.optional(v.string()),
title: v.string(),
})
.index("by_organizationId_and_createdAt", ["organizationId", "createdAt"])
.index("by_primaryProjectId_and_createdAt", [
"primaryProjectId",
"createdAt",
]),
threads: defineTable({
createdAt: v.number(),
createdFromEventId: v.id("events"),
organizationId: v.id("organizations"),
projectId: v.optional(v.id("projects")),
purpose: v.string(),
title: v.string(),
workId: v.id("works"),
})
.index("by_workId_and_createdAt", ["workId", "createdAt"])
.index("by_organizationId_and_createdAt", ["organizationId", "createdAt"]),
events: defineTable({
actor: v.union(
v.object({
kind: v.literal("user"),
userId: v.string(),
}),
v.object({
kind: v.literal("system"),
service: v.string(),
}),
v.object({
kind: v.literal("work"),
workId: v.id("works"),
}),
v.object({
kind: v.literal("thread"),
threadId: v.id("threads"),
}),
v.object({
kind: v.literal("tool"),
tool: v.string(),
}),
v.object({
integration: v.string(),
kind: v.literal("integration"),
})
),
artifactIds: v.optional(v.array(v.id("artifacts"))),
causationId: v.optional(v.id("events")),
correlationId: v.string(),
idempotencyKey: v.string(),
occurredAt: v.number(),
organizationId: v.id("organizations"),
payload: v.any(),
projectId: v.optional(v.id("projects")),
recordedAt: v.number(),
replyToEventId: v.optional(v.id("events")),
scopeKind: v.union(v.literal("global"), v.literal("work")),
threadId: v.optional(v.id("threads")),
type: v.string(),
visibility: v.union(
v.literal("timeline"),
v.literal("compact"),
v.literal("internal")
),
workId: v.optional(v.id("works")),
})
.index("by_organizationId_and_scopeKind_and_recordedAt", [
"organizationId",
"scopeKind",
"recordedAt",
])
.index("by_organizationId_and_scopeKind_and_workId_and_recordedAt", [
"organizationId",
"scopeKind",
"workId",
"recordedAt",
])
.index("by_organizationId_and_projectId_and_recordedAt", [
"organizationId",
"projectId",
"recordedAt",
])
.index("by_organizationId_and_threadId_and_recordedAt", [
"organizationId",
"threadId",
"recordedAt",
])
.index("by_organizationId_and_causationId", [
"organizationId",
"causationId",
])
.index("by_organizationId_and_idempotencyKey", [
"organizationId",
"idempotencyKey",
]),
artifacts: defineTable({
card: v.any(),
content: v.any(),
createdAt: v.number(),
createdByEventId: v.id("events"),
kind: v.union(
v.literal("project_setup"),
v.literal("summary"),
v.literal("plan"),
v.literal("preview"),
v.literal("blocker"),
v.literal("report")
),
logicalKey: v.string(),
organizationId: v.id("organizations"),
projectId: v.optional(v.id("projects")),
status: v.union(
v.literal("working"),
v.literal("ready"),
v.literal("blocked"),
v.literal("failed"),
v.literal("superseded")
),
summary: v.string(),
supersedesArtifactId: v.optional(v.id("artifacts")),
threadId: v.optional(v.id("threads")),
title: v.string(),
version: v.number(),
storageId: v.optional(v.id("_storage")),
workId: v.optional(v.id("works")),
})
.index("by_projectId_and_createdAt", ["projectId", "createdAt"])
.index("by_workId_and_createdAt", ["workId", "createdAt"])
.index("by_threadId_and_createdAt", ["threadId", "createdAt"])
.index("by_organizationId_and_logicalKey_and_version", [
"organizationId",
"logicalKey",
"version",
]),
projectRuntimes: defineTable({
attempt: v.optional(v.number()),
createdAt: v.number(),
idempotencyKey: v.string(),
lastError: v.optional(v.string()),
organizationId: v.id("organizations"),
projectId: v.id("projects"),
provider: v.string(),
repositoryCommit: v.optional(v.string()),
repositoryPath: v.optional(v.string()),
runtimeId: v.optional(v.string()),
status: v.union(
v.literal("requested"),
v.literal("creating_vm"),
v.literal("cloning"),
v.literal("checking_repository"),
v.literal("ready"),
v.literal("failed")
),
updatedAt: v.number(),
vmId: v.optional(v.string()),
workspacePath: v.optional(v.string()),
})
.index("by_projectId", ["projectId"])
.index("by_organizationId_and_status", ["organizationId", "status"])
.index("by_organizationId_and_runtime_id", ["organizationId", "runtimeId"]),
conversationAgents: defineTable({
agentType: v.string(),
createdAt: v.number(),
flueConversationId: v.optional(v.string()),
id: v.string(),
lastEventId: v.optional(v.id("events")),
organizationId: v.id("organizations"),
projectId: v.id("projects"),
runtimeId: v.optional(v.id("projectRuntimes")),
status: v.union(
v.literal("registered"),
v.literal("active"),
v.literal("idle"),
v.literal("disabled")
),
updatedAt: v.number(),
})
.index("by_projectId", ["projectId"])
.index("by_projectId_and_status", ["projectId", "status"])
.index("by_organizationId_and_status", ["organizationId", "status"]),
agentDispatches: defineTable({
agentId: v.string(),
attempt: v.number(),
createdAt: v.number(),
handlerVersion: v.string(),
idempotencyKey: v.string(),
lastError: v.optional(v.string()),
organizationId: v.id("organizations"),
projectId: v.optional(v.id("projects")),
sourceEventId: v.id("events"),
status: v.union(
v.literal("pending"),
v.literal("sending"),
v.literal("accepted"),
v.literal("completed"),
v.literal("failed")
),
threadId: v.optional(v.id("threads")),
updatedAt: v.number(),
workId: v.optional(v.id("works")),
})
.index("by_organizationId_and_source_event_handler", [
"organizationId",
"sourceEventId",
"agentId",
"handlerVersion",
])
.index("by_organizationId_and_status", ["organizationId", "status"])
.index("by_organizationId_and_status_and_updatedAt", [
"organizationId",
"status",
"updatedAt",
]),
flowRuns: defineTable({
agentId: v.optional(v.string()),
attempt: v.number(),
finishedAt: v.optional(v.number()),
flowType: v.string(),
flowVersion: v.string(),
idempotencyKey: v.string(),
organizationId: v.id("organizations"),
projectId: v.optional(v.id("projects")),
sourceEventId: v.id("events"),
startedAt: v.number(),
state: v.any(),
status: v.union(
v.literal("running"),
v.literal("completed"),
v.literal("failed"),
v.literal("cancelled")
),
threadId: v.optional(v.id("threads")),
updatedAt: v.number(),
workId: v.optional(v.id("works")),
})
.index("by_organizationId_and_thread", ["organizationId", "threadId"])
.index("by_organizationId_and_work_and_status", [
"organizationId",
"workId",
"status",
])
.index("by_organizationId_and_agent_and_status", [
"organizationId",
"agentId",
"status",
])
.index("by_organizationId_and_source_event", [
"organizationId",
"sourceEventId",
]),
artifactBuilds: defineTable({
artifactId: v.optional(v.id("artifacts")),
artifactKind: v.union(
v.literal("project_setup"),
v.literal("summary"),
v.literal("plan"),
v.literal("preview"),
v.literal("blocker"),
v.literal("report")
),
createdAt: v.number(),
flowRunId: v.optional(v.id("flowRuns")),
idempotencyKey: v.string(),
lastError: v.optional(v.string()),
organizationId: v.id("organizations"),
outputStorageId: v.optional(v.id("_storage")),
projectId: v.optional(v.id("projects")),
sourceManifest: v.any(),
status: v.union(
v.literal("pending"),
v.literal("building"),
v.literal("ready"),
v.literal("failed")
),
threadId: v.optional(v.id("threads")),
updatedAt: v.number(),
workId: v.optional(v.id("works")),
})
.index("by_organizationId_and_flow_run", ["organizationId", "flowRunId"])
.index("by_organizationId_and_status_and_updatedAt", [
"organizationId",
"status",
"updatedAt",
])
.index("by_organizationId_and_project_and_createdAt", [
"organizationId",
"projectId",
"createdAt",
]),
});