diff --git a/.claude/plan/arma3-ux-enhancement.md b/.claude/plan/arma3-ux-enhancement.md
index c70d940..56e498f 100644
--- a/.claude/plan/arma3-ux-enhancement.md
+++ b/.claude/plan/arma3-ux-enhancement.md
@@ -2,7 +2,23 @@
**Status:** APPROVED — Ready to implement
**Branch:** main
-**Estimated effort:** ~20h total (6 phases)
+**Estimated effort:** ~20h total (5 active phases)
+
+---
+
+## Progress Tracker
+
+> **IMPLEMENTING AGENT:** Update this section at the start and end of each session. Mark each phase `[x]` when ALL its checklist items pass. This is the only reliable way for the next session to know where to pick up.
+
+| Phase | Status | Last session note |
+|-------|--------|------------------|
+| 1 — Config UI Schema | `[ ] not started` | |
+| 2 — Mission Rotation | `[ ] not started` | |
+| 3 — Mod Display Names + Split Pane | `[ ] not started` | |
+| 4 — Player Kick/Ban | `[ ] not started` | |
+| 5 — Log File Browser | `[ ] not started` | |
+
+**How to resume:** Read this table first. Find the first phase that is not `[x] done`. Read only that phase section — do not re-read earlier phases. Run `cd frontend && npx tsc --noEmit` to confirm the build is clean before making any changes.
---
@@ -159,8 +175,8 @@ frontend/src/
| 4 | Player Kick/Ban | MUST | ~3h |
| 2 | Mission Rotation + Multi-file upload | MUST | ~5h |
| 3 | Mod Display Names + Split Pane | GOOD | ~4h |
-| 6 | Server Card Quick Actions | GOOD | ~1h |
| 5 | Log File Browser + Level Filter | GOOD | ~3h |
+| 6 | Server Card Quick Actions | ~~GOOD~~ | **DONE** |
---
@@ -176,16 +192,17 @@ Add this method to `Arma3ConfigGenerator`:
def get_ui_schema(self) -> dict:
return {
"server": {
+ # Field names MUST match Arma3ConfigGenerator.ServerConfig exactly
"hostname": {"widget": "text", "label": "Server Hostname"},
- "max_players": {"widget": "number", "label": "Max Players", "min": 1, "max": 256},
+ "max_players": {"widget": "number", "label": "Max Players", "min": 1, "max": 1000},
"password": {"widget": "password", "label": "Player Password"},
- "admin_password": {"widget": "password", "label": "Admin Password"},
+ "password_admin": {"widget": "password", "label": "Admin Password"}, # NOT admin_password
"motd_lines": {"widget": "textarea", "label": "Message of the Day (one line per row)"},
"forced_difficulty": {"widget": "select", "label": "Difficulty Preset",
- "options": ["", "Recruit", "Regular", "Veteran", "Custom"]},
- "battle_eye": {"widget": "toggle", "label": "BattleEye Anti-Cheat"},
- "von": {"widget": "toggle", "label": "Voice over Net (VoN)"},
- "verify_signatures": {"widget": "toggle", "label": "Verify Addon Signatures"},
+ "options": ["Recruit", "Regular", "Veteran", "Custom"]},
+ "battleye": {"widget": "toggle", "label": "BattleEye Anti-Cheat"}, # NOT battle_eye
+ "disable_von": {"widget": "toggle", "label": "Disable Voice over Net (VoN)"}, # NOT von — and it's inverted
+ "verify_signatures": {"widget": "number", "label": "Verify Signatures (0=off, 1=on, 2=strict)", "min": 0, "max": 2},
"persistent": {"widget": "toggle", "label": "Persistent (keep running when empty)"},
"admin_uids": {"widget": "tag-list", "label": "Admin Steam UIDs",
"placeholder": "76561198000000000"},
@@ -207,10 +224,11 @@ def get_ui_schema(self) -> dict:
### 1.2 `backend/core/servers/service.py` — add `get_config_schema()`
+Follow the existing pattern: `ServerService.__init__` already stores `self._server_repo` and `self._config_repo`. No `db` param needed:
```python
-async def get_config_schema(self, server_id: int, db: Session) -> dict:
- server = self.server_repo.get_by_id(server_id, db)
- adapter = self.adapter_registry.get(server.game_type)
+def get_config_schema(self, server_id: int) -> dict:
+ server = self.get_server(server_id) # raises 404 if not found, uses self._server_repo
+ adapter = GameAdapterRegistry.get(server["game_type"])
config_gen = adapter.get_config_generator()
if hasattr(config_gen, "get_ui_schema"):
return config_gen.get_ui_schema()
@@ -219,16 +237,16 @@ async def get_config_schema(self, server_id: int, db: Session) -> dict:
### 1.3 `backend/core/servers/router.py` — new endpoint
-Add after existing config routes:
+Add after existing config routes, following the `ServerService(db)` inline pattern:
```python
@router.get("/{server_id}/config/schema")
-async def get_config_schema(
+def get_config_schema(
server_id: int,
- db: Session = Depends(get_db),
- current_user: User = Depends(get_current_user),
-):
- schema = await server_service.get_config_schema(server_id, db)
- return {"success": True, "data": schema}
+ db: Annotated[Connection, Depends(get_db)],
+ _user: Annotated[dict, Depends(get_current_user)],
+) -> dict:
+ schema = ServerService(db).get_config_schema(server_id)
+ return {"success": True, "data": schema, "error": None}
```
### 1.4 `frontend/src/hooks/useServerDetail.ts` — add schema types + hook
@@ -282,7 +300,7 @@ export function TagListEditor({ value, onChange, placeholder, disabled }: TagLis
{value.map((item, idx) => (
))}
-