Skip to content
API reference

host

Import
import * as api from "@fungi.computer/oyster/host";
Kind Export Description
class ReleaseError Why a Release could not be read; the host maps it to an HTTP refusal.
type alias CapabilityMethodKind The four supported capability method kinds.
type alias CapabilityDescriptor A page descriptor carries routing, never the authority to use a capability.
type alias OysterVisitor The anonymous reader of a public installation. The host admits it only when authentication refuses; it reaches that App’s page and its read methods.
type alias OysterPrincipal Who an admitted request acts for: an authenticated tenant principal or the visitor.
type alias OysterAuthResult The outcome of authenticating one request.
type alias OysterAuth The host’s sign-in: who may use this Oyster.
type alias InstallationCommit A serializable registry commit result, including across native DO RPC.
type alias InstallationStore Durable commits remain with the host’s registry; reads are tenant-scoped.
type alias OysterJson A JSON value crossing the method boundary.
type alias InstanceResult The result of one Instance operation; refusals carry Oyster’s error code.
type alias InstanceHandle One running App Instance, wherever the host runs it.
type alias InstanceDirectory Finds the running Instance for an Instance ID.
type alias OysterMcp An MCP endpoint mounted at /mcp.
type alias OysterGitHost What Oyster’s git door needs from the host beyond sign-in and Instances.
type alias CapabilityAdmission The host’s admission of one capability request: who, for which installation.
type alias CapabilityEnv Capability routes read the host’s admission from c.env; they never authenticate.
type alias OysterCapability A capability adapter whose routes require live installation admission.
type alias OysterVariables What the host stamps once per request; inner routes read it with c.get.
type alias OysterEnv Owner routes run after the host’s owner guard and read c.get("principal").
type alias OysterHost Everything a host supplies to run Oyster.
type alias InstallationOperations Host-side port; RPC transport and tenant context belong to the adapter.
type alias ArtifactStore Immutable Release bytes addressed by their artifact reference.
type alias VerifiedRelease A Release whose root, UI and backend artifacts were read and verified.
type alias VerifiedObjectCache Copies of verified artifacts near the reader, keyed by content digest. An entry holds only bytes that already matched its digest, so a hit is served without another store read or hash.
constant capabilityMethodKindSchema How an admitted capability method is exposed to the App.
constant capabilityMethodSchema The HTTP operation exposed by one capability method on an Oyster page.
constant capabilityDescriptorSchema The serializable part of a capability admitted to an installation’s page.
constant defaultAssetPolicy Default bounds for an App’s UI asset build.
function oysterPrincipalIsVisitor() Narrow an admitted principal to the anonymous public reader.
function oysterPrincipalIsOwner() True only for a member admitted with the owner role.
function oysterPrincipalId() Stable actor identity for host storage and backend attribution.
function installOrSelect() Completed selection, without re-deriving or executing outside Watchdog.
function createOyster() Create the Oyster App server: a Hono app that installs App Releases, serves their UI, forwards their backend requests and methods to their Instances, and mounts the host’s MCP endpoint. The host’s adapters decide where state lives and who may sign in.
function sha256() Hex SHA-256 digest in Puffball’s sha256:<hex> form.
function parseRelease() Decode an untrusted Release record, as an install request carries it.
function verifyRelease() Read a Release root and verify its UI build and backend descriptor. readAssets verifies UI object bodies when true. When false, it reads the asset manifest needed to resolve references but does not read any UI object body, including standalone HTML.
function resolveBackend() Resolve a Release to its verified durable backend without reading its UI: the root artifact, then the backend descriptor it names.

Why a Release could not be read; the host maps it to an HTTP refusal.

  • Error
Signature
new ReleaseError(
code,
message,
options?
): ReleaseError;
Parameter Type
code | "artifact_missing" | "digest_mismatch" | "invalid_release" | "asset_missing"
message string
options? ErrorOptions

ReleaseError

Signature
Error.constructor;
Signature
readonly name: "ReleaseError" = "ReleaseError";
Signature
Error.name;
Signature
readonly code:
| "artifact_missing"
| "digest_mismatch"
| "invalid_release"
| "asset_missing";

CapabilityMethodKindtype alias

Section titled “CapabilityMethodKind”
Signature
type CapabilityMethodKind = Schema.Schema.Type<
typeof capabilityMethodKindSchema
>;

The four supported capability method kinds.


CapabilityDescriptortype alias

Section titled “CapabilityDescriptor”
Signature
type CapabilityDescriptor = Schema.Schema.Type<
typeof capabilityDescriptorSchema
>;

A page descriptor carries routing, never the authority to use a capability.


OysterVisitortype alias

Section titled “OysterVisitor”
Signature
type OysterVisitor = Readonly<{
actor: Readonly<{
kind: "visitor";
}>;
}>;

The anonymous reader of a public installation. The host admits it only when authentication refuses; it reaches that App’s page and its read methods.


OysterPrincipaltype alias

Section titled “OysterPrincipal”
Signature
type OysterPrincipal = TenantPrincipal | OysterVisitor;

Who an admitted request acts for: an authenticated tenant principal or the visitor.


OysterAuthResulttype alias

Section titled “OysterAuthResult”
Signature
type OysterAuthResult =
| Readonly<{
kind: "admitted";
principal: TenantPrincipal;
}>
| Readonly<{
kind: "refused";
status: 401 | 403 | 404 | 429;
retryAfter?: number;
}>;

The outcome of authenticating one request.


OysterAuthtype alias

Section titled “OysterAuth”
Signature
type OysterAuth = Readonly<{
resolve: (actor) => Promise<TenantPrincipal | null>;
authenticate: (request) => Promise<OysterAuthResult>;
login?: (request) => Promise<Response>;
}>;

The host’s sign-in: who may use this Oyster.


InstallationCommittype alias

Section titled “InstallationCommit”
Signature
type InstallationCommit =
| Readonly<{
ok: true;
}>
| Readonly<{
ok: false;
code: "stale_authority";
}>;

A serializable registry commit result, including across native DO RPC.


InstallationStoretype alias

Section titled “InstallationStore”
Signature
type InstallationStore = InstallationReader &
Readonly<{
operations?: InstallationOperations;
generation: () => Promise<string>;
compareAndPut: (
installation,
expectedAuthorityVersion,
expectedGeneration,
) => Promise<InstallationCommit>;
}>;

Durable commits remain with the host’s registry; reads are tenant-scoped.


OysterJsontype alias

Section titled “OysterJson”
Signature
type OysterJson = Schema.Json;

A JSON value crossing the method boundary.


InstanceResulttype alias

Section titled “InstanceResult”
Signature
type InstanceResult<T> =
| Readonly<{
ok: true;
value: T;
}>
| Readonly<{
ok: false;
code: AppInstanceErrorCode | "failed";
causeClass?:
| "Error"
| "TypeError"
| "RangeError"
| "SyntaxError"
| "AbortError"
| "TimeoutError"
| "Other";
}>;

The result of one Instance operation; refusals carry Oyster’s error code.

Type Parameter
T

InstanceHandletype alias

Section titled “InstanceHandle”
Signature
type InstanceHandle = Readonly<{
prepare: (
state,
release,
) => Promise<InstanceResult<UiBootCheckOutcome | null>>;
apply: (state, release) => Promise<InstanceResult<Instance>>;
onGitPush: (facts, fact) => Promise<void>;
syncRefused: (facts, refusal) => Promise<void>;
authorizeGitPush: (facts, question) => Promise<GitPushVerdict>;
fetch: (facts, request) => Promise<Response>;
gill: (facts, api, source, input) => Promise<InstanceResult<GillReply>>;
call: (facts, api, name, input) => Promise<InstanceResult<AppMethodReply>>;
}>;

One running App Instance, wherever the host runs it.


InstanceDirectorytype alias

Section titled “InstanceDirectory”
Signature
type InstanceDirectory = Readonly<{
get: (instanceId, limits?) => InstanceHandle;
}>;

Finds the running Instance for an Instance ID.


OysterMcptype alias

Section titled “OysterMcp”
Signature
type OysterMcp = Readonly<{
handleRequest: (request) => Promise<Response>;
close?: () => Promise<void>;
}>;

An MCP endpoint mounted at /mcp.


OysterGitHosttype alias

Section titled “OysterGitHost”
Signature
type OysterGitHost = Readonly<{
writerOf: Extract<
GitWriter,
{
kind: "actor";
}
>;
workflowPass?: Promise<Readonly<{
kind: "actor";
actor: HostActor;
role?: "owner" | "member";
workflow?: WorkflowAttestation & object;
}> | null>;
buildPass?: Promise<Readonly<{
kind: "actor";
actor: HostActor;
role?: "owner" | "member";
workflow?: WorkflowAttestation & object;
}> | null>;
git: Promise<
Readonly<{
push: Promise<
Readonly<{
status: number;
headers: Readonly<Record<string, string>>;
body: Uint8Array;
}>
>;
read: Promise<
Readonly<{
status: number;
headers: Readonly<Record<string, string>>;
body: Uint8Array;
}>
>;
binding: GitBinding;
}>
>;
}>;

What Oyster’s git door needs from the host beyond sign-in and Instances.


CapabilityAdmissiontype alias

Section titled “CapabilityAdmission”
Signature
type CapabilityAdmission = Readonly<{
principal: TenantPrincipal;
installation: Installation;
}>;

The host’s admission of one capability request: who, for which installation.


CapabilityEnvtype alias

Section titled “CapabilityEnv”
Signature
type CapabilityEnv = object;

Capability routes read the host’s admission from c.env; they never authenticate.

Signature
Bindings: CapabilityAdmission;

OysterCapabilitytype alias

Section titled “OysterCapability”
Signature
type OysterCapability = Readonly<CapabilityDescriptor & object>;

A capability adapter whose routes require live installation admission.


OysterVariablestype alias

Section titled “OysterVariables”
Signature
type OysterVariables = TimingVariables & object;

What the host stamps once per request; inner routes read it with c.get.

Name Type
principal OysterPrincipal
installation? Installation

OysterEnvtype alias

Section titled “OysterEnv”
Signature
type OysterEnv = object;

Owner routes run after the host’s owner guard and read c.get("principal").

Signature
Variables: OysterVariables;

OysterHosttype alias

Section titled “OysterHost”
Signature
type OysterHost = Readonly<{
approvals?: Readonly<{
submit: Promise<
| {
kind: Schema.Literal<"pending_approval">;
recordId: Schema.String;
description: Schema.Struct<{
title: Schema.String;
inputBytes: Schema.Int;
inputSha256: Schema.String;
}>;
}
| ApprovalApplyResult>;
}>;
workflows?: (principal) => Promise<
| {
status: Promise<
| {
runId: z.ZodString;
planDigest: z.ZodString;
outcome: z.ZodEnum<{
cancelled: ...;
terminal: ...;
active: ...;
}>;
title: z.ZodString;
events: z.ZodArray<z.ZodRecord<..., ...>>;
reviews: z.ZodArray<z.ZodRecord<..., ...>>;
status: z.ZodString;
output: z.ZodJSONSchema;
error: z.ZodJSONSchema;
}
| {
error: z.ZodString;
}
| null>;
cancel: Promise<
| {
kind: z.ZodEnum<{
cancelled: ...;
terminal: ...;
}>;
}
| {
kind: z.ZodLiteral<"refused">;
reason: z.ZodLiteral<"denied">;
}
| {
error: z.ZodString;
}>;
}
| null>;
computerControl?: (principal) => ComputerControlPort | null;
auth: OysterAuth;
backgroundOriginKey?: () => Promise<CryptoKey>;
artifacts: ArtifactStore;
uiCache?: VerifiedObjectCache;
installations: InstallationStore;
instances: InstanceDirectory;
bootUi: (release) => Promise<UiBootCheckOutcome>;
computerId?: string;
computer?: (principal) => KnapsackComputer | null | Promise<KnapsackComputer | null>;
appToolPolicy?: (actor) =>
| AppToolPolicy
| null
| Promise<AppToolPolicy | null>;
keys?: Readonly<{
live: Promise<
| Readonly<{
keyId: string;
owner: string;
grantVersion: number;
grants: readonly Grant<...>[];
}>
| null>;
}>;
guestLimits?: Partial<GuestLimits>;
mcp?: OysterMcp;
git?: OysterGitHost;
ownerRoutes?: Hono<OysterEnv>;
capabilities?: readonly OysterCapability[];
workbench?: Readonly<{
directory: Promise<Readonly<{
apps: readonly AppDirectoryEntry[];
roles: OysterRootRoles;
computer?: Readonly<{
computerId: string;
name: string;
}>;
}>>;
storage: Pick<AppStorageWire, "read" | "write" | "reset"> & Readonly<{
events: Promise<Response>;
}>;
}>;
homeInstallationId?: string;
pageScript?: string;
pageAssets?: () => Promise<{
pageScript: string;
publicHomeScript: string;
fontStyles: string;
loginFontStyles: string;
shellStyles: string;
grantConsentScript: string;
}>;
title?: string;
}>;

Everything a host supplies to run Oyster.


InstallationOperationstype alias

Section titled “InstallationOperations”
Signature
type InstallationOperations = Readonly<{
admit: Promise<
| {
requestId: string;
requestedInstallationId: string;
installationId: string;
release: {
releaseId: Schema.refine<ReleaseId, Schema.String>;
appId: Schema.refine<AppId, Schema.String>;
artifact: Schema.Struct<{
artifactRef: Schema.refine<ArtifactRef, Schema.String>;
artifactDigest: Schema.refine<Sha256Digest, Schema.String>;
provenance: Schema.Struct<{
sourceRevision: Schema.refine<..., ...>;
sourceTreeDigest: Schema.refine<..., ...>;
buildRecipeDigest: Schema.refine<..., ...>;
}>;
}>;
};
state: "refused";
status: number;
code: string;
}
| {
requestId: string;
requestedInstallationId: string;
installationId: string;
release: {
releaseId: Schema.refine<ReleaseId, Schema.String>;
appId: Schema.refine<AppId, Schema.String>;
artifact: Schema.Struct<{
artifactRef: Schema.refine<ArtifactRef, Schema.String>;
artifactDigest: Schema.refine<Sha256Digest, Schema.String>;
provenance: Schema.Struct<{
sourceRevision: Schema.refine<..., ...>;
sourceTreeDigest: Schema.refine<..., ...>;
buildRecipeDigest: Schema.refine<..., ...>;
}>;
}>;
};
state: "unconfirmed";
outcome: "cancelled" | "outcome_unknown" | "interrupted";
}
| {
requestId: string;
requestedInstallationId: string;
installationId: string;
release: {
releaseId: Schema.refine<ReleaseId, Schema.String>;
appId: Schema.refine<AppId, Schema.String>;
artifact: Schema.Struct<{
artifactRef: Schema.refine<ArtifactRef, Schema.String>;
artifactDigest: Schema.refine<Sha256Digest, Schema.String>;
provenance: Schema.Struct<{
sourceRevision: Schema.refine<..., ...>;
sourceTreeDigest: Schema.refine<..., ...>;
buildRecipeDigest: Schema.refine<..., ...>;
}>;
}>;
};
state: "succeeded";
reference: {
generation: string;
instanceId: InstanceId;
authorityVersion: number;
status: "enabled" | "disabled" | "deleted";
};
creation: "fresh" | "replacement" | "reminted";
uiCheck: | {
kind: "passed";
}
| {
kind: "failed";
code: "ui_mount_failed";
diagnostics?: {
failedPredicate: | "unexpected_candidate_request"
| "response_status"
| "request_failed"
| "page_error"
| "candidate_not_mounted";
errorName?: | "TypeError"
| "RangeError"
| "SyntaxError"
| "AbortError"
| "TimeoutError"
| "Other"
| "Error";
finalUrlPath: string;
consoleErrors: string[];
pageErrors: string[];
failedRequests: object[];
droppedCount: number;
};
}
| {
kind: "not_checked";
code: | "boot_runner_unavailable"
| "boot_browser_binding_missing"
| "boot_clone_unavailable"
| "boot_timeout"
| "boot_cleanup_failed"
| "ui_check_not_run_on_host";
}
| null;
installation: | {
installationId: string;
instanceId: InstanceId | null;
appId: AppId;
release: {
releaseId: Schema.refine<ReleaseId, Schema.String>;
appId: Schema.refine<AppId, Schema.String>;
artifact: Schema.Struct<{
artifactRef: Schema.refine<..., ...>;
artifactDigest: Schema.refine<..., ...>;
provenance: Schema.Struct<...>;
}>;
};
releasePin: "pinned" | "floating";
authority: {
authorityVersion: number;
declaredOperationsDigest: Sha256Digest;
approvedGrants: readonly Readonly<{
capability: ...;
capabilityApproved: ...;
operations: ...;
resources: ...;
}>[];
approval: | Readonly<{
by: ...;
at: ...;
authorityVersion: ...;
}>
| null;
};
status: "enabled" | "disabled" | "deleted";
visibility: "private" | "public";
approvedAnonymousMethods: readonly Readonly<{
name: string;
digest: Sha256Digest;
}>[];
anonymousApproval: | Readonly<{
by: ... | ... | ...;
at: number;
authorityVersion: number;
}>
| null;
}
| null;
}
| {
requestId: string;
requestedInstallationId: string;
installationId: string;
release: {
releaseId: Schema.refine<ReleaseId, Schema.String>;
appId: Schema.refine<AppId, Schema.String>;
artifact: Schema.Struct<{
artifactRef: Schema.refine<ArtifactRef, Schema.String>;
artifactDigest: Schema.refine<Sha256Digest, Schema.String>;
provenance: Schema.Struct<{
sourceRevision: Schema.refine<..., ...>;
sourceTreeDigest: Schema.refine<..., ...>;
buildRecipeDigest: Schema.refine<..., ...>;
}>;
}>;
};
state: "pending";
}>;
read: Promise<
| {
requestId: string;
requestedInstallationId: string;
installationId: string;
release: {
releaseId: Schema.refine<ReleaseId, Schema.String>;
appId: Schema.refine<AppId, Schema.String>;
artifact: Schema.Struct<{
artifactRef: Schema.refine<ArtifactRef, Schema.String>;
artifactDigest: Schema.refine<Sha256Digest, Schema.String>;
provenance: Schema.Struct<{
sourceRevision: Schema.refine<..., ...>;
sourceTreeDigest: Schema.refine<..., ...>;
buildRecipeDigest: Schema.refine<..., ...>;
}>;
}>;
};
state: "refused";
status: number;
code: string;
}
| {
requestId: string;
requestedInstallationId: string;
installationId: string;
release: {
releaseId: Schema.refine<ReleaseId, Schema.String>;
appId: Schema.refine<AppId, Schema.String>;
artifact: Schema.Struct<{
artifactRef: Schema.refine<ArtifactRef, Schema.String>;
artifactDigest: Schema.refine<Sha256Digest, Schema.String>;
provenance: Schema.Struct<{
sourceRevision: Schema.refine<..., ...>;
sourceTreeDigest: Schema.refine<..., ...>;
buildRecipeDigest: Schema.refine<..., ...>;
}>;
}>;
};
state: "unconfirmed";
outcome: "cancelled" | "outcome_unknown" | "interrupted";
}
| {
requestId: string;
requestedInstallationId: string;
installationId: string;
release: {
releaseId: Schema.refine<ReleaseId, Schema.String>;
appId: Schema.refine<AppId, Schema.String>;
artifact: Schema.Struct<{
artifactRef: Schema.refine<ArtifactRef, Schema.String>;
artifactDigest: Schema.refine<Sha256Digest, Schema.String>;
provenance: Schema.Struct<{
sourceRevision: Schema.refine<..., ...>;
sourceTreeDigest: Schema.refine<..., ...>;
buildRecipeDigest: Schema.refine<..., ...>;
}>;
}>;
};
state: "succeeded";
reference: {
generation: string;
instanceId: InstanceId;
authorityVersion: number;
status: "enabled" | "disabled" | "deleted";
};
creation: "fresh" | "replacement" | "reminted";
uiCheck: | {
kind: "passed";
}
| {
kind: "failed";
code: "ui_mount_failed";
diagnostics?: {
failedPredicate: | "unexpected_candidate_request"
| "response_status"
| "request_failed"
| "page_error"
| "candidate_not_mounted";
errorName?: | "TypeError"
| "RangeError"
| "SyntaxError"
| "AbortError"
| "TimeoutError"
| "Other"
| "Error";
finalUrlPath: string;
consoleErrors: string[];
pageErrors: string[];
failedRequests: object[];
droppedCount: number;
};
}
| {
kind: "not_checked";
code: | "boot_runner_unavailable"
| "boot_browser_binding_missing"
| "boot_clone_unavailable"
| "boot_timeout"
| "boot_cleanup_failed"
| "ui_check_not_run_on_host";
}
| null;
installation: | {
installationId: string;
instanceId: InstanceId | null;
appId: AppId;
release: {
releaseId: Schema.refine<ReleaseId, Schema.String>;
appId: Schema.refine<AppId, Schema.String>;
artifact: Schema.Struct<{
artifactRef: Schema.refine<..., ...>;
artifactDigest: Schema.refine<..., ...>;
provenance: Schema.Struct<...>;
}>;
};
releasePin: "pinned" | "floating";
authority: {
authorityVersion: number;
declaredOperationsDigest: Sha256Digest;
approvedGrants: readonly Readonly<{
capability: ...;
capabilityApproved: ...;
operations: ...;
resources: ...;
}>[];
approval: | Readonly<{
by: ...;
at: ...;
authorityVersion: ...;
}>
| null;
};
status: "enabled" | "disabled" | "deleted";
visibility: "private" | "public";
approvedAnonymousMethods: readonly Readonly<{
name: string;
digest: Sha256Digest;
}>[];
anonymousApproval: | Readonly<{
by: ... | ... | ...;
at: number;
authorityVersion: number;
}>
| null;
}
| null;
}
| {
requestId: string;
requestedInstallationId: string;
installationId: string;
release: {
releaseId: Schema.refine<ReleaseId, Schema.String>;
appId: Schema.refine<AppId, Schema.String>;
artifact: Schema.Struct<{
artifactRef: Schema.refine<ArtifactRef, Schema.String>;
artifactDigest: Schema.refine<Sha256Digest, Schema.String>;
provenance: Schema.Struct<{
sourceRevision: Schema.refine<..., ...>;
sourceTreeDigest: Schema.refine<..., ...>;
buildRecipeDigest: Schema.refine<..., ...>;
}>;
}>;
};
state: "pending";
}
| null>;
load: Promise<
| {
admission: {
requestId: string;
installationId: string;
release: {
releaseId: Schema.refine<ReleaseId, Schema.String>;
appId: Schema.refine<AppId, Schema.String>;
artifact: Schema.Struct<{
artifactRef: Schema.refine<ArtifactRef, Schema.String>;
artifactDigest: Schema.refine<Sha256Digest, Schema.String>;
provenance: Schema.Struct<{
sourceRevision: ...;
sourceTreeDigest: ...;
buildRecipeDigest: ...;
}>;
}>;
};
actor: | {
kind: z.ZodMiniLiteral<"member">;
memberId: z.ZodMiniString<string>;
}
| {
kind: z.ZodMiniLiteral<"agent">;
agentId: z.ZodMiniString<string>;
}
| {
kind: z.ZodMiniLiteral<"team-key">;
keyId: z.ZodMiniString<string>;
};
intent: "install-or-select" | "install-or-remint" | "create-only";
origin: "workflow" | "owner-direct";
};
scope: {
tenantId: string & Brand<"OysterTenantId">;
origin: string;
};
installationId: string;
instanceId: InstanceId;
generation: string;
baseline: | {
installationId: string;
instanceId: InstanceId | null;
appId: AppId;
release: {
releaseId: Schema.refine<ReleaseId, Schema.String>;
appId: Schema.refine<AppId, Schema.String>;
artifact: Schema.Struct<{
artifactRef: Schema.refine<..., ...>;
artifactDigest: Schema.refine<..., ...>;
provenance: Schema.Struct<...>;
}>;
};
releasePin: "pinned" | "floating";
authority: {
authorityVersion: number;
declaredOperationsDigest: Sha256Digest;
approvedGrants: readonly Readonly<{
capability: ...;
capabilityApproved: ...;
operations: ...;
resources: ...;
}>[];
approval: | Readonly<{
by: ...;
at: ...;
authorityVersion: ...;
}>
| null;
};
status: "enabled" | "disabled" | "deleted";
visibility: "private" | "public";
approvedAnonymousMethods: readonly Readonly<{
name: string;
digest: Sha256Digest;
}>[];
anonymousApproval: | Readonly<{
by: ... | ... | ...;
at: number;
authorityVersion: number;
}>
| null;
}
| null;
acceptedAt: number;
creation: "fresh" | "replacement" | "reminted";
plan: | {
installation: {
installationId: string;
instanceId: InstanceId | null;
appId: AppId;
release: {
releaseId: Schema.refine<ReleaseId, Schema.String>;
appId: Schema.refine<AppId, Schema.String>;
artifact: Schema.Struct<{
artifactRef: ...;
artifactDigest: ...;
provenance: ...;
}>;
};
releasePin: "pinned" | "floating";
authority: {
authorityVersion: number;
declaredOperationsDigest: Sha256Digest;
approvedGrants: readonly Readonly<...>[];
approval: Readonly<...> | null;
};
status: "enabled" | "disabled" | "deleted";
visibility: "private" | "public";
approvedAnonymousMethods: readonly Readonly<{
name: ...;
digest: ...;
}>[];
anonymousApproval: | Readonly<{
by: ...;
at: ...;
authorityVersion: ...;
}>
| null;
};
hasBackend: boolean;
prepared: boolean;
uiCheck?: | {
kind: "passed";
}
| {
kind: "failed";
code: "ui_mount_failed";
diagnostics?: {
failedPredicate: ...;
errorName?: ...;
finalUrlPath: ...;
consoleErrors: ...;
pageErrors: ...;
failedRequests: ...;
droppedCount: ...;
};
}
| {
kind: "not_checked";
code: | "boot_runner_unavailable"
| "boot_browser_binding_missing"
| "boot_clone_unavailable"
| "boot_timeout"
| "boot_cleanup_failed"
| "ui_check_not_run_on_host";
}
| null;
}
| null;
operation: {
requestId: string;
requestedInstallationId: string;
installationId: string;
release: {
releaseId: Schema.refine<ReleaseId, Schema.String>;
appId: Schema.refine<AppId, Schema.String>;
artifact: Schema.Struct<{
artifactRef: Schema.refine<ArtifactRef, Schema.String>;
artifactDigest: Schema.refine<Sha256Digest, Schema.String>;
provenance: Schema.Struct<{
sourceRevision: ...;
sourceTreeDigest: ...;
buildRecipeDigest: ...;
}>;
}>;
};
state: "pending";
};
}
| null>;
plan: Promise<{
admission: {
requestId: string;
installationId: string;
release: {
releaseId: Schema.refine<ReleaseId, Schema.String>;
appId: Schema.refine<AppId, Schema.String>;
artifact: Schema.Struct<{
artifactRef: Schema.refine<ArtifactRef, Schema.String>;
artifactDigest: Schema.refine<Sha256Digest, Schema.String>;
provenance: Schema.Struct<{
sourceRevision: Schema.refine<..., ...>;
sourceTreeDigest: Schema.refine<..., ...>;
buildRecipeDigest: Schema.refine<..., ...>;
}>;
}>;
};
actor: | {
kind: z.ZodMiniLiteral<"member">;
memberId: z.ZodMiniString<string>;
}
| {
kind: z.ZodMiniLiteral<"agent">;
agentId: z.ZodMiniString<string>;
}
| {
kind: z.ZodMiniLiteral<"team-key">;
keyId: z.ZodMiniString<string>;
};
intent: "install-or-select" | "install-or-remint" | "create-only";
origin: "workflow" | "owner-direct";
};
scope: {
tenantId: string & Brand<"OysterTenantId">;
origin: string;
};
installationId: string;
instanceId: InstanceId;
generation: string;
baseline: | {
installationId: string;
instanceId: InstanceId | null;
appId: AppId;
release: {
releaseId: Schema.refine<ReleaseId, Schema.String>;
appId: Schema.refine<AppId, Schema.String>;
artifact: Schema.Struct<{
artifactRef: Schema.refine<ArtifactRef, Schema.String>;
artifactDigest: Schema.refine<Sha256Digest, Schema.String>;
provenance: Schema.Struct<{
sourceRevision: ...;
sourceTreeDigest: ...;
buildRecipeDigest: ...;
}>;
}>;
};
releasePin: "pinned" | "floating";
authority: {
authorityVersion: number;
declaredOperationsDigest: Sha256Digest;
approvedGrants: readonly Readonly<{
capability: | ...
| ...
| ...
| ...
| ...
| ...
| ...
| ...
| ...
| ...
| ...
| ...
| ...
| ...
| ...
| ...
| ...
| ...
| ...
| ...
| ...
| ...
| ...
| ...
| ...
| ...
| ...
| ...
| ...;
capabilityApproved: true;
operations: readonly ...[];
resources: ... | ...;
}>[];
approval: | Readonly<{
by: ... | ... | ...;
at: number;
authorityVersion: number;
}>
| null;
};
status: "enabled" | "disabled" | "deleted";
visibility: "private" | "public";
approvedAnonymousMethods: readonly Readonly<{
name: string;
digest: Sha256Digest;
}>[];
anonymousApproval: | Readonly<{
by: | {
kind: ...;
memberId: ...;
}
| {
kind: ...;
agentId: ...;
}
| {
kind: ...;
keyId: ...;
};
at: number;
authorityVersion: number;
}>
| null;
}
| null;
acceptedAt: number;
creation: "fresh" | "replacement" | "reminted";
plan: | {
installation: {
installationId: string;
instanceId: InstanceId | null;
appId: AppId;
release: {
releaseId: Schema.refine<ReleaseId, Schema.String>;
appId: Schema.refine<AppId, Schema.String>;
artifact: Schema.Struct<{
artifactRef: Schema.refine<..., ...>;
artifactDigest: Schema.refine<..., ...>;
provenance: Schema.Struct<...>;
}>;
};
releasePin: "pinned" | "floating";
authority: {
authorityVersion: number;
declaredOperationsDigest: Sha256Digest;
approvedGrants: readonly Readonly<{
capability: ...;
capabilityApproved: ...;
operations: ...;
resources: ...;
}>[];
approval: | Readonly<{
by: ...;
at: ...;
authorityVersion: ...;
}>
| null;
};
status: "enabled" | "disabled" | "deleted";
visibility: "private" | "public";
approvedAnonymousMethods: readonly Readonly<{
name: string;
digest: Sha256Digest;
}>[];
anonymousApproval: | Readonly<{
by: ... | ... | ...;
at: number;
authorityVersion: number;
}>
| null;
};
hasBackend: boolean;
prepared: boolean;
uiCheck?: | {
kind: "passed";
}
| {
kind: "failed";
code: "ui_mount_failed";
diagnostics?: {
failedPredicate: ... | ... | ... | ... | ...;
errorName?: ... | ... | ... | ... | ... | ... | ... | ...;
finalUrlPath: string;
consoleErrors: ...[];
pageErrors: ...[];
failedRequests: ...[];
droppedCount: number;
};
}
| {
kind: "not_checked";
code: | "boot_runner_unavailable"
| "boot_browser_binding_missing"
| "boot_clone_unavailable"
| "boot_timeout"
| "boot_cleanup_failed"
| "ui_check_not_run_on_host";
}
| null;
}
| null;
operation: {
requestId: string;
requestedInstallationId: string;
installationId: string;
release: {
releaseId: Schema.refine<ReleaseId, Schema.String>;
appId: Schema.refine<AppId, Schema.String>;
artifact: Schema.Struct<{
artifactRef: Schema.refine<ArtifactRef, Schema.String>;
artifactDigest: Schema.refine<Sha256Digest, Schema.String>;
provenance: Schema.Struct<{
sourceRevision: Schema.refine<..., ...>;
sourceTreeDigest: Schema.refine<..., ...>;
buildRecipeDigest: Schema.refine<..., ...>;
}>;
}>;
};
state: "pending";
};
}>;
commit: Promise<InstallationCommit>;
}>;

Host-side port; RPC transport and tenant context belong to the adapter.


ArtifactStoretype alias

Section titled “ArtifactStore”
Signature
type ArtifactStore = Readonly<{
get: (artifactRef) => Promise<Uint8Array | null>;
put: (artifactRef, bytes) => Promise<void>;
}>;

Immutable Release bytes addressed by their artifact reference.


VerifiedReleasetype alias

Section titled “VerifiedRelease”
Signature
type VerifiedRelease = Readonly<{
release: Release;
build: AppBuild;
api: AppApi | null;
declaration: AppDeclaration | null;
ui:
| Readonly<{
kind: "html";
artifactRef: ArtifactRef;
digest: Sha256Digest;
}>
| Readonly<{
kind: "assets";
build: AssetBuild;
}>
| null;
backend: Readonly<{
artifactRef: ArtifactRef;
digest: Sha256Digest;
}> | null;
}>;

A Release whose root, UI and backend artifacts were read and verified.


VerifiedObjectCachetype alias

Section titled “VerifiedObjectCache”
Signature
type VerifiedObjectCache = Readonly<{
match: (digest) => Promise<ReadableStream<Uint8Array> | null>;
put: (digest, bytes) => Promise<"stored" | "unstored">;
}>;

Copies of verified artifacts near the reader, keyed by content digest. An entry holds only bytes that already matched its digest, so a hit is served without another store read or hash.

capabilityMethodKindSchemaconstant

Section titled “capabilityMethodKindSchema”
Signature
const capabilityMethodKindSchema: Literals<
readonly ["json", "transport", "read", "write"]
>;

How an admitted capability method is exposed to the App.


capabilityMethodSchemaconstant

Section titled “capabilityMethodSchema”
Signature
const capabilityMethodSchema: Union<
readonly [
Struct<{
kind: Literal<"transport">;
method: Literals<
readonly [
"GET",
"POST",
"PUT",
"DELETE",
"PATCH",
"HEAD",
"OPTIONS",
"ANY",
]
>;
path: String;
}>,
Struct<{
kind: Literals<readonly ["json", "read", "write"]>;
method: Literals<
readonly ["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"]
>;
path: String;
}>,
]
>;

The HTTP operation exposed by one capability method on an Oyster page.


capabilityDescriptorSchemaconstant

Section titled “capabilityDescriptorSchema”
Signature
const capabilityDescriptorSchema: Struct<{
id: String;
version: Number;
base: String;
methods: $Record<
String,
Union<
readonly [
Struct<{
kind: Literal<"transport">;
method: Literals<
readonly [
"GET",
"POST",
"PUT",
"DELETE",
"PATCH",
"HEAD",
"OPTIONS",
"ANY",
]
>;
path: String;
}>,
Struct<{
kind: Literals<readonly ["json", "read", "write"]>;
method: Literals<
readonly [
"GET",
"POST",
"PUT",
"DELETE",
"PATCH",
"HEAD",
"OPTIONS",
]
>;
path: String;
}>,
]
>
>;
}>;

The serializable part of a capability admitted to an installation’s page.


defaultAssetPolicyconstant

Section titled “defaultAssetPolicy”
Signature
const defaultAssetPolicy: AssetBuildPolicy;

Default bounds for an App’s UI asset build.

oysterPrincipalIsVisitor()function

Section titled “oysterPrincipalIsVisitor()”
Signature
function oysterPrincipalIsVisitor(
principal,
): principal is Readonly<{ actor: Readonly<{ kind: "visitor" }> }>;

Narrow an admitted principal to the anonymous public reader.

Parameter Type
principal OysterPrincipal

principal is Readonly<{ actor: Readonly<{ kind: "visitor" }> }>


oysterPrincipalIsOwner()function

Section titled “oysterPrincipalIsOwner()”
Signature
function oysterPrincipalIsOwner(
principal,
): principal is Readonly<{
actor: { kind: "member"; memberId: string };
role: "owner";
}>;

True only for a member admitted with the owner role.

Parameter Type
principal OysterPrincipal

principal is Readonly<{ actor: { kind: "member"; memberId: string }; role: "owner" }>


oysterPrincipalId()function

Section titled “oysterPrincipalId()”
Signature
function oysterPrincipalId(principal): string;

Stable actor identity for host storage and backend attribution.

Parameter Type
principal TenantPrincipal

string


installOrSelect()function

Section titled “installOrSelect()”
Signature
function installOrSelect(
host,
installationId,
release,
principal,
intent,
origin,
requestId?,
signal?,
): Promise<Response>;

Completed selection, without re-deriving or executing outside Watchdog.

Parameter Type
host OysterHost
installationId string
release Release
principal OysterPrincipal
intent "install-or-select" | "install-or-remint" | "create-only"
origin "workflow" | "owner-direct" | "app"
requestId string
signal AbortSignal

Promise<Response>


createOyster()function

Section titled “createOyster()”
Signature
function createOyster(host): Hono<OysterEnv>;

Create the Oyster App server: a Hono app that installs App Releases, serves their UI, forwards their backend requests and methods to their Instances, and mounts the host’s MCP endpoint. The host’s adapters decide where state lives and who may sign in.

Parameter Type
host OysterHost

Hono<OysterEnv>


Signature
function sha256(bytes): Promise<string>;

Hex SHA-256 digest in Puffball’s sha256:<hex> form.

Parameter Type
bytes Uint8Array

Promise<string>


parseRelease()function

Section titled “parseRelease()”
Signature
function parseRelease(value): Release;

Decode an untrusted Release record, as an install request carries it.

Parameter Type
value unknown

Release


verifyRelease()function

Section titled “verifyRelease()”
Signature
function verifyRelease(
store,
release,
policy?,
readAssets?
): Promise<Readonly<{
release: Release;
build: | {
declaration?: Readonly<{
api?: Readonly<{
methods: ...;
toolFamily?: ...;
events?: ...;
}>;
displayName?: string;
capabilities: readonly (
| "computer.list"
| "computer.readFile"
| "computer.writeFile"
| "computer.execute"
| "approvals"
| "agent.list"
| "agent.manage"
| "agent.rename"
| "agent.avatar"
| "agent.toolPolicy"
| "agent.read"
| "agent.send"
| "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")[];
calls?: readonly Readonly<...>[];
guidance?: string;
handlers: readonly "file.open"[];
receives?: readonly "git.push"[];
icon?: string;
roles: readonly ("files" | "dashboard" | "inbox" | "media" | "sessions" | "terminal")[];
storage?: readonly Readonly<...>[];
commands?: readonly Readonly<...>[];
gills?: readonly Readonly<...>[];
backend?: Readonly<{
bindings: ...;
sync?: ...;
}>;
}>;
format: "fungi-app-v1";
ui: {
mediaType: "text/html; charset=utf-8" | "application/vnd.fungi.app-assets+json";
artifactRef: ArtifactRef;
digest: Sha256Digest;
version: string;
byteLength: number;
};
backend: {
mediaType: "application/vnd.fungi.app-backend+json";
artifactRef: ArtifactRef;
digest: Sha256Digest;
version: string;
byteLength: number;
};
}
| {
declaration?: Readonly<{
api?: Readonly<{
methods: ...;
toolFamily?: ...;
events?: ...;
}>;
displayName?: string;
capabilities: readonly (
| "computer.list"
| "computer.readFile"
| "computer.writeFile"
| "computer.execute"
| "approvals"
| "agent.list"
| "agent.manage"
| "agent.rename"
| "agent.avatar"
| "agent.toolPolicy"
| "agent.read"
| "agent.send"
| "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")[];
calls?: readonly Readonly<...>[];
guidance?: string;
handlers: readonly "file.open"[];
receives?: readonly "git.push"[];
icon?: string;
roles: readonly ("files" | "dashboard" | "inbox" | "media" | "sessions" | "terminal")[];
storage?: readonly Readonly<...>[];
commands?: readonly Readonly<...>[];
gills?: readonly Readonly<...>[];
backend?: Readonly<{
bindings: ...;
sync?: ...;
}>;
}>;
format: "fungi-app-v1";
ui: {
mediaType: "text/html; charset=utf-8" | "application/vnd.fungi.app-assets+json";
artifactRef: ArtifactRef;
digest: Sha256Digest;
version: string;
byteLength: number;
};
}
| {
declaration?: Readonly<{
api?: Readonly<{
methods: ...;
toolFamily?: ...;
events?: ...;
}>;
displayName?: string;
capabilities: readonly (
| "computer.list"
| "computer.readFile"
| "computer.writeFile"
| "computer.execute"
| "approvals"
| "agent.list"
| "agent.manage"
| "agent.rename"
| "agent.avatar"
| "agent.toolPolicy"
| "agent.read"
| "agent.send"
| "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")[];
calls?: readonly Readonly<...>[];
guidance?: string;
handlers: readonly "file.open"[];
receives?: readonly "git.push"[];
icon?: string;
roles: readonly ("files" | "dashboard" | "inbox" | "media" | "sessions" | "terminal")[];
storage?: readonly Readonly<...>[];
commands?: readonly Readonly<...>[];
gills?: readonly Readonly<...>[];
backend?: Readonly<{
bindings: ...;
sync?: ...;
}>;
}>;
format: "fungi-app-v1";
backend: {
mediaType: "application/vnd.fungi.app-backend+json";
artifactRef: ArtifactRef;
digest: Sha256Digest;
version: string;
byteLength: number;
};
};
api: | Readonly<{
methods: Readonly<Record<string, Readonly<{
description: string;
input: object;
output: object;
effect: ... | ... | ...;
requires: readonly ...;
pending?: ... | ...;
hidden?: ... | ...;
anonymous?: ... | ...;
present?: ... | ...;
}>>>;
toolFamily?: Readonly<{
name: string;
list: string;
call: string;
}>;
events?: Readonly<Record<string, Readonly<{
description: ...;
payload: ...;
}>>>;
}>
| null;
declaration: | Readonly<{
api?: Readonly<{
methods: Readonly<Record<..., ...>>;
toolFamily?: Readonly<...>;
events?: Readonly<...>;
}>;
displayName?: string;
capabilities: readonly (
| "computer.list"
| "computer.readFile"
| "computer.writeFile"
| "computer.execute"
| "approvals"
| "agent.list"
| "agent.manage"
| "agent.rename"
| "agent.avatar"
| "agent.toolPolicy"
| "agent.read"
| "agent.send"
| "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")[];
calls?: readonly Readonly<{
appId: string;
methods: readonly ...[];
}>[];
guidance?: string;
handlers: readonly "file.open"[];
receives?: readonly "git.push"[];
icon?: string;
roles: readonly ("files" | "dashboard" | "inbox" | "media" | "sessions" | "terminal")[];
storage?: readonly Readonly<{
key: string;
scopes: readonly ...[];
maxBytes: number;
}>[];
commands?: readonly Readonly<{
id: string;
title: string;
category: string;
description?: ... | ...;
sigil?: ... | ...;
projections?: ... | ...;
}>[];
gills?: readonly Readonly<{
id: string;
source: string;
title: string;
params?: ... | ...;
watch?: ... | ...;
desktop?: ... | ...;
}>[];
backend?: Readonly<{
bindings: readonly Readonly<...>[];
sync?: Readonly<...>;
}>;
}>
| null;
ui: | Readonly<{
kind: "html";
artifactRef: ArtifactRef;
digest: Sha256Digest;
}>
| Readonly<{
kind: "assets";
build: {
format: "fungi-assets-v1";
base: string;
assets: readonly object[];
};
}>
| null;
backend: | Readonly<{
artifactRef: ArtifactRef;
digest: Sha256Digest;
}>
| null;
}>>;

Read a Release root and verify its UI build and backend descriptor. readAssets verifies UI object bodies when true. When false, it reads the asset manifest needed to resolve references but does not read any UI object body, including standalone HTML.

Parameter Type Default value Description
store ArtifactStore undefined -
release Release undefined -
policy { maxManifestBytes: number; maxObjects: number; maxObjectBytes: number; maxTotalBytes: number; } defaultAssetPolicy -
policy.maxManifestBytes number undefined -
policy.maxObjects number undefined -
policy.maxObjectBytes number undefined -
policy.maxTotalBytes number undefined -
readAssets boolean true Read and check every UI object now. Serving verifies each on demand.

Promise<Readonly<{ release: Release; build: | { declaration?: Readonly<{ api?: Readonly<{ methods: …; toolFamily?: …; events?: …; }>; displayName?: string; capabilities: readonly ( | "computer.list" | "computer.readFile" | "computer.writeFile" | "computer.execute" | "approvals" | "agent.list" | "agent.manage" | "agent.rename" | "agent.avatar" | "agent.toolPolicy" | "agent.read" | "agent.send" | "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")[]; calls?: readonly Readonly<…>[]; guidance?: string; handlers: readonly "file.open"[]; receives?: readonly "git.push"[]; icon?: string; roles: readonly ("files" | "dashboard" | "inbox" | "media" | "sessions" | "terminal")[]; storage?: readonly Readonly<…>[]; commands?: readonly Readonly<…>[]; gills?: readonly Readonly<…>[]; backend?: Readonly<{ bindings: …; sync?: …; }>; }>; format: "fungi-app-v1"; ui: { mediaType: "text/html; charset=utf-8" | "application/vnd.fungi.app-assets+json"; artifactRef: ArtifactRef; digest: Sha256Digest; version: string; byteLength: number; }; backend: { mediaType: "application/vnd.fungi.app-backend+json"; artifactRef: ArtifactRef; digest: Sha256Digest; version: string; byteLength: number; }; } | { declaration?: Readonly<{ api?: Readonly<{ methods: …; toolFamily?: …; events?: …; }>; displayName?: string; capabilities: readonly ( | "computer.list" | "computer.readFile" | "computer.writeFile" | "computer.execute" | "approvals" | "agent.list" | "agent.manage" | "agent.rename" | "agent.avatar" | "agent.toolPolicy" | "agent.read" | "agent.send" | "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")[]; calls?: readonly Readonly<…>[]; guidance?: string; handlers: readonly "file.open"[]; receives?: readonly "git.push"[]; icon?: string; roles: readonly ("files" | "dashboard" | "inbox" | "media" | "sessions" | "terminal")[]; storage?: readonly Readonly<…>[]; commands?: readonly Readonly<…>[]; gills?: readonly Readonly<…>[]; backend?: Readonly<{ bindings: …; sync?: …; }>; }>; format: "fungi-app-v1"; ui: { mediaType: "text/html; charset=utf-8" | "application/vnd.fungi.app-assets+json"; artifactRef: ArtifactRef; digest: Sha256Digest; version: string; byteLength: number; }; } | { declaration?: Readonly<{ api?: Readonly<{ methods: …; toolFamily?: …; events?: …; }>; displayName?: string; capabilities: readonly ( | "computer.list" | "computer.readFile" | "computer.writeFile" | "computer.execute" | "approvals" | "agent.list" | "agent.manage" | "agent.rename" | "agent.avatar" | "agent.toolPolicy" | "agent.read" | "agent.send" | "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")[]; calls?: readonly Readonly<…>[]; guidance?: string; handlers: readonly "file.open"[]; receives?: readonly "git.push"[]; icon?: string; roles: readonly ("files" | "dashboard" | "inbox" | "media" | "sessions" | "terminal")[]; storage?: readonly Readonly<…>[]; commands?: readonly Readonly<…>[]; gills?: readonly Readonly<…>[]; backend?: Readonly<{ bindings: …; sync?: …; }>; }>; format: "fungi-app-v1"; backend: { mediaType: "application/vnd.fungi.app-backend+json"; artifactRef: ArtifactRef; digest: Sha256Digest; version: string; byteLength: number; }; }; api: | Readonly<{ methods: Readonly<Record<string, Readonly<{ description: string; input: object; output: object; effect: … | … | …; requires: readonly …; pending?: … | …; hidden?: … | …; anonymous?: … | …; present?: … | …; }>>>; toolFamily?: Readonly<{ name: string; list: string; call: string; }>; events?: Readonly<Record<string, Readonly<{ description: …; payload: …; }>>>; }> | null; declaration: | Readonly<{ api?: Readonly<{ methods: Readonly<Record<…, …>>; toolFamily?: Readonly<…>; events?: Readonly<…>; }>; displayName?: string; capabilities: readonly ( | "computer.list" | "computer.readFile" | "computer.writeFile" | "computer.execute" | "approvals" | "agent.list" | "agent.manage" | "agent.rename" | "agent.avatar" | "agent.toolPolicy" | "agent.read" | "agent.send" | "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")[]; calls?: readonly Readonly<{ appId: string; methods: readonly …[]; }>[]; guidance?: string; handlers: readonly "file.open"[]; receives?: readonly "git.push"[]; icon?: string; roles: readonly ("files" | "dashboard" | "inbox" | "media" | "sessions" | "terminal")[]; storage?: readonly Readonly<{ key: string; scopes: readonly …[]; maxBytes: number; }>[]; commands?: readonly Readonly<{ id: string; title: string; category: string; description?: … | …; sigil?: … | …; projections?: … | …; }>[]; gills?: readonly Readonly<{ id: string; source: string; title: string; params?: … | …; watch?: … | …; desktop?: … | …; }>[]; backend?: Readonly<{ bindings: readonly Readonly<…>[]; sync?: Readonly<…>; }>; }> | null; ui: | Readonly<{ kind: "html"; artifactRef: ArtifactRef; digest: Sha256Digest; }> | Readonly<{ kind: "assets"; build: { format: "fungi-assets-v1"; base: string; assets: readonly object[]; }; }> | null; backend: | Readonly<{ artifactRef: ArtifactRef; digest: Sha256Digest; }> | null; }>>


resolveBackend()function

Section titled “resolveBackend()”
Signature
function resolveBackend(store, release): Promise<
| Readonly<{
digest: Sha256Digest;
backend: DurableBackend;
declaration: | Readonly<{
api?: Readonly<{
methods: Readonly<...>;
toolFamily?: ... | ...;
events?: ... | ...;
}>;
displayName?: string;
capabilities: readonly (
| "computer.list"
| "computer.readFile"
| "computer.writeFile"
| "computer.execute"
| "approvals"
| "agent.list"
| "agent.manage"
| "agent.rename"
| "agent.avatar"
| "agent.toolPolicy"
| "agent.read"
| "agent.send"
| "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")[];
calls?: readonly Readonly<{
appId: ...;
methods: ...;
}>[];
guidance?: string;
handlers: readonly "file.open"[];
receives?: readonly "git.push"[];
icon?: string;
roles: readonly ("files" | "dashboard" | "inbox" | "media" | "sessions" | "terminal")[];
storage?: readonly Readonly<{
key: ...;
scopes: ...;
maxBytes: ...;
}>[];
commands?: readonly Readonly<{
id: ...;
title: ...;
category: ...;
description?: ...;
sigil?: ...;
projections?: ...;
}>[];
gills?: readonly Readonly<{
id: ...;
source: ...;
title: ...;
params?: ...;
watch?: ...;
desktop?: ...;
}>[];
backend?: Readonly<{
bindings: readonly ...[];
sync?: ... | ...;
}>;
}>
| null;
}>
| null>;

Resolve a Release to its verified durable backend without reading its UI: the root artifact, then the backend descriptor it names.

Parameter Type
store ArtifactStore
release Release

Promise< | Readonly<{ digest: Sha256Digest; backend: DurableBackend; declaration: | Readonly<{ api?: Readonly<{ methods: Readonly<…>; toolFamily?: … | …; events?: … | …; }>; displayName?: string; capabilities: readonly ( | "computer.list" | "computer.readFile" | "computer.writeFile" | "computer.execute" | "approvals" | "agent.list" | "agent.manage" | "agent.rename" | "agent.avatar" | "agent.toolPolicy" | "agent.read" | "agent.send" | "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")[]; calls?: readonly Readonly<{ appId: …; methods: …; }>[]; guidance?: string; handlers: readonly "file.open"[]; receives?: readonly "git.push"[]; icon?: string; roles: readonly ("files" | "dashboard" | "inbox" | "media" | "sessions" | "terminal")[]; storage?: readonly Readonly<{ key: …; scopes: …; maxBytes: …; }>[]; commands?: readonly Readonly<{ id: …; title: …; category: …; description?: …; sigil?: …; projections?: …; }>[]; gills?: readonly Readonly<{ id: …; source: …; title: …; params?: …; watch?: …; desktop?: …; }>[]; backend?: Readonly<{ bindings: readonly …[]; sync?: … | …; }>; }> | null; }> | null>

Re-exports GuestLimits