C Stable API
Solving
Prepare an opaque C session and solve independent request snapshots.The solving concept explains the evaluation pipeline.
Here, the C facade prepares one selected policy in an opaque
maelys_datalog_session_t and returns one opaque result per successful solve.
A session keeps the selected policy prepared for independent requests.
Types
Defined on this page
| Type | Purpose |
|---|---|
maelys_datalog_session_t | Opaque prepared policy and per-request working state. |
maelys_datalog_session_config_t | Optional requirements and memory configuration fixed at session creation. |
maelys_datalog_result_t | One successful solve's answer; release before solving again on the same session. |
Used from other pages
These types are defined on the linked pages; this page uses them in the roles below.
| Type | Use on this page | Defined in |
|---|---|---|
maelys_datalog_policy_t | Input handle selecting the policy to prepare. | Manifests |
maelys_datalog_input_edb_t | Input buffer containing the complete request. | EDB |
maelys_datalog_fact_t | Input array element for an array-based solve. | EDB |
maelys_datalog_diagnostic_t | Optional output argument receiving solve details. | Errors |
Functions
| Function | Purpose |
|---|---|
maelys_datalog_session_create() | Prepare one selected policy with defaults. |
maelys_datalog_session_create_configured() | Prepare it with explicit requirements. |
maelys_datalog_session_solve_edb() | Evaluate a complete opaque input buffer. |
maelys_datalog_session_solve() | Evaluate a borrowed fact array for one request. |
maelys_datalog_session_fingerprint() | Identify the selected policy authority. |
maelys_datalog_session_execution_fingerprint() | Identify that authority together with execution settings. |
maelys_datalog_session_free() | Release the session after its result. |
Opaque lifecycle types
typedef struct maelys_datalog_session maelys_datalog_session_t;typedef struct maelys_datalog_session_config maelys_datalog_session_config_t;typedef struct maelys_datalog_result maelys_datalog_result_t;Create and select a session
A loaded handle may hold more than one policy. Use
maelys_datalog_policy_count()
to find its valid indices; an inline load has just index 0.
Creating a session prepares one selected policy. Use the default call below
unless you need the configured variant.
To prepare the selected policy:
maelys_datalog_status_t
maelys_datalog_session_create(
const maelys_datalog_policy_t * policy,
size_t policy_index,
maelys_datalog_session_t ** out_session
);maelys_datalog_status_tReturns OK with a new session, or an error without publishing a session.
maelys_datalog_session_t *session = NULL;
maelys_datalog_status_t status =
maelys_datalog_session_create(policy, 0u, &session);The session is fixed to its selected policy. To prepare a different policy in the same loaded set, create another session with its own index. A session owns the prepared state after creation, so its policy handle may then be freed.
Solve one complete request
Give the prepared session the entire fact snapshot for this request. A successful call returns a new result; the input is not appended to the prior request.
maelys_datalog_status_t
maelys_datalog_session_solve_edb(
maelys_datalog_session_t * session,
const maelys_datalog_input_edb_t * edb,
maelys_datalog_result_t ** out_result,
maelys_datalog_diagnostic_t * out_diagnostic
);maelys_datalog_status_tA successful result belongs to this session until it is freed.
maelys_datalog_result_t *result = NULL;
maelys_datalog_status_t status = maelys_datalog_session_solve_edb(
session, edb, &result, &diagnostic);When the caller already has a typed fact array, it may submit that complete snapshot without creating an input EDB:
maelys_datalog_status_t
maelys_datalog_session_solve(
maelys_datalog_session_t * session,
const maelys_datalog_fact_t * facts,
size_t fact_count,
maelys_datalog_result_t ** out_result,
maelys_datalog_diagnostic_t * out_diagnostic
);maelys_datalog_status_tReturns OK with a new result; failure publishes no result.
maelys_datalog_result_t *result = NULL;
maelys_datalog_status_t status = maelys_datalog_session_solve(
session, facts, fact_count, &result, &diagnostic);maelys_datalog_session_solve() borrows a fact array for one call;
maelys_datalog_session_solve_edb() borrows a previously filled opaque input
buffer for one call. Both return a maelys_datalog_result_t * on success and
publish no result on failure. They do not append to a previous request. One
result may be live per reference session: release it before another solve or
before freeing the session. See runtime EDB for
building input facts and querying for inspecting
the result.
Example — document access
The one-policy inline handle selects documents.main at index 0.
After the seven request facts
have been added, the session evaluates the policy once:
maelys_datalog_session_t *session = NULL;
maelys_datalog_status_t status =
maelys_datalog_session_create(policy, 0u, &session);
if (status != MAELYS_DATALOG_STATUS_OK) return status;
maelys_datalog_result_t *result = NULL;
maelys_datalog_diagnostic_t diagnostic = MAELYS_DATALOG_DIAGNOSTIC_INIT;
status = maelys_datalog_session_solve_edb(
session, edb, &result, &diagnostic);
if (status != MAELYS_DATALOG_STATUS_OK) {
/* No result was published: deny and inspect diagnostic. */
}The resulting IDB includes can_read("alice","roadmap.pdf") and
allow("alice","roadmap.pdf"); the blocked Mallory has no allow fact.
Release this result before solving another request on the same session.
Sessions and repeated solves
A session prepares one policy and may solve multiple independent fact arrays.
Each call to maelys_datalog_session_solve() replaces the runtime EDB for that
solve; callers do not clear or finalize an exposed EDB structure.
Public fact values are text symbols, signed integers, or booleans:
maelys_datalog_value_t values[3] = {
{ .kind = MAELYS_DATALOG_VALUE_SYMBOL, .as.symbol = "alice" },
{ .kind = MAELYS_DATALOG_VALUE_INTEGER, .as.integer = 42 },
{ .kind = MAELYS_DATALOG_VALUE_BOOLEAN, .as.boolean = 1 },
};The facade performs symbol interning and ground-query conversion internally. New consumers do not need direct access to a symbol table or predicate ID.
Opaque session configuration
Session configuration has been available since 0.4.0. Use it only when the defaults do not express an application's requirements.
Ordinary consumers still include only <maelys/datalog.h>. Use
maelys_datalog_session_config_t when you need to require a capability;
the default maelys_datalog_session_create() remains unchanged.
Pass the configuration at creation time when you must require capabilities or supply a bounded explanation workspace. A failed requirement prevents the session from being published.
maelys_datalog_status_t
maelys_datalog_session_create_configured(
const maelys_datalog_policy_t * policy,
size_t policy_index,
const maelys_datalog_session_config_t * config,
maelys_datalog_session_t ** out_session
);maelys_datalog_status_tReturns OK with a prepared session, or an error if requirements cannot be met.
This helper requires Why-false support when creating a session for the first policy. It returns an error if the requirement cannot be met:
#include <maelys/datalog.h>
maelys_datalog_status_t prepare_with_explanations(
const maelys_datalog_policy_t *policy,
maelys_datalog_session_t **out)
{
if (out == NULL) return MAELYS_DATALOG_STATUS_INVALID_ARGUMENT;
*out = NULL;
maelys_datalog_session_config_t *config = NULL;
maelys_datalog_status_t status =
maelys_datalog_session_config_create(&config);
if (status != MAELYS_DATALOG_STATUS_OK) return status;
status = maelys_datalog_session_config_set_required_capabilities(
config, MAELYS_DATALOG_CAP_EXPLAIN_FALSE);
if (status == MAELYS_DATALOG_STATUS_OK) {
status = maelys_datalog_session_create_configured(
policy, 0u, config, out);
}
maelys_datalog_session_config_free(config);
return status;
}A new configuration has no additional required capabilities and a zero work
budget. Unknown capability bits are rejected without modifying the configuration.
A nonzero budget requests enforcement; the current reference backend lacks
MAELYS_DATALOG_CAP_WORK_LIMIT, so session creation returns UNSUPPORTED.
Session creation copies the configuration. You may then free it, change it or reuse it without changing existing sessions. A null configuration is equivalent to the default session constructor. Configuration mutation is not synchronized: the caller must serialize access.
The separate datalog_backend.h header remains the extension-author API for
implementing a custom backend and using maelys_datalog_session_create_ex().
Its descriptor layout and ABI are unchanged. Applications and Python Next do
not need that header to configure a session.
Session identity and release
Use a fingerprint when an audit record or cache must identify the selected
policy, rather than just the loaded set. Both functions write into a
caller-owned buffer of MAELYS_DATALOG_PUBLIC_FINGERPRINT_BYTES bytes and
leave that buffer unchanged on failure.
maelys_datalog_status_t
maelys_datalog_session_fingerprint(
const maelys_datalog_session_t * session,
char * out_fingerprint
);maelys_datalog_status_tReturns OK with the selected policy authority identity; leaves the output unchanged on failure.
maelys_datalog_status_t
maelys_datalog_session_execution_fingerprint(
const maelys_datalog_session_t * session,
char * out_fingerprint
);maelys_datalog_status_tReturns OK with the policy, backend, execution options and size-profile identity; leaves the output unchanged on failure.
The execution fingerprint adds the backend, execution options and size profile to the policy authority identity. Neither fingerprint includes runtime request facts, so it is not an identifier for a particular decision or input batch.
char identity[MAELYS_DATALOG_PUBLIC_FINGERPRINT_BYTES];
maelys_datalog_status_t status =
maelys_datalog_session_execution_fingerprint(session, identity);
if (status != MAELYS_DATALOG_STATUS_OK) {
/* Do not use identity. */
}A successful solve gives the session one live result. Release that result before another solve and before freeing the session.
maelys_datalog_status_t
maelys_datalog_session_free(
maelys_datalog_session_t * session
);maelys_datalog_status_tReturns OK when the session is released; a still-live result prevents release.
maelys_datalog_status_t status = maelys_datalog_result_free(result);
if (status != MAELYS_DATALOG_STATUS_OK) return status;
result = NULL;
status = maelys_datalog_session_free(session);
if (status != MAELYS_DATALOG_STATUS_OK) return status;
session = NULL;