Extensions

Extension discovery and snapshot contracts for optional plugins.

See the usage guide for task-oriented examples. Signatures below are generated from the public headers at the same commit as the rest of this site.

class extension_hook

A registered hook for one event.

The event is trimmed when stored; the fingerprint is stored verbatim and must be non-blank. The callback must be callable. Hooks with the same event and priority are ordered by fingerprint inside extension_snapshot.

Public Functions

extension_hook(std::string event, std::string fingerprint, extension_hook_callback callback, int priority = default_hook_priority, std::map<std::string, std::string> provenance = {})

Creates a hook.

Parameters:
  • event – Event name; surrounding ASCII whitespace is trimmed.

  • fingerprint – Stable hook fingerprint; must not be blank.

  • callback – Callback invoked by execute_hooks(); must be callable.

  • priority – Lower values run first; defaults to default_hook_priority.

  • provenance – Free-form provenance metadata.

Throws:

fincore_error – With category ValidationError when event or fingerprint is blank, or callback is empty.

inline const std::string &event() const noexcept

Returns the normalized event name.

inline const std::string &fingerprint() const noexcept

Returns the fingerprint as supplied.

inline int priority() const noexcept

Returns the hook priority.

inline const std::map<std::string, std::string> &provenance() const noexcept

Returns the provenance metadata.

inline const extension_hook_callback &callback() const noexcept

Returns the callback.

class extension_snapshot

Immutable native snapshot of extension operations, hooks and renderers.

Ordering matches the pinned Python snapshot: operations by operation_id, hooks grouped by event then by (priority, fingerprint), renderers by name. Hooks are intentionally not duplicate-rejected (the source allows repeated registrations); operations and renderers are.

Public Functions

explicit extension_snapshot(std::vector<extension_operation> operations = {}, std::vector<extension_hook> hooks = {}, std::vector<renderer_registration> renderers = {})

Creates a snapshot, validates entries, orders them and computes the digest.

Operation and capability ids must start with extension. and contain at least two dots. Operations must have domain extensions and non-blank implementation fingerprints and RNG policies; operation ids must be unique, and semantic_mode and mode_approval must be supplied together. Hooks may repeat. Renderer names must be unique. Hooks are ordered by event, then priority and fingerprint; operations by operation_id; renderers by name. The digest is the SHA-256 of to_json().

Parameters:
  • operations – Operation descriptors.

  • hooks – Registered hooks.

  • renderers – Registered renderers.

Throws:

fincore_error – With category ValidationError for an invalid operation, a duplicate operation id or a duplicate renderer name.

inline const std::vector<extension_operation> &operations() const noexcept

Returns the operations ordered by operation_id.

inline const std::vector<extension_hook> &hooks() const noexcept

Returns the hooks ordered by event, then priority and fingerprint.

inline const std::vector<renderer_registration> &renderers() const noexcept

Returns the renderers ordered by name.

inline const std::string &digest() const noexcept

Returns the lowercase hexadecimal SHA-256 digest of to_json().

std::string to_json() const

Returns compact, key-sorted, ASCII-escaped JSON used to compute digest.

Returns:

Canonical snapshot JSON.

extension_snapshot with_operation(extension_operation operation) const

Returns a new snapshot with one more operation.

The receiver is unchanged. The operation is validated as in the constructor, so a duplicate operation id is rejected.

Parameters:

operation – Operation to add.

Throws:

fincore_error – With category ValidationError when the operation is invalid or its id is already registered.

Returns:

New snapshot containing all existing entries plus operation.

extension_snapshot with_hook(extension_hook hook) const

Returns a new snapshot with one more hook.

The receiver is unchanged. Repeated hook registrations are allowed.

Parameters:

hook – Hook to add.

Returns:

New snapshot containing all existing entries plus hook.

extension_snapshot with_renderer(renderer_registration renderer) const

Returns a new snapshot with one more renderer.

The receiver is unchanged. A duplicate renderer name is rejected.

Parameters:

renderer – Renderer to add.

Throws:

fincore_error – With category ValidationError when the name is already registered.

Returns:

New snapshot containing all existing entries plus renderer.

std::span<const extension_hook> hooks_for(std::string_view event) const

Returns the hooks registered for event.

event is normalized before lookup. The returned hooks are in execution order: ascending priority, then ascending fingerprint.

Parameters:

event – Event name.

Returns:

View of matching hooks; empty when none are registered.

extension_value execute_hooks(std::string_view event, std::optional<extension_value> first = std::nullopt, const extension_keywords &keywords = {}) const

Runs the priority-ordered hooks for event.

When first is present the hooks transform it left-to-right and the final value is returned; when it is absent the hooks are notifications and a monostate value is returned.

Exceptions thrown by a callback propagate to the caller.

Parameters:
  • event – Event name; normalized before lookup.

  • first – Value transformed by the hooks, or nullopt for a notification.

  • keywords – Named scalar arguments passed to every callback.

Returns:

Final transformed value, or monostate for a notification.

std::optional<extension_renderer_callback> renderer(std::string_view name) const

Looks up a renderer by name.

name is normalized before lookup; a blank or unknown name yields nullopt.

Parameters:

name – Renderer name.

Returns:

Copy of the renderer callback, or nullopt when not registered.

class renderer_registration

A registered renderer callback.

The name is trimmed when stored; the fingerprint is stored verbatim and must be non-blank. Renderer names are unique within a snapshot.

Public Functions

renderer_registration(std::string name, std::string fingerprint, extension_renderer_callback renderer, std::map<std::string, std::string> provenance = {})

Creates a renderer registration.

Parameters:
  • name – Renderer name; surrounding ASCII whitespace is trimmed.

  • fingerprint – Stable renderer fingerprint; must not be blank.

  • renderer – Callback invoked by the host; must be callable.

  • provenance – Free-form provenance metadata.

Throws:

fincore_error – With category ValidationError when name or fingerprint is blank, or renderer is empty.

inline const std::string &name() const noexcept

Returns the normalized renderer name.

inline const std::string &fingerprint() const noexcept

Returns the fingerprint as supplied.

inline const extension_renderer_callback &renderer() const noexcept

Returns the renderer callback.

inline const std::map<std::string, std::string> &provenance() const noexcept

Returns the provenance metadata.

struct discovered_extension

One unexecuted native extension manifest.

Field names mirror DiscoveredExtension; value uses the native component:symbol convention instead of a Python import path.

Public Functions

std::string fingerprint() const

Returns the stable SHA-256 of to_json().

std::string to_json() const

Returns compact, key-sorted, ASCII-escaped JSON for the manifest fields.

Public Members

std::string name

Extension name.

std::string group = "fincore.extensions"

Entry-point group label.

std::string distribution

Supplying distribution.

std::string value

component:symbol target.

struct extension_hook_invocation

Payload passed to a hook callback.

Public Members

extension_value value

Current value; monostate for notifications.

extension_keywords keywords

Named scalar arguments.

struct extension_operation

Native extension operation descriptor.

It mirrors the metadata subset of fincore.runtime.specs.OperationSpec that contributes to ExtensionSnapshot.digest; the callable and schemas stay in the runtime catalog rather than in this overlay descriptor.

Public Functions

std::string to_json() const

Returns compact, key-sorted, ASCII-escaped JSON for the fields that participate in the snapshot digest.

Stable across processes and platforms.

Public Members

std::string operation_id

extension.

-prefixed id with at least two dots.

std::string capability_id

Capability id in the same namespace.

std::string domain = "extensions"

Domain; must be extensions.

std::string implementation_fingerprint

Non-blank implementation fingerprint.

std::optional<std::string> optional_extra

Optional non-blank extra tag.

bool deterministic = true

Whether the operation is deterministic.

std::string rng_policy = "none"

Non-blank RNG policy label.

std::optional<std::string> semantic_mode

Optional semantic mode.

std::optional<std::string> mode_approval

Optional mode approval.

std::map<std::string, std::string> provenance

Metadata; excluded from the digest JSON.

struct loaded_extension

Result of validating one discovered manifest.

The native ABI does not import code or call dlopen; this record is the load validation boundary.

Public Members

discovered_extension manifest

Normalized, validated manifest.

std::string fingerprint

SHA-256 of the normalized manifest.

std::vector<discovered_extension> fincore::extensions::discover_extensions(std::span<const discovered_extension> manifests, std::span<const std::string_view> groups = entry_point_groups())

Discovers and deterministically orders manifests for the requested groups.

Each manifest is normalized by trimming its four text fields. A blank required field is rejected even when the manifest’s group is not requested. Manifests whose normalized group is not in groups are ignored. Results are stably sorted by (group, name, distribution, value), so duplicates are preserved in input order.

Parameters:
  • manifests – Candidate manifests.

  • groups – Requested entry-point groups; defaults to entry_point_groups().

Throws:

fincore_error – With category ValidationError when any candidate has a blank name, group, distribution or value.

Returns:

Normalized manifests in deterministic order.

std::vector<discovered_extension> fincore::extensions::discover_extensions(const std::vector<discovered_extension> &manifests, std::span<const std::string_view> groups = entry_point_groups())

Discovers and orders manifests from a vector.

Parameters:
  • manifests – Candidate manifests.

  • groups – Requested entry-point groups; defaults to entry_point_groups().

Throws:

fincore_error – With category ValidationError when any candidate has a blank name, group, distribution or value.

Returns:

Normalized manifests in deterministic order.

std::span<const std::string_view> fincore::extensions::entry_point_groups() noexcept

Returns the source entry-point group names used by default.

Returns:

View of ENTRY_POINT_GROUPS; valid for the process lifetime.

loaded_extension fincore::extensions::load_extension(const discovered_extension &extension)

Validates and normalizes one manifest for explicit loading.

The value must use the component:symbol form with exactly one colon, non-empty parts and no ASCII whitespace. The returned manifest is trimmed and fingerprinted. No dynamic library is opened and no code is loaded.

Parameters:

extension – Manifest to validate.

Throws:

fincore_error – With category ValidationError when a text field is blank or the value has the wrong shape.

Returns:

Normalized manifest and its SHA-256 fingerprint.

std::string fincore::extensions::normalize_extension_name(std::string_view value)

Trims ASCII whitespace around a registration name.

Case is preserved, as in the pinned source where names are case-sensitive. Returns an empty string when the input only contains whitespace.

Parameters:

value – Text to trim.

Returns:

Trimmed text, or an empty string when only whitespace was supplied.

std::vector<extension_operation> fincore::extensions::operations()

Returns the builtin extension-domain operations.

The pinned source returns an empty tuple: third parties register namespaced operations through snapshots.

Returns:

An empty vector.

using fincore::extensions::extension_hook_callback = std::function<std::optional<extension_value>(const extension_hook_invocation&)>

A hook either returns a replacement for the first argument or nullopt to leave it unchanged.

Returning a value for a notification invocation is ignored, matching the source execute_hooks contract.

using fincore::extensions::extension_keywords = std::map<std::string, extension_value>

Named scalar arguments passed to every hook callback.

using fincore::extensions::extension_manifest = discovered_extension

Native name for an input manifest supplied by a host application.

using fincore::extensions::extension_renderer_callback = std::function<std::string(std::string_view request)>

Renderers are native callbacks that map a request key to a stable payload.

The payload format is owned by the plugin; the snapshot only owns registration, ordering and fingerprinting.

using fincore::extensions::extension_value = std::variant<std::monostate, bool, std::int64_t, double, std::string>

One native hook argument.

Python hooks accept arbitrary positional and keyword arguments; the native ABI narrows this to one transformed value plus named scalar keywords.

constexpr std::array<std::string_view, 1> fincore::extensions::ENTRY_POINT_GROUPS{"fincore.extensions"}

Source group names from the pinned fincore.extensions.discovery module.

The native ABI replaces importlib.metadata entry points with explicitly supplied manifests while keeping the same group label.

constexpr int fincore::extensions::default_hook_priority = 100

Native equivalent of the pinned Python ExtensionHook value.

The Python object derives a module:qualname fingerprint from the callback; the native ABI requires that fingerprint explicitly because C++ callables have no portable qualified name.

Hooks use priority 100 unless another value is supplied; lower priorities run first.