Field Notebook
A quiet environmental journal that validates typed field observations with Pydantic and persists them through an asynchronous FastAPI-to-Trestle boundary.
What it proves
Typed observations
Pydantic bounds required text, categories, conditions, notes and temperatures before a record reaches Trestle.
Async public API calls
FastAPI exposes two domain endpoints while an httpx client holds the credential and calls one fixed collection.
Docs included
The application exposes interactive domain API documentation at /api/docs without exposing Trestle's administrative API.
Run the example
git clone https://github.com/trestle-cv/dogfood-field-notebook
cd dogfood-field-notebook
python3 -m venv .venv
. .venv/bin/activate
python -m pip install -e '.[dev]'
export TRESTLE_URL=http://127.0.0.1:7333
export TRESTLE_ADMIN_EMAIL=admin@example.test
export TRESTLE_ADMIN_PASSWORD='choose-a-real-password'
python scripts/bootstrap.py
nift build
uvicorn app.main:app --reload --host 127.0.0.1 --port 4182Start Trestle first, then open http://127.0.0.1:4182. Bootstrap creates fn_observations, applies service-only rules and saves its copy-once credential in .field-notebook.json with owner-only permissions.
Observation contract
Each entry has a title and location, a flora, fauna, weather or terrain category, a stable, watch or critical condition, bounded notes and an optional temperature between -80 and 80 degrees. The browser can list and create observations through the domain API; it never supplies an upstream path.
GET /api/observations
POST /api/observations
GET /api/docsArchitecture and authority
browser -> FastAPI domain endpoints -> Trestle HTTP API -> configured Trestle storeFastAPI owns the narrow browser boundary and Trestle owns schema enforcement and persistence. Static presentation remains independently rebuildable with Nift, and the service credential never enters generated HTML or browser responses.
Useful checks
pytest
python -m compileall -q app scripts