Private, expiring artifact hosting for AI agents. Upload via API or MCP; links die on their own.
One address for any MCP client. You sign in at veilfile.com once, after adding it.
Not assessed yet.
Odel charges nothing per call. The publisher may charge for its own service.
| Access to | Read | Change |
|---|---|---|
| Mcp | Not stated: mcp:use | |
From the sign-in at veilfile.com, as the endpoint publishes it. You approve it there.
Odel could not list its tools without signing in.
When a coding agent in CI or a cloud session produces a screenshot, log bundle, or HAR file for review, it needs a private URL to put it at — not a public repo. Veilfile is the sanctioned place: upload via API key (or MCP), get back an unguessable, expiring URL. Uploads are scanned for secret shapes and flagged (never blocked, never logged).
POST /api/v1/artifacts (multipart, Authorization: Bearer vlf_…) →
{id, url, expires_at, size_bytes, secret_flags[]}. GET /a/<token> serves
the file (the 256-bit token is the auth). List/revoke endpoints included.POST /mcp
(upload_artifact, list_artifacts, revoke_artifact), same vlf_ keys./app/ — API keys (raw key shown
once), usage vs plan caps, artifact table with secret-flag badges + revoke,
Stripe billing portal./ (public). Agent docs: /llms.txt, docs/API.md.See SPEC.md for the product spec.
| Plan | Price | Uploads/mo | Max TTL | API keys |
|---|---|---|---|---|
| Free | $0 | 100 | 7 days | 1 |
| Team | $4/mo | 2,000 | 90 days | 5 |
| Scale | $12/mo | 10,000 | 365 days | unlimited |
# 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
# Frontend (separate terminal; proxied /api -> :8000)
cd frontend && npm install && npm run dev # :5173
Sign up at http://localhost:8000/accounts/signup/ (or log in), open
/app/, create an API key, then:
curl -H "Authorization: Bearer vlf_..." \
-F "file=@screenshot.png" \
http://localhost:8000/api/v1/artifacts/
No secrets are committed to this repo. Copy the names below into a local
.env (gitignored) or your host's env config. Stripe stays in TEST mode
until live keys are connected.
| Variable | Required | Default | Notes |
|---|---|---|---|
DJANGO_SECRET_KEY | prod | — | Required when DJANGO_DEBUG is false |
DJANGO_DEBUG | no | False | Set True for local dev |
DJANGO_ALLOWED_HOSTS | prod | — | Comma-separated, e.g. veilfile.example.com |
DATABASE_URL | no | sqlite | Prod: Postgres URL |
DROP_BASE_URL | prod | http://localhost:8000 | Public URL; artifact links are built from it |
DROP_STORAGE | no | local | local (dev) or s3 (prod) |
DROP_LOCAL_DIR | no | backend/media/artifacts | Local storage root |
AWS_S3_ENDPOINT_URL | prod (s3) | — | R2 endpoint, e.g. https://<acct>.r2.cloudflarestorage.com |
AWS_S3_BUCKET | prod (s3) | — | R2 bucket name |
AWS_ACCESS_KEY_ID | prod (s3) | — | R2 API token (access key) |
AWS_SECRET_ACCESS_KEY | prod (s3) | — | R2 API token (secret) |
STRIPE_SECRET_KEY | billing | — | Test-mode secret key (sk_test_…) |
STRIPE_WEBHOOK_SECRET | billing | — | Webhook signing secret (whsec_…) |
STRIPE_PRICE_TEAM | billing | — | Price ID for the $4/mo Team plan (tax-inclusive) |
STRIPE_PRICE_SCALE | billing | — | Price ID for the $12/mo Scale plan (tax-inclusive) |
PORT | prod | 8000 | Set by the host (Render) |
Without Stripe vars, checkout/portal return 503 billing_not_configured and the
dashboard shows a friendly note; everything else works.
cd backend && DJANGO_DEBUG=True DJANGO_SECRET_KEY=dev-only-key \
../venv/bin/python manage.py test
# 73 tests: drop_core (34) + drop_billing (17) + drop_mcp (22)
cd frontend && npm run build # must succeed; assets resolve under /static/
python backend/manage.py sweep_expired
deletes expired artifacts (files + rows). Idempotent.DROP_STORAGE=s3 (Cloudflare R2).docs/REGISTRIES.md.backend/
config/ Django settings/URLs (env-driven)
drop_core/ Workspace, APIKey (vlf_), Artifact, plans, storage,
secret scan, agent API, key mgmt, sweeper
drop_billing/ Stripe checkout/portal/webhook (live, tax-inclusive, Managed Payments)
drop_mcp/ Streamable HTTP MCP server (POST /mcp)
templates/ login/logout/signup pages
frontend/ React + Vite (base: '/static/'); / landing, /app/ dashboard
docs/ API.md, llms.txt (served at /llms.txt), REGISTRIES.md
Dockerfile multi-stage node -> python build, WhiteNoise + gunicorn
render.yaml Render deploy blueprint
render.yaml); set env vars incl. DROP_BASE_URL.https://<host>/api/v1/billing/webhook;
set STRIPE_WEBHOOK_SECRET.python backend/manage.py sweep_expired.docs/REGISTRIES.md.