MetaList 0.7.3__tar.gz → 0.7.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 (472) hide show
  1. {metalist-0.7.3 → metalist-0.7.4}/PKG-INFO +8 -2
  2. {metalist-0.7.3 → metalist-0.7.4}/README.md +7 -1
  3. {metalist-0.7.3 → metalist-0.7.4}/app/https_proxy.py +55 -15
  4. {metalist-0.7.3 → metalist-0.7.4}/app/services/self_update.py +1 -7
  5. metalist-0.7.4/app/services/update_installer.py +260 -0
  6. {metalist-0.7.3 → metalist-0.7.4}/app/services/update_preflight.py +2 -5
  7. {metalist-0.7.3 → metalist-0.7.4}/app/version.py +1 -1
  8. {metalist-0.7.3 → metalist-0.7.4}/metalist.egg-info/PKG-INFO +8 -2
  9. metalist-0.7.3/app/services/update_installer.py +0 -122
  10. {metalist-0.7.3 → metalist-0.7.4}/MANIFEST.in +0 -0
  11. {metalist-0.7.3 → metalist-0.7.4}/app/__init__.py +0 -0
  12. {metalist-0.7.3 → metalist-0.7.4}/app/api/__init__.py +0 -0
  13. {metalist-0.7.3 → metalist-0.7.4}/app/api/deps.py +0 -0
  14. {metalist-0.7.3 → metalist-0.7.4}/app/api/dev.py +0 -0
  15. {metalist-0.7.3 → metalist-0.7.4}/app/api/middleware/auth.py +0 -0
  16. {metalist-0.7.3 → metalist-0.7.4}/app/api/note_requests.py +0 -0
  17. {metalist-0.7.3 → metalist-0.7.4}/app/api/request_auth.py +0 -0
  18. {metalist-0.7.3 → metalist-0.7.4}/app/api/routes/ai.py +0 -0
  19. {metalist-0.7.3 → metalist-0.7.4}/app/api/routes/app_updates.py +0 -0
  20. {metalist-0.7.3 → metalist-0.7.4}/app/api/routes/auth.py +0 -0
  21. {metalist-0.7.3 → metalist-0.7.4}/app/api/routes/backups.py +0 -0
  22. {metalist-0.7.3 → metalist-0.7.4}/app/api/routes/files.py +0 -0
  23. {metalist-0.7.3 → metalist-0.7.4}/app/api/routes/notes.py +0 -0
  24. {metalist-0.7.3 → metalist-0.7.4}/app/api/routes/ontology.py +0 -0
  25. {metalist-0.7.3 → metalist-0.7.4}/app/api/routes/reminders.py +0 -0
  26. {metalist-0.7.3 → metalist-0.7.4}/app/api/routes/remote_images.py +0 -0
  27. {metalist-0.7.3 → metalist-0.7.4}/app/api/routes/test.py +0 -0
  28. {metalist-0.7.3 → metalist-0.7.4}/app/api/transactions.py +0 -0
  29. {metalist-0.7.3 → metalist-0.7.4}/app/api/upload_limits.py +0 -0
  30. {metalist-0.7.3 → metalist-0.7.4}/app/config.py +0 -0
  31. {metalist-0.7.3 → metalist-0.7.4}/app/data_directory.py +0 -0
  32. {metalist-0.7.3 → metalist-0.7.4}/app/db/__init__.py +0 -0
  33. {metalist-0.7.3 → metalist-0.7.4}/app/db/backup_settings_sql.py +0 -0
  34. {metalist-0.7.3 → metalist-0.7.4}/app/db/engine.py +0 -0
  35. {metalist-0.7.3 → metalist-0.7.4}/app/db/file_schema.py +0 -0
  36. {metalist-0.7.3 → metalist-0.7.4}/app/db/file_session.py +0 -0
  37. {metalist-0.7.3 → metalist-0.7.4}/app/db/files_sql.py +0 -0
  38. {metalist-0.7.3 → metalist-0.7.4}/app/db/link_titles_sql.py +0 -0
  39. {metalist-0.7.3 → metalist-0.7.4}/app/db/live_recovery.py +0 -0
  40. {metalist-0.7.3 → metalist-0.7.4}/app/db/migrations.py +0 -0
  41. {metalist-0.7.3 → metalist-0.7.4}/app/db/notes_sql.py +0 -0
  42. {metalist-0.7.3 → metalist-0.7.4}/app/db/ontology_rules_sql.py +0 -0
  43. {metalist-0.7.3 → metalist-0.7.4}/app/db/reminders_sql.py +0 -0
  44. {metalist-0.7.3 → metalist-0.7.4}/app/db/retire_sounds.py +0 -0
  45. {metalist-0.7.3 → metalist-0.7.4}/app/db/schema.py +0 -0
  46. {metalist-0.7.3 → metalist-0.7.4}/app/db/search_history_sql.py +0 -0
  47. {metalist-0.7.3 → metalist-0.7.4}/app/db/session.py +0 -0
  48. {metalist-0.7.3 → metalist-0.7.4}/app/db/settings_sql.py +0 -0
  49. {metalist-0.7.3 → metalist-0.7.4}/app/db/tab_state_sql.py +0 -0
  50. {metalist-0.7.3 → metalist-0.7.4}/app/db/version.py +0 -0
  51. {metalist-0.7.3 → metalist-0.7.4}/app/encryption_audit.py +0 -0
  52. {metalist-0.7.3 → metalist-0.7.4}/app/exception_boundaries.py +0 -0
  53. {metalist-0.7.3 → metalist-0.7.4}/app/main.py +0 -0
  54. {metalist-0.7.3 → metalist-0.7.4}/app/models/commands.py +0 -0
  55. {metalist-0.7.3 → metalist-0.7.4}/app/models/database.py +0 -0
  56. {metalist-0.7.3 → metalist-0.7.4}/app/models/entities.py +0 -0
  57. {metalist-0.7.3 → metalist-0.7.4}/app/models/enums.py +0 -0
  58. {metalist-0.7.3 → metalist-0.7.4}/app/models/linked_list.py +0 -0
  59. {metalist-0.7.3 → metalist-0.7.4}/app/models/list_operations.py +0 -0
  60. {metalist-0.7.3 → metalist-0.7.4}/app/models/list_traversal.py +0 -0
  61. {metalist-0.7.3 → metalist-0.7.4}/app/models/note_crud.py +0 -0
  62. {metalist-0.7.3 → metalist-0.7.4}/app/models/utils.py +0 -0
  63. {metalist-0.7.3 → metalist-0.7.4}/app/network_settings.py +0 -0
  64. {metalist-0.7.3 → metalist-0.7.4}/app/presentation/__init__.py +0 -0
  65. {metalist-0.7.3 → metalist-0.7.4}/app/presentation/render/__init__.py +0 -0
  66. {metalist-0.7.3 → metalist-0.7.4}/app/presentation/render/note_renderer.py +0 -0
  67. {metalist-0.7.3 → metalist-0.7.4}/app/presentation/templates.py +0 -0
  68. {metalist-0.7.3 → metalist-0.7.4}/app/security/authenticated_logging.py +0 -0
  69. {metalist-0.7.3 → metalist-0.7.4}/app/security/encryption.py +0 -0
  70. {metalist-0.7.3 → metalist-0.7.4}/app/security/http_headers.py +0 -0
  71. {metalist-0.7.3 → metalist-0.7.4}/app/security/note_html.py +0 -0
  72. {metalist-0.7.3 → metalist-0.7.4}/app/security/request_boundary.py +0 -0
  73. {metalist-0.7.3 → metalist-0.7.4}/app/security/request_hosts.py +0 -0
  74. {metalist-0.7.3 → metalist-0.7.4}/app/security/sensitive_cache.py +0 -0
  75. {metalist-0.7.3 → metalist-0.7.4}/app/security/sensitive_logging.py +0 -0
  76. {metalist-0.7.3 → metalist-0.7.4}/app/security/shell_execution.py +0 -0
  77. {metalist-0.7.3 → metalist-0.7.4}/app/security/validation_errors.py +0 -0
  78. {metalist-0.7.3 → metalist-0.7.4}/app/server_runtime.py +0 -0
  79. {metalist-0.7.3 → metalist-0.7.4}/app/services/__init__.py +0 -0
  80. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/__init__.py +0 -0
  81. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/actions.py +0 -0
  82. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/cloud_privacy.py +0 -0
  83. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/context.py +0 -0
  84. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/evidence_serialization.py +0 -0
  85. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/help_catalog.py +0 -0
  86. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/history.py +0 -0
  87. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/inference.py +0 -0
  88. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/investigation.py +0 -0
  89. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/judging.py +0 -0
  90. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/menu_actions.py +0 -0
  91. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/model_policy.py +0 -0
  92. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/openai_cost_tracking.py +0 -0
  93. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/openai_inference.py +0 -0
  94. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/permissions.py +0 -0
  95. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/prompt_settings.py +0 -0
  96. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/prompts/__init__.py +0 -0
  97. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/prompts/final-response.md +0 -0
  98. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/prompts/help-response.md +0 -0
  99. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/prompts/system.md +0 -0
  100. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/prompts/tool-result.md +0 -0
  101. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/retrieval_settings.py +0 -0
  102. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/runtime.py +0 -0
  103. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/scope.py +0 -0
  104. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/skill_settings.py +0 -0
  105. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/skills/__init__.py +0 -0
  106. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/skills/help-ai.md +0 -0
  107. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/skills/help-data.md +0 -0
  108. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/skills/help-formatting.md +0 -0
  109. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/skills/help-menus.md +0 -0
  110. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/skills/help-notes.md +0 -0
  111. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/skills/help-privacy.md +0 -0
  112. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/skills/help-references.md +0 -0
  113. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/skills/help-reminders.md +0 -0
  114. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/skills/help-search.md +0 -0
  115. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/skills/help-tags.md +0 -0
  116. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/skills/scoped-investigation.md +0 -0
  117. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/structured_inference.py +0 -0
  118. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/tagging.py +0 -0
  119. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/tagging_run.py +0 -0
  120. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/token_estimation.py +0 -0
  121. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/tools.py +0 -0
  122. {metalist-0.7.3 → metalist-0.7.4}/app/services/agent/trace.py +0 -0
  123. {metalist-0.7.3 → metalist-0.7.4}/app/services/ai_chat.py +0 -0
  124. {metalist-0.7.3 → metalist-0.7.4}/app/services/ai_chat_rendering.py +0 -0
  125. {metalist-0.7.3 → metalist-0.7.4}/app/services/ai_chat_stream.py +0 -0
  126. {metalist-0.7.3 → metalist-0.7.4}/app/services/app_update_worker.py +0 -0
  127. {metalist-0.7.3 → metalist-0.7.4}/app/services/app_updates.py +0 -0
  128. {metalist-0.7.3 → metalist-0.7.4}/app/services/auth.py +0 -0
  129. {metalist-0.7.3 → metalist-0.7.4}/app/services/auth_cache_state.py +0 -0
  130. {metalist-0.7.3 → metalist-0.7.4}/app/services/auth_service.py +0 -0
  131. {metalist-0.7.3 → metalist-0.7.4}/app/services/backlink_index.py +0 -0
  132. {metalist-0.7.3 → metalist-0.7.4}/app/services/backlinks.py +0 -0
  133. {metalist-0.7.3 → metalist-0.7.4}/app/services/backup_service.py +0 -0
  134. {metalist-0.7.3 → metalist-0.7.4}/app/services/backup_settings_service.py +0 -0
  135. {metalist-0.7.3 → metalist-0.7.4}/app/services/bulk_operation.py +0 -0
  136. {metalist-0.7.3 → metalist-0.7.4}/app/services/client_state_service.py +0 -0
  137. {metalist-0.7.3 → metalist-0.7.4}/app/services/content_cache.py +0 -0
  138. {metalist-0.7.3 → metalist-0.7.4}/app/services/content_formatting.py +0 -0
  139. {metalist-0.7.3 → metalist-0.7.4}/app/services/diagnostics.py +0 -0
  140. {metalist-0.7.3 → metalist-0.7.4}/app/services/embedded_references.py +0 -0
  141. {metalist-0.7.3 → metalist-0.7.4}/app/services/encryption.py +0 -0
  142. {metalist-0.7.3 → metalist-0.7.4}/app/services/exception_capture.py +0 -0
  143. {metalist-0.7.3 → metalist-0.7.4}/app/services/file_registry.py +0 -0
  144. {metalist-0.7.3 → metalist-0.7.4}/app/services/file_storage.py +0 -0
  145. {metalist-0.7.3 → metalist-0.7.4}/app/services/footnote_layout.py +0 -0
  146. {metalist-0.7.3 → metalist-0.7.4}/app/services/footnote_rendering.py +0 -0
  147. {metalist-0.7.3 → metalist-0.7.4}/app/services/hierarchy.py +0 -0
  148. {metalist-0.7.3 → metalist-0.7.4}/app/services/html_export.py +0 -0
  149. {metalist-0.7.3 → metalist-0.7.4}/app/services/html_unformatting.py +0 -0
  150. {metalist-0.7.3 → metalist-0.7.4}/app/services/hydration_state.py +0 -0
  151. {metalist-0.7.3 → metalist-0.7.4}/app/services/image_size_formatting.py +0 -0
  152. {metalist-0.7.3 → metalist-0.7.4}/app/services/inline_image_occurrences.py +0 -0
  153. {metalist-0.7.3 → metalist-0.7.4}/app/services/input_errors.py +0 -0
  154. {metalist-0.7.3 → metalist-0.7.4}/app/services/integrity.py +0 -0
  155. {metalist-0.7.3 → metalist-0.7.4}/app/services/latex_rendering.py +0 -0
  156. {metalist-0.7.3 → metalist-0.7.4}/app/services/link_titles.py +0 -0
  157. {metalist-0.7.3 → metalist-0.7.4}/app/services/login_rate_limit.py +0 -0
  158. {metalist-0.7.3 → metalist-0.7.4}/app/services/maintenance_mode.py +0 -0
  159. {metalist-0.7.3 → metalist-0.7.4}/app/services/markdown_rendering.py +0 -0
  160. {metalist-0.7.3 → metalist-0.7.4}/app/services/namespace_deletion_jobs.py +0 -0
  161. {metalist-0.7.3 → metalist-0.7.4}/app/services/namespace_deletion_worker.py +0 -0
  162. {metalist-0.7.3 → metalist-0.7.4}/app/services/namespace_rename_jobs.py +0 -0
  163. {metalist-0.7.3 → metalist-0.7.4}/app/services/namespace_rename_worker.py +0 -0
  164. {metalist-0.7.3 → metalist-0.7.4}/app/services/namespace_runtime_guard.py +0 -0
  165. {metalist-0.7.3 → metalist-0.7.4}/app/services/namespace_switcher.py +0 -0
  166. {metalist-0.7.3 → metalist-0.7.4}/app/services/note_fullscreen.py +0 -0
  167. {metalist-0.7.3 → metalist-0.7.4}/app/services/note_image_tags.py +0 -0
  168. {metalist-0.7.3 → metalist-0.7.4}/app/services/note_ordering.py +0 -0
  169. {metalist-0.7.3 → metalist-0.7.4}/app/services/note_store.py +0 -0
  170. {metalist-0.7.3 → metalist-0.7.4}/app/services/ontology_rules_store.py +0 -0
  171. {metalist-0.7.3 → metalist-0.7.4}/app/services/openai_credentials.py +0 -0
  172. {metalist-0.7.3 → metalist-0.7.4}/app/services/password_note_fields.py +0 -0
  173. {metalist-0.7.3 → metalist-0.7.4}/app/services/reference_presentation.py +0 -0
  174. {metalist-0.7.3 → metalist-0.7.4}/app/services/reminders.py +0 -0
  175. {metalist-0.7.3 → metalist-0.7.4}/app/services/remote_image_proxy.py +0 -0
  176. {metalist-0.7.3 → metalist-0.7.4}/app/services/request_recovery.py +0 -0
  177. {metalist-0.7.3 → metalist-0.7.4}/app/services/resource_limits.py +0 -0
  178. {metalist-0.7.3 → metalist-0.7.4}/app/services/root_sorting.py +0 -0
  179. {metalist-0.7.3 → metalist-0.7.4}/app/services/runtime_generation.py +0 -0
  180. {metalist-0.7.3 → metalist-0.7.4}/app/services/runtime_hardening.py +0 -0
  181. {metalist-0.7.3 → metalist-0.7.4}/app/services/runtime_lock.py +0 -0
  182. {metalist-0.7.3 → metalist-0.7.4}/app/services/search_history.py +0 -0
  183. {metalist-0.7.3 → metalist-0.7.4}/app/services/search_history_storage.py +0 -0
  184. {metalist-0.7.3 → metalist-0.7.4}/app/services/search_index.py +0 -0
  185. {metalist-0.7.3 → metalist-0.7.4}/app/services/search_query.py +0 -0
  186. {metalist-0.7.3 → metalist-0.7.4}/app/services/search_text.py +0 -0
  187. {metalist-0.7.3 → metalist-0.7.4}/app/services/selected_text_tag.py +0 -0
  188. {metalist-0.7.3 → metalist-0.7.4}/app/services/session_timeout_service.py +0 -0
  189. {metalist-0.7.3 → metalist-0.7.4}/app/services/shell_session_service.py +0 -0
  190. {metalist-0.7.3 → metalist-0.7.4}/app/services/snapshot.py +0 -0
  191. {metalist-0.7.3 → metalist-0.7.4}/app/services/store.py +0 -0
  192. {metalist-0.7.3 → metalist-0.7.4}/app/services/structured_note_renderers.py +0 -0
  193. {metalist-0.7.3 → metalist-0.7.4}/app/services/sync.py +0 -0
  194. {metalist-0.7.3 → metalist-0.7.4}/app/services/sync_state.py +0 -0
  195. {metalist-0.7.3 → metalist-0.7.4}/app/services/tab_state.py +0 -0
  196. {metalist-0.7.3 → metalist-0.7.4}/app/services/tag_case.py +0 -0
  197. {metalist-0.7.3 → metalist-0.7.4}/app/services/tag_ontology.py +0 -0
  198. {metalist-0.7.3 → metalist-0.7.4}/app/services/tag_rename.py +0 -0
  199. {metalist-0.7.3 → metalist-0.7.4}/app/services/tag_suggestions.py +0 -0
  200. {metalist-0.7.3 → metalist-0.7.4}/app/services/tag_term_matching.py +0 -0
  201. {metalist-0.7.3 → metalist-0.7.4}/app/services/test_reset.py +0 -0
  202. {metalist-0.7.3 → metalist-0.7.4}/app/services/tokens.py +0 -0
  203. {metalist-0.7.3 → metalist-0.7.4}/app/services/undo_state.py +0 -0
  204. {metalist-0.7.3 → metalist-0.7.4}/app/services/update_backups.py +0 -0
  205. {metalist-0.7.3 → metalist-0.7.4}/app/services/view_cache.py +0 -0
  206. {metalist-0.7.3 → metalist-0.7.4}/app/services/view_diff.py +0 -0
  207. {metalist-0.7.3 → metalist-0.7.4}/app/services/view_state.py +0 -0
  208. {metalist-0.7.3 → metalist-0.7.4}/app/services/windows_process_control.py +0 -0
  209. {metalist-0.7.3 → metalist-0.7.4}/app/startup_environment.py +0 -0
  210. {metalist-0.7.3 → metalist-0.7.4}/app/startup_js_sanity.py +0 -0
  211. {metalist-0.7.3 → metalist-0.7.4}/app/startup_sanity.py +0 -0
  212. {metalist-0.7.3 → metalist-0.7.4}/app/startup_sanity_config.py +0 -0
  213. {metalist-0.7.3 → metalist-0.7.4}/app/static/config/agent-menu-actions.json +0 -0
  214. {metalist-0.7.3 → metalist-0.7.4}/app/static/config/command_palette_tags.json +0 -0
  215. {metalist-0.7.3 → metalist-0.7.4}/app/static/css/floating-notes.css +0 -0
  216. {metalist-0.7.3 → metalist-0.7.4}/app/static/css/forms.css +0 -0
  217. {metalist-0.7.3 → metalist-0.7.4}/app/static/css/main.css +0 -0
  218. {metalist-0.7.3 → metalist-0.7.4}/app/static/img/favicon.ico +0 -0
  219. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/locked.js +0 -0
  220. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/main.js +0 -0
  221. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/activity-tracker.js +0 -0
  222. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/ai-chat/agent-menu-actions.js +0 -0
  223. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/ai-chat/agent-prompt-service.js +0 -0
  224. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/ai-chat/agent-retrieval-settings.js +0 -0
  225. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/ai-chat/ai-agent-debug-view.js +0 -0
  226. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/ai-chat/ai-chat-api.js +0 -0
  227. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/ai-chat/ai-chat-panel-controller.js +0 -0
  228. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/ai-chat/ai-chat-panel-service.js +0 -0
  229. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/ai-chat/ai-thinking-level-service.js +0 -0
  230. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/ai-chat/bulk-elapsed-clock.js +0 -0
  231. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/ai-chat/bulk-proposal-ui.js +0 -0
  232. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/ai-chat/cloud-privacy-policy.js +0 -0
  233. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/ai-chat/proposal-menu.js +0 -0
  234. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/api-client.js +0 -0
  235. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/api-failure-classification-service.js +0 -0
  236. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/app-update-service.js +0 -0
  237. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/application-state.js +0 -0
  238. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/async-result.js +0 -0
  239. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/auth.js +0 -0
  240. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/client-state-api.js +0 -0
  241. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/client-state-migration.js +0 -0
  242. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/command-palette/activation-auth-policy.js +0 -0
  243. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/command-palette/backup-command-availability.js +0 -0
  244. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/command-palette/click-activation-service.js +0 -0
  245. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/command-palette/command-palette-controller.js +0 -0
  246. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/command-palette/endpoint-registry.js +0 -0
  247. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/command-palette/note-layout-preferences.js +0 -0
  248. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/command-palette/preferences-store.js +0 -0
  249. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/command-palette/tag-config-loader.js +0 -0
  250. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/command-palette/usage-store.js +0 -0
  251. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/config.js +0 -0
  252. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/connectivity-monitor.js +0 -0
  253. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/context-menu/context-menu-registry.js +0 -0
  254. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/context-menu/context-menu-service.js +0 -0
  255. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/context-menu/context-menu-target-service.js +0 -0
  256. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/context-menu/input-caret-service.js +0 -0
  257. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/disconnect-editing-state-service.js +0 -0
  258. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/dom-utils-fixed.js +0 -0
  259. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/dom-utils.js +0 -0
  260. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/editor-commands.js +0 -0
  261. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/editor-selection.js +0 -0
  262. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/editor-toolbar.js +0 -0
  263. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/elapsed-time.js +0 -0
  264. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/error-handler.js +0 -0
  265. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/error-overlay.js +0 -0
  266. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/expected-errors.js +0 -0
  267. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/location-flags.js +0 -0
  268. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/login-namespace-picker.js +0 -0
  269. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/maintenance.js +0 -0
  270. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/modals/agent-prompt-editor-modal.js +0 -0
  271. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/modals/ai-agent-settings-modal.js +0 -0
  272. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/modals/alphabetize-root-notes-modal.js +0 -0
  273. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/modals/backup-restore-modal.js +0 -0
  274. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/modals/backup-result-modal.js +0 -0
  275. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/modals/backup-retention-modal.js +0 -0
  276. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/modals/backup-settings-modal.js +0 -0
  277. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/modals/base-modal.js +0 -0
  278. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/modals/confirmation-modal.js +0 -0
  279. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/modals/delete-namespace-modal.js +0 -0
  280. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/modals/delete-namespace-validation.js +0 -0
  281. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/modals/help-modal.js +0 -0
  282. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/modals/namespace-loading-page.js +0 -0
  283. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/modals/namespace-modals.js +0 -0
  284. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/modals/namespace-ports-profile.js +0 -0
  285. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/modals/namespace-rename-validation.js +0 -0
  286. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/modals/note-layout-appearance-modal.js +0 -0
  287. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/modals/ontology-modal.js +0 -0
  288. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/modals/password-modal.js +0 -0
  289. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/modals/prioritize-modal.js +0 -0
  290. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/modals/random-password-modal.js +0 -0
  291. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/modals/reminder-modal.js +0 -0
  292. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/modals/reset-updated-at-modal.js +0 -0
  293. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/modals/search-suggestion-statistics-modal.js +0 -0
  294. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/modals/session-timeout-modal.js +0 -0
  295. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/modals/version-info-modal.js +0 -0
  296. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/actions/content-actions.js +0 -0
  297. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/actions/history-actions.js +0 -0
  298. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/actions/note-actions.js +0 -0
  299. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/actions/search-actions.js +0 -0
  300. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/actions/selection-actions.js +0 -0
  301. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/actions/ui-actions.js +0 -0
  302. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/events/context-menu-events.js +0 -0
  303. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/events/focus-events.js +0 -0
  304. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/events/inactivity-events.js +0 -0
  305. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/events/input-events.js +0 -0
  306. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/events/keyboard-events.js +0 -0
  307. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/events/mouse-events.js +0 -0
  308. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/events/search-events.js +0 -0
  309. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/mode-context.js +0 -0
  310. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/mode-logger.js +0 -0
  311. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/mode-manager-controller.js +0 -0
  312. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/add-style-service.js +0 -0
  313. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/animated-scroll-service.js +0 -0
  314. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/backlinks-navigation-service.js +0 -0
  315. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/backlinks-panel-service.js +0 -0
  316. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/clipboard-shortcut-policy-service.js +0 -0
  317. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/collapse-affordance-service.js +0 -0
  318. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/collapse-editing-policy-service.js +0 -0
  319. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/command-gate-service.js +0 -0
  320. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/context-menu-target-service.js +0 -0
  321. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/deselect-selection-state-service.js +0 -0
  322. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/differential-view-service.js +0 -0
  323. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/edit-session-collapse-policy-service.js +0 -0
  324. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/edit-session-collapse-service.js +0 -0
  325. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/embedded-image-service.js +0 -0
  326. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/file-drop-policy-service.js +0 -0
  327. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/file-image-preview-service.js +0 -0
  328. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/file-reference-service.js +0 -0
  329. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/filtered-refresh-selection-service.js +0 -0
  330. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/floating-note-dom.js +0 -0
  331. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/floating-note-layout.js +0 -0
  332. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/floating-note-service.js +0 -0
  333. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/footnote-navigation-service.js +0 -0
  334. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/history-selection-policy-service.js +0 -0
  335. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/history-shortcut-policy-service.js +0 -0
  336. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/html-paste-sanitizer-service.js +0 -0
  337. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/image-context-menu-action-service.js +0 -0
  338. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/image-file-insert-choice-modal-service.js +0 -0
  339. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/infinite-scroll-service.js +0 -0
  340. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/link-context-menu-action-service.js +0 -0
  341. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/link-title-prefetch-service.js +0 -0
  342. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/markdown-render-service.js +0 -0
  343. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/mermaid-render-service.js +0 -0
  344. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/note-click-target-service.js +0 -0
  345. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/note-clipboard-write-service.js +0 -0
  346. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/note-collapse-animation-service.js +0 -0
  347. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/note-context-menu-action-service.js +0 -0
  348. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/note-delete-shortcut-policy-service.js +0 -0
  349. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/note-drag-service.js +0 -0
  350. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/note-fullscreen-service.js +0 -0
  351. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/note-reposition-animation-service.js +0 -0
  352. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/note-split-service.js +0 -0
  353. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/note-timestamp-hover-service.js +0 -0
  354. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/password-clipboard-service.js +0 -0
  355. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/polling-service.js +0 -0
  356. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/reference-source-navigation-service.js +0 -0
  357. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/remote-image-proxy-service.js +0 -0
  358. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/remove-formatting-service.js +0 -0
  359. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/root-date-separator-service.js +0 -0
  360. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/root-sort-indicator-service.js +0 -0
  361. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/root-sort-service.js +0 -0
  362. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/scroll-anchor-service.js +0 -0
  363. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/scroll-restoration-service.js +0 -0
  364. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/scroll-to-top-service.js +0 -0
  365. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/search-contexts-overlay-service.js +0 -0
  366. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/search-debounce-service.js +0 -0
  367. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/search-input-service.js +0 -0
  368. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/search-interaction-service.js +0 -0
  369. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/search-redaction-reveal-service.js +0 -0
  370. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/search-suggestion-statistics-service.js +0 -0
  371. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/search-suggestion-window-labels-service.js +0 -0
  372. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/search-suggestion-windows-service.js +0 -0
  373. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/search-suggestions-service.js +0 -0
  374. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/search-syntax-service.js +0 -0
  375. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/selected-formatting-removal-service.js +0 -0
  376. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/selected-text-tag-service.js +0 -0
  377. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/shell-output-service.js +0 -0
  378. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/tab-dom-cache-service.js +0 -0
  379. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/tab-drag-service.js +0 -0
  380. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/tab-duplication-service.js +0 -0
  381. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/tab-state-service.js +0 -0
  382. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/tag-bar-service.js +0 -0
  383. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/tag-input-selection-service.js +0 -0
  384. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/tag-proposal-service.js +0 -0
  385. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/tag-suggestions-service.js +0 -0
  386. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/tag-syntax-service.js +0 -0
  387. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/todo-toggle-editing-service.js +0 -0
  388. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/untagged-view-indicator-service.js +0 -0
  389. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/mode-manager/services/view-mode-search-shortcut-service.js +0 -0
  390. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/note-html-sanitizer.js +0 -0
  391. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/password-generator.js +0 -0
  392. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/password-operation-response.js +0 -0
  393. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/password-policy.js +0 -0
  394. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/password-strength.js +0 -0
  395. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/reminder-store.js +0 -0
  396. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/reminder-surface-service.js +0 -0
  397. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/selection-markers.js +0 -0
  398. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/session-auth.js +0 -0
  399. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/tag-token.js +0 -0
  400. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/modules/uuid.js +0 -0
  401. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/namespace-deleted.js +0 -0
  402. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/namespace-renamed.js +0 -0
  403. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/vendor/dompurify-3.4.13.LICENSE.txt +0 -0
  404. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/vendor/dompurify-3.4.13.min.js +0 -0
  405. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/vendor/markdown-it-14.3.2.LICENSE.txt +0 -0
  406. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/vendor/markdown-it-14.3.2.min.js +0 -0
  407. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/vendor/mermaid-11.16.1.LICENSE.txt +0 -0
  408. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/vendor/mermaid-11.16.1.min.js +0 -0
  409. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/vendor/zxcvbn-4.4.2.LICENSE.txt +0 -0
  410. {metalist-0.7.3 → metalist-0.7.4}/app/static/js/vendor/zxcvbn-4.4.2.js +0 -0
  411. {metalist-0.7.3 → metalist-0.7.4}/app/static/note-html-policy.json +0 -0
  412. {metalist-0.7.3 → metalist-0.7.4}/app/static/video/login-startup.mp4 +0 -0
  413. {metalist-0.7.3 → metalist-0.7.4}/app/templates/base.html +0 -0
  414. {metalist-0.7.3 → metalist-0.7.4}/app/templates/index.html +0 -0
  415. {metalist-0.7.3 → metalist-0.7.4}/app/templates/locked.html +0 -0
  416. {metalist-0.7.3 → metalist-0.7.4}/app/templates/maintenance.html +0 -0
  417. {metalist-0.7.3 → metalist-0.7.4}/app/templates/namespace_deleted.html +0 -0
  418. {metalist-0.7.3 → metalist-0.7.4}/app/templates/namespace_renamed.html +0 -0
  419. {metalist-0.7.3 → metalist-0.7.4}/app/templates/notes_list.html +0 -0
  420. {metalist-0.7.3 → metalist-0.7.4}/app/upload_limits.py +0 -0
  421. {metalist-0.7.3 → metalist-0.7.4}/app/usecases/__init__.py +0 -0
  422. {metalist-0.7.3 → metalist-0.7.4}/app/usecases/add_selected_text_tag.py +0 -0
  423. {metalist-0.7.3 → metalist-0.7.4}/app/usecases/alphabetize_root_notes.py +0 -0
  424. {metalist-0.7.3 → metalist-0.7.4}/app/usecases/base.py +0 -0
  425. {metalist-0.7.3 → metalist-0.7.4}/app/usecases/bulk_tag_proposals.py +0 -0
  426. {metalist-0.7.3 → metalist-0.7.4}/app/usecases/collapse.py +0 -0
  427. {metalist-0.7.3 → metalist-0.7.4}/app/usecases/copy_note.py +0 -0
  428. {metalist-0.7.3 → metalist-0.7.4}/app/usecases/create_child.py +0 -0
  429. {metalist-0.7.3 → metalist-0.7.4}/app/usecases/create_note.py +0 -0
  430. {metalist-0.7.3 → metalist-0.7.4}/app/usecases/create_sibling.py +0 -0
  431. {metalist-0.7.3 → metalist-0.7.4}/app/usecases/delete_subtree.py +0 -0
  432. {metalist-0.7.3 → metalist-0.7.4}/app/usecases/delete_tag.py +0 -0
  433. {metalist-0.7.3 → metalist-0.7.4}/app/usecases/expand.py +0 -0
  434. {metalist-0.7.3 → metalist-0.7.4}/app/usecases/indent.py +0 -0
  435. {metalist-0.7.3 → metalist-0.7.4}/app/usecases/lock.py +0 -0
  436. {metalist-0.7.3 → metalist-0.7.4}/app/usecases/move.py +0 -0
  437. {metalist-0.7.3 → metalist-0.7.4}/app/usecases/move_to_top.py +0 -0
  438. {metalist-0.7.3 → metalist-0.7.4}/app/usecases/outdent.py +0 -0
  439. {metalist-0.7.3 → metalist-0.7.4}/app/usecases/paste_child.py +0 -0
  440. {metalist-0.7.3 → metalist-0.7.4}/app/usecases/paste_sibling.py +0 -0
  441. {metalist-0.7.3 → metalist-0.7.4}/app/usecases/prefetch_link_titles.py +0 -0
  442. {metalist-0.7.3 → metalist-0.7.4}/app/usecases/prioritize.py +0 -0
  443. {metalist-0.7.3 → metalist-0.7.4}/app/usecases/redo.py +0 -0
  444. {metalist-0.7.3 → metalist-0.7.4}/app/usecases/rename_tag.py +0 -0
  445. {metalist-0.7.3 → metalist-0.7.4}/app/usecases/reset_updated_at.py +0 -0
  446. {metalist-0.7.3 → metalist-0.7.4}/app/usecases/resize_image.py +0 -0
  447. {metalist-0.7.3 → metalist-0.7.4}/app/usecases/run_shell.py +0 -0
  448. {metalist-0.7.3 → metalist-0.7.4}/app/usecases/search_comment_autofill.py +0 -0
  449. {metalist-0.7.3 → metalist-0.7.4}/app/usecases/search_context_tags.py +0 -0
  450. {metalist-0.7.3 → metalist-0.7.4}/app/usecases/set_collapse_bulk.py +0 -0
  451. {metalist-0.7.3 → metalist-0.7.4}/app/usecases/set_collapse_in_context.py +0 -0
  452. {metalist-0.7.3 → metalist-0.7.4}/app/usecases/split_note.py +0 -0
  453. {metalist-0.7.3 → metalist-0.7.4}/app/usecases/tag_proposals.py +0 -0
  454. {metalist-0.7.3 → metalist-0.7.4}/app/usecases/toggle_reference_mode.py +0 -0
  455. {metalist-0.7.3 → metalist-0.7.4}/app/usecases/toggle_todo_done.py +0 -0
  456. {metalist-0.7.3 → metalist-0.7.4}/app/usecases/undo.py +0 -0
  457. {metalist-0.7.3 → metalist-0.7.4}/app/usecases/unformat_content.py +0 -0
  458. {metalist-0.7.3 → metalist-0.7.4}/app/usecases/update_content.py +0 -0
  459. {metalist-0.7.3 → metalist-0.7.4}/app/usecases/view.py +0 -0
  460. {metalist-0.7.3 → metalist-0.7.4}/app/utils/__init__.py +0 -0
  461. {metalist-0.7.3 → metalist-0.7.4}/app/utils/encryption.py +0 -0
  462. {metalist-0.7.3 → metalist-0.7.4}/app/utils/text_utils.py +0 -0
  463. {metalist-0.7.3 → metalist-0.7.4}/convert-from-legacy.py +0 -0
  464. {metalist-0.7.3 → metalist-0.7.4}/main.py +0 -0
  465. {metalist-0.7.3 → metalist-0.7.4}/metalist.egg-info/SOURCES.txt +0 -0
  466. {metalist-0.7.3 → metalist-0.7.4}/metalist.egg-info/dependency_links.txt +0 -0
  467. {metalist-0.7.3 → metalist-0.7.4}/metalist.egg-info/entry_points.txt +0 -0
  468. {metalist-0.7.3 → metalist-0.7.4}/metalist.egg-info/requires.txt +0 -0
  469. {metalist-0.7.3 → metalist-0.7.4}/metalist.egg-info/top_level.txt +0 -0
  470. {metalist-0.7.3 → metalist-0.7.4}/pyproject.toml +0 -0
  471. {metalist-0.7.3 → metalist-0.7.4}/scripts/generate-lan-cert.sh +0 -0
  472. {metalist-0.7.3 → metalist-0.7.4}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: metalist
3
- Version: 0.7.3
3
+ Version: 0.7.4
4
4
  Summary: A minimalist single-user note-taking app with SSR, fast in-memory tree operations, and efficient sync.
5
5
  Project-URL: Homepage, https://github.com/evolvingstuff/metalist
6
6
  Project-URL: Repository, https://github.com/evolvingstuff/metalist
@@ -48,6 +48,12 @@ A minimalist single-user note-taking app focused on server-side rendering (SSR),
48
48
  - Multi-tab search contexts with server-persisted scroll/search state (survives browser restarts)
49
49
  - Manual namespace backups/restores to a user-selected backup folder with retention controls
50
50
 
51
+ ## Changes in 0.7.4
52
+
53
+ - Updates use a private, checksum-verified uv release on Windows, macOS, and Linux. The updater does not execute a user-installed uv, and it revalidates both the cached official archive and extracted executable before each use.
54
+ - The HTTPS listener retries one bodyless safe request after a transient backend reset, records final transport failures server-side, and never replays a mutation or request body.
55
+ - Release CI builds one distribution pair, starts independent platform/Python, installed-update, browser-smoke, and browser-soak gates in parallel, and caches only hash- or lockfile-verified dependencies. Cross-platform runtime changes must pass branch CI before merge.
56
+
51
57
  ## Changes in 0.7.3
52
58
 
53
59
  - Windows updates use a private verified uv release when an older installer is vulnerable to the reported PE-resource access-denied failure. A standalone repair ZIP can bootstrap installations whose existing updater cannot update itself.
@@ -152,7 +158,7 @@ metalist update
152
158
  ```
153
159
  The updater checks the installed version against the latest PyPI release first. If MetaList is already current, it reports the installed version and leaves all running namespaces untouched. When an update is available, it checks installer prerequisites and uses uv to install the candidate into a disposable tool environment with the current base Python interpreter. It checks dependencies and starts a temporary namespace to verify HTTP readiness, version, and runtime assets. A failed preflight leaves the current installation and running namespaces unchanged. After preflight succeeds, it stops running namespaces, and creates and verifies a new backup of every namespace before installation can begin. Each archive includes the complete notes/settings database, the attachments database when present, and any legacy search-history database. Locked namespaces are backed up with their encrypted data and key metadata intact, without requiring a password.
154
160
 
155
- On Windows, the updater checks uv before installing packages. Versions older than 0.12.13 use a temporary PE-resource editing operation that can fail with `uv-trampoline.exe: Access is denied`. This checkout selects a private, checksum-verified uv 0.12.17 for those installations, keeping the same installer through preflight and final installation. It does not replace global uv. Already-installed MetaList releases retain their own updater code; the standalone repair launcher described in [recovery](docs/security/recovery.md#windows-updater-pe-resource-failure) supplies the compatible installer to that existing updater.
161
+ MetaList downloads its own checksum-verified uv 0.12.17 archive for the current operating system, architecture, and Linux C library. The verified archive and extracted executable are stored in the operating system's user cache; every update verifies the archive against its pinned upstream SHA-256 and the executable against the verified archive before use. That same executable performs both preflight and final installation. MetaList does not execute or replace the user's global uv. Download, verification, platform-selection, or version failures occur before any namespace is stopped. Already-installed releases retain their own updater code; the standalone repair launcher described in [recovery](docs/security/recovery.md#windows-updater-pe-resource-failure) supplies this managed installer to an older Windows updater.
156
162
 
157
163
  Backups are saved to `~/MetaList/namespaces/<namespace>/backups/<namespace>-<timestamp>.metalist-backup.tar.gz`; the updater prints each verified path. Existing backups remain unchanged and are not pruned. If any backup fails, the update aborts with the current installation intact; run `metalist` to restart the stopped servers after resolving the failure.
158
164
 
@@ -12,6 +12,12 @@ A minimalist single-user note-taking app focused on server-side rendering (SSR),
12
12
  - Multi-tab search contexts with server-persisted scroll/search state (survives browser restarts)
13
13
  - Manual namespace backups/restores to a user-selected backup folder with retention controls
14
14
 
15
+ ## Changes in 0.7.4
16
+
17
+ - Updates use a private, checksum-verified uv release on Windows, macOS, and Linux. The updater does not execute a user-installed uv, and it revalidates both the cached official archive and extracted executable before each use.
18
+ - The HTTPS listener retries one bodyless safe request after a transient backend reset, records final transport failures server-side, and never replays a mutation or request body.
19
+ - Release CI builds one distribution pair, starts independent platform/Python, installed-update, browser-smoke, and browser-soak gates in parallel, and caches only hash- or lockfile-verified dependencies. Cross-platform runtime changes must pass branch CI before merge.
20
+
15
21
  ## Changes in 0.7.3
16
22
 
17
23
  - Windows updates use a private verified uv release when an older installer is vulnerable to the reported PE-resource access-denied failure. A standalone repair ZIP can bootstrap installations whose existing updater cannot update itself.
@@ -116,7 +122,7 @@ metalist update
116
122
  ```
117
123
  The updater checks the installed version against the latest PyPI release first. If MetaList is already current, it reports the installed version and leaves all running namespaces untouched. When an update is available, it checks installer prerequisites and uses uv to install the candidate into a disposable tool environment with the current base Python interpreter. It checks dependencies and starts a temporary namespace to verify HTTP readiness, version, and runtime assets. A failed preflight leaves the current installation and running namespaces unchanged. After preflight succeeds, it stops running namespaces, and creates and verifies a new backup of every namespace before installation can begin. Each archive includes the complete notes/settings database, the attachments database when present, and any legacy search-history database. Locked namespaces are backed up with their encrypted data and key metadata intact, without requiring a password.
118
124
 
119
- On Windows, the updater checks uv before installing packages. Versions older than 0.12.13 use a temporary PE-resource editing operation that can fail with `uv-trampoline.exe: Access is denied`. This checkout selects a private, checksum-verified uv 0.12.17 for those installations, keeping the same installer through preflight and final installation. It does not replace global uv. Already-installed MetaList releases retain their own updater code; the standalone repair launcher described in [recovery](docs/security/recovery.md#windows-updater-pe-resource-failure) supplies the compatible installer to that existing updater.
125
+ MetaList downloads its own checksum-verified uv 0.12.17 archive for the current operating system, architecture, and Linux C library. The verified archive and extracted executable are stored in the operating system's user cache; every update verifies the archive against its pinned upstream SHA-256 and the executable against the verified archive before use. That same executable performs both preflight and final installation. MetaList does not execute or replace the user's global uv. Download, verification, platform-selection, or version failures occur before any namespace is stopped. Already-installed releases retain their own updater code; the standalone repair launcher described in [recovery](docs/security/recovery.md#windows-updater-pe-resource-failure) supplies this managed installer to an older Windows updater.
120
126
 
121
127
  Backups are saved to `~/MetaList/namespaces/<namespace>/backups/<namespace>-<timestamp>.metalist-backup.tar.gz`; the updater prints each verified path. Existing backups remain unchanged and are not pruned. If any backup fails, the update aborts with the current installation intact; run `metalist` to restart the stopped servers after resolving the failure.
122
128
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  import http.client
4
4
  from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
5
+ import logging
5
6
  from threading import BoundedSemaphore
6
7
  import time
7
8
  from app.upload_limits import MAX_UPLOAD_REQUEST_BYTES
@@ -12,6 +13,8 @@ IDLE_TIMEOUT_SECONDS = 60
12
13
  MAX_REQUEST_SECONDS = 30 * 60
13
14
  HOP_HEADERS = frozenset({'connection', 'keep-alive', 'proxy-authenticate', 'proxy-authorization',
14
15
  'te', 'trailer', 'trailers', 'transfer-encoding', 'upgrade'})
16
+ RETRYABLE_METHODS = frozenset({'GET', 'HEAD', 'OPTIONS'})
17
+ LOGGER = logging.getLogger(__name__)
15
18
 
16
19
 
17
20
  class BoundedProxyServer(ThreadingHTTPServer):
@@ -48,6 +51,39 @@ def make_proxy_handler(*, backend_host: str, backend_port: int, forward_headers)
48
51
  class ProxyHandler(BaseHTTPRequestHandler):
49
52
  protocol_version = 'HTTP/1.1'
50
53
 
54
+ def _request_upstream(self, *, headers, content_length: int, deadline: float):
55
+ attempts = 1
56
+ if self.command in RETRYABLE_METHODS and content_length == 0:
57
+ attempts = 2
58
+ for attempt in range(attempts):
59
+ connection = http.client.HTTPConnection(
60
+ backend_host, backend_port, timeout=IDLE_TIMEOUT_SECONDS,
61
+ )
62
+ # lint: allow-PY001 rationale="retry a bodyless safe request after an expected transient upstream transport failure"
63
+ try:
64
+ connection.putrequest(
65
+ self.command, self.path, skip_host=True, skip_accept_encoding=True,
66
+ )
67
+ for key, value in headers.items():
68
+ connection.putheader(key, value)
69
+ connection.endheaders()
70
+ remaining = content_length
71
+ while remaining:
72
+ if time.monotonic() >= deadline:
73
+ raise TimeoutError('Proxy request deadline exceeded')
74
+ chunk = self.rfile.read(min(CHUNK_BYTES, remaining))
75
+ if not chunk:
76
+ raise ConnectionError('Incomplete request body')
77
+ connection.send(chunk)
78
+ remaining -= len(chunk)
79
+ return connection, connection.getresponse()
80
+ # lint: allow-PY001 rationale="retry once, then re-raise the expected upstream transport failure"
81
+ except (OSError, http.client.HTTPException):
82
+ connection.close()
83
+ if attempt + 1 == attempts:
84
+ raise
85
+ raise AssertionError('Upstream request attempts were not exhausted')
86
+
51
87
  def _proxy(self):
52
88
  # Preserve the browser's HTTP/1.1 connection across module requests.
53
89
  # Chunked response framing and the socket timeout bound each transfer.
@@ -78,24 +114,24 @@ def make_proxy_handler(*, backend_host: str, backend_port: int, forward_headers)
78
114
  headers = forward_headers(incoming_headers=self.headers.items(), client_ip=self.client_address[0])
79
115
  headers = {key: value for key, value in headers.items() if key.casefold() not in connection_tokens | HOP_HEADERS}
80
116
  headers['Connection'] = 'close'
81
- connection = http.client.HTTPConnection(backend_host, backend_port, timeout=IDLE_TIMEOUT_SECONDS)
82
117
  deadline = time.monotonic() + MAX_REQUEST_SECONDS
118
+ # lint: allow-PY001 rationale="translate the final external upstream transport failure into a sanitized gateway response"
119
+ try:
120
+ connection, response = self._request_upstream(
121
+ headers=headers, content_length=remaining, deadline=deadline,
122
+ )
123
+ # lint: allow-PY001 rationale="return a sanitized gateway error after retrying an expected upstream transport failure"
124
+ except (OSError, http.client.HTTPException) as error:
125
+ self.close_connection = True
126
+ LOGGER.error(
127
+ 'HTTPS proxy upstream transport failed method=%s backend=%s:%s error=%s',
128
+ self.command, backend_host, backend_port, type(error).__name__,
129
+ )
130
+ self.send_error(502, 'Upstream transport failed')
131
+ return
83
132
  response_started = False
84
133
  # lint: allow-PY001 rationale="close upstream on client disconnect or expected transport failure without disclosing exception details"
85
134
  try:
86
- connection.putrequest(self.command, self.path, skip_host=True, skip_accept_encoding=True)
87
- for key, value in headers.items():
88
- connection.putheader(key, value)
89
- connection.endheaders()
90
- while remaining:
91
- if time.monotonic() >= deadline:
92
- raise TimeoutError('Proxy request deadline exceeded')
93
- chunk = self.rfile.read(min(CHUNK_BYTES, remaining))
94
- if not chunk:
95
- raise ConnectionError('Incomplete request body')
96
- connection.send(chunk)
97
- remaining -= len(chunk)
98
- response = connection.getresponse()
99
135
  self.send_response(response.status, response.reason)
100
136
  response_tokens = {part.strip().casefold() for value in response.headers.get_all('Connection', []) for part in value.split(',')}
101
137
  for key, value in response.getheaders():
@@ -125,9 +161,13 @@ def make_proxy_handler(*, backend_host: str, backend_port: int, forward_headers)
125
161
  self.wfile.write(b'0\r\n\r\n')
126
162
  self.wfile.flush()
127
163
  # lint: allow-PY001 rationale="terminate a disconnected or failed external HTTP transport; emit only a sanitized upstream error"
128
- except (OSError, http.client.HTTPException):
164
+ except (OSError, http.client.HTTPException) as error:
129
165
  # A partial request/response cannot be reused for another request.
130
166
  self.close_connection = True
167
+ LOGGER.error(
168
+ 'HTTPS proxy response transport failed method=%s backend=%s:%s error=%s',
169
+ self.command, backend_host, backend_port, type(error).__name__,
170
+ )
131
171
  if not response_started:
132
172
  self.send_error(502, 'Upstream transport failed')
133
173
  finally:
@@ -76,17 +76,11 @@ def schedule_self_update(
76
76
  message=message,
77
77
  )
78
78
 
79
- uv_executable = shutil.which("uv")
80
- if uv_executable is None:
81
- raise RuntimeError("uv executable was not found on PATH; MetaList was not stopped")
82
-
83
79
  if platform_name == "win32":
84
80
  _resolve_windows_powershell()
85
81
  elif not Path("/bin/sh").is_file():
86
82
  raise RuntimeError("/bin/sh is required for MetaList self-update; MetaList was not stopped")
87
- install_command = _prepare_update(
88
- uv_executable=uv_executable, target_version=target_version, environ=environ,
89
- )
83
+ install_command = _prepare_update(target_version=target_version, environ=environ)
90
84
  updater_command: list[str]
91
85
  updater_options: dict[str, object]
92
86
  if platform_name == "win32":
@@ -0,0 +1,260 @@
1
+ """Provide MetaList's checksum-pinned updater runtime on every supported OS."""
2
+ from __future__ import annotations
3
+
4
+ from collections.abc import Mapping
5
+ import hashlib
6
+ import io
7
+ import os
8
+ from pathlib import Path
9
+ import platform
10
+ import re
11
+ import shutil
12
+ import subprocess
13
+ import sys
14
+ import tarfile
15
+ from tempfile import NamedTemporaryFile
16
+ from urllib.request import urlopen
17
+ import zipfile
18
+
19
+
20
+ # Official immutable uv 0.12.17 release archives. These values match the
21
+ # upstream sha256.sum asset for the same release.
22
+ INSTALLER_VERSION = "0.12.17"
23
+ INSTALLER_ARCHIVE_SHA256 = {
24
+ "aarch64-apple-darwin": "85f00cbdc6dd3e97eba4c31b4d014375a9fdfe8f570023b84e5102fc3456896b",
25
+ "aarch64-pc-windows-msvc": "3e1aa6849d77f0e00dc865e4afab5c5b32de053e21fe35bf5ad5cec3734ec976",
26
+ "aarch64-unknown-linux-gnu": "d636d1b678e9e7f367ecb22b46bd1cabbed234d6bc3b4d96365d2b507f72f86c",
27
+ "aarch64-unknown-linux-musl": "a6096da273d548cb9f277d237a01ac7344a39ef0f455c0e148e4dc9737c1596b",
28
+ "armv7-unknown-linux-gnueabihf": "796e101976e18a0f92d90b6f3efd289f77fbc5afd1aaa6fdedd3c84c209eabab",
29
+ "armv7-unknown-linux-musleabihf": "421c5f9c53d49088e705e7a64fea147082a2191178ea1d8c51d9ad758ca899f6",
30
+ "i686-pc-windows-msvc": "1d3653cb6eafd1e675e979d7cd8eeac1456202f8927a2216419993077a4c473f",
31
+ "i686-unknown-linux-gnu": "3faa79a70e2a1aa6eb3cd78eba02263f3e4b17b6be584a01429968f92ff74966",
32
+ "i686-unknown-linux-musl": "fc05220cfa1c6585e0e209877c228393b25a96e17cd43028b06566ac894cd078",
33
+ "powerpc64le-unknown-linux-gnu": "eb6dbedaaa622af32cba2388e0d2d47e34c8724d4214a129d614b96f071d8e53",
34
+ "riscv64gc-unknown-linux-gnu": "65b807b24357133c49d97ca9394ee7e13ca62822e1095376c809654b35f39cf2",
35
+ "riscv64gc-unknown-linux-musl": "87c339a735b578f285b961bebdefe0a671f3652477d1e84dc69cd1a829f45e92",
36
+ "s390x-unknown-linux-gnu": "d99f69f47fc5e0975d6e7a5745cf2332317015caffb3bb81e5154cc7b66fa77a",
37
+ "x86_64-apple-darwin": "8dcf05a8c809bb3c471d2b614788ba27a6e41298fc8c31ac84b5f4339fd468e5",
38
+ "x86_64-pc-windows-msvc": "a252121d5b59398fcb137c6ea448176459a44010f33f67e0072305a637119ca7",
39
+ "x86_64-unknown-linux-gnu": "fa82fd8dde8e8eefdecada6aa0889666556cfceb690d06e0c3bca49eb3070a63",
40
+ "x86_64-unknown-linux-musl": "6401c4665d8fa2a9893e087c91f585430738e3170f5398a1141483efb4a93310",
41
+ }
42
+
43
+
44
+ def _installer_version(executable: str, environ: Mapping[str, str]) -> tuple[int, int, int]:
45
+ completed = subprocess.run(
46
+ [executable, "--version"], env=dict(environ), capture_output=True,
47
+ text=True, check=True, timeout=30,
48
+ )
49
+ match = re.fullmatch(
50
+ r"uv (\d+)\.(\d+)\.(\d+)(?: \([^\r\n]+\))?",
51
+ completed.stdout.strip(),
52
+ )
53
+ if match is None:
54
+ raise RuntimeError("Cannot verify the uv installer version; MetaList was not stopped")
55
+ return tuple(int(part) for part in match.groups())
56
+
57
+
58
+ def _normalized_architecture() -> str:
59
+ machine = platform.machine().casefold()
60
+ aliases = {
61
+ "amd64": "x86_64", "x86_64": "x86_64",
62
+ "arm64": "aarch64", "aarch64": "aarch64",
63
+ "x86": "i686", "i386": "i686", "i686": "i686",
64
+ "armv7": "armv7", "armv7l": "armv7",
65
+ "ppc64le": "powerpc64le", "powerpc64le": "powerpc64le",
66
+ "riscv64": "riscv64gc", "riscv64gc": "riscv64gc",
67
+ "s390x": "s390x",
68
+ }
69
+ if machine not in aliases:
70
+ raise RuntimeError(f"Unsupported MetaList updater platform architecture: {machine}")
71
+ return aliases[machine]
72
+
73
+
74
+ def _linux_environment() -> str:
75
+ libc_name = platform.libc_ver()[0].casefold()
76
+ if libc_name in {"glibc", "gnu libc"}:
77
+ return "gnu"
78
+ if libc_name == "musl":
79
+ return "musl"
80
+ raise RuntimeError(f"Unsupported MetaList updater platform C library: {libc_name or 'unknown'}")
81
+
82
+
83
+ def _installer_target(platform_name: str) -> str:
84
+ architecture = _normalized_architecture()
85
+ if platform_name == "win32":
86
+ target = f"{architecture}-pc-windows-msvc"
87
+ elif platform_name == "darwin":
88
+ target = f"{architecture}-apple-darwin"
89
+ elif platform_name == "linux":
90
+ environment = _linux_environment()
91
+ if architecture == "armv7":
92
+ if environment == "gnu":
93
+ abi = "gnueabihf"
94
+ elif environment == "musl":
95
+ abi = "musleabihf"
96
+ else:
97
+ raise AssertionError(f"Unexpected Linux environment: {environment}")
98
+ else:
99
+ abi = environment
100
+ target = f"{architecture}-unknown-linux-{abi}"
101
+ else:
102
+ raise RuntimeError(f"Unsupported MetaList updater platform: {platform_name}")
103
+ if target not in INSTALLER_ARCHIVE_SHA256:
104
+ raise RuntimeError(f"Unsupported MetaList updater platform target: {target}")
105
+ return target
106
+
107
+
108
+ def _required_absolute_directory(environ: Mapping[str, str], name: str) -> Path:
109
+ if name not in environ:
110
+ raise RuntimeError(f"{name} is required for the MetaList update installer")
111
+ directory = Path(environ[name])
112
+ if not directory.is_absolute():
113
+ raise RuntimeError(f"{name} must be an absolute path for the MetaList update installer")
114
+ return directory
115
+
116
+
117
+ def _installer_cache_root(*, platform_name: str, environ: Mapping[str, str]) -> Path:
118
+ if platform_name == "win32":
119
+ return _required_absolute_directory(environ, "LOCALAPPDATA") / "MetaList" / "update-tools"
120
+ if platform_name == "darwin":
121
+ home = _required_absolute_directory(environ, "HOME")
122
+ return home / "Library" / "Caches" / "MetaList" / "update-tools"
123
+ if platform_name == "linux":
124
+ if "XDG_CACHE_HOME" in environ:
125
+ cache_home = _required_absolute_directory(environ, "XDG_CACHE_HOME")
126
+ else:
127
+ home = _required_absolute_directory(environ, "HOME")
128
+ cache_home = home / ".cache"
129
+ return cache_home / "metalist" / "update-tools"
130
+ raise RuntimeError(f"Unsupported MetaList updater platform: {platform_name}")
131
+
132
+
133
+ def _archive_name(*, target: str, platform_name: str) -> str:
134
+ if platform_name == "win32":
135
+ extension = "zip"
136
+ elif platform_name in {"darwin", "linux"}:
137
+ extension = "tar.gz"
138
+ else:
139
+ raise RuntimeError(f"Unsupported MetaList updater platform: {platform_name}")
140
+ return f"uv-{target}.{extension}"
141
+
142
+
143
+ def _download_installer_archive(asset_name: str) -> bytes:
144
+ url = f"https://github.com/astral-sh/uv/releases/download/{INSTALLER_VERSION}/{asset_name}"
145
+ with urlopen(url, timeout=120) as response:
146
+ return response.read()
147
+
148
+
149
+ def _extract_installer_binary(
150
+ *, archive_body: bytes, asset_name: str, platform_name: str, target: str,
151
+ ) -> bytes:
152
+ if platform_name == "win32":
153
+ member_name = "uv.exe"
154
+ elif platform_name in {"darwin", "linux"}:
155
+ member_name = f"uv-{target}/uv"
156
+ else:
157
+ raise RuntimeError(f"Unsupported MetaList updater platform: {platform_name}")
158
+ if asset_name.endswith(".zip"):
159
+ with zipfile.ZipFile(io.BytesIO(archive_body)) as archive:
160
+ return archive.read(member_name)
161
+ with tarfile.open(fileobj=io.BytesIO(archive_body), mode="r:gz") as archive:
162
+ member = archive.extractfile(member_name)
163
+ if member is None:
164
+ raise RuntimeError("Verified update installer archive is missing the uv executable")
165
+ return member.read()
166
+
167
+
168
+ def _publish_bytes(*, destination: Path, body: bytes, mode: int) -> None:
169
+ destination.parent.mkdir(parents=True, exist_ok=True)
170
+ with NamedTemporaryFile(
171
+ dir=destination.parent, prefix=destination.name + "-", suffix=".tmp", delete=False,
172
+ ) as staged:
173
+ staged.write(body)
174
+ staged.flush()
175
+ os.fsync(staged.fileno())
176
+ staged_path = Path(staged.name)
177
+ os.chmod(staged_path, mode)
178
+ os.replace(staged_path, destination)
179
+
180
+
181
+ def _load_verified_archive(
182
+ *, archive_path: Path, expected_digest: str, asset_name: str,
183
+ ) -> bytes:
184
+ if archive_path.exists():
185
+ archive_body = archive_path.read_bytes()
186
+ if hashlib.sha256(archive_body).hexdigest() != expected_digest:
187
+ raise RuntimeError(
188
+ "Cached update installer archive failed checksum verification; "
189
+ "MetaList was not stopped"
190
+ )
191
+ return archive_body
192
+ print(f"Preparing verified MetaList update installer uv {INSTALLER_VERSION}...", flush=True)
193
+ archive_body = _download_installer_archive(asset_name)
194
+ if hashlib.sha256(archive_body).hexdigest() != expected_digest:
195
+ raise RuntimeError(
196
+ "Downloaded update installer failed checksum verification; MetaList was not stopped"
197
+ )
198
+ _publish_bytes(destination=archive_path, body=archive_body, mode=0o600)
199
+ return archive_body
200
+
201
+
202
+ def _managed_installer(*, platform_name: str, environ: Mapping[str, str]) -> str:
203
+ target = _installer_target(platform_name)
204
+ asset_name = _archive_name(target=target, platform_name=platform_name)
205
+ directory = _installer_cache_root(platform_name=platform_name, environ=environ) / (
206
+ f"uv-{INSTALLER_VERSION}-{target}"
207
+ )
208
+ archive_path = directory / asset_name
209
+ archive_body = _load_verified_archive(
210
+ archive_path=archive_path,
211
+ expected_digest=INSTALLER_ARCHIVE_SHA256[target],
212
+ asset_name=asset_name,
213
+ )
214
+ expected_binary = _extract_installer_binary(
215
+ archive_body=archive_body, asset_name=asset_name,
216
+ platform_name=platform_name, target=target,
217
+ )
218
+ if platform_name == "win32":
219
+ executable = directory / "uv.exe"
220
+ else:
221
+ assert platform_name in {"darwin", "linux"}
222
+ executable = directory / "uv"
223
+ if executable.exists():
224
+ if executable.read_bytes() != expected_binary:
225
+ raise RuntimeError(
226
+ "Cached update installer failed checksum verification; MetaList was not stopped"
227
+ )
228
+ else:
229
+ _publish_bytes(destination=executable, body=expected_binary, mode=0o700)
230
+ if platform_name != "win32":
231
+ os.chmod(executable, 0o700)
232
+ return str(executable)
233
+
234
+
235
+ def resolve_update_installer(*, platform_name: str, environ: Mapping[str, str]) -> str:
236
+ executable = _managed_installer(platform_name=platform_name, environ=environ)
237
+ expected_version = tuple(int(part) for part in INSTALLER_VERSION.split("."))
238
+ if _installer_version(executable, environ) != expected_version:
239
+ raise RuntimeError(
240
+ "Verified update installer reported the wrong version; MetaList was not stopped"
241
+ )
242
+ return executable
243
+
244
+
245
+ def repair_windows_update() -> None:
246
+ if sys.platform != "win32":
247
+ raise RuntimeError("This recovery launcher is for Windows installations")
248
+ metalist_executable = shutil.which("metalist")
249
+ if metalist_executable is None:
250
+ raise RuntimeError("The existing MetaList command must be available on PATH")
251
+ environ = dict(os.environ)
252
+ installer = resolve_update_installer(platform_name="win32", environ=environ)
253
+ # The already-installed updater discovers uv through PATH. Preserve that
254
+ # updater's preflight, shutdown, backup, offline install, and restart flow.
255
+ environ["PATH"] = str(Path(installer).parent) + os.pathsep + environ["PATH"]
256
+ subprocess.run([metalist_executable, "update"], env=environ, check=True)
257
+
258
+
259
+ if __name__ == "__main__":
260
+ repair_windows_update()
@@ -87,15 +87,12 @@ def _probe_candidate(*, python: str, executable: str, directory: Path,
87
87
  _stop_failed_namespace_launch(process=process)
88
88
 
89
89
 
90
- def prepare_update(*, uv_executable: str, target_version: str,
91
- environ: Mapping[str, str]) -> list[str]:
90
+ def prepare_update(*, target_version: str, environ: Mapping[str, str]) -> list[str]:
92
91
  # A tool environment is replaced during install: pin its external base interpreter.
93
92
  python = str(Path(sys._base_executable).resolve())
94
93
  if not Path(python).is_file():
95
94
  raise RuntimeError("The current base Python interpreter is missing; MetaList was not stopped")
96
- uv_executable = resolve_update_installer(
97
- uv_executable=uv_executable, platform_name=sys.platform, environ=environ,
98
- )
95
+ uv_executable = resolve_update_installer(platform_name=sys.platform, environ=environ)
99
96
  print(f"Checking MetaList v{target_version} installation and startup with Python {sys.version.split()[0]}...", flush=True)
100
97
  with TemporaryDirectory(prefix="metalist-update-check-") as temporary:
101
98
  directory = Path(temporary)
@@ -1,3 +1,3 @@
1
1
  """Single authoritative MetaList application version."""
2
2
 
3
- __version__ = "0.7.3"
3
+ __version__ = "0.7.4"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: metalist
3
- Version: 0.7.3
3
+ Version: 0.7.4
4
4
  Summary: A minimalist single-user note-taking app with SSR, fast in-memory tree operations, and efficient sync.
5
5
  Project-URL: Homepage, https://github.com/evolvingstuff/metalist
6
6
  Project-URL: Repository, https://github.com/evolvingstuff/metalist
@@ -48,6 +48,12 @@ A minimalist single-user note-taking app focused on server-side rendering (SSR),
48
48
  - Multi-tab search contexts with server-persisted scroll/search state (survives browser restarts)
49
49
  - Manual namespace backups/restores to a user-selected backup folder with retention controls
50
50
 
51
+ ## Changes in 0.7.4
52
+
53
+ - Updates use a private, checksum-verified uv release on Windows, macOS, and Linux. The updater does not execute a user-installed uv, and it revalidates both the cached official archive and extracted executable before each use.
54
+ - The HTTPS listener retries one bodyless safe request after a transient backend reset, records final transport failures server-side, and never replays a mutation or request body.
55
+ - Release CI builds one distribution pair, starts independent platform/Python, installed-update, browser-smoke, and browser-soak gates in parallel, and caches only hash- or lockfile-verified dependencies. Cross-platform runtime changes must pass branch CI before merge.
56
+
51
57
  ## Changes in 0.7.3
52
58
 
53
59
  - Windows updates use a private verified uv release when an older installer is vulnerable to the reported PE-resource access-denied failure. A standalone repair ZIP can bootstrap installations whose existing updater cannot update itself.
@@ -152,7 +158,7 @@ metalist update
152
158
  ```
153
159
  The updater checks the installed version against the latest PyPI release first. If MetaList is already current, it reports the installed version and leaves all running namespaces untouched. When an update is available, it checks installer prerequisites and uses uv to install the candidate into a disposable tool environment with the current base Python interpreter. It checks dependencies and starts a temporary namespace to verify HTTP readiness, version, and runtime assets. A failed preflight leaves the current installation and running namespaces unchanged. After preflight succeeds, it stops running namespaces, and creates and verifies a new backup of every namespace before installation can begin. Each archive includes the complete notes/settings database, the attachments database when present, and any legacy search-history database. Locked namespaces are backed up with their encrypted data and key metadata intact, without requiring a password.
154
160
 
155
- On Windows, the updater checks uv before installing packages. Versions older than 0.12.13 use a temporary PE-resource editing operation that can fail with `uv-trampoline.exe: Access is denied`. This checkout selects a private, checksum-verified uv 0.12.17 for those installations, keeping the same installer through preflight and final installation. It does not replace global uv. Already-installed MetaList releases retain their own updater code; the standalone repair launcher described in [recovery](docs/security/recovery.md#windows-updater-pe-resource-failure) supplies the compatible installer to that existing updater.
161
+ MetaList downloads its own checksum-verified uv 0.12.17 archive for the current operating system, architecture, and Linux C library. The verified archive and extracted executable are stored in the operating system's user cache; every update verifies the archive against its pinned upstream SHA-256 and the executable against the verified archive before use. That same executable performs both preflight and final installation. MetaList does not execute or replace the user's global uv. Download, verification, platform-selection, or version failures occur before any namespace is stopped. Already-installed releases retain their own updater code; the standalone repair launcher described in [recovery](docs/security/recovery.md#windows-updater-pe-resource-failure) supplies this managed installer to an older Windows updater.
156
162
 
157
163
  Backups are saved to `~/MetaList/namespaces/<namespace>/backups/<namespace>-<timestamp>.metalist-backup.tar.gz`; the updater prints each verified path. Existing backups remain unchanged and are not pruned. If any backup fails, the update aborts with the current installation intact; run `metalist` to restart the stopped servers after resolving the failure.
158
164
 
@@ -1,122 +0,0 @@
1
- """Select a compatible Windows installer; also runs standalone for old installations."""
2
- from __future__ import annotations
3
-
4
- from collections.abc import Mapping
5
- import hashlib
6
- import io
7
- import os
8
- from pathlib import Path
9
- import platform
10
- import re
11
- import shutil
12
- import subprocess
13
- import sys
14
- from tempfile import NamedTemporaryFile
15
- from urllib.request import urlopen
16
- import zipfile
17
-
18
-
19
- # Official immutable 0.12.17 release assets. 0.12.13 removed the temporary
20
- # Windows PE resource-editing operation that can fail under file inspection.
21
- INSTALLER_VERSION = "0.12.17"
22
- MINIMUM_WINDOWS_VERSION = (0, 12, 13)
23
- WINDOWS_INSTALLERS = {
24
- "x86_64": (
25
- "a252121d5b59398fcb137c6ea448176459a44010f33f67e0072305a637119ca7",
26
- "2019cdf564cb8f749262f5f021cedc75a99abb1c6081227ca340bbcda972611d",
27
- ),
28
- "aarch64": (
29
- "3e1aa6849d77f0e00dc865e4afab5c5b32de053e21fe35bf5ad5cec3734ec976",
30
- "92e3a7af84b7da8925997eb5b856595e1c36a4b3591fbccee7d143e69f1c8656",
31
- ),
32
- "i686": (
33
- "1d3653cb6eafd1e675e979d7cd8eeac1456202f8927a2216419993077a4c473f",
34
- "8d08a9c61f18f9436069f3ccf6e13e7f665b0e9b1ff85ac98f1ec8261c493145",
35
- ),
36
- }
37
-
38
-
39
- def _installer_version(executable: str, environ: Mapping[str, str]) -> tuple[int, int, int]:
40
- completed = subprocess.run([executable, "--version"], env=dict(environ),
41
- capture_output=True, text=True, check=True, timeout=30)
42
- match = re.fullmatch(r"uv (\d+)\.(\d+)\.(\d+)(?: \([^\r\n]+\))?", completed.stdout.strip())
43
- if match is None:
44
- raise RuntimeError("Cannot verify the uv installer version; MetaList was not stopped")
45
- return tuple(int(part) for part in match.groups())
46
-
47
-
48
- def _windows_architecture() -> str:
49
- machine = platform.machine().casefold()
50
- aliases = {"amd64": "x86_64", "x86_64": "x86_64", "arm64": "aarch64",
51
- "aarch64": "aarch64", "x86": "i686", "i386": "i686", "i686": "i686"}
52
- if machine not in aliases:
53
- raise RuntimeError(f"Unsupported Windows updater architecture: {machine}")
54
- return aliases[machine]
55
-
56
-
57
- def _download_installer_archive(architecture: str) -> bytes:
58
- assert architecture in WINDOWS_INSTALLERS
59
- url = (f"https://github.com/astral-sh/uv/releases/download/{INSTALLER_VERSION}/"
60
- f"uv-{architecture}-pc-windows-msvc.zip")
61
- with urlopen(url, timeout=120) as response:
62
- return response.read()
63
-
64
-
65
- def _managed_windows_installer(environ: Mapping[str, str]) -> str:
66
- architecture = _windows_architecture()
67
- archive_digest, binary_digest = WINDOWS_INSTALLERS[architecture]
68
- local_directory = Path(environ["LOCALAPPDATA"])
69
- if not local_directory.is_absolute():
70
- raise RuntimeError("LOCALAPPDATA must be an absolute path for the update installer")
71
- directory = local_directory / "MetaList" / "update-tools" / f"uv-{INSTALLER_VERSION}-{architecture}"
72
- executable = directory / "uv.exe"
73
- if executable.exists():
74
- if hashlib.sha256(executable.read_bytes()).hexdigest() != binary_digest:
75
- raise RuntimeError("Cached update installer failed checksum verification; MetaList was not stopped")
76
- return str(executable)
77
- print(f"Preparing verified Windows update installer uv {INSTALLER_VERSION}...", flush=True)
78
- archive_body = _download_installer_archive(architecture)
79
- if hashlib.sha256(archive_body).hexdigest() != archive_digest:
80
- raise RuntimeError("Downloaded update installer failed checksum verification; MetaList was not stopped")
81
- with zipfile.ZipFile(io.BytesIO(archive_body)) as archive:
82
- binary = archive.read("uv.exe")
83
- if hashlib.sha256(binary).hexdigest() != binary_digest:
84
- raise RuntimeError("Update installer executable failed checksum verification; MetaList was not stopped")
85
- directory.mkdir(parents=True, exist_ok=True)
86
- # Publish only complete, verified bytes. This is an installer cache, never a backup.
87
- with NamedTemporaryFile(dir=directory, prefix="uv-", suffix=".tmp", delete=False) as staged:
88
- staged.write(binary)
89
- os.replace(staged.name, executable)
90
- return str(executable)
91
-
92
-
93
- def resolve_update_installer(*, uv_executable: str, platform_name: str,
94
- environ: Mapping[str, str]) -> str:
95
- if platform_name != "win32":
96
- return uv_executable
97
- if _installer_version(uv_executable, environ) >= MINIMUM_WINDOWS_VERSION:
98
- return uv_executable
99
- executable = _managed_windows_installer(environ)
100
- expected_version = tuple(int(part) for part in INSTALLER_VERSION.split("."))
101
- if _installer_version(executable, environ) != expected_version:
102
- raise RuntimeError("Verified update installer reported the wrong version; MetaList was not stopped")
103
- return executable
104
-
105
-
106
- def repair_windows_update() -> None:
107
- if sys.platform != "win32":
108
- raise RuntimeError("This recovery launcher is for Windows installations")
109
- uv_executable = shutil.which("uv")
110
- metalist_executable = shutil.which("metalist")
111
- if uv_executable is None or metalist_executable is None:
112
- raise RuntimeError("The existing uv and MetaList commands must be available on PATH")
113
- environ = dict(os.environ)
114
- installer = resolve_update_installer(uv_executable=uv_executable, platform_name="win32", environ=environ)
115
- # The already-installed updater discovers uv through PATH. Preserve that
116
- # updater's preflight, shutdown, backup, offline install, and restart flow.
117
- environ["PATH"] = str(Path(installer).parent) + os.pathsep + environ["PATH"]
118
- subprocess.run([metalist_executable, "update"], env=environ, check=True)
119
-
120
-
121
- if __name__ == "__main__":
122
- repair_windows_update()
File without changes
File without changes
File without changes
File without changes
File without changes