Skip to content

Workspace contract

apizr.workspace owns explicit project settings, operator authority, captured analysis sessions and compiler composition. This document defines their shared boundary. The ownership inventory is architecture/packages.toml; its import allowlist admits the existing core contracts and Pydantic. CLI adapters, optional SDKs and plugin distributions consume this boundary rather than implementing it. Importing the workspace namespace reads no files and grants no authority.

Settings, authority and retained evidence

These values have different lifetimes and cannot substitute for each other:

Value Owner and admission Guarantee
ProjectConfig workspace.project.load_project(explicit_path) Closed apizr.project/v1 declarations, resolved locations and bounded analysis settings
OperatorPolicy workspace.operator_policy Explicit grants for exact operations and targets; project declarations cannot create them
Scope workspace.analysis_session.load_scope(project_path, operator_policy) Captured policies and settings, plus a canonical absolute root and nonnegative device/inode identity
PreparedExposure workspace.compiler.prepare_exposure(...) Retained source/resource bytes with full Catalog, Graph, readiness, exposure policy and plan
Bundle mapping workspace.compiler.render_bundle(prepared, ...) Validated output bytes for one explicitly selected interface and backend
flowchart LR
    Project[Explicit apizr.toml] --> Settings[ProjectConfig]
    Operator[Explicit OperatorPolicy] --> Admission[Source admission]
    Settings --> Admission
    Admission --> Session[Scope: settings and pinned root]
    Session --> Analysis[Bounded static analysis]
    Admission --> Analysis
    Analysis --> Prepared[PreparedExposure: retained evidence and bytes]
    Prepared --> Render[Validate and render REST or MCP]
    Render --> Bytes[Bundle bytes]

The Python compiler accepts explicit settings directly; loading a project file or creating a session is optional. PinnedRoot restricts analysis to the captured directory identity and still requires an operator grant. A live GitSnapshot uses its independently authorized acquisition and commit identity. No setting or prepared context authorizes execution, signing, image build or publication.

Project declarations

load_project reads only the named regular UTF-8 TOML file, bounded to 64 KiB. It performs no directory search, policy-file read, plugin discovery, environment interpolation or source import. Unknown fields, unknown versions, TOML date/time values and coercion of strings/booleans/floats into integer bounds are rejected. ProjectConfig and its existing nested models remain the executable definitions; there is no second workspace configuration schema.

root, readiness_policy and exposure_policy resolve against the named file's directory. Absolute local paths are accepted; URIs, empty paths and NUL are refused. Source roots remain relative to the repository root. Standard directory exclusions are added to the file's exclusions. CLI override precedence belongs to the adapter and is specified in the project guide. Python callers pass the resolved settings explicitly to the compiler.

application declares exact dependency pins and selected resource files; plugins declares artifact identities only. Loading either declaration installs and executes nothing. Output locations, execution credentials and operator grants are outside apizr.project/v1.

Captured analysis sessions

load_scope first loads the explicit project declaration, revalidates supplied operator authority and admits the root. It captures device/inode identity before reading the selected readiness/exposure JSON files. Those files must be regular, are limited to 64 KiB each and reject duplicate object keys. The resulting scope contains policy values rather than paths to reopen.

The private worker handoff is limited to 1 MiB. read_session consumes and closes its inherited regular-file descriptor, refuses duplicate JSON keys and strictly revalidates the closed scope. check_scope rechecks both authorization and root identity before work; workers recheck too. Replacing the root directory is refused. Changing project/policy files after capture cannot widen an existing session. Changes to source contents inside the same directory require fresh analysis; an inode pin does not freeze those contents.

mcp_session wraps this scope with separately captured delivery inputs only when requested by the operator. Its reader retains the existing plain-scope handoff for installed read-only clients. analysis_scope gives compiler workers only analysis grants; history_scope retains analysis/history grants. Neither passes delivery credentials or signing authority to read-only workers. Editor requests cannot replace captured roots or scan bounds; history operations independently authorize the exact store.

Scope is a private handoff between launchers and workers, not a user-editable project format or a new supported public wire schema.

Compiler API and ownership

assess_readiness performs one bounded discovery and returns the independent readiness report without applying exposure selection. prepare_exposure performs one analysis, assesses readiness and computes the explicit exposure plan. It retains the exact analyzed bytes and captures declared resources while source authority is available. Resource capture is bounded and checks individual files; it is not an atomic snapshot of a changing local filesystem.

PreparedExposure is an in-memory frozen dataclass over existing contracts. Construction, including dataclasses.replace, copies evidence.sources, resources and dependency_archives into read-only mappings of string paths to immutable bytes. Mutating a caller's original dictionaries cannot change later renderings. A mutable byte buffer is rejected with TypeError. The remaining fields use their existing frozen contract models and canonical serializers.

Direct construction retains values; it does not certify their consistency or grant authority. Each render_bundle revalidates the retained evidence/plan linkage, source digests, selected dependencies, resource identities and source provenance through the existing bundle admission. Fabricated or replaced values cannot bypass that admission. This context is not a new serialized evidence schema and must not be treated as a persistence format.

Rendering uses retained project bytes and installed generator resources. It never reopens the source root or configuration files, so the same prepared context can render REST and MCP after the project has been removed. A changed source revision requires a new preparation. The result is a fresh caller-owned dict[str, bytes]; writing files remains the separate repository_interfaces.output.write_bundle operation. The compiler neither starts services nor probes execution backends.

Refusals and compatibility

Operations return values or propagate exceptions without printing or exiting:

Condition Result
Missing or mismatched source grant; replaced pinned root AuthorizationDenied with the existing fixed decision
Invalid declarations, bounds, JSON/TOML or canonical evidence Existing validation/decoding ValueError subclasses; filesystem errors propagate
Readiness uncertainty Report diagnostics and exit_code; selection remains a separate decision
Unknown or ineligible exposure selection ExposureRefused, including diagnostics and the already computed readiness report when raised by preparation
Invalid rendering contract or forbidden backend Existing BundleRefused, PolicyRefused or ValueError; no backend fallback
Non-byte prepared payload TypeError at context construction

An empty selection may produce an empty plan but cannot produce a service bundle. Unselected uncertainty stays in the complete audit. The selected-evidence proof determines which required diagnostics block a selected root. Existing project version, session handoff shapes, canonical evidence bytes and CLI/Python bundle parity are preserved. Qualifications cover those bytes, caller-mutation isolation, duplicate authority refusal and replaced-root denial; package architecture gates enforce the supported dependency direction.