Add a feature roadmap and implementation plan to refactor configuration for distributor output paths
This commit is contained in:
126
docs/roadmap/distributor-paths.md
Normal file
126
docs/roadmap/distributor-paths.md
Normal file
@@ -0,0 +1,126 @@
|
||||
# Distributor Report Paths Roadmap
|
||||
|
||||
## Purpose
|
||||
|
||||
This roadmap defines the target behavior for naming Markdown reports inside
|
||||
distributor source bundles.
|
||||
|
||||
Weatherreporter currently uses one application-level
|
||||
`notify.distributor.report_path_templates` list for every report type. That
|
||||
model is too coarse for the intended output layout because different reports
|
||||
need different archive paths, latest paths, and report-specific aliases.
|
||||
|
||||
## Locked Decisions
|
||||
|
||||
- Remove `notify.distributor.report_path_templates`; do not keep a legacy
|
||||
fallback or compatibility alias.
|
||||
- Report definitions own canonical distributor output path templates.
|
||||
- Configuration may override distributor output path templates per report.
|
||||
- The app layer resolves report-specific distributor bundle paths before
|
||||
calling the distributor adapter.
|
||||
- The distributor adapter continues to receive explicit source-to-bundle file
|
||||
mappings and does not choose report types, render templates, scan
|
||||
workspaces, or apply report routing policy.
|
||||
- Managed Markdown report files remain the only distributor upload sources.
|
||||
Optional local output copies are not uploaded.
|
||||
- Batch distributor uploads, when enabled, use the same report-specific bundle
|
||||
path resolver for each included report.
|
||||
- Non-roadmap documentation must not describe this behavior until it is
|
||||
implemented.
|
||||
|
||||
## Target Configuration Model
|
||||
|
||||
The global path template list is removed from `notify.distributor`:
|
||||
|
||||
```yaml
|
||||
notify:
|
||||
distributor:
|
||||
enabled: false
|
||||
endpoint: https://distributor.example.com
|
||||
token_env: DISTRIBUTOR_UPLOAD_TOKEN
|
||||
timeout: 30s
|
||||
failure_policy: error
|
||||
pipeline_id_template: "weatherreporter.{report_id}"
|
||||
bundle_id_template: "weatherreporter.{location_id}.{report_id}"
|
||||
idempotency_key_template: "{bundle_id}.{run_id}"
|
||||
```
|
||||
|
||||
Per-report overrides live under `reports.<report>.distributor`:
|
||||
|
||||
```yaml
|
||||
reports:
|
||||
daily:
|
||||
distributor:
|
||||
path_templates:
|
||||
- "daily/{valid_start_date}/{run_id}.md"
|
||||
- "daily/{valid_start_date}/index.md"
|
||||
```
|
||||
|
||||
If a report override is omitted, weatherreporter uses the defaults declared by
|
||||
that report definition.
|
||||
|
||||
## Default Report Paths
|
||||
|
||||
Each generated report maps its managed Markdown source file to one or more
|
||||
bundle-relative distributor paths.
|
||||
|
||||
| Report | Default distributor paths |
|
||||
| --- | --- |
|
||||
| `hourly` | `hourly/index.md` |
|
||||
| `daily` | `daily/{valid_start_date}/{run_id}.md`; `daily/{valid_start_date}/index.md` |
|
||||
| `today` | `daily/{valid_start_date}/{run_id}.md`; `daily/{valid_start_date}/index.md`; `today/index.md` |
|
||||
| `tomorrow` | `daily/{valid_start_date}/{run_id}.md`; `daily/{valid_start_date}/index.md`; `tomorrow/index.md` |
|
||||
| `three_day` | `three-day/{valid_start_date}/{run_id}.md`; `three-day/{valid_start_date}/index.md` |
|
||||
| `weekend` | `weekend/{valid_start_date}/{run_id}.md`; `weekend/{valid_start_date}/index.md` |
|
||||
| `storm` | `storm/{storm_id}/{run_id}.md`; `storm/{storm_id}/index.md` |
|
||||
|
||||
`storm_id` is derived from the resolved storm valid period until a future
|
||||
explicit storm identity source exists.
|
||||
|
||||
## Template Values
|
||||
|
||||
Report path templates keep the existing report template values:
|
||||
|
||||
- `location_id`
|
||||
- `report_id`
|
||||
- `run_id`
|
||||
- `artifact_group`
|
||||
- `batch_output_name`
|
||||
- `valid_start_date`
|
||||
- `valid_end_date`
|
||||
- `valid_start_time`
|
||||
- `valid_end_time`
|
||||
- `valid_start_stamp`
|
||||
- `valid_end_stamp`
|
||||
- `storm_id`
|
||||
|
||||
The initial `storm_id` value is `{valid_start_stamp}-{valid_end_stamp}` in the
|
||||
effective report timezone. It is available for all single-report distributor
|
||||
templates, but it renders as an empty value for non-storm reports.
|
||||
|
||||
Rendered paths must stay unique relative paths using `/` separators. They must
|
||||
not contain backslashes, empty path segments, `.`, `..`, `manifest.json`, or
|
||||
`.distributor.json`.
|
||||
|
||||
## Intended Final State
|
||||
|
||||
`internal/report.Definition` declares distributor path defaults alongside the
|
||||
other report-owned behavior such as report ID, prompt ID, valid-period
|
||||
resolution, module composition, comparison strategy, artifact group, and output
|
||||
name.
|
||||
|
||||
`internal/config` owns per-report override loading and validation. Unknown
|
||||
fields under report config continue to fail validation or YAML unmarshalling.
|
||||
|
||||
`internal/app` resolves bundle paths through one helper used by both
|
||||
single-report notification and batch notification. That helper applies this
|
||||
precedence:
|
||||
|
||||
1. `reports.<report>.distributor.path_templates`, when explicitly configured.
|
||||
2. `report.Definition` distributor path defaults.
|
||||
|
||||
There is no third global fallback.
|
||||
|
||||
The distributor adapter API remains unchanged unless a separate adapter concern
|
||||
requires it. It should still upload the explicit file mappings passed by the
|
||||
app layer.
|
||||
Reference in New Issue
Block a user