Architecture
How the api, worker, and web app fit together, covering ingest, proof-indexer, and treasury.
Velic is an application-layer integration on top of the Filecoin Onchain Cloud; there are no custom smart contracts. It is split into three running services plus a set of shared packages.
Services
apps/api: a Fastify HTTP API. Everything is served under/api, with session-cookie auth (a Redis-cached session table),/healthand/readyprobes, and routes for accounts, the asset catalogue, uploads, jobs, restores, reports, and team management.apps/worker: a BullMQ + Redis worker running the multi-stage ingest and restore pipelines, plus scheduled jobs.apps/web: the Vite + React web application. It talks to the real API by default (configurable viaVITE_API_URL); a Mock Service Worker double is opt-in for isolated UI work and never ships in production.
The ingest pipeline
An upload is processed as a chain of idempotent stages, each advancing the job's status in the database:
validate → metadata → thumbnails → c2pa → confirm-dek → chunk →
dataset-upload → finalize
That is: validate the encrypted envelope, extract technical metadata, grab thumbnail frames, inspect any C2PA manifest, confirm the wrapped data-key, split the ciphertext into pieces, upload them to storage as two copies and register the dataset on-chain, then finalize.
The restore pipeline
A restore runs its own stages:
locating → retrieving → verifying → reassembling → decrypting →
ready
Pieces are pulled directly from providers, each verified against its PieceCID, reassembled in order, and decrypted with the unwrapped key.
The proof-indexer
A scheduled job reads live PDP verifier state and records the proof history into a cache table that powers the dashboard and certificates. The dashboard therefore reflects what is on-chain, and shows masters with no proofs yet honestly as pending.
The treasury / operator model
Velic acts as the Filecoin Pay operator: a scheduled job funds each dataset's payment rail and keeps its prepayment buffer topped up so masters are never dropped, with settlement in USDFC. Operator transactions are signed by the configured signer backend (local keystore, AWS KMS, or Turnkey).
Treasury is built; customer billing is not
The on-chain treasury layer is built and funds dataset rails directly from the operator wallet, decoupled from any fiat source. Customer-facing billing (invoicing in USD) is not part of this build.
Live progress
Upload and restore progress is streamed to the web app over Server-Sent
Events from the job rows (GET /jobs/:id/events,
GET /restore-jobs/:id/events). A point-read seeds the first render and the
client falls back to polling if the stream cannot open.
Source of truth
- On-chain (the trustless part): dataset registration, PDP proof records, and payment-rail state.
- Off-chain (caches and UX): the web app, the asset catalogue and metadata, thumbnails, the proof-indexer's cached views, encryption-key material, and the staging bucket.