{"slug": "open-source-agricultural-os-offline-first-agpl-grow-tent-to-500-warehouse-scale", "title": "Open-source agricultural OS,offline-first,AGPL, grow tent to 500-warehouse scale", "summary": "An open-source agricultural operating system called gr33n has shipped its Guardian agent layer and crop intelligence modules, enabling offline-first farm management from a single grow tent to 500-warehouse scale. The AGPL-licensed system uses PostgreSQL schemas, Go APIs, Vue dashboards, and Raspberry Pi clients to operate without permanent internet connections or third-party servers. The project aims to reclaim farmer data sovereignty from big agriculture and cloud landlords by providing decentralized tools that work on solar power or mesh networks.", "body_md": "An open-source agricultural operating system designed to reclaim data, land, and autonomy.\n\n**Current focus:** **Phase 29 — Guardian agent layer** is **shipped on main** (\n\n[plan](/dgang0404/gr33n/blob/main/docs/plans/phase_29_guardian_agent_layer.md)): global slide-out drawer, rule-assisted propose→confirm for alert ack/read, audit + RBAC, contextual\n\n**Ask Guardian** entry points, demo seed alerts, and\n\n**OpenAPI 0.4.0**.\n\n**Phase 28 — crop intelligence & Guardian depth** is also\n\n**shipped**(\n\n[plan](/dgang0404/gr33n/blob/main/docs/plans/phase_28_crop_intelligence_guardian_depth.md)).\n\n**Phase 30**(Guardian change-request PR queue — config + Pi via confirm) is the natural next slice —\n\n[plan](/dgang0404/gr33n/blob/main/docs/plans/phase_30_guardian_change_requests.plan.md).\n\n**Pi / edge field validation**(Phase 31) remains a parallel activity: real Pi or MQTT bridge with\n\n`PI_API_KEY`\n\n, base64-decode `config`\n\nfrom `GET /farms/{id}/devices`\n\n, then confirm readings and **(**\n\n`actuator_events`\n\n[,](/dgang0404/gr33n/blob/main/pi_client/gr33n_client.py)\n\n`pi_client/gr33n_client.py`\n\n[,](/dgang0404/gr33n/blob/main/docs/pi-integration-guide.md)\n\n`docs/pi-integration-guide.md`\n\n[). Key playbooks:](/dgang0404/gr33n/blob/main/cmd/api/smoke_pi_contract_test.go)\n\n`cmd/api/smoke_pi_contract_test.go`\n\n[,](/dgang0404/gr33n/blob/main/docs/workflow-guide.md)\n\n`docs/workflow-guide.md`\n\n[,](/dgang0404/gr33n/blob/main/docs/farm-guardian-architecture.md)\n\n`docs/farm-guardian-architecture.md`\n\n[,](/dgang0404/gr33n/blob/main/docs/mqtt-edge-operator-playbook.md)\n\n`docs/mqtt-edge-operator-playbook.md`\n\n[,](/dgang0404/gr33n/blob/main/docs/farm-guardian-ollama-setup.md)\n\n`docs/farm-guardian-ollama-setup.md`\n\n[,](/dgang0404/gr33n/blob/main/docs/local-operator-bootstrap.md)\n\n`docs/local-operator-bootstrap.md`\n\n[,](/dgang0404/gr33n/blob/main/docs/insert-commons-pipeline-runbook.md)\n\n`docs/insert-commons-pipeline-runbook.md`\n\n[,](/dgang0404/gr33n/blob/main/docs/insert-commons-receiver-playbook.md)\n\n`docs/insert-commons-receiver-playbook.md`\n\n[,](/dgang0404/gr33n/blob/main/docs/notifications-operator-playbook.md)\n\n`docs/notifications-operator-playbook.md`\n\n[,](/dgang0404/gr33n/blob/main/docs/domain-modules-operator-playbook.md)\n\n`docs/domain-modules-operator-playbook.md`\n\n[,](/dgang0404/gr33n/blob/main/docs/mobile-distribution.md)\n\n`docs/mobile-distribution.md`\n\n[,](/dgang0404/gr33n/blob/main/docs/audit-events-operator-playbook.md)\n\n`docs/audit-events-operator-playbook.md`\n\n[,](/dgang0404/gr33n/blob/main/docs/terminology-guideline.md)\n\n`docs/terminology-guideline.md`\n\n[,](/dgang0404/gr33n/blob/main/docs/phase-13-operator-documentation.md)\n\n`docs/phase-13-operator-documentation.md`\n\n[.](/dgang0404/gr33n/blob/main/docs/phase-14-operator-documentation.md)\n\n`docs/phase-14-operator-documentation.md`\n\ngr33n 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.\n\nIt's PostgreSQL schemas + Go APIs + Vue dashboards + Raspberry Pi clients + shared insert statements.\n\nBut more than that: it's a political stance in schema form.\n\n\"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.\"\n\nThis project exists because:\n\n- Big Ag is closing the loop on food systems, and we're cracking it back open.\n- Data rights matter — even your soil and sunlight deserve consent.\n- Billionaires shouldn't profit off your greenhouse or genome without giving back.\n- Farmers, tinkerers, and off-gridders deserve tools that don't call home.\n\ngr33n 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.\n\n-\n**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 via`gr33ncore.farm_active_modules`\n\n. -\n**Connectivity Optional**— Works offline, intranet-only, or online. Supports Supabase or bare-metal Postgres with TimescaleDB/PostGIS. -\n**Automation-Ready**— Schedule tasks, trigger actuators, run AI models — or run it all manually. Your tech, your tempo. -\n**Insert Commons (farm-side sender)**— Per-farm opt-in in Settings;`POST /farms/{id}/insert-commons/sync`\n\nbuilds**coarse, pseudonymous aggregates** and optionally POSTs them to`INSERT_COMMONS_INGEST_URL`\n\nwith optional`Authorization: Bearer <INSERT_COMMONS_SHARED_SECRET>`\n\n. Sync attempts are persisted (`GET /farms/{id}/insert-commons/sync-events`\n\n) with**idempotency keys**,** rate limits**, and** server-side backoff**after 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 via`GET /farms/{id}/audit-events`\n\n(see). For self-hosted pilots, an optional`docs/audit-events-operator-playbook.md`\n\n**receiver** process (`cmd/insert-commons-receiver`\n\n,`make run-receiver`\n\n) validates payloads, enforces the shared secret, dedupes on payload hash, and stores rows in Postgres — seeand migration`docs/insert-commons-receiver-playbook.md`\n\n`db/migrations/20260417_phase13_insert_commons_receiver.sql`\n\n. Apply`db/migrations/20260415_phase11_rbac_receipts_commons.sql`\n\nand`db/migrations/20260416_phase12_insert_commons_federation.sql`\n\non existing databases.**Custom clients** POSTing ingest JSON themselves must use the**exact** documented shape (only six top-level keys, complete`aggregates`\n\nchildren, boolean`includes_pii`\n\n) or validation returns**400**— see(`docs/insert-commons-pipeline-runbook.md`\n\n*Custom senders*).\n\n| Layer | Technology |\n|---|---|\n| API | Go 1.25 · `net/http` stdlib |\n| Database | PostgreSQL 14+ · TimescaleDB · PostGIS |\n| Query layer | sqlc (generated — do not edit `internal/db/` ) |\n| Frontend | Vue 3 · Vite · Pinia · Tailwind CSS |\n| Pi client | Python 3 · RPi.GPIO / smbus2 |\n| Auth | Supabase (hosted) / local peer auth (dev) |\n| Schema | Multi-schema PostgreSQL — `gr33ncore` + `gr33nnaturalfarming` |\n\n```\ngr33n/\n├── scripts/\n│   ├── bootstrap-local.sh             # Schema, migrations, npm ci, .env from example\n│   ├── setup-first-clone.sh           # First clone (+ optional --install-system-deps)\n│   ├── install-system-deps-debian.sh # Debian/Ubuntu: sudo apt Postgres+Node (not Go)\n│   └── install-pi-edge-deps.sh       # Raspberry Pi OS: sudo apt for pi_client (+ optional Docker)\n├── cmd/api/\n│   ├── main.go              # Entry point, DB pool, server startup\n│   ├── routes.go            # All HTTP route registrations\n│   └── cors.go              # CORS middleware\n├── cmd/insert-commons-receiver/\n│   └── main.go              # Optional pilot ingest service for Insert Commons (`POST /v1/ingest`, `GET /v1/stats`)\n├── internal/\n│   ├── db/                  # sqlc-generated query layer (DO NOT EDIT)\n│   ├── handler/\n│   │   ├── farm/            # GET /farms/:id\n│   │   ├── zone/            # Zones CRUD\n│   │   ├── sensor/          # Sensors CRUD + readings endpoints\n│   │   ├── device/          # Devices CRUD + status toggle\n│   │   └── task/            # Tasks list + status update\n│   ├── httputil/            # WriteJSON / WriteError helpers\n│   ├── insertcommonsreceiver/ # Optional Insert Commons ingest HTTP handler\n│   └── platform/\n│       └── commontypes/     # Shared enum types for sqlc\n├── db/\n│   ├── schema/\n│   │   └── gr33n-schema-v2-FINAL.sql   # Full PostgreSQL schema (source of truth)\n│   ├── seeds/\n│   │   └── master_seed.sql             # Demo farm: natural-farming inventory + JADAM-style inputs (v1.005)\n│   └── queries/             # sqlc SQL source files\n├── ui/                      # Vue 3 frontend\n│   └── src/\n│       ├── views/           # Dashboard, Zones, Sensors, Actuators, Schedules, Inventory\n│       ├── stores/farm.js   # Pinia store — all API state\n│       ├── api/index.js     # Axios instance → localhost:8080\n│       └── router/index.js  # Vue Router\n├── pi_client/\n│   ├── gr33n_client.py      # Sensor daemon — reads GPIO, POSTs readings to API\n│   ├── config.yaml          # Per-node hardware mapping\n│   ├── gr33n.service        # systemd unit for autostart\n│   └── setup.sh             # One-time Pi bootstrap\n├── sqlc.yaml\n├── go.mod / go.sum\n├── openapi.yaml             # Full API spec (paste into editor.swagger.io for live UI)\n├── INSTALL.md\n├── ARCHITECTURE.md\n└── SECURITY.md\n```\n\n**First time after git clone:** run\n\n**(or**\n\n`./scripts/setup-first-clone.sh`\n\n**) — it pulls Go deps, creates**\n\n`make first-clone`\n\n`.env`\n\n/ `ui/.env`\n\nfrom examples, runs **to load schema and**\n\n`scripts/bootstrap-local.sh`\n\n`npm ci`\n\nin `ui/`\n\n. On **Debian/Ubuntu**,\n\n**(**\n\n`./scripts/setup-first-clone.sh --install-system-deps`\n\n`make first-clone-install-deps`\n\n) runs **first (Postgres 16 + extensions + Node 22; Go still from**\n\n`sudo apt`\n\n[go.dev/dl](https://go.dev/dl/)). Otherwise you must have Postgres with TimescaleDB, PostGIS, and pgvector available first (native),\n\n*or*use\n\n**for the Compose database. Step-by-step:**\n\n`./scripts/setup-first-clone.sh --docker`\n\n[docs/local-operator-bootstrap.md](/dgang0404/gr33n/blob/main/docs/local-operator-bootstrap.md). How the database is actually defined (ignore stale ERDs):\n\n[docs/database-schema-overview.md](/dgang0404/gr33n/blob/main/docs/database-schema-overview.md).\n\nFull setup in [INSTALL.md](/dgang0404/gr33n/blob/main/INSTALL.md). Short manual version:\n\n```\n# 1. Clone\ngit clone https://github.com/dgang0404/gr33n.git\ncd gr33n\n\n# 2. Create and migrate the database\nsudo -u postgres psql -c \"CREATE DATABASE gr33n;\"\npsql -d gr33n -f db/schema/gr33n-schema-v2-FINAL.sql\n\n# 3. Seed demo data (natural farming + JADAM-style starter labels)\npsql -d gr33n -f db/seeds/master_seed.sql\n\n# 4. Run the API (from repo root)\ncp .env.example .env   # once: edit .env with DATABASE_URL, JWT_SECRET, PI_API_KEY if using auth\n# Or only: export DATABASE_URL=\"postgres://$(whoami)@/gr33n?host=/var/run/postgresql\"\ngo run -tags dev ./cmd/api/\n\n# 5. Run the frontend (separate terminal)\ncd ui && npm install && npm run dev\n```\n\nAPI → `http://localhost:8080`\n\nUI → `http://localhost:5173`\n\nYou do **not** need to re-clone or re-seed every time. From the repo root:\n\n```\nmake restart-local-serve   # starts Postgres (Compose), waits, sanity-checks, then API + UI\n```\n\nOr step by step:\n\n```\nmake restart-local           # Postgres only + db sanity report\nmake dev-auth-test           # API + UI in separate jobs (JWT login like production)\n```\n\nDetails: [ docs/local-operator-bootstrap.md](/dgang0404/gr33n/blob/main/docs/local-operator-bootstrap.md#after-a-reboot-same-db-volume--no-full-reinstall). First cold\n\n`go run`\n\nafter reboot can take several minutes — pre-build with `go build -tags dev -o ./bin/api ./cmd/api/`\n\nif you want faster restarts.Receipt storage defaults to local disk for development:\n\n`FILE_STORAGE_BACKEND=local`\n\n`FILE_STORAGE_DIR=./data/files`\n\nProduction deployments can switch receipts to S3-compatible object storage by setting:\n\n`FILE_STORAGE_BACKEND=s3`\n\n`S3_BUCKET=<bucket>`\n\n`S3_REGION=<region>`\n\n- optional:\n`S3_ENDPOINT=<custom endpoint>`\n\nfor MinIO / R2 / other S3-compatible providers - optional:\n`S3_PREFIX=<key prefix>`\n\n- optional:\n`S3_ACCESS_KEY_ID`\n\nand`S3_SECRET_ACCESS_KEY`\n\n- optional:\n`S3_USE_PATH_STYLE=true`\n\n- optional:\n`S3_DISABLE_HTTPS=true`\n\nfor local/test endpoints only - optional:\n`FILE_STORAGE_SIGNED_URL_TTL_SECONDS=300`\n\nfor short-lived receipt download links\n\nTo backfill existing blobs from an old local `FILE_STORAGE_DIR`\n\ninto the configured target backend before cutover:\n\n```\n# 1. Keep DATABASE_URL pointed at the live DB\n# 2. Point the target backend env vars at the new storage location\n# 3. Run a dry run first\ngo run ./cmd/filebackfill --source-dir /path/to/old/files --dry-run\n\n# 4. Then copy all attachments (or only receipts)\ngo run ./cmd/filebackfill --source-dir /path/to/old/files\ngo run ./cmd/filebackfill --source-dir /path/to/old/files --file-type cost_receipt\n```\n\nThe backfill preserves each attachment's existing `storage_path`\n\n, so DB rows do not change. After the copy is complete, switch the API to the new `FILE_STORAGE_BACKEND`\n\nand verify a few receipt downloads before removing the old local storage.\n\nFor operator guidance on receipt storage cutover plus DB/blob backup and restore, see `docs/receipt-storage-cutover-runbook.md`\n\n.\n\nPhase 12 adds an offline write queue for the Tasks workflow (`create task`\n\nand `advance status`\n\n):\n\n- when offline (or on retryable network failure), task writes are queued locally\n- queued items are marked in the Tasks UI\n- each queued item can be retried or discarded\n- queued writes auto-sync on reconnect, and manual\n`Sync now`\n\nis available - non-retryable server failures are shown as stale/conflict items for operator review\n\nInstall/offline notes:\n\n- install the app from your browser for field use (PWA)\n- keep one online sync checkpoint before long offline sessions\n- after reconnect, verify queued writes drained before ending a shift\n\nFor **Play Store / App Store / MDM** distribution without replacing the PWA, use the optional Capacitor scaffold in `ui/`\n\n(`npm run build:cap`\n\n, `cap:sync`\n\n, platform add/open). See [ docs/mobile-distribution.md](/dgang0404/gr33n/blob/main/docs/mobile-distribution.md).\n\nBase URL: `http://localhost:8080`\n\n— authoritative request/response schemas in [openapi.yaml](/dgang0404/gr33n/blob/main/openapi.yaml). Path placeholders use `:id`\n\n, `:rid`\n\n, `:uid`\n\n, `:iid`\n\nfor readability (the server matches the same paths with `{id}`\n\nstyle).\n\n| Method | Path | Description |\n|---|---|---|\n| GET | `/health` |\nAPI + DB health check |\n| POST | `/auth/login` |\nAuthenticate & receive JWT |\n| POST | `/auth/register` |\nRegister a new account or set password for an invited user (existing email with no password yet) |\n| GET | `/auth/mode` |\nCurrent auth mode (dev / production / auth_test) |\n| GET | `/capabilities` |\nFeature flags — `{\"ai_enabled\": bool}` . Read by the UI at startup to gate Farm Guardian / Knowledge Ask-LLM. |\n\nHeader: `X-API-Key: <PI_API_KEY>`\n\n(see env configuration for the API process).\n\n| Method | Path | Description |\n|---|---|---|\n| POST | `/sensors/:id/readings` |\nPi posts a sensor reading |\n| PATCH | `/devices/:id/status` |\nPi heartbeat / status update |\n| POST | `/actuators/:id/events` |\nPi reports executed command |\n| DELETE | `/devices/:id/pending-command` |\nPi clears pending command after execution |\n\nFarm API POSTs JSON to `INSERT_COMMONS_INGEST_URL`\n\n; this repo’s **pilot receiver** (`go run ./cmd/insert-commons-receiver/`\n\nor `make run-receiver`\n\n) listens on `INSERT_COMMONS_RECEIVER_LISTEN`\n\n(default ** :8765**) and implements:\n\n| Method | Path | Description |\n|---|---|---|\n| GET | `/health` |\nProcess liveness |\n| GET | `/v1/stats` |\nPilot aggregate counts (pseudonyms, daily ingests, retention) — same Bearer auth as ingest |\n| POST | `/v1/ingest` |\nValidate payload, optional `Authorization: Bearer <INSERT_COMMONS_SHARED_SECRET>` , optional `Gr33n-Idempotency-Key` (forwarded from farm sync), persist idempotently |\n\nDetails, migration, and retention: [ docs/insert-commons-receiver-playbook.md](/dgang0404/gr33n/blob/main/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\n\n`aggregates`\n\n; `privacy.includes_pii`\n\nas JSON boolean); `GET /farms/:id/insert-commons/preview`\n\nreturns a valid example body — full rules in [.](/dgang0404/gr33n/blob/main/docs/insert-commons-pipeline-runbook.md)\n\n`docs/insert-commons-pipeline-runbook.md`\n\nHeader: `Authorization: Bearer <JWT>`\n\n(SSE also supports `?token=`\n\non the stream URL where documented).\n\n**Farm access:** most `/farms/:id/...`\n\nroutes require the user to be the farm **owner** or a **member** (`gr33ncore.farm_memberships`\n\n). **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`\n\nand in [openapi.yaml](/dgang0404/gr33n/blob/main/openapi.yaml) per route.\n\nIntegration tests under `cmd/api/`\n\n(`TestMain`\n\nin [ cmd/api/smoke_test.go](/dgang0404/gr33n/blob/main/cmd/api/smoke_test.go)) spin up an\n\n`httptest`\n\nserver with **and a real JWT login flow. They need**\n\n`AUTH_MODE=auth_test`\n\n**Postgres** at\n\n**(schema + migrations;**\n\n`DATABASE_URL`\n\n**master seed** recommended). Env, CI behavior, and data-dependent skips:\n\n[.](/dgang0404/gr33n/blob/main/docs/local-operator-bootstrap.md#api-integration-smoke-tests)\n\n`docs/local-operator-bootstrap.md`\n\n| Method | Path | Description |\n|---|---|---|\n| PATCH | `/auth/password` |\nChange password (must be logged in) |\n| GET | `/profile` |\nCurrent user profile |\n| PUT | `/profile` |\nUpdate current user profile |\n| GET | `/units` |\nList all measurement units |\n\n| Method | Path | Description |\n|---|---|---|\n| GET | `/farms` |\nList 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. |\n| POST | `/farms` |\nCreate farm |\n| GET | `/farms/:id` |\nFarm detail (member or owner) |\n| PUT | `/farms/:id` |\nUpdate farm record (admin: owner or manager) |\n| DELETE | `/farms/:id` |\nSoft-delete farm (admin) |\n\n| Method | Path | Description |\n|---|---|---|\n| GET | `/farms/:id/members` |\nList members and roles |\n| POST | `/farms/:id/members` |\nInvite or add member (`email` , `role_in_farm` , optional `full_name` ) |\n| PATCH | `/farms/:id/members/:uid/role` |\nChange member role (`:uid` = user UUID) |\n| DELETE | `/farms/:id/members/:uid` |\nRemove member from farm |\n\n| Method | Path | Description |\n|---|---|---|\n| PATCH | `/farms/:id/insert-commons/opt-in` |\nToggle Insert Commons aggregate sharing (admin) |\n| GET | `/farms/:id/insert-commons/preview` |\nPreview validated ingest JSON only — no sync, no history (admin) |\n| POST | `/farms/:id/insert-commons/sync` |\nBuild aggregates and POST to `INSERT_COMMONS_INGEST_URL` when set (admin or finance) |\n| GET | `/farms/:id/insert-commons/sync-events` |\nPaginated sync attempt history (admin or finance / anyone with cost view) |\n| GET | `/farms/:id/audit-events` |\nSensitive-action audit log (admin only; query `limit` , `offset` ) |\n\n| Method | Path | Description |\n|---|---|---|\n| GET | `/farms/:id/zones` |\nList zones for farm |\n| GET | `/zones/:id` |\nZone detail |\n| POST | `/farms/:id/zones` |\nCreate zone |\n| PUT | `/zones/:id` |\nUpdate zone |\n| DELETE | `/zones/:id` |\nDelete zone |\n\n| Method | Path | Description |\n|---|---|---|\n| GET | `/farms/:id/devices` |\nList devices |\n| GET | `/devices/:id` |\nDevice detail |\n| POST | `/farms/:id/devices` |\nCreate device |\n| DELETE | `/devices/:id` |\nDelete device |\n| GET | `/farms/:id/actuators` |\nList actuators for farm |\n| PATCH | `/actuators/:id/state` |\nUpdate actuator state (dashboard) |\n| GET | `/actuators/:id/events` |\nActuator event history |\n\n| Method | Path | Description |\n|---|---|---|\n| GET | `/farms/:id/sensors` |\nList sensors |\n| GET | `/farms/:id/sensors/stream` |\nSSE live sensor readings (JWT may be passed as query `token` ) |\n| GET | `/sensors/:id` |\nSensor detail |\n| POST | `/farms/:id/sensors` |\nCreate sensor |\n| DELETE | `/sensors/:id` |\nDelete sensor |\n| GET | `/sensors/:id/readings/latest` |\nLatest reading |\n| GET | `/sensors/:id/readings` |\nList readings (`since` , `until` , `limit` , …) |\n| GET | `/sensors/:id/readings/stats` |\nAggregate stats for a time range |\n\n| Method | Path | Description |\n|---|---|---|\n| GET | `/farms/:id/schedules` |\nList schedules |\n| PATCH | `/schedules/:id/active` |\nToggle schedule active |\n| GET | `/farms/:id/automation/runs` |\nList automation runs for farm |\n| GET | `/schedules/:id/actuator-events` |\nActuator events triggered by schedule |\n| GET | `/automation/worker/health` |\nAutomation worker health |\n\n| Method | Path | Description |\n|---|---|---|\n| GET | `/farms/:id/tasks` |\nList tasks |\n| POST | `/farms/:id/tasks` |\nCreate task |\n| PATCH | `/tasks/:id/status` |\nUpdate task status |\n\n| Method | Path | Description |\n|---|---|---|\n| GET | `/farms/:id/fertigation/reservoirs` |\nList reservoirs |\n| POST | `/farms/:id/fertigation/reservoirs` |\nCreate reservoir |\n| PATCH | `/fertigation/reservoirs/:rid` |\nUpdate reservoir |\n| DELETE | `/fertigation/reservoirs/:rid` |\nDelete reservoir |\n| GET | `/farms/:id/fertigation/ec-targets` |\nList EC targets |\n| POST | `/farms/:id/fertigation/ec-targets` |\nCreate EC target |\n| GET | `/farms/:id/fertigation/programs` |\nList programs |\n| POST | `/farms/:id/fertigation/programs` |\nCreate program |\n| PATCH | `/fertigation/programs/:rid` |\nUpdate program |\n| DELETE | `/fertigation/programs/:rid` |\nDelete program |\n| GET | `/farms/:id/fertigation/events` |\nList fertigation events (`?crop_cycle_id=` optional) |\n| POST | `/farms/:id/fertigation/events` |\nCreate fertigation event (optional `crop_cycle_id` ) |\n\n| Method | Path | Description |\n|---|---|---|\n| GET | `/farms/:id/crop-cycles` |\nList crop cycles |\n| POST | `/farms/:id/crop-cycles` |\nCreate crop cycle |\n| GET | `/crop-cycles/:id` |\nGet crop cycle |\n| PUT | `/crop-cycles/:id` |\nUpdate crop cycle |\n| DELETE | `/crop-cycles/:id` |\nDeactivate crop cycle |\n| PATCH | `/crop-cycles/:id/stage` |\nUpdate growth stage |\n\n| Method | Path | Description |\n|---|---|---|\n| GET | `/farms/:id/costs/summary` |\nCost totals (income, expenses, net) |\n| GET | `/farms/:id/costs` |\nList cost transactions (`limit` , `offset` , …) |\n| GET | `/farms/:id/costs/export` |\nDownload CSV (`format=csv` or `format=gl_csv` ) |\n| GET | `/farms/:id/finance/coa-mappings` |\nList COA mappings for GL export |\n| PUT | `/farms/:id/finance/coa-mappings` |\nSave COA mapping overrides |\n| DELETE | `/farms/:id/finance/coa-mappings` |\nReset all COA overrides |\n| DELETE | `/farms/:id/finance/coa-mappings/:category` |\nReset one category override |\n| POST | `/farms/:id/costs` |\nCreate cost transaction |\n| PUT | `/costs/:id` |\nUpdate cost transaction |\n| DELETE | `/costs/:id` |\nDelete cost transaction |\n| POST | `/farms/:id/cost-receipts` |\nUpload cost receipt (multipart: `file` , optional `cost_transaction_id` ) |\n| GET | `/file-attachments/:id/content` |\nInline file bytes (cost receipt when linked) |\n| GET | `/file-attachments/:id/download` |\nPresigned or proxied download URL JSON (backend-dependent) |\n\n| Method | Path | Description |\n|---|---|---|\n| GET | `/farms/:id/alerts` |\nList alerts for farm |\n| GET | `/farms/:id/alerts/unread-count` |\nUnread count |\n| PATCH | `/alerts/:id/read` |\nMark alert read |\n| PATCH | `/alerts/:id/acknowledge` |\nAcknowledge alert |\n\n`AI_ENABLED=true`\n\nrequired; `LLM_BASE_URL`\n\n+ `LLM_MODEL`\n\nrequired for the chat endpoint. `POST /v1/chat`\n\nreturns **503** in Lite mode and **429** when rolling-window cost guards fire (`CHAT_COST_MAX_TOKENS_PER_USER`\n\n/ `CHAT_COST_MAX_TOKENS_PER_FARM`\n\n).\n\n| Method | Path | Description |\n|---|---|---|\n| POST | `/v1/chat` |\nSend 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` . |\n| GET | `/v1/chat/sessions` |\nList recent conversation sessions (up to 50, latest-first). |\n| GET | `/v1/chat/sessions/:id` |\nFull ordered turn history for a session. |\n| PATCH | `/v1/chat/sessions/:id` |\nRename session (`{\"title\": \"...\"}` , empty string clears). |\n| DELETE | `/v1/chat/sessions/:id` |\nDelete session and all its turns. |\n| GET | `/v1/chat/usage` |\nRolling-window token budget dashboard (per-user; optional `?farm_id=` for per-farm). Settings → Guardian usage card. |\n\n| Method | Path | Description |\n|---|---|---|\n| GET | `/crop-cycles/:id/summary` |\nPer-cycle fertigation + cost + yield + stage history (JSON). |\n| GET | `/crop-cycles/:id/summary.csv` |\nSame data, flat CSV row. |\n| GET | `/farms/:id/crop-cycles/compare?ids=1,2,3` |\nSide-by-side compare (up to 5 cycles). |\n| GET | `/farms/:id/crop-cycles/compare.csv` |\nCompare as CSV (one row per cycle). |\n\n`pgvector`\n\n+ embeddings required for search; `AI_ENABLED=true`\n\n+ LLM configured required for answer synthesis.\n\n| Method | Path | Description |\n|---|---|---|\n| POST | `/farms/:id/rag/search` |\nSemantic nearest-neighbour search over farm knowledge chunks. |\n| POST | `/farms/:id/rag/answer` |\nRetrieve top-K chunks then synthesise an LLM answer (Lite mode: 503 for synthesis; search still works). |\n\n| Method | Path | Description |\n|---|---|---|\n| GET | `/farms/:id/naturalfarming/inputs` |\nList input definitions |\n| POST | `/farms/:id/naturalfarming/inputs` |\nCreate input definition |\n| PUT | `/naturalfarming/inputs/:id` |\nUpdate input definition |\n| DELETE | `/naturalfarming/inputs/:id` |\nDelete input definition |\n| GET | `/farms/:id/naturalfarming/batches` |\nList input batches |\n| POST | `/farms/:id/naturalfarming/batches` |\nCreate input batch |\n| PUT | `/naturalfarming/batches/:id` |\nUpdate input batch |\n| DELETE | `/naturalfarming/batches/:id` |\nDelete input batch |\n\n| Method | Path | Description |\n|---|---|---|\n| GET | `/farms/:id/naturalfarming/recipes` |\nList application recipes |\n| POST | `/farms/:id/naturalfarming/recipes` |\nCreate recipe |\n| GET | `/naturalfarming/recipes/:id` |\nGet recipe |\n| PUT | `/naturalfarming/recipes/:id` |\nUpdate recipe |\n| DELETE | `/naturalfarming/recipes/:id` |\nDelete recipe |\n| GET | `/naturalfarming/recipes/:id/components` |\nList recipe components |\n| POST | `/naturalfarming/recipes/:id/components` |\nAdd component |\n| DELETE | `/naturalfarming/recipes/:id/components/:iid` |\nRemove component (`:iid` = component row id) |\n\nThe master seed loads a **demo farm** (`farm_id = 1`\n\n, **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:\n\n| Table | Rows | Contents |\n|---|---|---|\n`farms` |\n1 | gr33n Demo Farm |\n`zones` |\n3 | Veg Room, Flower Room, Outdoor Garden |\n`crop_cycles` |\n3 | Veg canopy (18/6), Flower run (12/12), Outdoor raised beds |\n`sensors` |\n10 | PAR, lux, temp, humidity, EC, pH, CO2, soil moisture |\n`input_definitions` |\n15 | JMS, LAB, FPJ, FFJ, OHN, JHS, WCA, WCS, JWA, JS, JLF variants, compost tea |\n`application_recipes` |\n14 | Soil drenches, foliar sprays, pest control, fungicide |\n`recipe_components` |\n20 | Input-to-recipe links with dilution ratios |\n`schedules` |\n14 | Light (24/0, 18/6, 16/8, 12/12) + watering programs per grow stage |\n`automation_rules` |\n7 | Automated light on/off rules per grow stage |\n\nApply once: `make seed`\n\nor `psql -d gr33n -f db/seeds/master_seed.sql`\n\n.\n\n**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`\n\n. After seeding, run ** make rag-ingest-demo** (or\n\n**for wipe + seed + ingest):**\n\n`make dev-stack-fresh-rag`\n\n```\nmake rag-ingest-demo   # needs EMBEDDING_API_KEY in .env; skips cleanly if unset\n# or one-shot fresh demo with embeddings:\nmake dev-stack-fresh-rag\n```\n\nSee [ docs/farm-guardian-architecture.md](/dgang0404/gr33n/blob/main/docs/farm-guardian-architecture.md) for the three knowledge layers (Llama weights + RAG corpus + live snapshot).\n\n**Smoke-test pollution:** Running `make test`\n\nagainst a long-lived dev DB accumulates junk rows. For a clean Guardian demo, use ** make dev-stack-fresh** or\n\n**. For day-to-day migration updates on an existing DB,**\n\n`make dev-stack-fresh-rag`\n\n**is idempotent.**\n\n`make dev-stack`\n\n```\nmake help       # Show all targets\nmake bootstrap-local  # Guided DB + env + UI deps (see docs/local-operator-bootstrap.md)\nmake bootstrap-local-docker  # Same, but start stack with docker compose\nmake compose-db-up   # Postgres only — docker-compose db (Timescale + pgvector); pair .env DATABASE_URL with INSTALL.md §2 / .env.example\nmake dev-stack       # Idempotent: migrations + seed on existing DB (auto-skips schema)\nmake dev-stack-fresh # Wipe Compose volume + full bootstrap + seed (clean Guardian demo)\nmake dev-stack-fresh-rag  # Same + rag-ingest demo farm when EMBEDDING_API_KEY is set\nmake rag-ingest-demo   # Index farm_id=1 only (skip message if no embedding key)\nmake local-up        # dev-stack then API + UI (same as ./scripts/dev-stack.sh --serve)\nmake restart-local   # After reboot: Compose db + wait + sanity report (no migrations)\nmake restart-local-serve  # restart-local then API + UI (make dev-auth-test)\nmake check-stack     # Verify DATABASE_URL + pgvector + optional API /health (see docs/local-operator-bootstrap.md)\nmake run        # Run the API server\nmake run-receiver # Run optional Insert Commons receiver (see docs/insert-commons-receiver-playbook.md)\nmake dev        # Run API + UI dev server in parallel\nmake ui         # Run the Vue dev server\nmake build      # Build the Go binary\nmake build-ui   # Build the Vue frontend for production\nmake test       # Run Go tests (-tags dev, ./...)\nmake lint       # Run go vet (-tags dev, ./...)\nmake audit-openapi  # OpenAPI ↔ cmd/api/routes.go shell diff + Go parity test in cmd/api/openapi_parity_test.go\nmake sqlc       # Regenerate sqlc Go code from SQL queries\nmake seed       # Apply seed data to the database\nmake schema     # Apply the schema to the database\nmake up         # Start Docker Compose services\nmake down       # Stop Docker Compose services\nmake logs       # Tail Docker Compose logs\nmake clean      # Remove build artifacts\n```\n\n**Phase 23 / pre-merge gate (local):** `make test`\n\n, `make lint`\n\n, `make audit-openapi`\n\n, `python3 -m pytest pi_client/test_gr33n_client.py pi_client/test_mqtt_telemetry_bridge.py -q`\n\n, and `npm --prefix ui run build`\n\n. ** make test** expects a reachable\n\n**(see**\n\n`DATABASE_URL`\n\n[bootstrap — smoke tests](/dgang0404/gr33n/blob/main/docs/local-operator-bootstrap.md#api-integration-smoke-tests)) so\n\n`cmd/api`\n\nintegration tests actually run.The Pi daemon runs four threads concurrently:\n\n**sensor-loop**— reads each GPIO/I2C sensor at its configured interval, POSTs to`POST /sensors/:id/readings`\n\n**heartbeat-loop**— PATCHes device status every 30s so the dashboard shows \"online\"** schedule-loop**— polls`GET /farms/:id/devices`\n\nfor`pending_command`\n\nin device config JSONB, executes via GPIO, reports via`POST /actuators/:id/events`\n\n, then clears via`DELETE /devices/:id/pending-command`\n\n**flush-loop**— drains the offline SQLite queue when API becomes reachable\n\nConfigure sensors, actuators (with `device_id`\n\n), and GPIO pins in `pi_client/config.yaml`\n\n. Install as a systemd service with `pi_client/setup.sh`\n\nso it starts automatically on boot.\n\n**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\n\n`docs/raspberry-pi-and-deployment-topology.md`\n\n`setup.sh`\n\n: `./scripts/install-pi-edge-deps.sh`\n\n(`make install-pi-edge-deps`\n\n).MCUs can publish to an on-farm **MQTT broker**; a **bridge** process subscribes and forwards to ** POST /sensors/readings/batch** using\n\n`X-API-Key`\n\n(same server `PI_API_KEY`\n\nas the Pi daemon). Reference implementation: [. Topics, TLS, ACLs, and tasking:](/dgang0404/gr33n/blob/main/pi_client/mqtt_telemetry_bridge.py)\n\n`pi_client/mqtt_telemetry_bridge.py`\n\n[.](/dgang0404/gr33n/blob/main/docs/mqtt-edge-operator-playbook.md)\n\n`docs/mqtt-edge-operator-playbook.md`\n\ngr33n's AI layer runs **fully on your intranet** — no data leaves the LAN in Full mode. Knowledge is never sent to cloud APIs.\n\n**Farm Guardian** (Phase 27) is a conversational assistant powered by **Llama 3.1 70B Q4** running on an on-premise GPU box via [Ollama](https://ollama.ai). It layers three knowledge sources:\n\n**Llama weights**— general agricultural, scientific, and world knowledge baked in during training.** Your farm's RAG corpus**— anything you've ingested into`POST /farms/{id}/rag/ingest`\n\n(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 reflect*right now*, not a stale index.\n\nThe AI features are gated by `AI_ENABLED`\n\n(default on) and degrade gracefully: in **Lite mode** (no LLM configured) `POST /v1/chat`\n\nreturns 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`\n\n.\n\n**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`\n\n). Nothing writes without your OK. Viewers can chat but cannot confirm. All confirmed actions log `guardian_tool_executed`\n\nto the farm audit trail. Guardian does **not** change schedules, programs, or actuators autonomously — that scope is Phase 30 (still Confirm-only).\n\n**What comes next (Phase 30):** expanded PR-queue tools (tasks, cycle stage, schedules, Pi actuator enqueue) — [plan](/dgang0404/gr33n/blob/main/docs/plans/phase_30_guardian_change_requests.plan.md).\n\nAll AI calls remain inside your farm's intranet:\n\n```\nPi clients ──HTTPS──▶ Go API\n                        ├──▶ Postgres + pgvector  (farm data + RAG corpus)\n                        └──▶ Ollama  (Llama 3.1 70B Q4, GPU box on intranet)\n\nBrowser ──HTTPS──▶ Vue UI ──▶ Go API  (same as Pi)\n```\n\nSee [ docs/farm-guardian-architecture.md](/dgang0404/gr33n/blob/main/docs/farm-guardian-architecture.md) for the request flow + three-knowledge-layer breakdown,\n\n[for install/setup, and](/dgang0404/gr33n/blob/main/docs/farm-guardian-ollama-setup.md)\n\n`docs/farm-guardian-ollama-setup.md`\n\n[for all](/dgang0404/gr33n/blob/main/INSTALL.md)\n\n`INSTALL.md`\n\n`AI_*`\n\n/ `LLM_*`\n\n/ `CHAT_*`\n\nenv vars.- AI is modular and never mandatory —\n`AI_ENABLED=false`\n\nproduces a clean Lite deployment. - No cloud calls, no training on your data, no opt-in required for basic operation.\n- Cost guards (\n`CHAT_COST_MAX_TOKENS_PER_USER`\n\n/`_PER_FARM`\n\n) prevent runaway token usage on shared deployments.\n\nA phase-by-phase ledger of what's live on `main`\n\n. Each row links to the governing plan doc where one exists; undated rows predate the phase-plan convention.\n\n| Phase | Focus | Status | Links |\n|---|---|---|---|\n| 10 | JWT smoke tests, farm-scoped write auth, fertigation ↔ crop cycle link, costs CSV, SensorDetail UX | ✅ Done | — |\n| 11 | Farm RBAC, cost receipts + local storage, PWA shell, Insert Commons opt-in | ✅ Done | — |\n| 12 | Insert Commons federation | ✅ Done | `db/migrations/20260416_phase12_insert_commons_federation.sql` |\n| 13 | Platform evolution — receiver, audit/compliance, offline, finance depth, tenancy | ✅ Done |\n|\n\n[plan](/dgang0404/gr33n/blob/main/docs/plans/phase_14_network_and_commons.plan.md)·[ops doc](/dgang0404/gr33n/blob/main/docs/phase-14-operator-documentation.md)[plan](/dgang0404/gr33n/blob/main/docs/plans/phase_15_farm_onboarding.plan.md)[plan](/dgang0404/gr33n/blob/main/docs/plans/phase_18_platform_polish.plan.md)[plan](/dgang0404/gr33n/blob/main/docs/plans/phase_19_safety_and_alert_rules.plan.md)[plan](/dgang0404/gr33n/blob/main/docs/plans/phase_20_automation_rule_engine.plan.md)`gr33ncore.zone_setpoints`\n\n) + rule engine integration + UI`cost_transactions.crop_cycle_id`\n\n`aquaponics.loops`\n\n, feed autologging, bootstrap upgrade`executable_actions`\n\nsurface + `metadata.steps`\n\nbackfill + `ResolveProgramActions`\n\nfallback[plan](/dgang0404/gr33n/blob/main/docs/plans/phase_20_95_rag_prep_and_housekeeping.plan.md)`GET /crop-cycles/{id}/summary`\n\n, compare, UI, CSV per plan)[plan](/dgang0404/gr33n/blob/main/docs/plans/phase_21_crop_cycle_analytics.plan.md)·[Phase 28](/dgang0404/gr33n/blob/main/docs/plans/phase_28_crop_intelligence_guardian_depth.md)**22****Worker program-tick + final**—`metadata.steps`\n\nbackfill sweep`runProgramTick`\n\ndispatches `executable_actions`\n\nper program, `automation_runs.program_id`\n\nattribution, 20260517 sweep + per-program NOTICE log, structured fallback warning**23****Stabilization sprint**— CI gates, smoke +`DATABASE_URL`\n\ndocs, OpenAPI parity, Pi/API key runbook, workflow + MQTT accuracy, worker monitoring docs[plan](/dgang0404/gr33n/blob/main/docs/plans/phase_23_stabilization_sprint.plan.md)·[exit sign-off](/dgang0404/gr33n/blob/main/docs/plans/phase_23_stabilization_sprint.plan.md#exit-sign-off)**24****RAG retrieval system**— embeddings + farm-scoped retrieval API (+ optional LLM synthesis); builds on[20.95 RAG-prep](/dgang0404/gr33n/blob/main/docs/plans/phase_20_95_rag_prep_and_housekeeping.plan.md)[plan](/dgang0404/gr33n/blob/main/docs/plans/phase_24_rag_retrieval_system.plan.md)**25****RAG operations & expansion**— ingest breadth, incremental re-embed, CI/pgvector parity, integration tests + synthesis limits, UX/docs ([schema ERD text](/dgang0404/gr33n/blob/main/docs/schema-erd-text.md))[plan](/dgang0404/gr33n/blob/main/docs/plans/phase_25_rag_operations_and_expansion.plan.md)**26****Operator tutorial, observability, RAG scope**— operator-guide UI, Loki/Promtail/Grafana logging overlay, RAG scope/threat-model, LLM retry/backoff, Ollama setup runbook[plan](/dgang0404/gr33n/blob/main/docs/plans/phase_26_operator_tutorial_observability_rag.plan.md)**27****Farm Guardian AI layer**— on-premise Llama 3.1 70B via Ollama,`AI_ENABLED`\n\n+ `/capabilities`\n\n, streaming `POST /v1/chat`\n\n, multi-turn history + RAG grounding + live farm-state snapshot, session CRUD, token usage, cost guards, `/chat`\n\nUI panel with session sidebar + bulk-delete[plan](/dgang0404/gr33n/blob/main/docs/plans/phase_27_farm_guardian_ai_layer.md)**28****Crop intelligence & Guardian depth**— crop-cycle analytics, Guardian ↔ cycles + alerts, token-usage dashboard, 80% budget warnings, OpenAPI 0.3.0[plan](/dgang0404/gr33n/blob/main/docs/plans/phase_28_crop_intelligence_guardian_depth.md)**29****Guardian agent layer**(candidate) — tool-calling actions with confirmation, global slide-out panel, Guardian-ready bootstrap[plan](/dgang0404/gr33n/blob/main/docs/plans/phase_29_guardian_agent_layer.md)Stabilization sprint **closed** on `main`\n\n**2026-04-18**. Criterion-by-criterion table and next-phase links: .\n\n`docs/plans/phase_23_stabilization_sprint.plan.md`\n\n— Exit sign-off| Gate | Status |\n|---|---|\nCI matrix (`make test` , `make lint` , `make audit-openapi` ; pytest + UI build — see\n|\n✅ |\nOpenAPI ↔ `routes.go` |\n✅ |\nSmoke / `DATABASE_URL` + CI without DB |\n✅ Documented + `TestMain` behavior |\n| Operator docs (workflow, MQTT, Pi auth, automation logs) | ✅ |\n\n**In flight / next up** (priority order):\n\n-\n**Phase 23 — stabilization**—** done**;[exit sign-off](/dgang0404/gr33n/blob/main/docs/plans/phase_23_stabilization_sprint.plan.md#exit-sign-off). -\n**Phase 24 — RAG retrieval**— vectors + farm-scoped API + optional LLM synthesis; Knowledge UI. -\n**Phase 25 — RAG operations & expansion**— CI parity, ingest breadth, incremental re-embed, limits/tests, docs/UX polish. -\n**Phase 26 — operator tutorial, observability, RAG scope**— guide UI, Loki overlay, RAG boundary doc, LLM retry, Ollama runbook. -\n**Phase 27 — Farm Guardian AI layer**— streaming chat, multi-turn history, RAG grounding, live snapshot, session management, cost guards. -\n**Pi ↔ API contract pass**— smoke tests`TestPiContract*`\n\nin: enqueue`cmd/api/smoke_pi_contract_test.go`\n\n`pending_command`\n\n→ Pi-key`GET /farms/1/devices`\n\n→`POST /actuators/{id}/events`\n\n→`DELETE`\n\npending. -\n**Phase 28 — crop intelligence & Guardian depth**— crop analytics, Guardian snapshot depth, usage dashboard, OpenAPI 0.3.0. -\n**Phase 29 — Guardian agent layer**— propose→confirm alert ack/read, slide-out drawer, contextual entry points, OpenAPI 0.4.0 —[plan](/dgang0404/gr33n/blob/main/docs/plans/phase_29_guardian_agent_layer.md) -\n**Phase 30 — Guardian change requests (PR queue)**— config + actuator proposals, pending inbox, zone photos / optional vision —[plan](/dgang0404/gr33n/blob/main/docs/plans/phase_30_guardian_change_requests.plan.md) -\n**Phase 31 — field validation & safe edge**— Pi/breadboard loop, proves confirmed actuator PRs reach GPIO —[plan](/dgang0404/gr33n/blob/main/docs/plans/phase_31_field_validation_and_edge.plan.md)·[enterprise topology sketch](/dgang0404/gr33n/blob/main/docs/hypothetical-enterprise-topology.md) -\n**Deprecate**— after N deploys with zero fallback warnings, promote`programs.metadata.steps`\n\n`action_source`\n\nchecks to hard errors and drop the column. -\n**Program \"run now\" API**— explicit trigger for unscheduled / ad-hoc programs. -\n**Mobile distribution polish**— Capacitor packaging, store submission checklist.\n\n- gr33ncore schema — users, sensors, schedules, zones, automation rules\n- gr33nnaturalfarming schema — inputs, recipes, batches\n- Go REST API — farms, zones, devices, sensors, tasks, readings\n- Natural farming demo seed — 15 inputs, 14 recipes, full automation (JADAM-style labels)\n- sqlc query layer + enum types\n- Vue 3 frontend — Dashboard, Zones, Sensors, Actuators, Schedules, Settings, Inventory\n- Raspberry Pi sensor client with systemd daemon\n- OpenAPI spec (openapi.yaml)\n- Sensor readings live on dashboard (SSE stream with JWT query param auth)\n- Phase 10 — JWT smoke tests (\n`AUTH_MODE=auth_test`\n\n), 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\n`FILE_STORAGE_DIR`\n\nstorage,**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;\nindexes plans and playbooks)`docs/phase-13-operator-documentation.md`\n\n- Phase 14 — Field network & commons (MQTT/edge, insert pipeline, gr33n_inserts catalog, federation/receiver depth, FCM notifications, org governance, domain schema stubs;\n,`docs/plans/phase_14_network_and_commons.plan.md`\n\n)`docs/phase-14-operator-documentation.md`\n\n- Actuator control pipeline (automation worker → pending_command → Pi poll → execute → report)\n- Fertigation module — reservoirs, EC targets, programs, events\n- Natural farming inventory UI — input definitions & batch tracking\n- Pi heartbeat loop — devices show online/offline in real time\n- Docker Compose + Dockerfile for containerized deployment\n- Microcontroller integrations — MQTT → HTTP bridge (\n,`pi_client/mqtt_telemetry_bridge.py`\n\n); field tasking unchanged (`docs/mqtt-edge-operator-playbook.md`\n\n`pending_command`\n\n+ Pi / bridge poll) - Data insert pipeline (Insert Commons validation, approval bundles, export —\n)`docs/insert-commons-pipeline-runbook.md`\n\n- LM Studio integration and AI scaffolds for insert-sharing\n- gr33n_inserts — commons catalog API (browse + farm import audit;\n)`docs/commons-catalog-operator-playbook.md`\n\n- Stub schemas\n`gr33ncrops`\n\n,`gr33nanimals`\n\n,`gr33naquaponics`\n\n(placeholder tables; enable via`farm_active_modules`\n\n—)`docs/domain-modules-operator-playbook.md`\n\n- Phase 20 — automation rule engine (sensor-driven conditions, action dispatch, cooldowns, rule-driven notifications) —\n[plan](/dgang0404/gr33n/blob/main/docs/plans/phase_20_automation_rule_engine.plan.md) - Phase 20.6–20.9 — stage-scoped setpoints, cost/energy nightly rollups, animal husbandry, labor auto-cost, program actions +\n`metadata.steps`\n\nbackfill - Phase 20.95 — RAG-prep schema housekeeping for AI consumption —\n[plan](/dgang0404/gr33n/blob/main/docs/plans/phase_20_95_rag_prep_and_housekeeping.plan.md) - Phase 21 — crop cycle analytics & yield (summary, compare, UI, CSV) —\n[plan](/dgang0404/gr33n/blob/main/docs/plans/phase_21_crop_cycle_analytics.plan.md)*(superseded by Phase 28 WS1 — endpoints shipped)* - Phase 22 — worker program-tick (\n`runProgramTick`\n\n),`automation_runs.program_id`\n\n, final`metadata.steps`\n\nbackfill sweep, observable fallback warning - Phase 23 — stabilization sprint (CI, smoke, OpenAPI parity, docs, small fixes) —\n[plan](/dgang0404/gr33n/blob/main/docs/plans/phase_23_stabilization_sprint.plan.md)·[exit sign-off](/dgang0404/gr33n/blob/main/docs/plans/phase_23_stabilization_sprint.plan.md#exit-sign-off) - Phase 24 — RAG retrieval system (vectors + farm-scoped API + optional LLM) —\n[plan](/dgang0404/gr33n/blob/main/docs/plans/phase_24_rag_retrieval_system.plan.md) - Phase 25 — RAG operations & expansion (ingest breadth, incremental re-embed, CI parity, limits, UX/docs) —\n[plan](/dgang0404/gr33n/blob/main/docs/plans/phase_25_rag_operations_and_expansion.plan.md) - Phase 26 — operator tutorial, observability, RAG scope (guide UI, Loki overlay, RAG boundary, LLM retry, Ollama runbook) —\n[plan](/dgang0404/gr33n/blob/main/docs/plans/phase_26_operator_tutorial_observability_rag.plan.md) - Phase 27 — Farm Guardian AI layer (streaming chat, multi-turn sessions, RAG grounding + live snapshot, cost guards,\n`/chat`\n\nUI panel) —[plan](/dgang0404/gr33n/blob/main/docs/plans/phase_27_farm_guardian_ai_layer.md) - Phase 28 — crop intelligence & Guardian depth (crop analytics, Guardian ↔ cycles/alerts, usage dashboard, OpenAPI 0.3.0) —\n[plan](/dgang0404/gr33n/blob/main/docs/plans/phase_28_crop_intelligence_guardian_depth.md) - Phase 29 — Guardian agent layer (propose→confirm, slide-out drawer, Ask Guardian entry points, OpenAPI 0.4.0) —\n[plan](/dgang0404/gr33n/blob/main/docs/plans/phase_29_guardian_agent_layer.md) - Phase 30 — Guardian PR queue (config agent, actuator proposals, zone vision) —\n[plan](/dgang0404/gr33n/blob/main/docs/plans/phase_30_guardian_change_requests.plan.md) - Phase 31 — field validation & edge (Pi loop, safe actuator, recipe packs) —\n[plan](/dgang0404/gr33n/blob/main/docs/plans/phase_31_field_validation_and_edge.plan.md)·[enterprise sketch](/dgang0404/gr33n/blob/main/docs/hypothetical-enterprise-topology.md)\n\n- Fork this repo\n- Join the insert-sharing network (coming soon in gr33n_inserts)\n- Help build bridges between sensors, dashboards, and soil\n- Translate docs, test offline installs, or write a better knf_notes parser\n\n\"Built for the commons.\"\n\nThe 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.\n\ngr33n lives in this tradition: Free to use, fork, and rebuild. Not fenced off behind corporate toll booths.\n\n**GNU Affero General Public License v3.0 (AGPL-3.0)**\n\nUse 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.\n\nJust don't try to put a fence around the commons.\n\nBuilt by farmers, hackers, and friends. With sunlight and rage.", "url": "https://wpnews.pro/news/open-source-agricultural-os-offline-first-agpl-grow-tent-to-500-warehouse-scale", "canonical_source": "https://github.com/dgang0404/gr33n", "published_at": "2026-05-27 20:48:29+00:00", "updated_at": "2026-05-27 21:14:52.988461+00:00", "lang": "en", "topics": ["ai-agents", "ai-products", "ai-infrastructure", "ai-startups", "robotics"], "entities": ["Guardian", "OpenAPI", "Pi", "MQTT", "AGPL", "gr33n", "Phase 29", "Phase 28"], "alternates": {"html": "https://wpnews.pro/news/open-source-agricultural-os-offline-first-agpl-grow-tent-to-500-warehouse-scale", "markdown": "https://wpnews.pro/news/open-source-agricultural-os-offline-first-agpl-grow-tent-to-500-warehouse-scale.md", "text": "https://wpnews.pro/news/open-source-agricultural-os-offline-first-agpl-grow-tent-to-500-warehouse-scale.txt", "jsonld": "https://wpnews.pro/news/open-source-agricultural-os-offline-first-agpl-grow-tent-to-500-warehouse-scale.jsonld"}}