Skip to main content

Module host

Module host 

Source
Expand description

§The host API (VAPP-91)

What a surface needs from its host, the same on all four platforms (packages/exponential-ui/catalog/host.json): the router turning server messages into ops, the wire decoders (JSONL, SSE, A2UI-over-MCP), the function / URL / media policy, binding sources, catalog negotiation and declarative app packages. A line-by-line port of the TypeScript reference (packages/exponential-ui/src/host/) over serde_json::Value; every output is JSON-equal to it, locked by fixtures/host-*.json. The I/O (transports, the runtime host) stays on each platform; the Swift and Kotlin painters reach this module through exponential-ui-ffi.

Re-exports§

pub use actions::action_call_name;
pub use actions::action_var_types;
pub use actions::apply_record_batch;
pub use actions::apply_record_batch_as;
pub use actions::function_effect;
pub use actions::is_action_name;
pub use actions::run_action;
pub use actions::validate_package_actions;
pub use actions::validate_package_effects;
pub use actions::ActionContext;
pub use actions::ACTION_CALL_PREFIX;
pub use actions::ACTION_LIMIT_ACTIONS;
pub use actions::ACTION_LIMIT_MAX_STEPS;
pub use actions::ACTION_LIMIT_STEPS;
pub use actions::ACTION_NAME_PATTERN;
pub use actions::ACTION_STEP_KINDS;
pub use actions::RECORDS_BATCH_FUNCTION;
pub use expressions::literal_type;
pub use expressions::record_row_type;
pub use expressions::records_value_type;
pub use expressions::schema_type;
pub use expressions::validate_package_expressions;
pub use exposes::expose_action_access;
pub use exposes::expose_issues;
pub use exposes::expose_name_destructive;
pub use exposes::expose_template_paths;
pub use exposes::validate_package_exposes;
pub use exposes::validate_upstreams;
pub use exposes::ExposeIssue;
pub use decoders::decode_jsonl;
pub use decoders::mcp_action_call;
pub use decoders::messages_from_mcp_result;
pub use decoders::DecodeIssue;
pub use decoders::Decoded;
pub use decoders::JsonlDecoder;
pub use decoders::SseDecoder;
pub use package::available_extensions;
pub use package::client_capabilities;
pub use package::merge_data;
pub use package::package_sources;
pub use package::source_allowed;
pub use package::supported_catalog_ids;
pub use package::template_messages;
pub use package::validate_package;
pub use package::validate_package_with;
pub use package::version_satisfies;
pub use package::AvailableExtension;
pub use package::PackageIssue;
pub use package::PACKAGE_FORMAT_VERSION;
pub use policy::combine_decisions;
pub use policy::decide_function;
pub use policy::decide_url;
pub use policy::image_dimensions;
pub use policy::image_frames;
pub use policy::image_header;
pub use policy::is_builtin_function;
pub use policy::is_private_host;
pub use policy::media_image_check;
pub use policy::ImageHeader;
pub use policy::matches_pattern;
pub use policy::media_image_within_limits;
pub use policy::media_request;
pub use policy::media_within_limits;
pub use policy::package_policy;
pub use policy::svg_dimensions;
pub use policy::safe_href;
pub use policy::FunctionDecision;
pub use policy::FunctionPolicy;
pub use policy::MediaOptions;
pub use policy::MediaRequest;
pub use policy::MediaRule;
pub use policy::UrlDecision;
pub use policy::UrlPolicy;
pub use policy::BUILTIN_FUNCTIONS;
pub use router::normalize_path;
pub use router::HostRouter;
pub use router::SurfaceInfo;
pub use query::expand_query_source;
pub use query::fill_query_templates;
pub use query::month_days;
pub use query::month_label;
pub use query::parse_records_json;
pub use query::parse_records_query;
pub use query::parse_records_source;
pub use query::records_value;
pub use query::records_value_owned;
pub use query::shift_month;
pub use query::RecordRow;
pub use query::RecordRowRef;
pub use query::RecordsAggregate;
pub use query::RecordsAggregateOp;
pub use query::RecordsBefore;
pub use query::RecordsContext;
pub use query::RecordsDay;
pub use query::RecordsFilter;
pub use query::RecordsFilterOp;
pub use query::RecordsFilterValue;
pub use query::RecordsGroupKey;
pub use query::RecordsMonthView;
pub use query::RecordsOrder;
pub use query::RecordsQueryIssue;
pub use query::RecordsRunning;
pub use query::RecordsRunningOp;
pub use query::RecordsQuery;
pub use query::RecordsSortKey;
pub use query::RECORDS_AGGREGATE_OPS;
pub use query::RECORDS_AGGREGATE_RESERVED;
pub use query::RECORDS_FILTER_OPS;
pub use query::RECORDS_MONTHS;
pub use query::RECORDS_OP_ALIASES;
pub use query::RECORDS_RUNNING_OPS;
pub use query::RECORDS_RESERVED_PARAMS;
pub use query::RECORDS_ROW_KEYS;
pub use query::RECORDS_SCHEME;
pub use query::RECORDS_WEEKDAYS;
pub use record_policy::readable_rows;
pub use record_policy::record_allowed;
pub use record_policy::record_author_of;
pub use record_policy::record_policy;
pub use record_policy::record_policy_copy;
pub use record_policy::record_refusal;
pub use record_policy::validate_record_policy;
pub use record_policy::RecordOp;
pub use record_policy::RecordPolicy;
pub use record_policy::RecordViewer;
pub use record_policy::APP_ACCESS_LEVELS;
pub use record_policy::DEFAULT_RECORD_POLICY;
pub use record_policy::RECORD_POLICY_LEVELS;
pub use record_policy::RECORD_POLICY_OPS;
pub use record_store::RECORDS_FUNCTIONS;
pub use records::is_record_kind;
pub use records::validate_record;
pub use records::validate_record_schema;
pub use records::RECORD_FIELD_TYPES;
pub use records::RECORD_FORMATS;
pub use records::RECORD_RESERVED_KEYS;
pub use signature::canonical_json;
pub use signature::package_file_signed_bytes;
pub use signature::AUTHOR_KEY_PREFIX;
pub use signature::AUTHOR_NAME_MAX;
pub use signature::PACKAGE_FILE_SIGNATURE_ALG;
pub use signature::PACKAGE_FILE_SIGNATURE_CONTEXT;
pub use sources::parse_source;
pub use sources::source_with_params;
pub use sources::ParsedSource;
pub use tests::package_test_issues;
pub use tests::run_package_tests;
pub use tests::test_failure;
pub use tests::test_matches;
pub use tests::validate_package_tests;
pub use tests::PackageTestResult;
pub use tests::PACKAGE_TEST_DEFAULT_AS;
pub use tests::PACKAGE_TEST_DEFAULT_NOW;
pub use tests::PACKAGE_TEST_DEFAULT_ROLE;
pub use tests::PACKAGE_TEST_ROLES;
pub use tests::PACKAGE_TEST_KINDS;
pub use tests::PACKAGE_TEST_LIMIT_GOT_MAX;
pub use tests::PACKAGE_TEST_LIMIT_TESTS;
pub use tools::tool_call;
pub use tools::validate_tools;
pub use tools::ToolCall;
pub use tools::ToolConsentRow;
pub use tools::TOOL_KINDS;
pub use contract::*;

Modules§

actions
VAPP-194 (eApps E1, spec docs/spec/apps.md §4.5): typed effects, the twin of packages/exponential-ui/src/host/actions.ts (read its header).
contract
The host API contract (catalog/host.json) as constants, plus the client messages every platform host sends (tests/host_fixtures.rs gates the constants against the JSON).
decoders
The wire decoders every transport adapter shares (pure, incremental, fixture-locked in fixtures/host-transport.json): A2UI JSONL over a byte stream, Server-Sent Events, and the A2UI-over-MCP carrier.
exposes
VAPP-180: the MCP tools a package EXPOSES (docs/package-format.md “Exposes”): declarative bindings {name, title, description, input, access, run} a host’s MCP broker lists and runs as the calling person, never code. The format half of the eMCP contract; what a run may reach on a given host is that host’s own check. Mirrors packages/exponential-ui/src/host/exposes.ts line by line; fixtures/host-router.json (validation) replays it.
expressions
VAPP-191 (eApps Q2): expressions are type-checked at package validation, the twin of src/host/expressions.ts. Every {"call": "expr", "args": {"expr": "<CEL>", "vars": {…}}} anywhere in a template is parsed and checked (crate::cel::check_expression) against the types of its vars: a literal’s own type, a records binding’s value (the kind’s schema fields) or the template data’s; anything else is open (dyn). An issue names the JSON pointer of the expression and the reason (fixtures/expressions.json packages).
package
Catalog negotiation and declarative app packages (VAPP-82: a manifest + A2UI templates + bindings, data never code).
policy
The policy rules every host applies before a client function, a URL open or a media load (catalog/host.json functions / urls / media). Pure; fixtures/host-policy.json locks them on every platform.
query
VAPP-189 (S1): THE records query, the Rust twin of packages/exponential-ui/src/host/query.ts, locked by fixtures/records-query.json (parseCases, sourceCases, jsonCases, valueCases, expandCases; bucketCases lock crate::dates). A binding’s URL sugar (records:<kind>?q) parses INTO the structured RecordsQuery; records_value evaluates it over the rows of any store. The desktop host calls it directly; the Swift and Compose SDKs reach it through exponential-ui-ffi (parse_records_query_json, parse_records_json, parse_records_source_json, records_value_json).
record_policy
eApps R3 (docs/spec/apps.md §3.4, §9): who may read, create, update and delete a kind’s records, under the member’s app access. A line-by-line port of src/host/record-policy.ts; fixtures/record-policy.json is the spec (tests/record_policy.rs replays it).
record_store
VAPP-161: the format’s NEUTRAL records (docs/package-format.md “Records”). A surface reads a kind through the binding records:<kind>?query and writes through the host functions records.upsert / records.delete; the HOST provides the store. The query and its value are super::query (VAPP-189: one evaluator over the rows of any store, fixtures/records-query.json).
records
VAPP-122: an app’s RECORDS, its own data. The manifest declares every kind with a JSON Schema SUBSET (records: {<kind>: {schema}}); a host validates a record against it before it is stored. Mirrors packages/exponential-ui/src/host/records.ts line by line; fixtures/host-router.json records replays it.
router
The host router. Server messages in, ops out (catalog/host.json ops); the platform host performs them on its surfaces. Pure and synchronous, so fixtures/host-router.json locks the same behaviour on every platform.
signature
VAPP-161: the PACKAGE FILE’s signed bytes (docs/package-format.md “The package file”): a context line + the RFC 8785 canonical JSON of the whole file without signature. Mirrors canonicalJson + packageFileSignedBytes of packages/exponential-ui/src/host/signature.ts; the Ed25519 itself is the host’s own (no crypto here). fixtures/host-package.json canonical + signatures[].signedText replay it.
sources
Binding sources. A data model path can follow a host source (exp:issues?board=…): the host registers one resolver per scheme, the router emits a bind op, the resolver’s emits land at the path.
tests
VAPP-196 (eApps T1): PACKAGE TESTS, the twin of packages/exponential-ui/src/host/tests.ts. A package carries tests: [{name, records?, now?, as?, expr | query | action, expect}]; validate_package runs every one on an otherwise valid package, each against its OWN in-memory store seeded with records, on a fixed clock (now, UTC) as the member as. A failing test is an install issue at /tests/<i> (expected vs got). Locked by fixtures/package-tests.json.
tools
VAPP-161: a package’s TOOLS (docs/package-format.md “Tools”): the MCP servers and scripts its functions call (tools.<id>.<name> for an MCP tool, tools.<id> for a script), each behind the consent card the host MUST show before the first call. Mirrors packages/exponential-ui/src/host/tools.ts line by line; fixtures/host-router.json (validation) and fixtures/host-package.json consent + toolCalls replay it.