mirror of
https://github.com/saltbo/agent-kanban.git
synced 2026-09-19 09:01:47 +08:00
96fdd70d2c
* feat(api)!: redesign task resource operations
Publish the complete resource-oriented OpenAPI contract, enforce scope-based authorization at the HTTP boundary, and replace lifecycle command routes with Task PATCH and nested Claim/Event resources.
Add server-side Task CAS, migration coverage, updated Agent Skills, and browser/API regression tests.
BREAKING CHANGE: remove the legacy task lifecycle endpoints and move bounded waits to /tasks/{taskId}/events.
* refactor(tasks)!: make claims create-only
Remove Task Claim retrieval and deletion routes, the release scope, live deletion logic, and release workflow guidance.
Keep historical release records readable for migration and audit compatibility.
BREAKING CHANGE: remove GET and DELETE /tasks/{taskId}/claims/{claimId} and the task:release scope.
* test(ci): align actor and projection contracts
Cover machine and service Task Action writes and update Agent detail fixtures to the canonical assignedTo query and paged lowerCamelCase response.
* fix(api): preserve merge patch fields and consume browser pagination
* test(ui): include terminal pagination in agent task fixture
---------
Co-authored-by: jarvis <jarvis@agents.realmroot.dev>
48 lines
1.7 KiB
TypeScript
48 lines
1.7 KiB
TypeScript
import { describe, expect, it, vi } from "vitest";
|
|
|
|
const authenticateRealmrootToken = vi.hoisted(() => vi.fn());
|
|
|
|
vi.mock("../../../server/auth/realmroot", async (importOriginal) => ({
|
|
...(await importOriginal<typeof import("../../../server/auth/realmroot")>()),
|
|
authenticateRealmrootToken,
|
|
}));
|
|
|
|
import { authenticationMiddleware, principalProvisioningMiddleware } from "../../../server/auth/middleware";
|
|
|
|
describe("authentication middleware boundaries", () => {
|
|
it("establishes the principal without provisioning it, then provisions in the independent middleware", async () => {
|
|
const principal = {
|
|
source: "token",
|
|
type: "human",
|
|
subjectId: "human-subject",
|
|
tenantId: "tenant-1",
|
|
scopes: ["board:read"],
|
|
};
|
|
authenticateRealmrootToken.mockResolvedValue(principal);
|
|
const batch = vi.fn(async () => []);
|
|
const statement = { bind: vi.fn(() => statement) };
|
|
const values: Record<string, unknown> = {};
|
|
const context = {
|
|
env: { DB: { prepare: vi.fn(() => statement), batch } },
|
|
req: { header: (name: string) => (name.toLowerCase() === "authorization" ? "DPoP access-token" : undefined) },
|
|
set: (key: string, value: unknown) => {
|
|
values[key] = value;
|
|
},
|
|
get: (key: string) => values[key],
|
|
} as Parameters<typeof authenticationMiddleware>[0];
|
|
const next = vi.fn(async () => undefined);
|
|
|
|
await authenticationMiddleware(context, next);
|
|
|
|
expect(values).toMatchObject({ principal, ownerId: "tenant-1" });
|
|
expect(batch).not.toHaveBeenCalled();
|
|
expect(next).toHaveBeenCalledOnce();
|
|
|
|
next.mockClear();
|
|
await principalProvisioningMiddleware(context, next);
|
|
|
|
expect(batch).toHaveBeenCalledOnce();
|
|
expect(next).toHaveBeenCalledOnce();
|
|
});
|
|
});
|