Dependency Direction¶
Dependency direction in bijux-core protects three different concerns:
product execution, reusable test support, and repository governance. A package
edge is acceptable only when the package being imported owns a narrower or
lower-level responsibility. Similar command names or shared release ownership
do not justify a dependency.
Workspace Graph¶
The solid arrows below are direct, normal Cargo dependencies. The dashed arrow is a development-only dependency.
flowchart TD
dag_cli["bijux-dag-cli"] --> dag_app["bijux-dag-app"]
dag_app --> dag_runtime["bijux-dag-runtime"]
dag_app --> dag_core["bijux-dag-core"]
dag_app --> dag_artifacts["bijux-dag-artifacts"]
dag_runtime --> dag_core
dag_runtime --> dag_artifacts
dag_testkit["bijux-dag-testkit"] --> dag_core
dag_testkit --> dag_artifacts
cli_python["bijux-cli-python"] --> cli["bijux-cli"]
dev["bijux-dev"] --> cli
dev --> dag_app
dev --> dag_runtime
dev --> dag_core
dev --> dag_artifacts
dev -. dev dependency .-> dag_testkit
bijux-cli has no Cargo dependency on the DAG packages. Product mounting is a
route and process integration concern, not permission to import DAG
implementation code into the general command runtime.
Package Rules¶
| Package | May depend on | Boundary protected by that direction |
|---|---|---|
bijux-dag-core |
third-party data, hashing, and error libraries | graph meaning remains deterministic and free of process, filesystem, environment, and clock access |
bijux-dag-artifacts |
serialization, hashing, and error libraries | persisted evidence remains independent of scheduling and command presentation |
bijux-dag-runtime |
core and artifacts | execution may consume graph meaning and write evidence, but cannot import app or CLI routing |
bijux-dag-app |
core, runtime, and artifacts | use-case orchestration may compose lower layers without reaching into runtime-private modules |
bijux-dag-cli |
app | argument parsing and terminal presentation remain at the outer edge |
bijux-dag-testkit |
core and artifacts | shared fixtures can construct domain values and inspect evidence without becoming a product dependency |
bijux-cli-python |
bijux-cli |
the native bridge exposes the Rust command contract instead of implementing a second runtime |
bijux-dev |
public product crates; testkit for development | governance can inspect and prove product behavior, while product crates remain free of maintainer code |
These are direct-dependency permissions, not invitations to expose internals.
For example, bijux-dag-app depends on bijux-dag-runtime but is explicitly
forbidden from importing runtime_core.
Integration Without A Cargo Edge¶
The Python package has two distinct integration paths:
- its native extension links to
bijux-cli - its DAG SDK resolves and invokes
bijux-dag --jsonas a subprocess
The subprocess boundary is deliberate. Installing the Python bijux-cli
distribution does not install bijux-dag, and the SDK must report a missing or
incompatible DAG executable rather than silently substituting another
implementation. BIJUX_BIN and the DAG executable resolver are runtime
selection mechanisms; they do not change package ownership.
Enforced Invariants¶
The graph is not governed by this page alone:
dependency_boundary_contracts.rsderives direct dependencies fromcargo metadataand enforces allowlists for core, runtime, and governanceno_core_io.rsrejects filesystem, process, environment, and time access in DAG core sourceno_runtime_in_core.rsrejects the reverse core-to-runtime edgeno_cli_in_runtime.rsrejects runtime dependencies on DAG app and CLImaintainer_leakage_boundaries.rsrejects maintainer assembly in the Python bridge- workspace package-boundary contracts classify public, internal, and non-publishable packages independently of dependency direction
When the intended graph changes, update Cargo metadata and the enforcing test in the same commit. Editing this diagram alone does not authorize a new edge.
Review A Proposed Edge¶
Before adding a workspace dependency, answer these questions:
- Which package owns the behavior being reused?
- Is the proposed consumer at the same or an outer architectural layer?
- Can a schema, public query, serialized value, or subprocess boundary avoid importing implementation code?
- Would the edge make product execution depend on test or governance code?
- Which contract test will reject a future reverse dependency?
Reject an edge when ownership is unclear. If two packages each need the other's behavior, the problem is usually a missing narrow contract or a misplaced responsibility, not a reason to create a cycle.
Source Anchors¶
Cargo.tomlcrates/bijux-dev/tests/dependency_boundary_contracts.rscrates/bijux-dev/tests/no_core_io.rscrates/bijux-dev/tests/no_runtime_in_core.rscrates/bijux-dev/tests/no_cli_in_runtime.rscrates/bijux-cli-python/tests/maintainer_leakage_boundaries.rscrates/bijux-cli-python/python/bijux_cli_py/_runtime.py