MetaList 0.7.3__tar.gz → 0.7.5__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 (474) hide show
  1. {metalist-0.7.3 → metalist-0.7.5}/PKG-INFO +13 -2
  2. {metalist-0.7.3 → metalist-0.7.5}/README.md +12 -1
  3. {metalist-0.7.3 → metalist-0.7.5}/app/https_proxy.py +55 -15
  4. {metalist-0.7.3 → metalist-0.7.5}/app/main.py +13 -0
  5. metalist-0.7.5/app/security/http_error_diagnostics.py +19 -0
  6. {metalist-0.7.3 → metalist-0.7.5}/app/services/self_update.py +1 -7
  7. metalist-0.7.5/app/services/update_installer.py +260 -0
  8. {metalist-0.7.3 → metalist-0.7.5}/app/services/update_preflight.py +2 -5
  9. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/api-client.js +2 -1
  10. metalist-0.7.5/app/static/js/modules/api-error-diagnostics.js +16 -0
  11. {metalist-0.7.3 → metalist-0.7.5}/app/version.py +1 -1
  12. {metalist-0.7.3 → metalist-0.7.5}/metalist.egg-info/PKG-INFO +13 -2
  13. {metalist-0.7.3 → metalist-0.7.5}/metalist.egg-info/SOURCES.txt +2 -0
  14. {metalist-0.7.3 → metalist-0.7.5}/pyproject.toml +2 -0
  15. metalist-0.7.3/app/services/update_installer.py +0 -122
  16. {metalist-0.7.3 → metalist-0.7.5}/MANIFEST.in +0 -0
  17. {metalist-0.7.3 → metalist-0.7.5}/app/__init__.py +0 -0
  18. {metalist-0.7.3 → metalist-0.7.5}/app/api/__init__.py +0 -0
  19. {metalist-0.7.3 → metalist-0.7.5}/app/api/deps.py +0 -0
  20. {metalist-0.7.3 → metalist-0.7.5}/app/api/dev.py +0 -0
  21. {metalist-0.7.3 → metalist-0.7.5}/app/api/middleware/auth.py +0 -0
  22. {metalist-0.7.3 → metalist-0.7.5}/app/api/note_requests.py +0 -0
  23. {metalist-0.7.3 → metalist-0.7.5}/app/api/request_auth.py +0 -0
  24. {metalist-0.7.3 → metalist-0.7.5}/app/api/routes/ai.py +0 -0
  25. {metalist-0.7.3 → metalist-0.7.5}/app/api/routes/app_updates.py +0 -0
  26. {metalist-0.7.3 → metalist-0.7.5}/app/api/routes/auth.py +0 -0
  27. {metalist-0.7.3 → metalist-0.7.5}/app/api/routes/backups.py +0 -0
  28. {metalist-0.7.3 → metalist-0.7.5}/app/api/routes/files.py +0 -0
  29. {metalist-0.7.3 → metalist-0.7.5}/app/api/routes/notes.py +0 -0
  30. {metalist-0.7.3 → metalist-0.7.5}/app/api/routes/ontology.py +0 -0
  31. {metalist-0.7.3 → metalist-0.7.5}/app/api/routes/reminders.py +0 -0
  32. {metalist-0.7.3 → metalist-0.7.5}/app/api/routes/remote_images.py +0 -0
  33. {metalist-0.7.3 → metalist-0.7.5}/app/api/routes/test.py +0 -0
  34. {metalist-0.7.3 → metalist-0.7.5}/app/api/transactions.py +0 -0
  35. {metalist-0.7.3 → metalist-0.7.5}/app/api/upload_limits.py +0 -0
  36. {metalist-0.7.3 → metalist-0.7.5}/app/config.py +0 -0
  37. {metalist-0.7.3 → metalist-0.7.5}/app/data_directory.py +0 -0
  38. {metalist-0.7.3 → metalist-0.7.5}/app/db/__init__.py +0 -0
  39. {metalist-0.7.3 → metalist-0.7.5}/app/db/backup_settings_sql.py +0 -0
  40. {metalist-0.7.3 → metalist-0.7.5}/app/db/engine.py +0 -0
  41. {metalist-0.7.3 → metalist-0.7.5}/app/db/file_schema.py +0 -0
  42. {metalist-0.7.3 → metalist-0.7.5}/app/db/file_session.py +0 -0
  43. {metalist-0.7.3 → metalist-0.7.5}/app/db/files_sql.py +0 -0
  44. {metalist-0.7.3 → metalist-0.7.5}/app/db/link_titles_sql.py +0 -0
  45. {metalist-0.7.3 → metalist-0.7.5}/app/db/live_recovery.py +0 -0
  46. {metalist-0.7.3 → metalist-0.7.5}/app/db/migrations.py +0 -0
  47. {metalist-0.7.3 → metalist-0.7.5}/app/db/notes_sql.py +0 -0
  48. {metalist-0.7.3 → metalist-0.7.5}/app/db/ontology_rules_sql.py +0 -0
  49. {metalist-0.7.3 → metalist-0.7.5}/app/db/reminders_sql.py +0 -0
  50. {metalist-0.7.3 → metalist-0.7.5}/app/db/retire_sounds.py +0 -0
  51. {metalist-0.7.3 → metalist-0.7.5}/app/db/schema.py +0 -0
  52. {metalist-0.7.3 → metalist-0.7.5}/app/db/search_history_sql.py +0 -0
  53. {metalist-0.7.3 → metalist-0.7.5}/app/db/session.py +0 -0
  54. {metalist-0.7.3 → metalist-0.7.5}/app/db/settings_sql.py +0 -0
  55. {metalist-0.7.3 → metalist-0.7.5}/app/db/tab_state_sql.py +0 -0
  56. {metalist-0.7.3 → metalist-0.7.5}/app/db/version.py +0 -0
  57. {metalist-0.7.3 → metalist-0.7.5}/app/encryption_audit.py +0 -0
  58. {metalist-0.7.3 → metalist-0.7.5}/app/exception_boundaries.py +0 -0
  59. {metalist-0.7.3 → metalist-0.7.5}/app/models/commands.py +0 -0
  60. {metalist-0.7.3 → metalist-0.7.5}/app/models/database.py +0 -0
  61. {metalist-0.7.3 → metalist-0.7.5}/app/models/entities.py +0 -0
  62. {metalist-0.7.3 → metalist-0.7.5}/app/models/enums.py +0 -0
  63. {metalist-0.7.3 → metalist-0.7.5}/app/models/linked_list.py +0 -0
  64. {metalist-0.7.3 → metalist-0.7.5}/app/models/list_operations.py +0 -0
  65. {metalist-0.7.3 → metalist-0.7.5}/app/models/list_traversal.py +0 -0
  66. {metalist-0.7.3 → metalist-0.7.5}/app/models/note_crud.py +0 -0
  67. {metalist-0.7.3 → metalist-0.7.5}/app/models/utils.py +0 -0
  68. {metalist-0.7.3 → metalist-0.7.5}/app/network_settings.py +0 -0
  69. {metalist-0.7.3 → metalist-0.7.5}/app/presentation/__init__.py +0 -0
  70. {metalist-0.7.3 → metalist-0.7.5}/app/presentation/render/__init__.py +0 -0
  71. {metalist-0.7.3 → metalist-0.7.5}/app/presentation/render/note_renderer.py +0 -0
  72. {metalist-0.7.3 → metalist-0.7.5}/app/presentation/templates.py +0 -0
  73. {metalist-0.7.3 → metalist-0.7.5}/app/security/authenticated_logging.py +0 -0
  74. {metalist-0.7.3 → metalist-0.7.5}/app/security/encryption.py +0 -0
  75. {metalist-0.7.3 → metalist-0.7.5}/app/security/http_headers.py +0 -0
  76. {metalist-0.7.3 → metalist-0.7.5}/app/security/note_html.py +0 -0
  77. {metalist-0.7.3 → metalist-0.7.5}/app/security/request_boundary.py +0 -0
  78. {metalist-0.7.3 → metalist-0.7.5}/app/security/request_hosts.py +0 -0
  79. {metalist-0.7.3 → metalist-0.7.5}/app/security/sensitive_cache.py +0 -0
  80. {metalist-0.7.3 → metalist-0.7.5}/app/security/sensitive_logging.py +0 -0
  81. {metalist-0.7.3 → metalist-0.7.5}/app/security/shell_execution.py +0 -0
  82. {metalist-0.7.3 → metalist-0.7.5}/app/security/validation_errors.py +0 -0
  83. {metalist-0.7.3 → metalist-0.7.5}/app/server_runtime.py +0 -0
  84. {metalist-0.7.3 → metalist-0.7.5}/app/services/__init__.py +0 -0
  85. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/__init__.py +0 -0
  86. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/actions.py +0 -0
  87. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/cloud_privacy.py +0 -0
  88. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/context.py +0 -0
  89. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/evidence_serialization.py +0 -0
  90. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/help_catalog.py +0 -0
  91. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/history.py +0 -0
  92. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/inference.py +0 -0
  93. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/investigation.py +0 -0
  94. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/judging.py +0 -0
  95. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/menu_actions.py +0 -0
  96. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/model_policy.py +0 -0
  97. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/openai_cost_tracking.py +0 -0
  98. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/openai_inference.py +0 -0
  99. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/permissions.py +0 -0
  100. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/prompt_settings.py +0 -0
  101. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/prompts/__init__.py +0 -0
  102. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/prompts/final-response.md +0 -0
  103. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/prompts/help-response.md +0 -0
  104. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/prompts/system.md +0 -0
  105. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/prompts/tool-result.md +0 -0
  106. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/retrieval_settings.py +0 -0
  107. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/runtime.py +0 -0
  108. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/scope.py +0 -0
  109. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/skill_settings.py +0 -0
  110. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/skills/__init__.py +0 -0
  111. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/skills/help-ai.md +0 -0
  112. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/skills/help-data.md +0 -0
  113. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/skills/help-formatting.md +0 -0
  114. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/skills/help-menus.md +0 -0
  115. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/skills/help-notes.md +0 -0
  116. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/skills/help-privacy.md +0 -0
  117. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/skills/help-references.md +0 -0
  118. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/skills/help-reminders.md +0 -0
  119. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/skills/help-search.md +0 -0
  120. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/skills/help-tags.md +0 -0
  121. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/skills/scoped-investigation.md +0 -0
  122. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/structured_inference.py +0 -0
  123. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/tagging.py +0 -0
  124. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/tagging_run.py +0 -0
  125. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/token_estimation.py +0 -0
  126. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/tools.py +0 -0
  127. {metalist-0.7.3 → metalist-0.7.5}/app/services/agent/trace.py +0 -0
  128. {metalist-0.7.3 → metalist-0.7.5}/app/services/ai_chat.py +0 -0
  129. {metalist-0.7.3 → metalist-0.7.5}/app/services/ai_chat_rendering.py +0 -0
  130. {metalist-0.7.3 → metalist-0.7.5}/app/services/ai_chat_stream.py +0 -0
  131. {metalist-0.7.3 → metalist-0.7.5}/app/services/app_update_worker.py +0 -0
  132. {metalist-0.7.3 → metalist-0.7.5}/app/services/app_updates.py +0 -0
  133. {metalist-0.7.3 → metalist-0.7.5}/app/services/auth.py +0 -0
  134. {metalist-0.7.3 → metalist-0.7.5}/app/services/auth_cache_state.py +0 -0
  135. {metalist-0.7.3 → metalist-0.7.5}/app/services/auth_service.py +0 -0
  136. {metalist-0.7.3 → metalist-0.7.5}/app/services/backlink_index.py +0 -0
  137. {metalist-0.7.3 → metalist-0.7.5}/app/services/backlinks.py +0 -0
  138. {metalist-0.7.3 → metalist-0.7.5}/app/services/backup_service.py +0 -0
  139. {metalist-0.7.3 → metalist-0.7.5}/app/services/backup_settings_service.py +0 -0
  140. {metalist-0.7.3 → metalist-0.7.5}/app/services/bulk_operation.py +0 -0
  141. {metalist-0.7.3 → metalist-0.7.5}/app/services/client_state_service.py +0 -0
  142. {metalist-0.7.3 → metalist-0.7.5}/app/services/content_cache.py +0 -0
  143. {metalist-0.7.3 → metalist-0.7.5}/app/services/content_formatting.py +0 -0
  144. {metalist-0.7.3 → metalist-0.7.5}/app/services/diagnostics.py +0 -0
  145. {metalist-0.7.3 → metalist-0.7.5}/app/services/embedded_references.py +0 -0
  146. {metalist-0.7.3 → metalist-0.7.5}/app/services/encryption.py +0 -0
  147. {metalist-0.7.3 → metalist-0.7.5}/app/services/exception_capture.py +0 -0
  148. {metalist-0.7.3 → metalist-0.7.5}/app/services/file_registry.py +0 -0
  149. {metalist-0.7.3 → metalist-0.7.5}/app/services/file_storage.py +0 -0
  150. {metalist-0.7.3 → metalist-0.7.5}/app/services/footnote_layout.py +0 -0
  151. {metalist-0.7.3 → metalist-0.7.5}/app/services/footnote_rendering.py +0 -0
  152. {metalist-0.7.3 → metalist-0.7.5}/app/services/hierarchy.py +0 -0
  153. {metalist-0.7.3 → metalist-0.7.5}/app/services/html_export.py +0 -0
  154. {metalist-0.7.3 → metalist-0.7.5}/app/services/html_unformatting.py +0 -0
  155. {metalist-0.7.3 → metalist-0.7.5}/app/services/hydration_state.py +0 -0
  156. {metalist-0.7.3 → metalist-0.7.5}/app/services/image_size_formatting.py +0 -0
  157. {metalist-0.7.3 → metalist-0.7.5}/app/services/inline_image_occurrences.py +0 -0
  158. {metalist-0.7.3 → metalist-0.7.5}/app/services/input_errors.py +0 -0
  159. {metalist-0.7.3 → metalist-0.7.5}/app/services/integrity.py +0 -0
  160. {metalist-0.7.3 → metalist-0.7.5}/app/services/latex_rendering.py +0 -0
  161. {metalist-0.7.3 → metalist-0.7.5}/app/services/link_titles.py +0 -0
  162. {metalist-0.7.3 → metalist-0.7.5}/app/services/login_rate_limit.py +0 -0
  163. {metalist-0.7.3 → metalist-0.7.5}/app/services/maintenance_mode.py +0 -0
  164. {metalist-0.7.3 → metalist-0.7.5}/app/services/markdown_rendering.py +0 -0
  165. {metalist-0.7.3 → metalist-0.7.5}/app/services/namespace_deletion_jobs.py +0 -0
  166. {metalist-0.7.3 → metalist-0.7.5}/app/services/namespace_deletion_worker.py +0 -0
  167. {metalist-0.7.3 → metalist-0.7.5}/app/services/namespace_rename_jobs.py +0 -0
  168. {metalist-0.7.3 → metalist-0.7.5}/app/services/namespace_rename_worker.py +0 -0
  169. {metalist-0.7.3 → metalist-0.7.5}/app/services/namespace_runtime_guard.py +0 -0
  170. {metalist-0.7.3 → metalist-0.7.5}/app/services/namespace_switcher.py +0 -0
  171. {metalist-0.7.3 → metalist-0.7.5}/app/services/note_fullscreen.py +0 -0
  172. {metalist-0.7.3 → metalist-0.7.5}/app/services/note_image_tags.py +0 -0
  173. {metalist-0.7.3 → metalist-0.7.5}/app/services/note_ordering.py +0 -0
  174. {metalist-0.7.3 → metalist-0.7.5}/app/services/note_store.py +0 -0
  175. {metalist-0.7.3 → metalist-0.7.5}/app/services/ontology_rules_store.py +0 -0
  176. {metalist-0.7.3 → metalist-0.7.5}/app/services/openai_credentials.py +0 -0
  177. {metalist-0.7.3 → metalist-0.7.5}/app/services/password_note_fields.py +0 -0
  178. {metalist-0.7.3 → metalist-0.7.5}/app/services/reference_presentation.py +0 -0
  179. {metalist-0.7.3 → metalist-0.7.5}/app/services/reminders.py +0 -0
  180. {metalist-0.7.3 → metalist-0.7.5}/app/services/remote_image_proxy.py +0 -0
  181. {metalist-0.7.3 → metalist-0.7.5}/app/services/request_recovery.py +0 -0
  182. {metalist-0.7.3 → metalist-0.7.5}/app/services/resource_limits.py +0 -0
  183. {metalist-0.7.3 → metalist-0.7.5}/app/services/root_sorting.py +0 -0
  184. {metalist-0.7.3 → metalist-0.7.5}/app/services/runtime_generation.py +0 -0
  185. {metalist-0.7.3 → metalist-0.7.5}/app/services/runtime_hardening.py +0 -0
  186. {metalist-0.7.3 → metalist-0.7.5}/app/services/runtime_lock.py +0 -0
  187. {metalist-0.7.3 → metalist-0.7.5}/app/services/search_history.py +0 -0
  188. {metalist-0.7.3 → metalist-0.7.5}/app/services/search_history_storage.py +0 -0
  189. {metalist-0.7.3 → metalist-0.7.5}/app/services/search_index.py +0 -0
  190. {metalist-0.7.3 → metalist-0.7.5}/app/services/search_query.py +0 -0
  191. {metalist-0.7.3 → metalist-0.7.5}/app/services/search_text.py +0 -0
  192. {metalist-0.7.3 → metalist-0.7.5}/app/services/selected_text_tag.py +0 -0
  193. {metalist-0.7.3 → metalist-0.7.5}/app/services/session_timeout_service.py +0 -0
  194. {metalist-0.7.3 → metalist-0.7.5}/app/services/shell_session_service.py +0 -0
  195. {metalist-0.7.3 → metalist-0.7.5}/app/services/snapshot.py +0 -0
  196. {metalist-0.7.3 → metalist-0.7.5}/app/services/store.py +0 -0
  197. {metalist-0.7.3 → metalist-0.7.5}/app/services/structured_note_renderers.py +0 -0
  198. {metalist-0.7.3 → metalist-0.7.5}/app/services/sync.py +0 -0
  199. {metalist-0.7.3 → metalist-0.7.5}/app/services/sync_state.py +0 -0
  200. {metalist-0.7.3 → metalist-0.7.5}/app/services/tab_state.py +0 -0
  201. {metalist-0.7.3 → metalist-0.7.5}/app/services/tag_case.py +0 -0
  202. {metalist-0.7.3 → metalist-0.7.5}/app/services/tag_ontology.py +0 -0
  203. {metalist-0.7.3 → metalist-0.7.5}/app/services/tag_rename.py +0 -0
  204. {metalist-0.7.3 → metalist-0.7.5}/app/services/tag_suggestions.py +0 -0
  205. {metalist-0.7.3 → metalist-0.7.5}/app/services/tag_term_matching.py +0 -0
  206. {metalist-0.7.3 → metalist-0.7.5}/app/services/test_reset.py +0 -0
  207. {metalist-0.7.3 → metalist-0.7.5}/app/services/tokens.py +0 -0
  208. {metalist-0.7.3 → metalist-0.7.5}/app/services/undo_state.py +0 -0
  209. {metalist-0.7.3 → metalist-0.7.5}/app/services/update_backups.py +0 -0
  210. {metalist-0.7.3 → metalist-0.7.5}/app/services/view_cache.py +0 -0
  211. {metalist-0.7.3 → metalist-0.7.5}/app/services/view_diff.py +0 -0
  212. {metalist-0.7.3 → metalist-0.7.5}/app/services/view_state.py +0 -0
  213. {metalist-0.7.3 → metalist-0.7.5}/app/services/windows_process_control.py +0 -0
  214. {metalist-0.7.3 → metalist-0.7.5}/app/startup_environment.py +0 -0
  215. {metalist-0.7.3 → metalist-0.7.5}/app/startup_js_sanity.py +0 -0
  216. {metalist-0.7.3 → metalist-0.7.5}/app/startup_sanity.py +0 -0
  217. {metalist-0.7.3 → metalist-0.7.5}/app/startup_sanity_config.py +0 -0
  218. {metalist-0.7.3 → metalist-0.7.5}/app/static/config/agent-menu-actions.json +0 -0
  219. {metalist-0.7.3 → metalist-0.7.5}/app/static/config/command_palette_tags.json +0 -0
  220. {metalist-0.7.3 → metalist-0.7.5}/app/static/css/floating-notes.css +0 -0
  221. {metalist-0.7.3 → metalist-0.7.5}/app/static/css/forms.css +0 -0
  222. {metalist-0.7.3 → metalist-0.7.5}/app/static/css/main.css +0 -0
  223. {metalist-0.7.3 → metalist-0.7.5}/app/static/img/favicon.ico +0 -0
  224. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/locked.js +0 -0
  225. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/main.js +0 -0
  226. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/activity-tracker.js +0 -0
  227. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/ai-chat/agent-menu-actions.js +0 -0
  228. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/ai-chat/agent-prompt-service.js +0 -0
  229. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/ai-chat/agent-retrieval-settings.js +0 -0
  230. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/ai-chat/ai-agent-debug-view.js +0 -0
  231. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/ai-chat/ai-chat-api.js +0 -0
  232. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/ai-chat/ai-chat-panel-controller.js +0 -0
  233. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/ai-chat/ai-chat-panel-service.js +0 -0
  234. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/ai-chat/ai-thinking-level-service.js +0 -0
  235. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/ai-chat/bulk-elapsed-clock.js +0 -0
  236. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/ai-chat/bulk-proposal-ui.js +0 -0
  237. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/ai-chat/cloud-privacy-policy.js +0 -0
  238. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/ai-chat/proposal-menu.js +0 -0
  239. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/api-failure-classification-service.js +0 -0
  240. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/app-update-service.js +0 -0
  241. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/application-state.js +0 -0
  242. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/async-result.js +0 -0
  243. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/auth.js +0 -0
  244. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/client-state-api.js +0 -0
  245. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/client-state-migration.js +0 -0
  246. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/command-palette/activation-auth-policy.js +0 -0
  247. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/command-palette/backup-command-availability.js +0 -0
  248. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/command-palette/click-activation-service.js +0 -0
  249. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/command-palette/command-palette-controller.js +0 -0
  250. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/command-palette/endpoint-registry.js +0 -0
  251. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/command-palette/note-layout-preferences.js +0 -0
  252. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/command-palette/preferences-store.js +0 -0
  253. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/command-palette/tag-config-loader.js +0 -0
  254. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/command-palette/usage-store.js +0 -0
  255. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/config.js +0 -0
  256. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/connectivity-monitor.js +0 -0
  257. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/context-menu/context-menu-registry.js +0 -0
  258. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/context-menu/context-menu-service.js +0 -0
  259. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/context-menu/context-menu-target-service.js +0 -0
  260. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/context-menu/input-caret-service.js +0 -0
  261. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/disconnect-editing-state-service.js +0 -0
  262. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/dom-utils-fixed.js +0 -0
  263. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/dom-utils.js +0 -0
  264. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/editor-commands.js +0 -0
  265. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/editor-selection.js +0 -0
  266. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/editor-toolbar.js +0 -0
  267. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/elapsed-time.js +0 -0
  268. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/error-handler.js +0 -0
  269. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/error-overlay.js +0 -0
  270. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/expected-errors.js +0 -0
  271. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/location-flags.js +0 -0
  272. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/login-namespace-picker.js +0 -0
  273. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/maintenance.js +0 -0
  274. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/modals/agent-prompt-editor-modal.js +0 -0
  275. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/modals/ai-agent-settings-modal.js +0 -0
  276. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/modals/alphabetize-root-notes-modal.js +0 -0
  277. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/modals/backup-restore-modal.js +0 -0
  278. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/modals/backup-result-modal.js +0 -0
  279. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/modals/backup-retention-modal.js +0 -0
  280. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/modals/backup-settings-modal.js +0 -0
  281. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/modals/base-modal.js +0 -0
  282. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/modals/confirmation-modal.js +0 -0
  283. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/modals/delete-namespace-modal.js +0 -0
  284. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/modals/delete-namespace-validation.js +0 -0
  285. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/modals/help-modal.js +0 -0
  286. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/modals/namespace-loading-page.js +0 -0
  287. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/modals/namespace-modals.js +0 -0
  288. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/modals/namespace-ports-profile.js +0 -0
  289. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/modals/namespace-rename-validation.js +0 -0
  290. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/modals/note-layout-appearance-modal.js +0 -0
  291. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/modals/ontology-modal.js +0 -0
  292. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/modals/password-modal.js +0 -0
  293. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/modals/prioritize-modal.js +0 -0
  294. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/modals/random-password-modal.js +0 -0
  295. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/modals/reminder-modal.js +0 -0
  296. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/modals/reset-updated-at-modal.js +0 -0
  297. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/modals/search-suggestion-statistics-modal.js +0 -0
  298. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/modals/session-timeout-modal.js +0 -0
  299. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/modals/version-info-modal.js +0 -0
  300. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/actions/content-actions.js +0 -0
  301. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/actions/history-actions.js +0 -0
  302. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/actions/note-actions.js +0 -0
  303. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/actions/search-actions.js +0 -0
  304. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/actions/selection-actions.js +0 -0
  305. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/actions/ui-actions.js +0 -0
  306. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/events/context-menu-events.js +0 -0
  307. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/events/focus-events.js +0 -0
  308. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/events/inactivity-events.js +0 -0
  309. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/events/input-events.js +0 -0
  310. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/events/keyboard-events.js +0 -0
  311. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/events/mouse-events.js +0 -0
  312. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/events/search-events.js +0 -0
  313. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/mode-context.js +0 -0
  314. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/mode-logger.js +0 -0
  315. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/mode-manager-controller.js +0 -0
  316. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/add-style-service.js +0 -0
  317. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/animated-scroll-service.js +0 -0
  318. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/backlinks-navigation-service.js +0 -0
  319. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/backlinks-panel-service.js +0 -0
  320. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/clipboard-shortcut-policy-service.js +0 -0
  321. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/collapse-affordance-service.js +0 -0
  322. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/collapse-editing-policy-service.js +0 -0
  323. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/command-gate-service.js +0 -0
  324. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/context-menu-target-service.js +0 -0
  325. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/deselect-selection-state-service.js +0 -0
  326. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/differential-view-service.js +0 -0
  327. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/edit-session-collapse-policy-service.js +0 -0
  328. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/edit-session-collapse-service.js +0 -0
  329. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/embedded-image-service.js +0 -0
  330. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/file-drop-policy-service.js +0 -0
  331. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/file-image-preview-service.js +0 -0
  332. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/file-reference-service.js +0 -0
  333. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/filtered-refresh-selection-service.js +0 -0
  334. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/floating-note-dom.js +0 -0
  335. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/floating-note-layout.js +0 -0
  336. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/floating-note-service.js +0 -0
  337. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/footnote-navigation-service.js +0 -0
  338. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/history-selection-policy-service.js +0 -0
  339. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/history-shortcut-policy-service.js +0 -0
  340. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/html-paste-sanitizer-service.js +0 -0
  341. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/image-context-menu-action-service.js +0 -0
  342. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/image-file-insert-choice-modal-service.js +0 -0
  343. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/infinite-scroll-service.js +0 -0
  344. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/link-context-menu-action-service.js +0 -0
  345. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/link-title-prefetch-service.js +0 -0
  346. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/markdown-render-service.js +0 -0
  347. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/mermaid-render-service.js +0 -0
  348. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/note-click-target-service.js +0 -0
  349. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/note-clipboard-write-service.js +0 -0
  350. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/note-collapse-animation-service.js +0 -0
  351. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/note-context-menu-action-service.js +0 -0
  352. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/note-delete-shortcut-policy-service.js +0 -0
  353. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/note-drag-service.js +0 -0
  354. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/note-fullscreen-service.js +0 -0
  355. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/note-reposition-animation-service.js +0 -0
  356. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/note-split-service.js +0 -0
  357. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/note-timestamp-hover-service.js +0 -0
  358. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/password-clipboard-service.js +0 -0
  359. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/polling-service.js +0 -0
  360. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/reference-source-navigation-service.js +0 -0
  361. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/remote-image-proxy-service.js +0 -0
  362. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/remove-formatting-service.js +0 -0
  363. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/root-date-separator-service.js +0 -0
  364. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/root-sort-indicator-service.js +0 -0
  365. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/root-sort-service.js +0 -0
  366. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/scroll-anchor-service.js +0 -0
  367. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/scroll-restoration-service.js +0 -0
  368. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/scroll-to-top-service.js +0 -0
  369. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/search-contexts-overlay-service.js +0 -0
  370. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/search-debounce-service.js +0 -0
  371. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/search-input-service.js +0 -0
  372. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/search-interaction-service.js +0 -0
  373. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/search-redaction-reveal-service.js +0 -0
  374. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/search-suggestion-statistics-service.js +0 -0
  375. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/search-suggestion-window-labels-service.js +0 -0
  376. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/search-suggestion-windows-service.js +0 -0
  377. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/search-suggestions-service.js +0 -0
  378. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/search-syntax-service.js +0 -0
  379. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/selected-formatting-removal-service.js +0 -0
  380. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/selected-text-tag-service.js +0 -0
  381. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/shell-output-service.js +0 -0
  382. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/tab-dom-cache-service.js +0 -0
  383. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/tab-drag-service.js +0 -0
  384. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/tab-duplication-service.js +0 -0
  385. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/tab-state-service.js +0 -0
  386. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/tag-bar-service.js +0 -0
  387. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/tag-input-selection-service.js +0 -0
  388. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/tag-proposal-service.js +0 -0
  389. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/tag-suggestions-service.js +0 -0
  390. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/tag-syntax-service.js +0 -0
  391. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/todo-toggle-editing-service.js +0 -0
  392. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/untagged-view-indicator-service.js +0 -0
  393. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/mode-manager/services/view-mode-search-shortcut-service.js +0 -0
  394. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/note-html-sanitizer.js +0 -0
  395. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/password-generator.js +0 -0
  396. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/password-operation-response.js +0 -0
  397. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/password-policy.js +0 -0
  398. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/password-strength.js +0 -0
  399. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/reminder-store.js +0 -0
  400. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/reminder-surface-service.js +0 -0
  401. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/selection-markers.js +0 -0
  402. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/session-auth.js +0 -0
  403. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/tag-token.js +0 -0
  404. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/modules/uuid.js +0 -0
  405. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/namespace-deleted.js +0 -0
  406. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/namespace-renamed.js +0 -0
  407. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/vendor/dompurify-3.4.13.LICENSE.txt +0 -0
  408. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/vendor/dompurify-3.4.13.min.js +0 -0
  409. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/vendor/markdown-it-14.3.2.LICENSE.txt +0 -0
  410. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/vendor/markdown-it-14.3.2.min.js +0 -0
  411. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/vendor/mermaid-11.16.1.LICENSE.txt +0 -0
  412. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/vendor/mermaid-11.16.1.min.js +0 -0
  413. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/vendor/zxcvbn-4.4.2.LICENSE.txt +0 -0
  414. {metalist-0.7.3 → metalist-0.7.5}/app/static/js/vendor/zxcvbn-4.4.2.js +0 -0
  415. {metalist-0.7.3 → metalist-0.7.5}/app/static/note-html-policy.json +0 -0
  416. {metalist-0.7.3 → metalist-0.7.5}/app/static/video/login-startup.mp4 +0 -0
  417. {metalist-0.7.3 → metalist-0.7.5}/app/templates/base.html +0 -0
  418. {metalist-0.7.3 → metalist-0.7.5}/app/templates/index.html +0 -0
  419. {metalist-0.7.3 → metalist-0.7.5}/app/templates/locked.html +0 -0
  420. {metalist-0.7.3 → metalist-0.7.5}/app/templates/maintenance.html +0 -0
  421. {metalist-0.7.3 → metalist-0.7.5}/app/templates/namespace_deleted.html +0 -0
  422. {metalist-0.7.3 → metalist-0.7.5}/app/templates/namespace_renamed.html +0 -0
  423. {metalist-0.7.3 → metalist-0.7.5}/app/templates/notes_list.html +0 -0
  424. {metalist-0.7.3 → metalist-0.7.5}/app/upload_limits.py +0 -0
  425. {metalist-0.7.3 → metalist-0.7.5}/app/usecases/__init__.py +0 -0
  426. {metalist-0.7.3 → metalist-0.7.5}/app/usecases/add_selected_text_tag.py +0 -0
  427. {metalist-0.7.3 → metalist-0.7.5}/app/usecases/alphabetize_root_notes.py +0 -0
  428. {metalist-0.7.3 → metalist-0.7.5}/app/usecases/base.py +0 -0
  429. {metalist-0.7.3 → metalist-0.7.5}/app/usecases/bulk_tag_proposals.py +0 -0
  430. {metalist-0.7.3 → metalist-0.7.5}/app/usecases/collapse.py +0 -0
  431. {metalist-0.7.3 → metalist-0.7.5}/app/usecases/copy_note.py +0 -0
  432. {metalist-0.7.3 → metalist-0.7.5}/app/usecases/create_child.py +0 -0
  433. {metalist-0.7.3 → metalist-0.7.5}/app/usecases/create_note.py +0 -0
  434. {metalist-0.7.3 → metalist-0.7.5}/app/usecases/create_sibling.py +0 -0
  435. {metalist-0.7.3 → metalist-0.7.5}/app/usecases/delete_subtree.py +0 -0
  436. {metalist-0.7.3 → metalist-0.7.5}/app/usecases/delete_tag.py +0 -0
  437. {metalist-0.7.3 → metalist-0.7.5}/app/usecases/expand.py +0 -0
  438. {metalist-0.7.3 → metalist-0.7.5}/app/usecases/indent.py +0 -0
  439. {metalist-0.7.3 → metalist-0.7.5}/app/usecases/lock.py +0 -0
  440. {metalist-0.7.3 → metalist-0.7.5}/app/usecases/move.py +0 -0
  441. {metalist-0.7.3 → metalist-0.7.5}/app/usecases/move_to_top.py +0 -0
  442. {metalist-0.7.3 → metalist-0.7.5}/app/usecases/outdent.py +0 -0
  443. {metalist-0.7.3 → metalist-0.7.5}/app/usecases/paste_child.py +0 -0
  444. {metalist-0.7.3 → metalist-0.7.5}/app/usecases/paste_sibling.py +0 -0
  445. {metalist-0.7.3 → metalist-0.7.5}/app/usecases/prefetch_link_titles.py +0 -0
  446. {metalist-0.7.3 → metalist-0.7.5}/app/usecases/prioritize.py +0 -0
  447. {metalist-0.7.3 → metalist-0.7.5}/app/usecases/redo.py +0 -0
  448. {metalist-0.7.3 → metalist-0.7.5}/app/usecases/rename_tag.py +0 -0
  449. {metalist-0.7.3 → metalist-0.7.5}/app/usecases/reset_updated_at.py +0 -0
  450. {metalist-0.7.3 → metalist-0.7.5}/app/usecases/resize_image.py +0 -0
  451. {metalist-0.7.3 → metalist-0.7.5}/app/usecases/run_shell.py +0 -0
  452. {metalist-0.7.3 → metalist-0.7.5}/app/usecases/search_comment_autofill.py +0 -0
  453. {metalist-0.7.3 → metalist-0.7.5}/app/usecases/search_context_tags.py +0 -0
  454. {metalist-0.7.3 → metalist-0.7.5}/app/usecases/set_collapse_bulk.py +0 -0
  455. {metalist-0.7.3 → metalist-0.7.5}/app/usecases/set_collapse_in_context.py +0 -0
  456. {metalist-0.7.3 → metalist-0.7.5}/app/usecases/split_note.py +0 -0
  457. {metalist-0.7.3 → metalist-0.7.5}/app/usecases/tag_proposals.py +0 -0
  458. {metalist-0.7.3 → metalist-0.7.5}/app/usecases/toggle_reference_mode.py +0 -0
  459. {metalist-0.7.3 → metalist-0.7.5}/app/usecases/toggle_todo_done.py +0 -0
  460. {metalist-0.7.3 → metalist-0.7.5}/app/usecases/undo.py +0 -0
  461. {metalist-0.7.3 → metalist-0.7.5}/app/usecases/unformat_content.py +0 -0
  462. {metalist-0.7.3 → metalist-0.7.5}/app/usecases/update_content.py +0 -0
  463. {metalist-0.7.3 → metalist-0.7.5}/app/usecases/view.py +0 -0
  464. {metalist-0.7.3 → metalist-0.7.5}/app/utils/__init__.py +0 -0
  465. {metalist-0.7.3 → metalist-0.7.5}/app/utils/encryption.py +0 -0
  466. {metalist-0.7.3 → metalist-0.7.5}/app/utils/text_utils.py +0 -0
  467. {metalist-0.7.3 → metalist-0.7.5}/convert-from-legacy.py +0 -0
  468. {metalist-0.7.3 → metalist-0.7.5}/main.py +0 -0
  469. {metalist-0.7.3 → metalist-0.7.5}/metalist.egg-info/dependency_links.txt +0 -0
  470. {metalist-0.7.3 → metalist-0.7.5}/metalist.egg-info/entry_points.txt +0 -0
  471. {metalist-0.7.3 → metalist-0.7.5}/metalist.egg-info/requires.txt +0 -0
  472. {metalist-0.7.3 → metalist-0.7.5}/metalist.egg-info/top_level.txt +0 -0
  473. {metalist-0.7.3 → metalist-0.7.5}/scripts/generate-lan-cert.sh +0 -0
  474. {metalist-0.7.3 → metalist-0.7.5}/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.5
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,17 @@ 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.5
52
+
53
+ - Unexpected API 500 errors now show the exception class and MetaList source line in the browser, without exposing note contents, exception messages, or local filesystem paths.
54
+ - A local release command validates the exact cross-platform CI matrix, publishes only its tested artifacts, then verifies the public PyPI package in a clean installation.
55
+
56
+ ## Changes in 0.7.4
57
+
58
+ - 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.
59
+ - 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.
60
+ - 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.
61
+
51
62
  ## Changes in 0.7.3
52
63
 
53
64
  - 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 +163,7 @@ metalist update
152
163
  ```
153
164
  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
165
 
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.
166
+ 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
167
 
157
168
  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
169
 
@@ -12,6 +12,17 @@ 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.5
16
+
17
+ - Unexpected API 500 errors now show the exception class and MetaList source line in the browser, without exposing note contents, exception messages, or local filesystem paths.
18
+ - A local release command validates the exact cross-platform CI matrix, publishes only its tested artifacts, then verifies the public PyPI package in a clean installation.
19
+
20
+ ## Changes in 0.7.4
21
+
22
+ - 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.
23
+ - 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.
24
+ - 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.
25
+
15
26
  ## Changes in 0.7.3
16
27
 
17
28
  - 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 +127,7 @@ metalist update
116
127
  ```
117
128
  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
129
 
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.
130
+ 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
131
 
121
132
  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
133
 
@@ -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:
@@ -38,6 +38,7 @@ from app.services.search_history import search_history_store
38
38
  from app.services.runtime_hardening import apply_runtime_hardening
39
39
  from app.security.encryption import set_encryption_required
40
40
  from app.security.http_headers import apply_security_headers
41
+ from app.security.http_error_diagnostics import describe_server_exception
41
42
  from app.security.request_boundary import RequestBoundaryMiddleware
42
43
  from app.security.request_boundary import resolve_allowed_request_hosts
43
44
  from app.security.validation_errors import summarize_validation_errors
@@ -149,6 +150,18 @@ async def request_validation_error(request: Request, exc: RequestValidationError
149
150
  async def handle_ontology_parse_error(request: Request, exc: OntologyParseError):
150
151
  return JSONResponse(status_code=400, content={"detail": str(exc)})
151
152
 
153
+
154
+ @app.exception_handler(Exception)
155
+ async def handle_unexpected_server_error(request: Request, exc: Exception):
156
+ return JSONResponse(
157
+ status_code=500,
158
+ content={
159
+ "detail": "Internal server error",
160
+ "diagnostic": describe_server_exception(exc),
161
+ },
162
+ headers={"Cache-Control": "no-store, private", "X-Content-Type-Options": "nosniff"},
163
+ )
164
+
152
165
  _startup_timing_enabled = True
153
166
 
154
167
 
@@ -0,0 +1,19 @@
1
+ """Small, data-free diagnostics for unexpected HTTP failures."""
2
+
3
+ from pathlib import Path
4
+ import traceback
5
+
6
+
7
+ _APP_DIRECTORY = Path(__file__).resolve().parents[1]
8
+ _REPOSITORY_DIRECTORY = _APP_DIRECTORY.parent
9
+
10
+
11
+ def describe_server_exception(error: Exception) -> dict[str, str]:
12
+ """Expose the exception class and last application frame, never its message."""
13
+ location = "external"
14
+ for frame in reversed(traceback.extract_tb(error.__traceback__)):
15
+ path = Path(frame.filename).resolve()
16
+ if path.is_relative_to(_APP_DIRECTORY):
17
+ location = f"{path.relative_to(_REPOSITORY_DIRECTORY).as_posix()}:{frame.lineno}"
18
+ break
19
+ return {"errorType": type(error).__name__, "codeLocation": location}
@@ -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)
@@ -7,6 +7,7 @@ import { computeScrollAnchor } from './mode-manager/services/scroll-anchor-servi
7
7
  import { CommandGate } from './mode-manager/services/command-gate-service.js';
8
8
  import { buildSessionHeaders } from './session-auth.js';
9
9
  import { sanitizeNoteHtmlForStorage } from './note-html-sanitizer.js';
10
+ import { describeApiFailure } from './api-error-diagnostics.js';
10
11
 
11
12
  function buildAuthHeaders(includeContentType) {
12
13
  return buildSessionHeaders(includeContentType);
@@ -125,7 +126,7 @@ export const NotesAPI = {
125
126
  if (!response.ok) {
126
127
  // Use centralized error handling
127
128
  ErrorHandler.handleApiError(null, response);
128
- throw new HttpRequestError(`API call failed: ${response.status} ${response.statusText}`);
129
+ throw new HttpRequestError(await describeApiFailure(response));
129
130
  }
130
131
 
131
132
  const data = await response.json();
@@ -0,0 +1,16 @@
1
+ const ERROR_TYPE = /^[A-Za-z_][A-Za-z0-9_]*$/;
2
+ const CODE_LOCATION = /^(?:app(?:\/[A-Za-z_][A-Za-z0-9_]*)+\.py:\d+|external)$/;
3
+
4
+ export async function describeApiFailure(response) {
5
+ const base = `API call failed: ${response.status} ${response.statusText}`;
6
+ if (response.status < 500 || !response.headers.get('content-type')?.includes('application/json')) {
7
+ return base;
8
+ }
9
+
10
+ const body = await response.json();
11
+ const diagnostic = body?.diagnostic;
12
+ if (!ERROR_TYPE.test(diagnostic?.errorType) || !CODE_LOCATION.test(diagnostic?.codeLocation)) {
13
+ return base;
14
+ }
15
+ return `${base} (${diagnostic.errorType} at ${diagnostic.codeLocation})`;
16
+ }
@@ -1,3 +1,3 @@
1
1
  """Single authoritative MetaList application version."""
2
2
 
3
- __version__ = "0.7.3"
3
+ __version__ = "0.7.5"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: metalist
3
- Version: 0.7.3
3
+ Version: 0.7.5
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,17 @@ 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.5
52
+
53
+ - Unexpected API 500 errors now show the exception class and MetaList source line in the browser, without exposing note contents, exception messages, or local filesystem paths.
54
+ - A local release command validates the exact cross-platform CI matrix, publishes only its tested artifacts, then verifies the public PyPI package in a clean installation.
55
+
56
+ ## Changes in 0.7.4
57
+
58
+ - 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.
59
+ - 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.
60
+ - 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.
61
+
51
62
  ## Changes in 0.7.3
52
63
 
53
64
  - 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 +163,7 @@ metalist update
152
163
  ```
153
164
  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
165
 
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.
166
+ 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
167
 
157
168
  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
169
 
@@ -70,6 +70,7 @@ app/presentation/render/__init__.py
70
70
  app/presentation/render/note_renderer.py
71
71
  app/security/authenticated_logging.py
72
72
  app/security/encryption.py
73
+ app/security/http_error_diagnostics.py
73
74
  app/security/http_headers.py
74
75
  app/security/note_html.py
75
76
  app/security/request_boundary.py
@@ -224,6 +225,7 @@ app/static/js/namespace-deleted.js
224
225
  app/static/js/namespace-renamed.js
225
226
  app/static/js/modules/activity-tracker.js
226
227
  app/static/js/modules/api-client.js
228
+ app/static/js/modules/api-error-diagnostics.js
227
229
  app/static/js/modules/api-failure-classification-service.js
228
230
  app/static/js/modules/app-update-service.js
229
231
  app/static/js/modules/application-state.js
@@ -77,6 +77,8 @@ app = [
77
77
  release = [
78
78
  "build==1.6.1",
79
79
  "pip-audit==2.10.1",
80
+ "requests==2.34.2",
81
+ "rich==14.3.4",
80
82
  "setuptools==83.0.0",
81
83
  "uv==0.11.23",
82
84
  "wheel==0.48.0",