optio-api 0.2.9 → 0.2.11
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 +39 -7
- package/dist/_generated/optio-engine.d.ts +8 -0
- package/dist/_generated/optio-engine.d.ts.map +1 -1
- package/dist/_generated/optio-engine.js +3 -0
- package/dist/_generated/optio-engine.js.map +1 -1
- package/dist/access-scope.d.ts +53 -0
- package/dist/access-scope.d.ts.map +1 -0
- package/dist/access-scope.js +110 -0
- package/dist/access-scope.js.map +1 -0
- package/dist/adapters/express.d.ts +5 -0
- package/dist/adapters/express.d.ts.map +1 -1
- package/dist/adapters/express.js +35 -23
- package/dist/adapters/express.js.map +1 -1
- package/dist/adapters/fastify.d.ts +5 -1
- package/dist/adapters/fastify.d.ts.map +1 -1
- package/dist/adapters/fastify.js +74 -33
- package/dist/adapters/fastify.js.map +1 -1
- package/dist/adapters/nextjs-app.d.ts +5 -0
- package/dist/adapters/nextjs-app.d.ts.map +1 -1
- package/dist/adapters/nextjs-app.js +44 -15
- package/dist/adapters/nextjs-app.js.map +1 -1
- package/dist/adapters/nextjs-pages.d.ts +5 -0
- package/dist/adapters/nextjs-pages.d.ts.map +1 -1
- package/dist/adapters/nextjs-pages.js +41 -15
- package/dist/adapters/nextjs-pages.js.map +1 -1
- package/dist/auth.d.ts +48 -0
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +44 -0
- package/dist/auth.js.map +1 -1
- package/dist/discovery.d.ts +7 -1
- package/dist/discovery.d.ts.map +1 -1
- package/dist/discovery.js +18 -11
- package/dist/discovery.js.map +1 -1
- package/dist/handlers.d.ts +44 -14
- package/dist/handlers.d.ts.map +1 -1
- package/dist/handlers.js +78 -20
- package/dist/handlers.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/process-change-hub.d.ts +87 -0
- package/dist/process-change-hub.d.ts.map +1 -0
- package/dist/process-change-hub.js +268 -0
- package/dist/process-change-hub.js.map +1 -0
- package/dist/process-change-relevance.d.ts +57 -0
- package/dist/process-change-relevance.d.ts.map +1 -0
- package/dist/process-change-relevance.js +101 -0
- package/dist/process-change-relevance.js.map +1 -0
- package/dist/stream-poller.d.ts +13 -1
- package/dist/stream-poller.d.ts.map +1 -1
- package/dist/stream-poller.js +290 -260
- package/dist/stream-poller.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -135,6 +135,7 @@ All adapters mount the same endpoints under `/api/processes/:prefix/...`:
|
|
|
135
135
|
| POST | `/api/processes/:prefix/:id/launch` | Forward launch to engine. 200 on success; 404/409 with `{reason, message}` per `LaunchFailureReason`. |
|
|
136
136
|
| POST | `/api/processes/:prefix/:id/cancel` | Forward cancel to engine. 200 on success; 404/409 per `CancelFailureReason`. |
|
|
137
137
|
| POST | `/api/processes/:prefix/:id/dismiss` | Forward dismiss to engine. 200 on success; 404/409 per `DismissFailureReason`. |
|
|
138
|
+
| POST | `/api/processes/:prefix/:id/resurrect` | Forward resurrect (save a failed run's unsaved work, then resume) to engine; optional body `{ sessionId?: string \| null }`. 200 on success; 404/409 per `ResurrectFailureReason`. |
|
|
138
139
|
| POST | `/api/processes/:prefix/resync` | 202 Accepted; engine handles resync asynchronously. |
|
|
139
140
|
|
|
140
141
|
Command endpoints do not validate state in this package. The engine owns all command-acceptance rules; the API translates the engine's discriminated-union result into HTTP status + body. See the architectural rule at the top of `AGENTS.md`.
|
|
@@ -155,8 +156,13 @@ with an explicit migration message.
|
|
|
155
156
|
|
|
156
157
|
## SSE Streams
|
|
157
158
|
|
|
158
|
-
- `GET /api/processes/:prefix/stream` — live flat process list
|
|
159
|
-
- `GET /api/processes/:prefix/:id/tree/stream` — live process tree with log deltas
|
|
159
|
+
- `GET /api/processes/:prefix/stream` — live flat process list. Accepts the same optional `?metadataFilter=<URL-encoded JSON>` query param as the REST list endpoint; the legacy `?metadata.<key>=<value>` form returns 400.
|
|
160
|
+
- `GET /api/processes/:prefix/:id/tree/stream` — live process tree with log deltas
|
|
161
|
+
|
|
162
|
+
A stream reads MongoDB once when it opens, then only when the shared change stream of its
|
|
163
|
+
`(database, prefix)` reports a change relevant to it, at most once a second. Without change
|
|
164
|
+
streams (a standalone MongoDB, or `OPTIO_API_CHANGE_STREAMS=off`) every stream re-reads once a
|
|
165
|
+
second.
|
|
160
166
|
|
|
161
167
|
## Building Custom Adapters
|
|
162
168
|
|
|
@@ -168,10 +174,11 @@ import {
|
|
|
168
174
|
createOptioContext, type OptioContext,
|
|
169
175
|
listProcesses, getProcess, getProcessTree,
|
|
170
176
|
getProcessLog, getProcessTreeLog,
|
|
171
|
-
launchProcess, cancelProcess, dismissProcess, resyncProcesses,
|
|
177
|
+
launchProcess, cancelProcess, dismissProcess, resurrectProcess, resyncProcesses,
|
|
172
178
|
createListPoller, createTreePoller,
|
|
173
179
|
type ListQuery, type PaginationQuery, type TreeLogQuery,
|
|
174
180
|
type LaunchCommandResult, type CancelCommandResult, type DismissCommandResult,
|
|
181
|
+
type ResurrectCommandResult,
|
|
175
182
|
type StreamPollerOptions, type TreePollerOptions, type ListPollerHandle,
|
|
176
183
|
} from 'optio-api';
|
|
177
184
|
```
|
|
@@ -180,14 +187,39 @@ Handler functions take an `OptioContext` (constructed once via
|
|
|
180
187
|
`createOptioContext({ dbOpts, redis })`) as the first argument, a per-request
|
|
181
188
|
`query` object as the second, and an optional `id` / additional parameters as
|
|
182
189
|
later positional args. Command handlers (`launchProcess`, `cancelProcess`,
|
|
183
|
-
`dismissProcess`) return per-command result unions
|
|
184
|
-
(`LaunchCommandResult` / `CancelCommandResult` / `DismissCommandResult`
|
|
185
|
-
whose 404/409 bodies are `{ reason, message }` —
|
|
186
|
-
directly.
|
|
190
|
+
`dismissProcess`, `resurrectProcess`) return per-command result unions
|
|
191
|
+
(`LaunchCommandResult` / `CancelCommandResult` / `DismissCommandResult` /
|
|
192
|
+
`ResurrectCommandResult`) whose 404/409 bodies are `{ reason, message }` —
|
|
193
|
+
map these to HTTP responses directly.
|
|
187
194
|
|
|
188
195
|
Stream pollers expose a `{ start(), stop() }` handle; call `start()` when the
|
|
189
196
|
client connects and `stop()` when they disconnect.
|
|
190
197
|
|
|
198
|
+
## Multi-tenant access
|
|
199
|
+
|
|
200
|
+
Besides `authenticate` (viewer / operator), every adapter accepts two optional
|
|
201
|
+
hooks for hosts that serve several tenants from one optio database:
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
registerOptioApi(app, {
|
|
205
|
+
ctx,
|
|
206
|
+
authenticate: (req) => (req.user ? 'operator' : null),
|
|
207
|
+
// Confine the request to its tenant: a flat exact-match metadata map, or
|
|
208
|
+
// null for an unrestricted user. Other tenants' processes behave as missing.
|
|
209
|
+
scope: (req) => (req.user.admin ? null : { customerId: req.user.customerId }),
|
|
210
|
+
// Decide individual actions: launch, cancel, dismiss, resurrect (a
|
|
211
|
+
// single-process action like launch), resync, the widget routes and
|
|
212
|
+
// instance discovery. false -> 403.
|
|
213
|
+
authorize: (req, { action, process, clean }) =>
|
|
214
|
+
action === 'instances' ? req.user.admin
|
|
215
|
+
: action === 'resync' && clean ? req.user.admin
|
|
216
|
+
: true,
|
|
217
|
+
});
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Without them nothing changes. The exact enforcement per route is in
|
|
221
|
+
`AGENTS.md` ("Access scope and authorization").
|
|
222
|
+
|
|
191
223
|
## Return value
|
|
192
224
|
|
|
193
225
|
`registerOptioApi`, `createOptioRouteHandlers`, and `createOptioHandler`
|
|
@@ -15,6 +15,8 @@ export type LaunchParams = z.infer<typeof optioEngineContract.methods.launch.par
|
|
|
15
15
|
export type LaunchResult = z.infer<typeof optioEngineContract.methods.launch.result>;
|
|
16
16
|
export type MaterializeUploadParams = z.infer<typeof optioEngineContract.methods.materializeUpload.params>;
|
|
17
17
|
export type MaterializeUploadResult = z.infer<typeof optioEngineContract.methods.materializeUpload.result>;
|
|
18
|
+
export type ResurrectParams = z.infer<typeof optioEngineContract.methods.resurrect.params>;
|
|
19
|
+
export type ResurrectResult = z.infer<typeof optioEngineContract.methods.resurrect.result>;
|
|
18
20
|
export type ResyncParams = z.infer<typeof optioEngineContract.methods.resync.params>;
|
|
19
21
|
export type UnblockLaunchesParams = z.infer<typeof optioEngineContract.methods.unblockLaunches.params>;
|
|
20
22
|
export type UnblockLaunchesResult = z.infer<typeof optioEngineContract.methods.unblockLaunches.result>;
|
|
@@ -42,6 +44,9 @@ export declare class OptioEngineClient {
|
|
|
42
44
|
materializeUpload(params: MaterializeUploadParams, opts?: {
|
|
43
45
|
timeoutMs?: number;
|
|
44
46
|
}): Promise<MaterializeUploadResult>;
|
|
47
|
+
resurrect(params: ResurrectParams, opts?: {
|
|
48
|
+
timeoutMs?: number;
|
|
49
|
+
}): Promise<ResurrectResult>;
|
|
45
50
|
resync(params: ResyncParams): Promise<void>;
|
|
46
51
|
unblockLaunches(params: UnblockLaunchesParams, opts?: {
|
|
47
52
|
timeoutMs?: number;
|
|
@@ -69,6 +74,9 @@ export interface OptioEngineService {
|
|
|
69
74
|
materializeUpload(params: MaterializeUploadParams, opts?: {
|
|
70
75
|
timeoutMs?: number;
|
|
71
76
|
}): Promise<MaterializeUploadResult>;
|
|
77
|
+
resurrect(params: ResurrectParams, opts?: {
|
|
78
|
+
timeoutMs?: number;
|
|
79
|
+
}): Promise<ResurrectResult>;
|
|
72
80
|
resync(params: ResyncParams): Promise<void>;
|
|
73
81
|
unblockLaunches(params: UnblockLaunchesParams, opts?: {
|
|
74
82
|
timeoutMs?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"optio-engine.d.ts","sourceRoot":"","sources":["../../src/_generated/optio-engine.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"optio-engine.d.ts","sourceRoot":"","sources":["../../src/_generated/optio-engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -24,6 +24,9 @@ export class OptioEngineClient {
|
|
|
24
24
|
materializeUpload(params, opts) {
|
|
25
25
|
return this.client.call('optio-engine', 'materializeUpload', params, opts);
|
|
26
26
|
}
|
|
27
|
+
resurrect(params, opts) {
|
|
28
|
+
return this.client.call('optio-engine', 'resurrect', params, opts);
|
|
29
|
+
}
|
|
27
30
|
resync(params) {
|
|
28
31
|
return this.client.notify('optio-engine', 'resync', params);
|
|
29
32
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"optio-engine.js","sourceRoot":"","sources":["../../src/_generated/optio-engine.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"optio-engine.js","sourceRoot":"","sources":["../../src/_generated/optio-engine.ts"],"names":[],"mappings":"AA0BA,MAAM,OAAO,iBAAiB;IACR;IAApB,YAAoB,MAAsB;QAAtB,WAAM,GAAN,MAAM,CAAgB;IAAG,CAAC;IAC9C,aAAa,CAAC,MAA2B,EAAE,IAA6B;QACtE,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,eAAe,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;IACzE,CAAC;IACD,MAAM,CAAC,MAAoB,EAAE,IAA6B;QACxD,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;IAClE,CAAC;IACD,OAAO,CAAC,MAAqB,EAAE,IAA6B;QAC1D,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;IACnE,CAAC;IACD,WAAW,CAAC,MAAyB,EAAE,IAA6B;QAClE,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,aAAa,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;IACvE,CAAC;IACD,kBAAkB,CAAC,MAAgC,EAAE,IAA6B;QAChF,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,oBAAoB,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;IAC9E,CAAC;IACD,MAAM,CAAC,MAAoB,EAAE,IAA6B;QACxD,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;IAClE,CAAC;IACD,iBAAiB,CAAC,MAA+B,EAAE,IAA6B;QAC9E,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,mBAAmB,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;IAC7E,CAAC;IACD,SAAS,CAAC,MAAuB,EAAE,IAA6B;QAC9D,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;IACrE,CAAC;IACD,MAAM,CAAC,MAAoB;QACzB,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,cAAc,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC9D,CAAC;IACD,eAAe,CAAC,MAA6B,EAAE,IAA6B;QAC1E,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,iBAAiB,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;IAC3E,CAAC;CACF"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { type Collection, type Document } from 'mongodb';
|
|
2
|
+
import type { ProcessMetadataFilter } from './types.js';
|
|
3
|
+
import type { Access, OptioAction, ProcessRef, ScopeFilter } from './auth.js';
|
|
4
|
+
/** `{ k: v }` -> `{ 'metadata.k': v }`: exact-match equality on metadata. */
|
|
5
|
+
export declare function scopeToMongo(scope: ScopeFilter | null): Record<string, unknown>;
|
|
6
|
+
/**
|
|
7
|
+
* Confine a Mongo filter to the scope. `$and` rather than a merge, so a client
|
|
8
|
+
* filter on a scope key can only narrow the result, never replace the scope.
|
|
9
|
+
*/
|
|
10
|
+
export declare function andScope(base: Record<string, unknown>, scope: ScopeFilter | null): Record<string, unknown>;
|
|
11
|
+
/**
|
|
12
|
+
* Whether a process is inside the scope. A process whose own metadata lacks
|
|
13
|
+
* any scope key is judged by its root's metadata; one whose root lacks it too
|
|
14
|
+
* is outside (fail closed).
|
|
15
|
+
*/
|
|
16
|
+
export declare function inScope(col: Collection, doc: Document, scope: ScopeFilter | null): Promise<boolean>;
|
|
17
|
+
/** Look a process up by either id form; outside the scope it is not found. */
|
|
18
|
+
export declare function findScopedProcess(col: Collection, id: string, scope: ScopeFilter | null): Promise<Document | null>;
|
|
19
|
+
export declare function toProcessRef(doc: Document): ProcessRef;
|
|
20
|
+
export type GateResult = {
|
|
21
|
+
ok: true;
|
|
22
|
+
doc: Document | null;
|
|
23
|
+
} | {
|
|
24
|
+
ok: false;
|
|
25
|
+
status: 404 | 403;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Admit a single-process action: the process must exist, be in scope (else
|
|
29
|
+
* 404, its existence is not revealed) and pass `authorize` (else 403).
|
|
30
|
+
* Unrestricted access skips the lookup, leaving everything to the engine as
|
|
31
|
+
* before. A duplicated `processId` resolves to the newest document, as the
|
|
32
|
+
* engine does.
|
|
33
|
+
*/
|
|
34
|
+
export declare function gateProcess(col: Collection, id: string, access: Access, action: OptioAction): Promise<GateResult>;
|
|
35
|
+
/** Instance discovery lists every optio database/prefix: `authorize` decides. */
|
|
36
|
+
export declare function gateInstances(access: Access): Promise<boolean>;
|
|
37
|
+
export type ScopedFilterResult = {
|
|
38
|
+
ok: true;
|
|
39
|
+
filter: ProcessMetadataFilter | undefined;
|
|
40
|
+
} | {
|
|
41
|
+
ok: false;
|
|
42
|
+
status: 400 | 403;
|
|
43
|
+
message: string;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* The filter a resync runs with under a scope: the client's flat filter plus
|
|
47
|
+
* the scope keys. The engine filters both the regenerated tasks and the stale
|
|
48
|
+
* records it removes by this map, so a scoped resync cannot reach outside.
|
|
49
|
+
* Resync filters are flat exact-match maps on the engine side; a predicate
|
|
50
|
+
* tree is refused rather than guessed at.
|
|
51
|
+
*/
|
|
52
|
+
export declare function scopedResyncFilter(filter: ProcessMetadataFilter | undefined, scope: ScopeFilter | null): ScopedFilterResult;
|
|
53
|
+
//# sourceMappingURL=access-scope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access-scope.d.ts","sourceRoot":"","sources":["../src/access-scope.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,UAAU,EAAE,KAAK,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAG9E,6EAA6E;AAC7E,wBAAgB,YAAY,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAG/E;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CACtB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,KAAK,EAAE,WAAW,GAAG,IAAI,GACxB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAKzB;AAMD;;;;GAIG;AACH,wBAAsB,OAAO,CAC3B,GAAG,EAAE,UAAU,EACf,GAAG,EAAE,QAAQ,EACb,KAAK,EAAE,WAAW,GAAG,IAAI,GACxB,OAAO,CAAC,OAAO,CAAC,CAOlB;AAED,8EAA8E;AAC9E,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,UAAU,EACf,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,WAAW,GAAG,IAAI,GACxB,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAI1B;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,QAAQ,GAAG,UAAU,CAStD;AAED,MAAM,MAAM,UAAU,GAClB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,GAAG,EAAE,QAAQ,GAAG,IAAI,CAAA;CAAE,GAClC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,GAAG,GAAG,GAAG,CAAA;CAAE,CAAC;AAErC;;;;;;GAMG;AACH,wBAAsB,WAAW,CAC/B,GAAG,EAAE,UAAU,EACf,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,UAAU,CAAC,CAUrB;AAED,iFAAiF;AACjF,wBAAsB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAGpE;AAED,MAAM,MAAM,kBAAkB,GAC1B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,qBAAqB,GAAG,SAAS,CAAA;CAAE,GACvD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,GAAG,GAAG,GAAG,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,qBAAqB,GAAG,SAAS,EACzC,KAAK,EAAE,WAAW,GAAG,IAAI,GACxB,kBAAkB,CAiBpB"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { ObjectId } from 'mongodb';
|
|
2
|
+
import { ProcessMetadataFilterLegacySchema } from 'optio-contracts';
|
|
3
|
+
import { findProcessByEitherId } from './process-id-resolver.js';
|
|
4
|
+
/** `{ k: v }` -> `{ 'metadata.k': v }`: exact-match equality on metadata. */
|
|
5
|
+
export function scopeToMongo(scope) {
|
|
6
|
+
if (!scope)
|
|
7
|
+
return {};
|
|
8
|
+
return Object.fromEntries(Object.entries(scope).map(([k, v]) => [`metadata.${k}`, v]));
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Confine a Mongo filter to the scope. `$and` rather than a merge, so a client
|
|
12
|
+
* filter on a scope key can only narrow the result, never replace the scope.
|
|
13
|
+
*/
|
|
14
|
+
export function andScope(base, scope) {
|
|
15
|
+
if (!scope)
|
|
16
|
+
return base;
|
|
17
|
+
const scoped = scopeToMongo(scope);
|
|
18
|
+
if (Object.keys(base).length === 0)
|
|
19
|
+
return scoped;
|
|
20
|
+
return { $and: [base, scoped] };
|
|
21
|
+
}
|
|
22
|
+
function matches(metadata, scope) {
|
|
23
|
+
return Object.entries(scope).every(([k, v]) => k in metadata && metadata[k] === v);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Whether a process is inside the scope. A process whose own metadata lacks
|
|
27
|
+
* any scope key is judged by its root's metadata; one whose root lacks it too
|
|
28
|
+
* is outside (fail closed).
|
|
29
|
+
*/
|
|
30
|
+
export async function inScope(col, doc, scope) {
|
|
31
|
+
if (!scope)
|
|
32
|
+
return true;
|
|
33
|
+
const own = (doc.metadata ?? {});
|
|
34
|
+
if (Object.keys(scope).every((k) => k in own))
|
|
35
|
+
return matches(own, scope);
|
|
36
|
+
if (!doc.parentId || !doc.rootId)
|
|
37
|
+
return false;
|
|
38
|
+
const root = await col.findOne({ _id: doc.rootId }, { projection: { metadata: 1 } });
|
|
39
|
+
return matches((root?.metadata ?? {}), scope);
|
|
40
|
+
}
|
|
41
|
+
/** Look a process up by either id form; outside the scope it is not found. */
|
|
42
|
+
export async function findScopedProcess(col, id, scope) {
|
|
43
|
+
const doc = await findProcessByEitherId(col, id);
|
|
44
|
+
if (!doc)
|
|
45
|
+
return null;
|
|
46
|
+
return (await inScope(col, doc, scope)) ? doc : null;
|
|
47
|
+
}
|
|
48
|
+
export function toProcessRef(doc) {
|
|
49
|
+
return {
|
|
50
|
+
_id: doc._id.toString(),
|
|
51
|
+
processId: doc.processId,
|
|
52
|
+
name: doc.name,
|
|
53
|
+
...(doc.parentId ? { parentId: doc.parentId.toString() } : {}),
|
|
54
|
+
rootId: doc.rootId.toString(),
|
|
55
|
+
metadata: (doc.metadata ?? {}),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Admit a single-process action: the process must exist, be in scope (else
|
|
60
|
+
* 404, its existence is not revealed) and pass `authorize` (else 403).
|
|
61
|
+
* Unrestricted access skips the lookup, leaving everything to the engine as
|
|
62
|
+
* before. A duplicated `processId` resolves to the newest document, as the
|
|
63
|
+
* engine does.
|
|
64
|
+
*/
|
|
65
|
+
export async function gateProcess(col, id, access, action) {
|
|
66
|
+
if (!access.restricted)
|
|
67
|
+
return { ok: true, doc: null };
|
|
68
|
+
const doc = ObjectId.isValid(id) && /^[a-f0-9]{24}$/i.test(id)
|
|
69
|
+
? await col.findOne({ _id: new ObjectId(id) })
|
|
70
|
+
: await col.find({ processId: id }).sort({ _id: -1 }).limit(1).next();
|
|
71
|
+
if (!doc || !(await inScope(col, doc, access.scope)))
|
|
72
|
+
return { ok: false, status: 404 };
|
|
73
|
+
if (!(await access.authorize({ action, process: toProcessRef(doc) }))) {
|
|
74
|
+
return { ok: false, status: 403 };
|
|
75
|
+
}
|
|
76
|
+
return { ok: true, doc };
|
|
77
|
+
}
|
|
78
|
+
/** Instance discovery lists every optio database/prefix: `authorize` decides. */
|
|
79
|
+
export async function gateInstances(access) {
|
|
80
|
+
if (!access.restricted)
|
|
81
|
+
return true;
|
|
82
|
+
return access.authorize({ action: 'instances' });
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* The filter a resync runs with under a scope: the client's flat filter plus
|
|
86
|
+
* the scope keys. The engine filters both the regenerated tasks and the stale
|
|
87
|
+
* records it removes by this map, so a scoped resync cannot reach outside.
|
|
88
|
+
* Resync filters are flat exact-match maps on the engine side; a predicate
|
|
89
|
+
* tree is refused rather than guessed at.
|
|
90
|
+
*/
|
|
91
|
+
export function scopedResyncFilter(filter, scope) {
|
|
92
|
+
if (!scope)
|
|
93
|
+
return { ok: true, filter };
|
|
94
|
+
const flat = ProcessMetadataFilterLegacySchema.safeParse(filter ?? {});
|
|
95
|
+
if (!flat.success) {
|
|
96
|
+
return {
|
|
97
|
+
ok: false,
|
|
98
|
+
status: 400,
|
|
99
|
+
message: 'A scoped resync needs a flat metadataFilter ({ key: value, ... })',
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
const client = flat.data;
|
|
103
|
+
for (const [k, v] of Object.entries(scope)) {
|
|
104
|
+
if (k in client && client[k] !== v) {
|
|
105
|
+
return { ok: false, status: 403, message: 'Forbidden' };
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return { ok: true, filter: { ...client, ...scope } };
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=access-scope.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access-scope.js","sourceRoot":"","sources":["../src/access-scope.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAkC,MAAM,SAAS,CAAC;AACnE,OAAO,EAAE,iCAAiC,EAAE,MAAM,iBAAiB,CAAC;AAGpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAEjE,6EAA6E;AAC7E,MAAM,UAAU,YAAY,CAAC,KAAyB;IACpD,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACtB,OAAO,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AACzF,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,QAAQ,CACtB,IAA6B,EAC7B,KAAyB;IAEzB,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IACnC,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC;IAClD,OAAO,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC;AAClC,CAAC;AAED,SAAS,OAAO,CAAC,QAAiC,EAAE,KAAkB;IACpE,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,QAAQ,IAAI,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;AACrF,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,GAAe,EACf,GAAa,EACb,KAAyB;IAEzB,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAA4B,CAAC;IAC5D,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,GAAG,CAAC;QAAE,OAAO,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC1E,IAAI,CAAC,GAAG,CAAC,QAAQ,IAAI,CAAC,GAAG,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAC/C,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IACrF,OAAO,OAAO,CAAC,CAAC,IAAI,EAAE,QAAQ,IAAI,EAAE,CAA4B,EAAE,KAAK,CAAC,CAAC;AAC3E,CAAC;AAED,8EAA8E;AAC9E,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,GAAe,EACf,EAAU,EACV,KAAyB;IAEzB,MAAM,GAAG,GAAG,MAAM,qBAAqB,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACjD,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACtB,OAAO,CAAC,MAAM,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,GAAa;IACxC,OAAO;QACL,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE;QACvB,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9D,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,QAAQ,EAAE;QAC7B,QAAQ,EAAE,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAA4B;KAC1D,CAAC;AACJ,CAAC;AAMD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,GAAe,EACf,EAAU,EACV,MAAc,EACd,MAAmB;IAEnB,IAAI,CAAC,MAAM,CAAC,UAAU;QAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;IACvD,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5D,CAAC,CAAC,MAAM,GAAG,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,IAAI,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;QAC9C,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACxE,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,MAAM,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;IACxF,IAAI,CAAC,CAAC,MAAM,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QACtE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;IACpC,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;AAC3B,CAAC;AAED,iFAAiF;AACjF,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAAc;IAChD,IAAI,CAAC,MAAM,CAAC,UAAU;QAAE,OAAO,IAAI,CAAC;IACpC,OAAO,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;AACnD,CAAC;AAMD;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAChC,MAAyC,EACzC,KAAyB;IAEzB,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IACxC,MAAM,IAAI,GAAG,iCAAiC,CAAC,SAAS,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;IACvE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QAClB,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,GAAG;YACX,OAAO,EAAE,mEAAmE;SAC7E,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,CAAC,IAA+B,CAAC;IACpD,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3C,IAAI,CAAC,IAAI,MAAM,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;YACnC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;QAC1D,CAAC;IACH,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,MAAM,EAAE,GAAG,KAAK,EAA2B,EAAE,CAAC;AAChF,CAAC"}
|
|
@@ -3,6 +3,7 @@ import type { Db } from 'mongodb';
|
|
|
3
3
|
import type { MongoClient } from 'mongodb';
|
|
4
4
|
import type { Redis } from 'ioredis';
|
|
5
5
|
import type { AuthCallback } from '../auth.js';
|
|
6
|
+
import { type AuthorizeCallback, type ScopeCallback } from '../auth.js';
|
|
6
7
|
import { type OptioContext } from '../context.js';
|
|
7
8
|
export type OptioApiOptions = (BaseOptioApiOptions & {
|
|
8
9
|
ctx: OptioContext;
|
|
@@ -18,6 +19,10 @@ export type OptioApiOptions = (BaseOptioApiOptions & {
|
|
|
18
19
|
interface BaseOptioApiOptions {
|
|
19
20
|
prefix?: string;
|
|
20
21
|
authenticate: AuthCallback<import('express').Request>;
|
|
22
|
+
/** Confine each request to a tenant's processes (see auth.ts). */
|
|
23
|
+
scope?: ScopeCallback<import('express').Request>;
|
|
24
|
+
/** Decide mutating actions and instance discovery (see auth.ts). */
|
|
25
|
+
authorize?: AuthorizeCallback<import('express').Request>;
|
|
21
26
|
}
|
|
22
27
|
export declare function registerOptioApi(app: Express, opts: OptioApiOptions): OptioContext | void;
|
|
23
28
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"express.d.ts","sourceRoot":"","sources":["../../src/adapters/express.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"express.d.ts","sourceRoot":"","sources":["../../src/adapters/express.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAOrC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAA0C,KAAK,iBAAiB,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAGhH,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAEtE,MAAM,MAAM,eAAe,GACvB,CAAC,mBAAmB,GAAG;IAAE,GAAG,EAAE,YAAY,CAAA;CAAE,CAAC,GAC7C,CAAC,mBAAmB,GAAG;IAAE,KAAK,EAAE,KAAK,CAAA;CAAE,GAAG,CACtC;IAAE,EAAE,EAAE,EAAE,CAAC;IAAC,WAAW,CAAC,EAAE,KAAK,CAAA;CAAE,GAC/B;IAAE,WAAW,EAAE,WAAW,CAAC;IAAC,EAAE,CAAC,EAAE,KAAK,CAAA;CAAE,CAC3C,CAAC,CAAC;AAEP,UAAU,mBAAmB;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,YAAY,CAAC,OAAO,SAAS,EAAE,OAAO,CAAC,CAAC;IACtD,kEAAkE;IAClE,KAAK,CAAC,EAAE,aAAa,CAAC,OAAO,SAAS,EAAE,OAAO,CAAC,CAAC;IACjD,oEAAoE;IACpE,SAAS,CAAC,EAAE,iBAAiB,CAAC,OAAO,SAAS,EAAE,OAAO,CAAC,CAAC;CAC1D;AAKD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,eAAe,GAAG,YAAY,GAAG,IAAI,CA+LzF"}
|
package/dist/adapters/express.js
CHANGED
|
@@ -4,13 +4,13 @@ import { createExpressEndpoints } from '@ts-rest/express';
|
|
|
4
4
|
import { initContract } from '@ts-rest/core';
|
|
5
5
|
import { processesContract } from 'optio-contracts';
|
|
6
6
|
import * as handlers from '../handlers.js';
|
|
7
|
-
import { findProcessByEitherId } from '../process-id-resolver.js';
|
|
8
7
|
import { createListPoller, createTreePoller } from '../stream-poller.js';
|
|
9
8
|
import { detectLegacyMetadataParams, formatLegacyMetadataMessage } from '../metadata-filter-query.js';
|
|
10
9
|
import { parseSseOptions, checkLegacyMetadataParams, LegacyMetadataParamError } from '../sse-options.js';
|
|
11
10
|
import { discoverInstances } from '../discovery.js';
|
|
12
11
|
import { resolveDb } from '../resolve.js';
|
|
13
|
-
import { checkAuth } from '../auth.js';
|
|
12
|
+
import { accessFor, checkAuth } from '../auth.js';
|
|
13
|
+
import { findScopedProcess, gateInstances } from '../access-scope.js';
|
|
14
14
|
import { isWriteMethod } from '../widget-proxy-core.js';
|
|
15
15
|
import { createOptioContext } from '../context.js';
|
|
16
16
|
const c = initContract();
|
|
@@ -30,6 +30,8 @@ export function registerOptioApi(app, opts) {
|
|
|
30
30
|
dbOpts = 'mongoClient' in opts && opts.mongoClient ? { mongoClient: opts.mongoClient } : { db: opts.db };
|
|
31
31
|
ctx = createOptioContext({ dbOpts, redis });
|
|
32
32
|
}
|
|
33
|
+
const hooks = { scope: opts.scope, authorize: opts.authorize };
|
|
34
|
+
const access = (req) => accessFor(req, hooks);
|
|
33
35
|
// Global auth enforcement. Runs on every /api/* request before any
|
|
34
36
|
// ts-rest, SSE, or discovery handler.
|
|
35
37
|
app.use('/api', async (req, res, next) => {
|
|
@@ -75,6 +77,7 @@ export function registerOptioApi(app, opts) {
|
|
|
75
77
|
return;
|
|
76
78
|
}
|
|
77
79
|
const { db, prefix } = resolveDb(dbOpts, sseOpts);
|
|
80
|
+
const { scope } = await access(req);
|
|
78
81
|
res.writeHead(200, {
|
|
79
82
|
'Content-Type': 'text/event-stream',
|
|
80
83
|
'Cache-Control': 'no-cache',
|
|
@@ -89,58 +92,67 @@ export function registerOptioApi(app, opts) {
|
|
|
89
92
|
sendEvent,
|
|
90
93
|
onError: () => res.end(),
|
|
91
94
|
metadataFilter: sseOpts.metadataFilter,
|
|
95
|
+
scope,
|
|
92
96
|
});
|
|
93
97
|
poller.start();
|
|
94
98
|
req.on('close', () => poller.stop());
|
|
95
99
|
});
|
|
96
100
|
createExpressEndpoints(apiContract.processes, {
|
|
97
|
-
list: async ({ query }) => {
|
|
98
|
-
const result = await handlers.listProcesses(ctx, query);
|
|
101
|
+
list: async ({ query, req }) => {
|
|
102
|
+
const result = await handlers.listProcesses(ctx, query, await access(req));
|
|
99
103
|
return { status: 200, body: result };
|
|
100
104
|
},
|
|
101
|
-
get: async ({ params, query }) => {
|
|
102
|
-
const result = await handlers.getProcess(ctx, query, params.id);
|
|
105
|
+
get: async ({ params, query, req }) => {
|
|
106
|
+
const result = await handlers.getProcess(ctx, query, params.id, await access(req));
|
|
103
107
|
if (!result)
|
|
104
108
|
return { status: 404, body: { message: 'Process not found' } };
|
|
105
109
|
return { status: 200, body: result };
|
|
106
110
|
},
|
|
107
|
-
getTree: async ({ params, query }) => {
|
|
108
|
-
const result = await handlers.getProcessTree(ctx, query, params.id);
|
|
111
|
+
getTree: async ({ params, query, req }) => {
|
|
112
|
+
const result = await handlers.getProcessTree(ctx, query, params.id, await access(req));
|
|
109
113
|
if (!result)
|
|
110
114
|
return { status: 404, body: { message: 'Process not found' } };
|
|
111
115
|
return { status: 200, body: result };
|
|
112
116
|
},
|
|
113
|
-
getLog: async ({ params, query }) => {
|
|
114
|
-
const result = await handlers.getProcessLog(ctx, query, params.id);
|
|
117
|
+
getLog: async ({ params, query, req }) => {
|
|
118
|
+
const result = await handlers.getProcessLog(ctx, query, params.id, await access(req));
|
|
115
119
|
if (!result)
|
|
116
120
|
return { status: 404, body: { message: 'Process not found' } };
|
|
117
121
|
return { status: 200, body: result };
|
|
118
122
|
},
|
|
119
|
-
getTreeLog: async ({ params, query }) => {
|
|
120
|
-
const result = await handlers.getProcessTreeLog(ctx, query, params.id);
|
|
123
|
+
getTreeLog: async ({ params, query, req }) => {
|
|
124
|
+
const result = await handlers.getProcessTreeLog(ctx, query, params.id, await access(req));
|
|
121
125
|
if (!result)
|
|
122
126
|
return { status: 404, body: { message: 'Process not found' } };
|
|
123
127
|
return { status: 200, body: result };
|
|
124
128
|
},
|
|
125
|
-
launch: async ({ params, query, body }) => {
|
|
126
|
-
const result = await handlers.launchProcess(ctx, query, params.id, body?.resume === true);
|
|
129
|
+
launch: async ({ params, query, body, req }) => {
|
|
130
|
+
const result = await handlers.launchProcess(ctx, query, params.id, body?.resume === true, null, await access(req));
|
|
127
131
|
return result;
|
|
128
132
|
},
|
|
129
|
-
cancel: async ({ params, query }) => {
|
|
130
|
-
const result = await handlers.cancelProcess(ctx, query, params.id);
|
|
133
|
+
cancel: async ({ params, query, req }) => {
|
|
134
|
+
const result = await handlers.cancelProcess(ctx, query, params.id, await access(req));
|
|
131
135
|
return result;
|
|
132
136
|
},
|
|
133
|
-
dismiss: async ({ params, query }) => {
|
|
134
|
-
const result = await handlers.dismissProcess(ctx, query, params.id);
|
|
137
|
+
dismiss: async ({ params, query, req }) => {
|
|
138
|
+
const result = await handlers.dismissProcess(ctx, query, params.id, await access(req));
|
|
135
139
|
return result;
|
|
136
140
|
},
|
|
137
|
-
|
|
138
|
-
const result = await handlers.
|
|
139
|
-
return
|
|
141
|
+
resurrect: async ({ params, query, body, req }) => {
|
|
142
|
+
const result = await handlers.resurrectProcess(ctx, query, params.id, body?.sessionId ?? null, await access(req));
|
|
143
|
+
return result;
|
|
144
|
+
},
|
|
145
|
+
resync: async ({ query, body, req }) => {
|
|
146
|
+
const result = await handlers.resyncProcesses(ctx, query, body.clean, body.metadataFilter, await access(req));
|
|
147
|
+
return result;
|
|
140
148
|
},
|
|
141
149
|
}, app);
|
|
142
150
|
app.get('/api/optio/instances', async (req, res) => {
|
|
143
|
-
|
|
151
|
+
if (!(await gateInstances(await access(req)))) {
|
|
152
|
+
res.status(403).json({ message: 'Forbidden' });
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
const instances = await discoverInstances(dbOpts, redis, opts.prefix);
|
|
144
156
|
res.json({ instances });
|
|
145
157
|
});
|
|
146
158
|
// SSE tree stream
|
|
@@ -156,7 +168,7 @@ export function registerOptioApi(app, opts) {
|
|
|
156
168
|
}
|
|
157
169
|
const { db, prefix } = resolveDb(dbOpts, sseOpts);
|
|
158
170
|
const col = db.collection(`${prefix}_processes`);
|
|
159
|
-
const proc = await
|
|
171
|
+
const proc = await findScopedProcess(col, id, (await access(req)).scope);
|
|
160
172
|
if (!proc) {
|
|
161
173
|
res.status(404).json({ message: 'Process not found' });
|
|
162
174
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"express.js","sourceRoot":"","sources":["../../src/adapters/express.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,6EAA6E;AAC7E,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAKpD,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"express.js","sourceRoot":"","sources":["../../src/adapters/express.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ import type { FastifyInstance } from 'fastify';
|
|
|
2
2
|
import type { Db } from 'mongodb';
|
|
3
3
|
import type { MongoClient } from 'mongodb';
|
|
4
4
|
import type { Redis } from 'ioredis';
|
|
5
|
-
import type { AuthCallback } from '../auth.js';
|
|
5
|
+
import type { AuthCallback, AuthorizeCallback, ScopeCallback } from '../auth.js';
|
|
6
6
|
import { type OptioContext } from '../context.js';
|
|
7
7
|
/**
|
|
8
8
|
* `verbose`: when true, the widget reverse-proxy's per-request upstream-call
|
|
@@ -31,6 +31,10 @@ export type OptioApiOptions = (BaseOptioApiOptions & {
|
|
|
31
31
|
interface BaseOptioApiOptions {
|
|
32
32
|
prefix?: string;
|
|
33
33
|
authenticate: AuthCallback<import('fastify').FastifyRequest>;
|
|
34
|
+
/** Confine each request to a tenant's processes (see auth.ts). */
|
|
35
|
+
scope?: ScopeCallback<import('fastify').FastifyRequest>;
|
|
36
|
+
/** Decide mutating actions and instance discovery (see auth.ts). */
|
|
37
|
+
authorize?: AuthorizeCallback<import('fastify').FastifyRequest>;
|
|
34
38
|
verbose?: boolean;
|
|
35
39
|
}
|
|
36
40
|
export declare function registerOptioApi(app: FastifyInstance, opts: OptioApiOptions): OptioContext | void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fastify.d.ts","sourceRoot":"","sources":["../../src/adapters/fastify.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"fastify.d.ts","sourceRoot":"","sources":["../../src/adapters/fastify.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAOrC,OAAO,KAAK,EAAE,YAAY,EAAe,iBAAiB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAoB9F,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AA0XtE;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,eAAe,GACvB,CAAC,mBAAmB,GAAG;IAAE,GAAG,EAAE,YAAY,CAAA;CAAE,CAAC,GAC7C,CAAC,mBAAmB,GAAG;IAAE,KAAK,EAAE,KAAK,CAAA;CAAE,GAAG,CACtC;IAAE,EAAE,EAAE,EAAE,CAAC;IAAC,WAAW,CAAC,EAAE,KAAK,CAAA;CAAE,GAC/B;IAAE,WAAW,EAAE,WAAW,CAAC;IAAC,EAAE,CAAC,EAAE,KAAK,CAAA;CAAE,CAC3C,CAAC,CAAC;AAEP,UAAU,mBAAmB;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,YAAY,CAAC,OAAO,SAAS,EAAE,cAAc,CAAC,CAAC;IAC7D,kEAAkE;IAClE,KAAK,CAAC,EAAE,aAAa,CAAC,OAAO,SAAS,EAAE,cAAc,CAAC,CAAC;IACxD,oEAAoE;IACpE,SAAS,CAAC,EAAE,iBAAiB,CAAC,OAAO,SAAS,EAAE,cAAc,CAAC,CAAC;IAChE,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAKD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,eAAe,GAAG,YAAY,GAAG,IAAI,CAgajG"}
|