Concepts

Manifest loading

Load policy sources through an integrity-checked, fail-closed deployment manifest.

A manifest is a JSON document describing a policy bundle: which sources to load, how to verify them, and what callers may inspect after solving. It is useful when deploying separately maintained policy files. Inline loading is also supported: it loads one in-memory source without a manifest.

A manifest binds policy source files to:

  • stable policy identifiers
  • registered domains
  • SHA-256 integrity fingerprints
  • loading modes
  • Public Query Whitelist
  • policy-set metadata

The policy source contains the logic. The manifest is the governance layer around that logic.

For programming details, see C Stable manifest loading and Advanced in-memory manifests. Python exposes file-manifest loading; the typed WASM wrapper exposes inline loading, not manifests.

Why manifests exist

A manifest gives Maelys DL a controlled loading boundary.

ResponsibilityMeaning
Policy discoveryIdentify which policy sources belong to a policy set.
Integrity verificationVerify SHA-256 fingerprints before parsing policy source.
Domain bindingSelect the registered predicate vocabulary used to validate each policy.
Loading modeDecide whether a policy is active, shadow, test-only, or disabled.
Public Query WhitelistControl which domain-declared QUERY predicates are publicly observable for this deployment.
MetadataAttach stable policy-set and policy identifiers to loaded rulesets.

These responsibilities stay separate:

ElementResponsibility
DomainDeclares the allowed predicates, their arities and their roles.
Policy sourceDefines the facts and rules used to reach a decision.
ManifestSelects policies and domains, verifies source integrity, and limits public queries.

Where the manifest fits

The manifest selects and constrains loading before the policy is parsed. The loaded result — the policy set — then connects to runtime evaluation.

ARCHITECTURELoad a bundle, then evaluate requests
    • Manifestidentity, domain, queries
    • Verify and loadcheck SHA + source vocabulary
    • Policy setvalidated policy entries
    • Sessionselect one policy
    • Request EDBcomplete runtime facts
    • Solveproduce a result

Example manifest

A typical manifest looks like this. The abbreviated SHA below is a placeholder: an actual manifest requires the exact 64-character lowercase SHA-256 of the source bytes.

CODE
{
  "policy_set_id": "document_access.v1",
  "policy_set_version": "1.0.0",
  "manifest_version": "1",
  "default_profile": "enforce",
  "created_for": "production",
  "strict_loading": true,
  "fail_closed": true,
  "capabilities": [],
  "policies": [
    {
      "policy_id": "document_access.main",
      "domain": "document_access",
      "file": "policies/document_access.dl",
      "sha256": "a3f7c291...",
      "mode": "enforce",
      "enabled": true,
      "description": "Document access policy",
      "queries": [
        { "name": "allow", "arity": 2 }
      ]
    }
  ]
}

This manifest says:

  • Load the policy called document_access.main.
  • Validate it with the document_access domain.
  • Read the source from policies/document_access.dl.
  • Verify the source SHA-256 before parsing.
  • Load it in enforce mode.
  • Expose only allow/2 as the publicly queryable surface.

The source can also use sensitivity_level/2 as an EDB guard. That predicate is installed by the selected domain, not by the manifest.

Manifest fields

The manifest root object is strict: unknown fields are rejected, and each required field must have the expected type.

FieldTypeRequiredMeaning
policy_set_idstringyesStable identifier for the whole set of policies.
policy_set_versionstringyesHuman-readable version of this policy set.
manifest_versionstringyesVersion of the manifest schema.
default_profilestringyesDefault loading profile. Use enforce for file-based loading and MAELYS-DATALOG-v2 for buffer-based loading.
created_forstringyesIntended environment, for example production or test.
strict_loadingbooleanyesRequired metadata. The current loaders always reject unknown fields; setting this to false does not enable permissive parsing.
fail_closedbooleanyesRequired metadata expressing intent. Setting it to false does not turn an engine error into a successful result or authorize a request.
capabilitiesarrayyesReserved manifest-level field. Must currently be an array; values are not interpreted yet.
policiesarrayyesList of policy entries to load.

Capabilities

The capabilities field is currently reserved for future manifest-level feature negotiation. It is required and must be an array, but its values are not interpreted yet and do not affect loading or evaluation.

For production manifests, use an empty array:

CODE
{
  "capabilities": []
}

Policy entry fields

Each item in policies describes one policy source file. Disabled policies are accepted by the manifest but skipped by the loader.

FieldTypeRequiredMeaning
policy_idstringyesStable identifier for this policy. Used in diagnostics.
domainstringyesRegistered domain used to validate predicates and queries.
filestringyesSafe relative path to the .dl policy source file. Absolute paths, .., and backslashes are rejected. Ignored for buffer-based loading.
sha256stringyesLowercase hex SHA-256 of the .dl file bytes. Must match exactly.
modestringyesPolicy loading mode: enforce, shadow, or test_only.
enabledbooleanyesDisabled policies are present in the manifest but not loaded for decisions.
descriptionstringyesHuman-readable description. No effect on evaluation.
queriesarraynoPublic Query Whitelist. Selects which domain-declared QUERY predicates are publicly observable. Does not create predicates.

Domain binding

The manifest does not create a domain. It selects one.

CODE
{
  "domain": "document_access"
}

During loading, Maelys DL looks up the selected domain in the domain registry. The domain installs the predicate vocabulary used to validate the policy source.

ARCHITECTUREValidate source against its selected domain
    • Select domainmanifest names document_access
    • Look up domainpreviously registered declaration
    • Install vocabularypredicates + source atoms
    • Parse sourcevalidate names, arity and safety

Public Query Whitelist

The queries field is the Public Query Whitelist. It controls which predicates are publicly observable after solving. It does not declare predicates — the Domain Registry is the sole vocabulary authority.

CODE
{
  "queries": [
    { "name": "allow", "arity": 2 }
  ]
}

This says: after solving, callers may inspect allow/2 results. The predicate must already exist in the selected domain with the QUERY capability — the manifest entry only selects it for public exposure.

Observation vs computation

The Public Query Whitelist restricts public observation, not solver computation. Predicates absent from queries are still evaluated internally and may contribute to deriving whitelisted predicates.

Suppose the domain declares both allow/2 and debug_trace/2 as IDB|QUERY, but the production manifest lists only allow/2:

PredicateComputationPublic observation
allow/2Evaluated by the solver.May be queried.
debug_trace/2Still evaluated; may help derive allow/2.May not be queried.

This lets a production manifest expose a minimal surface while a development manifest exposes additional predicates for inspection.

Validation

For each entry in queries, the loader verifies:

  1. Declared predicate: its name must exist in the selected domain.
  2. Matching arity: the number of arguments must match the domain declaration exactly.
  3. Query permission: the domain must declare that predicate with the QUERY flag.

If any check fails, loading fails closed.

Fail-closed defaults

Manifest entryPublic query access
queries: []No predicate may be queried.
No queries fieldNo predicate may be queried.

Only predicates explicitly listed in queries may be inspected for this deployment. An empty or missing list grants no public query access.

Manifest declaration

CODE
{
  "name": "allow",
  "arity": 2
}

Publicly queryable fact

DATALOG
allow("alice", "roadmap.pdf").

Manifest versus in-memory sources

Choose the loading path according to where the JSON and source bytes are stored. Advanced C includes the Stable C operations, so those paths appear in both columns.

PathVariantStable CAdvanced C
Manifestfiles on disk✓✓
ManifestJSON and source in memory✕✓
Inlinesource bytes; registered domain✓✓

A green check means that path is available; a red cross means it is not. A static declaration table and in-memory source work by registering the domain, then loading the policy.

The manifest is the contract: it describes which policies exist, which domain they use, which predicates are queryable, and which SHA-256 each source must match.

For buffer-based loading, the .dl sources are supplied separately as in-memory policy sources. They are matched to manifest entries by policy_id.

For example, the source for manifest entry document_access.main must carry that same policy_id, not merely occupy the same position in an array.

This means the manifest still controls policy identity, domain binding, query surface, and integrity checks. The source array only provides the actual .dl bytes.

Loading permissions

The manifest loader has two independent opt-in permissions:

  • Accept test-only policies. Without permission, an enabled entry marked test_only rejects the load. With permission it is loaded and evaluated normally; this is not a dry run.
  • Accept undeclared policy-source atoms. Without permission, a quoted string written in the source must be in the selected domain's atoms. With permission, it can be accepted locally for that loaded policy; the registered domain is not expanded.

Neither permission bypasses source SHA verification or permits undeclared predicates. Unknown permission bits are rejected. Inline loading exposes no such override and always requires declared source strings.

A runtime EDB value such as "alice" does not need to appear in atoms unless the policy source itself also names it.

What you have learned

KEEP THIS MODEL

Choose how to load and expose a policy
  • The manifest governs a deployment

    Manifest loading is the production governance path: policy discovery, SHA integrity, domain binding, loading modes, and a Public Query Whitelist that controls public observation.

  • The same manifest checks work in memory

    Buffer manifest loading keeps that model entirely in memory.

  • Inline loading has no manifest whitelist

    Inline loading removes the manifest for one in-memory source. It preserves the domain predicate and source-atom checks, but all domain QUERY predicates are accessible.

  • Declaration tables work with either path

    A static declaration table works with inline loading too, but registration and loading remain separate public operations.

  • Loading is not an authorization decision

    The selected domain defines the vocabulary; the policy supplies the logic; the manifest adds source-integrity checks, deployment metadata and a public-query boundary. Authorization decisions are produced exclusively by policy evaluation.