AI Connect/Integration/Padrões Multi-Tenant
Padrões Multi-Tenant
Um único cliente com escopo na aplicação, escopo resolvido antes da entrada da requisição, capacidades retornadas apenas para o usuário autenticado e uma fronteira de isolamento que você pode testar.
Um único cliente Vinkius atende todos os usuários da sua aplicação. O isolamento vem de como você deriva o externalId, não de instâncias de cliente. Esta página é o checklist de segurança para integrar o SDK a um backend multi-tenant.
A Vinkius nunca encontra os seus usuários reais. A plataforma conhece a sua Application e o identificador opaco que o seu backend repassa, nada além disso. E-mails, nomes e perfis ficam nos seus sistemas; a Vinkius vê apenas o escopo do usuário que o seu código resolveu.
Crie um cliente com escopo na aplicação
// lib/vinkius.ts — server only
import { Vinkius } from '@vinkius/connect';
export const vinkius = new Vinkius({
appId: process.env.VINKIUS_APP_ID!,
apiKey: process.env.VINKIUS_APP_KEY!,
});O cliente mantém credenciais da aplicação, nunca estado por usuário. Não construa um cliente por usuário; o escopo do usuário viaja na rota.
Resolva o escopo antes de ler a entrada da requisição
Vincule o externalId à sua sessão autenticada antes de qualquer outra coisa. A fronteira de autorização é a sua consulta de sessão; um App ID e uma chave autorizam a aplicação, nunca um usuário do navegador:
async function handleCapabilities(request: Request) {
const session = await requireSession(request); // your auth code
const capabilities = await vinkius.user(session.userId).capabilities();
// ...
}Retorne apenas as capacidades do usuário autenticado
Projete apenas os campos de que o seu cliente precisa e nada mais. Os objetos de capacidade já têm o escopo do usuário resolvido pela sessão:
return Response.json(
capabilities.map(({ name, description, inputSchema }) => ({
name,
description,
inputSchema,
})),
);Autorize a configuração do conector separadamente
Gravar credenciais é uma operação privilegiada. Verifique que a sessão tem permissão para administrar o conector daquele usuário antes de chamar connect() e credentials.set():
const github = vinkius.user(session.userId).connector('github');
await github.connect();
await github.credentials.set({ GITHUB_TOKEN: submittedToken });Execute apenas capacidades carregadas no mesmo escopo
As capacidades carregam a rota de conexão que as produziu. Nunca aceite um nome de capacidade do cliente e o execute contra um handle resolvido de outro escopo; carregue o conjunto de capacidades dentro da requisição autenticada e despache a partir dele:
const capabilities = await vinkius.user(session.userId).capabilities();
const capability = capabilities.findCapability(requestedName);
if (!capability) {
return Response.json({ error: 'not available for this user' }, { status: 404 });
}
const result = await capability.execute(args, { idempotencyKey });Use metadados somente para contexto não secreto da aplicação
user.ensure(metadata) executa o upsert do usuário e armazena contexto da aplicação, como nível de plano ou rótulos. Não é um cofre de credenciais; mantenha segredos nas credenciais de conectores, que são somente para escrita.
Teste a fronteira de isolamento
Dois usuários conectando o mesmo conector jamais devem ver o estado um do outro. Um formato mínimo de teste:
const alice = vinkius.user('alice_123');
const bob = vinkius.user('bob_456');
await alice.connector('github').connect();
const bobConnectors = await bob.connectors();
// bob's list must not contain alice's connectionExecute isso contra um ambiente de staging com o seu próprio App ID e chave. Consulte Authentication and scope para as regras de separação de ambientes.
