## Context The existing artifact transfer channel handles run-to-platform upload with chunk/resume semantics and platform-owned artifact metadata. Browser consumers need the opposite user-facing surface: list and download available artifacts from server/job/plugin contexts through platform authorization. The browser should receive safe references and platform routes, not raw storage locations. ## Goals / Non-Goals **Goals:** - Add platform artifact download metadata and content routes for authorized browser users and plugin bridge actions. - Support bounded chunk/range reads or download responses that can report progress in the frontend. - Enforce artifact owner scope, user/server access, plugin permissions, availability state, and response redaction. - Add frontend API client methods and UI controls for artifact download/open from operational pages. - Add plugin bridge artifact helpers that return safe references rather than raw paths or storage credentials. - Verify with tests and browser walkthrough. **Non-Goals:** - No external object storage backend or presigned raw storage URLs. - No browser direct access to run endpoints, host filesystem paths, sockets, or storage backend credentials. - No artifact upload from browser unless a future change explicitly adds it. - No archive extraction, malware scanning, lifecycle cleanup, billing, cloud host sales, or unrelated marketplace behavior. ## Decisions ### Decision 1: Browser downloads go through platform routes The platform exposes artifact content through authorized API routes. Any download URL or token is a platform route scoped to the requesting user/session and artifact, not a raw backend location. Alternative considered: return storage adapter paths or presigned backend URLs. Rejected because no storage backend exists yet and raw locations can leak internals. ### Decision 2: Artifact availability is required for download Only artifacts in an available/complete state can be downloaded by browser consumers. Uploading, failed, missing, or unauthorized artifacts return stable safe errors. Alternative considered: stream partial uploading artifacts. Rejected because partial reads complicate integrity and user expectations. ### Decision 3: Plugin bridge receives artifact references, not bytes by default Bridge actions can request artifact metadata/open/download references. Large byte transfer stays in platform/browser client code, preserving bounded payloads across plugin bridge messages. Alternative considered: pass base64 artifact bytes through plugin page bridge messages. Rejected because large payloads can block UI and violate channel separation. ## Risks / Trade-offs - [Risk] In-memory artifact payload storage limits realistic download size. Mitigation: keep interfaces ready for storage adapters and test bounded content behavior. - [Risk] Browser downloads can expose sensitive server files if ownership checks are weak. Mitigation: validate artifact owner scope, user/server access, plugin permissions, and availability before content reads. - [Risk] Plugin pages may expect direct bytes. Mitigation: provide safe artifact references and frontend host download helpers. ## Migration Plan 1. Add platform artifact download contracts, validators, service methods, routes, and docs. 2. Add frontend API client, UI controls, bridge host helpers, and tests. 3. Add plugin SDK artifact reference helpers/tests if needed. 4. Run browser walkthrough, structure check, and strict OpenSpec validation. Rollback removes browser download routes/client integration and this change's artifacts before plugin pages depend on them. ## Open Questions - Which durable artifact storage adapter should back downloads after in-memory transfer state is replaced? - Whether browser upload should be a separate future transfer direction.