Dedicated Download Service for Critical Run Artifacts
Status: Open (2026-06-19) - implementation complete; production rollout pending Timezone: UTC
Overview
Critical WEPPcloud archive downloads historically shared the browse service with interactive directory browsing, previews, parquet export, D-Tale handoff, and crawler-facing route families. This package separates exact archive delivery into a dedicated download service so large downloads can be isolated, range/resume friendly, and instrumented with request-level evidence. Production hosts still need cutover/smoke evidence before the remediation is considered fully closed.
The split does not remove shared NFS/run-root risk. It reduces other common-cause vectors so download reliability can be measured and hardened separately from browse UI pressure.
Objectives
- Create a dedicated download microservice for exact run artifact delivery, starting with archive ZIP downloads at
/weppcloud/runs/{runid}/{config}/download/archives/*.zip. - Preserve canonical browse authorization, public-run behavior, root-only path restrictions, and path traversal protections.
- Support range/resume-friendly HTTP behavior for archive downloads, including
HEAD,Accept-Ranges,206 Partial Content,416 Range Not Satisfiable,Content-Length, andContent-Range. - Add structured download logs with request id, run id, config, route family, sanitized path category, basename, file size, range start/end, bytes sent or best available byte count, duration, status, client abort/error reason when known, client address, and user agent.
- Wire Docker and Caddy so the exact archive route can be cut over independently of
browse, with its own health check, worker/process model, timeouts, and concurrency controls. - Add focused automated tests and an operator validation checklist that prove full, range, missing-file, unauthorized, traversal, and proxy-routed archive downloads behave correctly.
Scope
Included
- New or extracted download service code under
wepppy/microservices/, using the existing Starlette/gunicorn/uvicorn style already used bybrowse. - Shared auth/path resolution helpers only where needed to preserve current behavior without broad browse refactoring.
- Caddy and Docker Compose changes in
docker/docker-compose.dev.yml,docker/docker-compose.prod.yml,docker/docker-compose.prod.wepp1.yml,docker/caddy/Caddyfile, anddocker/caddy/Caddyfile.wepp1. - Focused unit/integration tests for service behavior and route wiring.
- Documentation updates for
wepppy/microservices/browse/README.md, any new download service README, and package closeout artifacts. - Production rollout notes for wepp1, including a rollback path that returns archive routes to
browse.
Explicitly Out of Scope
- Removing NFS as a shared dependency or moving archives to object storage.
- Rewriting the browse UI, D-Tale bridge, parquet preview/export implementation, or manifest listing system.
- Migrating all
/download/*families in one step. Culvert, batch, parquet-to-CSV, filtered CSV, and aria2c flows remain onbrowseuntil separately scoped. - Changing user-visible download URLs.
- Adding new third-party serving frameworks unless the dependency evaluation standard is completed first.
Implementation Fidelity and Evidence
- Fidelity target: faithful extraction for archive delivery semantics.
- Authoritative source path(s):
wepppy/microservices/browse/_download.py,wepppy/microservices/browse/auth.py,wepppy/microservices/browse/security.py, anddocs/schemas/weppcloud-browse-auth-contract.md. - Cutover proof required: Docker/Caddy route evidence showing
/weppcloud/runs/{runid}/{config}/download/archives/*.zipreaches the new service while other browse route families continue to reachbrowse:9009. - Acceptance evidence type: both generated-output and fixture-only evidence. Fixture tests prove edge cases; generated evidence must include local docker/Caddy
curlprobes forHEAD, full GET, and ranged GET.
Stakeholders
- Primary: WEPPcloud operators and users downloading completed run archives.
- Reviewers: WEPPcloud maintainers responsible for browse/download and production routing.
- Security Reviewer: Required because the package changes externally reachable artifact delivery and proxy routing.
- Informed: Incident responders tracking the June 2026 wepp1 browse/download slowdown.
Success Criteria
- Archive ZIP downloads can be served by the dedicated service without changing the public URL.
-
HEAD, fullGET, valid rangeGET, and invalid rangeGETreturn correct HTTP status and headers. - Auth, public-run allowance, traversal denial, missing-file, and non-archive route behavior are covered by tests.
- Caddy routes exact archive download traffic to the new service in dev and production configuration, while browse/schema/dtale/files/gdalinfo and non-migrated downloads still route correctly.
- Download logs include bytes, duration, status, range metadata, sanitized path category, client identity fields, and abort/error classification without logging secrets or raw tokens.
- The service has independent health check, worker/process configuration, timeout posture, and documented rollback.
- Work package security review has no unresolved high or medium findings before production rollout.
- Work package QA review has no unresolved high, medium, or low findings before production rollout.
- Local Caddy
HEAD, fullGET, range, sparse-resume, and service-log smoke evidence are captured for a 2.5 GB archive. - wepp1 production cutover and live archive
HEAD/full/range smoke evidence are captured.
Parameterization ADR Gate
- Parameterization change present: no
- ADR required: no
- ADR link(s): N/A
- Decision provenance captured: yes
Reference: docs/standards/parameterization-adr-standard.md
Dependencies
Prerequisites
- Current browse auth and path-boundary contracts remain canonical.
- Docker/Caddy development stack can be used for route validation.
- Operators can provide or confirm a representative archive ZIP under
/wc1/runs/for production smoke testing.
Blocks
- Production cutover of critical run archive downloads to an isolated service.
- Follow-up work to decide whether all non-transforming downloads should move out of
browse. - Any later object-storage or non-NFS download architecture evaluation.
Related Packages
- Depends on:
docs/work-packages/20260616_browse_arrow_pandas_elimination/for browse RSS remediation context. - Related:
docs/work-packages/20260616_dtale_lazy_parquet_backend/for D-Tale pandas memory isolation context. - Related:
docs/infrastructure/incident-2026-06-16-wepp1-browse-download-slowdown.mdfor the incident record motivating this package. - Follow-up: A separate package may evaluate object storage or non-NFS archive publication if evidence shows NFS remains the dominant reliability limit.
Timeline Estimate
- Expected duration: 2-4 focused sessions.
- Complexity: Medium-High.
- Risk level: High, because this changes production download routing and authorization-sensitive file delivery.
Security Impact and Review Gate
- Security impact triage: high
- Dedicated security review required: yes
- Triage rationale: The package adds an externally reachable artifact-serving service, changes proxy routing, and reuses sensitive run-scoped authorization/path logic.
- Security review artifact:
docs/work-packages/20260619_dedicated_download_service/artifacts/20260619_security_review.md - QA review artifact:
docs/work-packages/20260619_dedicated_download_service/artifacts/20260619_qa_review.md
Hardening and Callus Softening
- Failure signature(s): Slow or timed-out archive downloads on wepp1; browse worker RSS growth previously observed around 45-49 GiB; Caddy/browser downloads lacking service-level byte/duration/abort evidence; mixed browse UI and long download load on the same worker pool.
- Related prior hardening efforts:
docs/work-packages/20260616_browse_arrow_pandas_elimination/,docs/work-packages/20260616_dtale_lazy_parquet_backend/, anddocs/infrastructure/incident-2026-06-16-wepp1-browse-download-slowdown.md. - Health signals: Stable archive download throughput under browse UI/crawler load, low download worker RSS, clear
2xx/206/4xx/5xx/abort logs, and successful browser resume/range probes. - Danger signals: Duplicate auth logic drifting from browse, route shadowing that breaks non-archive downloads, logs containing tokens or sensitive full paths, or a new service that still lacks byte/duration evidence.
- Observation window: 14 days after production cutover.
- Temporary calluses introduced: Route-specific Caddy matcher and independent service knobs, owner WEPPcloud operators, review after the observation window.
- Callus softening hypothesis: If the dedicated service proves stable and route matching is clean, archive-specific Caddy exceptions can be simplified or generalized only after tests and security review cover the broader route family.
References
wepppy/microservices/browse/README.md- Current browse service contract and dedicated download service boundary.wepppy/microservices/browse/_download.py- Current download route implementation and archive serving behavior.wepppy/microservices/browse/auth.py- Browse authorization helpers that must remain authoritative or be shared safely.wepppy/microservices/browse/security.py- Path-boundary helpers for run-scoped files.docs/schemas/weppcloud-browse-auth-contract.md- Canonical browse/download authorization contract.docker/docker-compose.dev.yml- Development service wiring.docker/docker-compose.prod.yml- Production service wiring.docker/docker-compose.prod.wepp1.yml- wepp1 production override.docker/caddy/Caddyfile- Default Caddy route wiring.docker/caddy/Caddyfile.wepp1- wepp1 Caddy route wiring.docs/infrastructure/incident-2026-06-16-wepp1-browse-download-slowdown.md- Incident timeline and operational evidence.
Deliverables
- Dedicated download service code and tests in
wepppy/microservices/download/andtests/microservices/test_dedicated_download_service.py. - Docker Compose and Caddy route updates in dev, prod, and wepp1 configuration files.
- New service README at
wepppy/microservices/download/README.mdplus updated browse and microservices READMEs. - QA and security review artifacts with implementation findings resolved.
- Local config validation for Compose and Caddy.
- Production validation notes with full/range/HEAD smoke evidence remain pending until wepp1 cutover.
Follow-up Work
- Decide whether other exact non-transforming downloads should migrate after archive cutover evidence.
- Evaluate object storage, local archive cache, or other non-NFS approaches if NFS remains a dominant bottleneck.
- Revisit bot/rate-limit policies only after critical download service telemetry shows request classes clearly.