azimut 0.2.2__tar.gz → 0.2.4__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 (426) hide show
  1. {azimut-0.2.2 → azimut-0.2.4}/.github/workflows/release.yml +41 -36
  2. {azimut-0.2.2 → azimut-0.2.4}/.gitignore +1 -0
  3. {azimut-0.2.2 → azimut-0.2.4}/PKG-INFO +27 -30
  4. {azimut-0.2.2 → azimut-0.2.4}/README.md +25 -28
  5. {azimut-0.2.2 → azimut-0.2.4}/docs/ONTOLOGY.md +31 -5
  6. azimut-0.2.4/docs/RELEASE_NOTES.md +61 -0
  7. {azimut-0.2.2 → azimut-0.2.4}/docs/SPEC.md +81 -33
  8. {azimut-0.2.2 → azimut-0.2.4}/docs/STORAGE_AND_PERFORMANCE.md +99 -42
  9. azimut-0.2.4/docs/UI.md +202 -0
  10. azimut-0.2.4/extension/README.md +56 -0
  11. {azimut-0.2.2 → azimut-0.2.4}/extension/manifest.json +1 -1
  12. {azimut-0.2.2 → azimut-0.2.4}/extension/options.html +2 -3
  13. {azimut-0.2.2 → azimut-0.2.4}/extension/popup.html +5 -8
  14. {azimut-0.2.2 → azimut-0.2.4}/extension/popup.js +39 -0
  15. {azimut-0.2.2 → azimut-0.2.4}/extension/ui.css +3 -0
  16. {azimut-0.2.2 → azimut-0.2.4}/frontend/e2e/app.fixture.js +53 -9
  17. {azimut-0.2.2 → azimut-0.2.4}/frontend/e2e/proof-canvas.spec.js +111 -3
  18. azimut-0.2.4/frontend/e2e/saved-linked-posts.spec.js +125 -0
  19. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/App.svelte +4 -0
  20. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/app.css +29 -0
  21. azimut-0.2.4/frontend/src/components/CaseSidebar.svelte +627 -0
  22. azimut-0.2.4/frontend/src/components/CaseSidebar.test.js +202 -0
  23. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/components/CaseSwitcher.svelte +39 -7
  24. azimut-0.2.4/frontend/src/components/CaseSwitcher.test.js +48 -0
  25. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/components/EntityDetails.svelte +10 -2
  26. azimut-0.2.4/frontend/src/components/EntityDetails.test.js +13 -0
  27. azimut-0.2.4/frontend/src/components/FolderBrowser.svelte +142 -0
  28. azimut-0.2.4/frontend/src/components/FolderBrowser.test.js +79 -0
  29. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/components/Icon.svelte +10 -5
  30. azimut-0.2.4/frontend/src/components/SearchInput.svelte +72 -0
  31. azimut-0.2.4/frontend/src/components/SearchInput.test.js +17 -0
  32. azimut-0.2.4/frontend/src/components/sidebar/DetailsDrawer.svelte +63 -0
  33. azimut-0.2.4/frontend/src/components/sidebar/EntityRow.svelte +141 -0
  34. azimut-0.2.4/frontend/src/components/sidebar/SidebarHeader.svelte +130 -0
  35. azimut-0.2.4/frontend/src/components/sidebar/SidebarResults.svelte +51 -0
  36. azimut-0.2.4/frontend/src/components/sidebar/SidebarTree.svelte +336 -0
  37. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/catalog.js +6 -3
  38. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/catalog.test.js +44 -0
  39. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/composer.js +151 -80
  40. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/composer.test.js +157 -100
  41. azimut-0.2.4/frontend/src/lib/entityIcon.js +35 -0
  42. azimut-0.2.4/frontend/src/lib/entityIcon.test.js +27 -0
  43. azimut-0.2.4/frontend/src/lib/fileSort.js +66 -0
  44. azimut-0.2.4/frontend/src/lib/fileSort.test.js +42 -0
  45. azimut-0.2.4/frontend/src/lib/folderBrowse.js +45 -0
  46. azimut-0.2.4/frontend/src/lib/folderBrowse.test.js +70 -0
  47. azimut-0.2.4/frontend/src/lib/folderView.js +79 -0
  48. azimut-0.2.4/frontend/src/lib/folderView.test.js +85 -0
  49. azimut-0.2.4/frontend/src/lib/geoTree.js +236 -0
  50. azimut-0.2.4/frontend/src/lib/geoTree.test.js +303 -0
  51. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/inspect.js +38 -0
  52. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/inspect.test.js +83 -0
  53. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/maplinks.js +2 -2
  54. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/maplinks.test.js +1 -0
  55. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/mediaFilter.js +46 -5
  56. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/mediaFilter.test.js +69 -1
  57. azimut-0.2.4/frontend/src/lib/mediaQuery.js +19 -0
  58. azimut-0.2.4/frontend/src/lib/mediaQuery.test.js +29 -0
  59. azimut-0.2.4/frontend/src/lib/naming.js +94 -0
  60. azimut-0.2.4/frontend/src/lib/naming.test.js +118 -0
  61. azimut-0.2.4/frontend/src/lib/pagedList.svelte.js +97 -0
  62. azimut-0.2.4/frontend/src/lib/pagedList.test.js +107 -0
  63. azimut-0.2.4/frontend/src/lib/panelWidth.js +52 -0
  64. azimut-0.2.4/frontend/src/lib/panelWidth.test.js +76 -0
  65. azimut-0.2.4/frontend/src/lib/pasteAsset.js +35 -0
  66. azimut-0.2.4/frontend/src/lib/pasteAsset.test.js +50 -0
  67. azimut-0.2.4/frontend/src/lib/poll.js +24 -0
  68. azimut-0.2.4/frontend/src/lib/poll.test.js +32 -0
  69. azimut-0.2.4/frontend/src/lib/rowSelect.js +29 -0
  70. azimut-0.2.4/frontend/src/lib/rowSelect.test.js +45 -0
  71. azimut-0.2.4/frontend/src/lib/savedMarkers.js +74 -0
  72. azimut-0.2.4/frontend/src/lib/savedMarkers.test.js +98 -0
  73. azimut-0.2.4/frontend/src/lib/sidebar.js +16 -0
  74. azimut-0.2.4/frontend/src/lib/sidebarSearch.js +42 -0
  75. azimut-0.2.4/frontend/src/lib/sidebarSearch.test.js +60 -0
  76. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/state.svelte.js +4 -3
  77. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/tools/Files.svelte +560 -88
  78. azimut-0.2.4/frontend/src/tools/Files.test.js +105 -0
  79. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/tools/Inspector.svelte +557 -98
  80. azimut-0.2.4/frontend/src/tools/Inspector.test.js +172 -0
  81. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/tools/MediaLibrary.svelte +490 -120
  82. azimut-0.2.4/frontend/src/tools/MediaLibrary.test.js +226 -0
  83. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/tools/Notebook.svelte +81 -18
  84. azimut-0.2.4/frontend/src/tools/Notebook.test.js +67 -0
  85. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/tools/PostComposer.svelte +112 -15
  86. azimut-0.2.4/frontend/src/tools/PostComposer.test.js +66 -0
  87. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/tools/ProofComposer.svelte +692 -156
  88. azimut-0.2.4/frontend/src/tools/ProofComposer.test.js +429 -0
  89. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/tools/ReverseSearch.svelte +222 -48
  90. azimut-0.2.4/frontend/src/tools/ReverseSearch.test.js +37 -0
  91. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/tools/Satellite.svelte +554 -409
  92. azimut-0.2.4/frontend/src/tools/Satellite.test.js +255 -0
  93. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/tools/Settings.svelte +67 -125
  94. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/tools/inspect/CollageMenu.svelte +67 -4
  95. azimut-0.2.4/frontend/src/tools/inspect/CollageMenu.test.js +37 -0
  96. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/tools/inspect/SaveGallery.svelte +54 -26
  97. azimut-0.2.4/frontend/src/tools/inspect/SaveGallery.test.js +69 -0
  98. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/tools/inspect/SaveMenu.svelte +17 -4
  99. azimut-0.2.4/frontend/src/tools/inspect/SaveMenu.test.js +37 -0
  100. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/tools/proof/NewProofDialog.svelte +65 -34
  101. azimut-0.2.4/frontend/src/tools/proof/NewProofDialog.test.js +88 -0
  102. azimut-0.2.4/frontend/src/tools/proof/PanelCategories.svelte +46 -0
  103. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/tools/proof/ProofLayersPanel.svelte +129 -6
  104. azimut-0.2.4/frontend/src/tools/proof/ProofLayersPanel.test.js +25 -0
  105. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/tools/satellite/MapToolCluster.svelte +49 -17
  106. azimut-0.2.4/frontend/src/tools/satellite/SavedOverlay.svelte +248 -0
  107. azimut-0.2.4/frontend/src/tools/satellite/SavedPopup.svelte +395 -0
  108. azimut-0.2.4/frontend/src/tools/satellite/SavedPopup.test.js +185 -0
  109. azimut-0.2.4/frontend/src/tools/satellite/SavedRow.svelte +312 -0
  110. azimut-0.2.4/frontend/src/tools/satellite/SavedSearch.svelte +173 -0
  111. azimut-0.2.4/frontend/src/tools/satellite/SavedSearch.test.js +139 -0
  112. azimut-0.2.4/frontend/src/tools/satellite/SavedTree.svelte +458 -0
  113. azimut-0.2.4/frontend/src/tools/satellite/SavedTree.test.js +272 -0
  114. {azimut-0.2.2 → azimut-0.2.4}/pyproject.toml +9 -2
  115. azimut-0.2.4/scripts/vendor_ffmpeg.py +246 -0
  116. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/__init__.py +9 -1
  117. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/api/cases.py +7 -5
  118. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/api/drafts.py +34 -21
  119. azimut-0.2.4/src/azimut/api/files.py +45 -0
  120. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/api/ingest.py +67 -1
  121. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/api/inspect.py +39 -19
  122. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/api/media.py +54 -3
  123. azimut-0.2.4/src/azimut/api/naming.py +44 -0
  124. azimut-0.2.4/src/azimut/api/proofs.py +364 -0
  125. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/api/satellite.py +101 -15
  126. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/api/settings.py +7 -14
  127. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/config.py +2 -2
  128. azimut-0.2.4/src/azimut/engine/continents.py +127 -0
  129. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/engine/coords.py +1 -1
  130. azimut-0.2.4/src/azimut/engine/countries.py +113 -0
  131. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/engine/geo.py +97 -6
  132. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/engine/inspect.py +44 -29
  133. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/engine/links.py +5 -5
  134. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/engine/mapsites.py +33 -4
  135. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/engine/media.py +18 -29
  136. azimut-0.2.4/src/azimut/engine/satellite.py +467 -0
  137. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/engine/thumbnails.py +20 -3
  138. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/engine/tiles.py +7 -27
  139. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/repository.py +57 -13
  140. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/sqlite_backend.py +461 -34
  141. azimut-0.2.4/src/azimut/static/assets/Coordinates-BTvv-wM-.js +1 -0
  142. azimut-0.2.4/src/azimut/static/assets/Files-B2_kQAyd.css +1 -0
  143. azimut-0.2.4/src/azimut/static/assets/Files-Dk4RDk90.js +1 -0
  144. azimut-0.2.4/src/azimut/static/assets/FolderBrowser-Bw_BtxXT.js +1 -0
  145. azimut-0.2.4/src/azimut/static/assets/FolderBrowser-CIzLfX1P.css +1 -0
  146. azimut-0.2.2/src/azimut/static/assets/Icon-BgA9a5tG.js → azimut-0.2.4/src/azimut/static/assets/Icon-BbBIW1NX.js +2 -2
  147. azimut-0.2.4/src/azimut/static/assets/Inspector-DYlVevMi.js +6 -0
  148. azimut-0.2.4/src/azimut/static/assets/Inspector-Kzis3eVb.css +1 -0
  149. azimut-0.2.4/src/azimut/static/assets/MediaLibrary-B5jleDki.css +1 -0
  150. azimut-0.2.4/src/azimut/static/assets/MediaLibrary-BfWpwusH.js +4 -0
  151. azimut-0.2.4/src/azimut/static/assets/Notebook-K-LyWdfA.js +65 -0
  152. azimut-0.2.4/src/azimut/static/assets/Notebook-qbBuViJS.css +1 -0
  153. azimut-0.2.4/src/azimut/static/assets/PostComposer-1GLnb8o5.js +5 -0
  154. azimut-0.2.2/src/azimut/static/assets/PostComposer-C1P4_rp3.css → azimut-0.2.4/src/azimut/static/assets/PostComposer-CoKuI09l.css +1 -1
  155. azimut-0.2.4/src/azimut/static/assets/ProofComposer-8LPf0C7W.js +3 -0
  156. azimut-0.2.4/src/azimut/static/assets/ProofComposer-wT6PjcOM.css +1 -0
  157. azimut-0.2.4/src/azimut/static/assets/ReverseSearch--XzLo8zC.js +1 -0
  158. azimut-0.2.2/src/azimut/static/assets/ReverseSearch-DqIrU_Pa.css → azimut-0.2.4/src/azimut/static/assets/ReverseSearch-DyguTuti.css +1 -1
  159. azimut-0.2.4/src/azimut/static/assets/Satellite-BNf2aMJ9.css +1 -0
  160. azimut-0.2.4/src/azimut/static/assets/Satellite-DHLE7Zxq.js +31 -0
  161. azimut-0.2.4/src/azimut/static/assets/Settings-CbwII4OD.js +7 -0
  162. azimut-0.2.4/src/azimut/static/assets/composer-BOgT80fX.js +1 -0
  163. azimut-0.2.2/src/azimut/static/assets/gmaps-D52n5msu.js → azimut-0.2.4/src/azimut/static/assets/gmaps-UfC9RQrO.js +1 -1
  164. azimut-0.2.4/src/azimut/static/assets/index-B5LoFWtr.js +2 -0
  165. azimut-0.2.4/src/azimut/static/assets/index-D5HHtD16.css +1 -0
  166. azimut-0.2.4/src/azimut/static/assets/maplinks-Cnh2ZfxE.js +1 -0
  167. azimut-0.2.4/src/azimut/static/assets/mediaFilter-D6wNuzNu.js +2 -0
  168. azimut-0.2.4/src/azimut/static/assets/naming-6rrJTXku.js +1 -0
  169. azimut-0.2.4/src/azimut/static/assets/poll-g_Pnx6yJ.js +1 -0
  170. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/static/index.html +3 -5
  171. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/workspace.py +62 -19
  172. {azimut-0.2.2 → azimut-0.2.4}/tests/bigcase.py +8 -15
  173. {azimut-0.2.2 → azimut-0.2.4}/tests/conftest.py +15 -0
  174. {azimut-0.2.2 → azimut-0.2.4}/tests/test_bigcase.py +3 -4
  175. {azimut-0.2.2 → azimut-0.2.4}/tests/test_cases_api.py +39 -0
  176. {azimut-0.2.2 → azimut-0.2.4}/tests/test_drafts_api.py +47 -5
  177. azimut-0.2.4/tests/test_files_api.py +66 -0
  178. {azimut-0.2.2 → azimut-0.2.4}/tests/test_geo_api.py +36 -0
  179. azimut-0.2.4/tests/test_geo_locate.py +233 -0
  180. {azimut-0.2.2 → azimut-0.2.4}/tests/test_hardening.py +13 -1
  181. {azimut-0.2.2 → azimut-0.2.4}/tests/test_ingest_api.py +128 -0
  182. {azimut-0.2.2 → azimut-0.2.4}/tests/test_inspect_api.py +194 -8
  183. {azimut-0.2.2 → azimut-0.2.4}/tests/test_links_api.py +34 -36
  184. {azimut-0.2.2 → azimut-0.2.4}/tests/test_mapsites.py +30 -0
  185. {azimut-0.2.2 → azimut-0.2.4}/tests/test_media_api.py +178 -0
  186. azimut-0.2.4/tests/test_naming.py +50 -0
  187. azimut-0.2.4/tests/test_proofs_api.py +531 -0
  188. azimut-0.2.4/tests/test_proofs_assets_api.py +245 -0
  189. {azimut-0.2.2 → azimut-0.2.4}/tests/test_release_gate.py +36 -5
  190. {azimut-0.2.2 → azimut-0.2.4}/tests/test_repository.py +43 -2
  191. {azimut-0.2.2 → azimut-0.2.4}/tests/test_satellite_api.py +331 -1
  192. {azimut-0.2.2 → azimut-0.2.4}/tests/test_sqlite_backend.py +126 -6
  193. azimut-0.2.4/tests/test_vendor_ffmpeg.py +143 -0
  194. {azimut-0.2.2 → azimut-0.2.4}/uv.lock +0 -1
  195. azimut-0.2.2/bench/case_baseline.py +0 -149
  196. azimut-0.2.2/docs/RELEASE_NOTES.md +0 -19
  197. azimut-0.2.2/docs/UI.md +0 -111
  198. azimut-0.2.2/extension/README.md +0 -65
  199. azimut-0.2.2/frontend/src/components/CaseSidebar.svelte +0 -887
  200. azimut-0.2.2/frontend/src/lib/sidebar.js +0 -46
  201. azimut-0.2.2/frontend/src/tools/MediaLibrary.test.js +0 -95
  202. azimut-0.2.2/frontend/src/tools/Notebook.test.js +0 -39
  203. azimut-0.2.2/frontend/src/tools/PostComposer.test.js +0 -21
  204. azimut-0.2.2/frontend/src/tools/ProofComposer.test.js +0 -175
  205. azimut-0.2.2/src/azimut/api/files.py +0 -27
  206. azimut-0.2.2/src/azimut/api/proofs.py +0 -151
  207. azimut-0.2.2/src/azimut/engine/satellite.py +0 -65
  208. azimut-0.2.2/src/azimut/static/assets/Coordinates-Zk6hc7rX.js +0 -1
  209. azimut-0.2.2/src/azimut/static/assets/Files-B_kDrMmA.js +0 -1
  210. azimut-0.2.2/src/azimut/static/assets/Files-DoSPZhF-.css +0 -1
  211. azimut-0.2.2/src/azimut/static/assets/Inspector-3v5iq-jW.css +0 -1
  212. azimut-0.2.2/src/azimut/static/assets/Inspector-CbDQE9mL.js +0 -5
  213. azimut-0.2.2/src/azimut/static/assets/MediaLibrary-DxDbISiM.css +0 -1
  214. azimut-0.2.2/src/azimut/static/assets/MediaLibrary-aa18XUg0.js +0 -5
  215. azimut-0.2.2/src/azimut/static/assets/Modal-CuJYoHU9.css +0 -1
  216. azimut-0.2.2/src/azimut/static/assets/Modal-DHCHN-zW.js +0 -1
  217. azimut-0.2.2/src/azimut/static/assets/Notebook-6bRvw0Ld.css +0 -1
  218. azimut-0.2.2/src/azimut/static/assets/Notebook-De7CIAen.js +0 -65
  219. azimut-0.2.2/src/azimut/static/assets/PostComposer-BoRw8SZk.js +0 -5
  220. azimut-0.2.2/src/azimut/static/assets/ProofComposer-C5mWoc8h.css +0 -1
  221. azimut-0.2.2/src/azimut/static/assets/ProofComposer-hy7ZrvOu.js +0 -2
  222. azimut-0.2.2/src/azimut/static/assets/ReverseSearch-BP3C1CxL.js +0 -1
  223. azimut-0.2.2/src/azimut/static/assets/Satellite-BhhCtezr.js +0 -31
  224. azimut-0.2.2/src/azimut/static/assets/Satellite-DGCcPv9w.css +0 -1
  225. azimut-0.2.2/src/azimut/static/assets/Settings-CnfrsP9_.js +0 -30
  226. azimut-0.2.2/src/azimut/static/assets/composer-C17apZ5p.js +0 -1
  227. azimut-0.2.2/src/azimut/static/assets/index-B8MBkQLT.js +0 -3
  228. azimut-0.2.2/src/azimut/static/assets/index-BaaWj0p3.css +0 -1
  229. azimut-0.2.2/src/azimut/static/assets/maplinks-LmyLzEQg.js +0 -1
  230. azimut-0.2.2/tests/test_proofs_api.py +0 -119
  231. {azimut-0.2.2 → azimut-0.2.4}/.github/workflows/ci.yml +0 -0
  232. {azimut-0.2.2 → azimut-0.2.4}/LICENSE +0 -0
  233. {azimut-0.2.2 → azimut-0.2.4}/docs/IMAGERY_PROVIDERS.md +0 -0
  234. {azimut-0.2.2 → azimut-0.2.4}/extension/background.js +0 -0
  235. {azimut-0.2.2 → azimut-0.2.4}/extension/bridge.js +0 -0
  236. {azimut-0.2.2 → azimut-0.2.4}/extension/icons/icon128.png +0 -0
  237. {azimut-0.2.2 → azimut-0.2.4}/extension/icons/icon16.png +0 -0
  238. {azimut-0.2.2 → azimut-0.2.4}/extension/icons/icon32.png +0 -0
  239. {azimut-0.2.2 → azimut-0.2.4}/extension/icons/icon48.png +0 -0
  240. {azimut-0.2.2 → azimut-0.2.4}/extension/options.js +0 -0
  241. {azimut-0.2.2 → azimut-0.2.4}/extension/overlay.js +0 -0
  242. {azimut-0.2.2 → azimut-0.2.4}/frontend/e2e/satellite-canvas.spec.js +0 -0
  243. {azimut-0.2.2 → azimut-0.2.4}/frontend/index.html +0 -0
  244. {azimut-0.2.2 → azimut-0.2.4}/frontend/jsconfig.json +0 -0
  245. {azimut-0.2.2 → azimut-0.2.4}/frontend/package-lock.json +0 -0
  246. {azimut-0.2.2 → azimut-0.2.4}/frontend/package.json +0 -0
  247. {azimut-0.2.2 → azimut-0.2.4}/frontend/playwright.config.js +0 -0
  248. {azimut-0.2.2 → azimut-0.2.4}/frontend/public/favicon.svg +0 -0
  249. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/assets/logo-source.svg +0 -0
  250. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/components/ConfirmDialog.svelte +0 -0
  251. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/components/FolderSelect.svelte +0 -0
  252. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/components/FolderSelect.test.js +0 -0
  253. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/components/Logo.svelte +0 -0
  254. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/components/Modal.svelte +0 -0
  255. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/components/PostTemplateEditor.svelte +0 -0
  256. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/components/ProofPreview.svelte +0 -0
  257. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/components/ProofTemplateEditor.svelte +0 -0
  258. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/components/Toasts.svelte +0 -0
  259. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/components/Toasts.test.js +0 -0
  260. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/components/UpdateModal.svelte +0 -0
  261. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/components/Wordmark.svelte +0 -0
  262. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/api.js +0 -0
  263. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/appUpdate.js +0 -0
  264. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/appUpdate.test.js +0 -0
  265. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/bidi.js +0 -0
  266. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/bidi.test.js +0 -0
  267. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/bookmarks.js +0 -0
  268. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/bookmarks.test.js +0 -0
  269. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/captureSize.js +0 -0
  270. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/captureSize.test.js +0 -0
  271. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/chain.js +0 -0
  272. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/chain.test.js +0 -0
  273. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/coords.js +0 -0
  274. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/coords.test.js +0 -0
  275. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/events.js +0 -0
  276. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/events.test.js +0 -0
  277. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/extBridge.js +0 -0
  278. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/extBridge.test.js +0 -0
  279. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/extension.test.js +0 -0
  280. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/filing.js +0 -0
  281. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/filing.test.js +0 -0
  282. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/folderTree.js +0 -0
  283. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/folderTree.test.js +0 -0
  284. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/frameRotate.js +0 -0
  285. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/frameRotate.test.js +0 -0
  286. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/fullscreen.js +0 -0
  287. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/fullscreen.test.js +0 -0
  288. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/gmaps.js +0 -0
  289. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/gmaps.test.js +0 -0
  290. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/gridSearch.js +0 -0
  291. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/gridSearch.test.js +0 -0
  292. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/gridSelect.js +0 -0
  293. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/gridSelect.test.js +0 -0
  294. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/history.js +0 -0
  295. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/history.test.js +0 -0
  296. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/markdown.js +0 -0
  297. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/markdown.test.js +0 -0
  298. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/measure.js +0 -0
  299. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/measure.test.js +0 -0
  300. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/navigate.js +0 -0
  301. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/navigate.test.js +0 -0
  302. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/notebook.js +0 -0
  303. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/notebook.test.js +0 -0
  304. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/notebookContent.js +0 -0
  305. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/notebookContent.test.js +0 -0
  306. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/notebookPdf.js +0 -0
  307. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/notebookPdf.test.js +0 -0
  308. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/notebookTabs.js +0 -0
  309. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/notebookTabs.test.js +0 -0
  310. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/notes.js +0 -0
  311. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/notes.test.js +0 -0
  312. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/post.js +0 -0
  313. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/post.test.js +0 -0
  314. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/refViewers.js +0 -0
  315. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/refViewers.test.js +0 -0
  316. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/reverseSearch.js +0 -0
  317. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/reverseSearch.test.js +0 -0
  318. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/satRotate.js +0 -0
  319. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/satRotate.test.js +0 -0
  320. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/screenCrop.js +0 -0
  321. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/screenCrop.test.js +0 -0
  322. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/sentinel.js +0 -0
  323. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/sentinel.test.js +0 -0
  324. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/sidebar.test.js +0 -0
  325. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/state.test.js +0 -0
  326. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/theme.js +0 -0
  327. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/theme.test.js +0 -0
  328. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/toast.test.js +0 -0
  329. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/toolLoader.js +0 -0
  330. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/toolLoader.test.js +0 -0
  331. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/usage.js +0 -0
  332. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/usage.test.js +0 -0
  333. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/workspaces.js +0 -0
  334. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/lib/workspaces.test.js +0 -0
  335. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/main.js +0 -0
  336. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/tools/Coordinates.svelte +0 -0
  337. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/tools/RefViewer.svelte +0 -0
  338. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/tools/inspect/AdjustSliders.svelte +0 -0
  339. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/tools/inspect/CollageCanvas.svelte +0 -0
  340. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/tools/inspect/CollagePreview.svelte +0 -0
  341. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/tools/inspect/CropBox.svelte +0 -0
  342. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/tools/inspect/CropControls.svelte +0 -0
  343. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/tools/inspect/FrameMenu.svelte +0 -0
  344. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/tools/inspect/OrientationControls.svelte +0 -0
  345. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/tools/inspect/PieceCropModal.svelte +0 -0
  346. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/tools/inspect/SelectionMenu.svelte +0 -0
  347. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/tools/inspect/VideoPlayer.svelte +0 -0
  348. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/tools/inspect/VideoPlayer.test.js +0 -0
  349. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/tools/proof/ProofCanvas.svelte +0 -0
  350. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/tools/proof/ProofToolbar.svelte +0 -0
  351. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/tools/proof/ProofToolbar.test.js +0 -0
  352. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/tools/proof/canvasLifecycle.js +0 -0
  353. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/tools/satellite/CaptureOptions.svelte +0 -0
  354. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/tools/satellite/GridSearchPanel.svelte +0 -0
  355. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/tools/satellite/SentinelPicker.svelte +0 -0
  356. {azimut-0.2.2 → azimut-0.2.4}/frontend/src/tools/satellite/SentinelPicker.test.js +0 -0
  357. {azimut-0.2.2 → azimut-0.2.4}/frontend/vite.config.js +0 -0
  358. {azimut-0.2.2 → azimut-0.2.4}/packaging/azimut.ico +0 -0
  359. {azimut-0.2.2 → azimut-0.2.4}/packaging/azimut.spec +0 -0
  360. {azimut-0.2.2 → azimut-0.2.4}/packaging/entry.py +0 -0
  361. {azimut-0.2.2 → azimut-0.2.4}/scripts/relaunch.py +0 -0
  362. {azimut-0.2.2 → azimut-0.2.4}/scripts/smoke_binary.py +0 -0
  363. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/__main__.py +0 -0
  364. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/api/__init__.py +0 -0
  365. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/api/events.py +0 -0
  366. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/api/limits.py +0 -0
  367. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/api/templates.py +0 -0
  368. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/cli.py +0 -0
  369. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/engine/__init__.py +0 -0
  370. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/engine/ffmpeg.py +0 -0
  371. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/engine/google_tiles.py +0 -0
  372. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/engine/scrapers.py +0 -0
  373. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/engine/sentinel.py +0 -0
  374. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/engine/stitch.py +0 -0
  375. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/engine/tilecache.py +0 -0
  376. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/engine/updates.py +0 -0
  377. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/jobs.py +0 -0
  378. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/launcher.py +0 -0
  379. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/server.py +0 -0
  380. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/static/assets/Coordinates-CkOCsDYx.css +0 -0
  381. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/static/assets/Settings-Nqf90D6_.css +0 -0
  382. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/static/assets/bidi-wWDUT82v.js +0 -0
  383. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/static/assets/frameRotate-F1nGHpcH.js +0 -0
  384. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/static/assets/history-D8hJuA9t.js +0 -0
  385. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/static/assets/leaflet-rotate-hAaDqhcJ.js +0 -0
  386. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/static/assets/lib-Ce199MB2.js +0 -0
  387. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/static/assets/markdown-Db8boR5D.js +0 -0
  388. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/static/assets/oxanium-latin-400-normal-BnNz-3Mf.woff +0 -0
  389. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/static/assets/oxanium-latin-400-normal-DcSlRu53.woff2 +0 -0
  390. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/static/assets/oxanium-latin-600-normal-DNQhW0y0.woff +0 -0
  391. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/static/assets/oxanium-latin-600-normal-DW9ldEDP.woff2 +0 -0
  392. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/static/assets/oxanium-latin-700-normal-b_KP-pae.woff +0 -0
  393. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/static/assets/oxanium-latin-700-normal-l0hKEjh4.woff2 +0 -0
  394. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/static/assets/oxanium-latin-ext-400-normal-B1qoybeA.woff2 +0 -0
  395. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/static/assets/oxanium-latin-ext-400-normal-ngSbnDVv.woff +0 -0
  396. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/static/assets/oxanium-latin-ext-600-normal-B2S5WIA4.woff2 +0 -0
  397. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/static/assets/oxanium-latin-ext-600-normal-DywhiVWf.woff +0 -0
  398. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/static/assets/oxanium-latin-ext-700-normal-BSlCClLu.woff2 +0 -0
  399. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/static/assets/oxanium-latin-ext-700-normal-CPlnVieJ.woff +0 -0
  400. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/static/assets/post-COJahl2R.js +0 -0
  401. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/static/assets/rolldown-runtime-Bh1tDfsg.js +0 -0
  402. {azimut-0.2.2 → azimut-0.2.4}/src/azimut/static/favicon.svg +0 -0
  403. {azimut-0.2.2 → azimut-0.2.4}/tests/graph_read.py +0 -0
  404. {azimut-0.2.2 → azimut-0.2.4}/tests/legacy_case.py +0 -0
  405. {azimut-0.2.2 → azimut-0.2.4}/tests/test_binary_smoke.py +0 -0
  406. {azimut-0.2.2 → azimut-0.2.4}/tests/test_config.py +0 -0
  407. {azimut-0.2.2 → azimut-0.2.4}/tests/test_coords.py +0 -0
  408. {azimut-0.2.2 → azimut-0.2.4}/tests/test_events_api.py +0 -0
  409. {azimut-0.2.2 → azimut-0.2.4}/tests/test_ffmpeg.py +0 -0
  410. {azimut-0.2.2 → azimut-0.2.4}/tests/test_focus.py +0 -0
  411. {azimut-0.2.2 → azimut-0.2.4}/tests/test_geo_formats.py +0 -0
  412. {azimut-0.2.2 → azimut-0.2.4}/tests/test_google_tiles.py +0 -0
  413. {azimut-0.2.2 → azimut-0.2.4}/tests/test_jobs.py +0 -0
  414. {azimut-0.2.2 → azimut-0.2.4}/tests/test_launcher.py +0 -0
  415. {azimut-0.2.2 → azimut-0.2.4}/tests/test_migrations.py +0 -0
  416. {azimut-0.2.2 → azimut-0.2.4}/tests/test_relaunch.py +0 -0
  417. {azimut-0.2.2 → azimut-0.2.4}/tests/test_scrapers.py +0 -0
  418. {azimut-0.2.2 → azimut-0.2.4}/tests/test_sentinel.py +0 -0
  419. {azimut-0.2.2 → azimut-0.2.4}/tests/test_server_guard.py +0 -0
  420. {azimut-0.2.2 → azimut-0.2.4}/tests/test_settings_api.py +0 -0
  421. {azimut-0.2.2 → azimut-0.2.4}/tests/test_settings_backup.py +0 -0
  422. {azimut-0.2.2 → azimut-0.2.4}/tests/test_stitch.py +0 -0
  423. {azimut-0.2.2 → azimut-0.2.4}/tests/test_templates_api.py +0 -0
  424. {azimut-0.2.2 → azimut-0.2.4}/tests/test_thumbnails.py +0 -0
  425. {azimut-0.2.2 → azimut-0.2.4}/tests/test_tiles.py +0 -0
  426. {azimut-0.2.2 → azimut-0.2.4}/tests/test_updates.py +0 -0
@@ -11,8 +11,37 @@ permissions:
11
11
  id-token: write # PyPI Trusted Publishing (OIDC) — no token secret needed
12
12
 
13
13
  jobs:
14
+ guard:
15
+ name: Version + release gate
16
+ runs-on: ubuntu-latest
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+ - uses: astral-sh/setup-uv@v5
20
+ with:
21
+ python-version: "3.12"
22
+ # Install the app (editable) + dev tools, like the CI backend job, so the
23
+ # gate can import azimut and run its tests. No frontend build: these tests
24
+ # don't touch the built UI, and the app tolerates a missing static dir.
25
+ - run: uv sync --frozen --extra dev
26
+ # The pushed tag must equal the version baked into the code. When it
27
+ # didn't (0.2.2 shipped a stale __version__), the binary's self-update
28
+ # check nagged every user about the very release they were running. This
29
+ # is the check the release used to lack — it runs before anything builds.
30
+ - name: Tag matches the code version
31
+ if: startsWith(github.ref, 'refs/tags/v')
32
+ run: |
33
+ tag="${GITHUB_REF_NAME#v}"
34
+ ver="$(uv run --no-sync python -c 'import azimut; print(azimut.__version__)')"
35
+ echo "tag=$tag __version__=$ver"
36
+ [ "$tag" = "$ver" ] || { echo "::error::tag v$tag != __version__ $ver — bump src/azimut/__init__.py"; exit 1; }
37
+ # The version-parity gate the release workflow used to skip: pyproject's
38
+ # single-sourced version and the extension manifest must line up.
39
+ - name: Release gate + version parity
40
+ run: uv run --no-sync pytest tests/test_release_gate.py tests/test_updates.py -q
41
+
14
42
  dist:
15
43
  name: Build wheel + sdist
44
+ needs: guard
16
45
  runs-on: ubuntu-latest
17
46
  steps:
18
47
  - uses: actions/checkout@v4
@@ -45,6 +74,7 @@ jobs:
45
74
 
46
75
  binaries:
47
76
  name: Binary (${{ matrix.os }})
77
+ needs: guard
48
78
  runs-on: ${{ matrix.os }}
49
79
  strategy:
50
80
  fail-fast: false
@@ -52,13 +82,15 @@ jobs:
52
82
  include:
53
83
  - os: ubuntu-latest
54
84
  asset: azimut-linux-x86_64
85
+ ffmpeg_target: linux-x86_64
55
86
  - os: windows-latest
56
87
  asset: azimut-windows-x86_64.exe
88
+ ffmpeg_target: windows-x86_64
57
89
  - os: macos-latest
58
90
  asset: azimut-macos-arm64
59
- # macos-latest is Apple Silicon. We don't ship an Intel binary: the
60
- # last Intel runner (macos-13) is deprecated and its queue stalls
61
- # releases. Intel Macs are covered by `pip install azimut` instead.
91
+ ffmpeg_target: macos-arm64
92
+ # macos-latest is Apple Silicon. Intel remains a documented Python
93
+ # package install rather than a standalone release asset.
62
94
  steps:
63
95
  - uses: actions/checkout@v4
64
96
  - uses: actions/setup-node@v4
@@ -76,40 +108,13 @@ jobs:
76
108
  run: |
77
109
  uv sync --frozen --no-dev --group release --no-install-project
78
110
  uv sync --frozen --no-dev --group release --no-build-isolation --no-editable
79
- # ffmpeg is a native program, not a Python dep, so it isn't in the wheel.
80
- # Vendor a static ffmpeg + ffprobe per-OS so the binary works out of the
81
- # box (packaging/azimut.spec picks them up; engine/ffmpeg.py finds them at
82
- # runtime). One host, one arch per runner; each zip holds a single binary.
111
+ # ffmpeg is a native program, not a Python dep. The helper pins and hashes
112
+ # each upstream archive, then extracts only the expected tools.
83
113
  - name: Vendor static ffmpeg + ffprobe into the binary
84
- shell: bash
85
- run: |
86
- mkdir -p packaging/vendor
87
- if [ "${{ runner.os }}" = "Windows" ]; then
88
- # martin-riedl.de stopped publishing Windows builds; BtbN's
89
- # "latest" release tag always points at the newest static win64
90
- # build, so pull ffmpeg.exe/ffprobe.exe out of its nested bin/.
91
- curl -fL "https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-win64-gpl.zip" -o ffmpeg.zip
92
- uv run --no-sync python -c "
93
- import zipfile
94
- zf = zipfile.ZipFile('ffmpeg.zip')
95
- for n in zf.namelist():
96
- tail = n.rsplit('/', 1)[-1]
97
- if tail in ('ffmpeg.exe', 'ffprobe.exe'):
98
- open('packaging/vendor/' + tail, 'wb').write(zf.read(n))
99
- "
100
- else
101
- case "${{ runner.os }}" in
102
- Linux) plat=linux/amd64 ;;
103
- macOS) plat=macos/arm64 ;;
104
- esac
105
- base="https://ffmpeg.martin-riedl.de/redirect/latest/$plat/release"
106
- for tool in ffmpeg ffprobe; do
107
- curl -fL "$base/$tool.zip" -o "$tool.zip"
108
- uv run --no-sync python -c "import sys, zipfile; zipfile.ZipFile(sys.argv[1]).extractall('packaging/vendor')" "$tool.zip"
109
- done
110
- fi
111
- chmod +x packaging/vendor/* 2>/dev/null || true
112
- ls -l packaging/vendor
114
+ run: >-
115
+ uv run --no-sync python scripts/vendor_ffmpeg.py
116
+ "${{ matrix.ffmpeg_target }}"
117
+ --output packaging/vendor
113
118
  - name: Build single-file binary
114
119
  run: uv run --no-sync pyinstaller packaging/azimut.spec --distpath dist-bin --workpath build-bin
115
120
  - name: Smoke-test the binary
@@ -48,6 +48,7 @@ CLAUDE.md
48
48
  .claude/
49
49
  AGENTS.md
50
50
  .codex/
51
+ .agents/
51
52
  .cheatsheet
52
53
 
53
54
  # PyInstaller local output
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: azimut
3
- Version: 0.2.2
3
+ Version: 0.2.4
4
4
  Summary: A local OSINT workspace for media, geolocation proofs and case management.
5
5
  Project-URL: Homepage, https://github.com/OsintMeThat/azimut
6
6
  Author: OsintMeThat
7
7
  License: AGPL-3.0-only
8
8
  License-File: LICENSE
9
9
  Keywords: geoint,geolocation,investigation,osint,verification
10
- Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Development Status :: 4 - Beta
11
11
  Classifier: Environment :: Web Environment
12
12
  Classifier: Intended Audience :: Other Audience
13
13
  Classifier: Operating System :: OS Independent
@@ -47,7 +47,7 @@ case is a plain folder that can be reopened, archived or shared.
47
47
  *The name is the French word for azimuth, the compass bearing you sight along
48
48
  to fix a point on the map.*
49
49
 
50
- ## v0.2.2: Login-walled downloads
50
+ ## v0.2.4: Saved work and scalable browsing
51
51
 
52
52
  | Tool | What it does |
53
53
  |------|--------------|
@@ -67,15 +67,18 @@ extension, and cross-platform binaries with a bundled ffmpeg.
67
67
  Every tool works one-shot (a scratch session, no setup) or inside a case, a
68
68
  plain directory holding the whole investigation.
69
69
 
70
- New in v0.2.2:
70
+ New in v0.2.4:
71
71
 
72
- - Downloads now handle login-walled media. The first attempt is always
73
- cookie-less; only when a post turns out to need an account does Media offer to
74
- borrow a signed-in browser's session or an exported `cookies.txt`. The session
75
- is used for that download, kept 0600 in the workspace, and never leaves the
76
- machine. Chromium on Windows can't be read, so it points you to the file route.
77
- - The Geo Proof toolbar reflows to fit narrow screens instead of overflowing,
78
- and remembers the color and stroke width you last drew with.
72
+ - Saved places, captures, filed screenshots and proofs are easier to find,
73
+ preview and place on the map.
74
+ - The case sidebar and Files now support search, filters, folder browsing,
75
+ multi-select filing and a details list.
76
+ - Media and Files use bounded SQLite queries, including complete category
77
+ counts and search results beyond the first page.
78
+ - Inspect, Geo Proof and Geo Report use named saves. Their pickers can search
79
+ and browse folders.
80
+ - Release binaries now fetch pinned, SHA-256-verified ffmpeg archives. Images
81
+ above 100 MP are rejected before decode.
79
82
 
80
83
  ## Install & run
81
84
 
@@ -101,12 +104,9 @@ opens Azimut in your browser.
101
104
  |----|-------|
102
105
  | Windows | `azimut-windows-x86_64.exe` |
103
106
  | macOS (Apple Silicon) | `azimut-macos-arm64` |
104
- | macOS (Intel) | No standalone binary; install with `pipx` or `pip` |
107
+ | macOS (Intel, 14+) | No standalone binary; install with `pipx` or `pip` |
105
108
  | Linux | `azimut-linux-x86_64` |
106
109
 
107
- Intel Macs are supported through the Python package. They do not have a
108
- downloadable standalone binary.
109
-
110
110
  First run, the binaries are **unsigned**, so the OS warns before letting them
111
111
  open:
112
112
  - **macOS**: right-click the file → **Open** → **Open** (Gatekeeper only
@@ -116,10 +116,10 @@ open:
116
116
  info** → **Run anyway**.
117
117
  - **Linux**: mark it executable with `chmod +x azimut-linux-x86_64`.
118
118
 
119
- To update, **Settings → About → Check for updates** tells you when a newer
120
- release is out and links the download; replace the old file with the new one.
121
- To uninstall, delete the file. Either way `~/Azimut` stays put, so your cases
122
- open unchanged in the new version.
119
+ Azimut checks for a newer release on startup by default and links the download.
120
+ Settings can disable that check, and **Settings → About → Check for updates**
121
+ runs it manually. Replace the old binary with the new one. To uninstall, delete
122
+ the binary. Either way `~/Azimut` stays put, so cases open unchanged.
123
123
 
124
124
  The downloadable binaries bundle a static **ffmpeg** (and ffprobe), so video
125
125
  thumbnails, frame scans, video enhancement, and downloads that merge separate
@@ -235,7 +235,7 @@ wheel + Windows/Linux/macOS binaries, attaches them to a GitHub release, and
235
235
  publishes to PyPI. **Don't publish by hand.**
236
236
 
237
237
  ```bash
238
- git tag v0.2.2 && git push origin v0.2.2
238
+ git tag v0.2.4 && git push origin v0.2.4
239
239
  ```
240
240
 
241
241
  One-time setup: register the repo as a
@@ -244,17 +244,14 @@ One-time setup: register the repo as a
244
244
 
245
245
  ## Principles
246
246
 
247
- 1. **Local-first, privacy-first.** No account, no telemetry, no upload; the
248
- server binds to `127.0.0.1` only, and Azimut never posts anywhere on your
249
- behalf.
250
- 2. **The case is the product.** Media and notes stay as files and the graph lives
251
- in per-case SQLite. A closed case folder is complete and portable; a ZIP
252
- import/export workflow is planned.
247
+ 1. No account, telemetry or automatic upload. The server binds to
248
+ `127.0.0.1`, and Azimut never posts on your behalf.
249
+ 2. A case contains the investigation's files and SQLite graph. A closed case
250
+ folder is complete and portable; ZIP import/export is planned.
253
251
  3. One tab = one tool, useful in 30 seconds.
254
- 4. **Orchestrator, not replacer.** Integrate specialized services rather than
255
- cloning them.
256
- 5. Tools emit facts; the analyst decides. No automated "magic button".
257
- 6. **Honest output.** Every artifact records how it was produced.
252
+ 4. Azimut integrates specialized services instead of recreating them.
253
+ 5. The analyst decides; tools do not produce automated verdicts.
254
+ 6. Every artifact records how it was produced.
258
255
  7. Free and open source. No paid key is ever required; bring your own for
259
256
  more basemaps.
260
257
 
@@ -9,7 +9,7 @@ case is a plain folder that can be reopened, archived or shared.
9
9
  *The name is the French word for azimuth, the compass bearing you sight along
10
10
  to fix a point on the map.*
11
11
 
12
- ## v0.2.2: Login-walled downloads
12
+ ## v0.2.4: Saved work and scalable browsing
13
13
 
14
14
  | Tool | What it does |
15
15
  |------|--------------|
@@ -29,15 +29,18 @@ extension, and cross-platform binaries with a bundled ffmpeg.
29
29
  Every tool works one-shot (a scratch session, no setup) or inside a case, a
30
30
  plain directory holding the whole investigation.
31
31
 
32
- New in v0.2.2:
32
+ New in v0.2.4:
33
33
 
34
- - Downloads now handle login-walled media. The first attempt is always
35
- cookie-less; only when a post turns out to need an account does Media offer to
36
- borrow a signed-in browser's session or an exported `cookies.txt`. The session
37
- is used for that download, kept 0600 in the workspace, and never leaves the
38
- machine. Chromium on Windows can't be read, so it points you to the file route.
39
- - The Geo Proof toolbar reflows to fit narrow screens instead of overflowing,
40
- and remembers the color and stroke width you last drew with.
34
+ - Saved places, captures, filed screenshots and proofs are easier to find,
35
+ preview and place on the map.
36
+ - The case sidebar and Files now support search, filters, folder browsing,
37
+ multi-select filing and a details list.
38
+ - Media and Files use bounded SQLite queries, including complete category
39
+ counts and search results beyond the first page.
40
+ - Inspect, Geo Proof and Geo Report use named saves. Their pickers can search
41
+ and browse folders.
42
+ - Release binaries now fetch pinned, SHA-256-verified ffmpeg archives. Images
43
+ above 100 MP are rejected before decode.
41
44
 
42
45
  ## Install & run
43
46
 
@@ -63,12 +66,9 @@ opens Azimut in your browser.
63
66
  |----|-------|
64
67
  | Windows | `azimut-windows-x86_64.exe` |
65
68
  | macOS (Apple Silicon) | `azimut-macos-arm64` |
66
- | macOS (Intel) | No standalone binary; install with `pipx` or `pip` |
69
+ | macOS (Intel, 14+) | No standalone binary; install with `pipx` or `pip` |
67
70
  | Linux | `azimut-linux-x86_64` |
68
71
 
69
- Intel Macs are supported through the Python package. They do not have a
70
- downloadable standalone binary.
71
-
72
72
  First run, the binaries are **unsigned**, so the OS warns before letting them
73
73
  open:
74
74
  - **macOS**: right-click the file → **Open** → **Open** (Gatekeeper only
@@ -78,10 +78,10 @@ open:
78
78
  info** → **Run anyway**.
79
79
  - **Linux**: mark it executable with `chmod +x azimut-linux-x86_64`.
80
80
 
81
- To update, **Settings → About → Check for updates** tells you when a newer
82
- release is out and links the download; replace the old file with the new one.
83
- To uninstall, delete the file. Either way `~/Azimut` stays put, so your cases
84
- open unchanged in the new version.
81
+ Azimut checks for a newer release on startup by default and links the download.
82
+ Settings can disable that check, and **Settings → About → Check for updates**
83
+ runs it manually. Replace the old binary with the new one. To uninstall, delete
84
+ the binary. Either way `~/Azimut` stays put, so cases open unchanged.
85
85
 
86
86
  The downloadable binaries bundle a static **ffmpeg** (and ffprobe), so video
87
87
  thumbnails, frame scans, video enhancement, and downloads that merge separate
@@ -197,7 +197,7 @@ wheel + Windows/Linux/macOS binaries, attaches them to a GitHub release, and
197
197
  publishes to PyPI. **Don't publish by hand.**
198
198
 
199
199
  ```bash
200
- git tag v0.2.2 && git push origin v0.2.2
200
+ git tag v0.2.4 && git push origin v0.2.4
201
201
  ```
202
202
 
203
203
  One-time setup: register the repo as a
@@ -206,17 +206,14 @@ One-time setup: register the repo as a
206
206
 
207
207
  ## Principles
208
208
 
209
- 1. **Local-first, privacy-first.** No account, no telemetry, no upload; the
210
- server binds to `127.0.0.1` only, and Azimut never posts anywhere on your
211
- behalf.
212
- 2. **The case is the product.** Media and notes stay as files and the graph lives
213
- in per-case SQLite. A closed case folder is complete and portable; a ZIP
214
- import/export workflow is planned.
209
+ 1. No account, telemetry or automatic upload. The server binds to
210
+ `127.0.0.1`, and Azimut never posts on your behalf.
211
+ 2. A case contains the investigation's files and SQLite graph. A closed case
212
+ folder is complete and portable; ZIP import/export is planned.
215
213
  3. One tab = one tool, useful in 30 seconds.
216
- 4. **Orchestrator, not replacer.** Integrate specialized services rather than
217
- cloning them.
218
- 5. Tools emit facts; the analyst decides. No automated "magic button".
219
- 6. **Honest output.** Every artifact records how it was produced.
214
+ 4. Azimut integrates specialized services instead of recreating them.
215
+ 5. The analyst decides; tools do not produce automated verdicts.
216
+ 6. Every artifact records how it was produced.
220
217
  7. Free and open source. No paid key is ever required; bring your own for
221
218
  more basemaps.
222
219
 
@@ -7,7 +7,8 @@
7
7
  **Storage schema: `3`.** The manifest carries `{"azimut": {"schema": 3,
8
8
  "storage": "sqlite"}}`; schema 3 moved the graph from `case.json` to per-case
9
9
  `case.db`. The entity/link shape is unchanged since v1. Breaking changes require
10
- a schema bump and migration.
10
+ a manifest schema bump and migration. The internal SQLite schema is version 4;
11
+ it adds search and media browse indexes without changing this logical model.
11
12
 
12
13
  Legend: ✅ implemented in code · 🔶 machinery exists, unused · ⬜ proposed.
13
14
 
@@ -26,8 +27,9 @@ presents it as this logical shape:
26
27
  - **Links** are typed directed edges. Every save records its inputs; see §3. ✅
27
28
  - **Folders** are `/`-nested analyst buckets in `attrs.folder`, not semantic
28
29
  links. ✅
29
- - Media sidecars hold kind, size, uploader, duration and thumbnail data. Entities
30
- retain only what the graph needs for identity, links and deduplication.
30
+ - Media sidecars hold kind, size, uploader, duration and thumbnail data. A
31
+ SQLite browse index mirrors searchable fields. Entities retain only what the
32
+ graph needs for identity, links and deduplication.
31
33
 
32
34
  ## 2. Entity
33
35
 
@@ -43,13 +45,22 @@ presents it as this logical shape:
43
45
  `type` is extensible: unknown strings are stored but receive no custom renderer.
44
46
  `label` is editable and never defines identity.
45
47
 
48
+ `geo` is the country a saved point falls in, resolved once and kept:
49
+ `{state, country_code, country, region?, region_en?}` with `state` one of `ok`,
50
+ `nocoords` (no position to look up), `nocountry` (open sea) or `failed` (the
51
+ lookup did not answer — the only state a later pass retries). `country` and
52
+ `region` are the local-language names; `region_en` is a second lookup in English
53
+ and is absent when it failed or matched the native name. Continent and the
54
+ English country name are *not* stored: both are derived from `country_code` at
55
+ read time, so extending those tables repairs existing cases with no migration.
56
+
46
57
  ### Entity type registry
47
58
 
48
59
  | Type | State | Produced by | Key `attrs` | File-backed |
49
60
  |---|---|---|---|---|
50
61
  | `media` | ✅ | media-library | `path`, `sha256`, `source_url?` | yes (+ sidecar) |
51
- | `capture` | ✅ | satellite | `coords`, `lat`, `lon`, `plus_code`, `zoom`, `bearing`, `path` | yes (image) |
52
- | `place` | ✅ | satellite | `coords`, `lat`, `lon`, `plus_code`, `zoom`, `bearing`, `notes?` | no (a point) |
62
+ | `capture` | ✅ | satellite | `coords`, `lat`, `lon`, `plus_code`, `zoom`, `bearing`, `path`, `geo?` | yes (image) |
63
+ | `place` | ✅ | satellite, ingest | `coords`, `lat`, `lon`, `plus_code`, `zoom`, `bearing`, `notes?`, `geo?`, `source_url?`, `site?` | no (a point) |
53
64
  | `proof` | ✅ | proof-composer | `spec` (json), `path` (png) | yes |
54
65
  | `post` | ✅ | post-composer | `draft` (json) | yes |
55
66
  | `inspect-session` | ✅ | inspect | `spec` (json) | yes |
@@ -67,6 +78,11 @@ New types coming from the roadmap (declare here when built): `panorama`,
67
78
  Per-type attribute schemas remain open work. Today attribute keys are conventions,
68
79
  not a validated contract between tools.
69
80
 
81
+ The file-backed pointers of `proof`, `post` and `inspect-session` (`spec`,
82
+ `draft`, `path`) are not stable: the file's name follows the label, so renaming
83
+ one in its tool rewrites the pointer on the same entity. Look these up by id, or
84
+ re-read the pointer — never cache one across a save.
85
+
70
86
  ## 3. Link
71
87
 
72
88
  ```jsonc
@@ -106,6 +122,13 @@ A tool selects one of two deletion behaviours through its link type:
106
122
 
107
123
  - `derived-from` never cascades into an output. A post keeps its text when its
108
124
  proof is deleted; a frame keeps its pixels when its video is deleted.
125
+ - It is also read backwards, as geography. The Saved panel counts the proofs
126
+ hanging off each saved point through this edge, and a proof with no point of
127
+ its own is placed at the point of every capture it composes, one hop back.
128
+ A proof does carry its own point first, though: `coordsText` (what the analyst
129
+ typed, in any supported format) then `coords` (what the panels gave it, frozen
130
+ at save). That is what keeps a proof on the map once its capture is deleted —
131
+ a tombstone records the path, the sha256 and the URL, never coordinates.
109
132
  - `attrs.lost_sources[]` stores `{label, type, path, sha256, source_url, at}`.
110
133
  Tombstones are keyed by path and never stacked.
111
134
  - Every UI deletion uses the same dependency-aware service. The confirmation
@@ -133,6 +156,9 @@ How it is wired (`engine/links.py`):
133
156
  resolves path → entity and emits the edge.
134
157
  - Every save restates sources through `sync`. Removing a panel removes its edge;
135
158
  repeated saves keep one edge per panel.
159
+ - A proof's pasted images are read as decoration, not sources: they carry no case
160
+ path, so they file no entity and earn no edge. Only panels put a proof in a
161
+ chain.
136
162
  - A missing source path produces a tombstone instead of a link.
137
163
  - Media derivatives are all filed through one registration point, so any future
138
164
  tool producing imagery gets its chain for free. A derivative that **dedupes**
@@ -0,0 +1,61 @@
1
+ # Azimut v0.2.4
2
+
3
+ ## OSINT toolkit at a glance
4
+
5
+ - **Sources:** import or download media, use an existing login when a post
6
+ requires it, record hashes and provenance, inspect frames, crops, collages,
7
+ panoramas and ELA, then prepare reverse-image searches.
8
+ - **Maps:** convert coordinates, geocode places, capture attributed imagery,
9
+ compare providers, rotate and measure maps, save references and review AOI
10
+ grids.
11
+ - **Evidence:** organise media, places, proofs and notes in portable cases with
12
+ folders, links, Markdown notebooks and PDF output.
13
+ - **Publishing:** build annotated Geo Proofs and prepare evidence-linked Geo
14
+ Reports for X, Bluesky or Mastodon without posting automatically.
15
+
16
+ ## What changed
17
+
18
+ - **Saved work on the map.** Places, captures and filed screenshots can be
19
+ browsed by geography or case folder, searched in English or the local name,
20
+ previewed and shown on the map. Proofs appear at their own coordinates or at
21
+ the captures they use.
22
+ - **Case organisation.** The sidebar adds search, type and status filters,
23
+ multi-select filing and a details drawer. Files adds Small, Large and List
24
+ views with sortable columns and complete folder browsing.
25
+ - **Named work.** Inspect, Geo Proof and Geo Report name their documents in the
26
+ header and keep that name when saved or renamed. Inspect's save dialog can
27
+ name a batch and attach one note.
28
+ - **Faster browsing.** Media and Files now query a SQLite browse index. Search,
29
+ folder filters and Media category counts cover the complete case instead of
30
+ only the first 200 items. Files requests thumbnail metadata only for paths it
31
+ can display.
32
+ - **Better pickers and proofs.** Inspect, Reverse Search, Geo Proof and Notebook
33
+ pickers can search and browse folders. Geo Proof supports coloured panel
34
+ frames, layer controls and pasted overlays stored with that proof.
35
+ - **Capture extension.** A map point can be saved as a place, and any page can
36
+ be saved as a bookmark. Map captures keep their source metadata and
37
+ attribution.
38
+ - **Case-switch fix.** Saved Satellite items and Media thumbnail state are
39
+ cleared before a different case loads, so data from the previous case no
40
+ longer remains until refresh.
41
+ - **Release and security hardening.** Release builds use pinned, SHA-256-checked
42
+ ffmpeg archives and extract only the expected tools. Images above 100 MP are
43
+ rejected before decode. SQLite schema 4 adds the media browse index and
44
+ upgrades existing cases automatically.
45
+
46
+ The read-only GitHub release check still runs on startup by default. It can be
47
+ disabled in Settings, and offline failures remain silent.
48
+
49
+ ## Install or upgrade
50
+
51
+ Download the ready-to-run asset for Windows x86_64, Linux x86_64 or Apple
52
+ Silicon macOS and run it. Each binary includes the browser UI, `ffmpeg` and
53
+ `ffprobe`; no Python or system FFmpeg is needed.
54
+
55
+ Intel Macs require macOS 14 or newer and the Python package:
56
+ `pipx install azimut` or `pip install azimut`.
57
+
58
+ The binaries are unsigned. Follow the operating system prompt described in the
59
+ README on first launch.
60
+
61
+ Existing cases upgrade in place. No manual export or import is required.