mirror of
https://github.com/multica-ai/multica.git
synced 2026-06-17 03:38:32 +02:00
Fix attachment download for self-hosted deployments using private S3-compatible buckets without CloudFront. Closes #3721. **Server** - New unified `GET /api/attachments/{id}/download` endpoint that picks CloudFront / S3 presign / server proxy at request time. - `ATTACHMENT_DOWNLOAD_MODE=auto|cloudfront|presign|proxy` and `ATTACHMENT_DOWNLOAD_URL_TTL` env knobs; `auto` routes Docker hostnames / localhost / private IPs through the proxy and public S3 endpoints through presign. - `Storage.PresignGet` capability; S3 implementation generates presigned GET URLs. - `attachmentToResponse` returns the unified relative endpoint instead of leaking raw unsigned S3 URLs when CloudFront is not configured. Proxy path streams via `io.Copy` with `Content-Disposition` / `Content-Length` / `Cache-Control: no-store` / `X-Content-Type-Options: nosniff`. **Clients** - CLI / Desktop / Mobile resolve relative `download_url` values against the configured API base. Desktop covers the Electron native download bridge and the media preview modal; Mobile covers `Linking.openURL`, the markdown image RN loader, and the composer's completed non-image file chip. - Mobile gains a minimal Node-environment vitest lane wired into `mobile-verify.yml`. **Docs** - `.env.example`, `docker-compose.selfhost.yml`, `SELF_HOSTING_ADVANCED.md`, and the `environment-variables` doc set updated with the new env keys and the `ATTACHMENT_DOWNLOAD_MODE=proxy` recommendation for Docker / VPC-internal object stores. **Tests** - `internal/storage`, `internal/cli`, `internal/handler` (download endpoint, mode selection, proxy header, `/content` non-regression), `cmd/server` (trusted proxy parser). - `packages/views/editor/use-download-attachment.test.tsx` and `attachment-preview-modal.test.tsx` exercise relative URL resolution + absolute pass-through. - `apps/mobile/lib/attachment-url.test.ts` covers every helper branch plus the composer non-image chip case.
67 lines
2.0 KiB
YAML
67 lines
2.0 KiB
YAML
name: Mobile Verify
|
|
|
|
# Runs lint + typecheck for apps/mobile only, parallel to the main CI
|
|
# workflow. Path-filtered so PRs that don't touch mobile (or anything
|
|
# mobile transitively depends on) pay zero cost.
|
|
#
|
|
# Path scope rationale — mobile transitively depends on:
|
|
# - apps/mobile/** — the app itself
|
|
# - packages/core/** — mobile imports types AND pure functions
|
|
# (agents, markdown, permissions, api/schemas, …),
|
|
# not only @multica/core/types
|
|
# - package.json / pnpm-lock.yaml — install graph
|
|
# - pnpm-workspace.yaml — catalog versions
|
|
# - turbo.json — turbo task pipeline
|
|
#
|
|
# Mobile's vitest suite is intentionally narrow (Node env, pure-function
|
|
# tests under apps/mobile/lib/*.test.ts — see apps/mobile/vitest.config.ts).
|
|
# RN component-level rendering is not exercised here.
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
paths:
|
|
- "apps/mobile/**"
|
|
- "packages/core/**"
|
|
- "package.json"
|
|
- "pnpm-lock.yaml"
|
|
- "pnpm-workspace.yaml"
|
|
- "turbo.json"
|
|
- ".github/workflows/mobile-verify.yml"
|
|
pull_request:
|
|
branches: [main]
|
|
paths:
|
|
- "apps/mobile/**"
|
|
- "packages/core/**"
|
|
- "package.json"
|
|
- "pnpm-lock.yaml"
|
|
- "pnpm-workspace.yaml"
|
|
- "turbo.json"
|
|
- ".github/workflows/mobile-verify.yml"
|
|
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
mobile:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v6
|
|
|
|
- name: Setup pnpm
|
|
uses: pnpm/action-setup@v4
|
|
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@v6
|
|
with:
|
|
node-version: 22
|
|
cache: pnpm
|
|
|
|
- name: Install dependencies
|
|
run: pnpm install
|
|
|
|
- name: Type check, lint, and test
|
|
run: pnpm exec turbo typecheck lint test --filter=@multica/mobile
|