An open-source agricultural operating system designed to reclaim data, land, and autonomy.
Current focus: Phase 29 β Guardian agent layer is shipped on main (
plan): global slide-out drawer, rule-assisted proposeβconfirm for alert ack/read, audit + RBAC, contextual
Ask Guardian entry points, demo seed alerts, and
OpenAPI 0.4.0.
Phase 28 β crop intelligence & Guardian depth is also
shipped(
plan).
Phase 30(Guardian change-request PR queue β config + Pi via confirm) is the natural next slice β
plan.
Pi / edge field validation(Phase 31) remains a parallel activity: real Pi or MQTT bridge with
PI_API_KEY
, base64-decode config
from GET /farms/{id}/devices
, then confirm readings and (
actuator_events
pi_client/gr33n_client.py
docs/pi-integration-guide.md
cmd/api/smoke_pi_contract_test.go
docs/workflow-guide.md
docs/farm-guardian-architecture.md
docs/mqtt-edge-operator-playbook.md
docs/farm-guardian-ollama-setup.md
docs/local-operator-bootstrap.md
docs/insert-commons-pipeline-runbook.md
docs/insert-commons-receiver-playbook.md
docs/notifications-operator-playbook.md
docs/domain-modules-operator-playbook.md
docs/mobile-distribution.md
docs/audit-events-operator-playbook.md
docs/terminology-guideline.md
docs/phase-13-operator-documentation.md
docs/phase-14-operator-documentation.md
gr33n is a modular, scalable, and decentralized farm management system built for real humans β not cloud landlords. Whether you're managing a homestead on solar or automating thousands of acres, gr33n adapts to your size, ethics, and bandwidth.
It's PostgreSQL schemas + Go APIs + Vue dashboards + Raspberry Pi clients + shared insert statements.
But more than that: it's a political stance in schema form.
"If your DNA, soil, labor, and climate data feed trillion-dollar industries β and you're not seeing a dime β that's not tech, that's extraction."
This project exists because:
- Big Ag is closing the loop on food systems, and we're cracking it back open.
- Data rights matter β even your soil and sunlight deserve consent.
- Billionaires shouldn't profit off your greenhouse or genome without giving back.
- Farmers, tinkerers, and off-gridders deserve tools that don't call home.
gr33n will never require a permanent internet connection, forced login, or hidden check-in with third-party servers. Whether you're on an island, a mountaintop, or a mesh-netted greenhouse, gr33n works where you live, without compromise.
Modularityβ Each ag domain (crops, animals, natural-farming inputs, IoT sensors) lives in its own schema. Use what you need, prune the rest. Enable modules per-farm viagr33ncore.farm_active_modules
. -
Connectivity Optionalβ Works offline, intranet-only, or online. Supports Supabase or bare-metal Postgres with TimescaleDB/PostGIS. -
Automation-Readyβ Schedule tasks, trigger actuators, run AI models β or run it all manually. Your tech, your tempo. -
Insert Commons (farm-side sender)β Per-farm opt-in in Settings;POST /farms/{id}/insert-commons/sync
buildscoarse, pseudonymous aggregates and optionally POSTs them toINSERT_COMMONS_INGEST_URL
with optionalAuthorization: Bearer <INSERT_COMMONS_SHARED_SECRET>
. Sync attempts are persisted (GET /farms/{id}/insert-commons/sync-events
) withidempotency keys,** rate limits**, and** server-side backoffafter repeated delivery failures. A separate farm audit trail**records sensitive actions (membership, opt-in, sync attempts, finance COA changes, cost exports, receipt access, and more) for owner/manager review viaGET /farms/{id}/audit-events
(see). For self-hosted pilots, an optionaldocs/audit-events-operator-playbook.md
receiver process (cmd/insert-commons-receiver
,make run-receiver
) validates payloads, enforces the shared secret, dedupes on payload hash, and stores rows in Postgres β seeand migrationdocs/insert-commons-receiver-playbook.md
db/migrations/20260417_phase13_insert_commons_receiver.sql
. Applydb/migrations/20260415_phase11_rbac_receipts_commons.sql
anddb/migrations/20260416_phase12_insert_commons_federation.sql
on existing databases.Custom clients POSTing ingest JSON themselves must use theexact documented shape (only six top-level keys, completeaggregates
children, booleanincludes_pii
) or validation returns400β see(docs/insert-commons-pipeline-runbook.md
Custom senders).
| Layer | Technology |
|---|---|
| API | Go 1.25 Β· net/http stdlib |
| Database | PostgreSQL 14+ Β· TimescaleDB Β· PostGIS |
| Query layer | sqlc (generated β do not edit internal/db/ ) |
| Frontend | Vue 3 Β· Vite Β· Pinia Β· Tailwind CSS |
| Pi client | Python 3 Β· RPi.GPIO / smbus2 |
| Auth | Supabase (hosted) / local peer auth (dev) |
| Schema | Multi-schema PostgreSQL β gr33ncore + gr33nnaturalfarming |
gr33n/
βββ scripts/
β βββ bootstrap-local.sh # Schema, migrations, npm ci, .env from example
β βββ setup-first-clone.sh # First clone (+ optional --install-system-deps)
β βββ install-system-deps-debian.sh # Debian/Ubuntu: sudo apt Postgres+Node (not Go)
β βββ install-pi-edge-deps.sh # Raspberry Pi OS: sudo apt for pi_client (+ optional Docker)
βββ cmd/api/
β βββ main.go # Entry point, DB pool, server startup
β βββ routes.go # All HTTP route registrations
β βββ cors.go # CORS middleware
βββ cmd/insert-commons-receiver/
β βββ main.go # Optional pilot ingest service for Insert Commons (`POST /v1/ingest`, `GET /v1/stats`)
βββ internal/
β βββ db/ # sqlc-generated query layer (DO NOT EDIT)
β βββ handler/
β β βββ farm/ # GET /farms/:id
β β βββ zone/ # Zones CRUD
β β βββ sensor/ # Sensors CRUD + readings endpoints
β β βββ device/ # Devices CRUD + status toggle
β β βββ task/ # Tasks list + status update
β βββ httputil/ # WriteJSON / WriteError helpers
β βββ insertcommonsreceiver/ # Optional Insert Commons ingest HTTP handler
β βββ platform/
β βββ commontypes/ # Shared enum types for sqlc
βββ db/
β βββ schema/
β β βββ gr33n-schema-v2-FINAL.sql # Full PostgreSQL schema (source of truth)
β βββ seeds/
β β βββ master_seed.sql # Demo farm: natural-farming inventory + JADAM-style inputs (v1.005)
β βββ queries/ # sqlc SQL source files
βββ ui/ # Vue 3 frontend
β βββ src/
β βββ views/ # Dashboard, Zones, Sensors, Actuators, Schedules, Inventory
β βββ stores/farm.js # Pinia store β all API state
β βββ api/index.js # Axios instance β localhost:8080
β βββ router/index.js # Vue Router
βββ pi_client/
β βββ gr33n_client.py # Sensor daemon β reads GPIO, POSTs readings to API
β βββ config.yaml # Per-node hardware mapping
β βββ gr33n.service # systemd unit for autostart
β βββ setup.sh # One-time Pi bootstrap
βββ sqlc.yaml
βββ go.mod / go.sum
βββ openapi.yaml # Full API spec (paste into editor.swagger.io for live UI)
βββ INSTALL.md
βββ ARCHITECTURE.md
βββ SECURITY.md
First time after git clone: run
(or
./scripts/setup-first-clone.sh
) β it pulls Go deps, creates
make first-clone
.env
/ ui/.env
from examples, runs to load schema and
scripts/bootstrap-local.sh
npm ci
in ui/
. On Debian/Ubuntu,
(
./scripts/setup-first-clone.sh --install-system-deps
make first-clone-install-deps
) runs first (Postgres 16 + extensions + Node 22; Go still from
sudo apt
go.dev/dl). Otherwise you must have Postgres with TimescaleDB, PostGIS, and pgvector available first (native),
oruse
for the Compose database. Step-by-step:
./scripts/setup-first-clone.sh --docker
docs/local-operator-bootstrap.md. How the database is actually defined (ignore stale ERDs):
docs/database-schema-overview.md.
Full setup in INSTALL.md. Short manual version:
git clone https://github.com/dgang0404/gr33n.git
cd gr33n
sudo -u postgres psql -c "CREATE DATABASE gr33n;"
psql -d gr33n -f db/schema/gr33n-schema-v2-FINAL.sql
psql -d gr33n -f db/seeds/master_seed.sql
cp .env.example .env # once: edit .env with DATABASE_URL, JWT_SECRET, PI_API_KEY if using auth
go run -tags dev ./cmd/api/
cd ui && npm install && npm run dev
API β http://localhost:8080
UI β http://localhost:5173
You do not need to re-clone or re-seed every time. From the repo root:
make restart-local-serve # starts Postgres (Compose), waits, sanity-checks, then API + UI
Or step by step:
make restart-local # Postgres only + db sanity report
make dev-auth-test # API + UI in separate jobs (JWT login like production)
Details: docs/local-operator-bootstrap.md. First cold
go run
after reboot can take several minutes β pre-build with go build -tags dev -o ./bin/api ./cmd/api/
if you want faster restarts.Receipt storage defaults to local disk for development:
FILE_STORAGE_BACKEND=local
FILE_STORAGE_DIR=./data/files
Production deployments can switch receipts to S3-compatible object storage by setting:
FILE_STORAGE_BACKEND=s3
S3_BUCKET=<bucket>
S3_REGION=<region>
- optional:
S3_ENDPOINT=<custom endpoint>
for MinIO / R2 / other S3-compatible providers - optional:
S3_PREFIX=<key prefix>
- optional:
S3_ACCESS_KEY_ID
andS3_SECRET_ACCESS_KEY
-
optional:
S3_USE_PATH_STYLE=true -
optional:
S3_DISABLE_HTTPS=true
for local/test endpoints only - optional:
FILE_STORAGE_SIGNED_URL_TTL_SECONDS=300
for short-lived receipt download links
To backfill existing blobs from an old local FILE_STORAGE_DIR
into the configured target backend before cutover:
go run ./cmd/filebackfill --source-dir /path/to/old/files --dry-run
go run ./cmd/filebackfill --source-dir /path/to/old/files
go run ./cmd/filebackfill --source-dir /path/to/old/files --file-type cost_receipt
The backfill preserves each attachment's existing storage_path
, so DB rows do not change. After the copy is complete, switch the API to the new FILE_STORAGE_BACKEND
and verify a few receipt downloads before removing the old local storage.
For operator guidance on receipt storage cutover plus DB/blob backup and restore, see docs/receipt-storage-cutover-runbook.md
.
Phase 12 adds an offline write queue for the Tasks workflow (create task
and advance status
):
- when offline (or on retryable network failure), task writes are queued locally
- queued items are marked in the Tasks UI
- each queued item can be retried or discarded
- queued writes auto-sync on reconnect, and manual
Sync now
is available - non-retryable server failures are shown as stale/conflict items for operator review
Install/offline notes:
- install the app from your browser for field use (PWA)
- keep one online sync checkpoint before long offline sessions
- after reconnect, verify queued writes drained before ending a shift
For Play Store / App Store / MDM distribution without replacing the PWA, use the optional Capacitor scaffold in ui/
(npm run build:cap
, cap:sync
, platform add/open). See docs/mobile-distribution.md.
Base URL: http://localhost:8080
β authoritative request/response schemas in openapi.yaml. Path placeholders use :id
, :rid
, :uid
, :iid
for readability (the server matches the same paths with {id}
style).
| Method | Path | Description |
|---|---|---|
| GET | /health |
|
| API + DB health check | ||
| POST | /auth/login |
|
| Authenticate & receive JWT | ||
| POST | /auth/register |
|
| Register a new account or set password for an invited user (existing email with no password yet) | ||
| GET | /auth/mode |
|
| Current auth mode (dev / production / auth_test) | ||
| GET | /capabilities |
|
Feature flags β {"ai_enabled": bool} . Read by the UI at startup to gate Farm Guardian / Knowledge Ask-LLM. |
Header: X-API-Key: <PI_API_KEY>
(see env configuration for the API process).
| Method | Path | Description |
|---|---|---|
| POST | /sensors/:id/readings |
|
| Pi posts a sensor reading | ||
| PATCH | /devices/:id/status |
|
| Pi heartbeat / status update | ||
| POST | /actuators/:id/events |
|
| Pi reports executed command | ||
| DELETE | /devices/:id/pending-command |
|
| Pi clears pending command after execution |
Farm API POSTs JSON to INSERT_COMMONS_INGEST_URL
; this repoβs pilot receiver (go run ./cmd/insert-commons-receiver/
or make run-receiver
) listens on INSERT_COMMONS_RECEIVER_LISTEN
(default ** :8765**) and implements:
| Method | Path | Description |
|---|---|---|
| GET | /health |
|
| Process liveness | ||
| GET | /v1/stats |
|
| Pilot aggregate counts (pseudonyms, daily ingests, retention) β same Bearer auth as ingest | ||
| POST | /v1/ingest |
|
Validate payload, optional Authorization: Bearer <INSERT_COMMONS_SHARED_SECRET> , optional Gr33n-Idempotency-Key (forwarded from farm sync), persist idempotently |
Details, migration, and retention: docs/insert-commons-receiver-playbook.md. If you build or forward JSON manually, match the farm APIβs ingest schema (no extra top-level fields; full
aggregates
; privacy.includes_pii
as JSON boolean); GET /farms/:id/insert-commons/preview
returns a valid example body β full rules in .
docs/insert-commons-pipeline-runbook.md
Header: Authorization: Bearer <JWT>
(SSE also supports ?token=
on the stream URL where documented).
Farm access: most /farms/:id/...
routes require the user to be the farm owner or a member (gr33ncore.farm_memberships
). Role caps apply per area (for example view vs edit costs, operate for field workflows, admin for farm settings and membership). Exact checks live in internal/farmauthz
and in openapi.yaml per route.
Integration tests under cmd/api/
(TestMain
in cmd/api/smoke_test.go) spin up an
httptest
server with and a real JWT login flow. They need
AUTH_MODE=auth_test
Postgres at
(schema + migrations;
DATABASE_URL
master seed recommended). Env, CI behavior, and data-dependent skips:
docs/local-operator-bootstrap.md
| Method | Path | Description |
|---|---|---|
| PATCH | /auth/password |
|
| Change password (must be logged in) | ||
| GET | /profile |
|
| Current user profile | ||
| PUT | /profile |
|
| Update current user profile | ||
| GET | /units |
|
| List all measurement units |
| Method | Path | Description |
|---|---|---|
| GET | /farms |
|
List farms; use ?user_id=<uuid> to restrict to that userβs farms (recommended for UIs). If omitted, lists all farms β use only in trusted operator contexts. |
||
| POST | /farms |
|
| Create farm | ||
| GET | /farms/:id |
|
| Farm detail (member or owner) | ||
| PUT | /farms/:id |
|
| Update farm record (admin: owner or manager) | ||
| DELETE | /farms/:id |
|
| Soft-delete farm (admin) |
| Method | Path | Description |
|---|---|---|
| GET | /farms/:id/members |
|
| List members and roles | ||
| POST | /farms/:id/members |
|
Invite or add member (email , role_in_farm , optional full_name ) |
||
| PATCH | /farms/:id/members/:uid/role |
|
Change member role (:uid = user UUID) |
||
| DELETE | /farms/:id/members/:uid |
|
| Remove member from farm |
| Method | Path | Description |
|---|---|---|
| PATCH | /farms/:id/insert-commons/opt-in |
|
| Toggle Insert Commons aggregate sharing (admin) | ||
| GET | /farms/:id/insert-commons/preview |
|
| Preview validated ingest JSON only β no sync, no history (admin) | ||
| POST | /farms/:id/insert-commons/sync |
|
Build aggregates and POST to INSERT_COMMONS_INGEST_URL when set (admin or finance) |
||
| GET | /farms/:id/insert-commons/sync-events |
|
| Paginated sync attempt history (admin or finance / anyone with cost view) | ||
| GET | /farms/:id/audit-events |
|
Sensitive-action audit log (admin only; query limit , offset ) |
| Method | Path | Description |
|---|---|---|
| GET | /farms/:id/zones |
|
| List zones for farm | ||
| GET | /zones/:id |
|
| Zone detail | ||
| POST | /farms/:id/zones |
|
| Create zone | ||
| PUT | /zones/:id |
|
| Update zone | ||
| DELETE | /zones/:id |
|
| Delete zone |
| Method | Path | Description |
|---|---|---|
| GET | /farms/:id/devices |
|
| List devices | ||
| GET | /devices/:id |
|
| Device detail | ||
| POST | /farms/:id/devices |
|
| Create device | ||
| DELETE | /devices/:id |
|
| Delete device | ||
| GET | /farms/:id/actuators |
|
| List actuators for farm | ||
| PATCH | /actuators/:id/state |
|
| Update actuator state (dashboard) | ||
| GET | /actuators/:id/events |
|
| Actuator event history |
| Method | Path | Description |
|---|---|---|
| GET | /farms/:id/sensors |
|
| List sensors | ||
| GET | /farms/:id/sensors/stream |
|
SSE live sensor readings (JWT may be passed as query token ) |
||
| GET | /sensors/:id |
|
| Sensor detail | ||
| POST | /farms/:id/sensors |
|
| Create sensor | ||
| DELETE | /sensors/:id |
|
| Delete sensor | ||
| GET | /sensors/:id/readings/latest |
|
| Latest reading | ||
| GET | /sensors/:id/readings |
|
List readings (since , until , limit , β¦) |
||
| GET | /sensors/:id/readings/stats |
|
| Aggregate stats for a time range |
| Method | Path | Description |
|---|---|---|
| GET | /farms/:id/schedules |
|
| List schedules | ||
| PATCH | /schedules/:id/active |
|
| Toggle schedule active | ||
| GET | /farms/:id/automation/runs |
|
| List automation runs for farm | ||
| GET | /schedules/:id/actuator-events |
|
| Actuator events triggered by schedule | ||
| GET | /automation/worker/health |
|
| Automation worker health |
| Method | Path | Description |
|---|---|---|
| GET | /farms/:id/tasks |
|
| List tasks | ||
| POST | /farms/:id/tasks |
|
| Create task | ||
| PATCH | /tasks/:id/status |
|
| Update task status |
| Method | Path | Description |
|---|---|---|
| GET | /farms/:id/fertigation/reservoirs |
|
| List reservoirs | ||
| POST | /farms/:id/fertigation/reservoirs |
|
| Create reservoir | ||
| PATCH | /fertigation/reservoirs/:rid |
|
| Update reservoir | ||
| DELETE | /fertigation/reservoirs/:rid |
|
| Delete reservoir | ||
| GET | /farms/:id/fertigation/ec-targets |
|
| List EC targets | ||
| POST | /farms/:id/fertigation/ec-targets |
|
| Create EC target | ||
| GET | /farms/:id/fertigation/programs |
|
| List programs | ||
| POST | /farms/:id/fertigation/programs |
|
| Create program | ||
| PATCH | /fertigation/programs/:rid |
|
| Update program | ||
| DELETE | /fertigation/programs/:rid |
|
| Delete program | ||
| GET | /farms/:id/fertigation/events |
|
List fertigation events (?crop_cycle_id= optional) |
||
| POST | /farms/:id/fertigation/events |
|
Create fertigation event (optional crop_cycle_id ) |
| Method | Path | Description |
|---|---|---|
| GET | /farms/:id/crop-cycles |
|
| List crop cycles | ||
| POST | /farms/:id/crop-cycles |
|
| Create crop cycle | ||
| GET | /crop-cycles/:id |
|
| Get crop cycle | ||
| PUT | /crop-cycles/:id |
|
| Update crop cycle | ||
| DELETE | /crop-cycles/:id |
|
| Deactivate crop cycle | ||
| PATCH | /crop-cycles/:id/stage |
|
| Update growth stage |
| Method | Path | Description |
|---|---|---|
| GET | /farms/:id/costs/summary |
|
| Cost totals (income, expenses, net) | ||
| GET | /farms/:id/costs |
|
List cost transactions (limit , offset , β¦) |
||
| GET | /farms/:id/costs/export |
|
Download CSV (format=csv or format=gl_csv ) |
||
| GET | /farms/:id/finance/coa-mappings |
|
| List COA mappings for GL export | ||
| PUT | /farms/:id/finance/coa-mappings |
|
| Save COA mapping overrides | ||
| DELETE | /farms/:id/finance/coa-mappings |
|
| Reset all COA overrides | ||
| DELETE | /farms/:id/finance/coa-mappings/:category |
|
| Reset one category override | ||
| POST | /farms/:id/costs |
|
| Create cost transaction | ||
| PUT | /costs/:id |
|
| Update cost transaction | ||
| DELETE | /costs/:id |
|
| Delete cost transaction | ||
| POST | /farms/:id/cost-receipts |
|
Upload cost receipt (multipart: file , optional cost_transaction_id ) |
||
| GET | /file-attachments/:id/content |
|
| Inline file bytes (cost receipt when linked) | ||
| GET | /file-attachments/:id/download |
|
| Presigned or proxied download URL JSON (backend-dependent) |
| Method | Path | Description |
|---|---|---|
| GET | /farms/:id/alerts |
|
| List alerts for farm | ||
| GET | /farms/:id/alerts/unread-count |
|
| Unread count | ||
| PATCH | /alerts/:id/read |
|
| Mark alert read | ||
| PATCH | /alerts/:id/acknowledge |
|
| Acknowledge alert |
AI_ENABLED=true
required; LLM_BASE_URL
LLM_MODEL
required for the chat endpoint. POST /v1/chat
returns 503 in Lite mode and 429 when rolling-window cost guards fire (CHAT_COST_MAX_TOKENS_PER_USER
/ CHAT_COST_MAX_TOKENS_PER_FARM
).
| Method | Path | Description |
|---|---|---|
| POST | /v1/chat |
|
Send a message to Farm Guardian. Optional farm_id β RAG grounding + live snapshot. Optional session_id (UUID) for multi-turn context replay. Optional "stream": true for SSE streaming. Response includes answer , grounded , citations , session_id , turn_index , prompt_tokens , completion_tokens . |
||
| GET | /v1/chat/sessions |
|
| List recent conversation sessions (up to 50, latest-first). | ||
| GET | /v1/chat/sessions/:id |
|
| Full ordered turn history for a session. | ||
| PATCH | /v1/chat/sessions/:id |
|
Rename session ({"title": "..."} , empty string clears). |
||
| DELETE | /v1/chat/sessions/:id |
|
| Delete session and all its turns. | ||
| GET | /v1/chat/usage |
|
Rolling-window token budget dashboard (per-user; optional ?farm_id= for per-farm). Settings β Guardian usage card. |
| Method | Path | Description |
|---|---|---|
| GET | /crop-cycles/:id/summary |
|
| Per-cycle fertigation + cost + yield + stage history (JSON). | ||
| GET | /crop-cycles/:id/summary.csv |
|
| Same data, flat CSV row. | ||
| GET | /farms/:id/crop-cycles/compare?ids=1,2,3 |
|
| Side-by-side compare (up to 5 cycles). | ||
| GET | /farms/:id/crop-cycles/compare.csv |
|
| Compare as CSV (one row per cycle). |
pgvector
-
embeddings required for search;
AI_ENABLED=true -
LLM configured required for answer synthesis.
| Method | Path | Description |
|---|---|---|
| POST | /farms/:id/rag/search |
|
| Semantic nearest-neighbour search over farm knowledge chunks. | ||
| POST | /farms/:id/rag/answer |
|
| Retrieve top-K chunks then synthesise an LLM answer (Lite mode: 503 for synthesis; search still works). |
| Method | Path | Description |
|---|---|---|
| GET | /farms/:id/naturalfarming/inputs |
|
| List input definitions | ||
| POST | /farms/:id/naturalfarming/inputs |
|
| Create input definition | ||
| PUT | /naturalfarming/inputs/:id |
|
| Update input definition | ||
| DELETE | /naturalfarming/inputs/:id |
|
| Delete input definition | ||
| GET | /farms/:id/naturalfarming/batches |
|
| List input batches | ||
| POST | /farms/:id/naturalfarming/batches |
|
| Create input batch | ||
| PUT | /naturalfarming/batches/:id |
|
| Update input batch | ||
| DELETE | /naturalfarming/batches/:id |
|
| Delete input batch |
| Method | Path | Description |
|---|---|---|
| GET | /farms/:id/naturalfarming/recipes |
|
| List application recipes | ||
| POST | /farms/:id/naturalfarming/recipes |
|
| Create recipe | ||
| GET | /naturalfarming/recipes/:id |
|
| Get recipe | ||
| PUT | /naturalfarming/recipes/:id |
|
| Update recipe | ||
| DELETE | /naturalfarming/recipes/:id |
|
| Delete recipe | ||
| GET | /naturalfarming/recipes/:id/components |
|
| List recipe components | ||
| POST | /naturalfarming/recipes/:id/components |
|
| Add component | ||
| DELETE | /naturalfarming/recipes/:id/components/:iid |
|
Remove component (:iid = component row id) |
The master seed loads a demo farm (farm_id = 1
, gr33n Demo Farm) with natural-farming inventory and JADAM-style input names (JMS, JLF, β¦), photoperiod schedules, fertigation events, crop cycles, and automation β verified clean against the live schema:
| Table | Rows | Contents |
|---|---|---|
farms |
||
| 1 | gr33n Demo Farm | |
zones |
||
| 3 | Veg Room, Flower Room, Outdoor Garden | |
crop_cycles |
||
| 3 | Veg canopy (18/6), Flower run (12/12), Outdoor raised beds | |
sensors |
||
| 10 | PAR, lux, temp, humidity, EC, pH, CO2, soil moisture | |
input_definitions |
||
| 15 | JMS, LAB, FPJ, FFJ, OHN, JHS, WCA, WCS, JWA, JS, JLF variants, compost tea | |
application_recipes |
||
| 14 | Soil drenches, foliar sprays, pest control, fungicide | |
recipe_components |
||
| 20 | Input-to-recipe links with dilution ratios | |
schedules |
||
| 14 | Light (24/0, 18/6, 16/8, 12/12) + watering programs per grow stage | |
automation_rules |
||
| 7 | Automated light on/off rules per grow stage |
Apply once: make seed
or psql -d gr33n -f db/seeds/master_seed.sql
.
Farm Guardian needs a RAG corpus too. The seed loads operational rows (zones, cycles, NF inputs, β¦) but does not pre-populate gr33ncore.rag_embedding_chunks
. After seeding, run ** make rag-ingest-demo** (or
for wipe + seed + ingest):
make dev-stack-fresh-rag
make rag-ingest-demo # needs EMBEDDING_API_KEY in .env; skips cleanly if unset
make dev-stack-fresh-rag
See docs/farm-guardian-architecture.md for the three knowledge layers (Llama weights + RAG corpus + live snapshot).
Smoke-test pollution: Running make test
against a long-lived dev DB accumulates junk rows. For a clean Guardian demo, use ** make dev-stack-fresh** or
. For day-to-day migration updates on an existing DB,
make dev-stack-fresh-rag
is idempotent.
make dev-stack
make help # Show all targets
make bootstrap-local # Guided DB + env + UI deps (see docs/local-operator-bootstrap.md)
make bootstrap-local-docker # Same, but start stack with docker compose
make compose-db-up # Postgres only β docker-compose db (Timescale + pgvector); pair .env DATABASE_URL with INSTALL.md Β§2 / .env.example
make dev-stack # Idempotent: migrations + seed on existing DB (auto-skips schema)
make dev-stack-fresh # Wipe Compose volume + full bootstrap + seed (clean Guardian demo)
make dev-stack-fresh-rag # Same + rag-ingest demo farm when EMBEDDING_API_KEY is set
make rag-ingest-demo # Index farm_id=1 only (skip message if no embedding key)
make local-up # dev-stack then API + UI (same as ./scripts/dev-stack.sh --serve)
make restart-local # After reboot: Compose db + wait + sanity report (no migrations)
make restart-local-serve # restart-local then API + UI (make dev-auth-test)
make check-stack # Verify DATABASE_URL + pgvector + optional API /health (see docs/local-operator-bootstrap.md)
make run # Run the API server
make run-receiver # Run optional Insert Commons receiver (see docs/insert-commons-receiver-playbook.md)
make dev # Run API + UI dev server in parallel
make ui # Run the Vue dev server
make build # Build the Go binary
make build-ui # Build the Vue frontend for production
make test # Run Go tests (-tags dev, ./...)
make lint # Run go vet (-tags dev, ./...)
make audit-openapi # OpenAPI β cmd/api/routes.go shell diff + Go parity test in cmd/api/openapi_parity_test.go
make sqlc # Regenerate sqlc Go code from SQL queries
make seed # Apply seed data to the database
make schema # Apply the schema to the database
make up # Start Docker Compose services
make down # Stop Docker Compose services
make logs # Tail Docker Compose logs
make clean # Remove build artifacts
Phase 23 / pre-merge gate (local): make test
, make lint
, make audit-openapi
, python3 -m pytest pi_client/test_gr33n_client.py pi_client/test_mqtt_telemetry_bridge.py -q
, and npm --prefix ui run build
. ** make test** expects a reachable
(see
DATABASE_URL
cmd/api
integration tests actually run.The Pi daemon runs four threads concurrently:
sensor-loopβ reads each GPIO/I2C sensor at its configured interval, POSTs toPOST /sensors/:id/readings
heartbeat-loopβ PATCHes device status every 30s so the dashboard shows "online"** schedule-loop**β pollsGET /farms/:id/devices
forpending_command
in device config JSONB, executes via GPIO, reports viaPOST /actuators/:id/events
, then clears viaDELETE /devices/:id/pending-command
flush-loopβ drains the offline SQLite queue when API becomes reachable
Configure sensors, actuators (with device_id
), and GPIO pins in pi_client/config.yaml
. Install as a systemd service with pi_client/setup.sh
so it starts automatically on boot.
Deployments: Edge-only Pis vs running Postgres + API + UI on the Pi, and how setups scale to split DB/API/UI β see . Minimal Pi OS apt packages before
docs/raspberry-pi-and-deployment-topology.md
setup.sh
: ./scripts/install-pi-edge-deps.sh
(make install-pi-edge-deps
).MCUs can publish to an on-farm MQTT broker; a bridge process subscribes and forwards to ** POST /sensors/readings/batch** using
X-API-Key
(same server PI_API_KEY
as the Pi daemon). Reference implementation: . Topics, TLS, ACLs, and tasking:
pi_client/mqtt_telemetry_bridge.py
docs/mqtt-edge-operator-playbook.md
gr33n's AI layer runs fully on your intranet β no data leaves the LAN in Full mode. Knowledge is never sent to cloud APIs.
Farm Guardian (Phase 27) is a conversational assistant powered by Llama 3.1 70B Q4 running on an on-premise GPU box via Ollama. It layers three knowledge sources:
Llama weightsβ general agricultural, scientific, and world knowledge baked in during training.** Your farm's RAG corpus**β anything you've ingested intoPOST /farms/{id}/rag/ingest
(sensor notes, crop logs, manuals, etc.) retrieved at query time via pgvector similarity search.Live farm-state snapshotβ zones, active crop cycles, and unread alerts pulled from the DB at the start of every grounded turn so answers reflectright now, not a stale index.
The AI features are gated by AI_ENABLED
(default on) and degrade gracefully: in Lite mode (no LLM configured) POST /v1/chat
returns 503 and the "Ask (LLM)" button in the Knowledge UI is disabled with an explanation. In Full mode, Guardian is available from the global slide-out drawer on any page (sidebar, TopBar β¨, right-edge tab) and at /chat
.
What Guardian does today (Phase 27β29): conversational Q&A β explain alerts, compare crop cycles, cite your RAG corpus, and read the live farm snapshot. Phase 29 adds confirmed agent actions: Guardian may propose alert acknowledge or mark read; the operator taps Confirm on an inline card (POST /v1/chat/confirm
). Nothing writes without your OK. Viewers can chat but cannot confirm. All confirmed actions log guardian_tool_executed
to the farm audit trail. Guardian does not change schedules, programs, or actuators autonomously β that scope is Phase 30 (still Confirm-only).
What comes next (Phase 30): expanded PR-queue tools (tasks, cycle stage, schedules, Pi actuator enqueue) β plan.
All AI calls remain inside your farm's intranet:
Pi clients ββHTTPSβββΆ Go API
ββββΆ Postgres + pgvector (farm data + RAG corpus)
ββββΆ Ollama (Llama 3.1 70B Q4, GPU box on intranet)
Browser ββHTTPSβββΆ Vue UI βββΆ Go API (same as Pi)
See docs/farm-guardian-architecture.md for the request flow + three-knowledge-layer breakdown,
docs/farm-guardian-ollama-setup.md
INSTALL.md
AI_*
/ LLM_*
/ CHAT_*
env vars.- AI is modular and never mandatory β
AI_ENABLED=false
produces a clean Lite deployment. - No cloud calls, no training on your data, no opt-in required for basic operation.
- Cost guards (
CHAT_COST_MAX_TOKENS_PER_USER
/_PER_FARM
) prevent runaway token usage on shared deployments.
A phase-by-phase ledger of what's live on main
. Each row links to the governing plan doc where one exists; undated rows predate the phase-plan convention.
| Phase | Focus | Status | Links |
|---|---|---|---|
| 10 | JWT smoke tests, farm-scoped write auth, fertigation β crop cycle link, costs CSV, SensorDetail UX | β Done | β |
| 11 | Farm RBAC, cost receipts + local storage, PWA shell, Insert Commons opt-in | β Done | β |
| 12 | Insert Commons federation | β Done | db/migrations/20260416_phase12_insert_commons_federation.sql |
| 13 | Platform evolution β receiver, audit/compliance, offline, finance depth, tenancy | β Done | |
planΒ·ops docplanplanplanplangr33ncore.zone_setpoints
) + rule engine integration + UIcost_transactions.crop_cycle_id
aquaponics.loops
, feed autologging, bootstrap upgradeexecutable_actions
surface + metadata.steps
backfill + ResolveProgramActions
fallbackplanGET /crop-cycles/{id}/summary
, compare, UI, CSV per plan)planΒ·Phase 2822****Worker program-tick + finalβmetadata.steps
backfill sweeprunProgramTick
dispatches executable_actions
per program, automation_runs.program_id
attribution, 20260517 sweep + per-program NOTICE log, structured fallback warning23****Stabilization sprintβ CI gates, smoke +DATABASE_URL
docs, OpenAPI parity, Pi/API key runbook, workflow + MQTT accuracy, worker monitoring docsplanΒ·exit sign-off24****RAG retrieval systemβ embeddings + farm-scoped retrieval API (+ optional LLM synthesis); builds on20.95 RAG-prepplan25****RAG operations & expansionβ ingest breadth, incremental re-embed, CI/pgvector parity, integration tests + synthesis limits, UX/docs (schema ERD text)plan26****Operator tutorial, observability, RAG scopeβ operator-guide UI, Loki/Promtail/Grafana logging overlay, RAG scope/threat-model, LLM retry/backoff, Ollama setup runbookplan27****Farm Guardian AI layerβ on-premise Llama 3.1 70B via Ollama,AI_ENABLED
/capabilities
, streaming POST /v1/chat
, multi-turn history + RAG grounding + live farm-state snapshot, session CRUD, token usage, cost guards, /chat
UI panel with session sidebar + bulk-deleteplan28****Crop intelligence & Guardian depthβ crop-cycle analytics, Guardian β cycles + alerts, token-usage dashboard, 80% budget warnings, OpenAPI 0.3.0plan29****Guardian agent layer(candidate) β tool-calling actions with confirmation, global slide-out panel, Guardian-ready bootstrapplanStabilization sprint closed on main
2026-04-18. Criterion-by-criterion table and next-phase links: .
docs/plans/phase_23_stabilization_sprint.plan.md
β Exit sign-off| Gate | Status |
|---|---|
CI matrix (make test , make lint , make audit-openapi ; pytest + UI build β see
|
β
|
OpenAPI β routes.go |
β
|
Smoke / DATABASE_URL + CI without DB |
β
Documented + TestMain behavior |
| Operator docs (workflow, MQTT, Pi auth, automation logs) | β
|
In flight / next up (priority order):
Phase 23 β stabilizationβ** done**;exit sign-off. -
Phase 24 β RAG retrievalβ vectors + farm-scoped API + optional LLM synthesis; Knowledge UI. -
Phase 25 β RAG operations & expansionβ CI parity, ingest breadth, incremental re-embed, limits/tests, docs/UX polish. -
Phase 26 β operator tutorial, observability, RAG scopeβ guide UI, Loki overlay, RAG boundary doc, LLM retry, Ollama runbook. -
Phase 27 β Farm Guardian AI layerβ streaming chat, multi-turn history, RAG grounding, live snapshot, session management, cost guards. -
Pi β API contract passβ smoke testsTestPiContract*
in: enqueuecmd/api/smoke_pi_contract_test.go
pending_command
β Pi-keyGET /farms/1/devices
βPOST /actuators/{id}/events
βDELETE
pending. -
Phase 28 β crop intelligence & Guardian depthβ crop analytics, Guardian snapshot depth, usage dashboard, OpenAPI 0.3.0. -
Phase 29 β Guardian agent layerβ proposeβconfirm alert ack/read, slide-out drawer, contextual entry points, OpenAPI 0.4.0 βplan -
Phase 30 β Guardian change requests (PR queue)β config + actuator proposals, pending inbox, zone photos / optional vision βplan -
Phase 31 β field validation & safe edgeβ Pi/breadboard loop, proves confirmed actuator PRs reach GPIO βplanΒ·enterprise topology sketch -
Deprecateβ after N deploys with zero fallback warnings, promoteprograms.metadata.steps
action_source
checks to hard errors and drop the column. - Program "run now" APIβ explicit trigger for unscheduled / ad-hoc programs. - Mobile distribution polishβ Capacitor packaging, store submission checklist.
- gr33ncore schema β users, sensors, schedules, zones, automation rules
- gr33nnaturalfarming schema β inputs, recipes, batches
- Go REST API β farms, zones, devices, sensors, tasks, readings
- Natural farming demo seed β 15 inputs, 14 recipes, full automation (JADAM-style labels)
- sqlc query layer + enum types
- Vue 3 frontend β Dashboard, Zones, Sensors, Actuators, Schedules, Settings, Inventory
- Raspberry Pi sensor client with systemd daemon
- OpenAPI spec (openapi.yaml)
- Sensor readings live on dashboard (SSE stream with JWT query param auth)
- Phase 10 β JWT smoke tests (
AUTH_MODE=auth_test
), farm-scoped write authorization, fertigation β crop cycle link, costs CSV export, SensorDetail export UX - Phase 11 β Farm RBAC (viewer / operator / finance / manager / owner), cost receipts + local
FILE_STORAGE_DIR
storage,PWA-first installable shell (manifest + SW in production builds; Capacitor still an option for store-distributed apps), Insert Commons opt-in + early sync hook, OpenAPI updates - Phase 13 β Platform evolution (receiver-side Insert Commons, audit/compliance API, offline + finance depth, tenancy experiments, optional Capacitor scaffold;
indexes plans and playbooks)docs/phase-13-operator-documentation.md
- Phase 14 β Field network & commons (MQTT/edge, insert pipeline, gr33n_inserts catalog, federation/receiver depth, FCM notifications, org governance, domain schema stubs;
,
docs/plans/phase_14_network_and_commons.plan.md
)docs/phase-14-operator-documentation.md
- Actuator control pipeline (automation worker β pending_command β Pi poll β execute β report)
- Fertigation module β reservoirs, EC targets, programs, events
- Natural farming inventory UI β input definitions & batch tracking
- Pi heartbeat loop β devices show online/offline in real time
- Docker Compose + Dockerfile for containerized deployment
- Microcontroller integrations β MQTT β HTTP bridge (
,
pi_client/mqtt_telemetry_bridge.py
); field tasking unchanged (docs/mqtt-edge-operator-playbook.md
pending_command
- Pi / bridge poll) - Data insert pipeline (Insert Commons validation, approval bundles, export β
)
docs/insert-commons-pipeline-runbook.md
-
LM Studio integration and AI scaffolds for insert-sharing
-
gr33n_inserts β commons catalog API (browse + farm import audit; )
docs/commons-catalog-operator-playbook.md -
Stub schemas
gr33ncrops
,gr33nanimals
,gr33naquaponics
(placeholder tables; enable viafarm_active_modules
β)docs/domain-modules-operator-playbook.md
- Phase 20 β automation rule engine (sensor-driven conditions, action dispatch, cooldowns, rule-driven notifications) β
plan - Phase 20.6β20.9 β stage-scoped setpoints, cost/energy nightly rollups, animal husbandry, labor auto-cost, program actions +
metadata.steps
backfill - Phase 20.95 β RAG-prep schema housekeeping for AI consumption β
plan - Phase 21 β crop cycle analytics & yield (summary, compare, UI, CSV) β
plan(superseded by Phase 28 WS1 β endpoints shipped) - Phase 22 β worker program-tick (
runProgramTick
),automation_runs.program_id
, finalmetadata.steps
backfill sweep, observable fallback warning - Phase 23 β stabilization sprint (CI, smoke, OpenAPI parity, docs, small fixes) β
planΒ·exit sign-off - Phase 24 β RAG retrieval system (vectors + farm-scoped API + optional LLM) β
plan - Phase 25 β RAG operations & expansion (ingest breadth, incremental re-embed, CI parity, limits, UX/docs) β
plan - Phase 26 β operator tutorial, observability, RAG scope (guide UI, Loki overlay, RAG boundary, LLM retry, Ollama runbook) β
plan - Phase 27 β Farm Guardian AI layer (streaming chat, multi-turn sessions, RAG grounding + live snapshot, cost guards,
/chat
UI panel) βplan - Phase 28 β crop intelligence & Guardian depth (crop analytics, Guardian β cycles/alerts, usage dashboard, OpenAPI 0.3.0) β plan - Phase 29 β Guardian agent layer (proposeβconfirm, slide-out drawer, Ask Guardian entry points, OpenAPI 0.4.0) β plan - Phase 30 β Guardian PR queue (config agent, actuator proposals, zone vision) β plan - Phase 31 β field validation & edge (Pi loop, safe actuator, recipe packs) β planΒ·enterprise sketch
- Fork this repo
- Join the insert-sharing network (coming soon in gr33n_inserts)
- Help build bridges between sensors, dashboards, and soil
- Translate docs, test offline installs, or write a better knf_notes parser
"Built for the commons."
The commons means shared knowledge, shared code, shared resilience. It's an ancient concept β like the village well or a seed bank β remixed into digital space.
gr33n lives in this tradition: Free to use, fork, and rebuild. Not fenced off behind corporate toll booths.
GNU Affero General Public License v3.0 (AGPL-3.0)
Use it. Fork it. Share it. If you run it as a service β cloud, SaaS, or otherwise β you must release your modifications back to the community. No exceptions. No toll booths.
Just don't try to put a fence around the commons.
Built by farmers, hackers, and friends. With sunlight and rage.