* feat: poll peer_dynamic_tgs.need_reload for dynamic TG purge
Proxy send_opts and fallback loop apply TG-4000-equivalent reset when the
monitor sets need_reload, with migration 006 and restore filter updates.
* chore: fix import order in voice subscription plan test
After a server restart, Clients.logged_in stayed 1 for peers no longer
connected, letting the monitor authenticate disconnected hotspots via
login-by-ip. Replace the hourly clean_tbl (24h idle sweep) with a
reconcile in the existing 120s lst_seen loop: connected peers get
logged_in=1, the rest 0. The lst_seen loop now starts with now=True so
its first tick at boot clears all stale flags immediately.
* fix: add shared PASS= redaction for OPTIONS log lines
Mask PASS= secrets in RPTO/OPTIONS logging to avoid leaking hotspot
passwords in log files.
* fix: rework self-service RPTO to distinguish PASS, empty, and OPTIONS
Three RPTO cases now handled explicitly:
- PASS=password: store hash, fetch OPTIONS from DB (unchanged)
- Empty payload: DB is the authority, fetch OPTIONS from DB
- OPTIONS with content: hotspot is the authority, pass through to master
When the hotspot does not send PASS, the stored password is cleared
(NULL) so only IP auto-login works — password login is impossible
with a NULL hash, matching the legacy dashboard proxy behaviour.
Also removes the noisy DEBUG log on RPTC ("not in mysql_option_peers")
that fired on every normal login, and adds clear_psswd action to the
MySQL repository for explicit NULL writes.
* fix: elevate proxy attach rejection to WARNING for RPTC/RPTO
Control commands (RPTC/RPTO) rejected by attach should be visible at
INFO level, not hidden behind a debug flag, since they indicate a peer
sending configuration before the login exchange completed.
* fix: remove noisy CALL RX log on OBP DMRE voice header
The log fired on every DMRE VHEAD packet from each OBP peer, producing
duplicate entries for the same stream (multiple OBP peers relay the
same call). The existing CALL RX logs for DMRD and OBP v0/v1 paths
already cover stream start diagnostics.
* fix: fetch DB options when hotspot sends no RPTO after RPTC
Some hotspots complete the RPTC (repeater configuration) step but never
send an RPTO packet, leaving the peer without any OPTIONS applied. The
legacy proxy used a 10s timer after RPTC to fetch OPTIONS from MySQL in
that case; restore that behaviour here.
When RPTC arrives and the peer is not already in _mysql_option_peers,
schedule a 10s fallback timer. If no RPTO arrives before it fires, treat
the peer the same as an empty RPTO (BD is the authority) and fetch
OPTIONS from MySQL. If an RPTO does arrive, the existing cancel paths
abort the timer.
* feat: persist peer dynamic TGs in MariaDB across reconnects
Add DATABASE config, async DynamicTgStore, and restore on RPTC so
SINGLE=0/1 dynamics survive hotspot disconnects and server restarts
without blocking the DMRD voice path.
* fix: ensure peer_dynamic_tgs table on server startup
Apply migration 004 idempotently at boot so the server does not depend
on adn-monitor db_bootstrap when peer_dynamic_tgs is missing.
* fix: import DynamicTgEntry for ruff F821 in subscription_table
* fix: log clear MariaDB startup failures to file and stderr
Validate DATABASE at config load and on connect; map common MySQL
errors to actionable messages so the server does not fail silently.
* fix: TG 4000 clears STATUS and bridge legs after dynamic reset
Clear RX slot state to stop RPTO re-seeding cleared sessions, run
in-band 4000 deactivation on inject-only paths, and mark downlink dirty.
* fix: complete TG 4000 reset for monitor and dynamic TG persistence
Emit INGRESS BRDG_EVENT so SINGLE=0 UA chips clear without stuck TX;
wipe all peer dynamic rows from memory and MariaDB on reset. Never store
TG 4000 as a UA session. Require DATABASE only for full peer-server configs.
Normalize all Python sources to the standard ADN copyright block with
complete GPLv3 notice. Add legacy attribution on routing and dmr_utils
ports; drop SemVer wording from changelog and fix an unused test import.
Push STATE_SND when peers send RPTO so monitor chips update without reload.
Fetch and inject MySQL OPTIONS immediately on PASS= instead of a 10s delay.
Track per-peer dynamic TG sets for SINGLE=0 so keyed hotspots hear each other.
Enforce strict SINGLE=1 RX exclusivity, always filter inject-only downlink by
each peer's own OPTIONS, and push self-service DB options only after PASS=.
Stop merged SYSTEM static TG lists from leaking across hotspots in topology.