Patchpass V1
Deploy / Build (push) Successful in 28s
Deploy / Test & Lint (push) Failing after 29s
Deploy / Build and Push Docker Image (push) Has been skipped

This commit is contained in:
Space-Banane
2026-07-18 20:14:44 +02:00
commit 7e05dd918c
101 changed files with 15183 additions and 0 deletions
@@ -0,0 +1,182 @@
-- CreateEnum
CREATE TYPE "UserRole" AS ENUM ('ADMIN', 'USER');
-- CreateEnum
CREATE TYPE "RequestState" AS ENUM ('PENDING', 'CHANGES_REQUESTED', 'APPROVED', 'REJECTED', 'EXPIRED', 'CONSUMED', 'CANCELLED');
-- CreateEnum
CREATE TYPE "NotificationType" AS ENUM ('REQUEST_CREATED', 'REQUEST_UPDATED', 'REQUEST_APPROVED', 'REQUEST_REJECTED', 'CHANGES_REQUESTED', 'REQUEST_CONSUMED', 'REQUEST_CANCELLED', 'REQUEST_EXPIRED', 'AGENT_DISABLED', 'ADMIN_ACTION', 'SETTINGS_CHANGED');
-- CreateEnum
CREATE TYPE "GlobalSettingType" AS ENUM ('registration_enabled', 'requests_enabled');
-- CreateTable
CREATE TABLE "GlobalSetting" (
"type" "GlobalSettingType" NOT NULL,
"value" TEXT NOT NULL,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "GlobalSetting_pkey" PRIMARY KEY ("type")
);
-- CreateTable
CREATE TABLE "User" (
"id" SERIAL NOT NULL,
"username" TEXT NOT NULL,
"displayName" TEXT NOT NULL,
"password" TEXT NOT NULL,
"role" "UserRole" NOT NULL DEFAULT 'USER',
"totpSecret" TEXT,
"totpEnabled" BOOLEAN NOT NULL DEFAULT false,
"disabled" BOOLEAN NOT NULL DEFAULT false,
"autoDeleteEnabled" BOOLEAN NOT NULL DEFAULT false,
"autoDeleteDays" INTEGER NOT NULL DEFAULT 30,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "User_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Session" (
"id" SERIAL NOT NULL,
"hash" TEXT NOT NULL,
"userId" INTEGER NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "Session_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Agent" (
"id" SERIAL NOT NULL,
"name" TEXT NOT NULL,
"description" TEXT,
"website" TEXT,
"iconUrl" TEXT,
"apiKey" TEXT NOT NULL,
"disabled" BOOLEAN NOT NULL DEFAULT false,
"maxPendingRequests" INTEGER NOT NULL DEFAULT 5,
"ownerId" INTEGER NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "Agent_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "ChangeRequest" (
"id" SERIAL NOT NULL,
"publicId" TEXT NOT NULL,
"title" TEXT NOT NULL,
"description" TEXT,
"changes" JSONB NOT NULL,
"rawChanges" JSONB NOT NULL,
"metadata" JSONB,
"contentHash" TEXT NOT NULL,
"state" "RequestState" NOT NULL DEFAULT 'PENDING',
"expiresAt" TIMESTAMP(3) NOT NULL,
"comment" TEXT,
"decidedAt" TIMESTAMP(3),
"approverId" INTEGER,
"signature" TEXT,
"receiptIssuedAt" TIMESTAMP(3),
"consumedAt" TIMESTAMP(3),
"cancelledAt" TIMESTAMP(3),
"updateCount" INTEGER NOT NULL DEFAULT 0,
"resubmitted" BOOLEAN NOT NULL DEFAULT false,
"lastAgentUpdateAt" TIMESTAMP(3),
"agentId" INTEGER NOT NULL,
"userId" INTEGER NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "ChangeRequest_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Notification" (
"id" SERIAL NOT NULL,
"type" "NotificationType" NOT NULL,
"title" TEXT NOT NULL,
"message" TEXT NOT NULL,
"requestPublicId" TEXT,
"read" BOOLEAN NOT NULL DEFAULT false,
"userId" INTEGER NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "Notification_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "AuditLog" (
"id" SERIAL NOT NULL,
"action" TEXT NOT NULL,
"detail" TEXT,
"targetType" TEXT,
"targetId" TEXT,
"actorId" INTEGER,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "AuditLog_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE UNIQUE INDEX "User_username_key" ON "User"("username");
-- CreateIndex
CREATE UNIQUE INDEX "Session_hash_key" ON "Session"("hash");
-- CreateIndex
CREATE INDEX "Session_userId_idx" ON "Session"("userId");
-- CreateIndex
CREATE UNIQUE INDEX "Agent_apiKey_key" ON "Agent"("apiKey");
-- CreateIndex
CREATE INDEX "Agent_ownerId_idx" ON "Agent"("ownerId");
-- CreateIndex
CREATE UNIQUE INDEX "ChangeRequest_publicId_key" ON "ChangeRequest"("publicId");
-- CreateIndex
CREATE INDEX "ChangeRequest_userId_state_idx" ON "ChangeRequest"("userId", "state");
-- CreateIndex
CREATE INDEX "ChangeRequest_agentId_state_idx" ON "ChangeRequest"("agentId", "state");
-- CreateIndex
CREATE INDEX "ChangeRequest_createdAt_idx" ON "ChangeRequest"("createdAt");
-- CreateIndex
CREATE INDEX "Notification_userId_read_idx" ON "Notification"("userId", "read");
-- CreateIndex
CREATE INDEX "Notification_userId_createdAt_idx" ON "Notification"("userId", "createdAt");
-- CreateIndex
CREATE INDEX "AuditLog_createdAt_idx" ON "AuditLog"("createdAt");
-- CreateIndex
CREATE INDEX "AuditLog_actorId_idx" ON "AuditLog"("actorId");
-- AddForeignKey
ALTER TABLE "Session" ADD CONSTRAINT "Session_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Agent" ADD CONSTRAINT "Agent_ownerId_fkey" FOREIGN KEY ("ownerId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "ChangeRequest" ADD CONSTRAINT "ChangeRequest_approverId_fkey" FOREIGN KEY ("approverId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "ChangeRequest" ADD CONSTRAINT "ChangeRequest_agentId_fkey" FOREIGN KEY ("agentId") REFERENCES "Agent"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "ChangeRequest" ADD CONSTRAINT "ChangeRequest_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Notification" ADD CONSTRAINT "Notification_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "AuditLog" ADD CONSTRAINT "AuditLog_actorId_fkey" FOREIGN KEY ("actorId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
@@ -0,0 +1,3 @@
# Please do not edit this file manually
# It should be added in your version-control system (e.g., Git)
provider = "postgresql"
+214
View File
@@ -0,0 +1,214 @@
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
}
// ─────────────────────────────────────────────────────────────────────────────
// Enums
// ─────────────────────────────────────────────────────────────────────────────
enum UserRole {
ADMIN
USER
}
enum RequestState {
PENDING
CHANGES_REQUESTED
APPROVED
REJECTED
EXPIRED
CONSUMED
CANCELLED
}
enum NotificationType {
REQUEST_CREATED
REQUEST_UPDATED
REQUEST_APPROVED
REQUEST_REJECTED
CHANGES_REQUESTED
REQUEST_CONSUMED
REQUEST_CANCELLED
REQUEST_EXPIRED
AGENT_DISABLED
ADMIN_ACTION
SETTINGS_CHANGED
}
enum GlobalSettingType {
registration_enabled
requests_enabled
}
// ─────────────────────────────────────────────────────────────────────────────
// Models
// ─────────────────────────────────────────────────────────────────────────────
/// A global (admin-only) platform setting, keyed by type.
model GlobalSetting {
type GlobalSettingType @id
value String
updatedAt DateTime @updatedAt
}
/// A human account. The first registered user becomes ADMIN.
model User {
id Int @id @default(autoincrement())
/// Normalized (lowercased) username — enforces case-insensitive uniqueness.
username String @unique
/// Original-cased display handle shown in the UI.
displayName String
password String
role UserRole @default(USER)
// Optional TOTP two-factor auth
totpSecret String?
totpEnabled Boolean @default(false)
// Admin can disable a human account entirely
disabled Boolean @default(false)
// Auto-delete of old change requests (opt-in, min 7 days, default 30)
autoDeleteEnabled Boolean @default(false)
autoDeleteDays Int @default(30)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
sessions Session[]
agents Agent[]
changeRequests ChangeRequest[] @relation("Owner")
decisions ChangeRequest[] @relation("Approver")
notifications Notification[]
auditLogs AuditLog[] @relation("AuditActor")
}
/// A browser session for a human account (cookie-based auth).
model Session {
id Int @id @default(autoincrement())
hash String @unique
userId Int
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
@@index([userId])
}
/// An AGENT account. Fully managed by a human owner. Holds exactly one API key.
model Agent {
id Int @id @default(autoincrement())
name String
description String?
website String?
iconUrl String?
/// The single API key the agent authenticates with.
apiKey String @unique
disabled Boolean @default(false)
/// Max simultaneous pending requests (1..10, human-configurable, default 5).
maxPendingRequests Int @default(5)
ownerId Int
owner User @relation(fields: [ownerId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
changeRequests ChangeRequest[]
@@index([ownerId])
}
/// A structured change request submitted by an agent for human approval.
model ChangeRequest {
id Int @id @default(autoincrement())
/// Public UUID (v4) exposed to agents as request_id.
publicId String @unique @default(uuid())
title String
description String?
/// Normalized changes array (diffs normalized, canonical ordering).
changes Json
/// Original changes exactly as submitted (audit trail).
rawChanges Json
metadata Json?
/// SHA-256 hash over the canonical (title + description + normalized changes).
contentHash String
state RequestState @default(PENDING)
expiresAt DateTime
// Decision fields
comment String?
decidedAt DateTime?
approverId Int?
approver User? @relation("Approver", fields: [approverId], references: [id], onDelete: SetNull)
/// HMAC-SHA256 signature of the approval receipt (platform-signed decision).
signature String?
receiptIssuedAt DateTime?
consumedAt DateTime?
cancelledAt DateTime?
// Update tracking for the CHANGES_REQUESTED → resubmit loop
updateCount Int @default(0)
/// True after an agent resubmits following a CHANGES_REQUESTED decision.
resubmitted Boolean @default(false)
lastAgentUpdateAt DateTime?
agentId Int
agent Agent @relation(fields: [agentId], references: [id], onDelete: Cascade)
// The human who owns/reviews this request (the agent's owner at creation time).
userId Int
user User @relation("Owner", fields: [userId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([userId, state])
@@index([agentId, state])
@@index([createdAt])
}
/// An in-app notification for a human account.
model Notification {
id Int @id @default(autoincrement())
type NotificationType
title String
message String
/// Optional link to a change request (publicId).
requestPublicId String?
read Boolean @default(false)
userId Int
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
@@index([userId, read])
@@index([userId, createdAt])
}
/// An audit log entry. Records privileged/admin actions and payload views.
model AuditLog {
id Int @id @default(autoincrement())
action String
/// Human-readable detail / JSON string of context.
detail String?
/// Optional target references.
targetType String?
targetId String?
actorId Int?
actor User? @relation("AuditActor", fields: [actorId], references: [id], onDelete: SetNull)
createdAt DateTime @default(now())
@@index([createdAt])
@@index([actorId])
}