django-micboard 26.7.15__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (485) hide show
  1. django_micboard-26.7.15/.env.example +23 -0
  2. django_micboard-26.7.15/CHANGELOG.md +561 -0
  3. django_micboard-26.7.15/CONTRIBUTING.md +341 -0
  4. django_micboard-26.7.15/LICENSE +664 -0
  5. django_micboard-26.7.15/MANIFEST.in +23 -0
  6. django_micboard-26.7.15/PKG-INFO +555 -0
  7. django_micboard-26.7.15/README.md +379 -0
  8. django_micboard-26.7.15/django_micboard.egg-info/PKG-INFO +555 -0
  9. django_micboard-26.7.15/django_micboard.egg-info/SOURCES.txt +483 -0
  10. django_micboard-26.7.15/django_micboard.egg-info/dependency_links.txt +1 -0
  11. django_micboard-26.7.15/django_micboard.egg-info/entry_points.txt +2 -0
  12. django_micboard-26.7.15/django_micboard.egg-info/requires.txt +157 -0
  13. django_micboard-26.7.15/django_micboard.egg-info/top_level.txt +1 -0
  14. django_micboard-26.7.15/micboard/__init__.py +32 -0
  15. django_micboard-26.7.15/micboard/admin/__init__.py +34 -0
  16. django_micboard-26.7.15/micboard/admin/activity_logs.py +326 -0
  17. django_micboard-26.7.15/micboard/admin/assignments.py +98 -0
  18. django_micboard-26.7.15/micboard/admin/channel_forms.py +52 -0
  19. django_micboard-26.7.15/micboard/admin/channels.py +331 -0
  20. django_micboard-26.7.15/micboard/admin/chargers.py +48 -0
  21. django_micboard-26.7.15/micboard/admin/configuration.py +317 -0
  22. django_micboard-26.7.15/micboard/admin/discovery.py +48 -0
  23. django_micboard-26.7.15/micboard/admin/discovery_admin.py +347 -0
  24. django_micboard-26.7.15/micboard/admin/display_wall.py +47 -0
  25. django_micboard-26.7.15/micboard/admin/forms.py +112 -0
  26. django_micboard-26.7.15/micboard/admin/integrations.py +282 -0
  27. django_micboard-26.7.15/micboard/admin/manufacturers.py +98 -0
  28. django_micboard-26.7.15/micboard/admin/mixins.py +310 -0
  29. django_micboard-26.7.15/micboard/admin/monitoring.py +359 -0
  30. django_micboard-26.7.15/micboard/admin/realtime.py +143 -0
  31. django_micboard-26.7.15/micboard/admin/receiver_inlines.py +67 -0
  32. django_micboard-26.7.15/micboard/admin/receivers.py +400 -0
  33. django_micboard-26.7.15/micboard/admin/regulatory_annotations.py +51 -0
  34. django_micboard-26.7.15/micboard/admin/secret_fields.py +23 -0
  35. django_micboard-26.7.15/micboard/admin/settings.py +344 -0
  36. django_micboard-26.7.15/micboard/admin/sortable.py +118 -0
  37. django_micboard-26.7.15/micboard/admin/templates/admin/dashboard.html +428 -0
  38. django_micboard-26.7.15/micboard/admin/users.py +26 -0
  39. django_micboard-26.7.15/micboard/apps.py +185 -0
  40. django_micboard-26.7.15/micboard/chargers/__init__.py +0 -0
  41. django_micboard-26.7.15/micboard/checks.py +26 -0
  42. django_micboard-26.7.15/micboard/context_processors.py +10 -0
  43. django_micboard-26.7.15/micboard/decorators.py +51 -0
  44. django_micboard-26.7.15/micboard/discovery/__init__.py +0 -0
  45. django_micboard-26.7.15/micboard/discovery/limits.py +18 -0
  46. django_micboard-26.7.15/micboard/discovery/network_utils.py +63 -0
  47. django_micboard-26.7.15/micboard/exceptions.py +276 -0
  48. django_micboard-26.7.15/micboard/filters.py +48 -0
  49. django_micboard-26.7.15/micboard/fixtures/band_plans.yaml +78 -0
  50. django_micboard-26.7.15/micboard/fixtures/device_specifications.yaml +253 -0
  51. django_micboard-26.7.15/micboard/forms/assignments.py +33 -0
  52. django_micboard-26.7.15/micboard/forms/configuration.py +32 -0
  53. django_micboard-26.7.15/micboard/forms/dashboard.py +25 -0
  54. django_micboard-26.7.15/micboard/forms/integrations.py +42 -0
  55. django_micboard-26.7.15/micboard/forms/settings.py +380 -0
  56. django_micboard-26.7.15/micboard/forms/settings_admin.py +200 -0
  57. django_micboard-26.7.15/micboard/integrations/sennheiser/client.py +73 -0
  58. django_micboard-26.7.15/micboard/integrations/sennheiser/device_client.py +48 -0
  59. django_micboard-26.7.15/micboard/integrations/sennheiser/discovery_client.py +100 -0
  60. django_micboard-26.7.15/micboard/integrations/sennheiser/exceptions.py +24 -0
  61. django_micboard-26.7.15/micboard/integrations/sennheiser/plugin.py +87 -0
  62. django_micboard-26.7.15/micboard/integrations/sennheiser/sse_client.py +214 -0
  63. django_micboard-26.7.15/micboard/integrations/sennheiser/transformers.py +233 -0
  64. django_micboard-26.7.15/micboard/integrations/shure/client.py +140 -0
  65. django_micboard-26.7.15/micboard/integrations/shure/device_client.py +98 -0
  66. django_micboard-26.7.15/micboard/integrations/shure/discovery_client.py +140 -0
  67. django_micboard-26.7.15/micboard/integrations/shure/exceptions.py +11 -0
  68. django_micboard-26.7.15/micboard/integrations/shure/plugin.py +88 -0
  69. django_micboard-26.7.15/micboard/integrations/shure/transformers.py +297 -0
  70. django_micboard-26.7.15/micboard/integrations/shure/websocket.py +209 -0
  71. django_micboard-26.7.15/micboard/management/__init__.py +0 -0
  72. django_micboard-26.7.15/micboard/management/commands/__init__.py +0 -0
  73. django_micboard-26.7.15/micboard/management/commands/archive_audit_logs.py +44 -0
  74. django_micboard-26.7.15/micboard/management/commands/audit_admin.py +139 -0
  75. django_micboard-26.7.15/micboard/management/commands/audit_regulatory_coverage.py +159 -0
  76. django_micboard-26.7.15/micboard/management/commands/diagnostic_api_health_check.py +219 -0
  77. django_micboard-26.7.15/micboard/management/commands/discovery_add_devices.py +82 -0
  78. django_micboard-26.7.15/micboard/management/commands/import_devices.py +136 -0
  79. django_micboard-26.7.15/micboard/management/commands/import_efis_regulations.py +99 -0
  80. django_micboard-26.7.15/micboard/management/commands/init_settings.py +208 -0
  81. django_micboard-26.7.15/micboard/management/commands/poll_devices.py +158 -0
  82. django_micboard-26.7.15/micboard/management/commands/realtime_status.py +113 -0
  83. django_micboard-26.7.15/micboard/management/commands/set_logging_mode.py +34 -0
  84. django_micboard-26.7.15/micboard/management/commands/sse_subscribe.py +68 -0
  85. django_micboard-26.7.15/micboard/management/commands/sync_discovery.py +118 -0
  86. django_micboard-26.7.15/micboard/management/commands/websocket_subscribe.py +76 -0
  87. django_micboard-26.7.15/micboard/metrics.py +235 -0
  88. django_micboard-26.7.15/micboard/migrations/0001_initial.py +1143 -0
  89. django_micboard-26.7.15/micboard/migrations/0002_settingdefinition_setting.py +56 -0
  90. django_micboard-26.7.15/micboard/migrations/0003_building_campus_id_building_organization_id.py +23 -0
  91. django_micboard-26.7.15/micboard/migrations/0004_remove_manufacturerapiserver_verify_ssl.py +17 -0
  92. django_micboard-26.7.15/micboard/migrations/0005_setting_setting_exactly_one_scope_and_more.py +34 -0
  93. django_micboard-26.7.15/micboard/migrations/__init__.py +0 -0
  94. django_micboard-26.7.15/micboard/model_lifecycle.py +335 -0
  95. django_micboard-26.7.15/micboard/models/__init__.py +18 -0
  96. django_micboard-26.7.15/micboard/models/audit/__init__.py +1 -0
  97. django_micboard-26.7.15/micboard/models/audit/activity_log.py +279 -0
  98. django_micboard-26.7.15/micboard/models/audit/configuration_log.py +88 -0
  99. django_micboard-26.7.15/micboard/models/band_plans.py +238 -0
  100. django_micboard-26.7.15/micboard/models/base_managers.py +330 -0
  101. django_micboard-26.7.15/micboard/models/device_specs.py +150 -0
  102. django_micboard-26.7.15/micboard/models/discovery/__init__.py +1 -0
  103. django_micboard-26.7.15/micboard/models/discovery/configuration.py +92 -0
  104. django_micboard-26.7.15/micboard/models/discovery/manufacturer.py +38 -0
  105. django_micboard-26.7.15/micboard/models/discovery/queue.py +260 -0
  106. django_micboard-26.7.15/micboard/models/discovery/registry.py +213 -0
  107. django_micboard-26.7.15/micboard/models/hardware/__init__.py +1 -0
  108. django_micboard-26.7.15/micboard/models/hardware/charger.py +250 -0
  109. django_micboard-26.7.15/micboard/models/hardware/display_wall.py +279 -0
  110. django_micboard-26.7.15/micboard/models/hardware/wireless_chassis.py +387 -0
  111. django_micboard-26.7.15/micboard/models/hardware/wireless_unit.py +326 -0
  112. django_micboard-26.7.15/micboard/models/integrations.py +187 -0
  113. django_micboard-26.7.15/micboard/models/locations/__init__.py +1 -0
  114. django_micboard-26.7.15/micboard/models/locations/structure.py +176 -0
  115. django_micboard-26.7.15/micboard/models/mixins.py +7 -0
  116. django_micboard-26.7.15/micboard/models/monitoring/__init__.py +1 -0
  117. django_micboard-26.7.15/micboard/models/monitoring/alert.py +205 -0
  118. django_micboard-26.7.15/micboard/models/monitoring/group.py +79 -0
  119. django_micboard-26.7.15/micboard/models/monitoring/performer.py +158 -0
  120. django_micboard-26.7.15/micboard/models/monitoring/performer_assignment.py +181 -0
  121. django_micboard-26.7.15/micboard/models/realtime/__init__.py +1 -0
  122. django_micboard-26.7.15/micboard/models/realtime/connection.py +85 -0
  123. django_micboard-26.7.15/micboard/models/rf_coordination/__init__.py +1 -0
  124. django_micboard-26.7.15/micboard/models/rf_coordination/compliance.py +164 -0
  125. django_micboard-26.7.15/micboard/models/rf_coordination/rf_channel.py +238 -0
  126. django_micboard-26.7.15/micboard/models/settings/__init__.py +1 -0
  127. django_micboard-26.7.15/micboard/models/settings/registry.py +320 -0
  128. django_micboard-26.7.15/micboard/models/telemetry/__init__.py +1 -0
  129. django_micboard-26.7.15/micboard/models/telemetry/health.py +39 -0
  130. django_micboard-26.7.15/micboard/models/telemetry/sessions.py +72 -0
  131. django_micboard-26.7.15/micboard/models/users/__init__.py +1 -0
  132. django_micboard-26.7.15/micboard/models/users/user_profile.py +107 -0
  133. django_micboard-26.7.15/micboard/models/users/user_views.py +29 -0
  134. django_micboard-26.7.15/micboard/multitenancy/__init__.py +1 -0
  135. django_micboard-26.7.15/micboard/multitenancy/admin.py +215 -0
  136. django_micboard-26.7.15/micboard/multitenancy/apps.py +14 -0
  137. django_micboard-26.7.15/micboard/multitenancy/middleware.py +190 -0
  138. django_micboard-26.7.15/micboard/multitenancy/migrations/0001_initial.py +111 -0
  139. django_micboard-26.7.15/micboard/multitenancy/migrations/README.md +26 -0
  140. django_micboard-26.7.15/micboard/multitenancy/migrations/__init__.py +0 -0
  141. django_micboard-26.7.15/micboard/multitenancy/models.py +240 -0
  142. django_micboard-26.7.15/micboard/services/__init__.py +1 -0
  143. django_micboard-26.7.15/micboard/services/chargers/dashboard_dtos.py +52 -0
  144. django_micboard-26.7.15/micboard/services/chargers/dashboard_service.py +130 -0
  145. django_micboard-26.7.15/micboard/services/chargers/polling_cache.py +149 -0
  146. django_micboard-26.7.15/micboard/services/chargers/polling_dtos.py +91 -0
  147. django_micboard-26.7.15/micboard/services/chargers/polling_service.py +352 -0
  148. django_micboard-26.7.15/micboard/services/common/__init__.py +0 -0
  149. django_micboard-26.7.15/micboard/services/common/base/__init__.py +1 -0
  150. django_micboard-26.7.15/micboard/services/common/base/bounded_transport.py +93 -0
  151. django_micboard-26.7.15/micboard/services/common/base/circuit_breaker.py +93 -0
  152. django_micboard-26.7.15/micboard/services/common/base/client.py +392 -0
  153. django_micboard-26.7.15/micboard/services/common/base/plugin.py +106 -0
  154. django_micboard-26.7.15/micboard/services/common/base/rate_limiter.py +52 -0
  155. django_micboard-26.7.15/micboard/services/common/base/resilience.py +27 -0
  156. django_micboard-26.7.15/micboard/services/common/base/utils.py +58 -0
  157. django_micboard-26.7.15/micboard/services/common/network_limits.py +100 -0
  158. django_micboard-26.7.15/micboard/services/core/__init__.py +1 -0
  159. django_micboard-26.7.15/micboard/services/core/device_metadata.py +145 -0
  160. django_micboard-26.7.15/micboard/services/core/device_specs.py +100 -0
  161. django_micboard-26.7.15/micboard/services/core/hardware.py +82 -0
  162. django_micboard-26.7.15/micboard/services/core/hardware_lifecycle.py +211 -0
  163. django_micboard-26.7.15/micboard/services/core/hardware_post_save_hooks.py +111 -0
  164. django_micboard-26.7.15/micboard/services/core/hardware_sync.py +69 -0
  165. django_micboard-26.7.15/micboard/services/core/performer_assignment.py +351 -0
  166. django_micboard-26.7.15/micboard/services/core/performer_assignment_dtos.py +37 -0
  167. django_micboard-26.7.15/micboard/services/core/user_profile.py +38 -0
  168. django_micboard-26.7.15/micboard/services/deduplication/__init__.py +1 -0
  169. django_micboard-26.7.15/micboard/services/deduplication/check.py +379 -0
  170. django_micboard-26.7.15/micboard/services/deduplication/identity_index.py +191 -0
  171. django_micboard-26.7.15/micboard/services/deduplication/identity_mutation_lock.py +26 -0
  172. django_micboard-26.7.15/micboard/services/deduplication/identity_resolution.py +41 -0
  173. django_micboard-26.7.15/micboard/services/deduplication/queue_conflict_service.py +75 -0
  174. django_micboard-26.7.15/micboard/services/deduplication/result.py +122 -0
  175. django_micboard-26.7.15/micboard/services/deduplication/tracking.py +58 -0
  176. django_micboard-26.7.15/micboard/services/discovery/__init__.py +0 -0
  177. django_micboard-26.7.15/micboard/services/discovery/registry_service.py +23 -0
  178. django_micboard-26.7.15/micboard/services/hardware/__init__.py +1 -0
  179. django_micboard-26.7.15/micboard/services/hardware/chassis_admin_dtos.py +48 -0
  180. django_micboard-26.7.15/micboard/services/hardware/chassis_admin_service.py +175 -0
  181. django_micboard-26.7.15/micboard/services/hardware/chassis_lifecycle_service.py +169 -0
  182. django_micboard-26.7.15/micboard/services/hardware/chassis_refresh_service.py +182 -0
  183. django_micboard-26.7.15/micboard/services/hardware/chassis_regulatory_service.py +267 -0
  184. django_micboard-26.7.15/micboard/services/hardware/dtos.py +89 -0
  185. django_micboard-26.7.15/micboard/services/hardware/ip_ownership_service.py +82 -0
  186. django_micboard-26.7.15/micboard/services/hardware/receiver_browse_dtos.py +50 -0
  187. django_micboard-26.7.15/micboard/services/hardware/receiver_browse_service.py +109 -0
  188. django_micboard-26.7.15/micboard/services/hardware/rf_channel_service.py +214 -0
  189. django_micboard-26.7.15/micboard/services/hardware/wireless_chassis_persistence_service.py +342 -0
  190. django_micboard-26.7.15/micboard/services/hardware/wireless_unit_service.py +296 -0
  191. django_micboard-26.7.15/micboard/services/import_service.py +255 -0
  192. django_micboard-26.7.15/micboard/services/integrations/api_server_service.py +182 -0
  193. django_micboard-26.7.15/micboard/services/integrations/dtos.py +18 -0
  194. django_micboard-26.7.15/micboard/services/kiosk/__init__.py +1 -0
  195. django_micboard-26.7.15/micboard/services/kiosk/dtos.py +147 -0
  196. django_micboard-26.7.15/micboard/services/kiosk/health_service.py +185 -0
  197. django_micboard-26.7.15/micboard/services/kiosk/services.py +292 -0
  198. django_micboard-26.7.15/micboard/services/locations/__init__.py +0 -0
  199. django_micboard-26.7.15/micboard/services/locations/structure_service.py +36 -0
  200. django_micboard-26.7.15/micboard/services/maintenance/__init__.py +1 -0
  201. django_micboard-26.7.15/micboard/services/maintenance/admin_audit_checks.py +276 -0
  202. django_micboard-26.7.15/micboard/services/maintenance/admin_audit_dtos.py +103 -0
  203. django_micboard-26.7.15/micboard/services/maintenance/admin_audit_service.py +255 -0
  204. django_micboard-26.7.15/micboard/services/maintenance/audit.py +183 -0
  205. django_micboard-26.7.15/micboard/services/maintenance/efis_import.py +299 -0
  206. django_micboard-26.7.15/micboard/services/maintenance/logging_mode.py +62 -0
  207. django_micboard-26.7.15/micboard/services/maintenance/sync_audit_service.py +107 -0
  208. django_micboard-26.7.15/micboard/services/manufacturer/__init__.py +1 -0
  209. django_micboard-26.7.15/micboard/services/manufacturer/activation_service.py +14 -0
  210. django_micboard-26.7.15/micboard/services/manufacturer/config.py +121 -0
  211. django_micboard-26.7.15/micboard/services/manufacturer/plugin_registry.py +113 -0
  212. django_micboard-26.7.15/micboard/services/manufacturer/secret_redaction.py +133 -0
  213. django_micboard-26.7.15/micboard/services/manufacturer/signals.py +84 -0
  214. django_micboard-26.7.15/micboard/services/manufacturer/sync.py +341 -0
  215. django_micboard-26.7.15/micboard/services/monitoring/__init__.py +1 -0
  216. django_micboard-26.7.15/micboard/services/monitoring/alert_browse_dtos.py +68 -0
  217. django_micboard-26.7.15/micboard/services/monitoring/alert_browse_service.py +140 -0
  218. django_micboard-26.7.15/micboard/services/monitoring/alert_delivery_service.py +176 -0
  219. django_micboard-26.7.15/micboard/services/monitoring/alert_fanout_dtos.py +113 -0
  220. django_micboard-26.7.15/micboard/services/monitoring/alert_fanout_service.py +290 -0
  221. django_micboard-26.7.15/micboard/services/monitoring/alerts.py +247 -0
  222. django_micboard-26.7.15/micboard/services/monitoring/base_health_mixin.py +143 -0
  223. django_micboard-26.7.15/micboard/services/monitoring/monitoring_access.py +156 -0
  224. django_micboard-26.7.15/micboard/services/monitoring/poll_alert_service.py +215 -0
  225. django_micboard-26.7.15/micboard/services/multitenancy/organization_service.py +18 -0
  226. django_micboard-26.7.15/micboard/services/notification/__init__.py +1 -0
  227. django_micboard-26.7.15/micboard/services/notification/broadcast_service.py +347 -0
  228. django_micboard-26.7.15/micboard/services/notification/device_broadcast_dtos.py +25 -0
  229. django_micboard-26.7.15/micboard/services/notification/device_broadcast_service.py +185 -0
  230. django_micboard-26.7.15/micboard/services/notification/email.py +120 -0
  231. django_micboard-26.7.15/micboard/services/notification/realtime_routing_service.py +246 -0
  232. django_micboard-26.7.15/micboard/services/realtime/connection_service.py +67 -0
  233. django_micboard-26.7.15/micboard/services/realtime/health_dtos.py +34 -0
  234. django_micboard-26.7.15/micboard/services/realtime/health_service.py +115 -0
  235. django_micboard-26.7.15/micboard/services/realtime/shure_websocket_subscription_service.py +204 -0
  236. django_micboard-26.7.15/micboard/services/realtime/sse_subscription_service.py +196 -0
  237. django_micboard-26.7.15/micboard/services/realtime/subscription_dtos.py +39 -0
  238. django_micboard-26.7.15/micboard/services/realtime/subscription_lifecycle_service.py +177 -0
  239. django_micboard-26.7.15/micboard/services/realtime/subscription_supervisor.py +385 -0
  240. django_micboard-26.7.15/micboard/services/settings/__init__.py +1 -0
  241. django_micboard-26.7.15/micboard/services/settings/dtos.py +77 -0
  242. django_micboard-26.7.15/micboard/services/settings/persistence_service.py +112 -0
  243. django_micboard-26.7.15/micboard/services/settings/presentation_service.py +225 -0
  244. django_micboard-26.7.15/micboard/services/settings/registry.py +258 -0
  245. django_micboard-26.7.15/micboard/services/settings/settings_service.py +184 -0
  246. django_micboard-26.7.15/micboard/services/settings/visibility_service.py +220 -0
  247. django_micboard-26.7.15/micboard/services/shared/__init__.py +1 -0
  248. django_micboard-26.7.15/micboard/services/shared/access_policy.py +218 -0
  249. django_micboard-26.7.15/micboard/services/shared/api_health.py +185 -0
  250. django_micboard-26.7.15/micboard/services/shared/api_health_dtos.py +67 -0
  251. django_micboard-26.7.15/micboard/services/shared/base_dto.py +33 -0
  252. django_micboard-26.7.15/micboard/services/shared/rate_limiting.py +69 -0
  253. django_micboard-26.7.15/micboard/services/sync/__init__.py +1 -0
  254. django_micboard-26.7.15/micboard/services/sync/chassis_discovery_schedule_service.py +79 -0
  255. django_micboard-26.7.15/micboard/services/sync/device_promotion_service.py +145 -0
  256. django_micboard-26.7.15/micboard/services/sync/device_refresh_service.py +182 -0
  257. django_micboard-26.7.15/micboard/services/sync/device_update_service.py +323 -0
  258. django_micboard-26.7.15/micboard/services/sync/discovered_device_deletion_service.py +40 -0
  259. django_micboard-26.7.15/micboard/services/sync/discovered_device_service.py +89 -0
  260. django_micboard-26.7.15/micboard/services/sync/discovery_approval_inventory.py +192 -0
  261. django_micboard-26.7.15/micboard/services/sync/discovery_approval_plan.py +60 -0
  262. django_micboard-26.7.15/micboard/services/sync/discovery_approval_policy.py +147 -0
  263. django_micboard-26.7.15/micboard/services/sync/discovery_approval_resolution.py +259 -0
  264. django_micboard-26.7.15/micboard/services/sync/discovery_approval_service.py +359 -0
  265. django_micboard-26.7.15/micboard/services/sync/discovery_candidate_source_service.py +162 -0
  266. django_micboard-26.7.15/micboard/services/sync/discovery_claim_service.py +97 -0
  267. django_micboard-26.7.15/micboard/services/sync/discovery_configuration_service.py +128 -0
  268. django_micboard-26.7.15/micboard/services/sync/discovery_dtos.py +97 -0
  269. django_micboard-26.7.15/micboard/services/sync/discovery_execution_service.py +240 -0
  270. django_micboard-26.7.15/micboard/services/sync/discovery_queue_service.py +234 -0
  271. django_micboard-26.7.15/micboard/services/sync/discovery_service.py +275 -0
  272. django_micboard-26.7.15/micboard/services/sync/discovery_source_cursor_service.py +199 -0
  273. django_micboard-26.7.15/micboard/services/sync/discovery_sync_service.py +309 -0
  274. django_micboard-26.7.15/micboard/services/sync/discovery_trigger_service.py +200 -0
  275. django_micboard-26.7.15/micboard/services/sync/discovery_utils.py +248 -0
  276. django_micboard-26.7.15/micboard/services/sync/polling_api.py +117 -0
  277. django_micboard-26.7.15/micboard/services/sync/polling_dtos.py +92 -0
  278. django_micboard-26.7.15/micboard/services/sync/polling_service.py +158 -0
  279. django_micboard-26.7.15/micboard/settings/admin_theme.py +73 -0
  280. django_micboard-26.7.15/micboard/settings/defaults.py +11 -0
  281. django_micboard-26.7.15/micboard/settings/deployment_controls.py +34 -0
  282. django_micboard-26.7.15/micboard/settings/scope_policy.py +42 -0
  283. django_micboard-26.7.15/micboard/static/micboard/css/about.scss +10 -0
  284. django_micboard-26.7.15/micboard/static/micboard/css/accessibility.css +133 -0
  285. django_micboard-26.7.15/micboard/static/micboard/css/accessibility.scss +133 -0
  286. django_micboard-26.7.15/micboard/static/micboard/css/theme.css +15568 -0
  287. django_micboard-26.7.15/micboard/static/micboard/css/theme.css.map +1 -0
  288. django_micboard-26.7.15/micboard/static/micboard/favicon.png +0 -0
  289. django_micboard-26.7.15/micboard/static/micboard/images/field_unit_default.svg +8 -0
  290. django_micboard-26.7.15/micboard/static/micboard/images/ulxd1_wl185.svg +8 -0
  291. django_micboard-26.7.15/micboard/static/micboard/js/about.js +9 -0
  292. django_micboard-26.7.15/micboard/static/micboard/js/app.js +292 -0
  293. django_micboard-26.7.15/micboard/static/micboard/js/channelview.js +314 -0
  294. django_micboard-26.7.15/micboard/static/micboard/js/chart-smoothie.js +109 -0
  295. django_micboard-26.7.15/micboard/static/micboard/js/config.js +230 -0
  296. django_micboard-26.7.15/micboard/static/micboard/js/data.js +97 -0
  297. django_micboard-26.7.15/micboard/static/micboard/js/display.js +92 -0
  298. django_micboard-26.7.15/micboard/static/micboard/js/dnd.js +178 -0
  299. django_micboard-26.7.15/micboard/static/micboard/js/extended.js +114 -0
  300. django_micboard-26.7.15/micboard/static/micboard/js/gif.js +31 -0
  301. django_micboard-26.7.15/micboard/static/micboard/js/kbd.js +127 -0
  302. django_micboard-26.7.15/micboard/static/micboard/js/venues.js +8 -0
  303. django_micboard-26.7.15/micboard/static/micboard/js/web.js +8 -0
  304. django_micboard-26.7.15/micboard/static/micboard/logo.png +0 -0
  305. django_micboard-26.7.15/micboard/static/micboard/vendor/htmx/LICENSE +13 -0
  306. django_micboard-26.7.15/micboard/static/micboard/vendor/htmx/htmx-2.0.7.min.js +1 -0
  307. django_micboard-26.7.15/micboard/tasks/__init__.py +5 -0
  308. django_micboard-26.7.15/micboard/tasks/maintenance/__init__.py +1 -0
  309. django_micboard-26.7.15/micboard/tasks/maintenance/charger.py +28 -0
  310. django_micboard-26.7.15/micboard/tasks/monitoring/__init__.py +1 -0
  311. django_micboard-26.7.15/micboard/tasks/monitoring/health.py +121 -0
  312. django_micboard-26.7.15/micboard/tasks/monitoring/sse.py +13 -0
  313. django_micboard-26.7.15/micboard/tasks/monitoring/websocket.py +15 -0
  314. django_micboard-26.7.15/micboard/tasks/sync/__init__.py +1 -0
  315. django_micboard-26.7.15/micboard/tasks/sync/discovery.py +136 -0
  316. django_micboard-26.7.15/micboard/tasks/sync/polling.py +131 -0
  317. django_micboard-26.7.15/micboard/templates/admin/micboard/hardware_layout.html +106 -0
  318. django_micboard-26.7.15/micboard/templates/admin/micboard/receiver_change_form.html +239 -0
  319. django_micboard-26.7.15/micboard/templates/admin/micboard/receiver_changelist.html +11 -0
  320. django_micboard-26.7.15/micboard/templates/admin/micboard/settings_diff_stub.html +61 -0
  321. django_micboard-26.7.15/micboard/templates/micboard/about.html +26 -0
  322. django_micboard-26.7.15/micboard/templates/micboard/alert_detail.html +166 -0
  323. django_micboard-26.7.15/micboard/templates/micboard/alerts.html +137 -0
  324. django_micboard-26.7.15/micboard/templates/micboard/all_buildings_view.html +14 -0
  325. django_micboard-26.7.15/micboard/templates/micboard/all_rooms_view.html +10 -0
  326. django_micboard-26.7.15/micboard/templates/micboard/assignments/form.html +95 -0
  327. django_micboard-26.7.15/micboard/templates/micboard/assignments.html +50 -0
  328. django_micboard-26.7.15/micboard/templates/micboard/base.html +198 -0
  329. django_micboard-26.7.15/micboard/templates/micboard/charger_dashboard.html +104 -0
  330. django_micboard-26.7.15/micboard/templates/micboard/displaywall_list.html +20 -0
  331. django_micboard-26.7.15/micboard/templates/micboard/emails/alert_notification.html +155 -0
  332. django_micboard-26.7.15/micboard/templates/micboard/emails/alert_notification.txt +20 -0
  333. django_micboard-26.7.15/micboard/templates/micboard/index.html +62 -0
  334. django_micboard-26.7.15/micboard/templates/micboard/kiosk/display.html +82 -0
  335. django_micboard-26.7.15/micboard/templates/micboard/kiosk/display_content.html +69 -0
  336. django_micboard-26.7.15/micboard/templates/micboard/kiosk/section_list.html +22 -0
  337. django_micboard-26.7.15/micboard/templates/micboard/kiosk/wall_detail.html +11 -0
  338. django_micboard-26.7.15/micboard/templates/micboard/kiosk/wall_list.html +20 -0
  339. django_micboard-26.7.15/micboard/templates/micboard/partials/alert_row.html +29 -0
  340. django_micboard-26.7.15/micboard/templates/micboard/partials/alert_rows.html +53 -0
  341. django_micboard-26.7.15/micboard/templates/micboard/partials/assignment_row.html +28 -0
  342. django_micboard-26.7.15/micboard/templates/micboard/partials/assignment_rows.html +7 -0
  343. django_micboard-26.7.15/micboard/templates/micboard/partials/channel_card.html +21 -0
  344. django_micboard-26.7.15/micboard/templates/micboard/partials/charger_grid.html +65 -0
  345. django_micboard-26.7.15/micboard/templates/micboard/partials/charger_slot.html +17 -0
  346. django_micboard-26.7.15/micboard/templates/micboard/partials/device_tiles.html +52 -0
  347. django_micboard-26.7.15/micboard/templates/micboard/partials/empty.html +3 -0
  348. django_micboard-26.7.15/micboard/templates/micboard/partials/wall_section.html +40 -0
  349. django_micboard-26.7.15/micboard/templates/micboard/receiver_browse.html +70 -0
  350. django_micboard-26.7.15/micboard/templates/micboard/rooms_in_building_view.html +10 -0
  351. django_micboard-26.7.15/micboard/templates/micboard/settings/bulk_config.html +15 -0
  352. django_micboard-26.7.15/micboard/templates/micboard/settings/manufacturer_config.html +15 -0
  353. django_micboard-26.7.15/micboard/templates/micboard/settings/overview.html +92 -0
  354. django_micboard-26.7.15/micboard/templatetags/__init__.py +0 -0
  355. django_micboard-26.7.15/micboard/templatetags/micboard_tags.py +23 -0
  356. django_micboard-26.7.15/micboard/urls.py +126 -0
  357. django_micboard-26.7.15/micboard/utils/dependencies.py +88 -0
  358. django_micboard-26.7.15/micboard/utils/exception_logging.py +13 -0
  359. django_micboard-26.7.15/micboard/utils/mac_address.py +44 -0
  360. django_micboard-26.7.15/micboard/views/__init__.py +1 -0
  361. django_micboard-26.7.15/micboard/views/alerts.py +116 -0
  362. django_micboard-26.7.15/micboard/views/assignments.py +259 -0
  363. django_micboard-26.7.15/micboard/views/charger_dashboard.py +60 -0
  364. django_micboard-26.7.15/micboard/views/dashboard.py +193 -0
  365. django_micboard-26.7.15/micboard/views/kiosk.py +188 -0
  366. django_micboard-26.7.15/micboard/views/partials.py +90 -0
  367. django_micboard-26.7.15/micboard/views/settings.py +164 -0
  368. django_micboard-26.7.15/micboard/websockets/__init__.py +0 -0
  369. django_micboard-26.7.15/micboard/websockets/consumers.py +281 -0
  370. django_micboard-26.7.15/micboard/websockets/routing.py +12 -0
  371. django_micboard-26.7.15/pyproject.toml +438 -0
  372. django_micboard-26.7.15/setup.cfg +4 -0
  373. django_micboard-26.7.15/tests/test_access_security.py +589 -0
  374. django_micboard-26.7.15/tests/test_activity_log_admin.py +164 -0
  375. django_micboard-26.7.15/tests/test_admin_audit_checks.py +339 -0
  376. django_micboard-26.7.15/tests/test_admin_channels_coverage.py +309 -0
  377. django_micboard-26.7.15/tests/test_admin_chassis_refresh.py +105 -0
  378. django_micboard-26.7.15/tests/test_admin_configuration_discovery_coverage.py +256 -0
  379. django_micboard-26.7.15/tests/test_admin_custom_access.py +170 -0
  380. django_micboard-26.7.15/tests/test_admin_discovered_device_coverage.py +331 -0
  381. django_micboard-26.7.15/tests/test_admin_integrations_realtime_coverage.py +180 -0
  382. django_micboard-26.7.15/tests/test_admin_manufacturer_scope_coverage.py +276 -0
  383. django_micboard-26.7.15/tests/test_admin_mixins.py +80 -0
  384. django_micboard-26.7.15/tests/test_admin_settings_coverage.py +277 -0
  385. django_micboard-26.7.15/tests/test_admin_sortable_tenant_security.py +231 -0
  386. django_micboard-26.7.15/tests/test_admin_tenant_access.py +541 -0
  387. django_micboard-26.7.15/tests/test_admin_users.py +35 -0
  388. django_micboard-26.7.15/tests/test_admin_wireless_chassis_coverage.py +280 -0
  389. django_micboard-26.7.15/tests/test_alert_live_fragment.py +181 -0
  390. django_micboard-26.7.15/tests/test_alert_view_branches.py +98 -0
  391. django_micboard-26.7.15/tests/test_api_server_admin_security.py +126 -0
  392. django_micboard-26.7.15/tests/test_assignment_live_fragment.py +63 -0
  393. django_micboard-26.7.15/tests/test_assignment_view_branches.py +318 -0
  394. django_micboard-26.7.15/tests/test_async_monitoring_tasks.py +245 -0
  395. django_micboard-26.7.15/tests/test_audit_admin_command.py +405 -0
  396. django_micboard-26.7.15/tests/test_audit_regulatory_commands.py +171 -0
  397. django_micboard-26.7.15/tests/test_authenticated_transport_security.py +244 -0
  398. django_micboard-26.7.15/tests/test_bulk_settings_form_branches.py +242 -0
  399. django_micboard-26.7.15/tests/test_chassis_regulatory_service.py +263 -0
  400. django_micboard-26.7.15/tests/test_chassis_transaction_lifecycle.py +464 -0
  401. django_micboard-26.7.15/tests/test_ci_contracts.py +310 -0
  402. django_micboard-26.7.15/tests/test_configuration_admin_security.py +214 -0
  403. django_micboard-26.7.15/tests/test_configuration_form_branches.py +53 -0
  404. django_micboard-26.7.15/tests/test_core_only_host.py +31 -0
  405. django_micboard-26.7.15/tests/test_custom_user_host.py +30 -0
  406. django_micboard-26.7.15/tests/test_dashboard_access.py +138 -0
  407. django_micboard-26.7.15/tests/test_dashboard_view_branches.py +207 -0
  408. django_micboard-26.7.15/tests/test_deduplication_log_redaction.py +222 -0
  409. django_micboard-26.7.15/tests/test_discovery_command_coverage.py +212 -0
  410. django_micboard-26.7.15/tests/test_discovery_monitor_sync_command_coverage.py +90 -0
  411. django_micboard-26.7.15/tests/test_docs_requirements_script.py +63 -0
  412. django_micboard-26.7.15/tests/test_documentation_paths.py +32 -0
  413. django_micboard-26.7.15/tests/test_efis_init_commands.py +96 -0
  414. django_micboard-26.7.15/tests/test_example_settings.py +25 -0
  415. django_micboard-26.7.15/tests/test_exception_contracts.py +124 -0
  416. django_micboard-26.7.15/tests/test_factory_registry.py +212 -0
  417. django_micboard-26.7.15/tests/test_httpx_clients.py +349 -0
  418. django_micboard-26.7.15/tests/test_huey_integration.py +56 -0
  419. django_micboard-26.7.15/tests/test_huey_task_wrappers.py +141 -0
  420. django_micboard-26.7.15/tests/test_import_architecture.py +113 -0
  421. django_micboard-26.7.15/tests/test_import_devices_command.py +131 -0
  422. django_micboard-26.7.15/tests/test_import_service.py +110 -0
  423. django_micboard-26.7.15/tests/test_kiosk_live_refresh.py +174 -0
  424. django_micboard-26.7.15/tests/test_kiosk_view_branches.py +201 -0
  425. django_micboard-26.7.15/tests/test_lifecycle_hooks.py +402 -0
  426. django_micboard-26.7.15/tests/test_mac_address_utils.py +24 -0
  427. django_micboard-26.7.15/tests/test_maintenance_audit_service.py +124 -0
  428. django_micboard-26.7.15/tests/test_maintenance_command_contracts.py +35 -0
  429. django_micboard-26.7.15/tests/test_maintenance_efis_service.py +183 -0
  430. django_micboard-26.7.15/tests/test_maintenance_logging_mode_service.py +41 -0
  431. django_micboard-26.7.15/tests/test_manufacturer_config_validation.py +206 -0
  432. django_micboard-26.7.15/tests/test_manufacturer_settings_form_branches.py +88 -0
  433. django_micboard-26.7.15/tests/test_metrics_network_coverage.py +158 -0
  434. django_micboard-26.7.15/tests/test_migration_integrity_script.py +33 -0
  435. django_micboard-26.7.15/tests/test_model_display_audit_coverage.py +268 -0
  436. django_micboard-26.7.15/tests/test_model_manager_contract_coverage.py +179 -0
  437. django_micboard-26.7.15/tests/test_monitoring_transport_coverage.py +850 -0
  438. django_micboard-26.7.15/tests/test_multitenancy_admin_middleware_coverage.py +257 -0
  439. django_micboard-26.7.15/tests/test_multitenancy_runtime.py +752 -0
  440. django_micboard-26.7.15/tests/test_notification_broadcast.py +206 -0
  441. django_micboard-26.7.15/tests/test_notification_email_signal_connection.py +119 -0
  442. django_micboard-26.7.15/tests/test_notification_routing.py +145 -0
  443. django_micboard-26.7.15/tests/test_package_metadata.py +105 -0
  444. django_micboard-26.7.15/tests/test_plugin_registry.py +187 -0
  445. django_micboard-26.7.15/tests/test_poll_realtime_logging_commands.py +209 -0
  446. django_micboard-26.7.15/tests/test_polling_api_service.py +220 -0
  447. django_micboard-26.7.15/tests/test_query_hotpaths.py +251 -0
  448. django_micboard-26.7.15/tests/test_realtime_broadcast_routing.py +272 -0
  449. django_micboard-26.7.15/tests/test_realtime_subscription_command_coverage.py +194 -0
  450. django_micboard-26.7.15/tests/test_receiver_browse.py +167 -0
  451. django_micboard-26.7.15/tests/test_release_workflow_security.py +292 -0
  452. django_micboard-26.7.15/tests/test_removed_domain_reexports.py +42 -0
  453. django_micboard-26.7.15/tests/test_removed_forwarding_shims.py +103 -0
  454. django_micboard-26.7.15/tests/test_removed_model_service_shims.py +51 -0
  455. django_micboard-26.7.15/tests/test_restricted_superuser_tenant_access.py +312 -0
  456. django_micboard-26.7.15/tests/test_rf_channel_lifecycle.py +321 -0
  457. django_micboard-26.7.15/tests/test_runtime_contracts.py +221 -0
  458. django_micboard-26.7.15/tests/test_runtime_dependency_model_coverage.py +279 -0
  459. django_micboard-26.7.15/tests/test_settings.py +609 -0
  460. django_micboard-26.7.15/tests/test_settings_admin_form_branches.py +241 -0
  461. django_micboard-26.7.15/tests/test_settings_admin_security.py +510 -0
  462. django_micboard-26.7.15/tests/test_settings_and_partial_view_branches.py +177 -0
  463. django_micboard-26.7.15/tests/test_settings_architecture.py +39 -0
  464. django_micboard-26.7.15/tests/test_settings_dependency_leaves.py +103 -0
  465. django_micboard-26.7.15/tests/test_settings_diff_admin.py +109 -0
  466. django_micboard-26.7.15/tests/test_settings_registry_branch_coverage.py +88 -0
  467. django_micboard-26.7.15/tests/test_settings_role_access.py +166 -0
  468. django_micboard-26.7.15/tests/test_settings_service.py +396 -0
  469. django_micboard-26.7.15/tests/test_shared_runtime_coverage.py +120 -0
  470. django_micboard-26.7.15/tests/test_shure_discovery_sync.py +42 -0
  471. django_micboard-26.7.15/tests/test_shure_imports.py +15 -0
  472. django_micboard-26.7.15/tests/test_shure_websocket.py +153 -0
  473. django_micboard-26.7.15/tests/test_system_checks.py +48 -0
  474. django_micboard-26.7.15/tests/test_tenant_role_admin_policy.py +322 -0
  475. django_micboard-26.7.15/tests/test_ui_middleware_decorators_coverage.py +90 -0
  476. django_micboard-26.7.15/tests/test_vendor_device_clients.py +85 -0
  477. django_micboard-26.7.15/tests/test_vendor_discovery_and_transformers.py +229 -0
  478. django_micboard-26.7.15/tests/test_vendor_plugins_and_system_clients.py +232 -0
  479. django_micboard-26.7.15/tests/test_wall_section_partial_security.py +96 -0
  480. django_micboard-26.7.15/tests/test_websocket_access.py +389 -0
  481. django_micboard-26.7.15/tests/test_websocket_consumers.py +161 -0
  482. django_micboard-26.7.15/tests/test_wireless_chassis_admin_form_branches.py +57 -0
  483. django_micboard-26.7.15/tests/test_wireless_unit_lifecycle.py +312 -0
  484. django_micboard-26.7.15/tests/test_wireless_unit_service_api.py +106 -0
  485. django_micboard-26.7.15/tests/test_workflow_organization.py +121 -0
@@ -0,0 +1,23 @@
1
+ # Environment consumed by example_project/settings.py.
2
+ #
3
+ # Copy this file to .env only as a local reference. Django and start-dev.sh do
4
+ # not load it implicitly. To use it for one command, run for example:
5
+ # uv run --env-file .env --no-sync python manage.py runserver
6
+ #
7
+ # Never commit a populated .env file. Production hosts should keep secrets in
8
+ # their platform's secret manager and use PostgreSQL; SQLite is for development.
9
+
10
+ # Django example project
11
+ DJANGO_SECRET_KEY=django-insecure-change-me-for-local-development
12
+ DJANGO_DEBUG=True
13
+ DJANGO_ALLOWED_HOSTS=localhost,127.0.0.1
14
+
15
+ # Leave unset for the local SQLite database.
16
+ # DJANGO_DATABASE_URL=postgresql://user:password@localhost:5432/micboard
17
+
18
+ # Shure System API values mapped into MICBOARD_CONFIG by the example project
19
+ MICBOARD_SHURE_API_BASE_URL=https://localhost:10000
20
+ MICBOARD_SHURE_API_SHARED_KEY=replace-with-your-shared-key
21
+
22
+ # Hostnames that Manufacturer API Server rows may contact
23
+ MICBOARD_API_SERVER_ALLOWED_HOSTS=localhost
@@ -0,0 +1,561 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Calendar Versioning](https://calver.org/).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [26.07.15] - 2026-07-15
11
+
12
+ 2370c40 - feat(release): Default to current CalVer (#105) (bandwith)
13
+ eaa480d - fix(release): Make publication atomic and retryable (#104) (bandwith)
14
+ 20049d2 - ci(release): Harden package provenance (#103) (bandwith)
15
+ 1f8bf42 - ci(security): Protect solo-maintainer releases (#101) (bandwith)
16
+ 5b9ce4f - ref(security): Harden tenant, service, and release boundaries (#98) (bandwith)
17
+ 552b3ff - ci: Upgrade GitHub Actions to Node 24 (#96) (bandwith)
18
+ a62ca87 - ref: Eliminate cyclic lifecycle dependencies (#93) (bandwith)
19
+ 0d67373 - fix: harden tenant-safe operational workflows (#88) (bandwith)
20
+ 255faff - chore(deps): update dependency pillow to v12.3.0 (#86) (renovate[bot])
21
+ 1158b54 - chore(deps): update dependency pathspec to v1.1.1 (#85) (renovate[bot])
22
+ 3bc86d9 - test: expand service-layer coverage (#87) (bandwith)
23
+ 0354eab - chore(deps): update dependency idna to v3.18 (#84) (renovate[bot])
24
+ eabf7e7 - chore(deps): update dependency certifi to v2026.6.17 (#83) (renovate[bot])
25
+ d40559d - test: Add complete model factory catalog (#82) (bandwith)
26
+ 5bcd630 - chore(deps): update uv to 0.11.28 (Sam Kuonen)
27
+ 160d00e - chore(deps): update astral-sh/setup-uv action to v8.3.2 (#80) (renovate[bot])
28
+ 8ad8dbc - feat: Harden public reusable app boundaries (#79) (bandwith)
29
+ 266d7e2 - Merge pull request #50 from justprosound/renovate/charset-normalizer-3.x (bandwith)
30
+ 794b0a3 - chore(deps): update dependency charset-normalizer to v3.4.9 (renovate[bot])
31
+ 2fcc8a8 - chore: add FUNDING.yml (bandwith)
32
+ 4545c5c - fix: Replace pip install with uv pip install per project policy (Sam Kuonen)
33
+ 5544b7a - feat: Add Sentry Warden AI code review (Sam Kuonen)
34
+ d76756a - chore: Fix pre-commit config and cleanup repository (Sam Kuonen)
35
+ 20fe57f - refactor(models): extract band plan constants and functions from device_specs.py into band_plans.py (Sam Kuonen)
36
+ b91ccfd - fix(mypy): resolve 11 type errors in changed service files (Sam Kuonen)
37
+ 5846477 - refactor: migrate integrations/common/ to services/common/base/, fix bulk_sync_devices bug (Sam Kuonen)
38
+ b05db6e - refactor(hardware): decompose into domain services, add settings service, fix mypy errors (Sam Kuonen)
39
+ f84cc5a - docs: allow f-strings in logging per user preference (Sam Kuonen)
40
+ 1dc0de8 - refactor(admin): split configuration_and_logging.py into configuration.py and activity_logs.py (Sam Kuonen)
41
+ 2236a8f - chore: update uv.lock (Sam Kuonen)
42
+ db674a7 - refactor(core): decompose HardwareLifecycleManager into DeviceAPISyncService and DeviceHealthService (Sam Kuonen)
43
+ e867519 - refactor(discovery): decompose DiscoveryService into 5 single-responsibility services (Sam Kuonen)
44
+ abe7950 - refactor: remove manufacturers shim, GenericCRUDService, and dead code; fix logging f-strings (Sam Kuonen)
45
+ 5797f7c - docs: add 4 product requirement documents aligned with ADRs and issues (Sam Kuonen)
46
+ 33d95b2 - docs: add codebase context doc and 8 architecture decision records (Sam Kuonen)
47
+ 95fc1fb - fix: remove stray bold formatting in AGENTS.md Agent skills section (Sam Kuonen)
48
+ a1185d3 - chore: scaffold Matt Pocock's engineering skills config (Sam Kuonen)
49
+ 46db3ca - fix: register admin modules and fix import paths (Sam Kuonen)
50
+ f82e3d7 - chore: remove refactoring documentation artifacts (Sam Kuonen)
51
+ 77d4823 - refactor: complete E402 lint compliance and fix import paths (Sam Kuonen)
52
+ 257a058 - typing(integration_patterns): add casts and guards; fix mypy issues (Sam Kuonen)
53
+ c3a5fd0 - typing: improve GenericCRUDService generics; cast form fields & cleaned_data fixes (Sam Kuonen)
54
+ 1cb22cf - chore(lint): add __init__ docstrings and minor import noqa (Sam Kuonen)
55
+ abcc436 - Merge release prep changes (Sam Kuonen)
56
+ 82cdbda - feat: Add 12 specialized GitHub Copilot agents from awesome-copilot (Sam Kuonen)
57
+ 52bfd00 - Improve test coverage with proper exclusions and pragma comments (Sam Kuonen)
58
+ 5a11d46 - fix: code standards compliance - resolve ruff violations (Sam Kuonen)
59
+ 4127ca8 - test(coverage): improve plugin_registry coverage to 97% (Sam Kuonen)
60
+ b5aa9da - massive work in progress (Sam Kuonen)
61
+ ce575a9 - refactor(release-prep): standardize configuration, improve docs, expand tests (Sam Kuonen)
62
+ 434233d - massive work in progress (Sam Kuonen)
63
+ 7176b3f - checkpoint: saving state before further changes (skipped linting due to environment issues) (Sam Kuonen)
64
+ c21977a - chore: finalize production release preparation (Sam Kuonen)
65
+ 334b4f7 - docs: add Phase 4.2 completion summary (Sam Kuonen)
66
+ 3605b56 - refactor: extract common HTTP client to eliminate duplication (Sam Kuonen)
67
+ edb45e3 - docs: consolidate documentation and update Docker for GT live testing (Sam Kuonen)
68
+ e65cd4e - cleanup: remove temporary files and consolidate documentation (Sam Kuonen)
69
+ ee4a09c - docs: add Phase 3 completion summary and developer quick reference (Sam Kuonen)
70
+ cb23ff7 - refactor: integrate lifecycle manager into polling services (Phase 3) (Sam Kuonen)
71
+ 2bd55f6 - End of day commit: Updated README to clearly state major work in progress, added comprehensive tests, fixed various issues, and improved codebase structure (Sam Kuonen)
72
+ 91da9f6 - Fix: Resolve pre-commit hook issues and mypy errors (Sam Kuonen)
73
+ 25f566a - Complete Django Micboard refactor: Phase 1 modularization and Phase 2 core features (Sam Kuonen)
74
+ 6d457d5 - Phase 1: Codebase audit and modularization refactor (Sam Kuonen)
75
+ 3116436 - Fix signals/view issues: signatures, returns, cache guard, serialization (Sam Kuonen)
76
+ 5320d67 - Refactor: Centralize Shure discovery and polling logic into signals; prepare API to emit discovery/refresh events (Sam Kuonen)
77
+ efcc7e5 - Remove Windows container artifacts and related scripts; keep README docs (Sam Kuonen)
78
+ 89b947d - Add Windows demo image support: Dockerfile updates, CI workflow, installer handling and build helper (Sam Kuonen)
79
+ 26ebeee - docs: admin layout + health, demo: windows dockerfile, entrypoint and conditional mock data; docker-compose restart policy (Sam Kuonen)
80
+ 22cccf9 - Apply ruff formatting fixes (Sam Kuonen)
81
+ 50fdaa7 - style: ruff format applied (Sam Kuonen)
82
+ 1af4001 - chore: remove shim package and initial migration files (Sam Kuonen)
83
+ 2346787 - docs: remove dev install and test step from documentation workflow (bandwith)
84
+ 22ba8f6 - chore: add docs extra to pyproject and regenerate pinned requirements (bandwith)
85
+ a4bee37 - docs: simplify Read the Docs config — update build tools, move requirements and pre-install mkdocs-material (bandwith)
86
+ 633a4fa - docs: refine Read the Docs config - move post_install and remove setuptools install (bandwith)
87
+ d1192e1 - docs: add API reference pages, MkDocs macros and refine docs build/config (bandwith)
88
+ f4d95bf - ci: make Coveralls upload non-fatal and add coverage.lcov to .gitignore (bandwith)
89
+ 2ebfed1 - ci: cache matrix.json and make matrix generation resilient (bandwith)
90
+ 04da1f1 - ci: show generated matrix and add safe fallback to generate-matrix.py (bandwith)
91
+ a830f5a - ci: add concurrency group and limit matrix parallelism to 2 (bandwith)
92
+ 416fbe6 - ci: add concurrency group and limit matrix parallelism to 2 (bandwith)
93
+ 11aad95 - style: apply ruff fixes to generate-matrix.py (bandwith)
94
+ 0595fea - ci: standardize renovate condition quoting and use job-level test timeout (bandwith)
95
+ c046949 - chore: use pyproject.toml for pip-compile and consolidate requirements (bandwith)
96
+ f2431f2 - chore: tidy typing, tests and dev deps; add types-requests & mypy hook (bandwith)
97
+ d0e6db5 - Add multi-manufacturer plugin architecture (bandwith)
98
+ 8892bb8 - Add timeout to pytest in CI to prevent hanging tests (bandwith)
99
+ 4d531be - Fix CI workflow and dependencies (bandwith)
100
+ aacdec3 - chore: bump pre-commit hooks & ruff, replace bandit with mypy; tidy typing and tests (bandwith)
101
+ bb15441 - refactor: modernize model Meta typing, tidy docs/config, tests & entrypoint (bandwith)
102
+ 2fd8669 - docs: Replace Codecov badge with Coveralls badge (bandwith)
103
+ 9b27e63 - ci: Prevent workflows from running on Renovate branches (bandwith)
104
+ ed4562c - feat: Major feature update and refactoring (bandwith)
105
+ eee7a51 - docs: Add comprehensive AI agent instructions (bandwith)
106
+ 2158d67 - docs: Consolidate documentation for automated hosting (bandwith)
107
+ c9fd5d8 - chore: Remove legacy test files and add missing docstrings (bandwith)
108
+ 669fd7a - refactor: Split large files into organized packages for maintainability (bandwith)
109
+ 10580dd - refactor: Create centralized serializers module for DRY principles (bandwith)
110
+ c0a90ca - feat: Django reusable app optimizations - admin enhancements, model improvements, API endpoints (bandwith)
111
+ bb968a2 - Django reusable app optimizations: settings validation, health checks, connection pooling, comprehensive signal handlers (bandwith)
112
+ 397443d - Dev tooling: VS Code pytest runner + debug, pytest.ini, test migrations disabled; Shure API enrichment; remove splash assets; docs and tests updated (bandwith)
113
+ 8b3fe04 - Refactor: Update device polling and model definitions (bandwith)
114
+ 8e7a0ca - Major refactor: split views, modernize frontend, add templates & tests, update packaging (bandwith)
115
+ 1ae650a - Switch license to AGPL v3: stronger author protection for SaaS usage (bandwith)
116
+ a7c2ce4 - Update repository URLs to justprosound organization (bandwith)
117
+ d961693 - first commit (Sam Kuonen)
118
+
119
+
120
+ ### Added
121
+
122
+ - **Configuration API** (`micboard.services.settings.settings_service`): Unified settings service for host,
123
+ feature-flag, and scoped database configuration
124
+ - **Architecture Documentation** (`micboard/ARCHITECTURE.md`): Comprehensive guide for developers on plugin architecture, multi-tenancy, and settings registry
125
+ - **Expanded Test Suite**: Tests for configuration module, plugin registry, and settings behavior
126
+ - **Focused `.env.example`**: Minimal example-project environment values with explicit API-server
127
+ destination allowlisting
128
+ - **Enhanced README**: Detailed reusable app integration guide with plugin architecture examples
129
+ - **Comprehensive CONTRIBUTING.md**: Migration guidelines, code patterns, and development workflow documentation
130
+ - **Settings overrides diff view**: Admin view and template for scope-level configuration diffs
131
+ - **Native Huey integration**: Optional `huey.contrib.djhuey` task registration, Redis-backed
132
+ host configuration, and an in-memory test backend
133
+ - **Access-control regression coverage**: User-scoped tests for alerts, assignments, chargers,
134
+ display walls, kiosks, and nested resources
135
+ - **Reusable-app host coverage**: Core-only and custom-user host settings, migration integrity,
136
+ package API, installed-wheel, query-budget, and WebSocket routing regression tests
137
+ - **Release verification**: Wheel-content validation and installed-wheel smoke testing
138
+ - **Dependency-change security gate**: Reject pull requests that introduce moderate-or-higher
139
+ vulnerabilities across runtime, development, or unknown dependency scopes, and audit the full
140
+ lockfile during push, pull-request, manual, and weekly CI runs
141
+ - **Signed release provenance**: Attest sealed wheel and source distributions with isolated
142
+ Sigstore-backed GitHub build provenance before either package registry can publish them
143
+ - **Attested release SBOMs**: Generate an SPDX JSON bill of materials, bind it to the wheel and
144
+ source archive with a Sigstore SBOM attestation, and ship it with the release checksums
145
+ - **PEP 740 package attestations**: Sign each registry upload with its environment-bound OIDC
146
+ identity and publish the matching attestations alongside immutable GitHub release assets
147
+ - **NIST SSDF workflow evidence**: Map checked-in automation controls to the final SSDF 1.1
148
+ practices while identifying SSDF 1.2 as a draft
149
+ - **Complete model factory catalog**: Domain-grouped Factory Boy adapters for every installed
150
+ project model, with registry completeness, persistence, validation, optional-app, and
151
+ swappable-user coverage
152
+ - **Service-layer regression coverage**: Direct Factory Boy-backed tests for discovery,
153
+ deduplication, hardware lifecycle, locations, performers, alerts, and connections, with every
154
+ targeted module at 90% coverage or higher
155
+ - **Import architecture gate**: Detect internal strongly connected components and reject
156
+ model-to-service, model-to-task, service-to-task, and service-to-app dependency reversals
157
+ - **Performance contracts**: Query budgets for discovery batching, alert fanout, connection health,
158
+ and manufacturer statistics
159
+ - **Admin workflow coverage**: Request-level smoke tests for tenant-scoped chassis, discovery
160
+ approval, monitoring summaries, settings diffs, and HTMX channel fragments
161
+ - **Plugin development guide**: Live registry, shared transport, discovery, transformer,
162
+ protocol-specific streaming, security, native Huey, and test contracts for new manufacturers
163
+ - **Maintenance workflow coverage**: Branch-focused tests for supported discovery, diagnostics,
164
+ audit, settings, metrics, and realtime subscription commands and services
165
+ - **Poll-to-alert lifecycle coverage**: Exercise a native Huey task through persisted API-server
166
+ credentials, normalized device telemetry, alert persistence, recipient delivery, replay
167
+ deduplication, and cross-tenant rejection
168
+ - **Live monitoring fragments**: Add bounded HTMX row/grid refreshes for alerts, assignments,
169
+ chargers, kiosks, and wall sections without history-wide polling counts
170
+ - **Receiver browsing coverage**: Add tenant-scoped, eager-loaded building, room, performer,
171
+ priority, and device-role browsing through stable primary-key routes
172
+ - **Movement audit coverage**: Record manufacturer-detected chassis address changes as typed
173
+ `DeviceMovementLog` events inside the serialized synchronization transaction
174
+ - **Polling audit coverage**: Persist bounded, secret-free `ServiceSyncLog` rows for supported
175
+ manufacturer polling runs and expose the operational history through a read-only admin
176
+
177
+ ### Changed
178
+
179
+ - **Solo-maintainer release protection**: Keep pull requests mandatory without an impossible
180
+ self-approval requirement, preserve strict app-bound checks and signed linear history, require
181
+ non-bypassable Code Owners approval at the production PyPI environment, and allow only squash
182
+ merges
183
+ - **Organized GitHub Actions bootstrap**: Reuse one pinned uv/Python setup action across
184
+ repository-controlled jobs, retain direct immutable setup in privileged jobs, enforce explicit
185
+ job timeouts, expose one stable aggregate check for branch protection, assign valid code owners,
186
+ and document the workflow trust boundaries
187
+ - **Observed release checks**: Dispatch CI, dependency-review, and documentation checks for the
188
+ exact release head, wait for those workflow runs to succeed before merge, and separate Actions
189
+ dispatch, repository write, and publication dispatch permissions across jobs
190
+ - **Verified release promotion**: Create release metadata through GitHub's signed commit API,
191
+ build without workspace source overrides, verify TestPyPI digests before production approval,
192
+ publish production from the same sealed workflow run, make named artifacts and draft releases
193
+ safe to resume after job retries, and publish GitHub releases only after every integrity asset
194
+ is attached
195
+ - **Automatic release CalVer**: Default blank release dispatches to the current UTC `YY.MM.DD`
196
+ while retaining a validated manual override for backfills
197
+ - **Hardened build dependencies**: Upgrade the exactly pinned build backend to setuptools 83.0.0
198
+ and wheel 0.47.0, and lock Twine plus the PEP 740 signer through uv
199
+ - **Credential-safe workflow checkouts**: Disable persisted Git credentials for every read-only
200
+ checkout, scope Warden provider secrets to its trusted review step, and request maintainer review
201
+ for workflow, toolchain, lockfile, and agent-policy changes through CODEOWNERS
202
+ - **Tenant-safe chassis admin writes**: Validate final location ownership in request-bound forms,
203
+ reject tenant-to-platform inventory escapes, and route admin creates and updates through the
204
+ canonical organization-quota persistence seam
205
+ - **Bounded discovery approval plans**: Reject missing queue and hardware permissions before row
206
+ locks, cap selected and same-address conflict scopes at 100 rows and per-type inventory locks at
207
+ 400 rows, and isolate inventory, target resolution, and conflict validation behind one plan
208
+ interface
209
+ - **Canonical service exceptions**: Move settings, admin-audit setup, and realtime lease failures
210
+ under `MicboardError`, reject future service-local exception roots, and translate unexpected API
211
+ polling failures to a fixed secret-safe public error without flattening known transport metadata
212
+ - **Focused vendor clients**: Remove unverified test-only enrichment endpoints, Shure forwarding
213
+ methods, and duplicate Sennheiser polling orchestration; production plugins continue to use the
214
+ shared transport, discovery, transformation, and subscription contracts directly
215
+ - **Bounded vendor coordination**: Scope shared rate-limit locks to each remote API endpoint and
216
+ reject Shure discovery updates whose merged remote and requested address list exceeds the global
217
+ candidate limit
218
+ - **Protected release pipeline**: Prepare version and changelog changes on a release pull request,
219
+ run the required CI, CodeQL, Bandit, package, and documentation checks before auto-merge, and
220
+ publish the exact protected merge commit from environment-bound OIDC jobs
221
+ - **Least-privilege Warden token**: Reduce repository contents access from write to read while
222
+ retaining only the pull-request and check scopes required for automated review
223
+ - **Explicit service imports**: Remove root package re-exports; import services from their owning
224
+ domain modules
225
+ - **Explicit domain imports**: Remove unused domain-package service and view re-exports so package
226
+ imports no longer eagerly load unrelated implementations
227
+ - **Explicit model imports**: Keep `micboard.models` for Django discovery only and import model
228
+ classes from their defining domain modules
229
+ - **Validated service DTOs**: Replace mutable hardware-normalization and deduplication result
230
+ containers with Pydantic DTOs, including a mutually exclusive deduplication outcome enum
231
+ - **Canonical chassis persistence**: Route manufacturer sync, discovery approval, promotion,
232
+ imports, refresh, realtime updates, lifecycle creation, and regulatory repair through one
233
+ `WirelessChassisWrite` DTO seam; remove private cross-service writers
234
+ - **Focused chassis ownership**: Split save lifecycle from band-plan detection and regulatory
235
+ coverage, return typed band-plan results, and delete the mixed wireless-chassis service module
236
+ - **Settings persistence boundary**: Route bulk and manufacturer setting forms through one
237
+ authorization-aware DTO service that performs scoped bulk definition lookup, typed
238
+ serialization, upsert, and cache invalidation
239
+ - **Canonical settings ownership**: Move scoped lookup under the settings domain, make
240
+ `SettingsService` the only production read/cache interface, keep deployment controls host-owned,
241
+ and delete the shared registry path and feature-flag facade
242
+ - **Bounded live projections**: Cap dashboard and kiosk sections, chargers, and slots after tenant
243
+ filtering; return typed truncation metadata and render explicit overflow notices
244
+ - **Bounded kiosk health**: Replace the unbounded connection-validation aggregator with a typed,
245
+ tenant-scoped health projection capped at 16 sections, 32 chargers per section, and 32 slots per
246
+ charger, including sentinel overflow metadata
247
+ - **Deep charger snapshots**: Return primitive nested Pydantic charger, slot, and performer DTOs;
248
+ load assignments only for occupied serial numbers and skip the query for empty grids
249
+ - **Database-ranked assignments**: Select one deterministic active performer assignment per
250
+ bounded wireless unit in SQL instead of materializing every candidate in Python
251
+ - **Indexed discovery approval**: Pre-index locked chassis and charger inventory by primary key,
252
+ API identity, and serial identity so large approval batches avoid quadratic scans while
253
+ preserving ambiguous matches for fail-closed validation
254
+ - **Organization device quotas**: Enforce finite chassis quotas under a locked organization row
255
+ for creates, upsert create branches, and transfers into a different owner while allowing
256
+ same-owner metadata updates at quota
257
+ - **Query-oriented services**: Split charger cache state, discovery candidate collection, and
258
+ bounded HTTP transport enforcement from their orchestration services
259
+ - **Domain package cleanup**: Remove model package re-exports, dead pagination/sync/tenant helpers,
260
+ the duplicate discovery-queue service, and the no-op manufacturer-default registry command path
261
+ - **Direct implementation calls**: Remove residual email and alert convenience functions,
262
+ settings, metadata, lifecycle, regulatory, and routing forwarders, the optional-dependency
263
+ alias, package-level feature-flag exports, the wildcard settings facade, and the no-op device
264
+ status synchronization hook instead of retaining shims
265
+ - **Complexity enforcement**: Remove every remaining McCabe and branch-count exemption after
266
+ simplifying the affected paths, so complexity rules now apply uniformly to production code
267
+ - **Hardware service cleanup**: Remove unused chassis activity/band-plan facades and dead battery,
268
+ capability, and asynchronous status-sync methods; callers use lifecycle, specification, and
269
+ band-plan implementations directly
270
+ - **Strict device-refresh plugins**: Call the required manufacturer plugin interface directly,
271
+ removing optional-method compatibility branches while retaining fail-closed vendor errors
272
+ - **Explicit task imports**: Remove legacy task aliases and import task functions from their
273
+ defining domain modules
274
+ - **Queued API-server checks**: Move admin-triggered vendor health checks to a hard-capped native
275
+ Huey batch that revalidates the initiating user's permission in the worker
276
+ - **Fair, bounded alert fanout**: Rotate shared-cache cursors through eligible wireless units,
277
+ active assignments, and active group recipients; cap assignment, recipient, and delivery work;
278
+ and revalidate current user, group, assignment, and tenant scope before persistence and email
279
+ - **Bounded manufacturer polling**: Fail closed on oversized vendor inventories, bulk-index device
280
+ identities instead of issuing per-device lookup queries, and chunk full-fleet realtime updates
281
+ - **Coalesced discovery dispatch**: Reconcile only after chassis identity changes, collapse
282
+ manufacturer-sync batches to one post-commit request, and suppress duplicate Huey enqueues with
283
+ a short fail-open shared-cache claim
284
+ - **Bounded charger polling**: Move native Huey charger work into a typed service, cap device,
285
+ station, slot, and vendor-text processing, resume list-like inventories across cached pages,
286
+ publish only full-cycle snapshots with a deterministic station prefix, deduplicate station
287
+ requests, read health once, and revalidate that queued manufacturers remain active
288
+ - **Service surface cleanup**: Remove unused unscoped hardware, location, performer, and
289
+ manufacturer query facades in favor of authenticated model managers and active service paths
290
+ - **Realtime event cleanup**: Remove the duplicate polling emitter and unused arbitrary error,
291
+ sync-completion, and discovery-approval WebSocket event paths
292
+ - **pyproject.toml**: Fixed package data inclusion for fixtures and migrations
293
+ - **MANIFEST.in**: Improved to include `.env.example` and exclude workspace-only files
294
+ - **.gitignore**: Enhanced to prevent tracking of development artifacts and egg-info directories
295
+ - **GitHub pre-commit hooks**: Reject edits or deletions of migration history, validate that new
296
+ migration files were generated by Django, and check model-to-migration drift for both app labels
297
+ - **Settings diff route**: Wire settings diff URL to the real view implementation
298
+ - **Supported runtimes**: Target Python 3.13 with Django 5.1, 5.2, and 6.0 CI coverage
299
+ - **GitHub Actions runtimes**: Upgrade checkout and artifact uploads to Node 24-based releases
300
+ - **Dependency management**: Standardize development, documentation, CI, and release commands on
301
+ locked `uv` environments
302
+ - **HTTP integrations**: Use `httpx` consistently with typed retry, rate-limit, and API error
303
+ handling
304
+ - **Bounded vendor transports**: Stream decoded HTTP and SSE data under configurable package
305
+ ceilings, clamp retry delays, reject oversized JSON responses before parsing, discard oversized
306
+ SSE lines and events without payload logging, and revoke queued or live vendor work when its
307
+ manufacturer becomes inactive while preserving the explicit `poll_devices --force` override
308
+ - **Public project cleanup**: Remove private-host branding, obsolete queue guidance, and stale
309
+ live-integration scripts
310
+ - **Operator tooling cleanup**: Remove destructive hard-coded seeding and vendor-specific scratch
311
+ diagnostics while retaining supported admin auditing, discovery, health, import, and monitoring
312
+ commands
313
+ - **Maintenance safeguards**: Bound CIDR expansion memory, fail closed outside regulatory-domain
314
+ limits, propagate discovery batch failures, and preserve accurate structured sync metadata
315
+ - **Quality floor**: Raise enforced branch coverage from 49% to 95%, inventory every distributable
316
+ Python module, and add behavioral contracts across services, models, commands, admin, and tasks
317
+ - **Discovery reconciliation**: Batch exclusivity checks and manufacturer API updates, preserve
318
+ remote state while configured sources are incomplete, rotate shared budgets fairly across local
319
+ inventory and configured scan definitions, and still remove database-proven cross-vendor
320
+ ownership conflicts
321
+ - **Monitoring queries**: Prefetch alert recipients and preferences, eager-load unhealthy
322
+ connection ownership, and aggregate connection statistics in two fixed queries
323
+ - **Settings access**: Route app startup and callers through `SettingsService`; raw
324
+ `MICBOARD_CONFIG` reads are isolated to the settings service
325
+ - **Settings dependency boundaries**: Move package defaults and exact-scope policy into
326
+ dependency-free modules so startup, models, and services share invariants without import cycles
327
+ - **Lifecycle boundaries**: Route model persistence events through explicit Django signal adapters
328
+ while services own validation, derived state, audit, discovery, and post-commit behavior
329
+ - **Realtime update persistence**: Share one service between SSE, WebSocket, and command entry
330
+ points, treating event payloads as partial snapshots that cannot mark unrelated devices offline
331
+ - **Realtime supervision**: Separate long-running SSE/WebSocket supervisors from polling, share a
332
+ renewable singleton lease across commands and native Huey entrypoints, and hard-bound device and
333
+ concurrency counts
334
+ - **Fair realtime supervision**: Rotate bounded inventory windows across rounds and restarts with a
335
+ shared-cache cursor and time-slice long-lived subscriptions through a fixed worker pool so blocked
336
+ or dropped connections cannot permanently starve later devices; reload eligible batches within
337
+ the same supervisor lifetime with configurable rotation and reconnect delays
338
+ - **Realtime service boundaries**: Move SSE and Shure WebSocket subscription orchestration into
339
+ typed services shared by thin native Huey tasks and foreground management commands
340
+ - **Shared realtime lifecycle**: Share eligible chassis selection, transform, persistence,
341
+ primitive projection, broadcast, and secret-safe error handling between SSE and WebSocket while
342
+ keeping transport connection and cleanup local
343
+ - **Post-poll alerts**: Rotate through a configurable, hard-capped set of assigned wireless units
344
+ instead of scanning arbitrary manufacturer inventory or permanently starving later rows
345
+ - **Dependency automation**: Consolidate updates under Renovate; refresh locked Click, filelock,
346
+ certifi, idna, Pillow, and platformdirs versions; ignore generated requirements exports; enforce
347
+ lock/export consistency; and run documentation checks on dependency branches
348
+ - **Host-aware test users**: Shared pytest fixtures now use the host project's configured user
349
+ model
350
+ - **Optional admin integrations**: Enable admin enhancements only when the host registers their
351
+ Django applications
352
+ - **Settings presentation**: Separate tenant-visible diff and overview queries from configuration
353
+ resolution, with a fixed query budget and fail-closed display allowlist
354
+ - **Settings administration**: Mask unknown values across standard admin views, disable raw
355
+ import/export paths, and restrict row management and form choices to the user's tenant scope
356
+ - **Discovery approval**: Move queue promotion into an atomic service with target-model permission
357
+ checks, stable row-lock ordering, bounded fallback identities, cross-model IP ownership,
358
+ non-destructive updates, explicit charger validation, batch conflict detection, and one write per
359
+ logical inventory target
360
+
361
+ ### Fixed
362
+
363
+ - Apply the same tenant-role and platform-scope policy to queued API-server health checks and
364
+ request-time admin actions, including active/staff/permission revalidation in the worker
365
+ - Enforce active-Site ownership when listing or submitting monitoring groups, including
366
+ cross-organization superusers, and reject standalone admin relationships that combine RF
367
+ channels and wireless units from different chassis
368
+ - Resolve regulatory status once per row, eager-load the effective RF channel, annotate explicit
369
+ and country-fallback domains, and keep wireless-unit admin query counts constant as rows grow
370
+ - Eliminate duplicate lifecycle audit writes and use one alias-aware, redacting audit service for
371
+ model transitions, manufacturer events, and EFIS imports
372
+ - Keep Sennheiser SSCv2 event streaming on the authenticated GET connection while sending control
373
+ requests through a separate authenticated client to a validated same-origin control resource
374
+ - Remove per-refresh paginator counts from alert and assignment row fragments and reuse one
375
+ annotated discovery-device existence result across both admin status columns
376
+ - Prevent manufacturer movement updates from requesting a nonexistent chassis `updated_at` field
377
+ - Deepen live DisplayWall rendering into one typed, tenant-scoped kiosk snapshot used by initial
378
+ pages, periodic HTML fragments, JSON consumers, and wall-section partials while preserving a
379
+ bounded query count
380
+ - Activate pinned HTMX on built-in browser pages, route kiosk refreshes to swappable HTML, restore
381
+ template head extensions, and send kiosk heartbeats through Django's CSRF contract
382
+ - Render wall-section fragments from the current kiosk projection, with real section names,
383
+ charger groups, performer status, and explicit empty states
384
+ - Propagate failures from either realtime subscription task while cancelling its sibling, and
385
+ remove the remaining CodeQL warnings from branch and failure-path tests
386
+ - Configuration import consistency across app modules
387
+ - Whitespace issues in documentation and code examples
388
+ - Admin settings diff tests updated to validate masking and access control
389
+ - Preserve the public admin-audit command while moving registry selection and Unfold, media,
390
+ search-depth, template, eager-loading, and live query checks into typed services; quick audits now
391
+ skip HTTP query capture and audits no longer create a predictable persistent superuser account
392
+ - Restore wireless-unit admin registration and lifecycle/regulatory dispatch behavior
393
+ - Correct release provenance so tags and published artifacts target the release commit
394
+ - Enforce organization, campus, monitoring-group, and membership-role boundaries across model
395
+ managers, assignment services, admin views, HTTP views, and monitoring data
396
+ - Route real-time updates only to authorized organization and campus channel groups, including
397
+ collision-safe resolution for chassis and wireless-unit identifiers
398
+ - Bound charger, alert, and kiosk relationship loading to prevent per-row query growth
399
+ - Check discovery IP ownership before probing a candidate device
400
+ - Replace stale performer-assignment examples with the current scoped service API
401
+ - Stop normal Django ORM writes from emitting false deprecation warnings for required model
402
+ lifecycle hooks, and fail tests on future deprecation warnings
403
+ - Correct alert preference field lookups so battery, signal, and audio notifications are emitted
404
+ - Prevent persistent alert-fanout truncation from pinning work to one unit or alert class by
405
+ advancing the unit cursor after each attempt and alternating offline/transmitter priority
406
+ - Treat connected rows without a heartbeat as unhealthy and remove manufacturer-dependent query
407
+ growth from connection statistics
408
+ - Validate hardware transitions from the locked database row and support chassis without an
409
+ `updated_at` field
410
+ - Reconcile imported online devices through provisioning and roll back the complete import when
411
+ any lifecycle transition is rejected
412
+ - Require a building hierarchy when creating locations, reject cross-building rooms, serialize
413
+ duplicate checks for building-level locations, and prevent stale callers from restoring old data
414
+ - Preserve managed IPv4 and IPv6 chassis addresses when reconciling discovery candidates
415
+ - Restore pending-alert action routes, current hardware labels, and owner-scoped state transitions
416
+ - Prevent tenant-scoped settings diff and overview views from exposing foreign organization, site,
417
+ or manufacturer overrides and remove diff per-definition query growth
418
+ - Prevent discovery approval from reading nonexistent queue fields or creating chargers without
419
+ the required location
420
+ - Keep core admin changelists usable when optional admin packages are installed but not configured
421
+ - Preserve stable poll result keys and deterministic wireless-unit slot assignment across process
422
+ restarts
423
+ - Fail manufacturer configuration validation when its plugin cannot be imported, and never run
424
+ discovery network work inline when native Huey is unavailable or rejects a task
425
+ - Accept built-in vendor transformer identifiers, transition responding discovered hardware through
426
+ valid lifecycle states, and skip offline reconciliation for incomplete authoritative snapshots
427
+ - Group queryset deletion callbacks and suppress obsolete discovery work during manufacturer
428
+ cascades
429
+ - Require change permission for every mutating admin action and for discovery queue transitions
430
+ - Scope managed-device polling by API-server manufacturer and location before transport, preserve
431
+ embedded channel telemetry without double transformation, normalize nullable transmitter values,
432
+ and dispatch alerts only to their owning user's email address
433
+ - Keep test factories isolated from manufacturer discovery APIs while retaining explicit lifecycle
434
+ coverage for production task submission
435
+ - Keep discovery approval fail-closed when queue records disagree about API IDs, serial numbers,
436
+ roles, IP ownership, or explicit inventory links, while requiring only the target permission used
437
+ by each create or update
438
+ - Mask unknown stored-setting definitions regardless of their name or scalar type
439
+ - Defer chassis broadcasts, manufacturer registration, task submission, and grouped delete cleanup
440
+ until database commit, and run model lifecycle hooks exactly once through Django admin
441
+ - Replace stale discovery-admin fields and Django 6-incompatible one-argument `format_html()` calls,
442
+ and provide reachable, secret-safe settings management pages
443
+ - Keep persisted manufacturer API-server polling and imports bound to each row's allowlisted URL
444
+ and credential, with redacted failure state and deterministic client cleanup
445
+ - Keep lifecycle audit payloads JSON-safe when Django-native timestamps are recorded
446
+ - Restore platform-global and nested tenant-owned admin changelists in multi-site mode without
447
+ widening ordinary staff access, and register the previously unreachable accessory admin
448
+ - Require explicit permission for the single-site browser update stream while preserving
449
+ membership- and site-scoped WebSocket groups
450
+ - Move ORM work and blocking subscription handshakes off hardware event loops, and materialize
451
+ public async query results before returning them to callers
452
+ - Format authenticated WebSocket origins correctly for IPv4 and IPv6 literals and reject invalid
453
+ device ports before constructing a client
454
+ - Run the installed-wheel smoke contract from the local `just wheel` gate and mark its in-memory
455
+ SQLite host explicitly as development-only
456
+ - Preserve the last complete charger dashboard snapshot while resumable inventory pages accumulate,
457
+ retain the same vendor-order station prefix when a full cycle exceeds its station cap, and fail
458
+ closed when any station request makes the cycle incomplete
459
+
460
+ ### Removed
461
+
462
+ - **Settings package exports**: Import `settings`, `SettingsService`, and presentation services from
463
+ their defining modules instead of a package-level convenience API
464
+ - **Compatibility exports**: Remove root model, service, task, exception, telemetry, rate-limiter,
465
+ and discovery-sync aliases
466
+ - **Model convenience shims**: Use typed wireless-unit, chassis, and RF-channel domain services and
467
+ template filters instead of deprecated model delegation methods
468
+ - **Cross-layer model delegates**: Call realtime, monitoring, organization, discovery, and plugin
469
+ services directly from their owning application adapters
470
+ - **Obsolete runtime surfaces**: Delete destructive seeding and direct-probing commands, legacy
471
+ polling/discovery orchestrators, unused compatibility facades, duplicate realtime emitters,
472
+ private middleware, and their stale templates and guides
473
+ - **Dead monitoring surfaces**: Delete the duplicate charger-display route and template, the
474
+ generic connection-validation and connection-state services, and test-only health aggregation
475
+ and reconnect methods; supported kiosk and realtime services remain the only runtime paths
476
+ - **Test-only service APIs**: Delete unused lifecycle mutation/query helpers, metadata version
477
+ accessors, unscoped chassis refresh, notification progress/system-email methods, health-state
478
+ predicates, and the settings test-mode property; active callers use the canonical typed paths
479
+ - **Dead admin and polling surfaces**: Delete the unregistered wireless-unit inline and stop
480
+ returning raw vendor device payloads from the persistence-only discovery polling service
481
+
482
+ ### Security
483
+
484
+ - Update `cryptography` to 48.0.1 and `msgpack` to 1.2.1 to resolve
485
+ `GHSA-537c-gmf6-5ccf` and `GHSA-6v7p-g79w-8964` in the locked dependency graph
486
+ - Enforce the same group-to-unit tenant invariant for performer-assignment updates, deletions, and
487
+ deactivations, locking the authorization graph inside each mutation transaction
488
+ - Restrict optional sortable-admin writes to the request user's exact manageable queryset on the
489
+ write database, apply reorder batches atomically, and disable globally ranked page-move actions
490
+ - Enforce MSP `viewer`, `operator`, `admin`, and `owner` roles at generic admin, bulk-action,
491
+ related-widget, settings-management, and queued chassis-refresh mutation boundaries; reserve
492
+ host-wide catalog writes for unrestricted platform superusers
493
+ - Remove the stale trusted-HTML wall-section rendering path and autoescape section, charger, and
494
+ performer data in the HTMX fragment
495
+ - Clarified that `.env` files should never be committed (already in `.gitignore`)
496
+ - Added reminder in CONTRIBUTING.md about AGPL licensing requirements for production use
497
+ - Enforce monitoring-group scope on charger, kiosk, alert, performer-assignment, and HTMX lookup
498
+ surfaces
499
+ - Require authenticated POST requests for kiosk heartbeat mutation and admin user promotion
500
+ - Require owner or superuser scope plus CSRF-protected POST requests for alert acknowledgement and
501
+ resolution, and escape vendor channel snapshots in alert details
502
+ - Require HTTPS and certificate verification for authenticated manufacturer clients; private
503
+ certificate authorities use the standard `SSL_CERT_FILE` or `SSL_CERT_DIR` trust configuration
504
+ - Redact API keys and subscription handshake identifiers from integration logs, and hardware
505
+ identities and private network addresses from deduplication and probe logs
506
+ - Sanitize sortable payload failures and Sennheiser/Shure stream exception tracebacks so injected
507
+ primary keys, callback messages, transport errors, and subscription failures cannot forge logs
508
+ or disclose secrets
509
+ - Make activity and service-sync admin history strictly view-only, derive activity actor links and
510
+ search fields from the configured user model, and correct live sync/status badge choices
511
+ - Detect snake, kebab, spaced, and camel-case credential keys before metadata key truncation;
512
+ restore masked list secrets by stable identity and reject ambiguous or missing originals
513
+ - Serialize polling and import identity reads and writes behind one database lock, canonicalize
514
+ valid MAC addresses, discard invalid MAC placeholders, and fail closed on cross-manufacturer
515
+ serial, MAC, or occupied-IP conflicts in both live and dry-run imports
516
+ - Keep raw realtime event payloads and transport/cache exception details out of command and worker
517
+ output
518
+ - Centralize secret-safe exception metadata so traceback context remains useful without rendering
519
+ vendor payloads, credentials, private addresses, or forged log lines
520
+ - Pin GitHub Actions to immutable commits and keep coverage enforcement and reports self-contained
521
+ - Revalidate WebSocket authentication and current route membership immediately before every
522
+ outbound event, including pong replies to client pings, and close revoked connections after
523
+ discarding groups
524
+ - Build release artifacts without write or OIDC permissions, seal them with a SHA-256 manifest,
525
+ verify the manifest in isolated publisher jobs, and publish through native `uv` trusted
526
+ publishing with least-privilege permissions
527
+ - Treat incomplete local inventory, configured scan definitions, CIDR/FQDN expansion, and remote
528
+ discovery payloads as non-authoritative for removals while still clearing database-proven
529
+ cross-manufacturer conflicts
530
+ - Fail closed for unsupported or tenantless resources in MSP mode and prevent cross-tenant
531
+ WebSocket subscription or broadcast leakage
532
+ - Scope stored settings overrides to active, internally consistent organization/campus memberships
533
+ and visible managed manufacturers
534
+ - Honor restricted-superuser tenant memberships across monitoring topology, alert mutations, and
535
+ performer-assignment choices when cross-organization access is disabled
536
+ - Disable generic admin import and export routes until request-aware resources can prove tenant
537
+ scoping for every transferred row
538
+ - Scope charger and RF-channel admin inline choices to the current tenant, and reject forged
539
+ cross-tenant or cross-chassis relationships during formset validation
540
+ - Refuse same-version release retries unless the current main commit is the exact release-metadata
541
+ commit, preventing newer code from being published under previously prepared metadata
542
+
543
+ ### Documentation
544
+
545
+ - Reusable app integration guide in README.md
546
+ - Migration safety and lifecycle documentation
547
+ - Plugin architecture and settings registry patterns explained
548
+ - Development workflow and commit message guidelines
549
+ - Management-command and plugin examples now match the installed public APIs
550
+
551
+ ## [25.01.15] - 2026-01-15
552
+
553
+ ### Added
554
+
555
+ - Initial beta release with multi-manufacturer support
556
+ - Device discovery and lifecycle management
557
+ - Alerting and performer assignment
558
+ - Real-time telemetry via WebSockets/SSE
559
+ - Multi-tenant support framework
560
+ - Settings registry with scope resolution
561
+ - Plugin architecture for manufacturer integration