@fungi.computer/oyster 0.6.0 → 0.8.0
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 +133 -78
- package/dist/agent-archive-projection.d.ts +8 -0
- package/dist/agent-archive-projection.js +49 -0
- package/dist/agent-schedules.d.ts +61 -0
- package/dist/agent-schedules.js +19 -0
- package/dist/agents.d.ts +35 -14
- package/dist/agents.js +93 -144
- package/dist/app-builds.d.ts +7 -2
- package/dist/app-builds.js +19 -2
- package/dist/approval-capability.d.ts +1 -1
- package/dist/approval-capability.js +11 -16
- package/dist/approval-home.d.ts +2 -1
- package/dist/approval-home.js +5 -3
- package/dist/apps/catalog.js +1 -1
- package/dist/apps/gate.d.ts +4 -7
- package/dist/apps/gate.js +14 -29
- package/dist/apps/index.d.ts +1 -1
- package/dist/apps/installation.d.ts +4 -42
- package/dist/apps/installation.js +7 -75
- package/dist/apps/operations.js +0 -10
- package/dist/apps/permissions.d.ts +18 -8
- package/dist/apps/permissions.js +7 -1
- package/dist/auth.d.ts +1 -24
- package/dist/auth.js +9 -39
- package/dist/authorization.d.ts +307 -0
- package/dist/authorization.js +542 -0
- package/dist/boot-host-script.js +1 -1
- package/dist/build/build-jobs.d.ts +2 -2
- package/dist/build/candidate-builder.d.ts +2 -0
- package/dist/build/candidate-builder.js +5 -1
- package/dist/build/candidate-cli.js +3 -0
- package/dist/build/candidate-cli.mjs +70 -22
- package/dist/build/job-log.d.ts +23 -0
- package/dist/build/job-log.js +88 -0
- package/dist/build/local-build.d.ts +9 -1
- package/dist/build/local-build.js +11 -9
- package/dist/cloudflare.d.ts +4 -1
- package/dist/cloudflare.js +1 -1
- package/dist/files.js +9 -8
- package/dist/git-admission.d.ts +3 -3
- package/dist/git-admission.js +4 -6
- package/dist/git-door.d.ts +8 -7
- package/dist/git-door.js +18 -17
- package/dist/git.d.ts +1 -1
- package/dist/host.d.ts +33 -40
- package/dist/host.js +156 -275
- package/dist/installation-execution.js +14 -5
- package/dist/installation-operations.d.ts +4 -180
- package/dist/installation-operations.js +1 -5
- package/dist/installation-store-generation.d.ts +4 -1
- package/dist/installation-store-generation.js +59 -6
- package/dist/internal/delivery.js +0 -1
- package/dist/internal/host-gate.d.ts +3 -2
- package/dist/internal/host-gate.js +5 -18
- package/dist/internal/invocation-timing.d.ts +16 -0
- package/dist/internal/invocation-timing.js +23 -0
- package/dist/internal/registry-installations.js +1 -0
- package/dist/invocation.d.ts +15 -14
- package/dist/invocation.js +58 -26
- package/dist/keys.d.ts +2 -19
- package/dist/keys.js +1 -37
- package/dist/mcp.d.ts +15 -27
- package/dist/mcp.js +105 -155
- package/dist/page/agent-browser.d.ts +15 -0
- package/dist/page/agent-browser.js +162 -0
- package/dist/page/app-permissions-port.d.ts +3 -0
- package/dist/page/app-permissions-port.js +43 -0
- package/dist/page/app-permissions.d.ts +11 -0
- package/dist/page/app-permissions.js +296 -0
- package/dist/page/isolated-page-theme.d.ts +2 -0
- package/dist/page/isolated-page-theme.js +11 -0
- package/dist/page/mount.d.ts +2 -13
- package/dist/page/mount.js +7 -93
- package/dist/page-script.d.ts +0 -3
- package/dist/page-script.js +3 -4
- package/dist/standalone/agent-archive-owner.d.ts +42 -0
- package/dist/standalone/agent-archive-owner.js +116 -0
- package/dist/standalone/agent-archive-schedules.d.ts +6 -0
- package/dist/standalone/agent-archive-schedules.js +76 -0
- package/dist/standalone/agent-archive.d.ts +31 -0
- package/dist/standalone/agent-archive.js +67 -0
- package/dist/standalone/agent-computers.d.ts +7 -6
- package/dist/standalone/agent-computers.js +4 -7
- package/dist/standalone/agent-mail.d.ts +2 -2
- package/dist/standalone/agents.d.ts +186 -20
- package/dist/standalone/agents.js +251 -30
- package/dist/standalone/app-builds-binding.js +1 -1
- package/dist/standalone/app-set.js +2 -54
- package/dist/standalone/app-source.d.ts +3 -4
- package/dist/standalone/app-source.js +12 -9
- package/dist/standalone/builds.d.ts +2 -14
- package/dist/standalone/builds.js +15 -13
- package/dist/standalone/computer-fleet.d.ts +4 -4
- package/dist/standalone/computer-fleet.js +13 -42
- package/dist/standalone/computer.d.ts +4 -3
- package/dist/standalone/computer.js +52 -53
- package/dist/standalone/dashboard-approval.d.ts +10 -0
- package/dist/standalone/dashboard-approval.js +66 -0
- package/dist/standalone/machine-link.d.ts +4 -221
- package/dist/standalone/machine-link.js +21 -15
- package/dist/standalone/media.d.ts +1 -0
- package/dist/standalone/media.js +20 -14
- package/dist/standalone/owner-routes.d.ts +16 -0
- package/dist/standalone/owner-routes.js +21 -0
- package/dist/standalone/permission-resources.d.ts +5 -0
- package/dist/standalone/permission-resources.js +31 -0
- package/dist/standalone/registry.d.ts +7 -0
- package/dist/standalone/registry.js +3 -0
- package/dist/standalone/tenancy.d.ts +0 -3
- package/dist/standalone/tenancy.js +2 -5
- package/dist/standalone/worker-routes.d.ts +19 -0
- package/dist/standalone/worker-routes.js +9 -0
- package/dist/standalone/worker.d.ts +1 -1
- package/dist/standalone/worker.js +27 -35
- package/dist/standalone/workflow-binding.d.ts +10 -3
- package/dist/standalone/workflow-binding.js +22 -5
- package/dist/standalone/workflow-git-capture.js +2 -1
- package/dist/standalone/workflow-host.d.ts +8 -103
- package/dist/standalone/workflow-host.js +1 -1
- package/dist/standalone/workflow-node-capture.js +2 -2
- package/dist/standalone/workflow-root-authority.d.ts +1 -1
- package/dist/standalone/workflow-root-authority.js +1 -1
- package/dist/standalone/workflow-schedules.d.ts +31 -4
- package/dist/standalone/workflow-schedules.js +18 -5
- package/dist/standalone/workflow-webhooks.d.ts +4 -18
- package/dist/standalone/workflow-webhooks.js +5 -5
- package/dist/standalone/workflows.d.ts +53 -27
- package/dist/standalone/workflows.js +9 -3
- package/dist/storage-frame.d.ts +6 -6
- package/dist/testing/capabilities.d.ts +7 -6
- package/dist/testing/capabilities.js +3 -6
- package/dist/testing/installation.d.ts +0 -1
- package/dist/testing/installation.js +2 -5
- package/dist/workers-git.d.ts +12 -4
- package/dist/workers-git.js +38 -35
- package/dist/workers.d.ts +9 -1
- package/dist/workers.js +44 -8
- package/dist/workflows.d.ts +4 -0
- package/dist/workflows.js +2 -0
- package/docs/api/README.md +7 -0
- package/docs/api/agent-schedules.md +176 -0
- package/docs/api/agents.md +34 -13
- package/docs/api/app-storage.md +1 -1
- package/docs/api/apps.md +323 -225
- package/docs/api/auth.md +0 -55
- package/docs/api/authorization.md +1300 -0
- package/docs/api/build.md +42 -38
- package/docs/api/cloudflare.md +3 -3
- package/docs/api/git.md +20 -11
- package/docs/api/host.md +64 -192
- package/docs/api/index.md +1 -1
- package/docs/api/invocation.md +14 -14
- package/docs/api/keys.md +1 -98
- package/docs/api/mcp.md +43 -40
- package/docs/api/modules.md +2 -0
- package/docs/api/page/mount.md +16 -19
- package/docs/api/workers-git.md +46 -12
- package/docs/api/workers.md +111 -222
- package/package.json +41 -22
- package/dist/page/computer-target.d.ts +0 -3
- package/dist/page/computer-target.js +0 -9
- package/dist/standalone/channel-session-door.d.ts +0 -4
- package/dist/standalone/channel-session-door.js +0 -72
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { createOysterGitWorker, createOysterGitMcpOwner, oysterGitRoot, } from "../workers-git.js";
|
|
7
7
|
import { defaultTenant, tenantScope } from "../tenant.js";
|
|
8
|
-
import { oysterPrincipalIsOwner } from "../
|
|
8
|
+
import { oysterPrincipalIsOwner } from "../authorization.js";
|
|
9
9
|
import { standaloneComputerControl } from "./computer-control.js";
|
|
10
|
+
import { standalonePermissionResources } from "./permission-resources.js";
|
|
10
11
|
import { onBoxVmIngress } from "@fungi.computer/computer";
|
|
11
12
|
import { WorkerEntrypoint } from "cloudflare:workers";
|
|
12
13
|
import { installationWorkerEntrypoint } from "../installation-execution.js";
|
|
@@ -25,15 +26,13 @@ import { standalonePreviewRequest } from "./preview.js";
|
|
|
25
26
|
import { standaloneMachineLinkRoutes, } from "./machine-link.js";
|
|
26
27
|
export { MachineLinkDO } from "./machine-link.js";
|
|
27
28
|
import { standaloneWorkflowControl } from "./workflow-control.js";
|
|
28
|
-
import { standaloneWorkflowWebhookRoutes
|
|
29
|
-
import {
|
|
29
|
+
import { standaloneWorkflowWebhookRoutes } from "./workflow-webhooks.js";
|
|
30
|
+
import { serveDoors } from "../authorization.js";
|
|
31
|
+
import { standaloneWorkerRoutes } from "./worker-routes.js";
|
|
30
32
|
import { HTTPException } from "hono/http-exception";
|
|
31
|
-
import {
|
|
32
|
-
import {
|
|
33
|
-
import { standaloneAgentComputerRoutes } from "./agent-computers.js";
|
|
34
|
-
import { agentDirectoryForScope } from "./agent-directory.js";
|
|
33
|
+
import { standaloneOwnerRoutes } from "./owner-routes.js";
|
|
34
|
+
import { standaloneComputerSelection } from "./computer-fleet.js";
|
|
35
35
|
import { serveOysterComputerEgress, } from "./computer-egress.js";
|
|
36
|
-
import { appSourceOwnerRoutes, } from "./app-source.js";
|
|
37
36
|
export { StandaloneGraphWorkflow } from "./workflows.js";
|
|
38
37
|
export { MediaOperationDO } from "@fungi.computer/darkroom/cloudflare";
|
|
39
38
|
/** A tenant's registry: it owns that tenant's installations and App builds. */
|
|
@@ -68,13 +67,17 @@ const standaloneRoot = (selectComputer) => {
|
|
|
68
67
|
}),
|
|
69
68
|
homeInstallationId: (env) => env.OYSTER_HOME_INSTALLATION,
|
|
70
69
|
agents: standaloneAgents,
|
|
70
|
+
permissionResources: (env, scope) => standalonePermissionResources({
|
|
71
|
+
// Acquire the registry stub only when owner inventory is requested.
|
|
72
|
+
computerFleet: (memberId, request) => tenantRegistry(env, scope).computerFleet(memberId, request),
|
|
73
|
+
}, standaloneAgents(env, scope)),
|
|
71
74
|
workflows: standaloneWorkflowControl,
|
|
72
75
|
computerControl: (env, scope) => (principal) => oysterPrincipalIsOwner(principal)
|
|
73
76
|
? standaloneComputerControl(tenantRegistry(env, scope), principal.actor.memberId)
|
|
74
77
|
: null,
|
|
75
78
|
workspace: async (env, keysLive, scope, request) => standaloneWorkspace(env, keysLive, await selectComputer(tenantRegistry(env, scope), request)),
|
|
76
|
-
capabilities: (env, workspace
|
|
77
|
-
...standaloneComputerCapabilities(env, workspace
|
|
79
|
+
capabilities: (env, workspace) => [
|
|
80
|
+
...standaloneComputerCapabilities(env, workspace),
|
|
78
81
|
...workersMedia(env, workspace),
|
|
79
82
|
],
|
|
80
83
|
// A presented bearer names the library that issued it; only that
|
|
@@ -101,15 +104,7 @@ const standaloneRoot = (selectComputer) => {
|
|
|
101
104
|
};
|
|
102
105
|
},
|
|
103
106
|
// Operator source seeding and owner builds share the one owner guard.
|
|
104
|
-
ownerRoutes: (env, scope) =>
|
|
105
|
-
.route("/", standaloneBuildRoutes(() => tenantRegistry(env, scope)))
|
|
106
|
-
.route("/", standaloneComputerFleetRoutes(() => tenantRegistry(env, scope)))
|
|
107
|
-
.route("/", standaloneAgentComputerRoutes({
|
|
108
|
-
attach: (principal, command) => agentDirectoryForScope(env, scope).attachComputer(command, principal, scope.tenantId),
|
|
109
|
-
detach: (principal, command) => agentDirectoryForScope(env, scope).detachComputer(command, principal, scope.tenantId),
|
|
110
|
-
read: (principal, agentId) => agentDirectoryForScope(env, scope).readAgentComputers(agentId, principal, scope.tenantId),
|
|
111
|
-
}))
|
|
112
|
-
.route("/", standaloneWorkflowWebhookControls(env, () => root.hostFor(env, scope))),
|
|
107
|
+
ownerRoutes: (env, scope) => standaloneOwnerRoutes(env, scope, () => root.hostFor(env, scope)),
|
|
113
108
|
});
|
|
114
109
|
return root;
|
|
115
110
|
};
|
|
@@ -190,21 +185,18 @@ export default {
|
|
|
190
185
|
const fetchOyster = oyster.fetch;
|
|
191
186
|
if (fetchOyster === undefined)
|
|
192
187
|
throw new Error("Oyster fetch handler is missing");
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
.onError(standaloneWorkerErrorHandler)
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
}))
|
|
207
|
-
.all("*", () => fetchOyster(request, env, context))
|
|
208
|
-
.fetch(request, env, context);
|
|
188
|
+
// Doors before any tenant is selected; every other path reaches the
|
|
189
|
+
// tenant host's own declared table.
|
|
190
|
+
return serveDoors(standaloneWorkerRoutes({
|
|
191
|
+
machineLink: (incoming) => serveDoors(standaloneMachineLinkRoutes(env).onError(standaloneWorkerErrorHandler)).fetch(incoming, env, context),
|
|
192
|
+
workflowWebhooks: standaloneWorkflowWebhookRoutes(env, async (incoming) => {
|
|
193
|
+
const admitted = await oysterRoot.admit(env, incoming);
|
|
194
|
+
return admitted === null
|
|
195
|
+
? null
|
|
196
|
+
: oysterRoot.hostFor(env, admitted.scope);
|
|
197
|
+
}),
|
|
198
|
+
// The tenant table answers the Worker's own incoming request.
|
|
199
|
+
tenant: async () => fetchOyster(request, env, context),
|
|
200
|
+
}).onError(standaloneWorkerErrorHandler)).fetch(request, env, context);
|
|
209
201
|
},
|
|
210
202
|
};
|
|
@@ -48,7 +48,7 @@ export type TriggerArmTarget = z.output<typeof triggerArmTargetSchema>;
|
|
|
48
48
|
export type ScheduleDisarmInput = z.output<typeof scheduleDisarmInputSchema>;
|
|
49
49
|
export type EventDisarmInput = z.output<typeof eventDisarmInputSchema>;
|
|
50
50
|
/** The frame gate needs only these run-owner calls; it re-decodes each reply with the method's owner schema. */
|
|
51
|
-
export type WorkflowRunCalls = Pick<StandaloneWorkflowRunsBase, "admitWorkflowGit" | "catalog" | "start" | "status" | "cancel" | "answerReview" | "armSchedule" | "disarmSchedule" | "schedules" | "armEventTrigger" | "disarmEventTrigger" | "eventTriggers" | "runs">;
|
|
51
|
+
export type WorkflowRunCalls = Pick<StandaloneWorkflowRunsBase, "admitWorkflowGit" | "catalog" | "start" | "status" | "cancel" | "answerReview" | "armSchedule" | "pauseSchedule" | "resumeSchedule" | "disarmSchedule" | "schedules" | "armEventTrigger" | "disarmEventTrigger" | "eventTriggers" | "runs">;
|
|
52
52
|
export type WorkflowBindingEnv = Readonly<{
|
|
53
53
|
WORKFLOW_RUNS: Readonly<{
|
|
54
54
|
getByName(installationId: string): WorkflowRunCalls;
|
|
@@ -130,7 +130,14 @@ export declare const workflowFrameMethods: {
|
|
|
130
130
|
} | undefined;
|
|
131
131
|
}]) | ((args: unknown) => [{
|
|
132
132
|
scheduleId: string;
|
|
133
|
-
}]) | ((args: unknown) => [
|
|
133
|
+
}]) | ((args: unknown) => [{
|
|
134
|
+
scheduleId: string;
|
|
135
|
+
}]) | ((args: unknown) => [{
|
|
136
|
+
scheduleId: string;
|
|
137
|
+
}]) | ((args: unknown) => [{
|
|
138
|
+
limit: number;
|
|
139
|
+
after?: string | undefined;
|
|
140
|
+
}]) | ((args: unknown) => [{
|
|
134
141
|
digest: string & {
|
|
135
142
|
readonly appReleaseKind: "Sha256Digest";
|
|
136
143
|
};
|
|
@@ -150,7 +157,7 @@ export declare const workflowFrameMethods: {
|
|
|
150
157
|
workflowId?: string | undefined;
|
|
151
158
|
}]);
|
|
152
159
|
decodeResult: (value: unknown) => z.core.util.JSONType;
|
|
153
|
-
requiredOperations: () => ("catalog" | "runGraph" | "armSchedule" | "disarmSchedule" | "schedules" | "armEventTrigger" | "disarmEventTrigger" | "eventTriggers" | "cancel" | "answerReview" | "graphStatus" | "runs")[];
|
|
160
|
+
requiredOperations: () => ("catalog" | "runGraph" | "armSchedule" | "disarmSchedule" | "pauseSchedule" | "resumeSchedule" | "schedules" | "armEventTrigger" | "disarmEventTrigger" | "eventTriggers" | "cancel" | "answerReview" | "graphStatus" | "runs")[];
|
|
154
161
|
};
|
|
155
162
|
};
|
|
156
163
|
};
|
|
@@ -2,7 +2,7 @@ import * as S from "effect/Schema";
|
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { graphReviewSchema, reviewAnswerSchema } from "@fungi.computer/braid";
|
|
4
4
|
import { graphStartRequestSchema, workflowTriggerTargetSchema, } from "@fungi.computer/braid/runtime";
|
|
5
|
-
import { runReply, answerReviewReply, catalogReplySchema, statusReply, cancelReplySchema, runsReplySchema, runsInputSchema, eventArmReplySchema, eventDisarmInputSchema, eventTriggersReplySchema, scheduleArmReplySchema, scheduleDisarmInputSchema, schedulesReplySchema, triggerDisarmReplySchema, triggerListInputSchema, } from "@fungi.computer/workflows-wire";
|
|
5
|
+
import { runReply, answerReviewReply, catalogReplySchema, statusReply, cancelReplySchema, runsReplySchema, runsInputSchema, eventArmReplySchema, eventDisarmInputSchema, eventTriggersReplySchema, scheduleArmReplySchema, scheduleDisarmInputSchema, schedulePauseInputSchema, schedulePauseReplySchema, scheduleResumeInputSchema, scheduleResumeReplySchema, scheduleListInputSchema, schedulesReplySchema, triggerDisarmReplySchema, triggerListInputSchema, } from "@fungi.computer/workflows-wire";
|
|
6
6
|
import { workflowAttestationSchema } from "@fungi.computer/puffball/app-method-runtime";
|
|
7
7
|
import { appEventFactSchema, } from "@fungi.computer/puffball/app-event-facts";
|
|
8
8
|
import { AppInstanceError } from "../index.js";
|
|
@@ -26,7 +26,9 @@ const workflowArgs = {
|
|
|
26
26
|
answerReview: effectArgs(S.Tuple([reviewKey])),
|
|
27
27
|
armSchedule: (args) => z.tuple([triggerArmTargetSchema]).parse(args),
|
|
28
28
|
disarmSchedule: (args) => z.tuple([scheduleDisarmInputSchema]).parse(args),
|
|
29
|
-
|
|
29
|
+
pauseSchedule: (args) => z.tuple([schedulePauseInputSchema]).parse(args),
|
|
30
|
+
resumeSchedule: (args) => z.tuple([scheduleResumeInputSchema]).parse(args),
|
|
31
|
+
schedules: (args) => z.tuple([scheduleListInputSchema]).parse(args),
|
|
30
32
|
armEventTrigger: (args) => z.tuple([triggerArmTargetSchema]).parse(args),
|
|
31
33
|
disarmEventTrigger: (args) => z.tuple([eventDisarmInputSchema]).parse(args),
|
|
32
34
|
eventTriggers: (args) => z.tuple([triggerListInputSchema]).parse(args),
|
|
@@ -40,6 +42,8 @@ const workflowResults = {
|
|
|
40
42
|
answerReview: answerReviewReply,
|
|
41
43
|
armSchedule: scheduleArmReplySchema,
|
|
42
44
|
disarmSchedule: triggerDisarmReplySchema,
|
|
45
|
+
pauseSchedule: schedulePauseReplySchema,
|
|
46
|
+
resumeSchedule: scheduleResumeReplySchema,
|
|
43
47
|
schedules: schedulesReplySchema,
|
|
44
48
|
armEventTrigger: eventArmReplySchema,
|
|
45
49
|
disarmEventTrigger: triggerDisarmReplySchema,
|
|
@@ -53,6 +57,8 @@ const workflowMethod = z.enum([
|
|
|
53
57
|
"cancel",
|
|
54
58
|
"answerReview",
|
|
55
59
|
"armSchedule",
|
|
60
|
+
"pauseSchedule",
|
|
61
|
+
"resumeSchedule",
|
|
56
62
|
"disarmSchedule",
|
|
57
63
|
"schedules",
|
|
58
64
|
"armEventTrigger",
|
|
@@ -184,10 +190,21 @@ export async function dispatchWorkflowBinding(env, frame, props, method, args) {
|
|
|
184
190
|
result = await runs.disarmSchedule(frame.facts, input);
|
|
185
191
|
break;
|
|
186
192
|
}
|
|
187
|
-
case "
|
|
188
|
-
workflowArgs.
|
|
189
|
-
result = await runs.
|
|
193
|
+
case "pauseSchedule": {
|
|
194
|
+
const [input] = workflowArgs.pauseSchedule(args);
|
|
195
|
+
result = await runs.pauseSchedule(frame.facts, input);
|
|
190
196
|
break;
|
|
197
|
+
}
|
|
198
|
+
case "resumeSchedule": {
|
|
199
|
+
const [input] = workflowArgs.resumeSchedule(args);
|
|
200
|
+
result = await runs.resumeSchedule(frame.facts, input);
|
|
201
|
+
break;
|
|
202
|
+
}
|
|
203
|
+
case "schedules": {
|
|
204
|
+
const [input] = workflowArgs.schedules(args);
|
|
205
|
+
result = await runs.schedules(frame.facts, input);
|
|
206
|
+
break;
|
|
207
|
+
}
|
|
191
208
|
case "armEventTrigger": {
|
|
192
209
|
const [input] = workflowArgs.armEventTrigger(args);
|
|
193
210
|
result = await runs.armEventTrigger(frame.facts, input);
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { repositoryRefSchema } from "@fungi.computer/agar/git";
|
|
2
2
|
import { approvedBindingGrants } from "../apps/index.js";
|
|
3
3
|
import { createInstallationGitAdmission } from "../git.js";
|
|
4
|
-
import {
|
|
4
|
+
import { resolveBackend } from "../host.js";
|
|
5
|
+
import { oysterPrincipalIsOwner } from "../authorization.js";
|
|
5
6
|
import { invocationCallerContext } from "../invocation.js";
|
|
6
7
|
/** Installation Git only; Team-source needs its separate authoritative namespace owner. */
|
|
7
8
|
export function createStandaloneWorkflowInstallationGitCapture(options) {
|
|
@@ -127,25 +127,6 @@ export declare function createStandaloneWorkflowHost(owner: WatchdogSqliteOwner,
|
|
|
127
127
|
}> | null;
|
|
128
128
|
};
|
|
129
129
|
status: "enabled" | "disabled" | "deleted";
|
|
130
|
-
visibility: "private" | "public";
|
|
131
|
-
approvedAnonymousMethods: readonly Readonly<{
|
|
132
|
-
name: string;
|
|
133
|
-
digest: import("@fungi.computer/puffball").Sha256Digest;
|
|
134
|
-
}>[];
|
|
135
|
-
anonymousApproval: Readonly<{
|
|
136
|
-
by: {
|
|
137
|
-
kind: "member";
|
|
138
|
-
memberId: string;
|
|
139
|
-
} | {
|
|
140
|
-
kind: "agent";
|
|
141
|
-
agentId: string;
|
|
142
|
-
} | {
|
|
143
|
-
kind: "team-key";
|
|
144
|
-
keyId: string;
|
|
145
|
-
};
|
|
146
|
-
at: number;
|
|
147
|
-
authorityVersion: number;
|
|
148
|
-
}> | null;
|
|
149
130
|
}>;
|
|
150
131
|
verified: Readonly<{
|
|
151
132
|
release: import("@fungi.computer/puffball").Release;
|
|
@@ -263,25 +244,6 @@ export declare function createStandaloneWorkflowHost(owner: WatchdogSqliteOwner,
|
|
|
263
244
|
}> | null;
|
|
264
245
|
};
|
|
265
246
|
status: "enabled" | "disabled" | "deleted";
|
|
266
|
-
visibility: "private" | "public";
|
|
267
|
-
approvedAnonymousMethods: readonly Readonly<{
|
|
268
|
-
name: string;
|
|
269
|
-
digest: import("@fungi.computer/puffball").Sha256Digest;
|
|
270
|
-
}>[];
|
|
271
|
-
anonymousApproval: Readonly<{
|
|
272
|
-
by: {
|
|
273
|
-
kind: "member";
|
|
274
|
-
memberId: string;
|
|
275
|
-
} | {
|
|
276
|
-
kind: "agent";
|
|
277
|
-
agentId: string;
|
|
278
|
-
} | {
|
|
279
|
-
kind: "team-key";
|
|
280
|
-
keyId: string;
|
|
281
|
-
};
|
|
282
|
-
at: number;
|
|
283
|
-
authorityVersion: number;
|
|
284
|
-
}> | null;
|
|
285
247
|
}>;
|
|
286
248
|
verified: Readonly<{
|
|
287
249
|
release: import("@fungi.computer/puffball").Release;
|
|
@@ -349,25 +311,6 @@ export declare function createStandaloneWorkflowHost(owner: WatchdogSqliteOwner,
|
|
|
349
311
|
}> | null;
|
|
350
312
|
};
|
|
351
313
|
status: "enabled" | "disabled" | "deleted";
|
|
352
|
-
visibility: "private" | "public";
|
|
353
|
-
approvedAnonymousMethods: readonly Readonly<{
|
|
354
|
-
name: string;
|
|
355
|
-
digest: import("@fungi.computer/puffball").Sha256Digest;
|
|
356
|
-
}>[];
|
|
357
|
-
anonymousApproval: Readonly<{
|
|
358
|
-
by: {
|
|
359
|
-
kind: "member";
|
|
360
|
-
memberId: string;
|
|
361
|
-
} | {
|
|
362
|
-
kind: "agent";
|
|
363
|
-
agentId: string;
|
|
364
|
-
} | {
|
|
365
|
-
kind: "team-key";
|
|
366
|
-
keyId: string;
|
|
367
|
-
};
|
|
368
|
-
at: number;
|
|
369
|
-
authorityVersion: number;
|
|
370
|
-
}> | null;
|
|
371
314
|
}>;
|
|
372
315
|
pin: {
|
|
373
316
|
selection: {
|
|
@@ -468,25 +411,6 @@ export declare function createStandaloneWorkflowHost(owner: WatchdogSqliteOwner,
|
|
|
468
411
|
}> | null;
|
|
469
412
|
};
|
|
470
413
|
status: "enabled" | "disabled" | "deleted";
|
|
471
|
-
visibility: "private" | "public";
|
|
472
|
-
approvedAnonymousMethods: readonly Readonly<{
|
|
473
|
-
name: string;
|
|
474
|
-
digest: import("@fungi.computer/puffball").Sha256Digest;
|
|
475
|
-
}>[];
|
|
476
|
-
anonymousApproval: Readonly<{
|
|
477
|
-
by: {
|
|
478
|
-
kind: "member";
|
|
479
|
-
memberId: string;
|
|
480
|
-
} | {
|
|
481
|
-
kind: "agent";
|
|
482
|
-
agentId: string;
|
|
483
|
-
} | {
|
|
484
|
-
kind: "team-key";
|
|
485
|
-
keyId: string;
|
|
486
|
-
};
|
|
487
|
-
at: number;
|
|
488
|
-
authorityVersion: number;
|
|
489
|
-
}> | null;
|
|
490
414
|
}>;
|
|
491
415
|
verified: Readonly<{
|
|
492
416
|
release: import("@fungi.computer/puffball").Release;
|
|
@@ -568,25 +492,6 @@ export declare function createStandaloneWorkflowHost(owner: WatchdogSqliteOwner,
|
|
|
568
492
|
}> | null;
|
|
569
493
|
};
|
|
570
494
|
status: "enabled" | "disabled" | "deleted";
|
|
571
|
-
visibility: "private" | "public";
|
|
572
|
-
approvedAnonymousMethods: readonly Readonly<{
|
|
573
|
-
name: string;
|
|
574
|
-
digest: import("@fungi.computer/puffball").Sha256Digest;
|
|
575
|
-
}>[];
|
|
576
|
-
anonymousApproval: Readonly<{
|
|
577
|
-
by: {
|
|
578
|
-
kind: "member";
|
|
579
|
-
memberId: string;
|
|
580
|
-
} | {
|
|
581
|
-
kind: "agent";
|
|
582
|
-
agentId: string;
|
|
583
|
-
} | {
|
|
584
|
-
kind: "team-key";
|
|
585
|
-
keyId: string;
|
|
586
|
-
};
|
|
587
|
-
at: number;
|
|
588
|
-
authorityVersion: number;
|
|
589
|
-
}> | null;
|
|
590
495
|
}>;
|
|
591
496
|
verified: Readonly<{
|
|
592
497
|
release: import("@fungi.computer/puffball").Release;
|
|
@@ -654,13 +559,13 @@ export declare function createStandaloneWorkflowHost(owner: WatchdogSqliteOwner,
|
|
|
654
559
|
readonly input: {
|
|
655
560
|
readonly [x: string]: S.Json;
|
|
656
561
|
};
|
|
562
|
+
readonly title: string;
|
|
657
563
|
readonly apps: {
|
|
658
564
|
readonly [x: string]: {
|
|
659
565
|
readonly appId: string;
|
|
660
566
|
readonly role?: string | undefined;
|
|
661
567
|
};
|
|
662
568
|
};
|
|
663
|
-
readonly title: string;
|
|
664
569
|
readonly nodes: readonly ({
|
|
665
570
|
readonly id: string;
|
|
666
571
|
readonly kind: "code";
|
|
@@ -698,19 +603,19 @@ export declare function createStandaloneWorkflowHost(owner: WatchdogSqliteOwner,
|
|
|
698
603
|
} | {
|
|
699
604
|
readonly id: string;
|
|
700
605
|
readonly kind: "review";
|
|
701
|
-
readonly timeout: number;
|
|
702
606
|
readonly title: string;
|
|
607
|
+
readonly timeout: number;
|
|
703
608
|
readonly reviewers: "runner" | "owners";
|
|
704
609
|
readonly show: readonly {
|
|
705
610
|
readonly node: string;
|
|
706
611
|
readonly port: string;
|
|
707
612
|
}[];
|
|
613
|
+
readonly detail?: string | undefined;
|
|
708
614
|
readonly choices?: readonly {
|
|
709
615
|
readonly label: string;
|
|
710
616
|
readonly id: string;
|
|
711
617
|
readonly description?: string | undefined;
|
|
712
618
|
}[] | undefined;
|
|
713
|
-
readonly detail?: string | undefined;
|
|
714
619
|
} | {
|
|
715
620
|
readonly id: string;
|
|
716
621
|
readonly kind: "condition";
|
|
@@ -795,19 +700,19 @@ export declare function createStandaloneWorkflowHost(owner: WatchdogSqliteOwner,
|
|
|
795
700
|
} | {
|
|
796
701
|
readonly id: string;
|
|
797
702
|
readonly kind: "review";
|
|
798
|
-
readonly timeout: number;
|
|
799
703
|
readonly title: string;
|
|
704
|
+
readonly timeout: number;
|
|
800
705
|
readonly reviewers: "runner" | "owners";
|
|
801
706
|
readonly show: readonly {
|
|
802
707
|
readonly node: string;
|
|
803
708
|
readonly port: string;
|
|
804
709
|
}[];
|
|
710
|
+
readonly detail?: string | undefined;
|
|
805
711
|
readonly choices?: readonly {
|
|
806
712
|
readonly label: string;
|
|
807
713
|
readonly id: string;
|
|
808
714
|
readonly description?: string | undefined;
|
|
809
715
|
}[] | undefined;
|
|
810
|
-
readonly detail?: string | undefined;
|
|
811
716
|
} | {
|
|
812
717
|
readonly id: string;
|
|
813
718
|
readonly kind: "condition";
|
|
@@ -860,10 +765,10 @@ export declare function createStandaloneWorkflowHost(owner: WatchdogSqliteOwner,
|
|
|
860
765
|
readonly triggers?: readonly ({
|
|
861
766
|
readonly id: string;
|
|
862
767
|
readonly on: "webhook";
|
|
768
|
+
readonly when?: import("@fungi.computer/braid").Predicate | undefined;
|
|
863
769
|
readonly input?: {
|
|
864
770
|
readonly [x: string]: import("@fungi.computer/braid").Mapping;
|
|
865
771
|
} | undefined;
|
|
866
|
-
readonly when?: import("@fungi.computer/braid").Predicate | undefined;
|
|
867
772
|
readonly title?: string | undefined;
|
|
868
773
|
} | {
|
|
869
774
|
readonly id: string;
|
|
@@ -878,14 +783,14 @@ export declare function createStandaloneWorkflowHost(owner: WatchdogSqliteOwner,
|
|
|
878
783
|
readonly title?: string | undefined;
|
|
879
784
|
} | {
|
|
880
785
|
readonly id: string;
|
|
786
|
+
readonly app: string;
|
|
881
787
|
readonly on: "event";
|
|
882
788
|
readonly event: string;
|
|
883
|
-
readonly app: string;
|
|
884
789
|
readonly eventDigest: string;
|
|
790
|
+
readonly when?: import("@fungi.computer/braid").Predicate | undefined;
|
|
885
791
|
readonly input?: {
|
|
886
792
|
readonly [x: string]: import("@fungi.computer/braid").Mapping;
|
|
887
793
|
} | undefined;
|
|
888
|
-
readonly when?: import("@fungi.computer/braid").Predicate | undefined;
|
|
889
794
|
readonly repository?: import("@fungi.computer/braid").Mapping | undefined;
|
|
890
795
|
readonly title?: string | undefined;
|
|
891
796
|
})[] | undefined;
|
|
@@ -10,7 +10,7 @@ import { appCapabilityIds } from "@fungi.computer/puffball";
|
|
|
10
10
|
import { createGraphWorkflowRuns, createTriggerRunReservations, compileForMember, graphStartRequestSchema, preparationFromRun, planNodeCall, workflowRunContextSchema, } from "@fungi.computer/braid/runtime";
|
|
11
11
|
import { appMethodCallContextSchema } from "@fungi.computer/puffball/app";
|
|
12
12
|
import { appEventFactSchema, } from "@fungi.computer/puffball/app-event-facts";
|
|
13
|
-
import { keyAppAccess } from "../
|
|
13
|
+
import { keyAppAccess } from "../authorization.js";
|
|
14
14
|
import { Validator } from "@cfworker/json-schema";
|
|
15
15
|
// Mirrors packages/oyster/src/cloudflare.ts's MAX_APP_REPLY_BYTES. That
|
|
16
16
|
// module imports "cloudflare:workers" at the top level, so it cannot be
|
|
@@ -3,7 +3,8 @@ import { appBackendBindingsSchema } from "@fungi.computer/puffball/app";
|
|
|
3
3
|
import { catalogMethods } from "@fungi.computer/braid";
|
|
4
4
|
import { workflowMethodRequiresComputer, } from "@fungi.computer/braid/runtime";
|
|
5
5
|
import { admitMethodMetadata, appInvocationCeiling, approvedBindingGrants, deriveDeclaredOperations, scopedBindings, } from "../apps/index.js";
|
|
6
|
-
import {
|
|
6
|
+
import { verifyRelease } from "../host.js";
|
|
7
|
+
import { oysterPrincipalIsOwner } from "../authorization.js";
|
|
7
8
|
import { invocationCallerContext } from "../invocation.js";
|
|
8
9
|
/** Capture one compiled node through the same metadata admission as ordinary App calls. */
|
|
9
10
|
export function createStandaloneWorkflowNodeCapture(options) {
|
|
@@ -33,7 +34,6 @@ export function createStandaloneWorkflowNodeCapture(options) {
|
|
|
33
34
|
principal: { actor: caller.actor, role: caller.role ?? null },
|
|
34
35
|
installation: {
|
|
35
36
|
status: installation.status,
|
|
36
|
-
visibility: installation.visibility,
|
|
37
37
|
instanceId: installation.instanceId,
|
|
38
38
|
authority: installation.authority,
|
|
39
39
|
artifactDigest: installation.release.artifact.artifactDigest,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type WorkflowRunAuthority } from "@fungi.computer/braid/runtime";
|
|
2
2
|
import type { RepositoryRef } from "@fungi.computer/agar/git";
|
|
3
3
|
import type { AppToolPolicy } from "../apps/index.js";
|
|
4
|
-
import {
|
|
4
|
+
import type { LiveOysterKey } from "../keys.js";
|
|
5
5
|
import type { StandaloneTenancy } from "./tenancy.js";
|
|
6
6
|
import { type StandaloneWorkflowNodeCaptureOptions } from "./workflow-node-capture.js";
|
|
7
7
|
import type { StandaloneWorkflowAuthorityReaderOptions } from "./workflow-authority-readers.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createWorkflowRunAuthority, createWorkflowCeilingCapture, planInstallationLevels, } from "@fungi.computer/braid/runtime";
|
|
2
2
|
import { AppInstanceError } from "../index.js";
|
|
3
|
-
import { keyAppAccess } from "../
|
|
3
|
+
import { keyAppAccess } from "../authorization.js";
|
|
4
4
|
import { createStandaloneWorkflowAuthorityReaders } from "./workflow-authority-readers.js";
|
|
5
5
|
import { createStandaloneWorkflowNodeCapture, } from "./workflow-node-capture.js";
|
|
6
6
|
import { createStandaloneWorkflowInstallationGitCapture } from "./workflow-git-capture.js";
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createWorkflowSchedules, type WorkflowInstallationAuthority } from "@fungi.computer/braid/runtime";
|
|
2
2
|
import type { AppMethodCallContext } from "@fungi.computer/puffball/app-method-runtime";
|
|
3
3
|
import type { workflowAgentAuthority } from "../workflow-agent-authority.js";
|
|
4
|
+
import { type ScheduleListInput } from "@fungi.computer/workflows-wire";
|
|
4
5
|
import { type TriggerArmTarget, type ScheduleDisarmInput } from "./workflow-binding.js";
|
|
5
6
|
/** The host supplies this result only after reopening the protected invocation. */
|
|
6
7
|
export type TriggerAdmission = Readonly<{
|
|
@@ -10,7 +11,7 @@ export type TriggerAdmission = Readonly<{
|
|
|
10
11
|
/** The admitted frame's selection and verified artifact, pinned on arm. */
|
|
11
12
|
installationAuthority: WorkflowInstallationAuthority;
|
|
12
13
|
}>;
|
|
13
|
-
export type ScheduleOperation = "armSchedule" | "disarmSchedule" | "schedules";
|
|
14
|
+
export type ScheduleOperation = "armSchedule" | "pauseSchedule" | "resumeSchedule" | "disarmSchedule" | "schedules";
|
|
14
15
|
/** Host controls and alarm delivery compose the shared schedule owner unchanged. */
|
|
15
16
|
export declare function createStandaloneWorkflowSchedules<Frame>(options: Parameters<typeof createWorkflowSchedules>[0] & {
|
|
16
17
|
admitInvocation(frame: Frame, operation: ScheduleOperation): Promise<TriggerAdmission>;
|
|
@@ -37,19 +38,45 @@ export declare function createStandaloneWorkflowSchedules<Frame>(options: Parame
|
|
|
37
38
|
} | {
|
|
38
39
|
error: string;
|
|
39
40
|
}>;
|
|
40
|
-
|
|
41
|
+
pause(frame: Frame, raw: {
|
|
42
|
+
scheduleId: string;
|
|
43
|
+
}): Promise<{
|
|
44
|
+
kind: "not_found";
|
|
45
|
+
} | {
|
|
46
|
+
kind: "paused";
|
|
47
|
+
} | {
|
|
41
48
|
error: string;
|
|
42
|
-
|
|
49
|
+
}>;
|
|
50
|
+
resume(frame: Frame, raw: {
|
|
51
|
+
scheduleId: string;
|
|
52
|
+
}): Promise<{
|
|
53
|
+
kind: "not_found";
|
|
54
|
+
reason?: never;
|
|
55
|
+
} | {
|
|
56
|
+
kind: "refused";
|
|
57
|
+
reason: string;
|
|
43
58
|
} | {
|
|
59
|
+
kind: "resumed";
|
|
60
|
+
reason?: never;
|
|
61
|
+
} | {
|
|
62
|
+
error: string;
|
|
63
|
+
}>;
|
|
64
|
+
list(frame: Frame, raw: ScheduleListInput): Promise<{
|
|
44
65
|
schedules: {
|
|
45
66
|
scheduleId: string;
|
|
46
67
|
installationId: string;
|
|
47
68
|
workflowId: string;
|
|
48
69
|
triggerId: string;
|
|
70
|
+
cron: {
|
|
71
|
+
expression: string;
|
|
72
|
+
timeZone: string;
|
|
73
|
+
};
|
|
49
74
|
nextDueAt: number;
|
|
50
75
|
state: "active" | "finished" | "paused" | "cancelled";
|
|
51
76
|
lastError: string | null;
|
|
52
77
|
}[];
|
|
53
|
-
|
|
78
|
+
nextCursor: string | null;
|
|
79
|
+
} | {
|
|
80
|
+
error: string;
|
|
54
81
|
}>;
|
|
55
82
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createWorkflowSchedules, } from "@fungi.computer/braid/runtime";
|
|
2
|
-
import { scheduleDisarmInputSchema } from "@fungi.computer/workflows-wire";
|
|
2
|
+
import { scheduleDisarmInputSchema, schedulePauseInputSchema, scheduleResumeInputSchema, scheduleListInputSchema, } from "@fungi.computer/workflows-wire";
|
|
3
3
|
import { triggerArmTargetSchema, } from "./workflow-binding.js";
|
|
4
4
|
/** Host controls and alarm delivery compose the shared schedule owner unchanged. */
|
|
5
5
|
export function createStandaloneWorkflowSchedules(options) {
|
|
@@ -27,13 +27,26 @@ export function createStandaloneWorkflowSchedules(options) {
|
|
|
27
27
|
return { error: "not_granted" };
|
|
28
28
|
return schedules.disarm(authority.principal, libraryId, scheduleId);
|
|
29
29
|
},
|
|
30
|
-
async
|
|
30
|
+
async pause(frame, raw) {
|
|
31
|
+
const { scheduleId } = schedulePauseInputSchema.parse(raw);
|
|
32
|
+
const { libraryId, authority } = await options.admitInvocation(frame, "pauseSchedule");
|
|
33
|
+
if (authority === null)
|
|
34
|
+
return { error: "not_granted" };
|
|
35
|
+
return schedules.pause(authority.principal, libraryId, scheduleId);
|
|
36
|
+
},
|
|
37
|
+
async resume(frame, raw) {
|
|
38
|
+
const { scheduleId } = scheduleResumeInputSchema.parse(raw);
|
|
39
|
+
const { libraryId, authority } = await options.admitInvocation(frame, "resumeSchedule");
|
|
40
|
+
if (authority === null)
|
|
41
|
+
return { error: "not_granted" };
|
|
42
|
+
return schedules.resume(authority.principal, libraryId, scheduleId);
|
|
43
|
+
},
|
|
44
|
+
async list(frame, raw) {
|
|
45
|
+
const input = scheduleListInputSchema.parse(raw);
|
|
31
46
|
const { libraryId, authority } = await options.admitInvocation(frame, "schedules");
|
|
32
47
|
if (authority === null)
|
|
33
48
|
return { error: "not_granted" };
|
|
34
|
-
return
|
|
35
|
-
schedules: await schedules.list(authority.principal, libraryId),
|
|
36
|
-
};
|
|
49
|
+
return schedules.list(authority.principal, libraryId, input);
|
|
37
50
|
},
|
|
38
51
|
};
|
|
39
52
|
}
|
|
@@ -1,22 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { BlankEnv } from "hono/types";
|
|
2
|
+
import { type Routes } from "../authorization.js";
|
|
2
3
|
import type { OysterEnv, OysterHost } from "../host.js";
|
|
3
4
|
import type { StandaloneWorkflowEnv } from "./workflows.js";
|
|
4
5
|
/** The root resolves the origin before this unauthenticated signed-delivery path. */
|
|
5
|
-
export declare function standaloneWorkflowWebhookRoutes(env: Pick<StandaloneWorkflowEnv, "WORKFLOW_RUNS">, hostFor: (request: Request) => Promise<Pick<OysterHost, "installations"> | null>):
|
|
6
|
-
"/api/installations/:installationId/workflows/webhooks/:bindingId": {
|
|
7
|
-
$all: {
|
|
8
|
-
input: {
|
|
9
|
-
param: {
|
|
10
|
-
installationId: string;
|
|
11
|
-
} & {
|
|
12
|
-
bindingId: string;
|
|
13
|
-
};
|
|
14
|
-
};
|
|
15
|
-
output: {};
|
|
16
|
-
outputFormat: string;
|
|
17
|
-
status: import("hono/utils/http-status").StatusCode;
|
|
18
|
-
};
|
|
19
|
-
};
|
|
20
|
-
}, "/", "/api/installations/:installationId/workflows/webhooks/:bindingId">;
|
|
6
|
+
export declare function standaloneWorkflowWebhookRoutes(env: Pick<StandaloneWorkflowEnv, "WORKFLOW_RUNS">, hostFor: (request: Request) => Promise<Pick<OysterHost, "installations"> | null>): Routes<BlankEnv>;
|
|
21
7
|
/** Mounted only under the root's authenticated owner routes; the DO re-admits. */
|
|
22
|
-
export declare function standaloneWorkflowWebhookControls(env: Pick<StandaloneWorkflowEnv, "WORKFLOW_RUNS">, hostFor: () => Promise<Pick<OysterHost, "installations">>):
|
|
8
|
+
export declare function standaloneWorkflowWebhookControls(env: Pick<StandaloneWorkflowEnv, "WORKFLOW_RUNS">, hostFor: () => Promise<Pick<OysterHost, "installations">>): Routes<OysterEnv>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { door, owner, routes } from "../authorization.js";
|
|
2
2
|
import { bodyLimit } from "hono/body-limit";
|
|
3
3
|
import * as Schema from "effect/Schema";
|
|
4
4
|
import { workflowWebhookCommandSchema } from "../webhooks.js";
|
|
@@ -11,7 +11,7 @@ async function libraryExists(host, installationId) {
|
|
|
11
11
|
}
|
|
12
12
|
/** The root resolves the origin before this unauthenticated signed-delivery path. */
|
|
13
13
|
export function standaloneWorkflowWebhookRoutes(env, hostFor) {
|
|
14
|
-
return
|
|
14
|
+
return routes().all("/api/installations/:installationId/workflows/webhooks/:bindingId", door("a signed delivery; the library's run owner verifies its signature"), async (context) => {
|
|
15
15
|
const host = await hostFor(context.req.raw);
|
|
16
16
|
const installationId = context.req.param("installationId");
|
|
17
17
|
if (host === null || !(await libraryExists(host, installationId)))
|
|
@@ -24,7 +24,7 @@ export function standaloneWorkflowWebhookRoutes(env, hostFor) {
|
|
|
24
24
|
}
|
|
25
25
|
/** Mounted only under the root's authenticated owner routes; the DO re-admits. */
|
|
26
26
|
export function standaloneWorkflowWebhookControls(env, hostFor) {
|
|
27
|
-
return
|
|
27
|
+
return routes().post("/api/installations/:installationId/workflows/webhooks", owner("direct-or-app"), async (context, { principal }) => {
|
|
28
28
|
const installationId = context.req.param("installationId");
|
|
29
29
|
if (!(await libraryExists(await hostFor(), installationId)))
|
|
30
30
|
return refused();
|
|
@@ -34,6 +34,6 @@ export function standaloneWorkflowWebhookControls(env, hostFor) {
|
|
|
34
34
|
const command = workflowWebhookCommandSchema.safeParse(body.success);
|
|
35
35
|
if (!command.success)
|
|
36
36
|
return refused();
|
|
37
|
-
return env.WORKFLOW_RUNS.getByName(installationId).webhookControl(
|
|
38
|
-
});
|
|
37
|
+
return env.WORKFLOW_RUNS.getByName(installationId).webhookControl(principal, installationId, command.data);
|
|
38
|
+
}, { middleware: [bodyLimit({ maxSize: 64 * 1024, onError: refused })] });
|
|
39
39
|
}
|