@fungi.computer/oyster 0.2.0 → 0.3.1
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 +396 -72
- package/dist/agents.d.ts +3 -2
- package/dist/agents.js +4 -2
- package/dist/app-builds.d.ts +81 -8
- package/dist/app-builds.js +213 -60
- package/dist/app-storage.d.ts +3 -3
- package/dist/approval-capability.d.ts +5 -0
- package/dist/approval-capability.js +46 -0
- package/dist/approval-home.d.ts +51 -0
- package/dist/approval-home.js +226 -0
- package/dist/apps/catalog.d.ts +335 -0
- package/dist/apps/catalog.js +46 -0
- package/dist/apps/gate.d.ts +20 -6
- package/dist/apps/gate.js +42 -16
- package/dist/apps/index.d.ts +3 -1
- package/dist/apps/index.js +3 -1
- package/dist/apps/installation.d.ts +132 -51
- package/dist/apps/installation.js +176 -70
- package/dist/apps/permissions.d.ts +247 -0
- package/dist/apps/permissions.js +255 -0
- package/dist/boot-capability-route.d.ts +15 -0
- package/dist/boot-capability-route.js +196 -0
- package/dist/boot-capability.d.ts +103 -0
- package/dist/boot-capability.js +141 -0
- package/dist/boot-construction.d.ts +12 -0
- package/dist/boot-construction.js +175 -0
- package/dist/boot-gate.d.ts +267 -0
- package/dist/boot-gate.js +236 -0
- package/dist/boot-host-script.d.ts +2 -0
- package/dist/boot-host-script.js +1 -0
- package/dist/boot-mount.d.ts +21 -0
- package/dist/boot-mount.js +65 -0
- package/dist/browser/boot.d.ts +73 -0
- package/dist/browser/boot.js +502 -0
- package/dist/browser/browser.d.ts +104 -0
- package/dist/browser/browser.js +374 -0
- package/dist/browser/capability-source.d.ts +76 -0
- package/dist/browser/capability-source.js +338 -0
- package/dist/browser/cdp-client.d.ts +56 -0
- package/dist/browser/cdp-client.js +184 -0
- package/dist/browser/errors.d.ts +79 -0
- package/dist/browser/errors.js +32 -0
- package/dist/browser/index.d.ts +16 -0
- package/dist/browser/index.js +14 -0
- package/dist/browser/lease-registry.d.ts +61 -0
- package/dist/browser/lease-registry.js +101 -0
- package/dist/browser/operations.d.ts +225 -0
- package/dist/browser/operations.js +137 -0
- package/dist/browser/page.d.ts +25 -0
- package/dist/browser/page.js +172 -0
- package/dist/browser/quick-reads.d.ts +29 -0
- package/dist/browser/quick-reads.js +160 -0
- package/dist/browser/sessions.d.ts +52 -0
- package/dist/browser/sessions.js +118 -0
- package/dist/browser/url-policy.d.ts +18 -0
- package/dist/browser/url-policy.js +58 -0
- package/dist/build/app-imports.d.ts +12 -0
- package/dist/build/app-imports.js +105 -0
- package/dist/build/build-policy.d.ts +5 -3
- package/dist/build/build-policy.js +5 -3
- package/dist/build/candidate-builder.d.ts +1 -1
- package/dist/build/candidate-cli.mjs +8375 -334
- package/dist/build/local-build.d.ts +2 -0
- package/dist/build/local-build.js +28 -6
- package/dist/build/snapshot-package-store.d.ts +1 -1
- package/dist/build/snapshot-package-store.js +7 -2
- package/dist/build/workspace-build.d.ts +92 -5
- package/dist/build/workspace-build.js +93 -19
- package/dist/build.d.ts +1 -1
- package/dist/build.js +1 -1
- package/dist/catalog-frame.js +1 -1
- package/dist/cloudflare.d.ts +13 -3
- package/dist/cloudflare.js +102 -4
- package/dist/frame-binding-wire-script.js +1 -1
- package/dist/frame-binding-wire.js +4 -2
- package/dist/git-auth.d.ts +0 -2
- package/dist/git-auth.js +0 -2
- package/dist/git.d.ts +0 -1
- package/dist/git.js +0 -2
- package/dist/host.d.ts +39 -13
- package/dist/host.js +268 -142
- package/dist/index.d.ts +25 -15
- package/dist/index.js +39 -16
- package/dist/install-release-cli.d.ts +2 -0
- package/dist/install-release-cli.js +46 -0
- package/dist/installation-client.d.ts +43 -0
- package/dist/installation-client.js +178 -0
- package/dist/installation-execution.d.ts +11 -0
- package/dist/installation-execution.js +184 -0
- package/dist/installation-operations.d.ts +1437 -0
- package/dist/installation-operations.js +664 -0
- package/dist/installation-store-generation.d.ts +3 -0
- package/dist/installation-store-generation.js +16 -0
- package/dist/instance-id.d.ts +10 -0
- package/dist/instance-id.js +10 -0
- package/dist/instance-refusal.d.ts +11 -0
- package/dist/instance-refusal.js +21 -0
- package/dist/internal/delivery.js +4 -2
- package/dist/internal/host-gate.js +7 -1
- package/dist/internal/registry-installations.js +4 -4
- package/dist/keys.d.ts +5 -1
- package/dist/keys.js +10 -2
- package/dist/machine-link/authority.d.ts +89 -0
- package/dist/machine-link/authority.js +37 -0
- package/dist/machine-link/client.d.ts +66 -0
- package/dist/machine-link/client.js +94 -0
- package/dist/machine-link/delivery.d.ts +18 -0
- package/dist/machine-link/delivery.js +55 -0
- package/dist/machine-link/enrollment.d.ts +111 -0
- package/dist/machine-link/enrollment.js +286 -0
- package/dist/machine-link/fences.d.ts +37 -0
- package/dist/machine-link/fences.js +166 -0
- package/dist/machine-link/home.d.ts +20 -0
- package/dist/machine-link/home.js +24 -0
- package/dist/machine-link/host.d.ts +43 -0
- package/dist/machine-link/host.js +189 -0
- package/dist/machine-link/index.d.ts +15 -0
- package/dist/machine-link/index.js +15 -0
- package/dist/machine-link/link.d.ts +48 -0
- package/dist/machine-link/link.js +223 -0
- package/dist/machine-link/presence.d.ts +10 -0
- package/dist/machine-link/presence.js +25 -0
- package/dist/machine-link/workers.d.ts +6 -0
- package/dist/machine-link/workers.js +6 -0
- package/dist/mcp-owner.d.ts +2 -2
- package/dist/mcp-owner.js +41 -33
- package/dist/mcp.d.ts +15 -3
- package/dist/mcp.js +146 -25
- package/dist/older-oyster-store-refusal.d.ts +4 -0
- package/dist/older-oyster-store-refusal.js +18 -0
- package/dist/older-oyster-store.d.ts +21 -0
- package/dist/older-oyster-store.js +43 -0
- package/dist/pack.d.ts +14 -3
- package/dist/pack.js +44 -19
- package/dist/page/app-access.d.ts +7 -0
- package/dist/page/app-access.js +75 -0
- package/dist/page/boot-host.js +57 -0
- package/dist/page/capabilities.d.ts +3 -3
- package/dist/page/capabilities.js +16 -12
- package/dist/page/computer-handles.d.ts +3 -3
- package/dist/page/computer-target.d.ts +3 -0
- package/dist/page/computer-target.js +9 -0
- package/dist/page/mount.d.ts +23 -3
- package/dist/page/mount.js +152 -16
- package/dist/page-assets.d.ts +22 -0
- package/dist/page-assets.js +28 -0
- package/dist/page-script.d.ts +3 -0
- package/dist/page-script.js +5 -4
- package/dist/release.d.ts +13 -6
- package/dist/release.js +10 -7
- package/dist/root-data.d.ts +16 -6
- package/dist/root-data.js +2 -2
- package/dist/source/index.d.ts +1 -1
- package/dist/source/team-source.d.ts +20 -8
- package/dist/source/team-source.js +39 -10
- package/dist/source/template-seed.d.ts +2 -2
- package/dist/standalone/agent-mail.d.ts +24 -0
- package/dist/standalone/agent-mail.js +62 -0
- package/dist/standalone/agent-store.d.ts +9 -0
- package/dist/standalone/agent-store.js +30 -0
- package/dist/standalone/agents.d.ts +68 -9
- package/dist/standalone/agents.js +428 -56
- package/dist/standalone/app-builds-binding.d.ts +20 -2
- package/dist/standalone/app-builds-binding.js +147 -23
- package/dist/standalone/app-set.d.ts +5 -2
- package/dist/standalone/app-set.js +186 -144
- package/dist/standalone/browser.d.ts +11 -0
- package/dist/standalone/browser.js +72 -0
- package/dist/standalone/builds.d.ts +13 -4
- package/dist/standalone/builds.js +28 -44
- package/dist/standalone/computer-egress.d.ts +2 -0
- package/dist/standalone/computer-egress.js +13 -4
- package/dist/standalone/computer-fleet.d.ts +43 -0
- package/dist/standalone/computer-fleet.js +200 -0
- package/dist/standalone/computer.d.ts +44 -9
- package/dist/standalone/computer.js +129 -22
- package/dist/standalone/install-apps-cli.js +43 -6
- package/dist/standalone/instance.d.ts +2 -2
- package/dist/standalone/instance.js +8 -11
- package/dist/standalone/machine-link.d.ts +354 -0
- package/dist/standalone/machine-link.js +368 -0
- package/dist/standalone/media.d.ts +2 -2
- package/dist/standalone/media.js +19 -16
- package/dist/standalone/preview.d.ts +2 -2
- package/dist/standalone/preview.js +37 -10
- package/dist/standalone/registry.d.ts +151 -9
- package/dist/standalone/registry.js +305 -8
- package/dist/standalone/worker.d.ts +19 -5
- package/dist/standalone/worker.js +90 -54
- package/dist/standalone/workflow-binding.d.ts +18 -22
- package/dist/standalone/workflow-binding.js +18 -18
- package/dist/standalone/workflow-control.d.ts +4 -0
- package/dist/standalone/workflow-control.js +40 -0
- package/dist/standalone/workflow-events.d.ts +2 -2
- package/dist/standalone/workflow-events.js +9 -10
- package/dist/standalone/workflow-git-capture.js +4 -3
- package/dist/standalone/workflow-host.d.ts +162 -161
- package/dist/standalone/workflow-host.js +101 -21
- package/dist/standalone/workflow-node-capture.js +11 -4
- package/dist/standalone/workflow-schedules.d.ts +5 -2
- package/dist/standalone/workflow-schedules.js +9 -10
- package/dist/standalone/workflow-trigger-host.d.ts +65 -5
- package/dist/standalone/workflow-trigger-host.js +2 -2
- package/dist/standalone/workflow-webhooks.d.ts +22 -0
- package/dist/standalone/workflow-webhooks.js +39 -0
- package/dist/standalone/workflows.d.ts +140 -43
- package/dist/standalone/workflows.js +198 -39
- package/dist/storage-frame.d.ts +6 -6
- package/dist/testing/capabilities.js +14 -3
- package/dist/testing/installation.js +26 -2
- package/dist/testing/worker.js +1 -1
- package/dist/testing/workers-runtime.d.ts +8 -2
- package/dist/testing/workers-runtime.js +20 -2
- package/dist/webhook-abuse.d.ts +25 -0
- package/dist/webhook-abuse.js +54 -0
- package/dist/webhook-custody.d.ts +144 -0
- package/dist/webhook-custody.js +222 -0
- package/dist/webhook-ingress.d.ts +36 -0
- package/dist/webhook-ingress.js +146 -0
- package/dist/webhooks.d.ts +111 -0
- package/dist/webhooks.js +189 -0
- package/dist/workers-git.d.ts +12 -17
- package/dist/workers-git.js +64 -52
- package/dist/workers.d.ts +226 -13
- package/dist/workers.js +363 -51
- package/dist/workflow-agent-authority.d.ts +8 -0
- package/dist/workflow-agent-authority.js +42 -0
- package/dist/workflows.d.ts +66 -0
- package/dist/workflows.js +97 -0
- package/docs/api/README.md +63 -37
- package/docs/api/agents.md +17 -0
- package/docs/api/app-storage.md +1 -1
- package/docs/api/apps.md +1394 -543
- package/docs/api/browser/boot.md +132 -0
- package/docs/api/browser.md +1440 -0
- package/docs/api/build-contract.md +38 -25
- package/docs/api/build.md +263 -84
- package/docs/api/cloudflare.md +93 -7
- package/docs/api/git.md +3 -13
- package/docs/api/host.md +944 -118
- package/docs/api/index.md +320 -18
- package/docs/api/keys.md +24 -1
- package/docs/api/mcp.md +59 -12
- package/docs/api/modules.md +33 -40
- package/docs/api/pack.md +57 -8
- package/docs/api/page/mount.md +92 -4
- package/docs/api/workers-git.md +103 -24
- package/docs/api/workers.md +1594 -244
- package/docs/site/agent-quickstart.mdx +28 -14
- package/examples/standalone/worker.ts +3 -1
- package/examples/standalone/wrangler.jsonc +2 -0
- package/package.json +73 -71
- package/dist/installation-consent.d.ts +0 -81
- package/dist/installation-consent.js +0 -84
- package/dist/shell/app-directory.d.ts +0 -542
- package/dist/shell/app-directory.js +0 -196
- package/dist/shell/browser-actions.d.ts +0 -7
- package/dist/shell/browser-actions.js +0 -56
- package/dist/shell/command-host.d.ts +0 -112
- package/dist/shell/command-host.js +0 -502
- package/dist/shell/commands.d.ts +0 -25
- package/dist/shell/commands.js +0 -78
- package/dist/shell/index.d.ts +0 -8
- package/dist/shell/index.js +0 -8
- package/dist/shell/keys.d.ts +0 -41
- package/dist/shell/keys.js +0 -134
- package/dist/shell/shell-module.d.ts +0 -55
- package/dist/shell/shell-module.js +0 -86
- package/dist/shell/window-manager.d.ts +0 -128
- package/dist/shell/window-manager.js +0 -730
- package/dist/shell/workbench-contract.d.ts +0 -68
- package/dist/shell/workbench-directory.d.ts +0 -332
- package/dist/shell/workbench-directory.js +0 -35
- package/dist/shell/workbench-host-types.d.ts +0 -96
- package/dist/shell/workbench-host-types.js +0 -1
- package/dist/shell/workbench-host.d.ts +0 -34
- package/dist/shell/workbench-host.js +0 -352
- package/dist/shell/workbench-model.d.ts +0 -194
- package/dist/shell/workbench-model.js +0 -53
- package/dist/shell/workbench.d.ts +0 -4
- package/dist/shell/workbench.js +0 -2
- package/docs/api/shell/app-directory.md +0 -599
- package/docs/api/shell/command-host.md +0 -224
- package/docs/api/shell/commands.md +0 -197
- package/docs/api/shell/keys.md +0 -183
- package/docs/api/shell/shell-module.md +0 -204
- package/docs/api/shell/window-manager.md +0 -267
- package/docs/api/shell/workbench-directory.md +0 -119
- package/docs/api/shell/workbench.md +0 -205
- package/docs/api/shell.md +0 -1915
- /package/dist/{shell/workbench-contract.js → page/boot-host.d.ts} +0 -0
|
@@ -1,38 +1,63 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The APPS guest binding on the standalone Bonsai root:
|
|
2
|
+
* The APPS guest binding on the standalone Bonsai root: register an App from
|
|
3
|
+
* its repository's committed root manifest, start a build job on
|
|
3
4
|
* this Oyster's one Computer, read a job's status, and install (or switch) a
|
|
4
5
|
* Release at an installation id. Every operation re-checks the caller is the
|
|
5
6
|
* tenant owner; the binding carries no key and no owner secret.
|
|
6
7
|
*/
|
|
7
8
|
import { z } from "zod";
|
|
9
|
+
import { buildStartFailureReply } from "./builds.js";
|
|
8
10
|
import * as Schema from "effect/Schema";
|
|
9
11
|
import { AppInstanceError } from "../index.js";
|
|
10
|
-
import { installOrSelect } from "../host.js";
|
|
12
|
+
import { installOrSelect, verifyRelease, } from "../host.js";
|
|
13
|
+
import { repositoryWorkflowSourceSchema } from "@fungi.computer/workflows-wire";
|
|
11
14
|
import { installationIdSchema } from "../apps/index.js";
|
|
12
15
|
import { appIdSchema, releaseSchema } from "@fungi.computer/puffball/effect";
|
|
16
|
+
import { gitRepositoryNameSchema } from "@fungi.computer/puffball/git-representation";
|
|
13
17
|
/** The calling tenant's registry owns its App builds. */
|
|
14
18
|
const buildRegistry = (env, scope) => env.REGISTRY.getByName(scope.durableName("registry"));
|
|
19
|
+
const repositoryName = Schema.String.check(Schema.makeFilter((name) => gitRepositoryNameSchema.safeParse(name).success));
|
|
20
|
+
const registrationArgs = Schema.decodeUnknownSync(Schema.Tuple([Schema.Struct({ repo: repositoryName })]), { onExcessProperty: "error" });
|
|
15
21
|
const buildInput = z.lazy(() => z.strictObject({
|
|
16
22
|
appId: z.string().min(1).max(256),
|
|
17
23
|
sourceRevision: z.string().min(1).max(256),
|
|
24
|
+
installationId: z.string().min(1).max(256).optional(),
|
|
18
25
|
}));
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
26
|
+
// Workflows wait for their particular job; Settings discovers the latest
|
|
27
|
+
// job for its captured installation's repository after reload.
|
|
28
|
+
const buildStatusArgs = Schema.decodeUnknownSync(Schema.Tuple([
|
|
29
|
+
Schema.Union([
|
|
30
|
+
Schema.Struct({
|
|
31
|
+
jobId: Schema.String.check(Schema.isMinLength(1), Schema.isMaxLength(256)),
|
|
32
|
+
}),
|
|
33
|
+
Schema.Struct({ repo: repositoryName }),
|
|
34
|
+
]),
|
|
35
|
+
]), { onExcessProperty: "error" });
|
|
22
36
|
const selectInput = z.lazy(() => z.strictObject({
|
|
23
37
|
installationId: z.string().min(1).max(256),
|
|
38
|
+
jobId: z.string().min(1).max(256),
|
|
24
39
|
release: z.unknown(),
|
|
25
40
|
}));
|
|
26
41
|
/** The Instance gate and native guest entrypoint share these argument codecs. */
|
|
27
42
|
export const appsFrameMethods = {
|
|
28
43
|
APPS: {
|
|
44
|
+
repository: {
|
|
45
|
+
decodeArgs: registrationArgs,
|
|
46
|
+
decodeResult: Schema.decodeUnknownSync(Schema.Json),
|
|
47
|
+
requiredOperations: () => ["repository"],
|
|
48
|
+
},
|
|
49
|
+
register: {
|
|
50
|
+
decodeArgs: registrationArgs,
|
|
51
|
+
decodeResult: Schema.decodeUnknownSync(Schema.Json),
|
|
52
|
+
requiredOperations: () => ["register"],
|
|
53
|
+
},
|
|
29
54
|
build: {
|
|
30
55
|
decodeArgs: (raw) => z.tuple([buildInput]).parse(raw),
|
|
31
56
|
decodeResult: Schema.decodeUnknownSync(Schema.Json),
|
|
32
57
|
requiredOperations: () => ["build"],
|
|
33
58
|
},
|
|
34
59
|
buildStatus: {
|
|
35
|
-
decodeArgs:
|
|
60
|
+
decodeArgs: buildStatusArgs,
|
|
36
61
|
decodeResult: Schema.decodeUnknownSync(Schema.Json),
|
|
37
62
|
requiredOperations: () => ["buildStatus"],
|
|
38
63
|
},
|
|
@@ -43,7 +68,7 @@ export const appsFrameMethods = {
|
|
|
43
68
|
},
|
|
44
69
|
},
|
|
45
70
|
};
|
|
46
|
-
/** Only a live owner call reaches build, status or select; a key or a
|
|
71
|
+
/** Only a live owner call reaches registration, build, status or select; a key or a
|
|
47
72
|
* member without the owner role is refused before any registry or host read. */
|
|
48
73
|
function callerOwner(frame) {
|
|
49
74
|
const subject = frame.facts.subject;
|
|
@@ -61,36 +86,129 @@ export async function dispatchAppsBuildsBinding(env, scope, frame, props, method
|
|
|
61
86
|
frame.signal.throwIfAborted();
|
|
62
87
|
if (props.binding !== "APPS")
|
|
63
88
|
throw new AppInstanceError("revoked");
|
|
89
|
+
if (method === "repository") {
|
|
90
|
+
const subject = frame.facts.subject;
|
|
91
|
+
if (frame.facts.selection.owner.kind !== "installation")
|
|
92
|
+
throw new AppInstanceError("revoked");
|
|
93
|
+
if (subject.kind === "call")
|
|
94
|
+
callerOwner(frame);
|
|
95
|
+
else if (subject.name !== "onGitPush")
|
|
96
|
+
throw new AppInstanceError("revoked");
|
|
97
|
+
const [input] = registrationArgs(args);
|
|
98
|
+
const installationId = frame.facts.selection.owner.id;
|
|
99
|
+
const source = await buildRegistry(env, scope).repositoryBuildSource(installationId, input.repo);
|
|
100
|
+
if (source === null)
|
|
101
|
+
return null;
|
|
102
|
+
const host = await backgroundHost();
|
|
103
|
+
if (host === null)
|
|
104
|
+
throw new AppInstanceError("revoked");
|
|
105
|
+
const installation = await host.installations.get(installationId);
|
|
106
|
+
if (installation?.status !== "enabled" ||
|
|
107
|
+
installation.instanceId !== frame.facts.instanceId ||
|
|
108
|
+
installation.authority.authorityVersion !==
|
|
109
|
+
frame.facts.selection.authorityVersion ||
|
|
110
|
+
installation.release.appId !== frame.facts.selection.appId ||
|
|
111
|
+
installation.release.releaseId !== frame.facts.selection.releaseId)
|
|
112
|
+
throw new AppInstanceError("revoked");
|
|
113
|
+
const verified = await verifyRelease(host.artifacts, installation.release, undefined, false);
|
|
114
|
+
frame.signal.throwIfAborted();
|
|
115
|
+
// invocationAuthorityOf pins executable backend bytes, not the App descriptor.
|
|
116
|
+
if (verified.backend?.digest !== frame.facts.artifactDigest)
|
|
117
|
+
throw new AppInstanceError("revoked");
|
|
118
|
+
return Schema.decodeUnknownSync(Schema.Json)(Schema.decodeUnknownSync(repositoryWorkflowSourceSchema)({
|
|
119
|
+
appId: source.appId,
|
|
120
|
+
installationId,
|
|
121
|
+
callerAppId: verified.release.appId,
|
|
122
|
+
callerSourceRevision: verified.release.artifact.provenance.sourceRevision,
|
|
123
|
+
}));
|
|
124
|
+
}
|
|
64
125
|
const principal = callerOwner(frame);
|
|
65
126
|
const requestedBy = principal.actor.kind === "member" ? principal.actor.memberId : "owner";
|
|
127
|
+
if (method === "register") {
|
|
128
|
+
const [input] = registrationArgs(args);
|
|
129
|
+
let result;
|
|
130
|
+
try {
|
|
131
|
+
result = await buildRegistry(env, scope).registerRepositoryApp({
|
|
132
|
+
memberId: requestedBy,
|
|
133
|
+
installationId: frame.facts.selection.owner.id,
|
|
134
|
+
repository: input.repo,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
frame.signal.throwIfAborted();
|
|
139
|
+
return { status: 503, body: { error: "App registration unavailable" } };
|
|
140
|
+
}
|
|
141
|
+
frame.signal.throwIfAborted();
|
|
142
|
+
if (result.kind === "registered")
|
|
143
|
+
return {
|
|
144
|
+
status: 200,
|
|
145
|
+
body: { appId: result.appId, sourceRevision: result.sourceRevision },
|
|
146
|
+
};
|
|
147
|
+
switch (result.kind) {
|
|
148
|
+
case "unauthorized":
|
|
149
|
+
return { status: 403, body: { error: "Owner only" } };
|
|
150
|
+
case "invalid_app":
|
|
151
|
+
return {
|
|
152
|
+
status: 400,
|
|
153
|
+
body: { error: "Repository has no valid root App manifest" },
|
|
154
|
+
};
|
|
155
|
+
case "conflict":
|
|
156
|
+
return {
|
|
157
|
+
status: 409,
|
|
158
|
+
body: {
|
|
159
|
+
error: "App identity is already registered to another source",
|
|
160
|
+
},
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
}
|
|
66
164
|
if (method === "build") {
|
|
67
165
|
const [input] = z.tuple([buildInput]).parse(args);
|
|
68
166
|
const appId = Schema.decodeUnknownSync(appIdSchema)(input.appId);
|
|
69
167
|
const registry = buildRegistry(env, scope);
|
|
70
|
-
|
|
168
|
+
const context = frame.facts.subject.kind === "call"
|
|
169
|
+
? frame.facts.subject.context
|
|
170
|
+
: undefined;
|
|
171
|
+
const workflowRequestId = context?.workflow === undefined ? undefined : context.idempotencyKey;
|
|
172
|
+
if (context?.workflow !== undefined && workflowRequestId === undefined)
|
|
173
|
+
throw new AppInstanceError("revoked");
|
|
174
|
+
const request = {
|
|
175
|
+
appId,
|
|
176
|
+
sourceRevision: input.sourceRevision,
|
|
177
|
+
requestedBy,
|
|
178
|
+
};
|
|
179
|
+
if (input.installationId !== undefined && workflowRequestId === undefined)
|
|
180
|
+
throw new AppInstanceError("revoked");
|
|
181
|
+
if (workflowRequestId !== undefined) {
|
|
182
|
+
request.workflow = {
|
|
183
|
+
requestId: workflowRequestId,
|
|
184
|
+
callerInstallationId: frame.facts.selection.owner.id,
|
|
185
|
+
};
|
|
186
|
+
if (input.installationId !== undefined)
|
|
187
|
+
request.workflow.installationId = input.installationId;
|
|
188
|
+
}
|
|
189
|
+
let result;
|
|
71
190
|
try {
|
|
72
|
-
|
|
73
|
-
appId,
|
|
74
|
-
sourceRevision: input.sourceRevision,
|
|
75
|
-
requestedBy,
|
|
76
|
-
});
|
|
191
|
+
result = await registry.startBuild(request);
|
|
77
192
|
}
|
|
78
193
|
catch {
|
|
79
|
-
return Schema.decodeUnknownSync(Schema.Json)(
|
|
80
|
-
status: 409,
|
|
81
|
-
body: { error: "App has no build source" },
|
|
82
|
-
});
|
|
194
|
+
return Schema.decodeUnknownSync(Schema.Json)(buildStartFailureReply("unavailable"));
|
|
83
195
|
}
|
|
84
196
|
frame.signal.throwIfAborted();
|
|
85
|
-
return Schema.decodeUnknownSync(Schema.Json)(
|
|
197
|
+
return Schema.decodeUnknownSync(Schema.Json)(result.kind === "started"
|
|
198
|
+
? { status: 202, body: result.build }
|
|
199
|
+
: buildStartFailureReply(result.reason));
|
|
86
200
|
}
|
|
87
201
|
if (method === "buildStatus") {
|
|
88
|
-
const [input] =
|
|
89
|
-
const
|
|
202
|
+
const [input] = buildStatusArgs(args);
|
|
203
|
+
const registry = buildRegistry(env, scope);
|
|
204
|
+
const build = "repo" in input
|
|
205
|
+
? await registry.readRepositoryBuild(frame.facts.selection.owner.id, input.repo)
|
|
206
|
+
: await registry.readBuild(input.jobId);
|
|
90
207
|
frame.signal.throwIfAborted();
|
|
208
|
+
const missingJob = build === null && "jobId" in input;
|
|
91
209
|
return Schema.decodeUnknownSync(Schema.Json)({
|
|
92
|
-
status:
|
|
93
|
-
body:
|
|
210
|
+
status: missingJob ? 404 : 200,
|
|
211
|
+
body: missingJob ? { error: "Not found" } : build,
|
|
94
212
|
});
|
|
95
213
|
}
|
|
96
214
|
if (method === "select") {
|
|
@@ -108,10 +226,16 @@ export async function dispatchAppsBuildsBinding(env, scope, frame, props, method
|
|
|
108
226
|
body: { error: "Invalid Release" },
|
|
109
227
|
});
|
|
110
228
|
}
|
|
229
|
+
if (frame.facts.subject.kind === "call" &&
|
|
230
|
+
frame.facts.subject.context.workflow !== undefined) {
|
|
231
|
+
const result = await buildRegistry(env, scope).installWorkflowBuild(input.jobId, installationId, release, requestedBy, frame.facts.selection.owner.id);
|
|
232
|
+
frame.signal.throwIfAborted();
|
|
233
|
+
return Schema.decodeUnknownSync(Schema.Json)(result);
|
|
234
|
+
}
|
|
111
235
|
const host = await backgroundHost();
|
|
112
236
|
if (host === null)
|
|
113
237
|
throw new AppInstanceError("revoked");
|
|
114
|
-
const response = await installOrSelect(host, installationId, release, principal);
|
|
238
|
+
const response = await installOrSelect(host, installationId, release, principal, "install-or-select", "app");
|
|
115
239
|
frame.signal.throwIfAborted();
|
|
116
240
|
return Schema.decodeUnknownSync(Schema.Json)(await responseResult(response));
|
|
117
241
|
}
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import * as Schema from "effect/Schema";
|
|
2
2
|
import { type PackOptions } from "../pack.js";
|
|
3
|
-
/** One starter App
|
|
3
|
+
/** One starter App's identity and source; its manifest owns the build recipe. */
|
|
4
4
|
export type StarterApp = Readonly<{
|
|
5
|
+
/** Selecting this configured dashboard approves its declared shell authority only. */
|
|
6
|
+
dashboard?: true;
|
|
5
7
|
installationId: string;
|
|
6
8
|
appId: string;
|
|
7
9
|
/** The App's directory in a Botanical checkout; its recipe is rooted there. */
|
|
8
10
|
directory: string;
|
|
9
11
|
/** Its own public source repository's name, the App at that repository's root. */
|
|
10
12
|
repository: string;
|
|
11
|
-
recipe: PackOptions["recipe"];
|
|
12
13
|
}>;
|
|
13
14
|
export declare const standaloneAppSet: readonly StarterApp[];
|
|
14
15
|
/** Where the starter Apps' sources come from. */
|
|
@@ -87,5 +88,7 @@ export declare function installStandaloneAppSet(options: Readonly<{
|
|
|
87
88
|
recipe: PackOptions["recipe"];
|
|
88
89
|
}>) => Promise<Response>;
|
|
89
90
|
pollMs?: number;
|
|
91
|
+
/** The idle wait between build status reads; the real timer by default. */
|
|
92
|
+
idle?: (ms: number, signal: AbortSignal) => Promise<void>;
|
|
90
93
|
waitMs?: number;
|
|
91
94
|
}>): Promise<readonly InstalledStarterApp[]>;
|