Skip to main content

Module native

Module native 

Source
Expand description

Native (non-WASM) plugin support.

These plugins run as native Rust code for maximum performance. They implement the same interface as WASM plugins.

§Pass discrimination (issue #1166)

Plugins run in one of two passes — see the loader’s PluginPass enum:

  • Pre-booking synth pass: synthesizers like auto_accounts and document_discovery that inject directives the Early validator depends on (e.g. Open directives so account- presence checks see them).
  • Post-booking regular pass: transformations on already- booked directives — most plugins, including the cost-spec- reading ones (implicit_prices, unrealized, etc.) that need to see filled-in per-unit values from the booker.

Each native plugin declares which pass it runs in by implementing either SynthPlugin or RegularPlugin (both extend the base NativePlugin trait). The registry holds two separately-typed Vecs (Vec<Box<dyn SynthPlugin>> and Vec<Box<dyn RegularPlugin>>), and the loader’s runner consults the typed registry for the appropriate pass via NativePluginRegistry::find_synth / NativePluginRegistry::find_regular. The returned trait reference’s type matches the pass: find_synth can never return a RegularPlugin and vice versa, so the dispatch site can’t accidentally invoke a wrong-pass plugin even on a name collision.

§Where the discipline is enforced

The marker traits are intentionally not mutually exclusive at the type level — SynthPlugin and RegularPlugin are empty sub-traits of NativePlugin, and nothing in the type system prevents a single type from implementing both. Exclusivity is enforced by:

  1. Registry construction convention: each plugin is pushed into exactly one of the two Vecs in build_global_registry.
  2. A pinned test (test_registry_synth_and_regular_are_disjoint): iterates registry.iter() and asserts every plugin lives in exactly one Vec — CI catches a wrong-pass registration or a type that implements both markers and ends up in both Vecs.

The marker pair is therefore lighter than full type-level exclusivity (which would need negative trait bounds or a sealed pass-marker pattern that breaks object safety in our registry) — the cost is one assertion in CI instead of a compile error.

§Why a marker-trait pair rather than a single trait with a const

const PASS: PluginPass on the base trait would be cleaner if consts were object-safe — but they aren’t, and the registry uses trait objects (Box<dyn SynthPlugin> / Box<dyn RegularPlugin>) for heterogeneous storage. The marker-pair approach gives the dispatch-site type guarantee (described above) at the cost of one extra empty impl line per plugin.

§WASM and Python plugins

Non-native plugins don’t implement NativePlugin and therefore aren’t held in this registry. They’re dispatched by the loader through path-based name resolution, run only in the post-booking regular pass, and never carry a synth/regular marker at the type level. Synth-pass semantics are a native-only concern.

Modules§

utils
Shared utility functions for native plugins.

Structs§

AutoAccountsPlugin
Plugin that auto-generates Open directives for accounts used without explicit open.
AutoTagPlugin
Plugin that automatically adds tags based on account patterns.
BoxAccrualPlugin
Plugin for splitting capital losses across multiple years.
CapitalGainsGainLossPlugin
Plugin for classifying capital gains into gains/losses categories.
CapitalGainsLongShortPlugin
Plugin for classifying capital gains into long/short term categories.
CheckAverageCostPlugin
Plugin that validates reducing postings against the running average cost for accounts opened with the NONE booking method.
CheckClosingPlugin
Plugin that inserts zero balance assertion when posting has closing: TRUE metadata.
CheckCommodityPlugin
Plugin that checks all used commodities are declared.
CheckDrainedPlugin
Plugin that inserts zero balance assertions when balance sheet accounts are closed.
CloseTreePlugin
Plugin that closes all descendant accounts when a parent account closes.
CoherentCostPlugin
Plugin that ensures currencies are tracked consistently with cost or price-only.
CommodityAttrPlugin
Plugin that validates Commodity directives have required metadata attributes.
CurrencyAccountsPlugin
Plugin that auto-generates currency trading account postings.
DocumentDiscoveryPlugin
Plugin that auto-discovers document files from configured directories.
EffectiveDatePlugin
Plugin for handling effective dates on postings.
ForecastPlugin
Plugin for generating recurring forecast transactions.
GenerateBaseCcyPricesPlugin
Plugin for generating base currency prices.
ImplicitPricesPlugin
Plugin that generates price entries from transaction postings.
LeafOnlyPlugin
Plugin that errors when posting to non-leaf (parent) accounts.
NativePluginRegistry
Registry of built-in native plugins, split by pass.
NoDuplicatesPlugin
Plugin that detects duplicate transactions based on structural hash.
NoUnusedPlugin
Plugin that identifies accounts that are opened but never used.
OneCommodityPlugin
Plugin that enforces single commodity per account.
PedanticPlugin
Meta-plugin that enables all strict validation plugins.
RenameAccountsPlugin
Plugin for renaming accounts using regex patterns.
RxTxnPlugin
Plugin for Regular Expected Transactions.
SellGainsPlugin
Plugin that cross-checks declared gains against sale prices.
SplitExpensesPlugin
Plugin for splitting expenses between multiple people.
UniquePricesPlugin
Plugin that enforces unique prices (one per commodity pair per day).
UnrealizedPlugin
Plugin that calculates unrealized gains on positions.
ValuationPlugin
Plugin for tracking opaque fund values.
ZerosumPlugin
Plugin for matching zero-sum postings.

Constants§

AUTO_ACCOUNTS_NAME
Name used by the registry, the loader (when emitting the implicit synth-pass entry for options.auto_accounts), and external callers. Kept as a constant so the three sites stay in sync.
DOCUMENT_DISCOVERY_NAME
Name passed to file-declared / extra-plugin lookups and used by the loader when emitting the synth-pass config entry. Kept as a constant so the registry, the loader, and the rustdoc stay in sync.

Traits§

NativePlugin
Base capability for native plugins. Both SynthPlugin and RegularPlugin extend this — every native plugin has these three methods regardless of pass.
RegularPlugin
Marker trait: a plugin that runs in the post-booking regular pass.
SynthPlugin
Marker trait: a plugin that runs in the pre-booking synth pass.

Functions§

document_discovery_config
Build the PluginInput::config JSON string for this plugin.