Heimþallr — Watchman of Bifröst (/heimdallr)
"He needs less sleep than a bird; he sees equally well night and day a hundred leagues from him, and hears the grass growing on the earth." — Gylfaginning, Prose Edda
Heimþallr is the watchman who stands at the edge of the bridge. He never sleeps. He sees every request before it crosses. He decides who passes and who turns back.
His domain is traffic control — the infrastructure layer beneath all other agents. Before Kvasir retrieves, before Forseþi judges, before Niove renders, before Njörðr counts the cost — Heimþallr decides whether the request reaches them at all.
Deployment Status (2026-03-25)
Crash-tested by Dummiþ. Documented by Miþir. This is the truth.
| Watch | Designed | Deployed | Status |
|---|---|---|---|
| Watch 0 — Maintenance toggle | /shared/maintenance.flag | /shared/maintenance.flag via n8n | ✅ Active |
| Watch 1 — Geo-filtering | GeoBlock plugin + ["FR"] | Nothing | ❌ Not implemented |
| Watch 2 — Rate limiting | rateLimit middleware | Nothing | ❌ Not implemented |
| Watch 3 — Gjallarhorn alerts | Spike/429/cert/backend alerts | Nothing | ❌ Not implemented |
| SSL/TLS | Let's Encrypt ACME | Let's Encrypt ACME | ✅ Active |
| Routing | Host-based via Docker labels | Host-based via Docker labels | ✅ Active |
| OTEL observability | git-http-proxy traces | git-http-proxy → Opik | ✅ Active |
| Bifröst Calendar | 6 crons per election | Executed for Audierne 2026 T1+T2 | ✅ Complete |
| State markers | <!-- heimthallr-state: --> | In holding pages | ✅ Active |
Current reality: All traffic to cap.audierne2026.fr passes through with no country check, no rate limit, no IP filter. Only the maintenance flag stands between the public internet and the backend.
To implement Watch 1: Requires Traefik GeoBlock plugin + MaxMind GeoLite2 database on VPS. See docker-compose.yml for the prepared middleware labels.
Why a Dedicated Agent?
Traffic control is not governance (Archi), not cost (Njörðr), not UI (Niove). It is its own domain:
| Agent | Relationship to Traffic |
|---|---|
| Archi | "Did we follow the access rules?" — compliance |
| Njörðr | "How much did this request cost?" — after the fact |
| Niove | "What does the citizen see?" — presentation |
| Heimþallr | "Should this request reach the app at all?" — gatekeeping |
Without the gate, the others are exposed. Bots consume Njörðr's budget. Scrapers pollute Kvasir's traces. Foreign traffic inflates Archi's audit logs. Heimþallr prevents all of this by standing at the bridge.
The Bridge (Bifröst)
Bifröst is the reverse proxy — the single point through which all traffic flows. In the Vaettir realm, this is Traefik on the VPS.
Citizen (France) → cap.audierne2026.fr
→ DNS CNAME → vaettir.locki.io
→ Traefik (Heimþallr)
├── GeoIP check: FR? → pass
├── Rate limit check: within bounds? → pass
├── SSL termination (Let's Encrypt)
└── Proxy → backend
Scraper (US) → cap.audierne2026.fr
→ Traefik (Heimþallr)
├── GeoIP check: US? → 403 Forbidden
└── (request never reaches backend)
The Three Watches
Watch 1 — Geo-Filtering (who crosses)
Control access by country. For a civic tool serving a French commune, this is the primary gate.
| State | Config | Use Case |
|---|---|---|
| Closed | allowCountries: [] | Maintenance, pre-launch |
| Admin only | IP whitelist | Testing before opening |
| France only | ["FR"] | Election period — citizens only |
| Francophonie | ["FR", "BE", "CH", "LU", "MC"] | Broader civic access |
| Open | Remove middleware | Post-election, global access |
Watch 2 — Rate Limiting (how fast they cross)
Protect the app from abuse without blocking legitimate citizens.
- Normal citizen: 1-2 req/s (page loads + API calls)
- Suspicious: >10 req/s sustained — likely bot
- Attack: >50 req/s — rate limit kicks in, returns 429
Watch 3 — Gjallarhorn (alerts)
When traffic is anomalous, sound the horn:
- Sudden spike from non-FR countries → possible scraping
- Sustained 429s → someone hitting rate limits repeatedly
- SSL cert expiring → Traefik ACME renewal failed
- Backend down → Render returning 502/503
The Keep — Realm Preservation
Heimþallr guards not only who crosses the bridge, but what lies behind it. The n8n workflows are the nervous system of Vaettir. The PostgreSQL database is their memory. If these are lost, no amount of traffic control matters.
| Asset | Location | Backup Frequency |
|---|---|---|
| PostgreSQL (n8n workflows, credentials) | VPS Docker volume | Before every deploy, weekly |
| n8n_data (custom nodes, settings) | VPS Docker volume | Before every deploy, weekly |
| Config (.env, docker-compose) | VPS ~/vaettir/ | Before every deploy |
| Traefik certs (ACME/Let's Encrypt) | VPS Docker volume | Monthly |
Observability (2026-03-16)
Heimþallr's newest sense: OpenTelemetry instrumentation on the sovereign git proxy (git.lockilabs.com).
Traces flow to the Opik locki workspace under the git-http-proxy project. Every request is traced:
| Span | What it measures |
|---|---|
git.request | Full request lifecycle — method, path, user, outcome |
imap.auth | STARTTLS authentication latency, success/failure |
acl.check | Push authorization — patterns matched, allowed/denied |
git.cgi | CGI execution time for git-http-backend |
First-hour findings revealed bot probes (banking phishing kits, Scrapy crawlers) — traffic that was previously invisible. The guard can now see.
Maintenance Mode
Heimþallr controls maintenance state via a shared Docker volume flag:
/shared/maintenance.flagexists → serve holding page/shared/maintenance.flagabsent → proxy to backend- Toggled by n8n crons ("Heimþallr — Maintenance ON/OFF") or CLI
No container restart required. No environment variable. Just a file.
State Marker Convention
Every holding page MUST include a hidden HTML comment:
<!-- heimthallr-state: {project}/{page-name} -->
The verify node in every maintenance workflow checks that the served page contains the expected marker. If it doesn't, the wrong page is showing — Gjallarhorn sounds.
Examples:
<!-- heimthallr-state: ocapistaine/shutdown-merci --><!-- heimthallr-state: ocapistaine/between-rounds -->
Bifröst Calendar
Heimþallr knows when the gate opens and closes. Every deployment has a calendar of scheduled gate states, managed as n8n cron workflows.
Template: Two-Round French Election
# Event Cron pattern Gate Page
1 Blackout T1 ON 0 0 <SAT_T1> * * maint ON blackout page
2 Between rounds 0 20 <SUN_T1> * * maint ON between-rounds page
3 Campaign T2 ON 0 18 <TUE_T2> * * maint OFF (tool live)
4 Blackout T2 ON 0 0 <SAT_T2> * * maint ON blackout page
5 Shutdown 0 0 <SAT_T2> * * maint ON shutdown-merci page
6 (no OFF) — stays ON mission complete
All crons run Europe/Paris timezone. Six crons per two-round election.
Relationship to Njörðr
Heimþallr and Njörðr are complementary:
- Heimþallr blocks before the cost — a blocked request costs zero
- Njörðr counts after the bridge — only passed requests are measured
- Together they form a complete cost control loop: prevent unnecessary spend (Heimþallr) + measure necessary spend (Njörðr)