# Destination State ## Purpose `internal/state` parses, validates, writes, and compares `.distributor.json` destination state. ## Inputs and outputs Input is JSON destination state plus the current source manifest, pipeline id, destination id, and whether the destination path has unmanaged content. Output is a deterministic comparison outcome and reason. ## State behavior `.distributor.json` requires: - `schema_version: 1` - `pipeline_id` - `destination_id` - `published_at` - `source.manifest` - `outputs` `distributor_version` is optional diagnostic metadata. `published_at` parses as RFC3339 and distributor-written state serializes it as RFC3339 UTC. The embedded `source.manifest` is validated with the same source manifest rules used by `internal/bundle`. ## Outputs Each output records `path`, `kind`, `source_path`, `sha256`, and `size`. Supported output kinds are `source` and `generated`. Generated outputs require `transform`. ## Comparison Comparison outcomes cover absent destination state, unmanaged destination content, invalid state, pipeline or destination mismatch, same source manifest, older destination source, newer destination source, same-created digest conflict, and different source id conflict. ## Failure behavior Invalid JSON, invalid state schema, invalid embedded source manifests, unsafe output paths, unsupported output kinds, missing generated-output transform names, and mismatched pipeline or destination ids produce comparison outcomes that publish planning can turn into fail actions. Supported identity and source-manifest conflicts can become forced replacement only when publish planning receives explicit force and compatible transfer policy. ## Boundaries This package does not publish files, delete files, inspect storage backends, or choose transfer policy actions. Publish planning consumes these comparison outcomes later. ## Tests Before changing destination state behavior, inspect tests under `internal/state`. ## Invariants - `.distributor.json` is the destination sentinel and state record. - Embedded source manifests use the same validation rules as source bundles. - Generated outputs always record a transform id. - Comparison returns outcomes and reasons; it does not mutate storage. - `distributor_version` is diagnostic metadata, not a comparison key.