server/db/schema/agent-identity-tables.ts
Rama main · réplica de lectura del repositorio original.
import { sql } from 'drizzle-orm'
import { check, index, integer, sqliteTable, text, uniqueIndex } from 'drizzle-orm/sqlite-core'
import { agent } from './agent-tables'
import { user } from './auth-tables'
export const agentIdentity = sqliteTable(
'agent_identity',
{
id: text('id').primaryKey(),
issuer: text('issuer').notNull(),
subject: text('subject').notNull(),
username: text('username'),
name: text('name').notNull(),
runtime: text('runtime'),
ownerUserId: text('owner_user_id')
.notNull()
.references(() => user.id, { onDelete: 'restrict' }),
status: text('status', { enum: ['active', 'inactive'] })
.notNull()
.default('active'),
deletedAt: integer('deleted_at', { mode: 'timestamp_ms' }),
createdAt: integer('created_at', { mode: 'timestamp_ms' }).notNull(),
updatedAt: integer('updated_at', { mode: 'timestamp_ms' }).notNull(),
},
(table) => [
// Stable Agent identities are historical principals and must never be reassigned after deletion.
uniqueIndex('agentIdentity_issuer_subject_unique').on(table.issuer, table.subject),
uniqueIndex('agentIdentity_username_unique').on(table.username).where(sql`${table.username} is not null`),
index('agentIdentity_ownerUserId_idx').on(table.ownerUserId),
index('agentIdentity_status_idx').on(table.status),
index('agentIdentity_deletedAt_idx').on(table.deletedAt),
],
)
export const agentIdentityBinding = sqliteTable(
'agent_identity_binding',
{
id: text('id').primaryKey(),
agentIdentityId: text('agent_identity_id')
.notNull()
.references(() => agentIdentity.id, { onDelete: 'restrict' }),
protocolAgentId: text('protocol_agent_id')
.notNull()
.references(() => agent.id, { onDelete: 'restrict' }),
status: text('status').notNull().default('active'),
boundAt: integer('bound_at', { mode: 'timestamp_ms' }).notNull(),
revokedAt: integer('revoked_at', { mode: 'timestamp_ms' }),
createdAt: integer('created_at', { mode: 'timestamp_ms' }).notNull(),
updatedAt: integer('updated_at', { mode: 'timestamp_ms' }).notNull(),
},
(table) => [
uniqueIndex('agentIdentityBinding_protocolAgentId_unique').on(table.protocolAgentId),
index('agentIdentityBinding_agentIdentityId_idx').on(table.agentIdentityId),
index('agentIdentityBinding_status_idx').on(table.status),
],
)
export const agentApplicationCreation = sqliteTable(
'agent_application_creation',
{
id: text('id').primaryKey(),
// The authenticated Application identifier is an immutable invocation-boundary value, not an Application row FK.
applicationId: text('application_id').notNull(),
actorUserId: text('actor_user_id')
.notNull()
.references(() => user.id, { onDelete: 'restrict' }),
idempotencyKey: text('idempotency_key').notNull(),
requestFingerprint: text('request_fingerprint').notNull(),
agentIdentityId: text('agent_identity_id')
.notNull()
.references(() => agentIdentity.id, { onDelete: 'restrict' }),
createdAt: integer('created_at', { mode: 'timestamp_ms' }).notNull(),
},
(table) => [
uniqueIndex('agentApplicationCreation_applicationActorKey_unique').on(
table.applicationId,
table.actorUserId,
table.idempotencyKey,
),
uniqueIndex('agentApplicationCreation_agentIdentityId_unique').on(table.agentIdentityId),
],
)
export const agentEnrollmentIntent = sqliteTable(
'agent_enrollment_intent',
{
id: text('id').primaryKey(),
agentIdentityId: text('agent_identity_id').references(() => agentIdentity.id, { onDelete: 'restrict' }),
requestedName: text('requested_name'),
requestedUsername: text('requested_username'),
requestedRuntime: text('requested_runtime'),
ownerUserId: text('owner_user_id')
.notNull()
.references(() => user.id, { onDelete: 'restrict' }),
protocolAgentId: text('protocol_agent_id')
.notNull()
.references(() => agent.id, { onDelete: 'restrict' }),
idempotencyKey: text('idempotency_key'),
status: text('status').notNull().default('pending'),
createdByUserId: text('created_by_user_id')
.notNull()
.references(() => user.id, { onDelete: 'restrict' }),
approvedByUserId: text('approved_by_user_id').references(() => user.id, { onDelete: 'restrict' }),
expiresAt: integer('expires_at', { mode: 'timestamp_ms' }).notNull(),
approvedAt: integer('approved_at', { mode: 'timestamp_ms' }),
createdAt: integer('created_at', { mode: 'timestamp_ms' }).notNull(),
updatedAt: integer('updated_at', { mode: 'timestamp_ms' }).notNull(),
},
(table) => [
index('agentEnrollmentIntent_agentIdentityId_idx').on(table.agentIdentityId),
index('agentEnrollmentIntent_protocolAgentId_idx').on(table.protocolAgentId),
uniqueIndex('agentEnrollmentIntent_protocolAgentIdempotencyKey_uidx')
.on(table.protocolAgentId, table.idempotencyKey)
.where(sql`${table.idempotencyKey} is not null`),
index('agentEnrollmentIntent_status_idx').on(table.status),
index('agentEnrollmentIntent_expiresAt_idx').on(table.expiresAt),
check(
'agentEnrollmentIntent_new_or_existing_identity_check',
sql`(${table.agentIdentityId} is not null) or ((${table.requestedName} is not null) and (${table.requestedUsername} is not null) and (${table.requestedRuntime} is not null))`,
),
],
)