The project side of the frozen Hub contract
(central_ai_llm_master/docs/ask-contract.md), on this service's own port:
GET /capabilities the routing topics the Hub reads, project "compass_nhs"
POST /ask one short, read-only answer about a child's school work
POST /notify accept the contract's notification shape, deliver via Apprise
All three require the shared bearer token SCHOOL_HUB_TOKEN; with no token they
answer 503. GET /health now also carries "ok": true and "hub_api".
/ask answers deterministically (no model on the path) from the stored Compass
items, reusing dashboard.Classify so the answer and the dashboard never
disagree. It is one short sentence, for example "Harry has 8 school events
today from 8:55am to 6:00pm and 6 overdue tasks", with the buckets in `data`.
It reads only, enforced by a Reader interface with no write method and by
TestHubAskReadsOnly.
Fail loudly (FR-12): a missing or failed scan is never an empty day. /ask says
due work is unknown, and an answer older than 36 hours carries a stale warning.
Permission follows the contract: a parent may ask about any child; anyone else
only about themselves.
/notify follows the house interpretation already used by internet_use_control:
the contract shape is accepted and delivered to the named person, recorded in
notifications with scope "hub". An unknown person is refused, not misdelivered.
Live proof on .13 (deploy/verify-phase8.sh):
/health 200, ok true
/capabilities 200, project compass_nhs; unsigned 401
/ask 200, the sentence above, duration 1ms
/notify 400 on a bad level (auth proven, nothing sent), then 200 with
a real delivery to Sam on email and WhatsApp
The live Hub registration (HUB_PROJECTS + HUB_PROJECT_COMPASS_NHS_TOKEN +
hub restart) is a change to a running family service and is pending approval.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
89 lines
3.9 KiB
Plaintext
89 lines
3.9 KiB
Plaintext
# Compass / NHS — service environment (EXAMPLE).
|
|
#
|
|
# Copy to environment.d/school-service.env and fill the secrets in. The real
|
|
# file is gitignored; never commit it. Generate values with:
|
|
# docker run --rm --entrypoint /app/school compass-teams-nhs/school:0.1.0-phase1 gen-secret
|
|
# docker run --rm --entrypoint /app/school compass-teams-nhs/school:0.1.0-phase1 hash-password 'the-password'
|
|
|
|
# Listen address inside the container. The host maps 8792 -> 8792.
|
|
SCHOOL_ADDR=:8792
|
|
|
|
# SQLite database in the named volume.
|
|
SCHOOL_DB_PATH=/data/school.db
|
|
|
|
# Signs the session cookie. Required, >= 16 characters. Secret.
|
|
SCHOOL_SESSION_SECRET=change-me-32-bytes-of-random
|
|
|
|
# The single dashboard login (Sam). Prefer the bcrypt hash over the plaintext.
|
|
SCHOOL_ADMIN_USERNAME=sam
|
|
SCHOOL_ADMIN_PASSWORD_HASH=
|
|
SCHOOL_ADMIN_PASSWORD=
|
|
|
|
# Keep true behind HTTPS (Caddy terminates TLS).
|
|
SCHOOL_COOKIE_SECURE=true
|
|
SCHOOL_SESSION_TTL=12h
|
|
|
|
# Family timezone for due dates and briefs.
|
|
SCHOOL_TIMEZONE=Australia/Sydney
|
|
|
|
SCHOOL_LOG_LEVEL=info
|
|
SCHOOL_APP_ENV=production
|
|
|
|
# ---- Home Assistant calendar (AGENTS.md §4 FR-8, Phase 6) -------------------
|
|
# Important school events are written to Sam's Home Assistant calendar through
|
|
# the Home Assistant REST API. Nothing is written until all three of URL, token
|
|
# and entity are set; the dashboard shows CALENDAR NOT CONFIGURED until then.
|
|
#
|
|
# The token is a long-lived access token created on Sam's Home Assistant
|
|
# profile page. It is a SECRET: keep it in this file only.
|
|
SCHOOL_HA_URL=http://192.168.20.30:8123
|
|
SCHOOL_HA_TOKEN=
|
|
# The calendar entity to write to. Discover the real ids with:
|
|
# scripts/calendar-push.sh entities
|
|
SCHOOL_HA_CALENDAR_ENTITY=calendar.school
|
|
# The internal .lab Caddy certificate is not in the container trust store.
|
|
# Set true only when SCHOOL_HA_URL is the https://homeassistant.home.lab URL.
|
|
SCHOOL_HA_INSECURE=false
|
|
SCHOOL_HA_TIMEOUT=20s
|
|
|
|
# ---- Apprise notifications (AGENTS.md §4 FR-9/FR-14, §11 Phase 7) ----------
|
|
# The morning briefs go out through the house Apprise API on `.35:8210`. The
|
|
# Apprise configuration holds every destination (email address, WhatsApp number,
|
|
# SMTP password); this service only names a tag such as "harry_email", so no
|
|
# address or password is ever stored here or committed (AGENTS.md §10 rule 3).
|
|
#
|
|
# Create the stored configuration once in the Apprise web UI
|
|
# (https://apprise.lab.audasmedia.com.au), then copy its key here. The key acts
|
|
# like a password: keep it in this file only, never in git.
|
|
SCHOOL_APPRISE_URL=http://192.168.20.35:8210
|
|
SCHOOL_APPRISE_KEY=
|
|
# Optional bearer token if the Apprise API is protected. Empty in this lab.
|
|
SCHOOL_APPRISE_TOKEN=
|
|
SCHOOL_APPRISE_TIMEOUT=15s
|
|
|
|
# Channels the morning brief uses (AGENTS.md §13 decision 8). Each recipient
|
|
# needs a tag per channel: <tag base>_email and <tag base>_whatsapp.
|
|
SCHOOL_APPRISE_CHANNELS=email,whatsapp
|
|
|
|
# Recipients: Name=tag-base. The boys are children in the database and get their
|
|
# own brief; the rest are parents and get one combined brief (FR-9, FR-14).
|
|
SCHOOL_APPRISE_TAGS=Harry=harry,Finn=finn,Jo=joanna,Sam=sam
|
|
SCHOOL_APPRISE_PARENTS=Jo,Sam
|
|
|
|
# Bearer token for POST /notify/morning, the endpoint n8n calls at 6:00am.
|
|
# Generate one and keep it here:
|
|
# docker run --rm --entrypoint /app/school <image> gen-secret
|
|
SCHOOL_NOTIFY_TOKEN=
|
|
|
|
# ---- Hub API (AGENTS.md §4 FR-11, §11 Phase 8) ------------------------------
|
|
# The shared token the Hub sends to GET /capabilities, POST /ask (read-only) and
|
|
# POST /notify. It is a SECRET: keep it in this file only, never in git.
|
|
#
|
|
# The Hub holds the same value as HUB_PROJECT_COMPASS_NHS_TOKEN in
|
|
# ~/.config/environment.d/10-secrets.conf, and reaches this service through
|
|
# HUB_PROJECTS=compass_nhs=http://192.168.20.13:8792. Generate one with:
|
|
# head -c 32 /dev/urandom | base64 | tr -d '=+/' | cut -c1-40
|
|
# An empty value turns the three Hub endpoints off with 503; the dashboard is
|
|
# unaffected.
|
|
SCHOOL_HUB_TOKEN=
|