feat(ST-1111.1): add ClaudeJob model and state-machine enum

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Janpeter Visser 2026-04-29 18:59:01 +02:00
parent 8a9fb9d32b
commit 5274e1ee1a
2 changed files with 96 additions and 14 deletions

View file

@ -0,0 +1,43 @@
-- CreateEnum
CREATE TYPE "ClaudeJobStatus" AS ENUM ('QUEUED', 'CLAIMED', 'RUNNING', 'DONE', 'FAILED', 'CANCELLED');
-- CreateTable
CREATE TABLE "claude_jobs" (
"id" TEXT NOT NULL,
"user_id" TEXT NOT NULL,
"product_id" TEXT NOT NULL,
"task_id" TEXT NOT NULL,
"status" "ClaudeJobStatus" NOT NULL DEFAULT 'QUEUED',
"claimed_by_token_id" TEXT,
"claimed_at" TIMESTAMP(3),
"started_at" TIMESTAMP(3),
"finished_at" TIMESTAMP(3),
"branch" TEXT,
"summary" TEXT,
"error" TEXT,
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3) NOT NULL,
CONSTRAINT "claude_jobs_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE INDEX "claude_jobs_user_id_status_idx" ON "claude_jobs"("user_id", "status");
-- CreateIndex
CREATE INDEX "claude_jobs_task_id_status_idx" ON "claude_jobs"("task_id", "status");
-- CreateIndex
CREATE INDEX "claude_jobs_status_claimed_at_idx" ON "claude_jobs"("status", "claimed_at");
-- AddForeignKey
ALTER TABLE "claude_jobs" ADD CONSTRAINT "claude_jobs_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "claude_jobs" ADD CONSTRAINT "claude_jobs_product_id_fkey" FOREIGN KEY ("product_id") REFERENCES "products"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "claude_jobs" ADD CONSTRAINT "claude_jobs_task_id_fkey" FOREIGN KEY ("task_id") REFERENCES "tasks"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "claude_jobs" ADD CONSTRAINT "claude_jobs_claimed_by_token_id_fkey" FOREIGN KEY ("claimed_by_token_id") REFERENCES "api_tokens"("id") ON DELETE SET NULL ON UPDATE CASCADE;

View file

@ -29,6 +29,15 @@ enum PbiStatus {
DONE
}
enum ClaudeJobStatus {
QUEUED
CLAIMED
RUNNING
DONE
FAILED
CANCELLED
}
enum TaskStatus {
TO_DO
IN_PROGRESS
@ -66,14 +75,15 @@ model User {
created_at DateTime @default(now())
updated_at DateTime @updatedAt
roles UserRole[]
api_tokens ApiToken[]
products Product[]
todos Todo[]
product_members ProductMember[]
assigned_stories Story[] @relation("StoryAssignee")
login_pairings LoginPairing[]
api_tokens ApiToken[]
products Product[]
todos Todo[]
product_members ProductMember[]
assigned_stories Story[] @relation("StoryAssignee")
login_pairings LoginPairing[]
asked_questions ClaudeQuestion[] @relation("ClaudeQuestionAsker")
answered_questions ClaudeQuestion[] @relation("ClaudeQuestionAnswerer")
claude_jobs ClaudeJob[]
@@index([active_product_id])
@@map("users")
@ -90,13 +100,14 @@ model UserRole {
}
model ApiToken {
id String @id @default(cuid())
user User @relation(fields: [user_id], references: [id], onDelete: Cascade)
user_id String
token_hash String @unique
label String?
created_at DateTime @default(now())
revoked_at DateTime?
id String @id @default(cuid())
user User @relation(fields: [user_id], references: [id], onDelete: Cascade)
user_id String
token_hash String @unique
label String?
created_at DateTime @default(now())
revoked_at DateTime?
claimed_jobs ClaudeJob[]
@@index([token_hash])
@@map("api_tokens")
@ -119,8 +130,9 @@ model Product {
stories Story[]
todos Todo[]
members ProductMember[]
active_for_users User[] @relation("UserActiveProduct")
active_for_users User[] @relation("UserActiveProduct")
claude_questions ClaudeQuestion[]
claude_jobs ClaudeJob[]
@@unique([user_id, name])
@@unique([user_id, code])
@ -225,12 +237,39 @@ model Task {
created_at DateTime @default(now())
updated_at DateTime @updatedAt
claude_questions ClaudeQuestion[]
claude_jobs ClaudeJob[]
@@index([story_id, priority, sort_order])
@@index([sprint_id, status])
@@map("tasks")
}
model ClaudeJob {
id String @id @default(cuid())
user User @relation(fields: [user_id], references: [id], onDelete: Cascade)
user_id String
product Product @relation(fields: [product_id], references: [id], onDelete: Cascade)
product_id String
task Task @relation(fields: [task_id], references: [id], onDelete: Cascade)
task_id String
status ClaudeJobStatus @default(QUEUED)
claimed_by_token ApiToken? @relation(fields: [claimed_by_token_id], references: [id], onDelete: SetNull)
claimed_by_token_id String?
claimed_at DateTime?
started_at DateTime?
finished_at DateTime?
branch String?
summary String?
error String?
created_at DateTime @default(now())
updated_at DateTime @updatedAt
@@index([user_id, status])
@@index([task_id, status])
@@index([status, claimed_at])
@@map("claude_jobs")
}
model ProductMember {
id String @id @default(cuid())
product Product @relation(fields: [product_id], references: [id], onDelete: Cascade)