File download (S3 signed URL)

Sells a one-time download. After payment, the buyer is shown a time-limited signed URL to the file in your S3-compatible bucket.

What it does

When an order is paid, the glue uses @aws-sdk/s3-request-presigner to generate a pre-signed GET URL with the configured expiry (default 24h) and surfaces it on the buyer's confirmation page + customer portal. The same URL is sent via the entitlement.applied webhook payload.

Prerequisites

Step-by-step (MinIO, default)

  1. After install, open https://<your-domain>:9001 (MinIO console).
  2. Sign in with MINIO_ROOT_USER / MINIO_ROOT_PASSWORD from .env.
  3. Bucket openbitum-files already exists. Upload your file (drag and drop) — say pdfs/my-book.pdf.
  4. In the dashboard, add an entitlement of type File download to your product:
    • S3 key: pdfs/my-book.pdf
    • Expiry seconds: 86400 (24 h)

Step-by-step (AWS S3)

  1. Create a bucket with public access blocked and CORS allowing your domain.

  2. Create an IAM user with s3:GetObject and s3:PutObject on the bucket.

  3. Override env vars (post-MVP we'll surface these in the dashboard; for now edit .env directly):

    S3_ENDPOINT=https://s3.eu-west-1.amazonaws.com
    S3_REGION=eu-west-1
    S3_BUCKET=openbitum-files
    S3_ACCESS_KEY_ID=AKIA...
    S3_SECRET_ACCESS_KEY=...
    
  4. Restart the glue: docker compose up -d glue.

Troubleshooting

| Symptom | Likely cause | |---|---| | 403 SignatureDoesNotMatch | clock skew on host (run timedatectl) or wrong secret | | 403 AccessDenied | IAM policy missing s3:GetObject on the key | | 404 NoSuchKey | wrong S3 key spelling on the entitlement | | Link works for buyer but caches in browser | the signed URL is one-time-visible by design; ask the buyer to keep the tab open until download completes |

Coming after MVP launch

Single-use download tokens (download counter), client-side encrypted files with keys held in glue, R2/Backblaze docs.