The MVP goal is a domain-agnostic bundle distributor that discovers source bundles, validates `manifest.json`, optionally transforms Markdown to HTML, publishes selected outputs to one or more destinations, and records destination state in `.distributor.json`.
## Global Implementation Rules
All stages should preserve these invariants:
- Producer applications own source bundle creation.
## Stage 1: Project Skeleton, CLI Shell, and Baseline Tooling
### Goal
Create the initial Go application structure and a minimal executable `distributor` command with no business behavior beyond version/help output and placeholder commands.
### Scope
Implement the accepted package skeleton from `docs/roadmap/packages.md` at the level needed for compilation.
Create:
```text
cmd/distributor/main.go
internal/cli/
internal/app/
internal/config/
internal/logging/
```
Initial CLI commands:
-`distributor --help`
-`distributor version`
-`distributor run`
-`distributor validate`
-`distributor inspect`
At this stage, `run`, `validate`, and `inspect` may return clear “not implemented” errors, but the command structure should be present.
### Notes
Prefer a small CLI dependency only if the project already standardizes on one. Otherwise, the standard library is acceptable for the first pass.
Add a version variable that can later be set at build time.
### Tests
Add tests for:
- command construction if testable;
- version string behavior if exposed through a package;
- basic package compilation.
### Completion Criteria
-`go test ./...` passes.
-`go run ./cmd/distributor --help` works.
-`go run ./cmd/distributor version` works.
- Placeholder operational commands fail clearly and intentionally.
## Stage 2: Config Schema, Loading, Defaults, and Validation
### Goal
Implement the MVP `config.yml` schema described in `docs/roadmap/config.md`.
### Scope
Create config structs for:
- top-level config;
- pipelines;
- source backend config;
- destination backend config;
- validation policy;
- publish policy;
- transform policy;
- transfer/replacement policy;
- backend-specific local, SSH, and S3 fields.
Support loading YAML from a file path.
Implement validation for:
- required top-level `pipelines`;
- unique pipeline ids;
- required pipeline `id`, `source`, and non-empty `destinations`;
- unique destination ids within a pipeline;
- supported backend names: `local`, `ssh`, `s3`;
- required backend fields;
- supported validation action: `fail`;
- supported transfer actions;
- valid `publish` policy;
- valid Markdown-to-HTML transform config.
Default behavior should match `docs/roadmap/config.md`.
### CLI Integration
Add `--config` to `run`.
For this stage, `distributor run --config config.yml --dry-run` may only load and validate config, then print a concise summary of configured pipelines and destinations.
### Tests
Add unit tests for:
- valid minimal local-to-local config;
- valid fan-out config;
- valid local, SSH, and S3 backend configs;
- duplicate pipeline ids;
- duplicate destination ids;
- missing required fields;
- unsupported backend;
- invalid transfer action;
- invalid validation action, including `warn`.
### Completion Criteria
- Config load/default/validate behavior is implemented and tested.
-`distributor run --config <file> --dry-run` validates config and prints a summary.
- No bundle discovery or publication occurs yet.
## Stage 3: Storage Abstraction, Local Backend, and Fake Backend
### Goal
Introduce the storage backend abstraction before bundle validation so source discovery, validation, and publication are backend-agnostic from the start.
Clarify orchestration behavior when one destination fails. For MVP, fan-out should be deterministic and sequential. Continue planning and reporting later destinations where safe, but return non-zero if any destination fails.
Improve run summary output:
- pipeline id;
- source backend;
- discovered bundle count;
- destination ids;
- action per bundle/destination;
- final status.
### Tests
Add tests for:
- notifier is invoked at the expected orchestration point where testable;
- pipeline failure when a destination fails;
- run summary contains meaningful status information;
- dry-run does not invoke write-side effects.
### Completion Criteria
- The pipeline shape includes notification as an internal no-op stage.
- Run output is useful for unattended operation logs.
Stages 1 through 8 define the local MVP checkpoint. Later stages extend the local MVP with remote backends, cross-backend hardening, user-facing documentation sync, and release readiness.
Implement SSH/SFTP storage backend support for sources and destinations.
### Scope
Create:
```text
internal/adapters/ssh/backend.go
internal/adapters/ssh/config.go
```
Implement the storage backend interface over native SSH/SFTP.
Required config:
```yaml
backend: ssh
uri: ssh://user@example.com:22
path: /remote/root
```
Authentication expectations:
- prefer SSH agent by default;
- use known_hosts validation by default where practical;
- do not require passwords in YAML;
- optional key-file support may be implemented if straightforward, but should not distract from agent-based auth.
Support SSH/SFTP backend as both source and destination:
- local -> ssh;
- ssh -> local;
- ssh -> ssh where feasible through staging or streaming.
### Safety Requirements
The SSH backend must enforce the same logical path safety rules as the local backend.
Deletion must remain limited to managed destination bundle paths guarded by valid `.distributor.json`.
### Tests
Unit-test path handling and config validation.
If practical, add integration tests that can be skipped unless an SSH test endpoint is configured through environment variables. Do not require a live SSH server for normal `go test ./...`.
### Completion Criteria
- SSH/SFTP backend compiles and satisfies the storage interface.
- Backend config validation is tested.
- Normal tests do not depend on a live SSH server.
- At least local-to-SSH and SSH-to-local flows are documented or manually testable.
Support S3 backend as both source and destination.
### Safety Requirements
Treat S3 prefixes as object trees. Do not assume real directories exist.
Deletion must be limited to destination bundle prefixes that are confirmed managed by `.distributor.json`.
### Tests
Add unit tests for:
- config validation;
- key/prefix normalization;
- content type selection;
- path traversal rejection;
- publish planning with S3 destination state fixtures.
If practical, add integration tests gated by environment variables or a local S3-compatible test service. Normal `go test ./...` must not require live S3 credentials.
### Completion Criteria
- S3 backend compiles and satisfies the storage interface.
- S3 source and destination flows are supported through the common pipeline path.
Harden the MVP across backend combinations, destination policies, and failure cases.
### Scope
Add end-to-end coverage for representative scenarios:
- local source -> local archive destination;
- local source -> local HTML destination;
- local source -> two destinations with different publish policies;
- local source -> SSH destination, where integration credentials exist;
- local source -> S3 destination, where integration credentials exist;
- S3 source -> local destination, where integration credentials exist;
- SSH source -> local destination, where integration credentials exist.
Improve logging and error messages for:
- invalid config;
- invalid source manifest;
- digest mismatch;
- destination conflict;
- unmanaged destination path;
- backend read/write/list failures;
- transform failures.
Ensure all destructive paths have tests or explicit safeguards.
### Tests
Add or expand tests for:
- dry-run across multiple destinations;
- partial failure behavior;
- repeated run idempotency;
- older/newer destination state behavior;
- destination state output metadata accuracy;
- generated HTML output metadata accuracy.
### Completion Criteria
- MVP behavior is reliable across implemented backend types.
- Error messages identify pipeline id, destination id, bundle id, and reason where practical.
- Idempotent repeated runs behave as expected.
## Stage 12: User-Facing Documentation Sync
### Goal
Update documentation to reflect implemented MVP behavior.
### Scope
Following `docs/policy/documentation.md`, create or update user-facing documentation only for implemented features.
Likely docs:
```text
README.md
docs/config.md
docs/cli.md
docs/policy/architecture.md
docs/internal/bundles.md
docs/internal/backends.md
```
Document:
- what `distributor` does;
- bundle contract summary;
-`.distributor.json` role;
- example source bundle;
- example local-to-local config;
- example local-to-S3 config;
- example local-to-SSH config;
-`run`, `validate`, and `inspect` commands;
- dry-run behavior;
- replacement and safety rules;
- Markdown-to-HTML transform behavior;
- environment-variable credential handling.
Move roadmap material to historical/planning status only if your documentation policy allows it. Do not describe unimplemented notification adapters as available features.
### Tests
Run the full test suite.
If docs include command examples, verify that basic examples correspond to actual CLI behavior.
### Completion Criteria
- User-facing docs describe the implemented MVP accurately.
- Roadmap docs no longer masquerade as implemented behavior.
-`go test ./...` passes.
## Stage 13: MVP Release Readiness Pass
### Goal
Perform a final pre-release quality pass.
### Scope
Review:
- package boundaries against `docs/policy/architecture.md`;
- package layout against `docs/roadmap/packages.md`;
- implemented contracts against `docs/roadmap/contracts.md`;
- implemented config behavior against `docs/roadmap/config.md`;
- docs against `docs/policy/documentation.md`;
- destructive operation safety;
- logs and errors for unattended operation;
- command UX;
- test coverage for core invariants.
Add any missing small tests or docs discovered during review.
Do not add new product features in this stage.
### Completion Criteria
- MVP is ready to deploy against one real producer pipeline.
- A dry-run can be performed safely against a real source and destination.