modules/board/ — the farm's page (layer 4)#
The thinnest slice of an app (spec v0.1 §11, layer 4). A notification says that something happened; board.py shows what is still the case, on one read-only page per language:
- Needs someone: every alert that stands and was sent to someone, with who was told, by what, when, and who said they are on it, or that nobody has yet. Red until someone takes it, then green.
- Also standing: what the modules say now that went to nobody, such as this morning's soil advice.
- Latest readings: the newest reading of each series the board is given (a trough's level, a bed's water, the tunnel's air), with its time. A reading the health checks flagged says so and names the flag, and one more than three of its intervals old says how long nothing newer has come. A fraction shows as a percentage, and each language writes its own decimal mark.
- Cleared in the last day: what stopped being the case, and when.
Like the notifier, it reads any module's decisions without importing any
module (rules.render), and it never writes the log. Its grant reads decisions,
notifications and acknowledgements, the names of what decisions are about, and the series
its page shows.
It says when it was made. A page that stopped updating looks exactly like a quiet farm, the failure §4.2 forbids for sensors ("no news is not good news"). So the page:
- states the minute it was made;
- reloads itself every minute;
- says plainly, once it is ten minutes old, that the farm's computer or the board has stopped and that what follows may no longer be true.
For a phone in a field:
- large type and strong contrast, light or dark as the phone is set;
- nothing loaded from anywhere else;
- no script it needs: the only script makes the "stopped" warning appear;
- a content-security policy that lets that script and the style run, by hash, and nothing else.
Everything a farm or a module wrote, labels included, is escaped.
python3 -I modules/board/board.py --socket /run/fieldmesh/modules.sock \
--config board.json --out /var/lib/fieldmesh-board --serve 127.0.0.1:8080
board.json names the farm, its time zone, the languages to write pages in, the units its
alerts are said in ("metric", the default, or "us"), and the names of the people
acknowledgements refer to by id (names only; reaching people is the notifier's business):
{"farm": "Harrow Bend", "timezone": "America/Chicago", "languages": ["en", "es"], "units": "us",
"people": {"0192…": "María", "0192…": "Sam"},
"series": ["<trough level datastream id>", "<hoop house air datastream id>"]}
The series it shows are the ones its grant names (modhost.py grant --datastream …); a
series it was not given shows as having no reading, never as an error. It keeps what it
reads of the log to what a page needs: on each question its last two answers, every
decision of the last day, and what was sent about those. A board that runs for months
holds days of decisions, and the page is the same (tested).
Serving it:
- It writes
index.htmland oneindex.<language>.htmlper language, each replaced whole so nobody reads half a page.index.htmlsends a browser to its own language. --serveserves those pages and nothing else, read-only.- Like the data service, it refuses to serve beyond this machine without TLS, because the
page names the farm's troughs and its people. On the farm computer, open
http://127.0.0.1:8080/. For phones on the farm's Wi-Fi, give it--tls-certand--tls-key, or put it behind a proxy that holds a certificate. - Under systemd it is
fieldmesh-module@boardwith its drop-in (deploy/systemd/), scored 1.2 ("OK") bysystemd-analyze security.
Code AGPL-3.0-or-later (LICENSE); strings in packs/ under the
board. prefix, with the Spanish an unreviewed draft.
Next: a certificate story for the farm's own network that does not ask a farmer to run a certificate authority.