auth-core-keys.ts142 lines · main
1/**
2 * briven-engine SDK keys API.
3 *
4 * Requires project admin (dashboard session or project API key).
5 */
6
7import { Hono } from 'hono';
8
9import { requireAuthCoreProject } from '../middleware/auth-core-guard.js';
10import { BRIVEN_ENGINE_ID } from '../services/auth-core/engine.js';
11import {
12 createAuthSdkKey,
13 listAuthSdkKeysForProject,
14 revokeAuthSdkKey,
15} from '../services/auth-sdk-keys.js';
16import type { AppEnv } from '../types/app-env.js';
17import type { User } from '../middleware/session.js';
18
19export const authCoreKeysRouter = new Hono<AppEnv>();
20
21authCoreKeysRouter.use(
22 '/v1/auth-core/projects/:projectId/keys',
23 ...requireAuthCoreProject('admin'),
24);
25authCoreKeysRouter.use(
26 '/v1/auth-core/projects/:projectId/keys/*',
27 ...requireAuthCoreProject('admin'),
28);
29
30authCoreKeysRouter.get('/v1/auth-core/projects/:projectId/keys', async (c) => {
31 const projectId = c.req.param('projectId');
32 try {
33 const keys = await listAuthSdkKeysForProject(projectId);
34 return c.json({
35 engine: BRIVEN_ENGINE_ID,
36 projectId,
37 keys: keys.map((k) => ({
38 id: k.id,
39 name: k.name,
40 hint: `${k.prefix}…${k.suffix}`,
41 scope: k.scope,
42 createdAt: k.createdAt,
43 lastUsedAt: k.lastUsedAt,
44 expiresAt: k.expiresAt,
45 revokedAt: k.revokedAt,
46 })),
47 });
48 } catch (err) {
49 return c.json(
50 {
51 engine: BRIVEN_ENGINE_ID,
52 code: 'list_failed',
53 message: err instanceof Error ? err.message : String(err),
54 },
55 500,
56 );
57 }
58});
59
60authCoreKeysRouter.post('/v1/auth-core/projects/:projectId/keys', async (c) => {
61 const projectId = c.req.param('projectId');
62 let body: { name?: string; scope?: string; createdBy?: string } = {};
63 try {
64 body = await c.req.json();
65 } catch {
66 body = {};
67 }
68 if (!body.name?.trim()) {
69 return c.json(
70 { engine: BRIVEN_ENGINE_ID, code: 'name_required' },
71 400,
72 );
73 }
74 const user = c.get('user') as User | null;
75 const createdBy = user?.id;
76 if (!createdBy) {
77 return c.json(
78 {
79 engine: BRIVEN_ENGINE_ID,
80 code: 'unauthorized',
81 message: 'dashboard session required to mint keys',
82 },
83 401,
84 );
85 }
86 try {
87 const created = await createAuthSdkKey({
88 projectId,
89 createdBy,
90 name: body.name,
91 scope: (body.scope as 'read' | 'read-write' | 'admin') ?? 'read',
92 });
93 return c.json({
94 engine: BRIVEN_ENGINE_ID,
95 projectId,
96 key: {
97 id: created.record.id,
98 name: created.record.name,
99 scope: created.record.scope,
100 hint: `${created.record.prefix}…${created.record.suffix}`,
101 /** Only returned once at creation */
102 plaintext: created.plaintext,
103 },
104 note: 'Copy the plaintext now — it is not shown again.',
105 });
106 } catch (err) {
107 return c.json(
108 {
109 engine: BRIVEN_ENGINE_ID,
110 code: 'create_failed',
111 message: err instanceof Error ? err.message : String(err),
112 },
113 400,
114 );
115 }
116});
117
118authCoreKeysRouter.delete(
119 '/v1/auth-core/projects/:projectId/keys/:keyId',
120 async (c) => {
121 const projectId = c.req.param('projectId');
122 const keyId = c.req.param('keyId');
123 try {
124 await revokeAuthSdkKey(projectId, keyId);
125 return c.json({
126 engine: BRIVEN_ENGINE_ID,
127 ok: true,
128 projectId,
129 keyId,
130 });
131 } catch (err) {
132 return c.json(
133 {
134 engine: BRIVEN_ENGINE_ID,
135 code: 'revoke_failed',
136 message: err instanceof Error ? err.message : String(err),
137 },
138 404,
139 );
140 }
141 },
142);