@elaraai/e3-api-server 0.0.2-beta.12 → 0.0.2-beta.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +144 -29
- package/dist/src/async-operation-state.d.ts +63 -0
- package/dist/src/async-operation-state.d.ts.map +1 -0
- package/dist/src/async-operation-state.js +193 -0
- package/dist/src/async-operation-state.js.map +1 -0
- package/dist/src/auth/device.d.ts +26 -0
- package/dist/src/auth/device.d.ts.map +1 -0
- package/dist/src/auth/device.js +227 -0
- package/dist/src/auth/device.js.map +1 -0
- package/dist/src/auth/discovery.d.ts +23 -0
- package/dist/src/auth/discovery.d.ts.map +1 -0
- package/dist/src/auth/discovery.js +40 -0
- package/dist/src/auth/discovery.js.map +1 -0
- package/dist/src/auth/index.d.ts +56 -0
- package/dist/src/auth/index.d.ts.map +1 -0
- package/dist/src/auth/index.js +69 -0
- package/dist/src/auth/index.js.map +1 -0
- package/dist/src/auth/keys.d.ts +55 -0
- package/dist/src/auth/keys.d.ts.map +1 -0
- package/dist/src/auth/keys.js +78 -0
- package/dist/src/auth/keys.js.map +1 -0
- package/dist/src/beast2.d.ts +15 -3
- package/dist/src/beast2.d.ts.map +1 -1
- package/dist/src/beast2.js +30 -4
- package/dist/src/beast2.js.map +1 -1
- package/dist/src/cli.js +58 -6
- package/dist/src/cli.js.map +1 -1
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/errors.js +5 -2
- package/dist/src/errors.js.map +1 -1
- package/dist/src/execution-state.d.ts +54 -0
- package/dist/src/execution-state.d.ts.map +1 -0
- package/dist/src/execution-state.js +150 -0
- package/dist/src/execution-state.js.map +1 -0
- package/dist/src/handlers/dataflow.d.ts +49 -0
- package/dist/src/handlers/dataflow.d.ts.map +1 -0
- package/dist/src/handlers/dataflow.js +371 -0
- package/dist/src/handlers/dataflow.js.map +1 -0
- package/dist/src/handlers/datasets.d.ts +23 -0
- package/dist/src/handlers/datasets.d.ts.map +1 -0
- package/dist/src/handlers/datasets.js +113 -0
- package/dist/src/handlers/datasets.js.map +1 -0
- package/dist/src/handlers/index.d.ts +12 -0
- package/dist/src/handlers/index.d.ts.map +1 -0
- package/dist/src/handlers/index.js +12 -0
- package/dist/src/handlers/index.js.map +1 -0
- package/dist/src/handlers/packages.d.ts +26 -0
- package/dist/src/handlers/packages.d.ts.map +1 -0
- package/dist/src/handlers/packages.js +101 -0
- package/dist/src/handlers/packages.js.map +1 -0
- package/dist/src/handlers/repos.d.ts +11 -0
- package/dist/src/handlers/repos.d.ts.map +1 -0
- package/dist/src/handlers/repos.js +52 -0
- package/dist/src/handlers/repos.js.map +1 -0
- package/dist/src/handlers/repository.d.ts +35 -0
- package/dist/src/handlers/repository.d.ts.map +1 -0
- package/dist/src/handlers/repository.js +142 -0
- package/dist/src/handlers/repository.js.map +1 -0
- package/dist/src/handlers/tasks.d.ts +18 -0
- package/dist/src/handlers/tasks.d.ts.map +1 -0
- package/dist/src/handlers/tasks.js +134 -0
- package/dist/src/handlers/tasks.js.map +1 -0
- package/dist/src/handlers/workspaces.d.ts +34 -0
- package/dist/src/handlers/workspaces.d.ts.map +1 -0
- package/dist/src/handlers/workspaces.js +225 -0
- package/dist/src/handlers/workspaces.js.map +1 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +6 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/middleware/auth.d.ts +51 -0
- package/dist/src/middleware/auth.d.ts.map +1 -0
- package/dist/src/middleware/auth.js +158 -0
- package/dist/src/middleware/auth.js.map +1 -0
- package/dist/src/routes/datasets.d.ts +2 -1
- package/dist/src/routes/datasets.d.ts.map +1 -1
- package/dist/src/routes/datasets.js +50 -85
- package/dist/src/routes/datasets.js.map +1 -1
- package/dist/src/routes/executions.d.ts +2 -1
- package/dist/src/routes/executions.d.ts.map +1 -1
- package/dist/src/routes/executions.js +60 -286
- package/dist/src/routes/executions.js.map +1 -1
- package/dist/src/routes/index.d.ts +11 -0
- package/dist/src/routes/index.d.ts.map +1 -0
- package/dist/src/routes/index.js +11 -0
- package/dist/src/routes/index.js.map +1 -0
- package/dist/src/routes/packages.d.ts +2 -1
- package/dist/src/routes/packages.d.ts.map +1 -1
- package/dist/src/routes/packages.js +42 -105
- package/dist/src/routes/packages.js.map +1 -1
- package/dist/src/routes/repository.d.ts +2 -1
- package/dist/src/routes/repository.d.ts.map +1 -1
- package/dist/src/routes/repository.js +19 -54
- package/dist/src/routes/repository.js.map +1 -1
- package/dist/src/routes/tasks.d.ts +2 -1
- package/dist/src/routes/tasks.d.ts.map +1 -1
- package/dist/src/routes/tasks.js +22 -46
- package/dist/src/routes/tasks.js.map +1 -1
- package/dist/src/routes/workspaces.d.ts +2 -1
- package/dist/src/routes/workspaces.d.ts.map +1 -1
- package/dist/src/routes/workspaces.js +45 -116
- package/dist/src/routes/workspaces.js.map +1 -1
- package/dist/src/server.d.ts +24 -3
- package/dist/src/server.d.ts.map +1 -1
- package/dist/src/server.js +178 -19
- package/dist/src/server.js.map +1 -1
- package/dist/src/types.d.ts +486 -1
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js +209 -2
- package/dist/src/types.js.map +1 -1
- package/package.json +15 -3
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Licensed under BSL 1.1. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
import * as fs from 'node:fs/promises';
|
|
6
|
+
import * as os from 'node:os';
|
|
7
|
+
import * as path from 'node:path';
|
|
8
|
+
import { BlobType, NullType, some, none, variant } from '@elaraai/east';
|
|
9
|
+
import { ArrayType } from '@elaraai/east';
|
|
10
|
+
import { WorkspaceStateType, parsePackageRef } from '@elaraai/e3-types';
|
|
11
|
+
import { workspaceList, workspaceCreate, workspaceRemove, workspaceGetState, workspaceDeploy, workspaceExport, workspaceStatus, packageGetLatestVersion, } from '@elaraai/e3-core';
|
|
12
|
+
import { sendSuccess, sendError } from '../beast2.js';
|
|
13
|
+
import { errorToVariant } from '../errors.js';
|
|
14
|
+
import { WorkspaceInfoType, WorkspaceStatusResultType } from '../types.js';
|
|
15
|
+
/**
|
|
16
|
+
* List all workspaces in the repository.
|
|
17
|
+
*/
|
|
18
|
+
export async function listWorkspaces(storage, repoPath) {
|
|
19
|
+
try {
|
|
20
|
+
const workspaces = await workspaceList(storage, repoPath);
|
|
21
|
+
const result = await Promise.all(workspaces.map(async (name) => {
|
|
22
|
+
const state = await workspaceGetState(storage, repoPath, name);
|
|
23
|
+
if (state) {
|
|
24
|
+
return {
|
|
25
|
+
name,
|
|
26
|
+
deployed: true,
|
|
27
|
+
packageName: some(state.packageName),
|
|
28
|
+
packageVersion: some(state.packageVersion),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
return {
|
|
33
|
+
name,
|
|
34
|
+
deployed: false,
|
|
35
|
+
packageName: none,
|
|
36
|
+
packageVersion: none,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
}));
|
|
40
|
+
return sendSuccess(ArrayType(WorkspaceInfoType), result);
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
return sendError(ArrayType(WorkspaceInfoType), errorToVariant(err));
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Create a new workspace.
|
|
48
|
+
*/
|
|
49
|
+
export async function createWorkspace(storage, repoPath, name) {
|
|
50
|
+
try {
|
|
51
|
+
await workspaceCreate(storage, repoPath, name);
|
|
52
|
+
return sendSuccess(WorkspaceInfoType, {
|
|
53
|
+
name,
|
|
54
|
+
deployed: false,
|
|
55
|
+
packageName: none,
|
|
56
|
+
packageVersion: none,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
return sendError(WorkspaceInfoType, errorToVariant(err));
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Get workspace state.
|
|
65
|
+
*/
|
|
66
|
+
export async function getWorkspace(storage, repoPath, name) {
|
|
67
|
+
try {
|
|
68
|
+
const state = await workspaceGetState(storage, repoPath, name);
|
|
69
|
+
if (!state) {
|
|
70
|
+
return sendError(WorkspaceStateType, errorToVariant(new Error(`Workspace '${name}' is not deployed`)));
|
|
71
|
+
}
|
|
72
|
+
return sendSuccess(WorkspaceStateType, state);
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
return sendError(WorkspaceStateType, errorToVariant(err));
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Get comprehensive workspace status.
|
|
80
|
+
*/
|
|
81
|
+
export async function getWorkspaceStatus(storage, repoPath, name) {
|
|
82
|
+
try {
|
|
83
|
+
const status = await workspaceStatus(storage, repoPath, name);
|
|
84
|
+
// Convert numbers to bigints for BEAST2 serialization
|
|
85
|
+
const result = {
|
|
86
|
+
workspace: status.workspace,
|
|
87
|
+
lock: status.lock ? some({
|
|
88
|
+
pid: BigInt(status.lock.pid ?? 0),
|
|
89
|
+
acquiredAt: status.lock.acquiredAt,
|
|
90
|
+
bootId: status.lock.bootId ? some(status.lock.bootId) : none,
|
|
91
|
+
command: status.lock.command ? some(status.lock.command) : none,
|
|
92
|
+
}) : none,
|
|
93
|
+
datasets: status.datasets.map(d => ({
|
|
94
|
+
path: d.path,
|
|
95
|
+
status: convertDatasetStatus(d.status),
|
|
96
|
+
hash: d.hash ? some(d.hash) : none,
|
|
97
|
+
isTaskOutput: d.isTaskOutput,
|
|
98
|
+
producedBy: d.producedBy ? some(d.producedBy) : none,
|
|
99
|
+
})),
|
|
100
|
+
tasks: status.tasks.map(t => ({
|
|
101
|
+
name: t.name,
|
|
102
|
+
hash: t.hash,
|
|
103
|
+
status: convertTaskStatus(t.status),
|
|
104
|
+
inputs: t.inputs,
|
|
105
|
+
output: t.output,
|
|
106
|
+
dependsOn: t.dependsOn,
|
|
107
|
+
})),
|
|
108
|
+
summary: {
|
|
109
|
+
datasets: {
|
|
110
|
+
total: BigInt(status.summary.datasets.total),
|
|
111
|
+
unset: BigInt(status.summary.datasets.unset),
|
|
112
|
+
stale: BigInt(status.summary.datasets.stale),
|
|
113
|
+
upToDate: BigInt(status.summary.datasets.upToDate),
|
|
114
|
+
},
|
|
115
|
+
tasks: {
|
|
116
|
+
total: BigInt(status.summary.tasks.total),
|
|
117
|
+
upToDate: BigInt(status.summary.tasks.upToDate),
|
|
118
|
+
ready: BigInt(status.summary.tasks.ready),
|
|
119
|
+
waiting: BigInt(status.summary.tasks.waiting),
|
|
120
|
+
inProgress: BigInt(status.summary.tasks.inProgress),
|
|
121
|
+
failed: BigInt(status.summary.tasks.failed),
|
|
122
|
+
error: BigInt(status.summary.tasks.error),
|
|
123
|
+
staleRunning: BigInt(status.summary.tasks.staleRunning),
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
return sendSuccess(WorkspaceStatusResultType, result);
|
|
128
|
+
}
|
|
129
|
+
catch (err) {
|
|
130
|
+
return sendError(WorkspaceStatusResultType, errorToVariant(err));
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// Helper to convert dataset status to variant format
|
|
134
|
+
function convertDatasetStatus(status) {
|
|
135
|
+
switch (status.type) {
|
|
136
|
+
case 'unset': return variant('unset', null);
|
|
137
|
+
case 'stale': return variant('stale', null);
|
|
138
|
+
case 'up-to-date': return variant('up-to-date', null);
|
|
139
|
+
default: return variant('unset', null);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
// Helper to convert task status to variant format
|
|
143
|
+
function convertTaskStatus(status) {
|
|
144
|
+
switch (status.type) {
|
|
145
|
+
case 'up-to-date':
|
|
146
|
+
return variant('up-to-date', { cached: status.cached });
|
|
147
|
+
case 'ready':
|
|
148
|
+
return variant('ready', null);
|
|
149
|
+
case 'waiting':
|
|
150
|
+
return variant('waiting', { reason: status.reason });
|
|
151
|
+
case 'in-progress':
|
|
152
|
+
return variant('in-progress', {
|
|
153
|
+
pid: status.pid != null ? some(BigInt(status.pid)) : none,
|
|
154
|
+
startedAt: status.startedAt ? some(status.startedAt) : none,
|
|
155
|
+
});
|
|
156
|
+
case 'failed':
|
|
157
|
+
return variant('failed', {
|
|
158
|
+
exitCode: BigInt(status.exitCode),
|
|
159
|
+
completedAt: status.completedAt ? some(status.completedAt) : none,
|
|
160
|
+
});
|
|
161
|
+
case 'error':
|
|
162
|
+
return variant('error', {
|
|
163
|
+
message: status.message,
|
|
164
|
+
completedAt: status.completedAt ? some(status.completedAt) : none,
|
|
165
|
+
});
|
|
166
|
+
case 'stale-running':
|
|
167
|
+
return variant('stale-running', {
|
|
168
|
+
pid: status.pid != null ? some(BigInt(status.pid)) : none,
|
|
169
|
+
startedAt: status.startedAt ? some(status.startedAt) : none,
|
|
170
|
+
});
|
|
171
|
+
default:
|
|
172
|
+
return variant('ready', null);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Delete a workspace.
|
|
177
|
+
*/
|
|
178
|
+
export async function deleteWorkspace(storage, repoPath, name) {
|
|
179
|
+
try {
|
|
180
|
+
await workspaceRemove(storage, repoPath, name);
|
|
181
|
+
return sendSuccess(NullType, null);
|
|
182
|
+
}
|
|
183
|
+
catch (err) {
|
|
184
|
+
return sendError(NullType, errorToVariant(err));
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Deploy a package to a workspace.
|
|
189
|
+
*/
|
|
190
|
+
export async function deployWorkspace(storage, repoPath, workspace, packageRef) {
|
|
191
|
+
try {
|
|
192
|
+
const { name: pkgName, version: maybeVersion } = parsePackageRef(packageRef);
|
|
193
|
+
const pkgVersion = maybeVersion ?? await packageGetLatestVersion(storage, repoPath, pkgName);
|
|
194
|
+
if (!pkgVersion) {
|
|
195
|
+
return sendError(NullType, errorToVariant(new Error(`Package not found: ${pkgName}`)));
|
|
196
|
+
}
|
|
197
|
+
await workspaceDeploy(storage, repoPath, workspace, pkgName, pkgVersion);
|
|
198
|
+
return sendSuccess(NullType, null);
|
|
199
|
+
}
|
|
200
|
+
catch (err) {
|
|
201
|
+
return sendError(NullType, errorToVariant(err));
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Export a workspace as a zip archive.
|
|
206
|
+
*/
|
|
207
|
+
export async function exportWorkspace(storage, repoPath, workspace) {
|
|
208
|
+
try {
|
|
209
|
+
// Export to temp file
|
|
210
|
+
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'e3-ws-export-'));
|
|
211
|
+
const tempPath = path.join(tempDir, 'workspace.zip');
|
|
212
|
+
try {
|
|
213
|
+
await workspaceExport(storage, repoPath, workspace, tempPath);
|
|
214
|
+
const archive = await fs.readFile(tempPath);
|
|
215
|
+
return sendSuccess(BlobType, new Uint8Array(archive));
|
|
216
|
+
}
|
|
217
|
+
finally {
|
|
218
|
+
await fs.rm(tempDir, { recursive: true, force: true });
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
catch (err) {
|
|
222
|
+
return sendError(BlobType, errorToVariant(err));
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
//# sourceMappingURL=workspaces.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspaces.js","sourceRoot":"","sources":["../../../src/handlers/workspaces.ts"],"names":[],"mappings":"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"}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -10,4 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
export { createServer, type ServerConfig, type Server } from './server.js';
|
|
12
12
|
export { ApiTypes } from './types.js';
|
|
13
|
+
export * from './handlers/index.js';
|
|
14
|
+
export { createAuthMiddleware, type AuthConfig } from './middleware/auth.js';
|
|
15
|
+
export { sendSuccess, sendError, sendSuccessWithStatus, decodeBeast2, decodeBody } from './beast2.js';
|
|
13
16
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/src/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,KAAK,YAAY,EAAE,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,KAAK,YAAY,EAAE,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAGtC,cAAc,qBAAqB,CAAC;AAGpC,OAAO,EAAE,oBAAoB,EAAE,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAG7E,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,qBAAqB,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/src/index.js
CHANGED
|
@@ -10,4 +10,10 @@
|
|
|
10
10
|
*/
|
|
11
11
|
export { createServer } from './server.js';
|
|
12
12
|
export { ApiTypes } from './types.js';
|
|
13
|
+
// Export handlers for Lambda reuse
|
|
14
|
+
export * from './handlers/index.js';
|
|
15
|
+
// Export auth middleware
|
|
16
|
+
export { createAuthMiddleware } from './middleware/auth.js';
|
|
17
|
+
// Export BEAST2 helpers for custom integrations
|
|
18
|
+
export { sendSuccess, sendError, sendSuccessWithStatus, decodeBeast2, decodeBody } from './beast2.js';
|
|
13
19
|
//# sourceMappingURL=index.js.map
|
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAkC,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAkC,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,mCAAmC;AACnC,cAAc,qBAAqB,CAAC;AAEpC,yBAAyB;AACzB,OAAO,EAAE,oBAAoB,EAAmB,MAAM,sBAAsB,CAAC;AAE7E,gDAAgD;AAChD,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,qBAAqB,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Licensed under BSL 1.1. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
import type { MiddlewareHandler } from 'hono';
|
|
6
|
+
import type { KeyPair } from '../auth/keys.js';
|
|
7
|
+
/**
|
|
8
|
+
* JWT authentication configuration.
|
|
9
|
+
*
|
|
10
|
+
* Supports three modes:
|
|
11
|
+
* 1. publicKeyPath - Load key from PEM file
|
|
12
|
+
* 2. jwksUrl - Fetch keys from JWKS endpoint (for Cognito/external providers)
|
|
13
|
+
* 3. _internalKeys - Use provided KeyPair directly (for built-in OIDC provider)
|
|
14
|
+
*/
|
|
15
|
+
export interface AuthConfig {
|
|
16
|
+
/** Path to public key file (PEM format) for RS256 signature verification */
|
|
17
|
+
publicKeyPath?: string;
|
|
18
|
+
/** URL to JWKS endpoint for fetching public keys */
|
|
19
|
+
jwksUrl?: string;
|
|
20
|
+
/** Expected issuer claim (iss) */
|
|
21
|
+
issuer: string;
|
|
22
|
+
/** Expected audience claim (aud) */
|
|
23
|
+
audience: string;
|
|
24
|
+
/** Internal: direct KeyPair for built-in OIDC provider (avoids self-fetch) */
|
|
25
|
+
_internalKeys?: KeyPair;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Identity information extracted from JWT and set on context.
|
|
29
|
+
*/
|
|
30
|
+
export interface Identity {
|
|
31
|
+
/** Subject - typically user ID */
|
|
32
|
+
sub: string;
|
|
33
|
+
/** User email (if present in token) */
|
|
34
|
+
email?: string;
|
|
35
|
+
/** User roles (if present in token) */
|
|
36
|
+
roles: string[];
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Create JWT authentication middleware.
|
|
40
|
+
*
|
|
41
|
+
* The middleware:
|
|
42
|
+
* 1. Extracts Bearer token from Authorization header
|
|
43
|
+
* 2. Verifies RS256 signature using the configured public key
|
|
44
|
+
* 3. Validates exp, nbf, iss, and aud claims
|
|
45
|
+
* 4. Sets identity on Hono context (accessible via c.get('identity'))
|
|
46
|
+
*
|
|
47
|
+
* @param config - Authentication configuration
|
|
48
|
+
* @returns Hono middleware handler
|
|
49
|
+
*/
|
|
50
|
+
export declare function createAuthMiddleware(config: AuthConfig): Promise<MiddlewareHandler>;
|
|
51
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/middleware/auth.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAC9C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE/C;;;;;;;GAOG;AACH,MAAM,WAAW,UAAU;IACzB,4EAA4E;IAC5E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kCAAkC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,oCAAoC;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAwBD;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,kCAAkC;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,uCAAuC;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAgCD;;;;;;;;;;;GAWG;AACH,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA+FzF"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Licensed under BSL 1.1. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
import * as fs from 'node:fs/promises';
|
|
6
|
+
import * as crypto from 'node:crypto';
|
|
7
|
+
// Cache JWKS for 5 minutes
|
|
8
|
+
const JWKS_CACHE_TTL = 5 * 60 * 1000;
|
|
9
|
+
/**
|
|
10
|
+
* Create JWT authentication middleware.
|
|
11
|
+
*
|
|
12
|
+
* The middleware:
|
|
13
|
+
* 1. Extracts Bearer token from Authorization header
|
|
14
|
+
* 2. Verifies RS256 signature using the configured public key
|
|
15
|
+
* 3. Validates exp, nbf, iss, and aud claims
|
|
16
|
+
* 4. Sets identity on Hono context (accessible via c.get('identity'))
|
|
17
|
+
*
|
|
18
|
+
* @param config - Authentication configuration
|
|
19
|
+
* @returns Hono middleware handler
|
|
20
|
+
*/
|
|
21
|
+
export async function createAuthMiddleware(config) {
|
|
22
|
+
// Determine key source
|
|
23
|
+
let getPublicKey;
|
|
24
|
+
if (config._internalKeys) {
|
|
25
|
+
// Use provided KeyPair directly (built-in OIDC provider)
|
|
26
|
+
const keys = config._internalKeys;
|
|
27
|
+
getPublicKey = () => Promise.resolve(keys.publicKey);
|
|
28
|
+
}
|
|
29
|
+
else if (config.publicKeyPath) {
|
|
30
|
+
// Load public key from file at startup
|
|
31
|
+
const publicKeyPem = await fs.readFile(config.publicKeyPath, 'utf8');
|
|
32
|
+
const publicKey = crypto.createPublicKey(publicKeyPem);
|
|
33
|
+
getPublicKey = () => Promise.resolve(publicKey);
|
|
34
|
+
}
|
|
35
|
+
else if (config.jwksUrl) {
|
|
36
|
+
// Fetch keys from JWKS endpoint
|
|
37
|
+
let cache = null;
|
|
38
|
+
getPublicKey = async (kid) => {
|
|
39
|
+
// Check cache
|
|
40
|
+
if (cache && Date.now() - cache.fetchedAt < JWKS_CACHE_TTL) {
|
|
41
|
+
if (kid && cache.keys.has(kid)) {
|
|
42
|
+
return cache.keys.get(kid);
|
|
43
|
+
}
|
|
44
|
+
// If no kid specified, return first key
|
|
45
|
+
if (!kid && cache.keys.size > 0) {
|
|
46
|
+
return cache.keys.values().next().value;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// Fetch JWKS
|
|
50
|
+
const response = await fetch(config.jwksUrl);
|
|
51
|
+
if (!response.ok) {
|
|
52
|
+
throw new Error(`Failed to fetch JWKS: ${response.status}`);
|
|
53
|
+
}
|
|
54
|
+
const jwks = await response.json();
|
|
55
|
+
// Parse keys
|
|
56
|
+
const keys = new Map();
|
|
57
|
+
for (const key of jwks.keys) {
|
|
58
|
+
if (key.kty === 'RSA' && key.alg === 'RS256') {
|
|
59
|
+
const publicKey = crypto.createPublicKey({
|
|
60
|
+
key: {
|
|
61
|
+
kty: key.kty,
|
|
62
|
+
n: key.n,
|
|
63
|
+
e: key.e,
|
|
64
|
+
},
|
|
65
|
+
format: 'jwk',
|
|
66
|
+
});
|
|
67
|
+
keys.set(key.kid, publicKey);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
cache = { keys, fetchedAt: Date.now() };
|
|
71
|
+
if (kid && keys.has(kid)) {
|
|
72
|
+
return keys.get(kid);
|
|
73
|
+
}
|
|
74
|
+
if (!kid && keys.size > 0) {
|
|
75
|
+
return keys.values().next().value;
|
|
76
|
+
}
|
|
77
|
+
throw new Error(`Key not found: ${kid ?? 'no keys available'}`);
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
throw new Error('AuthConfig must specify publicKeyPath, jwksUrl, or _internalKeys');
|
|
82
|
+
}
|
|
83
|
+
return async (c, next) => {
|
|
84
|
+
const authHeader = c.req.header('authorization');
|
|
85
|
+
if (!authHeader?.startsWith('Bearer ')) {
|
|
86
|
+
return new Response('Unauthorized: Missing Bearer token', { status: 401 });
|
|
87
|
+
}
|
|
88
|
+
const token = authHeader.slice(7);
|
|
89
|
+
try {
|
|
90
|
+
// Extract kid from token header
|
|
91
|
+
const headerB64 = token.split('.')[0];
|
|
92
|
+
const header = JSON.parse(Buffer.from(headerB64, 'base64url').toString());
|
|
93
|
+
const publicKey = await getPublicKey(header.kid);
|
|
94
|
+
const payload = verifyJwt(token, publicKey, config.issuer, config.audience);
|
|
95
|
+
// Set identity on context for handlers
|
|
96
|
+
const identity = {
|
|
97
|
+
sub: payload.sub ?? 'unknown',
|
|
98
|
+
email: payload.email,
|
|
99
|
+
roles: payload.roles ?? [],
|
|
100
|
+
};
|
|
101
|
+
c.set('identity', identity);
|
|
102
|
+
await next();
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
const message = err instanceof Error ? err.message : 'Invalid token';
|
|
106
|
+
return new Response(`Unauthorized: ${message}`, { status: 401 });
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Verify JWT token and return payload.
|
|
112
|
+
*
|
|
113
|
+
* @param token - Raw JWT string
|
|
114
|
+
* @param publicKey - RSA public key for signature verification
|
|
115
|
+
* @param expectedIssuer - Expected iss claim
|
|
116
|
+
* @param expectedAudience - Expected aud claim
|
|
117
|
+
* @returns Decoded JWT payload
|
|
118
|
+
* @throws Error if verification fails
|
|
119
|
+
*/
|
|
120
|
+
function verifyJwt(token, publicKey, expectedIssuer, expectedAudience) {
|
|
121
|
+
const parts = token.split('.');
|
|
122
|
+
if (parts.length !== 3) {
|
|
123
|
+
throw new Error('Malformed JWT: expected 3 parts');
|
|
124
|
+
}
|
|
125
|
+
const [headerB64, payloadB64, signatureB64] = parts;
|
|
126
|
+
// Decode header and verify algorithm
|
|
127
|
+
const header = JSON.parse(Buffer.from(headerB64, 'base64url').toString());
|
|
128
|
+
if (header.alg !== 'RS256') {
|
|
129
|
+
throw new Error(`Unsupported algorithm: ${header.alg}`);
|
|
130
|
+
}
|
|
131
|
+
// Verify signature
|
|
132
|
+
const verify = crypto.createVerify('RSA-SHA256');
|
|
133
|
+
verify.update(`${headerB64}.${payloadB64}`);
|
|
134
|
+
const signature = Buffer.from(signatureB64, 'base64url');
|
|
135
|
+
if (!verify.verify(publicKey, signature)) {
|
|
136
|
+
throw new Error('Invalid signature');
|
|
137
|
+
}
|
|
138
|
+
// Decode payload
|
|
139
|
+
const payload = JSON.parse(Buffer.from(payloadB64, 'base64url').toString());
|
|
140
|
+
// Verify time-based claims
|
|
141
|
+
const now = Math.floor(Date.now() / 1000);
|
|
142
|
+
if (payload.exp !== undefined && payload.exp < now) {
|
|
143
|
+
throw new Error('Token expired');
|
|
144
|
+
}
|
|
145
|
+
if (payload.nbf !== undefined && payload.nbf > now) {
|
|
146
|
+
throw new Error('Token not yet valid');
|
|
147
|
+
}
|
|
148
|
+
// Verify issuer
|
|
149
|
+
if (payload.iss !== expectedIssuer) {
|
|
150
|
+
throw new Error(`Invalid issuer: expected ${expectedIssuer}, got ${payload.iss}`);
|
|
151
|
+
}
|
|
152
|
+
// Verify audience
|
|
153
|
+
if (payload.aud !== expectedAudience) {
|
|
154
|
+
throw new Error(`Invalid audience: expected ${expectedAudience}, got ${payload.aud}`);
|
|
155
|
+
}
|
|
156
|
+
return payload;
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/middleware/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,5 +3,6 @@
|
|
|
3
3
|
* Licensed under BSL 1.1. See LICENSE for details.
|
|
4
4
|
*/
|
|
5
5
|
import { Hono } from 'hono';
|
|
6
|
-
|
|
6
|
+
import type { StorageBackend } from '@elaraai/e3-core';
|
|
7
|
+
export declare function createDatasetRoutes(storage: StorageBackend, getRepoPath: (repo: string) => string): Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
|
|
7
8
|
//# sourceMappingURL=datasets.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"datasets.d.ts","sourceRoot":"","sources":["../../../src/routes/datasets.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"datasets.d.ts","sourceRoot":"","sources":["../../../src/routes/datasets.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAQvD,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,cAAc,EACvB,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,8EAoEtC"}
|