关于 Veilfile
Veilfile 为 AI Agent 提供私有、限时的文件托管,可通过 API 或 MCP 上传文件并获得带过期时间的链接。它面向需要分享 CI 或云端会话产物的开发者,并可扫描文件中的疑似密钥。
主要功能
- 01上传并托管临时文件
- 02生成限时访问链接
- 03扫描疑似密钥内容
- 04列出与撤销文件
- 05提供 API、MCP 与 CLI
适用场景
- 01分享 CI 生成的截图供审阅
- 02传递日志包或 HAR 文件
- 03为 Agent 产物创建临时链接
MCP 相关
托管的 MCP 服务通过 HTTP JSON-RPC 提供上传文件、创建上传链接、列出文件和撤销文件工具,使用 API 密钥或 OAuth 令牌认证。
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://veilfile.com/mcp/claude mcp add --transport http veilfile-veilfile https://veilfile.com/mcp/{"mcpServers":{"veilfile-veilfile":{"type":"http","url":"https://veilfile.com/mcp/"}}}在 Cursor 中打开{"servers":{"veilfile-veilfile":{"type":"http","url":"https://veilfile.com/mcp/"}}}在 VS Code 中打开{"mcpServers":{"veilfile-veilfile":{"type":"http","url":"https://veilfile.com/mcp/"}}}{"mcpServers":{"veilfile-veilfile":{"serverUrl":"https://veilfile.com/mcp/"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
https://veilfile.com/mcp/需要授权工具
详细介绍
Veilfile — 面向 AI Agent 的私密、临时文件托管
当 CI 或云端会话中的编码 Agent 生成截图、日志包或 HAR 文件供人审核时,需要一个私密 URL 来存放文件,而不是放到公开仓库中。Veilfile 是指定的存放位置:通过 API 密钥(或 MCP)上传,即可获得一个不可猜测、会过期的 URL。上传内容会经过扫描,以检测类似密钥的模式并标记(只有调用方传入 on_secret=reject 时才会阻止上传;文件内容绝不会被记录)。
- API:
POST /api/v1/artifacts(multipart,Authorization: Bearer vlf_…)→{id, url, expires_at, size_bytes, secret_flags[]}。GET /a/<token>用于提供文件(256 位 token 本身就是授权凭证)。还提供列表(纯 JSON 数组)和撤销端点。 - **MCP:**托管的服务,位于
POST /mcp(基于 HTTP 的 JSON-RPC;工具包括upload_artifact、create_upload_url、list_artifacts、revoke_artifact), 使用vlf_密钥或 OAuth 令牌进行身份验证。 - **CLI:**PyPI(
cli/)和 npm(npm/)上的veilfile:login(设备流程)、logout、status、push、pull。 - **控制台:**已登录用户可访问
/app/下的页面。Django 视图与网站其他部分使用同一套页面框架:概览(用量与套餐上限对比)、文件(密钥标记说明 + 撤销)、密钥(新密钥仅显示一次)、已连接应用和账单(套餐切换与 Stripe 账单门户)。 - 落地页:
/(公开)。Agent 文档:/llms.txt、docs/API.md、/docs/。 - **在此仓库中工作的 Agent:**请阅读 AGENTS.md。
产品规格请参阅 SPEC.md。
套餐
| 套餐 | 价格 | 每月上传量 | 最大 TTL | 存储空间 | API 密钥 |
|---|---|---|---|---|---|
| Free | $0 | 100 | 7 天 | 1 GB | 1 |
| Team | $4/月 | 2,000 | 90 天 | 25 GB | 5 |
| Scale | $12/月 | 10,000 | 365 天 | 100 GB | 不限 |
权威来源是 backend/drop_core/plans.py(Stripe 价格保存在 Stripe 中,并通过
STRIPE_PRICE_* 变量配置)。如果文档或模板中写明的价格或上限不一致,
backend/drop_core/tests_fix_docs.py 会报错。
快速开始(本地开发)
# Backend
python3 -m venv venv && ./venv/bin/pip install -r backend/requirements.txt
export DJANGO_DEBUG=True DJANGO_SECRET_KEY=dev-only-key
./venv/bin/python backend/manage.py migrate
./venv/bin/python backend/manage.py createsuperuser # dashboard login
./venv/bin/python backend/manage.py runserver # :8000
在 http://localhost:8000/accounts/signup/ 注册(或登录),打开
/app/,创建 API 密钥,然后:
curl -H "Authorization: Bearer vlf_..." \
-F "[email protected]" \
http://localhost:8000/api/v1/artifacts/
环境变量
此仓库不会提交任何密钥。将下面的变量名复制到本地
.env(已加入 gitignore)或托管平台的环境配置中。生产环境中的账单功能会实际运行
(使用 sk_live_...、正式价格 ID 和 Stripe Managed Payments);仅在本地或预发布环境中使用 Stripe 沙盒/测试密钥。
| 变量 | 必填 | 默认值 | 说明 |
|---|---|---|---|
DJANGO_SECRET_KEY | 生产环境 | — | 当 DJANGO_DEBUG 为 false 时必填 |
DJANGO_DEBUG | 否 | False | 本地开发和测试时设为 True |
DJANGO_ALLOWED_HOSTS | 生产环境 | — | 以逗号分隔,例如 veilfile.com |
DJANGO_CSRF_TRUSTED_ORIGINS | 否 | 根据 DJANGO_ALLOWED_HOSTS 推导 | 以逗号分隔的来源 |
DATABASE_URL | 生产环境 | sqlite(仅限开发环境) | Postgres URL。生产环境未设置此项或使用 sqlite:// URL 时会拒绝启动,除非 DJANGO_ALLOW_SQLITE=True。用户名、密码和名称会进行百分号解码;?sslmode=... 会传递给驱动程序 |
DJANGO_ALLOW_SQLITE | 否 | — | 设为 True 可有意让生产模式在 SQLite 上运行(本地 docker run、构建镜像) |
DJANGO_CONN_MAX_AGE | 否 | 60 | 数据库持久连接的生命周期(秒) |
DROP_BASE_URL | 生产环境 | http://localhost:8000 | 公共 URL;资源链接将基于此 URL 生成 |
DROP_STORAGE | 否 | local | local(开发环境)或 s3(生产环境) |
DROP_LOCAL_DIR | 否 | backend/media/artifacts | 本地存储根目录 |
AWS_S3_ENDPOINT_URL | 生产环境(s3) | — | R2 端点,例如 https://<acct>.r2.cloudflarestorage.com |
AWS_S3_BUCKET | 生产环境(s3) | — | R2 存储桶名称 |
AWS_ACCESS_KEY_ID | 生产环境(s3) | — | R2 API 令牌(访问密钥) |
AWS_SECRET_ACCESS_KEY | 生产环境(s3) | — | R2 API 令牌(密钥) |
STRIPE_SECRET_KEY | 账单 | — | 生产环境中的实时密钥(sk_live_…) |
STRIPE_WEBHOOK_SECRET | 账单 | — | 与密钥相同的 Stripe 账户和模式中的签名密钥(whsec_…) |
STRIPE_PRICE_TEAM | 账单 | — | Team 方案(含税,每月 $4)的价格 ID |
STRIPE_PRICE_SCALE | 账单 | — | Scale 方案(含税,每月 $12)的价格 ID |
EMAIL_BACKEND | 生产环境 | console | 设置为 django.core.mail.backends.smtp.EmailBackend;未配置 SMTP 时,新用户将无法验证邮箱、生成密钥或批准 CLI 登录(veilfile.W001) |
EMAIL_HOST、EMAIL_PORT、EMAIL_USE_TLS、EMAIL_HOST_USER、EMAIL_HOST_PASSWORD | 生产环境 | — | SMTP 设置(线上服务使用 Gmail SMTP) |
DEFAULT_FROM_EMAIL | 生产环境 | — | 发件地址,例如 [email protected] |
EMAIL_TIMEOUT | 否 | 10 | SMTP 超时时间(秒) |
VEILFILE_SAFETY_MODE | 否 | off | off、log 或 enforce:对上传内容进行 SHA-256 阻止名单筛查。未设置时会报告为 veilfile.W002 |
VEILFILE_CLIENT_IP_HEADER | 否 | CF-Connecting-IP | 携带访客 IP 的标头,由 Cloudflare 设置(并覆盖)。当标头中包含有效 IP 且请求来自 Cloudflare 边缘地址时,用于速率限制;否则使用下方的 X-Forwarded-For 跳数逻辑。留空可禁用 |
VEILFILE_TRUSTED_PROXY_HOPS | 否 | 2 | 应用前方可信公共代理的跳数。当最后一个代理是 Cloudflare 边缘地址时,速率限制所用的客户端 IP 是从右侧数对应位置的 X-Forwarded-For 条目(跳过末尾的私有网络跳数)。不经过 Cloudflare 的请求会使用最后一个条目(由平台代理追加的条目)。更改前请根据实际流量确认 |
DJANGO_SECURE_HSTS_SECONDS | 否 | 31536000 | HTTPS 响应中的 HSTS max-age |
DJANGO_SECURE_HSTS_INCLUDE_SUBDOMAINS、DJANGO_SECURE_HSTS_PRELOAD | 否 | False | 仅在所有子域名都通过 HTTPS 提供服务后启用 |
PORT | 否 | 8000 | 由主机设置(Render);入口点默认使用 8000 |
WEB_CONCURRENCY | 否 | 1 | gunicorn 工作进程数(gthread) |
GUNICORN_THREADS | 否 | 4 | 每个工作进程的线程数。每个正在处理的上传都会占用内存;小型实例应调低此值 |
GUNICORN_TIMEOUT、GUNICORN_GRACEFUL_TIMEOUT | 否 | 120、30 | gunicorn 超时时间(秒) |
SKIP_MIGRATE | 否 | 未设置 | 设为 1 可在启动时跳过 migrate(与 Render 的预部署命令配合使用) |
VEILFILE_FUNNEL_RETENTION_DAYS | 否 | 365 | prune_funnel_events 保留漏斗记录的时间 |
VEILFILE_ALERT_DIR | 否 | 未设置 | 同时将 CRITICAL 安全警报写入文件的目录,供外部警报总线使用;警报始终会写入日志 |
DJANGO_TEST_ALLOW_REMOTE_DB | 否 | — | 允许 manage.py test 使用非本地数据库服务运行(CI 配合服务容器使用) |
未设置 Stripe 变量时,checkout/switch/portal 会返回 503 billing_not_configured,而控制面板会显示友好提示;其他功能均正常。 |
测试
测试需要设置 DJANGO_DEBUG=True(测试运行器不接受 False)并使用本地数据库;它还会强制使用本地存储,并移除 STRIPE_*/AWS_*。
# Backend (the count changes; run it rather than trusting a number here)
cd backend && DJANGO_DEBUG=True DJANGO_SECRET_KEY=dev-only-key \
../venv/bin/python manage.py test
../venv/bin/python manage.py makemigrations --check --dry-run # must report no changes
# CLIs
cd npm && node --test
cd cli && ../venv/bin/python -m unittest discover -s tests -t .
CI(.github/workflows/ci.yml)会运行上述所有检查,以及 manage.py check --deploy、使用生产设置的 collectstatic,还有 site-tests/ 中的浏览器检查(作业 site、site-cloth、site-ink、site-reading、site-phone、site-forms、site-catalog 和 site-dashboard;参见 AGENTS.md 中的“Site checks”),每次向 main 提交拉取请求时都会运行(未更改页面的拉取请求会跳过浏览器检查),并在每次推送到 main 时运行后端和 CLI 检查。CI 在 GitHub 托管的运行器上运行,每个作业使用一台机器,各作业并行执行(参见 AGENTS.md 中的“Where CI runs”)。
运维
- 部署: Render Docker Web 服务(提供 veilfile.com),每次提交到
main并通过 CI 检查后都会自动部署,并使用付费 Postgres。render.yaml与之对应。容器以非 root 用户运行。启动顺序(backend/entrypoint.sh):migrate --noinput(设置SKIP_MIGRATE=1时跳过)、createcachetable、后台每日清理循环,然后启动 gunicorn。 - 健康检查:
GET /healthz在执行SELECT 1后返回200 {"status":"ok"},否则返回503。将其设为 Render Health Check Path。 - 每日清理: entrypoint 循环每天运行一次
sweep_expired、clearsessions、cleartokens、prune_funnel_events、prune_email_ips(90 天后清除发送日志中的 IP)和purge_expired_cache。无需单独的 cron 作业。上传时也会触发一次小规模的延迟清理。 - TTL 清理器:
python backend/manage.py sweep_expired会删除已过期的制品(文件和记录)。可幂等执行。会打印swept=N bytes=N failed=N,如果任何存储删除失败则以非零状态码退出(这些记录会保留,供下次运行处理);可通过--limit N/--time-budget SECONDS限制单次运行。 - 孤立文件:
python backend/manage.py reconcile_storage会列出没有制品记录的已存储对象;--delete会将其删除。请手动运行,并先执行试运行:如果数据库状态异常(制品表为空、孤立对象超过 20%,或使用 R2 存储但未使用 PostgreSQL),--delete会拒绝执行;检查其打印的db=/storage=后,可传入--force强制执行。 - 账单重新同步:
python backend/manage.py sync_stripe_billing(试运行;使用--apply写入)会根据 Stripe 重建工作区套餐。Stripe 设置步骤见私有运维仓库。 - 部署检查:
manage.py check --deploy会报告veilfile.W001-W006配置错误(每个 worker 启动时也会以 ERROR 级别记录日志)。 - 本地容器:
docker run需要同时设置DATABASE_URL=sqlite:////tmp/db.sqlite3和DJANGO_ALLOW_SQLITE=True(否则生产模式会拒绝使用 SQLite);非 root 用户对/app/backend只有只读权限。 - 存储: Render 的磁盘是临时的。生产环境必须使用
DROP_STORAGE=s3(Cloudflare R2)。 - MCP 注册目录: 启动清单见
docs/REGISTRIES.md。
项目结构
backend/
config/ Django settings/URLs (env-driven)
drop_core/ Workspace, APIKey (vlf_), Artifact, plans, storage,
secret scan, agent API, key mgmt, device login, OAuth
glue, sweeper
drop_billing/ Stripe checkout/switch/portal/status/webhook (live,
tax-inclusive, Managed Payments)
drop_mcp/ MCP server (POST /mcp)
blog/, docs/ Markdown-rendered Journal posts (and their feed) and Docs pages
legal/ Terms, privacy policy, abuse reporting (Markdown)
pages/ public-page registry, sitemap, component catalog, content checks
static/ the new shell's CSS, JS, fonts and images
dashboard/ the signed-in dashboard at /app/ (views, URLs, tests)
templates/ shell.html, layouts/, chapters/ and components/, the Journal, Docs and legal pages, the form pages (sign in, device, OAuth), the dashboard and the error pages
cli/, npm/ Python and Node `veilfile` command-line clients
plugin/ Claude Code plugin (share-artifact skill)
docs/ API.md, llms.txt (served at /llms.txt), REGISTRIES.md,
superpowers/ (design specs and build plans)
site-tests/ browser checks for the new shell (CI jobs `site`, `site-cloth`, `site-ink`, `site-reading`, `site-phone`, `site-forms`, `site-catalog`, `site-dashboard`)
tools/ one-off font and image generators, run by hand
Dockerfile one Python stage, WhiteNoise + gunicorn (the site has no build step)
render.yaml Render deploy blueprint (mirrors the live service)
AGENTS.md Rules and commands for agents working on this repo
许可证与贡献
代码已公开,任何人都可以阅读并检查 Veilfile 的功能。除 cli/ 和 npm/ 中采用 MIT License 的命令行客户端外,所有权利均予保留(LICENSE)。本仓库不接受外部贡献者提交的拉取请求。欢迎提交问题;如发现安全问题,请通过仓库 Security 标签页中的“Report a vulnerability”私下报告。
上线检查清单
- 创建 Cloudflare R2 存储桶和 API 令牌(兼容 S3)。
- 创建 Stripe 产品和价格(Team $4、Scale $12,含税),并设置产品税务代码; 记下价格 ID。
- 在 Render 上部署(参见
render.yaml);设置环境变量,包括DROP_BASE_URL、DATABASE_URL和EMAIL_*SMTP 设置;将健康检查路径 设置为/healthz。 - 将 Stripe webhook 指向
https://<host>/api/v1/billing/webhook; 设置STRIPE_WEBHOOK_SECRET。 - 决定
VEILFILE_SAFETY_MODE(log或enforce)。 - 按照
docs/REGISTRIES.md列出 MCP 服务。
入口循环会每天清理过期工件;无需设置 cron 作业。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。