Files
digiserver-v2/docs/SANITIZATION-REVIEW.md
ske087 46602f1933 Sanitize codebase, reorganize docs, and add missing deploy files
Remove dead code identified in docs/SANITIZATION-REVIEW.md:
- app/blueprints/content_old.py and app/blueprints/playlist.py
- app/models/group.py, app/utils/nginx_config_reader.py
- orphaned templates (content_list, edit_content, upload_content,
  player_page) and the related group/Template references

Result: 6 blueprints, 82 routes, no dead modules or orphan templates.

Add files that deploy.sh and docker-entrypoint.sh already require but
which were never tracked:
- https_manager.py       (referenced by deploy.sh, migrate_network.sh,
                          docker-entrypoint.sh)
- Caddyfile.example      (seeded by deploy.sh; its absence aborts deploy)

Relocate generated Graphify artifacts from graphify-out/ to
docs/graphify-out/ (110 files, no content change) and archive the
superseded docs under docs/.

Ignore hygiene:
- ignore ad-hoc .env backups (.env.bak*) — they contain live secrets
- keep the pre-sanitization snapshots (docs/legacy code/,
  docs/old_code_documentation/) on disk but out of the repo

Fix .env.example: drop a duplicated config block, genericize the
hardcoded host IP, and document HOSTNAME_INTERNAL.
2026-09-11 12:18:34 +03:00

10 KiB
Raw Permalink Blame History

DigiServer v2 — Code Sanitization Review

Generated: 2026-09-10 Snapshot: docs/legacy code/ (1.7 MB, 171 files, 49 Python files) — full restore point.

Analysed 42 Python files / 240 functions / 104 routes / 32 templates under app/ and migrations/.

Review each section below and reply with the IDs you want deleted (e.g. A1, A2, B1). Nothing is deleted until you confirm. Everything is recoverable from docs/legacy code/.


Status — Applied 2026-09-10

Removed (A1, A2, D1, D2):

ID Removed Notes
A1 app/blueprints/content_old.py + 3 templates orphaned by its removal
A2 app/utils/nginx_config_reader.py
D1 5 group functions + their __init__.py exports get_player_status_info kept (live)
D2 app/models/group.py, Content.groups, Content.group_count

Extra cleanup triggered by A1/D2:

  • Deleted orphaned templates: upload_content.html (278), edit_content.html (11)
  • Removed the dead groups key from /api/system-info and group_count from /api/content
  • Removed the 'group_id': getattr(player, 'group_id', None) compat shim from /api/player-status
  • Updated 8 documentation files

Also removed (B1, B2) — applied in a second pass:

ID Removed Notes
B1 app/blueprints/playlist.py (310 LOC) + its registration in app.py Whole legacy blueprint; its only real route redirected to content.manage_playlist_content
B2 3 routes in players.py: reorder_content, reorder_playlist, remove_from_playlist (~103 LOC) Two queried nonexistent columns (Content.player_id, Content.position, Player.playlist_version) → guaranteed 500s

Extra cleanup triggered by B1:

  • Deleted content_list.html (202 lines) — its only remaining reference was url_for('playlist.manage_playlist'). It was already orphaned (no Python file rendered it) after content_old.py was deleted, so it has been removed for real this time.
  • Deleted players/player_page.html (227 lines) — it was never rendered by any view (the players.player_page route redirects to manage_player), so it was dead UI. Corrects the earlier "false positive" note below.

⚠️ Functional note: players.regenerate_auth_code (POST /players/<id>/regenerate-auth) is now referenced by no templateplayer_page.html was its only caller. The endpoint still works if invoked directly. The equivalent control lives in manage_player.html via the quickconnect flow. Restore player_page.html from docs/legacy code/ if you want that button back.

Result (A + B + D combined):

42 → 38 Python modules      9,311 → 8,296 LOC
104 → 82 routes             32 → 28 templates
7 → 6 blueprints            dead modules: 2 → 0, orphan templates: 0

Verified: all files compile; smoke test passes on a fresh DB (every API endpoint + key UI route returns < 500); db.metadata no longer registers group/group_content; app boots against a migrated copy of the real dashboard.db with all data intact; app.blueprints no longer contains playlist.

⚠️ Still open: the real data/instance/dashboard.db predates the original_filename migration. On startup the entrypoint now applies it automatically. To fix locally, run:

DATABASE_URL=sqlite:///$PWD/data/instance/dashboard.db ./.venv/bin/python migrations/add_original_filename_to_content.py

Section A — Dead modules (zero importers)

ID Target LOC Evidence Risk
A1 app/blueprints/content_old.py 500 app.py imports content.py; this file's content_bp is never registered. Superseded "old" content workflow. Low
A2 app/utils/nginx_config_reader.py 120 Never imported anywhere. Stack migrated nginx → Caddy, so the reader is obsolete. Low
graph LR
    app_py["app.py<br/>register_blueprints()"] --> content["content.py<br/>content_bp ✅ ACTIVE"]
    content_old["content_old.py<br/>content_bp ❌ DEAD"] -.->|never imported| x1[" "]
    nginx["nginx_config_reader.py<br/>❌ DEAD"] -.->|never imported| x2[" "]
    caddy["caddy_manager.py<br/>✅ ACTIVE"] --> app_py
    style content_old fill:#7f1d1d,color:#fff
    style nginx fill:#7f1d1d,color:#fff

Section B — Legacy duplicate route surface — REMOVED

Two blueprints exposed parallel implementations of the same operations. Only the content.* versions were wired to the UI; the legacy ones had no template references.

ID Target LOC Evidence Risk
B1 app/blueprints/playlist.py (whole file + registration) 310 Entire file was legacy per-player playlist. Its manage_playlist route did nothing but redirect to the modern content.manage_playlist_content. The other 6 routes had no template reference. LowMed
B2 3 routes in players.py: reorder_content, reorder_playlist, remove_from_playlist ~103 Superseded by content.*. Two queried nonexistent columns (Content.player_id, .position, Player.playlist_version) → guaranteed HTTP 500 if called. Low

Duplicate operation matrix

Operation Modern (LIVE) Legacy (DEAD)
Add content content.add_content_to_playlist playlist.add_to_playlist
Remove content content.remove_content_from_playlist playlist.remove_from_playlist, players.remove_from_playlist ⚠️broken
Reorder content.reorder_playlist_content playlist.reorder_playlist, players.reorder_content ⚠️broken, players.reorder_playlist ⚠️broken
Set duration content.update_playlist_content_duration playlist.update_duration
Mute audio content.update_playlist_content_muted playlist.update_muted
Toggle edit content.update_playlist_content_edit_enabled
Clear playlist.clear_playlist

Section C — Broken code: references to columns that do not exist

Confirmed against the live DB schema. These raised AttributeError/OperationalError at runtime. All resolved by deleting A1 + B2.

ID Location Broken reference Reachable?
C1 players.py:768,775 (remove_from_playlist) player.playlist_version Via route only (no UI link)
C2 players.py:~700 (reorder_playlist) Content.player_id, Content.position Via route only (no UI link)
C3 content_old.py:189-190 player.playlist_version No (dead module)
C4 content_old.py:50,57 content.player_id, player.group No (dead module)

Resolved by deleting A1 + B2. If you keep those files, they must be rewritten.

Not a bug (verified by hand): Content._playlist_duration / ._playlist_position / ._playlist_muted in api.py are set dynamically by Playlist.get_content_ordered(). These are intentional and work correctly — the static analyzer flags them because it only sees model class attributes.


Section D — Legacy groups subsystem

Groups are fully deprecated (0 rows, /api/groups already commented out), but the code lingers.

ID Target LOC Evidence Risk
D1 5 group functions in app/utils/group_player_management.py: get_group_statistics, assign_player_to_group, bulk_assign_players_to_group, get_online_players_count, get_players_by_status + their __init__.py exports ~130 Zero callers outside the module. All three group functions reference player.group_id, which does not exist → broken. Low
D2 app/models/group.py (Group model + group_content table) 71 Retained only because Content.groups FK relationship and Content.group_count reference it. Requires touching the Content model. Medium

⚠️ Keep: get_player_status_info() (top of the same file) is live — used at players.py:28 and players.py:432. Only the group functions should go.


Section E — Legacy redirect stubs

Thin compatibility shims that only redirect to the modern UI. They're harmless but keep dead URL surface alive.

ID Target Evidence
E1 players.player_page (/players/<id>) Body is a single redirect(url_for('players.manage_player')). Still url_for-referenced by 2 templates, so keeping it is fine.
E2 playlist.manage_playlist (/playlist/<id>) Part of B1 — already covered by deleting that file.

Section F — Orphan templates / assets

ID Target LOC Evidence
(none) After the B1/B2 pass the codebase has 0 orphan templates.

Batch Contents Total removed Status
Batch 1 — Safe clean A1, A2 ~620 LOC done
Batch 2 — Legacy playlist B1, B2 ~413 LOC done
Batch 3 — Groups D1 ~130 LOC done
Batch 4 — Group model D2 ~71 LOC done

Every batch was followed by: compile-all + app-factory boot + route smoke test, so hidden dependencies were caught before moving on.


How I verified this (so you can trust it)

Check Method
Module reachability AST import extraction + register_blueprint cross-reference
Route usage url_for('endpoint') and literal path matching against all templates/JS
Broken columns Compared every var.attr access against live SQLite PRAGMA table_info
Dynamic attributes Manually inspected get_content_ordered() to rule out false positives
Duplicate bodies ast.dump body hashing across all functions (result: 0 exact duplicates)

Reproduce anytime:

./.venv/bin/python docs/tools/sanitize_report.py     # dead code + broken refs
./.venv/bin/python docs/tools/sanitize_audit.py      # full function inventory
./.venv/bin/python docs/tools/sanitize_templates.py  # orphan templates
./.venv/bin/python docs/tools/smoke_test.py          # post-change smoke test

⚠️ Rollback / hygiene notes

  1. docs/legacy code/ is excluded from the Docker image (via legacy code/ and **/legacy code/ in .dockerignore) so it never ships to production or bloats the build.
  2. It is not git-ignored, so it will appear in git status. Decide:
    • commit it as a recovery point, or
    • add legacy code/ to .gitignore if you'd rather rely on git history.
  3. Deleting files listed here is not recoverable from git unless committed first — the docs/legacy code/ copy is your safety net.