Skip to main content

neutron-compiler

The package that turns a set of manifests and Motoko modules into a running canister. It is shared by three callers — the browser installer, the CLI, and the provisioner — so all three produce actors from the same template.

Responsibilities

AreaWhat it does
Package decodingBounded MessagePack/gzip decoding of .neutron archives
Install planningPath rewriting, hash verification, and the migration plan
AssemblyGenerating the complete Motoko actor source from all manifests
CompilationDriving the vendored Motoko compiler and the AST policy scan
DeploymentUpload sequencing, staging, journalling, activation, verification, commit, recovery, uninstall, and module garbage collection

assemble()

Generates one persistent Motoko actor class from all supplied app configs. It emits imports, persistent memory wrappers, transient module initializers, capability projections, and one wrapper per manifest function.

Before emitting anything it validates each generated-syntax context. Motoko identifiers and enum-like values go through no_inject; import paths use the separate no_module_path grammar; compiler-owned blobs are byte-checked; and manifest text such as descriptions, URLs, and purposes is emitted through an escaped Motoko string-literal encoder. These checks are explicit at the fields that enter generated source, after closed manifest and capability validation.

Details: Actor assembly.

compile()

Loads the vendored neutron-motoko-wasm compiler, validates every manifest, walks each active entry/schema/migration root, and requires every recursive import to exist in the current input. It scans that reachable graph with the shared Motoko policy, writes only reachable modules into a fresh compiler runtime, assembles the actor, compiles it, and stamps the supported HTTP-certification custom section.

It returns considerably more than a Wasm blob:

wasm · candid · stable signature · diagnostics
migration plan · canonical capability plans · deployment id
danger report · reachable module paths

Two safety properties are built into the compile step itself:

The input list is an allowlist. compile() uses isolated compiler lifecycles and requires every root and recursive import to be present in the current input map. Modules retained by a previous failed or rejected compile cannot satisfy a later build.

Danger findings are hard failures for ordinary apps. Non-whitelisted findings in an app entry, a memory schema root, or a selected migration root fail the compile. Kernel modules keep the explicit exception.

install.ts — the shared package helpers

Everything package-specific that the browser and the provisioner both need:

  • .neutron MessagePack/gzip unpacking with bounded limits
  • package path safety checks and Motoko content-hash verification
  • install-path rewriting (web/app/<id>/, mo//mo/, everything else → pkg/)
  • app registry and Candid asset construction
  • MIME selection, gzip/identity encoding choice, and default 1 MiB chunking
  • generic upload sequencing
  • staged activation, verification, commit, recovery, and abort
  • uninstall and module garbage collection
  • installed-package state collection through IO callbacks

The Kernel's install, MIME, and concurrency compatibility adapters re-export the corresponding helpers from this module.

Decode limits differ by source

SourceLimits
Manual local fileLarger finite compatibility ceilings
Direct URL installThe smaller remote limits
Repository importRemote limits plus aggregate limits across the whole manifest

The decoder preflights the MessagePack map before materialising values, bounds raw bytes, entry count, path length, compressed values, single decoded entries and total decoded bytes, and rejects duplicate or dangerous map keys, unsafe paths, trailing data, multiple gzip members, and invalid gzip sizes or checksums.

caution

A direct URL install is an owner-initiated transport convenience. It is not a certified or digest-pinned source and it does not become package provenance.

Observer callbacks are observers

Deployment exposes onStep and onProgress callbacks for UI. The shared helper catches and logs failures from them, so a broken logging or UI callback cannot alter activation, verification, commit, or abort behaviour.