@fungi.computer/oyster 0.1.0 → 0.3.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 +376 -72
- package/dist/agent-avatars.d.ts +103 -0
- package/dist/agent-avatars.js +66 -0
- package/dist/agents.d.ts +15 -4
- package/dist/agents.js +43 -4
- package/dist/app-builds.d.ts +81 -8
- package/dist/app-builds.js +210 -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 +26 -12
- package/dist/apps/gate.js +48 -22
- package/dist/apps/index.d.ts +3 -1
- package/dist/apps/index.js +3 -1
- package/dist/apps/installation.d.ts +147 -66
- package/dist/apps/installation.js +193 -86
- 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 +8428 -337
- 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-egress.js +4 -4
- 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 +106 -8
- package/dist/frame-binding-wire-script.js +1 -1
- package/dist/frame-binding-wire.d.ts +1 -1
- package/dist/frame-binding-wire.js +5 -3
- package/dist/git-auth.d.ts +0 -2
- package/dist/git-auth.js +0 -2
- package/dist/git-journal.js +4 -4
- 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 +26 -15
- package/dist/index.js +40 -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/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 -7
- 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 +78 -12
- package/dist/standalone/agents.js +470 -59
- package/dist/standalone/app-builds-binding.d.ts +20 -2
- package/dist/standalone/app-builds-binding.js +151 -27
- package/dist/standalone/app-set.d.ts +5 -2
- package/dist/standalone/app-set.js +174 -143
- 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 +132 -25
- 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 +39 -12
- package/dist/standalone/registry.d.ts +149 -9
- package/dist/standalone/registry.js +299 -8
- package/dist/standalone/worker.d.ts +19 -5
- package/dist/standalone/worker.js +90 -54
- package/dist/standalone/workflow-binding.d.ts +28 -32
- package/dist/standalone/workflow-binding.js +20 -20
- 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 +177 -152
- package/dist/standalone/workflow-host.js +137 -30
- 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 +88 -6
- 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 +203 -50
- 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 +60 -55
- package/dist/workers.d.ts +224 -13
- package/dist/workers.js +351 -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 +1581 -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 -69
- package/dist/installation-consent.d.ts +0 -79
- package/dist/installation-consent.js +0 -82
- package/dist/shell/app-directory.d.ts +0 -542
- package/dist/shell/app-directory.js +0 -199
- 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 -124
- package/dist/shell/window-manager.js +0 -711
- 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 -347
- package/dist/shell/workbench-model.d.ts +0 -192
- 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
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
import type { AppPermissionRequest } from "@fungi.computer/agar";
|
|
3
|
+
import { type AppDeclaration, type AppCapabilityId } from "@fungi.computer/puffball/app";
|
|
4
|
+
import { type PermissionCatalogEntry } from "./catalog.js";
|
|
5
|
+
import type { SigilName } from "@fungi.computer/sigils";
|
|
6
|
+
import { type AppAuthority, type DeclaredOperations, type GrantCommand, type GrantChange, type ResourceRef } from "./installation.js";
|
|
7
|
+
/** A host-provided resource identity and its display label. */
|
|
8
|
+
export type ResourceOption = {
|
|
9
|
+
kind: string;
|
|
10
|
+
id: string;
|
|
11
|
+
label: string;
|
|
12
|
+
};
|
|
13
|
+
/** Includes newly declared operations and capabilities the owner has narrowed. */
|
|
14
|
+
export declare function pendingCapabilities(authority: Pick<AppAuthority, "approvedGrants">, declaration: Pick<AppDeclaration, "capabilities">, declaredOperations: DeclaredOperations): AppDeclaration["capabilities"];
|
|
15
|
+
/** How an App's runtime permission request relates to the owner's stored grants. */
|
|
16
|
+
export type GrantRequestDecision = Readonly<{
|
|
17
|
+
kind: "covered";
|
|
18
|
+
}> | Readonly<{
|
|
19
|
+
kind: "customize";
|
|
20
|
+
}> | Readonly<{
|
|
21
|
+
kind: "refused";
|
|
22
|
+
code: "not_declared" | "stale_authority" | "window_scope_unavailable";
|
|
23
|
+
}> | Readonly<{
|
|
24
|
+
kind: "ask";
|
|
25
|
+
adds: readonly GrantChange[];
|
|
26
|
+
command: Extract<GrantCommand, {
|
|
27
|
+
kind: "change-grants";
|
|
28
|
+
}>;
|
|
29
|
+
}>;
|
|
30
|
+
/** Bound the real SDK request; an Allow never silently widens selected resources. */
|
|
31
|
+
export declare function grantRequestFor(authority: AppAuthority, facts: Readonly<{
|
|
32
|
+
declaration: Pick<AppDeclaration, "capabilities">;
|
|
33
|
+
declaredOperations: DeclaredOperations;
|
|
34
|
+
}>, request: AppPermissionRequest, window: Readonly<{
|
|
35
|
+
computerId: string | null;
|
|
36
|
+
}>): GrantRequestDecision;
|
|
37
|
+
/**
|
|
38
|
+
* A draft contains approvals, never the broader declared-operation projection.
|
|
39
|
+
* @inline
|
|
40
|
+
*/
|
|
41
|
+
export type PermissionGrant = Readonly<{
|
|
42
|
+
operations: readonly string[];
|
|
43
|
+
resources: "tenant-scope" | readonly ResourceRef[];
|
|
44
|
+
}>;
|
|
45
|
+
/**
|
|
46
|
+
* Capability approvals being edited; null removes the capability's grant.
|
|
47
|
+
* @inlineType PermissionGrant
|
|
48
|
+
*/
|
|
49
|
+
export type PermissionDraft = ReadonlyMap<AppCapabilityId, PermissionGrant | null>;
|
|
50
|
+
/** One switch, scope, resource or operation change applied to a draft. */
|
|
51
|
+
export type PermissionEdit = Readonly<{
|
|
52
|
+
kind: "switch" | "all";
|
|
53
|
+
capability: AppCapabilityId;
|
|
54
|
+
on: boolean;
|
|
55
|
+
}> | Readonly<{
|
|
56
|
+
kind: "resource";
|
|
57
|
+
capability: AppCapabilityId;
|
|
58
|
+
resource: ResourceRef;
|
|
59
|
+
on: boolean;
|
|
60
|
+
}> | Readonly<{
|
|
61
|
+
kind: "operation";
|
|
62
|
+
capability: AppCapabilityId;
|
|
63
|
+
operation: string;
|
|
64
|
+
on: boolean;
|
|
65
|
+
}>;
|
|
66
|
+
/** The saved operation ceiling is the starting point, including empty operation rows. */
|
|
67
|
+
export declare function draftOf(authority: AppAuthority): PermissionDraft;
|
|
68
|
+
/** An edit changes one capability; unrelated saved operations and scopes are retained. */
|
|
69
|
+
export declare function editPermissions(draft: PermissionDraft, edit: PermissionEdit, declared: DeclaredOperations): PermissionDraft;
|
|
70
|
+
/** Only touched capability rows cross the save boundary. */
|
|
71
|
+
export declare function planGrantChange(baseline: AppAuthority, draft: PermissionDraft): readonly GrantChange[];
|
|
72
|
+
/** A conflict preserves the person's edits while taking fresh untouched capabilities. */
|
|
73
|
+
export declare function rebaseDraft(draft: PermissionDraft, baseline: AppAuthority, current: AppAuthority): PermissionDraft;
|
|
74
|
+
/** Serializable host facts; the browser derives presentation, never authority. */
|
|
75
|
+
export declare const appPermissionsWireSchema: z.ZodObject<{
|
|
76
|
+
authority: z.ZodObject<{
|
|
77
|
+
authorityVersion: z.ZodLazy<z.ZodNumber>;
|
|
78
|
+
declaredOperationsDigest: z.ZodPipe<z.ZodUnknown, z.ZodTransform<import("@fungi.computer/puffball").Sha256Digest, unknown>>;
|
|
79
|
+
approvedGrants: z.ZodLazy<z.ZodReadonly<z.ZodArray<z.ZodReadonly<z.ZodObject<{
|
|
80
|
+
capability: z.ZodPipe<z.ZodUnknown, z.ZodTransform<"approvals" | "agent.list" | "agent.manage" | "agent.rename" | "agent.avatar" | "agent.toolPolicy" | "agent.read" | "agent.send" | "computer.list" | "computer.readFile" | "computer.writeFile" | "computer.execute" | "llm.generation" | "media.generation" | "games:servers" | "git.repository" | "apps.open" | "apps.call" | "app.storage" | "app.events.emit" | "team.workbenchHost" | "marketplace.browse" | "marketplace.purchase" | "workflow.run" | "workflow.publish" | "workflow.arm" | "world" | "channels.read" | "channels.personal.manage", unknown>>;
|
|
81
|
+
capabilityApproved: z.ZodLiteral<true>;
|
|
82
|
+
operations: z.ZodLazy<z.ZodReadonly<z.ZodArray<z.ZodString>>>;
|
|
83
|
+
resources: z.ZodUnion<readonly [z.ZodLiteral<"tenant-scope">, z.ZodReadonly<z.ZodArray<z.ZodLazy<z.ZodReadonly<z.ZodObject<{
|
|
84
|
+
kind: z.ZodString;
|
|
85
|
+
id: z.ZodString;
|
|
86
|
+
}, z.core.$strict>>>>>]>;
|
|
87
|
+
}, z.core.$strict>>>>>;
|
|
88
|
+
approval: z.ZodNullable<z.ZodLazy<z.ZodReadonly<z.ZodObject<{
|
|
89
|
+
by: import("zod/mini").ZodMiniDiscriminatedUnion<[import("zod/mini").ZodMiniObject<{
|
|
90
|
+
kind: import("zod/mini").ZodMiniLiteral<"member">;
|
|
91
|
+
memberId: import("zod/mini").ZodMiniString<string>;
|
|
92
|
+
}, z.core.$strip>, import("zod/mini").ZodMiniObject<{
|
|
93
|
+
kind: import("zod/mini").ZodMiniLiteral<"agent">;
|
|
94
|
+
agentId: import("zod/mini").ZodMiniString<string>;
|
|
95
|
+
}, z.core.$strip>, import("zod/mini").ZodMiniObject<{
|
|
96
|
+
kind: import("zod/mini").ZodMiniLiteral<"team-key">;
|
|
97
|
+
keyId: import("zod/mini").ZodMiniString<string>;
|
|
98
|
+
}, z.core.$strip>], "kind">;
|
|
99
|
+
at: z.ZodNumber;
|
|
100
|
+
authorityVersion: z.ZodLazy<z.ZodNumber>;
|
|
101
|
+
}, z.core.$strict>>>>;
|
|
102
|
+
}, z.core.$strict>;
|
|
103
|
+
declaredOperations: z.ZodLazy<z.ZodObject<{
|
|
104
|
+
artifactDigest: z.ZodPipe<z.ZodUnknown, z.ZodTransform<import("@fungi.computer/puffball").Sha256Digest, unknown>>;
|
|
105
|
+
digest: z.ZodPipe<z.ZodUnknown, z.ZodTransform<import("@fungi.computer/puffball").Sha256Digest, unknown>>;
|
|
106
|
+
anonymousMethods: z.ZodReadonly<z.ZodArray<z.ZodReadonly<z.ZodObject<{
|
|
107
|
+
name: z.ZodPipe<z.ZodUnknown, z.ZodTransform<string, unknown>>;
|
|
108
|
+
digest: z.ZodPipe<z.ZodUnknown, z.ZodTransform<import("@fungi.computer/puffball").Sha256Digest, unknown>>;
|
|
109
|
+
}, z.core.$strict>>>>;
|
|
110
|
+
capabilities: z.ZodReadonly<z.ZodArray<z.ZodReadonly<z.ZodObject<{
|
|
111
|
+
capability: z.ZodPipe<z.ZodUnknown, z.ZodTransform<"approvals" | "agent.list" | "agent.manage" | "agent.rename" | "agent.avatar" | "agent.toolPolicy" | "agent.read" | "agent.send" | "computer.list" | "computer.readFile" | "computer.writeFile" | "computer.execute" | "llm.generation" | "media.generation" | "games:servers" | "git.repository" | "apps.open" | "apps.call" | "app.storage" | "app.events.emit" | "team.workbenchHost" | "marketplace.browse" | "marketplace.purchase" | "workflow.run" | "workflow.publish" | "workflow.arm" | "world" | "channels.read" | "channels.personal.manage", unknown>>;
|
|
112
|
+
operations: z.ZodLazy<z.ZodReadonly<z.ZodArray<z.ZodString>>>;
|
|
113
|
+
}, z.core.$strict>>>>;
|
|
114
|
+
}, z.core.$strict>>;
|
|
115
|
+
}, z.core.$strict>;
|
|
116
|
+
/** Host-supplied authority and declared operations used to derive permission UI. */
|
|
117
|
+
export type AppPermissionsWire = z.output<typeof appPermissionsWireSchema>;
|
|
118
|
+
export type PermissionCellState = "on" | "off" | "via-all";
|
|
119
|
+
/**
|
|
120
|
+
* Catalog copy and pending status shared by a group's scoped and switch columns.
|
|
121
|
+
* @inline
|
|
122
|
+
*/
|
|
123
|
+
export type PermissionColumn = Readonly<{
|
|
124
|
+
capability: AppCapabilityId;
|
|
125
|
+
label: string;
|
|
126
|
+
caption: string;
|
|
127
|
+
description: string;
|
|
128
|
+
sigil: SigilName;
|
|
129
|
+
warning: string | null;
|
|
130
|
+
pending: boolean;
|
|
131
|
+
}>;
|
|
132
|
+
/**
|
|
133
|
+
* Catalog-derived permission groups, resource cells and operation switches.
|
|
134
|
+
* @inlineType PermissionColumn
|
|
135
|
+
*/
|
|
136
|
+
export type PermissionScreen = Readonly<{
|
|
137
|
+
canEdit: boolean;
|
|
138
|
+
pending: readonly AppCapabilityId[];
|
|
139
|
+
groups: readonly Readonly<{
|
|
140
|
+
id: PermissionCatalogEntry["group"];
|
|
141
|
+
scope: "computer" | "agent" | null;
|
|
142
|
+
columns: readonly PermissionColumn[];
|
|
143
|
+
rows: readonly Readonly<{
|
|
144
|
+
resource: ResourceRef | "all";
|
|
145
|
+
label: string;
|
|
146
|
+
cells: readonly Readonly<{
|
|
147
|
+
capability: AppCapabilityId;
|
|
148
|
+
state: PermissionCellState;
|
|
149
|
+
}>[];
|
|
150
|
+
}>[];
|
|
151
|
+
switches: readonly (PermissionColumn & Readonly<{
|
|
152
|
+
on: boolean;
|
|
153
|
+
}>)[];
|
|
154
|
+
operations: readonly Readonly<{
|
|
155
|
+
capability: "apps.call";
|
|
156
|
+
operation: string;
|
|
157
|
+
on: boolean;
|
|
158
|
+
}>[];
|
|
159
|
+
}>[];
|
|
160
|
+
}>;
|
|
161
|
+
/** Every declared permission is visible, including removable saved resources no longer listed by the host. */
|
|
162
|
+
export declare function permissionScreen(input: AppPermissionsWire & Readonly<{
|
|
163
|
+
resources: readonly ResourceOption[];
|
|
164
|
+
canEdit: boolean;
|
|
165
|
+
}>): PermissionScreen;
|
|
166
|
+
/** Owner-direct permission page and JSON projection. Copy stays in the catalog. */
|
|
167
|
+
export declare const permissionPinsSchema: z.ZodObject<{
|
|
168
|
+
storeGeneration: z.ZodString;
|
|
169
|
+
authorityVersion: z.ZodNumber;
|
|
170
|
+
artifactDigest: z.ZodPipe<z.ZodUnknown, z.ZodTransform<import("@fungi.computer/puffball").Sha256Digest, unknown>>;
|
|
171
|
+
}, z.core.$strict>;
|
|
172
|
+
/** Generation, authority version and artifact digest fencing a permission edit. */
|
|
173
|
+
export type PermissionPins = z.output<typeof permissionPinsSchema>;
|
|
174
|
+
/** Permission edit command coupled to the version pins read by the owner. */
|
|
175
|
+
export declare const permissionSaveSchema: z.ZodObject<{
|
|
176
|
+
storeGeneration: z.ZodString;
|
|
177
|
+
authorityVersion: z.ZodNumber;
|
|
178
|
+
artifactDigest: z.ZodPipe<z.ZodUnknown, z.ZodTransform<import("@fungi.computer/puffball").Sha256Digest, unknown>>;
|
|
179
|
+
command: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
180
|
+
kind: z.ZodLiteral<"install">;
|
|
181
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
182
|
+
kind: z.ZodLiteral<"change-grants">;
|
|
183
|
+
changes: z.ZodReadonly<z.ZodArray<z.ZodReadonly<z.ZodObject<{
|
|
184
|
+
capability: z.ZodPipe<z.ZodUnknown, z.ZodTransform<"approvals" | "agent.list" | "agent.manage" | "agent.rename" | "agent.avatar" | "agent.toolPolicy" | "agent.read" | "agent.send" | "computer.list" | "computer.readFile" | "computer.writeFile" | "computer.execute" | "llm.generation" | "media.generation" | "games:servers" | "git.repository" | "apps.open" | "apps.call" | "app.storage" | "app.events.emit" | "team.workbenchHost" | "marketplace.browse" | "marketplace.purchase" | "workflow.run" | "workflow.publish" | "workflow.arm" | "world" | "channels.read" | "channels.personal.manage", unknown>>;
|
|
185
|
+
grant: z.ZodNullable<z.ZodReadonly<z.ZodObject<{
|
|
186
|
+
operations: z.ZodLazy<z.ZodReadonly<z.ZodArray<z.ZodString>>>;
|
|
187
|
+
resources: z.ZodUnion<readonly [z.ZodLiteral<"tenant-scope">, z.ZodReadonly<z.ZodArray<z.ZodLazy<z.ZodReadonly<z.ZodObject<{
|
|
188
|
+
kind: z.ZodString;
|
|
189
|
+
id: z.ZodString;
|
|
190
|
+
}, z.core.$strict>>>>>]>;
|
|
191
|
+
}, z.core.$strict>>>;
|
|
192
|
+
}, z.core.$strict>>>>;
|
|
193
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
194
|
+
kind: z.ZodLiteral<"select-release">;
|
|
195
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
196
|
+
kind: z.ZodLiteral<"delete">;
|
|
197
|
+
}, z.core.$strict>], "kind">;
|
|
198
|
+
}, z.core.$strict>;
|
|
199
|
+
/** Owner permission-page identity, artifact and current permission facts. */
|
|
200
|
+
export declare const appPermissionPageSchema: z.ZodObject<{
|
|
201
|
+
storeGeneration: z.ZodString;
|
|
202
|
+
installationId: z.ZodString;
|
|
203
|
+
appId: z.ZodString;
|
|
204
|
+
appName: z.ZodString;
|
|
205
|
+
artifactDigest: z.ZodPipe<z.ZodUnknown, z.ZodTransform<import("@fungi.computer/puffball").Sha256Digest, unknown>>;
|
|
206
|
+
permissions: z.ZodObject<{
|
|
207
|
+
authority: z.ZodObject<{
|
|
208
|
+
authorityVersion: z.ZodLazy<z.ZodNumber>;
|
|
209
|
+
declaredOperationsDigest: z.ZodPipe<z.ZodUnknown, z.ZodTransform<import("@fungi.computer/puffball").Sha256Digest, unknown>>;
|
|
210
|
+
approvedGrants: z.ZodLazy<z.ZodReadonly<z.ZodArray<z.ZodReadonly<z.ZodObject<{
|
|
211
|
+
capability: z.ZodPipe<z.ZodUnknown, z.ZodTransform<"approvals" | "agent.list" | "agent.manage" | "agent.rename" | "agent.avatar" | "agent.toolPolicy" | "agent.read" | "agent.send" | "computer.list" | "computer.readFile" | "computer.writeFile" | "computer.execute" | "llm.generation" | "media.generation" | "games:servers" | "git.repository" | "apps.open" | "apps.call" | "app.storage" | "app.events.emit" | "team.workbenchHost" | "marketplace.browse" | "marketplace.purchase" | "workflow.run" | "workflow.publish" | "workflow.arm" | "world" | "channels.read" | "channels.personal.manage", unknown>>;
|
|
212
|
+
capabilityApproved: z.ZodLiteral<true>;
|
|
213
|
+
operations: z.ZodLazy<z.ZodReadonly<z.ZodArray<z.ZodString>>>;
|
|
214
|
+
resources: z.ZodUnion<readonly [z.ZodLiteral<"tenant-scope">, z.ZodReadonly<z.ZodArray<z.ZodLazy<z.ZodReadonly<z.ZodObject<{
|
|
215
|
+
kind: z.ZodString;
|
|
216
|
+
id: z.ZodString;
|
|
217
|
+
}, z.core.$strict>>>>>]>;
|
|
218
|
+
}, z.core.$strict>>>>>;
|
|
219
|
+
approval: z.ZodNullable<z.ZodLazy<z.ZodReadonly<z.ZodObject<{
|
|
220
|
+
by: import("zod/mini").ZodMiniDiscriminatedUnion<[import("zod/mini").ZodMiniObject<{
|
|
221
|
+
kind: import("zod/mini").ZodMiniLiteral<"member">;
|
|
222
|
+
memberId: import("zod/mini").ZodMiniString<string>;
|
|
223
|
+
}, z.core.$strip>, import("zod/mini").ZodMiniObject<{
|
|
224
|
+
kind: import("zod/mini").ZodMiniLiteral<"agent">;
|
|
225
|
+
agentId: import("zod/mini").ZodMiniString<string>;
|
|
226
|
+
}, z.core.$strip>, import("zod/mini").ZodMiniObject<{
|
|
227
|
+
kind: import("zod/mini").ZodMiniLiteral<"team-key">;
|
|
228
|
+
keyId: import("zod/mini").ZodMiniString<string>;
|
|
229
|
+
}, z.core.$strip>], "kind">;
|
|
230
|
+
at: z.ZodNumber;
|
|
231
|
+
authorityVersion: z.ZodLazy<z.ZodNumber>;
|
|
232
|
+
}, z.core.$strict>>>>;
|
|
233
|
+
}, z.core.$strict>;
|
|
234
|
+
declaredOperations: z.ZodLazy<z.ZodObject<{
|
|
235
|
+
artifactDigest: z.ZodPipe<z.ZodUnknown, z.ZodTransform<import("@fungi.computer/puffball").Sha256Digest, unknown>>;
|
|
236
|
+
digest: z.ZodPipe<z.ZodUnknown, z.ZodTransform<import("@fungi.computer/puffball").Sha256Digest, unknown>>;
|
|
237
|
+
anonymousMethods: z.ZodReadonly<z.ZodArray<z.ZodReadonly<z.ZodObject<{
|
|
238
|
+
name: z.ZodPipe<z.ZodUnknown, z.ZodTransform<string, unknown>>;
|
|
239
|
+
digest: z.ZodPipe<z.ZodUnknown, z.ZodTransform<import("@fungi.computer/puffball").Sha256Digest, unknown>>;
|
|
240
|
+
}, z.core.$strict>>>>;
|
|
241
|
+
capabilities: z.ZodReadonly<z.ZodArray<z.ZodReadonly<z.ZodObject<{
|
|
242
|
+
capability: z.ZodPipe<z.ZodUnknown, z.ZodTransform<"approvals" | "agent.list" | "agent.manage" | "agent.rename" | "agent.avatar" | "agent.toolPolicy" | "agent.read" | "agent.send" | "computer.list" | "computer.readFile" | "computer.writeFile" | "computer.execute" | "llm.generation" | "media.generation" | "games:servers" | "git.repository" | "apps.open" | "apps.call" | "app.storage" | "app.events.emit" | "team.workbenchHost" | "marketplace.browse" | "marketplace.purchase" | "workflow.run" | "workflow.publish" | "workflow.arm" | "world" | "channels.read" | "channels.personal.manage", unknown>>;
|
|
243
|
+
operations: z.ZodLazy<z.ZodReadonly<z.ZodArray<z.ZodString>>>;
|
|
244
|
+
}, z.core.$strict>>>>;
|
|
245
|
+
}, z.core.$strict>>;
|
|
246
|
+
}, z.core.$strict>;
|
|
247
|
+
}, z.core.$strict>;
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
import { permissionCatalog } from "./catalog.js";
|
|
3
|
+
import { sha256DigestSchema } from "@fungi.computer/puffball/effect";
|
|
4
|
+
import { appAuthoritySchema, declaredOperationsSchema, ownerCodec, grantCommandSchema, } from "./installation.js";
|
|
5
|
+
/** Includes newly declared operations and capabilities the owner has narrowed. */
|
|
6
|
+
export function pendingCapabilities(authority, declaration, declaredOperations) {
|
|
7
|
+
return declaration.capabilities.filter((capability) => {
|
|
8
|
+
if (permissionCatalog[capability].consent === "affordance")
|
|
9
|
+
return false;
|
|
10
|
+
const grant = authority.approvedGrants.find((row) => row.capability === capability);
|
|
11
|
+
return (grant === undefined ||
|
|
12
|
+
(grant.resources !== "tenant-scope" && grant.resources.length === 0) ||
|
|
13
|
+
declaredOperations.capabilities
|
|
14
|
+
.find((row) => row.capability === capability)
|
|
15
|
+
?.operations.some((operation) => !grant.operations.includes(operation)) === true);
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
/** Bound the real SDK request; an Allow never silently widens selected resources. */
|
|
19
|
+
export function grantRequestFor(authority, facts, request, window) {
|
|
20
|
+
if (authority.declaredOperationsDigest !== facts.declaredOperations.digest)
|
|
21
|
+
return { kind: "refused", code: "stale_authority" };
|
|
22
|
+
const requested = [
|
|
23
|
+
...new Set([...(request.agents ?? []), ...(request.computers ?? [])]),
|
|
24
|
+
];
|
|
25
|
+
if (requested.some((capability) => !facts.declaration.capabilities.includes(capability)))
|
|
26
|
+
return { kind: "refused", code: "not_declared" };
|
|
27
|
+
const adds = [];
|
|
28
|
+
for (const capability of requested) {
|
|
29
|
+
const existing = authority.approvedGrants.find((row) => row.capability === capability);
|
|
30
|
+
const operations = facts.declaredOperations.capabilities.find((row) => row.capability === capability)?.operations ?? [];
|
|
31
|
+
if (existing !== undefined &&
|
|
32
|
+
existing.resources !== "tenant-scope" &&
|
|
33
|
+
existing.resources.length > 0) {
|
|
34
|
+
// approvedGrantSchema admits only capabilityApproved: true.
|
|
35
|
+
// A replay can use that approval, but cannot extend its finite scope.
|
|
36
|
+
if (permissionCatalog[capability].scope === "computer" &&
|
|
37
|
+
window.computerId !== null &&
|
|
38
|
+
existing.resources.some((resource) => resource.kind === "computer" && resource.id === window.computerId) &&
|
|
39
|
+
operations.every((operation) => existing.operations.includes(operation)))
|
|
40
|
+
continue;
|
|
41
|
+
return { kind: "customize" };
|
|
42
|
+
}
|
|
43
|
+
if (existing?.resources === "tenant-scope" &&
|
|
44
|
+
operations.every((operation) => existing.operations.includes(operation)))
|
|
45
|
+
continue;
|
|
46
|
+
let resources = "tenant-scope";
|
|
47
|
+
if (permissionCatalog[capability].scope === "computer") {
|
|
48
|
+
// Only the embedding host supplies this fact, never the App's request.
|
|
49
|
+
const computerId = window.computerId;
|
|
50
|
+
if (computerId == null)
|
|
51
|
+
return { kind: "refused", code: "window_scope_unavailable" };
|
|
52
|
+
resources = [{ kind: "computer", id: computerId }];
|
|
53
|
+
}
|
|
54
|
+
adds.push({ capability, grant: { operations, resources } });
|
|
55
|
+
}
|
|
56
|
+
if (adds.length === 0)
|
|
57
|
+
return { kind: "covered" };
|
|
58
|
+
return {
|
|
59
|
+
kind: "ask",
|
|
60
|
+
adds,
|
|
61
|
+
command: { kind: "change-grants", changes: adds },
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/** The saved operation ceiling is the starting point, including empty operation rows. */
|
|
65
|
+
export function draftOf(authority) {
|
|
66
|
+
return new Map(authority.approvedGrants.map(({ capability, operations, resources }) => [
|
|
67
|
+
capability,
|
|
68
|
+
{ operations, resources },
|
|
69
|
+
]));
|
|
70
|
+
}
|
|
71
|
+
function sameGrant(a, b) {
|
|
72
|
+
if (a == null || b == null)
|
|
73
|
+
return a == null && b == null;
|
|
74
|
+
const sameValues = (left, right) => left.length === right.length &&
|
|
75
|
+
left.every((value) => right.includes(value));
|
|
76
|
+
if (!sameValues(a.operations, b.operations))
|
|
77
|
+
return false;
|
|
78
|
+
if (a.resources === "tenant-scope" || b.resources === "tenant-scope")
|
|
79
|
+
return a.resources === b.resources;
|
|
80
|
+
return (a.resources.length === b.resources.length &&
|
|
81
|
+
a.resources.every((resource) => b.resources !== "tenant-scope" &&
|
|
82
|
+
b.resources.some((other) => resource.kind === other.kind && resource.id === other.id)));
|
|
83
|
+
}
|
|
84
|
+
/** An edit changes one capability; unrelated saved operations and scopes are retained. */
|
|
85
|
+
export function editPermissions(draft, edit, declared) {
|
|
86
|
+
const row = declared.capabilities.find(({ capability }) => capability === edit.capability);
|
|
87
|
+
const policy = permissionCatalog[edit.capability];
|
|
88
|
+
if (row === undefined || policy.consent === "affordance")
|
|
89
|
+
return draft;
|
|
90
|
+
const next = new Map(draft);
|
|
91
|
+
const existing = draft.get(edit.capability);
|
|
92
|
+
const enabled = existing ?? {
|
|
93
|
+
operations: row.operations,
|
|
94
|
+
resources: "tenant-scope",
|
|
95
|
+
};
|
|
96
|
+
switch (edit.kind) {
|
|
97
|
+
case "switch":
|
|
98
|
+
next.set(edit.capability, edit.on ? enabled : null);
|
|
99
|
+
break;
|
|
100
|
+
case "all":
|
|
101
|
+
if (policy.scope === null)
|
|
102
|
+
return draft;
|
|
103
|
+
next.set(edit.capability, edit.on ? { ...enabled, resources: "tenant-scope" } : null);
|
|
104
|
+
break;
|
|
105
|
+
case "resource": {
|
|
106
|
+
if (policy.scope !== edit.resource.kind ||
|
|
107
|
+
existing?.resources === "tenant-scope")
|
|
108
|
+
return draft;
|
|
109
|
+
const resources = existing?.resources ?? [];
|
|
110
|
+
const kept = resources.filter((resource) => resource.kind !== edit.resource.kind ||
|
|
111
|
+
resource.id !== edit.resource.id);
|
|
112
|
+
const changed = edit.on ? [...kept, edit.resource] : kept;
|
|
113
|
+
next.set(edit.capability, changed.length === 0 ? null : { ...enabled, resources: changed });
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
case "operation": {
|
|
117
|
+
if (edit.capability !== "apps.call" ||
|
|
118
|
+
!row.operations.includes(edit.operation))
|
|
119
|
+
return draft;
|
|
120
|
+
const kept = (existing?.operations ?? []).filter((operation) => operation !== edit.operation);
|
|
121
|
+
const operations = edit.on ? [...kept, edit.operation] : kept;
|
|
122
|
+
next.set(edit.capability, operations.length === 0 ? null : { ...enabled, operations });
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return next;
|
|
127
|
+
}
|
|
128
|
+
/** Only touched capability rows cross the save boundary. */
|
|
129
|
+
export function planGrantChange(baseline, draft) {
|
|
130
|
+
const saved = draftOf(baseline);
|
|
131
|
+
const capabilities = new Set([...saved.keys(), ...draft.keys()]);
|
|
132
|
+
return [...capabilities].flatMap((capability) => sameGrant(saved.get(capability), draft.get(capability))
|
|
133
|
+
? []
|
|
134
|
+
: [{ capability, grant: draft.get(capability) ?? null }]);
|
|
135
|
+
}
|
|
136
|
+
/** A conflict preserves the person's edits while taking fresh untouched capabilities. */
|
|
137
|
+
export function rebaseDraft(draft, baseline, current) {
|
|
138
|
+
const rebased = new Map(draftOf(current));
|
|
139
|
+
for (const change of planGrantChange(baseline, draft))
|
|
140
|
+
rebased.set(change.capability, change.grant);
|
|
141
|
+
return rebased;
|
|
142
|
+
}
|
|
143
|
+
/** Serializable host facts; the browser derives presentation, never authority. */
|
|
144
|
+
export const appPermissionsWireSchema = z.strictObject({
|
|
145
|
+
authority: appAuthoritySchema,
|
|
146
|
+
declaredOperations: declaredOperationsSchema,
|
|
147
|
+
});
|
|
148
|
+
/** Every declared permission is visible, including removable saved resources no longer listed by the host. */
|
|
149
|
+
export function permissionScreen(input) {
|
|
150
|
+
const pending = pendingCapabilities(input.authority, {
|
|
151
|
+
capabilities: input.declaredOperations.capabilities.map((row) => row.capability),
|
|
152
|
+
}, input.declaredOperations);
|
|
153
|
+
const draft = draftOf(input.authority);
|
|
154
|
+
const grouped = new Map();
|
|
155
|
+
for (const { capability } of input.declaredOperations.capabilities) {
|
|
156
|
+
const group = permissionCatalog[capability].group;
|
|
157
|
+
grouped.set(group, [...(grouped.get(group) ?? []), capability]);
|
|
158
|
+
}
|
|
159
|
+
const column = (capability) => {
|
|
160
|
+
const { label, caption, description, sigil, warning } = permissionCatalog[capability];
|
|
161
|
+
return {
|
|
162
|
+
capability,
|
|
163
|
+
label,
|
|
164
|
+
caption,
|
|
165
|
+
description,
|
|
166
|
+
sigil,
|
|
167
|
+
warning,
|
|
168
|
+
pending: pending.includes(capability),
|
|
169
|
+
};
|
|
170
|
+
};
|
|
171
|
+
return {
|
|
172
|
+
canEdit: input.canEdit,
|
|
173
|
+
pending,
|
|
174
|
+
groups: [...grouped].map(([id, capabilities]) => {
|
|
175
|
+
const scoped = capabilities.filter((capability) => permissionCatalog[capability].scope !== null);
|
|
176
|
+
const scope = scoped.length === 0
|
|
177
|
+
? null
|
|
178
|
+
: permissionCatalog[scoped[0] ?? "apps.open"].scope;
|
|
179
|
+
const resources = new Map(input.resources
|
|
180
|
+
.filter((resource) => resource.kind === scope)
|
|
181
|
+
.map((resource) => [resource.id, resource]));
|
|
182
|
+
for (const capability of scoped) {
|
|
183
|
+
const grant = draft.get(capability);
|
|
184
|
+
if (grant == null || grant.resources === "tenant-scope")
|
|
185
|
+
continue;
|
|
186
|
+
for (const resource of grant.resources) {
|
|
187
|
+
if (resource.kind === scope && !resources.has(resource.id))
|
|
188
|
+
resources.set(resource.id, { ...resource, label: resource.id });
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
const row = (resource, label) => ({
|
|
192
|
+
resource,
|
|
193
|
+
label,
|
|
194
|
+
cells: scoped.map((capability) => {
|
|
195
|
+
const grant = draft.get(capability);
|
|
196
|
+
const state = grant == null
|
|
197
|
+
? "off"
|
|
198
|
+
: grant.resources === "tenant-scope"
|
|
199
|
+
? resource === "all"
|
|
200
|
+
? "on"
|
|
201
|
+
: "via-all"
|
|
202
|
+
: resource !== "all" &&
|
|
203
|
+
grant.resources.some((ref) => ref.kind === resource.kind && ref.id === resource.id)
|
|
204
|
+
? "on"
|
|
205
|
+
: "off";
|
|
206
|
+
return { capability, state };
|
|
207
|
+
}),
|
|
208
|
+
});
|
|
209
|
+
return {
|
|
210
|
+
id,
|
|
211
|
+
scope,
|
|
212
|
+
columns: scoped.map(column),
|
|
213
|
+
rows: scope === null
|
|
214
|
+
? []
|
|
215
|
+
: [
|
|
216
|
+
row("all", scope === "computer" ? "All Computers" : "All Agents"),
|
|
217
|
+
...[...resources.values()].map((resource) => row(resource, resource.label)),
|
|
218
|
+
],
|
|
219
|
+
switches: capabilities
|
|
220
|
+
.filter((capability) => permissionCatalog[capability].scope === null)
|
|
221
|
+
.map((capability) => ({
|
|
222
|
+
...column(capability),
|
|
223
|
+
on: permissionCatalog[capability].consent === "affordance" ||
|
|
224
|
+
draft.get(capability) != null,
|
|
225
|
+
})),
|
|
226
|
+
operations: capabilities.includes("apps.call")
|
|
227
|
+
? (input.declaredOperations.capabilities.find((capability) => capability.capability === "apps.call")?.operations ?? []).map((operation) => ({
|
|
228
|
+
capability: "apps.call",
|
|
229
|
+
operation,
|
|
230
|
+
on: draft.get("apps.call")?.operations.includes(operation) === true,
|
|
231
|
+
}))
|
|
232
|
+
: [],
|
|
233
|
+
};
|
|
234
|
+
}),
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
/** Owner-direct permission page and JSON projection. Copy stays in the catalog. */
|
|
238
|
+
export const permissionPinsSchema = z.strictObject({
|
|
239
|
+
storeGeneration: z.string().min(1),
|
|
240
|
+
authorityVersion: z.number().int().positive(),
|
|
241
|
+
artifactDigest: ownerCodec(sha256DigestSchema),
|
|
242
|
+
});
|
|
243
|
+
/** Permission edit command coupled to the version pins read by the owner. */
|
|
244
|
+
export const permissionSaveSchema = permissionPinsSchema.extend({
|
|
245
|
+
command: grantCommandSchema,
|
|
246
|
+
});
|
|
247
|
+
/** Owner permission-page identity, artifact and current permission facts. */
|
|
248
|
+
export const appPermissionPageSchema = z.strictObject({
|
|
249
|
+
storeGeneration: permissionPinsSchema.shape.storeGeneration,
|
|
250
|
+
installationId: z.string(),
|
|
251
|
+
appId: z.string(),
|
|
252
|
+
appName: z.string(),
|
|
253
|
+
artifactDigest: ownerCodec(sha256DigestSchema),
|
|
254
|
+
permissions: appPermissionsWireSchema,
|
|
255
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type BootCapabilityStore } from "./boot-capability.js";
|
|
2
|
+
/** The artifact bucket read the route needs; an R2 bucket is one. */
|
|
3
|
+
export type BootAssetBucket = Readonly<{
|
|
4
|
+
get(key: string): Promise<Readonly<{
|
|
5
|
+
size: number;
|
|
6
|
+
body: ReadableStream<Uint8Array>;
|
|
7
|
+
}> | null>;
|
|
8
|
+
}>;
|
|
9
|
+
export type BootCapabilityRouteOptions = Readonly<{
|
|
10
|
+
configuredOrigin: string;
|
|
11
|
+
bucket: BootAssetBucket;
|
|
12
|
+
capabilities: BootCapabilityStore;
|
|
13
|
+
}>;
|
|
14
|
+
/** Worker-only HTTPS endpoint for a single digest-authorized boot lease. */
|
|
15
|
+
export declare function serveBootCapability(request: Request, options: BootCapabilityRouteOptions): Promise<Response | null>;
|