security: CORS hardening, path traversal fix, WebSocket auth + cleanup

- Restrict CORS to localhost origins (was allow_origins=[*])
- Require valid JWT on WebSocket /ws (anonymous no longer gets admin view)
- Fix path traversal in delete_cell(): resolve() + parent check
- Validate cell_id format in /charts/download-noaa/{cell_id}
- Exclude charts/ and Cartas/ from git (keep US1GC09M world overview)
- Add NOAA ENC Portal external link in charts catalog tab
- Untrack __pycache__/, .db, .claude/ session files

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-07-03 12:45:43 -04:00
parent 3e04c4113f
commit cfd94f905a
47 changed files with 1847 additions and 427 deletions
+10 -4
View File
@@ -22,19 +22,23 @@ class LampIn(BaseModel):
lamp_count: int = 1
voltage_min: float = Field(..., gt=0)
voltage_max: float = Field(..., gt=0)
warn_pct: float = Field(20.0, ge=1, le=50) # % of range → warning
alarm_pct: float = Field(10.0, ge=1, le=50) # % of range → alarm
notes: Optional[str] = None
def compute_thresholds(vmin: float, vmax: float) -> dict:
def compute_thresholds(vmin: float, vmax: float,
warn_pct: float = 20.0, alarm_pct: float = 10.0) -> dict:
rng = vmax - vmin
return {
"warn_v": round(vmin + rng * 0.20, 3),
"alarm_v": round(vmin + rng * 0.10, 3),
"warn_v": round(vmin + rng * (warn_pct / 100), 3),
"alarm_v": round(vmin + rng * (alarm_pct / 100), 3),
}
def _lamp_dict(l: Lamp) -> dict:
th = compute_thresholds(l.voltage_min, l.voltage_max)
th = compute_thresholds(l.voltage_min, l.voltage_max,
l.warn_pct or 20.0, l.alarm_pct or 10.0)
return {
"id": l.id,
"manufacturer": l.manufacturer,
@@ -42,6 +46,8 @@ def _lamp_dict(l: Lamp) -> dict:
"lamp_count": l.lamp_count,
"voltage_min": l.voltage_min,
"voltage_max": l.voltage_max,
"warn_pct": l.warn_pct or 20.0,
"alarm_pct": l.alarm_pct or 10.0,
"notes": l.notes,
"warn_v": th["warn_v"],
"alarm_v": th["alarm_v"],