The fleet row named the wave by its short name only ("PILOT-2") while the
detail view and the filter carry the full label ("P2 — PILOT-2"). An operator
matching a row against a work order speaks in codes, so the row carries the
full label now -- still named once, which the row test asserts.
Also takes the console agent's leftover: a dead state_style helper removed and
the unit convention on ALL_TOKENS documented (lengths are unitless; Tk padding
is already pixels, the parity test strips the CSS unit).
|
||
|---|---|---|
| .. | ||
| data | ||
| static | ||
| templates | ||
| __init__.py | ||
| fleet_data.py | ||
| panel.py | ||
| README.md | ||
| render.py | ||
| server.py | ||
Blueforce Field OS — Filo Paneli (merkez web paneli)
Operatörün ofis tarayıcısından filoyu gördüğü yüzey: hangi cihaz kuruldu,
hangi yayılım dalgasında ve sıradaki tek iş ne. Cihaz başına operatör arayüzü
sudo bf (tkinter konsolu, bfos/) ile aynı filoyu iki uçtan anlatır; iki yüzey
tek durum sözlüğünü paylaşır (docs/DESIGN.md).
Neden yalnız Python standart kütüphanesi
Filo çevrimdışı kurulur ve paketler commit'lenmiş havuzdan gelir; fastapi,
uvicorn, flask, jinja2 bu havuzda yok. Panel bunları import etse
yönettiği cihazlara kurulamaz (bkz. PRODUCT.md, "Stack"; karar kullanıcıyla
birlikte alındı). Bu yüzden: http.server + string.Template, harici CDN veya
webfont yok, tüm varlıklar yerel.
Çalıştırma
# 1) Hiçbir şey vermeden: 127.0.0.1:8787, etiketli DEMO VERİ, salt-okunur
python3 -m web.server
# (python3 web/server.py de aynı şekilde çalışır)
# 2) Gerçek envanter dosyasıyla
python3 -m web.server --data /var/lib/blueforce/inventory/fleet.json
# 3) Sunucuyu başlatmadan veri kaynağını denetle (CI/operatör kontrolü)
python3 -m web.server --check --data ./web/data/fleet.json
# 4) Tam yetki (bu sürümde yazma uç noktası yoktur; yalnız arayüz farkı)
python3 -m web.server --privilege full
Seçenekler: --host (varsayılan 127.0.0.1), --port (varsayılan 8787),
--data, --privilege {read-only,full}, --check, --version.
Panel varsayılan olarak yalnız yerel arayüze bağlanır.
Uç noktalar (hepsi okuma)
| Yol | Ne döner |
|---|---|
/ (veya /filo) |
İlk ekran: başlık bandı, durum özeti, cihaz listesi, seçili cihaz ayrıntısı |
/?q=&durum=&dalga=&hazir_degil=1&cihaz= |
Aynı ekran, sunucu tarafında filtrelenmiş (JavaScript yok) |
/hakkinda |
Panelin sürümü, veri kaynağı, durum sözlüğü, dalgalar, kanallar ve panel kuralları |
/static/tokens.css, /static/app.css |
Yerel stil dosyaları (allow-list; listeye eklenmeyen dosya 404) |
GET ve HEAD dışındaki yöntemler 405 ile ve Türkçe gerekçeyle reddedilir.
Hiçbir uç nokta komut çalıştırmaz, dosya yazmaz veya cihazda değişiklik yapmaz.
Veri sözleşmesi (schema_version: 1)
{
"schema_version": 1,
"generated_at": "2026-09-16T09:30:00+03:00",
"devices": [
{
"dealer_id": "12010193",
"wave": "P1",
"state": "READY",
"last_seen": "2026-09-16T09:05:00+03:00",
"channels": {
"ssh_over_wg": {"status": "verified", "checked_at": "2026-09-14T10:00:00+03:00"},
"xrdp": "pending",
"rustdesk": "verified",
"meshcentral": "verified"
}
}
]
}
dealer_id: 8 hane (^[0-9]{8}$). Cihaz kimliği ve hostname türetilir:BF-<no>/bf-<no>(docs/02). Dosyadadevice_id/hostnamede varsa yalnız kurala uyduğunda kabul edilir.wave:LAB,P1,P2,W1,W2,PROD(Ansible grup adları da kabul:lab,pilot_1,wave_1,production).state:PROVISIONED_OFFLINE,ENROLLED,READY,FAILED,ABSENT(Türkçe kelimeler de kabul:KURULDU,KAYITLI,HAZIR,HATA,YOK).channels: dört kanal (ssh_over_wg,xrdp,rustdesk,meshcentral), durumverified/pending/failed/unknown/missing.- Örnek dosya:
web/data/fleet.example.json.
Panelin uyguladığı kurallar (fail-closed)
- HAZIR kapısı:
READYiddiası dört kanal daverifiedolmadan reddedilir; cihazHATAolarak ve gerekçesiyle gösterilir (docs/27). Panel bir iddiayı uyarıya yumuşatmaz. - Başarısız kanal: denetimi başarısız (
failed) bir kanal varsa cihazHATAsayılır — cihaz bir insan bekliyor demektir. - Yükseltme yok: panel hiçbir cihazın durumunu ilerletmez;
KAYITLIyı kendiliğindenHAZIRyapmaz. - Geçersiz kayıt görünür: kimliği kurulamayan kayıt (hatalı bayi no, yinelenen bayi no, bilinmeyen dalga) sessizce düşürülmez; sayfada "Geçersiz kayıtlar" altında nedeniyle listelenir.
- Bozuk veri demo veriye dönüşmez:
--data/BF_FLEET_DATAile verilen dosya yoksa, JSON değilse veya şema sürümü desteklenmiyorsa panelVERİ YOKder; uydurmaz.
Test
python3 tests/test_web_static.py -v # statik + sözleşme testleri (port açmaz)
bash tests/run-all.sh # depo genelindeki tüm testler
Testler HTTP yüzeyini web/panel.py:route() (saf fonksiyon) üzerinden kapsar;
bu yüzden hiçbir test gerçek port bağlamaz, tarayıcı açmaz.