{ "lexicon": 1, "id": "com.fedfork.exec.wasm.module", "defs": { "main": { "type": "record", "key": "any", "description": "A sandboxed WebAssembly module that turns user input into XRPC calls made with the session of an OAuth client metadata record. A module may run over several rounds: each output can name a next entry and state, and the host passes the call results back in.", "record": { "type": "object", "required": [ "name", "module", "abi", "actions", "createdAt" ], "properties": { "name": { "type": "string", "maxLength": 2560, "maxGraphemes": 256 }, "description": { "type": "string", "maxLength": 30000, "maxGraphemes": 3000 }, "module": { "type": "blob", "accept": [ "application/wasm" ], "maxSize": 4194304 }, "abi": { "type": "string", "maxLength": 256, "knownValues": [ "emdash-wasm-json-v1" ] }, "session": { "type": "ref", "ref": "com.atproto.repo.strongRef", "description": "The com.fedfork.exec.oauth.clientMetadata record whose session the module's calls use. Absent for a module that makes no session calls of its own (a policy module in a composition)." }, "source": { "type": "ref", "ref": "com.atproto.repo.strongRef", "description": "The com.fedfork.exec.source.manifest record listing the source files and the build that produced the module blob." }, "actions": { "type": "array", "maxLength": 256, "items": { "type": "ref", "ref": "#action" } }, "calls": { "type": "array", "maxLength": 256, "description": "NSIDs the module may ask the host to call. The host refuses any other call. When absent, the session's granted scopes are the only limit. Includes host pseudo-calls, handled by the host and never sent to a PDS: com.fedfork.exec.attest (sign a record), com.fedfork.exec.webrtc.connect (datachannel to a guest VM), com.fedfork.exec.iroh.connect (dial an iroh ticket).", "items": { "type": "string", "format": "nsid" } }, "hooks": { "type": "array", "maxLength": 256, "description": "NSIDs the module calls that another party must serve: a composition routes each to an instance's entry or a caller handler. Not sent to the session's PDS.", "items": { "type": "ref", "ref": "#hook" } }, "implements": { "type": "array", "maxLength": 256, "description": "Hook contracts an entry of this module serves; a hook default routes to the entry named here.", "items": { "type": "ref", "ref": "#implementation" } }, "config": { "type": "array", "maxLength": 256, "description": "The input a composition's instance of this module may give it: every key of an instance's input is one of these fields, of its type; a required one must be given. None: no input.", "items": { "type": "ref", "ref": "#field" } }, "anyHooks": { "type": "boolean", "description": "A relay whose routed NSIDs its input names (ingress routes): a composition may route any NSID from it, not only its hooks and calls." }, "anyRecords": { "type": "array", "maxLength": 256, "description": "Collections where the module may update and delete records it did not create. In every other collection the host lets it update and delete only records it saw the module create.", "items": { "type": "string", "format": "nsid" } }, "http": { "type": "array", "maxLength": 256, "description": "Origins (scheme://host[:port]) the module's com.fedfork.exec.http.fetch calls may reach, or \"*\" for any the host allows; a request goes out only to an origin the host allows too, with the host's own headers (API keys) added.", "items": { "type": "string", "maxLength": 2048 } }, "didkey": { "type": "ref", "ref": "#didkey", "description": "The host holds a P-256 did:key for the module (sealed per module record) and answers the com.fedfork.exec.didkey.* pseudo-calls." }, "createdAt": { "type": "string", "format": "datetime" } } } }, "hook": { "type": "object", "required": [ "nsid", "reason" ], "properties": { "nsid": { "type": "string", "format": "nsid", "description": "The contract: a lexicon (procedure input and output)." }, "entries": { "type": "array", "maxLength": 256, "description": "The entries that call it (absent: every entry). A composition checks a required hook only for the entries its edges and policies reach, and the root run's entry.", "items": { "type": "string", "maxLength": 256 } }, "required": { "type": "boolean", "description": "With no route, no default and (for a transport: an NSID com.fedfork.exec..connect also in calls) not provided by the host, a composition is refused at load and a run fails at start. Default false: an unrouted hook without a default answers null (skip), or for a transport goes to the host as an ordinary call. Any other hook never reaches the host's call, in calls or not." }, "reason": { "type": "string", "maxLength": 30000, "maxGraphemes": 3000 }, "combine": { "type": "string", "knownValues": [ "all-allow" ], "description": "all-allow: any number of routes, each answering a com.publicdomainrelay.temp.market.evaluatePolicy verdict; they run in edge order and the first that does not allow is the answer (errors are denies), else {allow: true, violations: []}. Absent: at most one route." }, "default": { "type": "string", "maxLength": 512, "description": "A module (rkey of the same publisher's com.fedfork.exec.wasm.module, or a local key) that serves the hook when nothing routes it, at the entry its implements names, on its own calls allowlist (never the caller's call); a default whose module lists no calls is refused. A pinned module's default comes only from where it is pinned (a lockfile, a pinned composition instance)." } } }, "implementation": { "type": "object", "required": [ "nsid", "entry" ], "properties": { "nsid": { "type": "string", "format": "nsid" }, "entry": { "type": "string", "maxLength": 256 } } }, "didkey": { "type": "object", "required": [ "services" ], "properties": { "services": { "type": "array", "maxLength": 64, "description": "https origins whose request calls carry a service-auth token the did:key mints (the fedproxy ingress relay).", "items": { "type": "string", "format": "uri" } } } }, "action": { "type": "object", "required": [ "entry", "label" ], "properties": { "entry": { "type": "string", "maxLength": 256 }, "label": { "type": "string", "maxLength": 2560, "maxGraphemes": 256 }, "description": { "type": "string", "maxLength": 30000, "maxGraphemes": 3000 }, "readOnly": { "type": "boolean", "description": "The entry changes none of the user's data: a host may run it without asking (an MCP tool's readOnlyHint). Absent: a write, which a host confirms with the user. Not part of the module's pin: a host's own config may override it." }, "fields": { "type": "array", "maxLength": 256, "description": "Inputs the user (or an MCP client) supplies; each key becomes a property of the module input.", "items": { "type": "ref", "ref": "#field" } } } }, "field": { "type": "object", "required": [ "key", "label" ], "properties": { "key": { "type": "string", "maxLength": 256 }, "label": { "type": "string", "maxLength": 2560, "maxGraphemes": 256 }, "type": { "type": "string", "knownValues": ["string", "integer", "number", "boolean", "object", "array"], "default": "string", "description": "The JSON Schema type of the value (an MCP tool's inputSchema); an MCP host coerces an argument to it, or refuses the call." }, "required": { "type": "boolean", "description": "An MCP host refuses a call without it before the module runs." }, "description": { "type": "string", "maxLength": 30000, "maxGraphemes": 3000, "description": "What the value is, for a form's hint or an MCP tool's input description (default: the label)." } } } } }