Jasper Van bf0bf99ef4 feat: separate storage code revoke and delete
* feat(quota-store): separate revoke and delete semantics for redemption codes

- PATCH /api/admin/quota-store/storage-codes/:code accepts { revokedAt } to
  revoke a code (keeps it visible, prevents future redemptions)
- DELETE /api/admin/quota-store/storage-codes/:code removes eligible codes
- Added revokeStorageCodeSchema (shared) with zValidator on PATCH route
- Fixed revokeStorageRedemptionCode API fn to use PATCH with revokedAt payload
- Added deleteStorageRedemptionCode API fn using DELETE
- UI: separate Revoke and Delete buttons per code row with distinct disabled rules
  - Revoke disabled when already revoked or fully redeemed
  - Delete disabled when any redemptions exist (usesCount > 0)
- Updated confirmation copy to describe product outcome, not technical action
- i18n: added delete keys in en.json and zh.json; updated revokeConfirm copy
- Updated integration, unit, and component tests

Agent-Profile: https://agent-kanban.dev/agents/f68cfbce6456edb5
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: align storage code revoke contract

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-06 17:08:41 -04:00
2026-04-14 23:44:12 -04:00
2026-05-06 12:41:02 -04:00
2026-05-06 12:41:02 -04:00
2026-05-06 12:41:02 -04:00
2026-05-06 12:41:02 -04:00

ZPan

The open-source, S3-native file hosting platform.

CI codecov Release GitHub Release Docker Image License

Image bed, file sharing, and backup — powered by S3, deployed anywhere.

What is ZPan?

ZPan is a lightweight file hosting platform built on top of S3-compatible storage. Files upload directly from the client to S3, bypassing server bandwidth entirely.

Three scenarios, one platform:

  • Image Bed — Upload via PicGo / ShareX / API, get a URL instantly
  • File Sharing — Upload files, generate share links, distribute to anyone
  • File Backup — CLI agent syncs local directories to S3/R2

Deploy

Deploy via GitHub Actions with zero server management. Free tier covers personal use.

  1. Fork this repository
  2. In your fork, go to Settings → Secrets and variables → Actions and add:
    • CLOUDFLARE_ACCOUNT_ID — found on the Cloudflare dashboard sidebar
    • CLOUDFLARE_API_TOKEN — create one here with Workers Scripts:Edit, D1:Edit, and R2 Storage:Edit permissions (R2 scope is needed to auto-provision the avatar/logo bucket)
  3. Go to the Actions tab, select Deploy to Cloudflare Workers, and click Run workflow

After initial setup, the workflow runs automatically every time you sync your fork with the latest release.

AWS Lambda

Deploy via GitHub Actions using SAM. Lambda Function URL provides HTTPS with no API Gateway needed.

  1. Fork this repository
  2. In your fork, go to Settings → Secrets and variables → Actions and add:
    • TURSO_DATABASE_URL and TURSO_AUTH_TOKEN — from Turso (free, no credit card)
    • AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION
  3. Go to the Actions tab, select Deploy to AWS Lambda, and click Run workflow

See docs/deploy/aws-lambda.md for full setup instructions and IAM permissions.

Docker

Quick start — pull the pre-built image and bring your own S3 storage:

curl -O https://raw.githubusercontent.com/saltbo/zpan/master/deploy/docker-compose.yml
docker compose up -d

With RustFS (self-hosted S3-compatible storage, no external dependencies):

curl -O https://raw.githubusercontent.com/saltbo/zpan/master/deploy/docker-compose.rustfs.yml
docker compose -f docker-compose.rustfs.yml up -d

After startup:

  1. Open the RustFS console at http://localhost:9001 (admin / admin123) and create a bucket (e.g. zpan-bucket)
  2. Open ZPan at http://localhost:8222, register a user (first user gets admin role)
  3. Go to Admin → Storage and add the RustFS storage:
    • Endpoint: http://localhost:9000 (must be reachable from your browser, not the Docker internal hostname)
    • Bucket: the bucket name you created in step 1
    • Region: us-east-1
    • Access Key / Secret Key: admin / admin123

Important: The storage endpoint must be accessible from the client browser, since files upload directly to S3 via presigned URLs. Use http://localhost:9000 for local development, or your server's public URL for production.

Documentation

Why ZPan?

  • Zero bandwidth bottleneck — files transfer directly between client and S3
  • Zero ops option — deploy to Cloudflare Workers for free, no server needed
  • Self-host friendly — Docker deployment with any S3-compatible storage
  • Tool ecosystem — works with PicGo, ShareX, Flameshot out of the box
  • Open source — free forever for self-hosted users

v1

Looking for ZPan v1 (Go version)? See the v1 branch.

Contributing

See CONTRIBUTING.md for details.

Thank you to all the people who contributed to ZPan!

License

ZPan is under the GNU Affero General Public License v3.0. See the LICENSE file for details.

S
Description
A self-hosted cloud disk base on the cloud storage./ 一个基于云存储的网盘系统,用于自建私人网盘或企业网盘。
Readme AGPL-3.0 72 MiB
Languages
TypeScript 92.7%
Go 6.5%
JavaScript 0.5%
CSS 0.1%