Skip to content

System architecture

OpenSoil uses one monorepo with separately deployable applications. This keeps shared decisions and infrastructure visible without coupling runtime failures.

Internet
  └─ Route 53
      └─ Nginx + Let's Encrypt on one EC2 host
          ├─ opensoil.net      → static release + Node app on 127.0.0.1:3000
          ├─ lab.opensoil.net  → independent Node prototype on 127.0.0.1:8080
          ├─ api.opensoil.net  → API landing pages + FastAPI on 127.0.0.1:8100
          └─ docs.opensoil.net → versioned MkDocs static release

FastAPI
  ├─ versioned routes and generated OpenAPI
  ├─ canonical Pydantic models and registries
  ├─ provider adapter registry
  ├─ bounded in-memory cache
  └─ USDA SDA adapter → official USDA REST/POST service

Normalization flow

  1. FastAPI validates coordinate, provider, properties, and depth.
  2. The route resolves an adapter; it contains no provider SQL or parsing.
  3. The adapter builds a bounded provider request from allowlisted fields.
  4. A timeout, one limited retry, and cache protect the provider and caller.
  5. The original JSON enters the cache with a timestamp.
  6. The adapter maps rows into canonical observations while preserving original fields.
  7. FastAPI validates the response model and returns JSON with request/cache metadata.

The raw route stops after step 5 and places the original payload in an explicitly labeled wrapper.

API versioning

Public contracts live under /v1; health, generated OpenAPI, and the explorer are unversioned service surfaces. The project is experimental, so v1 can change with decision-log updates. Stable releases will add a documented deprecation and compatibility policy.

Database boundary

The host already runs loopback-only PostgreSQL/PostGIS for the main application. The first public adapter does not need persistent metadata, spatial joins, or durable caching, so it does not gain database credentials. A future persistent cache or area service will use a separately owned schema and least-privilege runtime role.

Provider availability

/health checks OpenSoil only. Provider records expose planned/operational state, while actual upstream failures return provider-specific errors. This avoids making routine health checks consume provider capacity or marking the application dead during a temporary government-service interruption.