Skip to content

Package Manifest

Every WASM package should include a flow-like.toml file beside its project sources. The manifest describes the package and the package-wide settings a node cannot state in code: resource limits, the outbound host allowlist, and OAuth scopes. Node definitions and execution permissions come from the compiled WASM binary.

flow-like.toml
manifest_version = 1
id = "com.example.hello"
name = "Hello World"
version = "1.0.0"
description = "A simple example package"
wasm_path = "build/node.wasm"
[permissions]
memory = "standard"
timeout = "standard"

The desktop developer tools look specifically for flow-like.toml.

FieldTypeRequiredDescription
manifest_versionintegerYesCurrent schema version: 1
idstringYesStable package ID, preferably reverse-domain notation
namestringYesPackage display name
versionstringYesPackage version
descriptionstringYesShort package description
authorsarrayNoAuthor records
licensestringNoSPDX license identifier
repositorystringNoSource repository URL
homepagestringNoPackage homepage
keywordsstring arrayNoDiscovery keywords
primary_categorystringNoPrimary package category
secondary_categorystringNoSecondary package category
min_flow_like_versionstringNoMinimum compatible Flow-Like version
wasm_pathstringNoWASM path relative to the manifest
wasm_hashstringNoSHA-256 integrity hash
metadatatableNoAdditional package metadata

Authors use TOML array-of-table syntax:

[[authors]]
name = "Jane Developer"
url = "https://example.com"

Categories use the enum’s uppercase names, for example "DOCUMENT_PROCESSING", "WORKFLOW_AUTOMATION", "INTEGRATION_CONNECTORS", "AI_ML", or "OTHER".

Package resource limits are applied to each node loaded from the package:

[permissions]
memory = "standard"
timeout = "extended"
TierLimit
minimal16 MB
light32 MB
standard64 MB
heavy128 MB
intensive256 MB
large512 MB
huge1 GB
extreme2 GB
maximum4 GB
TierLimit
quick5 seconds
standard30 seconds
extended60 seconds
long_running5 minutes
very_long10 minutes
maximum30 minutes

Choose the smallest tier that supports normal operation. A higher tier increases the maximum available resource; it does not reserve that resource in advance.

Each node exports its own permissions from code. For example, a Rust WASM node that performs an HTTP request and writes storage declares:

use flow_like_wasm_sdk::NodePermission;
node.add_permission(NodePermission::NetworkHttp);
node.add_permission(NodePermission::StorageWrite);

The available node permissions are:

PermissionCapability
NetworkHttpOutbound HTTP
NetworkWebsocketWebSocket access
NetworkTcpTCP sockets
NetworkUdpUDP sockets
NetworkDnsDNS lookups
StorageReadRead node/user storage
StorageWriteWrite and delete node/user storage
DatabaseReadRead from wired database and SQL session pins
DatabaseWriteModify rows through wired database pins
VariablesRead and write flow variables
CacheRead and write execution cache
StreamingStream events or text
ModelsUse model-provider host functions
A2uiUse A2UI host functions
OAuthAccess OAuth tokens
FunctionsCall functions or subflows

Language SDKs expose the same serialized permission labels, such as "network:http", "storage:write", and "streaming".

The sandbox grants each node exactly the capabilities that node declares. The manifest cannot add or remove them.

Besides the resource tiers, [permissions] holds two package-wide settings:

[permissions.network]
allowed_hosts = ["api.example.com"]
[[permissions.oauth_scopes]]
provider = "google"
scopes = ["https://www.googleapis.com/auth/calendar.events"]
reason = "Create calendar events"
required = true
FieldDescription
network.allowed_hostsOutbound host allowlist for every node in the package. An empty or missing list means unrestricted hosts
oauth_scopes[].providerOAuth provider ID
oauth_scopes[].scopesScopes requested from that provider
oauth_scopes[].reasonWhy the package needs them; shown in the store
oauth_scopes[].requiredMarks the entry as required in the store; defaults to false

WASM node definitions carry no OAuth providers or scopes today, so these authored entries are the only source for the store’s OAuth listing.

The typed manifest still has capability fields: network.http_enabled, websocket_enabled, tcp_enabled, udp_enabled, dns_enabled, filesystem.node_storage, user_storage, upload_dir, cache_dir, database.read, database.write, variables, cache, streaming, a2ui, and models. Do not author them. They hold the capability listing shown in the store, and the registry derives them from the compiled node definitions when a version is compiled and again when it is approved. Authored values are replaced.

The desktop app derives the same listing when a developer project is loaded and logs a warning for every authored flag that no node backs.

A package whose nodes declare StorageRead or StorageWrite lists all four storage flags, because the sandbox gates the node, user, upload, and cache directories on a single storage capability.

The runtime calls the binary’s get_nodes export and builds the catalog from the returned definitions. This keeps the visible catalog synchronized with the code that will actually run.

The current PackageManifest type has no nodes field. Older templates may contain [[nodes]] tables; TOML deserialization ignores those unknown tables. They do not register nodes, set permissions, or validate the binary. Remove them from new manifests to avoid maintaining a second, ineffective definition.

flow-like.toml
manifest_version = 1
id = "com.example.text-tools"
name = "Text Tools"
version = "1.2.0"
description = "Text transformation nodes"
license = "MIT"
repository = "https://github.com/example/text-tools"
homepage = "https://example.com/text-tools"
keywords = ["text", "transform"]
primary_category = "DOCUMENT_PROCESSING"
wasm_path = "build/node.wasm"
[[authors]]
name = "Jane Developer"
[permissions]
memory = "light"
timeout = "quick"
[metadata]
support = "https://example.com/support"

The parser requires fields with non-optional types, and publish/install validation additionally checks that id, name, and version are not empty. The package ID should remain stable across releases. Increment the version when behavior or pin interfaces change.

Use reverse-domain package IDs to reduce collisions:

id = "io.github.username.text-tools"

The package version is stored as a string. Semantic versioning is recommended, even though the manifest validator does not currently perform a strict semver parse.