feat: materialize rcon matches and backend detail data
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
---
|
||||
id: TASK-122
|
||||
title: Materialize RCON matches from AdminLog events
|
||||
status: done
|
||||
type: backend
|
||||
team: Backend Senior
|
||||
supporting_teams:
|
||||
- Arquitecto de Base de Datos
|
||||
- Arquitecto Python
|
||||
roadmap_item: rcon-full-data
|
||||
priority: high
|
||||
---
|
||||
|
||||
# TASK-122 - Materialize RCON matches from AdminLog events
|
||||
|
||||
## Goal
|
||||
|
||||
Create a materialization layer that converts RCON AdminLog and useful session/gamestate data into durable RCON match records.
|
||||
|
||||
## Background
|
||||
|
||||
Recent matches need consistent RCON-first scores. AdminLog contains `MATCH START` and `MATCH ENDED` records, while session/gamestate capture can provide partial in-progress scores. A materialized read model should make this data reliable and idempotent before UI changes consume it.
|
||||
|
||||
## Constraints
|
||||
|
||||
- Do not delete or replace existing competitive-window logic.
|
||||
- No UI changes.
|
||||
- Do not reactivate Elo/MMR.
|
||||
- Do not reintroduce Comunidad Hispana #03.
|
||||
- Do not store secrets, runtime DB files or `backend/runtime`.
|
||||
- Preserve RCON as the source of truth; public scoreboard is optional enrichment/fallback only.
|
||||
|
||||
## Allowed Changes
|
||||
|
||||
- backend storage/model modules for materialized RCON matches
|
||||
- backend tests for materialization
|
||||
- small wiring needed to initialize/read the new table
|
||||
- this task file when moving it through the workflow
|
||||
|
||||
## Implementation Requirements
|
||||
|
||||
- Work from a dedicated branch for this task.
|
||||
- Read first:
|
||||
- `AGENTS.md`
|
||||
- `ai/architecture-index.md`
|
||||
- `ai/repo-context.md`
|
||||
- `ai/orchestrator/backend-senior.md`
|
||||
- `ai/orchestrator/database-architect.md`
|
||||
- `backend/app/rcon_admin_log_storage.py`
|
||||
- `backend/app/rcon_admin_log_parser.py`
|
||||
- `backend/app/rcon_historical_read_model.py`
|
||||
- existing historical storage modules
|
||||
- Derive RCON matches from:
|
||||
- `match_start`
|
||||
- `match_end`
|
||||
- session/gamestate samples where useful
|
||||
- Store materialized records in SQLite, using a table such as `rcon_materialized_matches`.
|
||||
- Include fields for `id`, `target_key`, `external_server_id`, `match_key` or `session_key`, `map_name`, `map_pretty_name`, `game_mode`, server/event start/end times, scores, winner, `confidence_mode`, `source_basis`, `created_at` and `updated_at`.
|
||||
- Make materialization idempotent.
|
||||
- Treat `MATCH ENDED` as authoritative result when present.
|
||||
- Treat session/gamestate scores as partial or in-progress when no `MATCH ENDED` exists.
|
||||
- Parse and test results including 5-0, 2-2 and 0-5.
|
||||
|
||||
## Validation Commands
|
||||
|
||||
- `python -m compileall backend/app`
|
||||
- `python -m pytest backend/tests/<new_or_relevant_materialized_match_tests>.py`
|
||||
|
||||
## Manual Verification Steps
|
||||
|
||||
- Confirm repeated materialization does not duplicate matches.
|
||||
- Confirm a sample `MATCH ENDED \`ST MARIE DU MONT Warfare\` ALLIED (5 - 0) AXIS` produces the expected score and winner.
|
||||
- Confirm existing competitive-window reads still work.
|
||||
- Confirm `/health` still works.
|
||||
- Confirm `git diff --name-only` matches the allowed scope.
|
||||
|
||||
## Git Requirements
|
||||
|
||||
- Create a dedicated branch for this task, for example `codex/task-122-rcon-match-materialization`.
|
||||
- Run relevant validation before committing.
|
||||
- Stage only intended files.
|
||||
- Commit the completed implementation.
|
||||
- Push the branch to origin.
|
||||
|
||||
## Outcome
|
||||
|
||||
Implemented `backend/app/rcon_admin_log_materialization.py` with idempotent SQLite tables for `rcon_materialized_matches` and the shared materialization command `python -m app.rcon_admin_log_materialization`. Match records are derived from AdminLog `match_start` and `match_end` events, with `MATCH ENDED` results stored as authoritative `admin-log-match-ended` rows. Session windows remain available as partial fallback without deleting the existing competitive-window code.
|
||||
|
||||
The command also exposes `python -m app.rcon_admin_log_materialization status` for materialization diagnostics: materialized match count, matches with player stats, first/last server time by target and event counts by type.
|
||||
|
||||
No server #03 target was reintroduced, Elo/MMR was not reactivated, and no runtime DB files were committed.
|
||||
|
||||
## Validation Result
|
||||
|
||||
- Passed: `python -m compileall backend/app`
|
||||
- Pytest was not installed in the local Python environment.
|
||||
- Passed deterministic fallback: `$env:PYTHONPATH='backend'; python -m unittest backend.tests.test_rcon_materialization_pipeline backend.tests.test_scoreboard_match_links`
|
||||
- Passed Docker smoke: `docker compose up -d --build backend rcon-historical-worker`
|
||||
- Passed Docker materialization: `docker compose exec backend python -m app.rcon_admin_log_materialization` reported `matches_seen: 24`, `matches_materialized: 24`, `errors: []`.
|
||||
- Passed diagnostic command: `docker compose exec backend python -m app.rcon_admin_log_materialization status`.
|
||||
@@ -0,0 +1,96 @@
|
||||
---
|
||||
id: TASK-123
|
||||
title: Materialize RCON player match stats
|
||||
status: done
|
||||
type: backend
|
||||
team: Backend Senior
|
||||
supporting_teams:
|
||||
- Arquitecto de Base de Datos
|
||||
- Arquitecto Python
|
||||
roadmap_item: rcon-full-data
|
||||
priority: high
|
||||
---
|
||||
|
||||
# TASK-123 - Materialize RCON player match stats
|
||||
|
||||
## Goal
|
||||
|
||||
Build first-pass per-match player statistics from RCON AdminLog kill, team and presence events.
|
||||
|
||||
## Background
|
||||
|
||||
The internal match detail page should eventually show a simplified scoreboard-like view backed by RCON. AdminLog includes `KILL`, `TEAMSWITCH`, `CONNECTED` and `DISCONNECTED` events that can produce kills, deaths, teamkills, weapon counts and player presence.
|
||||
|
||||
## Constraints
|
||||
|
||||
- No UI changes.
|
||||
- Do not expose raw player IDs in frontend work.
|
||||
- Do not reactivate Elo/MMR.
|
||||
- Do not reintroduce Comunidad Hispana #03.
|
||||
- Do not store secrets, runtime DB files or `backend/runtime`.
|
||||
- Keep rematerialization deterministic and idempotent.
|
||||
|
||||
## Allowed Changes
|
||||
|
||||
- backend materialization/storage code for RCON player match stats
|
||||
- optional structured event timeline table or read logic
|
||||
- backend tests and fixtures
|
||||
- this task file when moving it through the workflow
|
||||
|
||||
## Implementation Requirements
|
||||
|
||||
- Work from a dedicated branch for this task.
|
||||
- Read first:
|
||||
- `AGENTS.md`
|
||||
- `ai/architecture-index.md`
|
||||
- `ai/repo-context.md`
|
||||
- `ai/orchestrator/backend-senior.md`
|
||||
- `ai/orchestrator/database-architect.md`
|
||||
- `backend/app/rcon_admin_log_parser.py`
|
||||
- `backend/app/rcon_admin_log_storage.py`
|
||||
- materialized match code from TASK-122
|
||||
- Use parsed events from `rcon_admin_log_events`.
|
||||
- Associate events to matches by target and server-time range between `match_start` and `match_end`.
|
||||
- Create a table such as `rcon_match_player_stats` with target, match, player identity/display, team, kills, deaths, teamkills, deaths by teamkill, weapon JSON, death-by weapon JSON, most-killed JSON, death-by JSON and first/last seen server time.
|
||||
- Optionally create `rcon_match_events` for structured timeline rows, or read directly from AdminLog events.
|
||||
- For `KILL`, add one kill to the killer when teams differ, add one death to the victim, and count same-team kills as teamkills plus victim deaths by teamkill.
|
||||
- Track weapon counts and killer-victim counts.
|
||||
- Use connected/disconnected/team switch events to improve presence and team attribution.
|
||||
- Handle missing or non-Steam-style player IDs robustly.
|
||||
|
||||
## Validation Commands
|
||||
|
||||
- `python -m compileall backend/app`
|
||||
- `python -m pytest backend/tests/<new_or_relevant_player_stats_tests>.py`
|
||||
|
||||
## Manual Verification Steps
|
||||
|
||||
- Validate offline fixtures containing `KILL`, `TEAMSWITCH`, `CONNECTED` and `DISCONNECTED`.
|
||||
- Confirm kills, deaths, teamkills, weapons, most killed and death-by summaries.
|
||||
- Confirm repeated materialization does not duplicate or inflate stats.
|
||||
- Confirm `/health` still works.
|
||||
- Confirm `git diff --name-only` matches the allowed scope.
|
||||
|
||||
## Git Requirements
|
||||
|
||||
- Create a dedicated branch for this task, for example `codex/task-123-rcon-player-stats`.
|
||||
- Run relevant validation before committing.
|
||||
- Stage only intended files.
|
||||
- Commit the completed implementation.
|
||||
- Push the branch to origin.
|
||||
|
||||
## Outcome
|
||||
|
||||
Implemented AdminLog-derived `rcon_match_player_stats` materialization in `backend/app/rcon_admin_log_materialization.py`. The materializer associates kill/presence events to materialized matches by target and server-time range, rebuilds stats deterministically on each run, and handles Steam-style and non-Steam player identifiers without exposing them in the match-detail read model.
|
||||
|
||||
Kill logic now records kills, deaths, teamkills, deaths by teamkill, weapon counts, death-by weapon counts, most-killed summaries and death-by summaries. Presence events are used when they include stable player identity, while team-switch rows without player IDs are ignored for identity creation to avoid duplicate display-name-only player rows.
|
||||
|
||||
Non-blocking follow-up note: suspicious live/session queue fields remain worth reviewing separately. In previous worker output, `vip_queue_count` appeared as `464/434` while `max_vip_queue_count` was `2`; this batch did not change that parser path.
|
||||
|
||||
## Validation Result
|
||||
|
||||
- Passed: `python -m compileall backend/app`
|
||||
- Pytest was not installed in the local Python environment.
|
||||
- Passed deterministic fallback: `$env:PYTHONPATH='backend'; python -m unittest backend.tests.test_rcon_materialization_pipeline backend.tests.test_scoreboard_match_links`
|
||||
- Passed Docker AdminLog ingestion: `docker compose exec backend python -m app.rcon_admin_log_ingestion --minutes 1440` reported `events_seen: 143`, `errors: []`.
|
||||
- Passed Docker materialization: `docker compose exec backend python -m app.rcon_admin_log_materialization` reported `player_stats_seen: 22`, `player_stats_materialized: 22`, `errors: []`.
|
||||
98
ai/tasks/done/TASK-124-add-internal-rcon-match-detail-api.md
Normal file
98
ai/tasks/done/TASK-124-add-internal-rcon-match-detail-api.md
Normal file
@@ -0,0 +1,98 @@
|
||||
---
|
||||
id: TASK-124
|
||||
title: Add internal RCON match detail API
|
||||
status: done
|
||||
type: backend
|
||||
team: Backend Senior
|
||||
supporting_teams:
|
||||
- Arquitecto Python
|
||||
- Frontend Senior
|
||||
roadmap_item: rcon-full-data
|
||||
priority: high
|
||||
---
|
||||
|
||||
# TASK-124 - Add internal RCON match detail API
|
||||
|
||||
## Goal
|
||||
|
||||
Expose internal match detail data from materialized RCON matches and player stats.
|
||||
|
||||
## Background
|
||||
|
||||
`frontend/historico-partida.html` needs a reliable internal backend payload when an external scoreboard link is unavailable or not safely correlated. The API should be RCON-first and graceful for partial or old data.
|
||||
|
||||
## Constraints
|
||||
|
||||
- No UI changes in this task.
|
||||
- Preserve existing query params and fallback behavior.
|
||||
- If no materialized RCON detail exists, return a controlled empty or partial payload, not a 500.
|
||||
- Do not reactivate Elo/MMR.
|
||||
- Do not reintroduce Comunidad Hispana #03.
|
||||
- Do not store secrets, runtime DB files or `backend/runtime`.
|
||||
- Public scoreboard URL is optional enrichment only.
|
||||
|
||||
## Allowed Changes
|
||||
|
||||
- `backend/app/routes.py` or existing route modules
|
||||
- backend read-model modules for historical match detail
|
||||
- backend tests for response builder/read model
|
||||
- this task file when moving it through the workflow
|
||||
|
||||
## Implementation Requirements
|
||||
|
||||
- Work from a dedicated branch for this task.
|
||||
- Read first:
|
||||
- `AGENTS.md`
|
||||
- `ai/architecture-index.md`
|
||||
- `ai/repo-context.md`
|
||||
- `ai/orchestrator/backend-senior.md`
|
||||
- `backend/app/routes.py`
|
||||
- `backend/app/rcon_historical_read_model.py`
|
||||
- materialized match/player stats code from TASK-122 and TASK-123
|
||||
- `frontend/historico-partida.html`
|
||||
- `frontend/assets/js/historico-partida.js`
|
||||
- Extend or add `/api/historical/matches/detail?server=...&match=...`.
|
||||
- Prefer an existing endpoint if present and do not break current query params.
|
||||
- Response should include server, match id, map, game mode, start/end, duration, result, winner, confidence/source basis, optional external `match_url`, player rows and timeline/event summary.
|
||||
- Player rows should include display name, team, kills, deaths, teamkills, K/D, top weapons, most killed and death-by summary.
|
||||
- Keep old data fallbacks controlled and backwards-compatible.
|
||||
|
||||
## Validation Commands
|
||||
|
||||
- `python -m compileall backend/app`
|
||||
- `python -m pytest backend/tests/<new_or_relevant_match_detail_api_tests>.py`
|
||||
- `docker compose up -d --build backend`
|
||||
- `Invoke-WebRequest "http://localhost:8000/api/historical/matches/detail?server=<server>&match=<match>"`
|
||||
- `Invoke-WebRequest "http://localhost:8000/health"`
|
||||
|
||||
## Manual Verification Steps
|
||||
|
||||
- Confirm known materialized match detail returns the expected summary and players.
|
||||
- Confirm missing materialized data returns a controlled partial payload.
|
||||
- Confirm `/health` still works.
|
||||
- Confirm no server #03, Elo/MMR or secrets were introduced.
|
||||
- Confirm `git diff --name-only` matches the allowed scope.
|
||||
|
||||
## Git Requirements
|
||||
|
||||
- Create a dedicated branch for this task, for example `codex/task-124-rcon-match-detail-api`.
|
||||
- Run relevant validation before committing.
|
||||
- Stage only intended files.
|
||||
- Commit the completed implementation.
|
||||
- Push the branch to origin.
|
||||
|
||||
## Outcome
|
||||
|
||||
Extended the existing RCON historical read model behind `/api/historical/matches/detail?server=...&match=...` to prefer materialized RCON AdminLog match detail when available, while preserving the existing competitive-window and public-scoreboard fallback behavior.
|
||||
|
||||
Materialized detail payloads now include server, match id, map, game mode, start/end, duration, result, winner, confidence/source basis, safe optional `match_url`, player rows and timeline event counts. Player rows expose display names and derived summaries only, not raw player IDs.
|
||||
|
||||
Missing materialized detail remains controlled: the endpoint falls back to the existing paths and returns `found: false` instead of raising a 500 when no detail is available.
|
||||
|
||||
## Validation Result
|
||||
|
||||
- Passed: `python -m compileall backend/app`
|
||||
- Pytest was not installed in the local Python environment.
|
||||
- Passed deterministic fallback: `$env:PYTHONPATH='backend'; python -m unittest backend.tests.test_rcon_materialization_pipeline backend.tests.test_scoreboard_match_links`
|
||||
- Passed API smoke: `Invoke-WebRequest "http://localhost:8000/health"`.
|
||||
- Passed API detail check: `Invoke-WebRequest "http://localhost:8000/api/historical/matches/detail?server=comunidad-hispana-02&match=comunidad-hispana-02:1779108337:1779111786:stmariedumontwarfare"` returned `found: true`, `result_source: admin-log-match-ended`, players and timeline counts.
|
||||
@@ -0,0 +1,101 @@
|
||||
---
|
||||
id: TASK-125
|
||||
title: Prefer materialized RCON recent matches
|
||||
status: done
|
||||
type: backend
|
||||
team: Backend Senior
|
||||
supporting_teams:
|
||||
- Frontend Senior
|
||||
roadmap_item: rcon-full-data
|
||||
priority: high
|
||||
---
|
||||
|
||||
# TASK-125 - Prefer materialized RCON recent matches
|
||||
|
||||
## Goal
|
||||
|
||||
Update the recent matches API to prefer materialized RCON match records over approximate competitive windows and public-scoreboard fallback.
|
||||
|
||||
## Background
|
||||
|
||||
End users should see correct scores as consistently as possible. RCON AdminLog `MATCH ENDED` data should be the primary source when available, with active RCON sessions next and public scoreboard only as fallback or degraded enrichment.
|
||||
|
||||
## Constraints
|
||||
|
||||
- No frontend changes unless strictly necessary for contract compatibility.
|
||||
- Do not show stale public scoreboard as selected source when RCON is healthy.
|
||||
- Do not reactivate Elo/MMR.
|
||||
- Do not reintroduce Comunidad Hispana #03.
|
||||
- Do not store secrets, runtime DB files or `backend/runtime`.
|
||||
- Preserve RCON-first policy.
|
||||
|
||||
## Allowed Changes
|
||||
|
||||
- backend recent matches read model modules
|
||||
- backend route tests or read-model tests
|
||||
- minimal compatibility-only frontend changes if unavoidable and justified
|
||||
- this task file when moving it through the workflow
|
||||
|
||||
## Implementation Requirements
|
||||
|
||||
- Work from a dedicated branch for this task.
|
||||
- Read first:
|
||||
- `AGENTS.md`
|
||||
- `ai/architecture-index.md`
|
||||
- `ai/repo-context.md`
|
||||
- `ai/orchestrator/backend-senior.md`
|
||||
- `backend/app/routes.py`
|
||||
- `backend/app/rcon_historical_read_model.py`
|
||||
- existing recent matches read-model/storage modules
|
||||
- materialized match code from TASK-122
|
||||
- Use priority:
|
||||
- materialized RCON matches with `MATCH ENDED` result
|
||||
- active/partial RCON session windows with current gamestate
|
||||
- public-scoreboard fallback only if RCON is unavailable or explicitly degraded
|
||||
- Recent match items should expose result scores/winner when available.
|
||||
- Add `result_source` values: `admin-log-match-ended`, `rcon-session`, `public-scoreboard-fallback`, `unavailable`.
|
||||
- Include `match_url` only when safe external link exists.
|
||||
- Include internal detail link data whenever match id and server allow it.
|
||||
|
||||
## Validation Commands
|
||||
|
||||
- `python -m compileall backend/app`
|
||||
- `python -m pytest backend/tests/<new_or_relevant_recent_matches_tests>.py`
|
||||
- `docker compose up -d --build backend`
|
||||
- `docker compose exec backend python -m app.rcon_admin_log_ingestion --minutes 1440`
|
||||
- `Invoke-WebRequest "http://localhost:8000/api/historical/recent-matches?server=all-servers&limit=10"`
|
||||
|
||||
## Manual Verification Steps
|
||||
|
||||
- Confirm recent matches show RCON/AdminLog scores where available.
|
||||
- Confirm source priority uses AdminLog over stale public scoreboard.
|
||||
- Confirm internal detail data exists for match cards.
|
||||
- Confirm `/health` and `frontend/historico.html` are not broken.
|
||||
- Confirm `git diff --name-only` matches the allowed scope.
|
||||
|
||||
## Git Requirements
|
||||
|
||||
- Create a dedicated branch for this task, for example `codex/task-125-rcon-recent-matches-priority`.
|
||||
- Run relevant validation before committing.
|
||||
- Stage only intended files.
|
||||
- Commit the completed implementation.
|
||||
- Push the branch to origin.
|
||||
|
||||
## Outcome
|
||||
|
||||
Updated the RCON historical recent-matches read model to prefer materialized AdminLog matches with authoritative `MATCH ENDED` results before using active/session competitive windows. Public-scoreboard recent matches remain fallback only when RCON read coverage is unavailable or empty.
|
||||
|
||||
Recent match rows now include `result_source` values for the implemented paths:
|
||||
|
||||
- `admin-log-match-ended`
|
||||
- `rcon-session`
|
||||
- `public-scoreboard-fallback`
|
||||
|
||||
The payload builder no longer selects the public scoreboard merely to fill the requested limit when RCON has usable materialized/session results. Stale local historical targets such as `comunidad-hispana-03` are not re-added to configuration or shown as configured RCON targets by this batch.
|
||||
|
||||
## Validation Result
|
||||
|
||||
- Passed: `python -m compileall backend/app`
|
||||
- Pytest was not installed in the local Python environment.
|
||||
- Passed deterministic fallback: `$env:PYTHONPATH='backend'; python -m unittest backend.tests.test_rcon_materialization_pipeline backend.tests.test_scoreboard_match_links`
|
||||
- Passed API recent-matches check: `Invoke-WebRequest "http://localhost:8000/api/historical/recent-matches?server=all-servers&limit=10"` returned `selected_source: rcon`, `fallback_used: false`, and materialized rows with `result_source: admin-log-match-ended`.
|
||||
@@ -0,0 +1,93 @@
|
||||
---
|
||||
id: TASK-126
|
||||
title: Correlate scoreboard links with RCON materialized matches
|
||||
status: done
|
||||
type: backend
|
||||
team: Backend Senior
|
||||
supporting_teams:
|
||||
- Arquitecto Python
|
||||
roadmap_item: rcon-full-data
|
||||
priority: medium
|
||||
---
|
||||
|
||||
# TASK-126 - Correlate scoreboard links with RCON materialized matches
|
||||
|
||||
## Goal
|
||||
|
||||
Safely correlate materialized RCON matches with public scoreboard game URLs when a high-confidence match exists.
|
||||
|
||||
## Background
|
||||
|
||||
Match cards should link to the public scoreboard only when safe correlation exists. RCON remains the primary data source; public scoreboard links are optional enrichment and should never open arbitrary domains.
|
||||
|
||||
## Constraints
|
||||
|
||||
- No UI changes.
|
||||
- Do not reactivate Elo/MMR.
|
||||
- Do not reintroduce Comunidad Hispana #03.
|
||||
- Do not store secrets, runtime DB files or `backend/runtime`.
|
||||
- Do not treat public scoreboard as source of truth for RCON data.
|
||||
- If correlation fails, internal detail links must still work.
|
||||
|
||||
## Allowed Changes
|
||||
|
||||
- existing scoreboard origin catalog/correlation code if present
|
||||
- backend safe URL/correlation storage or cache code
|
||||
- backend tests
|
||||
- this task file when moving it through the workflow
|
||||
|
||||
## Implementation Requirements
|
||||
|
||||
- Work from a dedicated branch for this task.
|
||||
- Read first:
|
||||
- `AGENTS.md`
|
||||
- `ai/architecture-index.md`
|
||||
- `ai/repo-context.md`
|
||||
- `ai/orchestrator/backend-senior.md`
|
||||
- `backend/app/scoreboard_origin_catalog.py` if present
|
||||
- existing scoreboard link correlation modules
|
||||
- materialized match code from TASK-122
|
||||
- Correlate by server, map, end time/server time where possible, duration where possible and player count/peak players where available.
|
||||
- Support known origins:
|
||||
- Comunidad Hispana #01: `https://scoreboard.comunidadhll.es`
|
||||
- Comunidad Hispana #02: `https://scoreboard.comunidadhll.es:5443`
|
||||
- Only return external `match_url` for expected origins and `/games/<id>` paths.
|
||||
- Store or cache correlation result if appropriate.
|
||||
- Include a manual check for `https://scoreboard.comunidadhll.es/games/1561515`.
|
||||
|
||||
## Validation Commands
|
||||
|
||||
- `python -m compileall backend/app`
|
||||
- `python -m pytest backend/tests/<new_or_relevant_scoreboard_correlation_tests>.py`
|
||||
|
||||
## Manual Verification Steps
|
||||
|
||||
- Confirm safe URL allowlist rejects arbitrary domains and paths.
|
||||
- Confirm #01 and #02 origin selection works.
|
||||
- Confirm no server #03 is added to catalogs, defaults or tests.
|
||||
- Confirm failed correlation still leaves internal detail links available.
|
||||
- Confirm `git diff --name-only` matches the allowed scope.
|
||||
|
||||
## Git Requirements
|
||||
|
||||
- Create a dedicated branch for this task, for example `codex/task-126-rcon-scoreboard-correlation`.
|
||||
- Run relevant validation before committing.
|
||||
- Stage only intended files.
|
||||
- Commit the completed implementation.
|
||||
- Push the branch to origin.
|
||||
|
||||
## Outcome
|
||||
|
||||
Kept scoreboard correlation as optional enrichment over RCON-backed match data. Materialized RCON recent/detail payloads call the existing correlation path and only expose `match_url` when the persisted public scoreboard candidate belongs to the trusted origin for the active server.
|
||||
|
||||
Hardened trusted scoreboard URL validation so only the known #01 and #02 origins and `/games/<id>` paths are accepted. Arbitrary domains, wrong ports, non-game paths, credentials, query strings and fragments are rejected. Comunidad Hispana #03 was not reintroduced.
|
||||
|
||||
If correlation fails, the internal materialized detail payload still works and simply returns `match_url: null`.
|
||||
|
||||
## Validation Result
|
||||
|
||||
- Passed: `python -m compileall backend/app`
|
||||
- Pytest was not installed in the local Python environment.
|
||||
- Passed deterministic fallback: `$env:PYTHONPATH='backend'; python -m unittest backend.tests.test_rcon_materialization_pipeline backend.tests.test_scoreboard_match_links`
|
||||
- Passed safe URL allowlist coverage for Comunidad Hispana #01 and #02 in `backend.tests.test_rcon_materialization_pipeline`.
|
||||
- Passed existing scoreboard correlation regression suite in `backend.tests.test_scoreboard_match_links`.
|
||||
Reference in New Issue
Block a user