docs: registrar fluxo do updater e atualizar chaves

This commit is contained in:
Esdras Renan 2025-10-12 04:06:29 -03:00
parent 206d00700e
commit b5fd920efd
50 changed files with 980 additions and 93 deletions

View file

@ -9,6 +9,7 @@ import type { MutationCtx } from "./_generated/server"
const DEFAULT_TENANT_ID = "tenant-atlas"
const DEFAULT_TOKEN_TTL_MS = 1000 * 60 * 60 * 24 * 30 // 30 dias
const ALLOWED_MACHINE_PERSONAS = new Set(["collaborator", "manager"])
type NormalizedIdentifiers = {
macs: string[]
@ -327,6 +328,11 @@ export const register = mutation({
updatedAt: now,
status: "online",
registeredBy: args.registeredBy ?? existing.registeredBy,
persona: existing.persona,
assignedUserId: existing.assignedUserId,
assignedUserEmail: existing.assignedUserEmail,
assignedUserName: existing.assignedUserName,
assignedUserRole: existing.assignedUserRole,
})
machineId = existing._id
} else {
@ -347,6 +353,11 @@ export const register = mutation({
createdAt: now,
updatedAt: now,
registeredBy: args.registeredBy,
persona: undefined,
assignedUserId: undefined,
assignedUserEmail: undefined,
assignedUserName: undefined,
assignedUserRole: undefined,
})
}
@ -447,6 +458,11 @@ export const upsertInventory = mutation({
updatedAt: now,
status: args.metrics ? "online" : existing.status ?? "unknown",
registeredBy: args.registeredBy ?? existing.registeredBy,
persona: existing.persona,
assignedUserId: existing.assignedUserId,
assignedUserEmail: existing.assignedUserEmail,
assignedUserName: existing.assignedUserName,
assignedUserRole: existing.assignedUserRole,
})
machineId = existing._id
} else {
@ -467,6 +483,11 @@ export const upsertInventory = mutation({
createdAt: now,
updatedAt: now,
registeredBy: args.registeredBy,
persona: undefined,
assignedUserId: undefined,
assignedUserEmail: undefined,
assignedUserName: undefined,
assignedUserRole: undefined,
})
}
@ -570,6 +591,11 @@ export const resolveToken = mutation({
architecture: machine.architecture,
authUserId: machine.authUserId,
authEmail: machine.authEmail,
persona: machine.persona ?? null,
assignedUserId: machine.assignedUserId ?? null,
assignedUserEmail: machine.assignedUserEmail ?? null,
assignedUserName: machine.assignedUserName ?? null,
assignedUserRole: machine.assignedUserRole ?? null,
status: machine.status,
lastHeartbeatAt: machine.lastHeartbeatAt,
metadata: machine.metadata,
@ -646,6 +672,11 @@ export const listByTenant = query({
serialNumbers: machine.serialNumbers,
authUserId: machine.authUserId ?? null,
authEmail: machine.authEmail ?? null,
persona: machine.persona ?? null,
assignedUserId: machine.assignedUserId ?? null,
assignedUserEmail: machine.assignedUserEmail ?? null,
assignedUserName: machine.assignedUserName ?? null,
assignedUserRole: machine.assignedUserRole ?? null,
status: derivedStatus,
lastHeartbeatAt: machine.lastHeartbeatAt ?? null,
heartbeatAgeMs: machine.lastHeartbeatAt ? now - machine.lastHeartbeatAt : null,
@ -669,6 +700,140 @@ export const listByTenant = query({
},
})
export const updatePersona = mutation({
args: {
machineId: v.id("machines"),
persona: v.optional(v.string()),
assignedUserId: v.optional(v.id("users")),
assignedUserEmail: v.optional(v.string()),
assignedUserName: v.optional(v.string()),
assignedUserRole: v.optional(v.string()),
},
handler: async (ctx, args) => {
const machine = await ctx.db.get(args.machineId)
if (!machine) {
throw new ConvexError("Máquina não encontrada")
}
let nextPersona = machine.persona ?? undefined
const personaProvided = args.persona !== undefined
if (args.persona !== undefined) {
const trimmed = args.persona.trim().toLowerCase()
if (!trimmed) {
nextPersona = undefined
} else if (!ALLOWED_MACHINE_PERSONAS.has(trimmed)) {
throw new ConvexError("Perfil inválido para a máquina")
} else {
nextPersona = trimmed
}
}
let nextAssignedUserId = machine.assignedUserId ?? undefined
if (args.assignedUserId !== undefined) {
nextAssignedUserId = args.assignedUserId
}
let nextAssignedEmail = machine.assignedUserEmail ?? undefined
if (args.assignedUserEmail !== undefined) {
const trimmedEmail = args.assignedUserEmail.trim().toLowerCase()
nextAssignedEmail = trimmedEmail || undefined
}
let nextAssignedName = machine.assignedUserName ?? undefined
if (args.assignedUserName !== undefined) {
const trimmedName = args.assignedUserName.trim()
nextAssignedName = trimmedName || undefined
}
let nextAssignedRole = machine.assignedUserRole ?? undefined
if (args.assignedUserRole !== undefined) {
const trimmedRole = args.assignedUserRole.trim().toUpperCase()
nextAssignedRole = trimmedRole || undefined
}
if (nextPersona && !nextAssignedUserId) {
throw new ConvexError("Associe um usuário ao definir a persona da máquina")
}
if (nextAssignedUserId) {
const assignedUser = await ctx.db.get(nextAssignedUserId)
if (!assignedUser) {
throw new ConvexError("Usuário vinculado não encontrado")
}
if (assignedUser.tenantId !== machine.tenantId) {
throw new ConvexError("Usuário vinculado pertence a outro tenant")
}
}
let nextMetadata = machine.metadata
if (nextPersona) {
const collaboratorMeta = {
email: nextAssignedEmail ?? null,
name: nextAssignedName ?? null,
role: nextPersona,
}
nextMetadata = mergeMetadata(machine.metadata, { collaborator: collaboratorMeta })
}
const patch: Record<string, unknown> = {
persona: nextPersona,
assignedUserId: nextPersona ? nextAssignedUserId : undefined,
assignedUserEmail: nextPersona ? nextAssignedEmail : undefined,
assignedUserName: nextPersona ? nextAssignedName : undefined,
assignedUserRole: nextPersona ? nextAssignedRole : undefined,
updatedAt: Date.now(),
}
if (nextMetadata !== machine.metadata) {
patch.metadata = nextMetadata
}
if (personaProvided) {
patch.persona = nextPersona
}
if (nextPersona) {
patch.assignedUserId = nextAssignedUserId
patch.assignedUserEmail = nextAssignedEmail
patch.assignedUserName = nextAssignedName
patch.assignedUserRole = nextAssignedRole
} else if (personaProvided) {
patch.assignedUserId = undefined
patch.assignedUserEmail = undefined
patch.assignedUserName = undefined
patch.assignedUserRole = undefined
}
await ctx.db.patch(machine._id, patch)
return { ok: true, persona: nextPersona ?? null }
},
})
export const getContext = query({
args: {
machineId: v.id("machines"),
},
handler: async (ctx, args) => {
const machine = await ctx.db.get(args.machineId)
if (!machine) {
throw new ConvexError("Máquina não encontrada")
}
return {
id: machine._id,
tenantId: machine.tenantId,
companyId: machine.companyId ?? null,
companySlug: machine.companySlug ?? null,
persona: machine.persona ?? null,
assignedUserId: machine.assignedUserId ?? null,
assignedUserEmail: machine.assignedUserEmail ?? null,
assignedUserName: machine.assignedUserName ?? null,
assignedUserRole: machine.assignedUserRole ?? null,
metadata: machine.metadata ?? null,
authEmail: machine.authEmail ?? null,
}
},
})
export const linkAuthAccount = mutation({
args: {
machineId: v.id("machines"),
@ -710,7 +875,7 @@ export const rename = mutation({
throw new ConvexError("Acesso negado ao tenant da máquina")
}
const normalizedRole = (viewer.role ?? "AGENT").toUpperCase()
const STAFF = new Set(["ADMIN", "MANAGER", "AGENT", "COLLABORATOR"])
const STAFF = new Set(["ADMIN", "MANAGER", "AGENT"])
if (!STAFF.has(normalizedRole)) {
throw new ConvexError("Apenas equipe interna pode renomear máquinas")
}
@ -741,7 +906,7 @@ export const remove = mutation({
throw new ConvexError("Acesso negado ao tenant da máquina")
}
const role = (actor.role ?? "AGENT").toUpperCase()
const STAFF = new Set(["ADMIN", "MANAGER", "AGENT", "COLLABORATOR"])
const STAFF = new Set(["ADMIN", "MANAGER", "AGENT"])
if (!STAFF.has(role)) {
throw new ConvexError("Apenas equipe interna pode excluir máquinas")
}