# Alma Supply-Chain Notes
Alma does not vendor or patch transitive runtime dependencies unless there is a
specific release blocker, exploitable vulnerability, or abandoned upstream. For
framework-owned dependencies such as Bevy, wgpu, Metal bindings, and platform
FFI shims, prefer tracking the issue upstream and upgrading through the owning
stack.
## Wasm Plugin Threat Model
Wasm plugins change Alma's supply-chain model. They are third-party executable
components loaded into the editor process, so runtime selection, host imports,
component provenance, and revocation policy are part of the security boundary.
Runtime execution uses the Wasmtime component model behind Alma's
`plugin-runtime` feature. WIT/component bindings match Alma's stable host
interface. Guest-facing view and buffer authority is passed as borrowed WIT
resources during `update`; host-issued scalar handle secrets are no longer part
of the ABI. Wasmtime resource reps stay adapter-local and must not become a
public protocol. Exposed host imports are represented by typed metadata that
ties each WIT function name to one capability atom and one redacted operational
class. `status.publish`, `buffer.observe`, `buffer.propose_edit`, and
`workspace.artifact_write` have generated host import adapters; additional
imports remain future work.
Runtime fixture tests build small Wasm components from checked-in WIT with
`wasm-encoder`, `wit-parser`, and `wit-component` as direct dev-dependencies.
Those crates are already locked through the Wasmtime stack; the direct
dev-dependency exists so component fixtures remain source-reviewable.
The v1 loading policy is local and explicit. Plugins are loaded from configured
component paths, not discovered from arbitrary directories and not downloaded at
runtime. Remote plugin URLs, package registries, and signature enforcement are
future work; adding any of them should update this document before adding code.
Each plugin must have a stable identity, component path, WIT world version, and
static maximum capability grants in config. Disabling or revoking a plugin is a
config change: remove the plugin, set it disabled, or remove individual grants.
Unknown WIT worlds, unknown capabilities, missing manifests, and disabled
plugins fail closed.
Proposal review policy is also static config. It does not grant authority to
guest code; it decides whether admitted buffer edit proposals auto-apply through
the buffer owner or wait in the manual review lane.
Every new host import needs capability review. The review should answer what
user authority the import represents, which manifest/config capability gates it,
what data it may disclose, how failures are redacted, and which ECS owner
boundary eventually applies the effect. Host imports should be capability
shaped, not raw ECS access or generic host RPC.
WASI remains deny-by-default for plugins. Filesystem, environment, network,
clock, random, and stdio access should be added only through reviewed narrow
capabilities or captured diagnostics, not through ambient WASI authority.
Workspace imports require an additional filesystem-policy step after capability
authorization. A workspace capability grant can approve only a normalized
workspace-relative request; actual reads and writes must still use Alma's
filesystem helpers for canonicalization, no-follow handling, workspace-root
enforcement, platform identity checks, and atomic writes. Whole-workspace grants
must be explicit in code and config review because they are broad user
authority.
The host-session path for direct workspace observations already requires an
explicit filesystem policy context and returns only bounded bytes or a closed
rejection while spending the per-update workspace request budget. The WIT import
is task-based only. The WIT start/poll/take names are exposed and drift-tested
as a complete group so a partial public read protocol cannot appear by
accident. The metadata also owns the redacted operational import classes, so
diagnostics cannot be added as a parallel table after the ABI names move.
Deferred I/O, direct observations, and task-style observation reservations
spend one shared per-update request ledger. The observation task queue models a
host-owned result resource with pending bounds, retained-result bounds,
identity-scoped polling, revocation cleanup, and pending-capacity plus
non-reused task-id reservation before guest-visible return. Its adapter-facing
task id and result-state vocabulary is separate from queue mutation, and its
poll/take states are closed as pending, completed, and unknown, with consumed,
evicted, stale, and cross-plugin ids all collapsing to unknown.
Host-import sessions now keep task read proofs behind the successful-return
boundary before they can enter that queue; failed updates release reserved
capacity and may burn task ids, but they cannot publish filesystem work.
Persistent Wasmtime task resources retain the workspace path that authorized
them and revalidate that path against the current update snapshot before
poll/take can reach the resource table or task queue; denied revalidation
tombstones the resource without freeing the table rep and returns the typed
authorization rejection.
Wasmtime cleanup for queued task state and persistent task resources requires a
matching `PluginRevocationReport`, keeping revocation identity proof at the
runtime boundary. Enqueue and execution also require the matching active
`PluginInstanceState`, so retained sealed batches cannot publish reads after
revocation. Public
workspace reads must still avoid synchronous Rust filesystem reads inside a
Wasmtime host import unless the host can enforce a deadline or cancellation
without waiting for the blocking read to return. Owner-facing display paths and
filesystem error detail must not cross the guest boundary.
Alma requires execution limits in plugin config before guest code can run. Fuel,
epoch interruption, wall-clock timeouts, memory limits, and bounded message sizes
are runtime controls, not optional hardening. The typed defaults are bounded, but
operators can tighten them per plugin and invalid zero or oversized limits fail
closed during config validation. Tests should prove a plugin can be denied or
interrupted without mutating authoritative editor state.
## Current Tracked Risks
- `block 0.1.6` currently appears in Cargo future-incompatibility reports
through the Bevy/wgpu/Metal dependency path. This is an upstream framework
dependency, not an Alma-owned API surface.
- Check with `cargo report future-incompatibilities --id 1` after builds that
emit the warning.
- Prefer a Bevy/wgpu upgrade when the owning stack removes the warning.
- Only add a local `[patch.crates-io]` if the warning becomes a hard compiler
error before the Bevy stack has a compatible fix.