Skip to content

Admission architecture

ImportSpy is a policy-as-code admission engine for Python modules and their observed dependencies. The local engine remains useful offline: it does not require an account, send telemetry, or contact a control plane.

Source bytes → SourceInspector → DependencyResolver → Evidence collection
                                                        ↓
                                      AdmissionPolicy + PolicyEngine
                                                        ↓
                                               AdmissionDecision
                                             ADMIT           DENY
                                               ↓              stop
                                     explicit load(request)
                                               ↓
                                     execute inspected bytes
                                               ↓
                                     optional runtime validators

check never executes target code, including on admission. load performs a fresh admission and executes the captured bytes once only after admission. The host's Python, operating system, architecture and requested environment conditions can be inspected before loading a target. Checks requiring actual runtime objects necessarily happen after module initialization, and cannot prevent or undo its top-level effects. No part of this is a sandbox.

Responsibilities

Component Responsibility Executes target code?
SourceInspector Parse/compile syntax; collect lexical declarations, imports and uncertainty No
DependencyResolver Resolve local paths and installed distribution metadata; collect origins/declarations No
Host evidence collection Read host identity and requested environment conditions No
EvidenceProvider Collect explicitly selected external/local facts Trusted plugin code runs
PolicyEngine Compare collected facts to structural, runtime, dependency and evidence policy No
AdmissionEngine.check Orchestrate inspection, collection and pure evaluation No
AdmissionEngine.load Admit fresh source, execute captured bytes, run runtime validators Yes
Reporters Render an existing decision as human text, JSON or SARIF No
Spy.importspy, SpyModel.from_module Compatibility inspection of already loaded objects Runtime introspection may invoke dynamic attributes

Providers and validators are application-selected trusted code. Entry-point loading executes Python and is not itself covered by the target no-execution boundary. The engine never automatically imports all installed extensions.

Data and policy

domain.py defines serializable AdmissionRequest, AdmissionContext, AdmissionDecision, Evidence, Violation, dependency and origin records. The decision includes source/policy identity and SHA-256 hashes, engine version, host identity, dependencies, observations, violations, phases, timestamp, runtime_required, and target_executed.

Evidence.status distinguishes verified, observed, unknown, and unavailable; phase distinguishes static, host/runtime, and external collection. Verification is scoped to the provider's stated fact. Observed installation metadata is not cryptographic provenance. Static facts describe declarations, not the eventual behavior of arbitrary Python code.

AdmissionPolicy extends the existing structural SpyModel vocabulary. schema_version: 1 is validated; version still constrains the target module's version. Unknown fields are rejected. Contracts are loaded with safe YAML; annotations are compared as text and never evaluated.

Policy evaluation performs no network or filesystem operations. Collection and policy remain separate so applications can test deterministic decisions and replace providers. JSON serialization of the same decision is stable; timestamps and host/install metadata can differ between separate checks.

Execution and limitations

The loader rejects an already loaded module name rather than replacing an existing sys.modules entry. Execution or runtime-validation failure removes its registration; it cannot roll back other effects. It does not alter sys.path, install packages or implement an import hook. Configure the runtime's normal import environment before loading; package-relative loading needs the appropriate qualified name and package context.

Dependency resolution inventories imports in the inspected file, including conditional/function imports. It is not recursive transitive dependency validation and does not intercept dynamic imports. A project directory checks only explicit configured subjects. Metadata caching is scoped to an engine instance; explicit load refreshes it. Create a new engine after changing an installation for independent check-only requests.

A future control plane can consume decisions and evidence without changing the local enforcement API. Organizational dashboards, policy registries and approval workflows are outside this repository; no core enforcement feature requires them.