# Miden Project And Packaging: Post-Hoc Specification

## Scope

This document specifies the current project/versioning/dependency behavior implemented by:

- `miden-project`
- `miden-assembly` / `ProjectAssembler`
- `miden-mast-package`
- `miden-package-registry`
- `miden-package-registry-local`

It is intentionally implementation-first. Where the current behavior appears surprising, incomplete, or inconsistent with older documentation, that is called out explicitly.

## Versioning Model

### Source projects

- A source project is versioned only by the semantic version declared in `miden-project.toml` under `[package].version`.
- Workspace members may inherit a version from `[workspace.package].version` using dotted-key syntax in the member manifest, e.g. `[package] version.workspace = true`, but the effective version is still a semantic version only.
- A source project does not have an artifact digest until it is assembled.

### Assembled packages

- A `.masp` package preserves the project semantic version as package metadata.
- The assembled package also has a content digest, derived from the package MAST artifact.
- In the package registry and dependency solver, the effective package identity of a published artifact is `name + semver + digest`.
- In assembled package manifests, each runtime dependency records:
  - dependency package name
  - dependency target kind
  - dependency semantic version
  - dependency digest

### Registry version identity

- The registry uses `Version` values of the form `semver` or `semver#digest`.
- Published packages are registered canonically as `semver#digest`.
- `miden-package-registry-local` rejects duplicate registrations for the same package name and semantic version, even if the bytes or digest differ.
- Consequently, a semantic version can map to at most one canonical published artifact in the local registry.

## Dependency Specification

### Accepted manifest forms

Project dependencies in `miden-project.toml` may currently be expressed as:

- a semantic version requirement string, e.g. `dep = "=1.2.3"`
- a digest-only requirement string, e.g. `dep = "0x..."`
- an exact published package requirement string, e.g. `dep = "1.2.3#0x..."`
- a path dependency table, e.g. `dep = { path = "../dep" }`
- a path dependency table with requirement, e.g. `dep = { path = "../dep", version = "^1.2.0" }`
- a git dependency table, e.g. `dep = { git = "...", branch = "main" }`
- a git dependency table with semantic version requirement, e.g. `dep = { git = "...", rev = "deadbeef", version = "^1.2.0" }`
- a workspace-inherited dependency entry, e.g. `dep.workspace = true` or `dep = { workspace = true, linkage = "static" }`

### Registry-hosted dependencies

- A dependency with neither `path` nor `git` is resolved via the configured package registry.
- Registry requirements support:
  - semantic version requirements
  - digest-only requirements
  - exact `semver#digest` requirements
- Registry resolution uses `find_latest`.
- Semantic requirements select the latest matching semantic version.
- Exact `semver#digest` requirements select only that exact published artifact.
- Digest-only requirements select the latest registered package version whose digest matches.
- If multiple semantic versions share the same digest, a plain digest-only lookup still prefers the latest matching registered version.
- When additional semantic constraints on that same dependency are introduced transitively, the dependency solver intersects the digest and semantic constraints and can select a compatible shared-digest version instead of failing resolution.

### Path dependencies

- A `path` dependency may point to:
  - a project directory
  - a workspace root directory
  - a `.masp` artifact
- If `path` points to a project/workspace source tree and no `version` is provided:
  - no additional version validation is performed
  - the dependency uses whatever semantic version is declared in the referenced source manifest
- If `path` points to a project/workspace source tree and `version` is provided:
  - assembly/dependency-graph construction fails unless the referenced source manifest version satisfies the requirement
- If `path` points to a `.masp` artifact and no `version` is provided:
  - the dependency uses whatever semantic version and digest are embedded in that artifact
- If `path` points to a `.masp` artifact and `version` is provided:
  - the requirement is validated against the fully-qualified package version

### Workspace dependencies

- Inside a workspace, any dependency inherited via `workspace = true` is taken from `[workspace.dependencies]`.
- When the inherited dependency path resolves to a member located within the workspace root, it is treated as a workspace-member dependency rather than a generic path dependency.
- Workspace-member dependencies always use the current workspace member source version, not any registry version.
- Package-level linkage may override the linkage defined at the workspace level.
- Workspace-member dependency resolution ignores any registry packages with the same name.

### Git dependencies

- A `git` dependency must specify exactly one of:
  - `branch`
  - `rev`
- `branch` and `rev` together are rejected.
- Digest-only and exact `semver#digest` requirements are rejected for `git` dependencies.
- If no `version` is provided:
  - no additional semantic-version validation is performed
  - the dependency uses whatever semantic version is declared by the checked-out project manifest at the requested revision
- If `version` is provided:
  - dependency resolution fails unless the checked-out project manifest version satisfies the semantic version requirement
- Git dependencies are resolved by cloning/fetching into a cache, checking out the requested revision, and loading `miden-project.toml` from the repository root.

## Assembly And Publication Behavior

### Assembling source dependencies

- Source dependencies resolved from workspace/path/git are assembled before being linked into the dependent package.
- Source dependencies are automatically published to the mutable package store used by `ProjectAssembler`.
- The root package being assembled is not auto-published by `ProjectAssembler`; publication happens only for source dependencies.

### Reuse of already-registered source packages

- Before re-assembling a source dependency, `ProjectAssembler` tries to reuse an already-registered canonical package with the same package name and semantic version.
- Reuse is allowed only if source provenance matches:
  - path/workspace sources use a provenance check derived from the target metadata and the effective manifest/source inputs used for assembly
  - git sources use `repo + resolved commit hash`
- Workspace-manifest changes that do not change a member package’s effective manifest, semantic version, profiles, or dependencies do not prevent reuse of that member package.
- If the registry already contains the same package name and semantic version but different provenance, assembly fails and instructs the caller to bump the semantic version.
- If the registry already contains the same package name and semantic version but the package lacks provenance metadata, assembly also fails and instructs the caller to bump the semantic version.

### Runtime dependency recording

- Dynamically linked dependencies are recorded in the assembled package manifest.
- Statically linked dependencies are not recorded directly, but their own dynamic dependencies are propagated upward.
- Kernel dependencies are always recorded as runtime dependencies, even when linked statically for executable assembly.
- Runtime dependency merging requires exact agreement on dependency name, semantic version, kind, and digest; otherwise assembly fails with a runtime dependency conflict.

### Executable package names

- Library-like targets produce packages named exactly after the project package name.
- Executable targets produce packages named `project:target`.

## Special Cases And Under-Specified Behavior

### Current special cases

- Digest-only requirements are weaker than exact `semver#digest` requirements and stronger than plain semantic requirements, but they are not semver-aware when multiple semantic versions reuse one digest.
- A path dependency pointing at source accepts a digest-only or exact `semver#digest` requirement syntactically, but such a requirement is only satisfiable for a preassembled `.masp` path, not for source-only projects, because source projects do not have digests before assembly.
- Workspace-member dependencies always resolve to the workspace member’s current source version; they do not preserve any explicit semantic requirement from the original path-based workspace dependency declaration once it is normalized to a workspace-member dependency.
- Git dependencies only support repositories whose project manifest is at repository root.
- `assemble_with_sources` omits source-provenance sections and bypasses source-path hashing for the package being assembled from provided modules.
