# Architectural boundary enforcement (run: `lint-imports`).
#
# The codebase is organised in three trust rings (see docs/ARCHITECTURE.md):
#
#   Ring 0  kernel    — the trusted computing base: the gate logic and the data
#                       it reasons over. A bug here can cause a wrong ALLOW.
#   Ring 1  runtime   — wires the kernel to an executor (capability boundary,
#                       node/worker orchestration, opt-in federation).
#   Ring 2  platform  — quality/cost/observability (budget, context, trace,
#                       extensions). A bug here wastes resources, not safety.
#
# The one guarantee that matters: the kernel must not depend on the runtime or
# the platform. A platform bug therefore cannot reach the decision. (Runtime is
# allowed to use the platform — node legitimately orchestrates budget/context/
# trace — so that edge is not forbidden; only the kernel boundary is.)

[importlinter]
root_package = axor_core

[importlinter:contract:kernel-purity]
name = Kernel (Ring 0) must not import runtime (Ring 1) or platform (Ring 2)
type = forbidden
source_modules =
    axor_core.contracts
    axor_core.errors
    axor_core.taint
    axor_core.security
    axor_core.policy
    axor_core.kernel
    axor_core.degradation
    axor_core.governor
forbidden_modules =
    axor_core.plane
    axor_core.capability
    axor_core.node
    axor_core.worker
    axor_core.federation
    axor_core.budget
    axor_core.context
    axor_core.trace
    axor_core.extensions

# T0 (producing process non-interpreting) — see docs/kernel-theorem.md §3.
#
# The functions that PRODUCE a trusted-path projection must be deterministic and
# structural, never a model reading the governed content (a steerable projector
# can emit a valid-but-unfaithful projection). This contract pins the structural
# half: a projection producer must not import the advisory/model layer
# (kernel.adjudicator — the only model-consumer surface in core). The external
# half (no provider SDK / network / subprocess in a producer) is pinned by
# tests/invariants/test_t0_producers_non_interpreting.py, because import-linter
# graphs only the root package by default. The adjudicator is a *consumer* of the
# projection (advisory, projection-only, tightening-only) and may itself be a
# model — T0 constrains the producer, not the consumer, which is why the rule is
# scoped to these four modules, not to the whole kernel.
[importlinter:contract:t0-producers-non-interpreting]
name = T0 — projection producers must not import the advisory/model surface
type = forbidden
source_modules =
    axor_core.security.carrier
    axor_core.policy.consequence
    axor_core.policy.normalizer
    axor_core.node.canonicalizer
forbidden_modules =
    axor_core.kernel.adjudicator
