Types drive the UI form — bbox picker, date, number.
Defaults mean a job works with zero config.
category sets the default schedule & behaviour.
No params plumbing — the platform passes them in.
Categories drive behaviour
📥
ingest
Pulls external data into the catalog. Nightly by default.
🧮
preparation
Derives products from catalog data. Runs after ingest.
📊
compute
Analytics that emit results — on demand or scheduled.
Pick a category; sensible scheduling and publishing come for free.
The SDK is just environment variables
import os, json
params = json.loads(os.environ["UPROJ_PARAMS"])
bbox = params["bbox"]
# read inputs straight from object storage via GDAL
src = "/vsis3/inputs/s2-l2a/.../red.tif"
# where to write + how to call back
out_dir = os.environ["UPROJ_OUTPUT_DIR"]
api = os.environ["UPROJ_API_URL"]
token = os.environ["UPROJ_SERVICE_TOKEN"]
Params arrive as JSON — no parsing framework.
Read rasters in place from storage — no download.
A short-lived token authorizes catalog calls.
Plain Python — use whatever libraries you like.
Walkthrough — an ingest script
# 1. search the source for new scenes in the window
scenes = search(bbox, since=window_start)
# 2. mirror each asset into the catalog's storage
for s in scenes:
for asset in s.assets:
copy_to_storage(asset.url, key=object_key(s, asset))
# 3. register the scene as a catalog item
register_item(stac_item(s))
Search → mirror → register. That's ingest.
Already-mirrored scenes are skipped — re-runs are cheap.
Set a start date once to backfill; then it rolls forward nightly.
Walkthrough — a preprocessing script
# read bands in place, compute the index
red = read("/vsis3/inputs/s2-l2a/.../red.tif")
nir = read("/vsis3/inputs/s2-l2a/.../nir.tif")
ndvi = (nir - red) / (nir + red)
# write a cloud-optimized GeoTIFF + register it
write_cog(ndvi, f"{out_dir}/ndvi.tif")
register_item(stac_item("s2-ndvi", scene_id))
Reads parents from storage, writes a COG.
Publishes back into the catalog as a new product.
Same shape for any index, mask or composite you dream up.
Upload — it auto-versions
Each upload is a new immutable version; nothing in production breaks.
Wire a job, set a schedule
Pick the process, fill the form (defaults prefilled), add a cron — done.
05
The platform, hands on
Catalog — browse every input
Inputs and results in one searchable, paginated browser.
Map & analysis
Visualize any scene or result on an interactive map.
Jobs — saved configs + schedule
Each job: a process, its params, an optional cron, a run button.
Runs — every execution tracked
State, logs and the catalogued result for every run.
Secrets — encrypted, per-owner
Credentials stored encrypted, bound to a process input, never echoed back.
Operations dashboard
Containers, disk and the last runs — at a glance for the operator.
Settings — live, no restart
Tune limits, access and categories from the UI; changes apply immediately.
Users & access
Identity backed by OIDC — admins and users, real role-based access.
06
Operations & trust
Security in layers
🧱
Sandboxed runs
Locked-down containers — no privileges, capped, time-limited.
🔑
Scoped storage
Each run reaches only its own data, nothing else.
🌐
Network isolation
Runs can't touch the database or auth; egress is optional & allow-listed.
👤
Identity & RBAC
OIDC sign-in, API tokens, admin vs user — real access control.
Operate with confidence
📊
Observability
Structured logs, per-run stats, an operator dashboard.
💾
Backups
One-command database dump and a storage inventory.
⬆️
Install & update
Install and update each run as a single command — no manual steps.
07
Why uproj
Not a notebook. Not a cloud bill.
📓
vs. notebooks
Repeatable, scheduled, catalogued, multi-user — not a one-off script.
☁️
vs. cloud SaaS
On-prem and sovereign — no per-scene egress fees, your hardware.
🧩
Extensible
Any new source or analytic is just Python — same simple contract.
Where it goes next
🛡️
Tighter egress
Per-process declared egress allow-lists.
📈
Observability stack
Optional metrics + dashboards for larger deployments.
⚡
GPU compute
Heavier analytics on accelerated runtimes.
Let's build it
Your data, your servers, your analysts — in production next week.