62 lines
2.9 KiB
TypeScript
62 lines
2.9 KiB
TypeScript
// SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0
|
|
// The real procedure/kernel/tenancy path over memory repositories. No live Cloud/provider claim.
|
|
import { type Actor, buildRegistry, Container, createCaller } from "@conusai-kit/core"
|
|
import { createMemoryDataSource, DATA_SOURCE, entitiesOf, SYSTEM_DATA } from "@conusai-kit/data"
|
|
import { createTenancyHooks, orgMemberships, TENANCY, tenancyModule, users } from "@conusai-kit/tenancy"
|
|
import { expect, it } from "vitest"
|
|
import { AGENT_MODULE_BASE } from "../module.shared.js"
|
|
|
|
it("an open stream observes membership revocation and reconnect is refused", async () => {
|
|
const registry = buildRegistry([tenancyModule, AGENT_MODULE_BASE])
|
|
const data = createMemoryDataSource({ entities: entitiesOf(registry, "postgres") })
|
|
const root = new Container()
|
|
root.value(DATA_SOURCE, data)
|
|
root.value(SYSTEM_DATA, data)
|
|
const caller = (actor: Actor) => {
|
|
const tenancy = createTenancyHooks({ data, registry })
|
|
const container = root.child()
|
|
container.value(TENANCY, tenancy)
|
|
return createCaller({ registry, container, tenancy }, { actor })
|
|
}
|
|
const user = async (subject: string) => {
|
|
const row = await data.global(users).insert({
|
|
issuer: "https://id.example.test",
|
|
subject,
|
|
email: `${subject}@example.test`,
|
|
displayName: subject,
|
|
locale: "en",
|
|
})
|
|
return { userId: row.id }
|
|
}
|
|
const owner = await user("owner")
|
|
const member = await user("reader")
|
|
const call = caller(owner)
|
|
const { orgId } = (await call.callByName("tenancy.org.create", { slug: "alpha", name: "Alpha" })) as { orgId: string }
|
|
await call.callByName("tenancy.workspace.create", { org: "alpha", slug: "work", name: "Work", visibility: "org" })
|
|
await call.callByName("tenancy.project.create", {
|
|
org: "alpha",
|
|
workspace: "work",
|
|
slug: "project",
|
|
name: "Project",
|
|
moduleKey: "agent",
|
|
})
|
|
await data.unitOfWork.run({ level: "org", actor: owner, orgId }, (tx) =>
|
|
tx.of(orgMemberships).insert({ userId: member.userId, role: "viewer" }),
|
|
)
|
|
const slugs = { org: "alpha", workspace: "work", project: "project" }
|
|
const run = (await call.callByName("agent.run.start", {
|
|
...slugs,
|
|
goal: "Synthetic run",
|
|
plan: [{ key: "read", label: "Read", tool: "records.read", args: {} }],
|
|
})) as { runId: string }
|
|
const response = (await caller(member).callByName("agent.run.events", { ...slugs, runId: run.runId })) as Response
|
|
if (!response.body) throw new Error("expected a streamed response")
|
|
const reader = response.body.getReader()
|
|
expect(new TextDecoder().decode((await reader.read()).value)).toContain("RUN_STARTED")
|
|
await caller(owner).callByName("tenancy.member.remove", { org: "alpha", userId: member.userId })
|
|
expect(await reader.read()).toEqual({ done: true, value: undefined })
|
|
await expect(caller(member).callByName("agent.run.events", { ...slugs, runId: run.runId })).rejects.toMatchObject({
|
|
status: 404,
|
|
})
|
|
})
|