# Controlled custom downloads This optional channel supplements existing package mirrors with public artifact downloads such as source archives. It is disabled by default. It is not an HTTP forward proxy, CONNECT tunnel, upload API, or private artifact service. ## Enable and authorize A super administrator opens **Custom downloads** in `/admin`, enables the channel, and grants permission to a registered user or an existing group. Registration alone grants nothing. A direct user deny overrides group grants; otherwise a direct user allow or an allowed group grants access. Removing a direct rule falls back to group permissions. Group deny grants nothing but does not override another allowed group. Existing group membership management remains under Users & groups. The user opens `/account` and creates a named, expiring **download-only token**. The token has only `download:fetch` scope. It is shown once in plain text with a copy button beside it; it cannot be revealed again after a page refresh or navigation. Only its hash is stored on the server. If creation succeeds but the list refresh fails, save the displayed token first. Retry only refreshes the list and never creates a second token. Each user can hold at most 20 active tokens, lasting 1–365 days. These tokens cannot log in or access administration APIs. Browser sessions and administrator tokens cannot authenticate download requests. Account disablement, permission changes, token expiry and revocation are checked again during transfer. Revoking a token cancels that user's active downloads; permission changes cancel active downloads so that policy takes effect promptly. The permission list identifies users by display name, username and email, and groups by name; IDs are secondary identifiers. **Revoke permission** removes that direct grant. A user may still receive access through a group; without any group grant, downloads are denied. **Remove deny** removes a direct deny and may restore access granted by a group. A group without a grant does not override a direct user grant or another group's grant; these entries use **Remove rule**. The account page lists active tokens in a table with name, purpose, expiry and revocation. **Custom downloads only** is the plain-language label for the `download:fetch` scope; it grants no sign-in or administration access. ## CLI and MCP Install a client build containing `download`. After token creation, the account page offers complete setup commands for Linux/macOS and Windows PowerShell. Copy and run the appropriate command locally; no further input is needed: ```sh printf '%s\n' 'YOUR_DOWNLOAD_TOKEN' | mirrorproxy download --base-url 'https://mirror.example.org' auth --token-stdin ``` ```powershell 'YOUR_DOWNLOAD_TOKEN' | mirrorproxy download --base-url 'https://mirror.example.org' auth --token-stdin ``` `Download credential saved for this instance.` confirms completion. The command contains the token and may be stored in terminal history; keep it local. The new client also prompts when `auth --token-stdin` is run directly in a terminal: paste the token and press Enter. Older clients wait for EOF (Ctrl-D on Unix, Ctrl-Z then Enter on Windows); the pipeline commands above work with those clients too. Never share the token in chat, Skill content, project files or shared MCP configuration. The credential is saved under `~/.mirrorproxy/credentials`, keyed by exact normalized instance origin, with mode 0600 on Unix. On Windows it inherits the user profile's ACL; do not use a shared profile directory. The `MIRRORPROXY_DOWNLOAD_TOKEN` environment variable can override the saved token for a managed local process. HTTPS is required except for loopback development. The download client refuses redirects from the MirrorProxy origin. ```sh mirrorproxy download --base-url https://mirror.example.org check https://example.org/source.tar.xz mirrorproxy download --base-url https://mirror.example.org fetch https://example.org/source.tar.xz --output source.tar.xz mirrorproxy download --base-url https://mirror.example.org auth --logout ``` Downloads refuse existing outputs and symlinks. A private temporary file is removed on failure; on success the complete file is published without overwrite using a hard link. The output filesystem must support hard links. Results show path, size and SHA-256; compare with an independently trusted upstream digest or signature. The local default file limit is 2 GiB; `--max-bytes` can lower it or raise it up to 64 GiB, still subject to the server limit. The existing MCP connection automatically exposes `check_download` and `download_file`; no second MCP server is needed. The tools load the same local credential. They never take or return tokens. `inspect_instance` reports the public `controlled_download` policy, not personal permission or quota. `check_download` issues HEAD through the server; it does not reserve quota or guarantee later success. `download_file` writes a new local file and consumes quota, and is marked as a writing, non-idempotent tool. File bodies never enter the model context. Existing Skill installations must be refreshed with setup to include this guidance; restart the Agent to refresh the MCP tool list. ## HTTP contract - `GET /api/download?url=`: streamed attachment. - `HEAD /api/download?url=...`: metadata without a file body. - `GET /api/download/check?url=...`: authenticated policy/HEAD check as JSON. - All require `Authorization: Bearer `. URL tokens are unsupported. - Only port 443 and public DNS hostnames are accepted. IP literals, credentials, fragments, private/special IPv4 and IPv6 addresses are rejected. - All DNS answers must be public. Connections pin those checked addresses and keep TLS hostname verification. Every redirect repeats URL, DNS and block checks, up to five redirects. HTTP downgrade and unsafe schemes are refused. - Requests bypass environment/configured proxies and do not inherit insecure mirror TLS settings, upstream credentials, cookies or client request headers. - A single `Range: bytes=start-end` or `bytes=start-` is supported by the HTTP endpoint when the upstream supports it. Suffix/multiple ranges are refused. The CLI performs complete downloads only. - Responses are attachments with octet-stream content type and `no-store`. Upstream cookies, HTML content types and authentication challenges are removed. - Upstream failures are sanitized; full URLs and query strings are not recorded in download statistics or application request logs. Your reverse proxy must also avoid recording URL query strings containing signed download links. ## Limits and statistics `[download]` in `config.example.toml` documents defaults: 10 GiB/file, 20 GiB/user/day (UTC), 16 instance downloads, 5 per user, 300 requests/user/minute, 30-minute deadline and a shared 100 MiB/s output rate. Downloads remain disabled by default. Existing saved policies are preserved. Config values are persisted using the existing runtime configuration mechanism. Saving download policy cancels active transfers. Existing global, user and billing-group monthly quotas also apply; the same transaction checks the budgets before each queued chunk. Bidirectional monthly billing follows the existing instance setting. Daily budgets count output bytes once. Small queued chunks may be billed even when a client disconnects. Midstream errors terminate the body and the CLI removes its partial file; HTTP status cannot change after headers have been sent. The admin panel reports request/error/denial counts, metered output and upstream body bytes by exact final hostname, user and day, with entry-host associations. There is no shared cache in this version. Header/DNS failures do not contribute body bytes; bytes already read from an upstream before an interruption are still reported. Statistics retain 90 days and contain no URL paths or query strings. Top hostname/user lists show 200 entries, details show up to 2,000 rows; totals and daily summaries include all matching records. Filter by exact entry/final hostname or user and select 1–90 days. Domain blocks match exact labels, optionally including all subdomains. They apply to entry hosts and redirect targets and cancel matching active transfers. Admin actions record actor, time and reason in the audit log. The active list also supports terminating individual downloads. Shared CDN domains may serve many projects; choose the narrowest appropriate hostname when blocking. ## Upgrade and rollback Schema v5 adds tables without changing existing users, sessions or mirror routes. No migration grants permission automatically. Back up the SQLite database before upgrading. To disable the feature, turn off downloads in the admin panel, revoke tokens if needed, and remove local credentials with `auth --logout`. Existing mirror clients and the discovery tools remain available. No release publication or production deployment is implied by enabling this feature in source.