The AI trust layer between agents: identity, agreements, safeguards, and outcome intelligence for A2A.

Viewing files at commit 3dc3c2c6da63Commit detailsView latest

tests/api.test.ts 76 lines · 2.4 KB · typescript
1
import { describe, expect, it } from 'vitest';
2
import { buildApi } from '../apps/api/src/app.js';
3
4
describe('HTTP API', () => {
5
  it('serves health, readiness, and OpenAPI', async () => {
6
    const app = buildApi();
7
    await app.ready();
8
    expect((await app.inject({ method: 'GET', url: '/health' })).statusCode).toBe(200);
9
    expect((await app.inject({ method: 'GET', url: '/ready' })).json()).toEqual({
10
      status: 'ready',
11
    });
12
    const specification = (await app.inject({ method: 'GET', url: '/openapi.json' })).json();
13
    expect(specification.info.title).toBe('OpenClasp API');
14
    expect(specification.paths).toHaveProperty('/v0.1/risk/assess');
15
    await app.close();
16
  });
17
18
  it('isolates hosted dashboard and settings by authenticated operator', async () => {
19
    const calls: string[] = [];
20
    const repository = {
21
      dashboard: async (operatorId: string) => {
22
        calls.push(`dashboard:${operatorId}`);
23
        return {
24
          agents: [],
25
          projects: [],
26
          installations: [],
27
          setupRequests: [],
28
          interactions: [],
29
          events: [],
30
          conflicts: [],
31
          receipts: [],
32
          profiles: [],
33
        };
34
      },
35
      getSettings: async (operatorId: string) => {
36
        calls.push(`settings:${operatorId}`);
37
        return {
38
          displayName: '',
39
          contributionEnabled: false,
40
          retentionDays: 30,
41
          evidenceSharing: 'ask' as const,
42
          rawConversationsStored: false as const,
43
        };
44
      },
45
      saveSettings: async (operatorId: string, value: any) => {
46
        calls.push(`save:${operatorId}`);
47
        return { ...value, rawConversationsStored: false as const };
48
      },
49
      upsert: async () => undefined,
50
      list: async () => [],
51
    };
52
    const app = buildApi(undefined, undefined, repository);
53
    await app.ready();
54
    expect((await app.inject({ method: 'GET', url: '/v0.1/dashboard' })).statusCode).toBe(401);
55
    expect(
56
      (
57
        await app.inject({
58
          method: 'GET',
59
          url: '/v0.1/dashboard',
60
          headers: { 'x-openclasp-operator': 'user-a' },
61
        })
62
      ).statusCode,
63
    ).toBe(200);
64
    expect(
65
      (
66
        await app.inject({
67
          method: 'GET',
68
          url: '/v0.1/settings',
69
          headers: { 'x-openclasp-operator': 'user-b' },
70
        })
71
      ).statusCode,
72
    ).toBe(200);
73
    expect(calls).toEqual(['dashboard:user-a', 'settings:user-b']);
74
    await app.close();
75
  });
76
});