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

Viewing files at commit 6450fe9d331dCommit detailsView latest

api/index.ts 48 lines · 2.1 KB · typescript
1
import type { IncomingMessage, ServerResponse } from 'node:http';
2
import descopeSdk from '@descope/node-sdk';
3
import { buildApi } from '../apps/api/src/app.js';
4
import { TrustEngine } from '../packages/core/src/index.js';
5
import { HostedRepository } from '../packages/persistence/src/hosted.js';
6
7
const databaseUrl = process.env.DATABASE_URL;
8
const repository = databaseUrl ? new HostedRepository(databaseUrl) : undefined;
9
const app = buildApi(new TrustEngine(), undefined, repository);
10
const ready = app.ready();
11
12
export default async function handler(request: IncomingMessage, response: ServerResponse) {
13
  const incoming = new URL(request.url ?? '/', 'https://openclasp.local');
14
  const target = incoming.searchParams.get('path');
15
  if (target) request.url = target;
16
  if ((request.url ?? '').startsWith('/v0.1/')) {
17
    const projectId = process.env.DESCOPE_PROJECT_ID ?? process.env.NEXT_PUBLIC_DESCOPE_PROJECT_ID;
18
    const authorization = request.headers.authorization;
19
    const token = authorization?.startsWith('Bearer ') ? authorization.slice(7) : undefined;
20
    if (!projectId || !token) {
21
      response.statusCode = 401;
22
      response.setHeader('content-type', 'application/json');
23
      response.end(JSON.stringify({ error: 'authentication_required' }));
24
      return;
25
    }
26
    try {
27
      const authentication = await descopeSdk({ projectId }).validateSession(token, {
28
        audience: projectId,
29
      });
30
      const operatorId = authentication.token.sub;
31
      if (!operatorId) throw new Error('Session has no subject');
32
      request.headers['x-openclasp-operator'] = operatorId;
33
      request.headers['x-openclasp-email'] = encodeURIComponent(
34
        String(authentication.token.email ?? ''),
35
      );
36
      request.headers['x-openclasp-name'] = encodeURIComponent(
37
        String(authentication.token.name ?? ''),
38
      );
39
    } catch {
40
      response.statusCode = 401;
41
      response.setHeader('content-type', 'application/json');
42
      response.end(JSON.stringify({ error: 'invalid_session' }));
43
      return;
44
    }
45
  }
46
  await ready;
47
  app.server.emit('request', request, response);
48
}