Contents

Extensions

How a reader, a chunker, an embedding provider or a way of signing in is added from a folder without a change to this repository, allowed by hash, loaded from the bytes that were checked, and refused with a reason.

A reader, a chunker, an embedding provider or a way of signing in can be added without a change to this repository. An extension is a folder holding one assembly and an extension.json beside it:

json01
{
  "name": "sentence-chunker",
  "version": "1.0.0",
  "assemblyFile": "SentenceChunker.dll",
  "sha256": "0a1b...",
  "seams": { "chunker": 1, "reader": 1, "signin": 1 }
}

The folder goes under the extensions folder, which is the setting extensions.folder or the environment variable PREM_EXTENSIONS_DIR, the setting winning. Neither one means no extensions, which is not an error.

Nothing loads until an administrator allows it:

bash02
prem extensions allow /opt/premagentic/extensions/sentence-chunker
prem extensions list
prem extensions disallow sentence-chunker

allow reads the manifest, computes the assembly's SHA-256 itself, and writes the name and that hash to the setting extensions.allowed, with an entry in the change record. It refuses when the manifest's hash and the assembly disagree, rather than writing a pair that could never match.

At startup the host reads the assembly once, hashes those bytes, and loads the assembly from the same bytes, so the file cannot be exchanged between the check and the load. The pair of name and hash must be in extensions.allowed. An extension is refused, with a reason, when its manifest cannot be read or used, when it names an assembly outside its own folder, when the hash does not match, when nobody allowed the pair, when it was built for a seam version this release does not offer, when it will not run, or when what it registers is named the same as something already loaded. A refusal never stops the deployment: it starts with the built-in readers, chunkers, embedding providers and ways of signing in, and prem extensions list and the health page say what was refused and why.

Each extension loads into its own context and takes the contracts it implements from the process, so two extensions can carry different versions of one library and neither can bring its own copy of the core. An extension may add an embedding provider under a new name and may not take a built-in one, so naming a provider can never quietly stand in for the local, offline model. An extension that brings a way of signing in is named in the log at every start, the way the trusted-header mode is.

An upgrade is a new assembly with a new hash, so it is allowed again on purpose. Changing either setting applies when the service is next started, which is also the only safe moment to replace an assembly on disk.

samples/extensions/sentence-chunker is a whole extension that registers a chunker, a reader for .csv files and a sign-in adapter that claims nothing; it is loaded in this repository's tests to prove the refusals and that each seam is used end to end. tests/Premagentic.Conformance holds xunit fixtures to inherit that prove a reader, a chunker, a connector or an embedding provider keeps its contract; the built-ins are held to them here.