MetaList 0.3.11__tar.gz → 0.3.13__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 (380) hide show
  1. {metalist-0.3.11/metalist.egg-info → metalist-0.3.13}/PKG-INFO +63 -8
  2. {metalist-0.3.11 → metalist-0.3.13}/README.md +57 -7
  3. {metalist-0.3.11 → metalist-0.3.13}/app/api/middleware/auth.py +26 -30
  4. {metalist-0.3.11 → metalist-0.3.13}/app/api/request_auth.py +12 -1
  5. {metalist-0.3.11 → metalist-0.3.13}/app/api/routes/auth.py +54 -212
  6. {metalist-0.3.11 → metalist-0.3.13}/app/api/routes/backups.py +15 -13
  7. {metalist-0.3.11 → metalist-0.3.13}/app/api/routes/notes.py +130 -46
  8. metalist-0.3.13/app/api/routes/remote_images.py +88 -0
  9. {metalist-0.3.11 → metalist-0.3.13}/app/config.py +6 -1
  10. {metalist-0.3.11 → metalist-0.3.13}/app/db/file_session.py +4 -2
  11. {metalist-0.3.11 → metalist-0.3.13}/app/db/migrations.py +112 -3
  12. {metalist-0.3.11 → metalist-0.3.13}/app/db/schema.py +28 -20
  13. metalist-0.3.13/app/db/search_history_sql.py +77 -0
  14. metalist-0.3.13/app/db/version.py +3 -0
  15. {metalist-0.3.11 → metalist-0.3.13}/app/encryption_audit.py +198 -19
  16. {metalist-0.3.11 → metalist-0.3.13}/app/main.py +80 -14
  17. {metalist-0.3.11 → metalist-0.3.13}/app/models/database.py +5 -2
  18. {metalist-0.3.11 → metalist-0.3.13}/app/models/note_crud.py +6 -4
  19. {metalist-0.3.11 → metalist-0.3.13}/app/models/utils.py +22 -19
  20. {metalist-0.3.11 → metalist-0.3.13}/app/presentation/render/note_renderer.py +5 -1
  21. metalist-0.3.13/app/presentation/templates.py +13 -0
  22. metalist-0.3.13/app/security/authenticated_logging.py +179 -0
  23. metalist-0.3.13/app/security/http_headers.py +43 -0
  24. metalist-0.3.13/app/security/note_html.py +204 -0
  25. metalist-0.3.13/app/security/request_boundary.py +244 -0
  26. metalist-0.3.13/app/security/sensitive_logging.py +14 -0
  27. metalist-0.3.13/app/security/shell_execution.py +40 -0
  28. metalist-0.3.13/app/security/validation_errors.py +29 -0
  29. {metalist-0.3.11 → metalist-0.3.13}/app/server_runtime.py +16 -6
  30. {metalist-0.3.11 → metalist-0.3.13}/app/services/auth_service.py +78 -8
  31. {metalist-0.3.11 → metalist-0.3.13}/app/services/backup_service.py +87 -20
  32. {metalist-0.3.11 → metalist-0.3.13}/app/services/base_service.py +5 -2
  33. {metalist-0.3.11 → metalist-0.3.13}/app/services/client_state_service.py +27 -0
  34. {metalist-0.3.11 → metalist-0.3.13}/app/services/content_cache.py +17 -6
  35. {metalist-0.3.11 → metalist-0.3.13}/app/services/content_formatting.py +290 -35
  36. {metalist-0.3.11 → metalist-0.3.13}/app/services/diagnostics.py +173 -28
  37. {metalist-0.3.11 → metalist-0.3.13}/app/services/embedded_references.py +89 -85
  38. {metalist-0.3.11 → metalist-0.3.13}/app/services/encryption.py +52 -0
  39. {metalist-0.3.11 → metalist-0.3.13}/app/services/html_export.py +0 -1
  40. {metalist-0.3.11 → metalist-0.3.13}/app/services/html_unformatting.py +73 -22
  41. {metalist-0.3.11 → metalist-0.3.13}/app/services/link_titles.py +207 -22
  42. {metalist-0.3.11 → metalist-0.3.13}/app/services/markdown_rendering.py +7 -0
  43. metalist-0.3.13/app/services/namespace_runtime_guard.py +143 -0
  44. {metalist-0.3.11 → metalist-0.3.13}/app/services/namespace_switcher.py +72 -27
  45. metalist-0.3.13/app/services/note_fullscreen.py +107 -0
  46. {metalist-0.3.11 → metalist-0.3.13}/app/services/note_image_tags.py +8 -21
  47. {metalist-0.3.11 → metalist-0.3.13}/app/services/note_store.py +2 -2
  48. metalist-0.3.13/app/services/remote_image_proxy.py +299 -0
  49. {metalist-0.3.11 → metalist-0.3.13}/app/services/root_sorting.py +36 -1
  50. {metalist-0.3.11 → metalist-0.3.13}/app/services/runtime_lock.py +2 -0
  51. metalist-0.3.13/app/services/search_history.py +829 -0
  52. metalist-0.3.13/app/services/search_history_storage.py +153 -0
  53. {metalist-0.3.11 → metalist-0.3.13}/app/services/search_index.py +128 -126
  54. {metalist-0.3.11 → metalist-0.3.13}/app/services/search_query.py +70 -12
  55. {metalist-0.3.11 → metalist-0.3.13}/app/services/selected_text_tag.py +2 -0
  56. {metalist-0.3.11 → metalist-0.3.13}/app/services/self_update.py +91 -8
  57. {metalist-0.3.11 → metalist-0.3.13}/app/services/snapshot.py +224 -118
  58. {metalist-0.3.11 → metalist-0.3.13}/app/services/tag_ontology.py +2 -0
  59. {metalist-0.3.11 → metalist-0.3.13}/app/services/tag_suggestions.py +1 -1
  60. {metalist-0.3.11 → metalist-0.3.13}/app/services/transaction_manager.py +6 -3
  61. {metalist-0.3.11 → metalist-0.3.13}/app/services/undo_state.py +2 -277
  62. {metalist-0.3.11 → metalist-0.3.13}/app/services/view_cache.py +19 -5
  63. {metalist-0.3.11 → metalist-0.3.13}/app/services/view_diff.py +3 -0
  64. metalist-0.3.13/app/startup_environment.py +55 -0
  65. {metalist-0.3.11 → metalist-0.3.13}/app/startup_js_sanity.py +22 -0
  66. {metalist-0.3.11 → metalist-0.3.13}/app/startup_sanity.py +253 -2
  67. {metalist-0.3.11 → metalist-0.3.13}/app/static/config/command_palette_tags.json +25 -5
  68. {metalist-0.3.11 → metalist-0.3.13}/app/static/css/main.css +726 -309
  69. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/main.js +11 -0
  70. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/api-client.js +73 -62
  71. metalist-0.3.13/app/static/js/modules/api-failure-classification-service.js +82 -0
  72. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/auth.js +67 -18
  73. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/client-state-api.js +17 -2
  74. metalist-0.3.13/app/static/js/modules/command-palette/activation-auth-policy.js +27 -0
  75. metalist-0.3.13/app/static/js/modules/command-palette/backup-command-availability.js +49 -0
  76. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/command-palette/command-palette-controller.js +274 -23
  77. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/command-palette/endpoint-registry.js +48 -7
  78. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/config.js +6 -4
  79. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/connectivity-monitor.js +1 -1
  80. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/context-menu/context-menu-registry.js +148 -36
  81. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/context-menu/context-menu-service.js +56 -7
  82. metalist-0.3.13/app/static/js/modules/disconnect-editing-state-service.js +30 -0
  83. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/dom-utils-fixed.js +0 -1
  84. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/dom-utils.js +0 -1
  85. metalist-0.3.13/app/static/js/modules/elapsed-time.js +18 -0
  86. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/error-handler.js +36 -48
  87. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/error-overlay.js +13 -0
  88. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/login-namespace-picker.js +25 -7
  89. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/modals/backup-restore-modal.js +12 -33
  90. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/modals/backup-result-modal.js +0 -10
  91. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/modals/backup-settings-modal.js +73 -28
  92. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/modals/base-modal.js +59 -5
  93. metalist-0.3.13/app/static/js/modules/modals/confirmation-modal.js +145 -0
  94. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/modals/delete-namespace-modal.js +64 -62
  95. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/modals/delete-namespace-validation.js +19 -15
  96. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/modals/help-modal.js +0 -7
  97. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/modals/namespace-loading-page.js +14 -0
  98. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/modals/namespace-modals.js +20 -14
  99. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/modals/ontology-modal.js +4 -7
  100. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/modals/password-modal.js +355 -86
  101. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/modals/random-password-modal.js +150 -16
  102. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/modals/reminder-modal.js +1 -5
  103. metalist-0.3.13/app/static/js/modules/modals/search-suggestion-statistics-modal.js +455 -0
  104. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/modals/session-timeout-modal.js +1 -1
  105. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/modals/sound-manager-modal.js +1 -5
  106. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/modals/version-info-modal.js +0 -9
  107. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/actions/content-actions.js +3 -2
  108. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/actions/history-actions.js +32 -89
  109. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/actions/note-actions.js +26 -10
  110. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/actions/selection-actions.js +11 -42
  111. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/actions/ui-actions.js +6 -2
  112. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/events/context-menu-events.js +104 -7
  113. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/events/keyboard-events.js +88 -129
  114. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/events/mouse-events.js +26 -125
  115. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/events/search-events.js +36 -8
  116. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/mode-context.js +16 -1
  117. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/mode-logger.js +7 -12
  118. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/add-style-service.js +1 -0
  119. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/command-gate-service.js +0 -7
  120. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/context-menu-target-service.js +16 -0
  121. metalist-0.3.13/app/static/js/modules/mode-manager/services/deselect-selection-state-service.js +27 -0
  122. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/differential-view-service.js +79 -9
  123. metalist-0.3.13/app/static/js/modules/mode-manager/services/history-selection-policy-service.js +25 -0
  124. metalist-0.3.13/app/static/js/modules/mode-manager/services/history-shortcut-policy-service.js +23 -0
  125. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/html-paste-sanitizer-service.js +21 -1
  126. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/image-file-insert-choice-modal-service.js +10 -0
  127. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/infinite-scroll-service.js +41 -3
  128. metalist-0.3.13/app/static/js/modules/mode-manager/services/mermaid-render-service.js +223 -0
  129. metalist-0.3.13/app/static/js/modules/mode-manager/services/note-fullscreen-service.js +95 -0
  130. metalist-0.3.13/app/static/js/modules/mode-manager/services/note-timestamp-hover-service.js +61 -0
  131. metalist-0.3.13/app/static/js/modules/mode-manager/services/reference-source-navigation-service.js +83 -0
  132. metalist-0.3.13/app/static/js/modules/mode-manager/services/remote-image-proxy-service.js +216 -0
  133. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/root-sort-indicator-service.js +17 -0
  134. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/root-sort-service.js +5 -0
  135. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/search-input-service.js +13 -0
  136. metalist-0.3.13/app/static/js/modules/mode-manager/services/search-interaction-service.js +125 -0
  137. metalist-0.3.13/app/static/js/modules/mode-manager/services/search-suggestion-statistics-service.js +78 -0
  138. metalist-0.3.13/app/static/js/modules/mode-manager/services/search-suggestion-window-labels-service.js +72 -0
  139. metalist-0.3.13/app/static/js/modules/mode-manager/services/search-suggestion-windows-service.js +80 -0
  140. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/search-suggestions-service.js +41 -13
  141. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/search-syntax-service.js +54 -0
  142. metalist-0.3.13/app/static/js/modules/mode-manager/services/selected-formatting-removal-service.js +599 -0
  143. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/selected-text-tag-service.js +2 -1
  144. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/tab-state-service.js +0 -2
  145. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/tag-syntax-service.js +48 -14
  146. metalist-0.3.13/app/static/js/modules/mode-manager/services/untagged-view-indicator-service.js +13 -0
  147. metalist-0.3.13/app/static/js/modules/note-html-sanitizer.js +193 -0
  148. metalist-0.3.13/app/static/js/modules/password-operation-response.js +27 -0
  149. metalist-0.3.13/app/static/js/modules/password-policy.js +37 -0
  150. metalist-0.3.13/app/static/js/modules/password-strength.js +81 -0
  151. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/tag-token.js +3 -0
  152. metalist-0.3.13/app/static/js/vendor/dompurify-3.4.12.LICENSE.txt +202 -0
  153. metalist-0.3.13/app/static/js/vendor/dompurify-3.4.12.min.js +3 -0
  154. metalist-0.3.13/app/static/js/vendor/mermaid-11.9.0.LICENSE.txt +21 -0
  155. metalist-0.3.13/app/static/js/vendor/mermaid-11.9.0.min.js +2659 -0
  156. metalist-0.3.13/app/static/js/vendor/zxcvbn-4.4.2.LICENSE.txt +20 -0
  157. metalist-0.3.13/app/static/js/vendor/zxcvbn-4.4.2.js +28 -0
  158. metalist-0.3.13/app/static/note-html-policy.json +99 -0
  159. {metalist-0.3.11 → metalist-0.3.13}/app/templates/base.html +2 -1
  160. {metalist-0.3.11 → metalist-0.3.13}/app/templates/index.html +60 -29
  161. {metalist-0.3.11 → metalist-0.3.13}/app/templates/locked.html +1 -1
  162. {metalist-0.3.11 → metalist-0.3.13}/app/templates/maintenance.html +1 -1
  163. {metalist-0.3.11 → metalist-0.3.13}/app/templates/namespace_deleted.html +1 -1
  164. {metalist-0.3.11 → metalist-0.3.13}/app/templates/namespace_renamed.html +1 -1
  165. {metalist-0.3.11 → metalist-0.3.13}/app/usecases/add_selected_text_tag.py +8 -7
  166. {metalist-0.3.11 → metalist-0.3.13}/app/usecases/create_note.py +6 -2
  167. {metalist-0.3.11 → metalist-0.3.13}/app/usecases/delete_subtree.py +14 -3
  168. {metalist-0.3.11 → metalist-0.3.13}/app/usecases/rename_tag.py +2 -0
  169. {metalist-0.3.11 → metalist-0.3.13}/app/usecases/run_shell.py +18 -0
  170. {metalist-0.3.11 → metalist-0.3.13}/app/usecases/search_comment_autofill.py +4 -3
  171. {metalist-0.3.11 → metalist-0.3.13}/app/usecases/search_context_tags.py +5 -4
  172. {metalist-0.3.11 → metalist-0.3.13}/app/usecases/set_collapse_in_context.py +42 -65
  173. {metalist-0.3.11 → metalist-0.3.13}/app/usecases/split_note.py +5 -10
  174. {metalist-0.3.11 → metalist-0.3.13}/app/usecases/update_content.py +15 -29
  175. {metalist-0.3.11 → metalist-0.3.13}/app/usecases/view.py +1 -0
  176. {metalist-0.3.11 → metalist-0.3.13}/app/version.py +1 -1
  177. {metalist-0.3.11 → metalist-0.3.13}/main.py +102 -32
  178. {metalist-0.3.11 → metalist-0.3.13/metalist.egg-info}/PKG-INFO +63 -8
  179. {metalist-0.3.11 → metalist-0.3.13}/metalist.egg-info/SOURCES.txt +44 -1
  180. {metalist-0.3.11 → metalist-0.3.13}/metalist.egg-info/requires.txt +5 -0
  181. {metalist-0.3.11 → metalist-0.3.13}/pyproject.toml +5 -0
  182. metalist-0.3.11/app/db/search_history_sql.py +0 -213
  183. metalist-0.3.11/app/presentation/templates.py +0 -22
  184. metalist-0.3.11/app/services/search_history.py +0 -987
  185. metalist-0.3.11/app/static/js/modules/mode-manager/services/search-interaction-service.js +0 -181
  186. metalist-0.3.11/app/static/js/modules/mode-manager/services/selected-formatting-removal-service.js +0 -207
  187. metalist-0.3.11/app/usecases/record_edit_mode.py +0 -45
  188. {metalist-0.3.11 → metalist-0.3.13}/MANIFEST.in +0 -0
  189. {metalist-0.3.11 → metalist-0.3.13}/app/__init__.py +0 -0
  190. {metalist-0.3.11 → metalist-0.3.13}/app/api/__init__.py +0 -0
  191. {metalist-0.3.11 → metalist-0.3.13}/app/api/deps.py +0 -0
  192. {metalist-0.3.11 → metalist-0.3.13}/app/api/dev.py +0 -0
  193. {metalist-0.3.11 → metalist-0.3.13}/app/api/routes/files.py +0 -0
  194. {metalist-0.3.11 → metalist-0.3.13}/app/api/routes/ontology.py +0 -0
  195. {metalist-0.3.11 → metalist-0.3.13}/app/api/routes/reminders.py +0 -0
  196. {metalist-0.3.11 → metalist-0.3.13}/app/api/routes/sounds.py +0 -0
  197. {metalist-0.3.11 → metalist-0.3.13}/app/api/routes/test.py +0 -0
  198. {metalist-0.3.11 → metalist-0.3.13}/app/api/transactions.py +0 -0
  199. {metalist-0.3.11 → metalist-0.3.13}/app/db/__init__.py +0 -0
  200. {metalist-0.3.11 → metalist-0.3.13}/app/db/backup_settings_sql.py +0 -0
  201. {metalist-0.3.11 → metalist-0.3.13}/app/db/engine.py +0 -0
  202. {metalist-0.3.11 → metalist-0.3.13}/app/db/file_schema.py +0 -0
  203. {metalist-0.3.11 → metalist-0.3.13}/app/db/files_sql.py +0 -0
  204. {metalist-0.3.11 → metalist-0.3.13}/app/db/link_titles_sql.py +0 -0
  205. {metalist-0.3.11 → metalist-0.3.13}/app/db/notes_sql.py +0 -0
  206. {metalist-0.3.11 → metalist-0.3.13}/app/db/ontology_rules_sql.py +0 -0
  207. {metalist-0.3.11 → metalist-0.3.13}/app/db/reminders_sql.py +0 -0
  208. {metalist-0.3.11 → metalist-0.3.13}/app/db/session.py +0 -0
  209. {metalist-0.3.11 → metalist-0.3.13}/app/db/settings_sql.py +0 -0
  210. {metalist-0.3.11 → metalist-0.3.13}/app/db/sounds_sql.py +0 -0
  211. {metalist-0.3.11 → metalist-0.3.13}/app/db/tab_state_sql.py +0 -0
  212. {metalist-0.3.11 → metalist-0.3.13}/app/models/commands.py +0 -0
  213. {metalist-0.3.11 → metalist-0.3.13}/app/models/entities.py +0 -0
  214. {metalist-0.3.11 → metalist-0.3.13}/app/models/enums.py +0 -0
  215. {metalist-0.3.11 → metalist-0.3.13}/app/models/linked_list.py +0 -0
  216. {metalist-0.3.11 → metalist-0.3.13}/app/models/list_operations.py +0 -0
  217. {metalist-0.3.11 → metalist-0.3.13}/app/models/list_traversal.py +0 -0
  218. {metalist-0.3.11 → metalist-0.3.13}/app/presentation/__init__.py +0 -0
  219. {metalist-0.3.11 → metalist-0.3.13}/app/presentation/render/__init__.py +0 -0
  220. {metalist-0.3.11 → metalist-0.3.13}/app/security/encryption.py +0 -0
  221. {metalist-0.3.11 → metalist-0.3.13}/app/services/__init__.py +0 -0
  222. {metalist-0.3.11 → metalist-0.3.13}/app/services/auth.py +0 -0
  223. {metalist-0.3.11 → metalist-0.3.13}/app/services/auth_cache_state.py +0 -0
  224. {metalist-0.3.11 → metalist-0.3.13}/app/services/backlinks.py +0 -0
  225. {metalist-0.3.11 → metalist-0.3.13}/app/services/backup_settings_service.py +0 -0
  226. {metalist-0.3.11 → metalist-0.3.13}/app/services/date_filtering.py +0 -0
  227. {metalist-0.3.11 → metalist-0.3.13}/app/services/dependencies.py +0 -0
  228. {metalist-0.3.11 → metalist-0.3.13}/app/services/exception_capture.py +0 -0
  229. {metalist-0.3.11 → metalist-0.3.13}/app/services/file_registry.py +0 -0
  230. {metalist-0.3.11 → metalist-0.3.13}/app/services/file_storage.py +0 -0
  231. {metalist-0.3.11 → metalist-0.3.13}/app/services/hydration_state.py +0 -0
  232. {metalist-0.3.11 → metalist-0.3.13}/app/services/image_size_formatting.py +0 -0
  233. {metalist-0.3.11 → metalist-0.3.13}/app/services/inline_image_occurrences.py +0 -0
  234. {metalist-0.3.11 → metalist-0.3.13}/app/services/integrity.py +0 -0
  235. {metalist-0.3.11 → metalist-0.3.13}/app/services/latex_rendering.py +0 -0
  236. {metalist-0.3.11 → metalist-0.3.13}/app/services/login_rate_limit.py +0 -0
  237. {metalist-0.3.11 → metalist-0.3.13}/app/services/maintenance_mode.py +0 -0
  238. {metalist-0.3.11 → metalist-0.3.13}/app/services/namespace_deletion_jobs.py +0 -0
  239. {metalist-0.3.11 → metalist-0.3.13}/app/services/namespace_deletion_worker.py +0 -0
  240. {metalist-0.3.11 → metalist-0.3.13}/app/services/namespace_rename_jobs.py +0 -0
  241. {metalist-0.3.11 → metalist-0.3.13}/app/services/namespace_rename_worker.py +0 -0
  242. {metalist-0.3.11 → metalist-0.3.13}/app/services/note_service.py +0 -0
  243. {metalist-0.3.11 → metalist-0.3.13}/app/services/ontology_rules_store.py +0 -0
  244. {metalist-0.3.11 → metalist-0.3.13}/app/services/query_service.py +0 -0
  245. {metalist-0.3.11 → metalist-0.3.13}/app/services/reminders.py +0 -0
  246. {metalist-0.3.11 → metalist-0.3.13}/app/services/runtime_hardening.py +0 -0
  247. {metalist-0.3.11 → metalist-0.3.13}/app/services/search_text.py +0 -0
  248. {metalist-0.3.11 → metalist-0.3.13}/app/services/session_timeout_service.py +0 -0
  249. {metalist-0.3.11 → metalist-0.3.13}/app/services/shell_session_service.py +0 -0
  250. {metalist-0.3.11 → metalist-0.3.13}/app/services/sound_storage.py +0 -0
  251. {metalist-0.3.11 → metalist-0.3.13}/app/services/store.py +0 -0
  252. {metalist-0.3.11 → metalist-0.3.13}/app/services/sync.py +0 -0
  253. {metalist-0.3.11 → metalist-0.3.13}/app/services/sync_state.py +0 -0
  254. {metalist-0.3.11 → metalist-0.3.13}/app/services/tab_state.py +0 -0
  255. {metalist-0.3.11 → metalist-0.3.13}/app/services/tag_case.py +0 -0
  256. {metalist-0.3.11 → metalist-0.3.13}/app/services/tag_rename.py +0 -0
  257. {metalist-0.3.11 → metalist-0.3.13}/app/services/tag_term_matching.py +0 -0
  258. {metalist-0.3.11 → metalist-0.3.13}/app/services/test_reset.py +0 -0
  259. {metalist-0.3.11 → metalist-0.3.13}/app/services/tokens.py +0 -0
  260. {metalist-0.3.11 → metalist-0.3.13}/app/services/undo_service.py +0 -0
  261. {metalist-0.3.11 → metalist-0.3.13}/app/services/view_state.py +0 -0
  262. {metalist-0.3.11 → metalist-0.3.13}/app/services/windows_process_control.py +0 -0
  263. {metalist-0.3.11 → metalist-0.3.13}/app/startup_sanity_config.py +0 -0
  264. {metalist-0.3.11 → metalist-0.3.13}/app/static/css/forms.css +0 -0
  265. {metalist-0.3.11 → metalist-0.3.13}/app/static/img/favicon.ico +0 -0
  266. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/locked.js +0 -0
  267. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/activity-tracker.js +0 -0
  268. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/async-result.js +0 -0
  269. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/client-state-migration.js +0 -0
  270. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/command-palette/click-activation-service.js +0 -0
  271. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/command-palette/note-layout-preferences.js +0 -0
  272. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/command-palette/preferences-store.js +0 -0
  273. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/command-palette/tag-config-loader.js +0 -0
  274. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/command-palette/usage-store.js +0 -0
  275. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/context-menu/context-menu-target-service.js +0 -0
  276. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/context-menu/input-caret-service.js +0 -0
  277. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/editor-commands.js +0 -0
  278. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/editor-selection.js +0 -0
  279. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/editor-toolbar.js +0 -0
  280. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/location-flags.js +0 -0
  281. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/modals/alphabetize-root-notes-modal.js +0 -0
  282. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/modals/backup-retention-modal.js +0 -0
  283. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/modals/namespace-ports-profile.js +0 -0
  284. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/modals/namespace-rename-validation.js +0 -0
  285. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/modals/note-layout-appearance-modal.js +0 -0
  286. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/modals/prioritize-modal.js +0 -0
  287. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/modals/reset-updated-at-modal.js +0 -0
  288. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/actions/search-actions.js +0 -0
  289. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/events/focus-events.js +0 -0
  290. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/events/inactivity-events.js +0 -0
  291. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/events/input-events.js +0 -0
  292. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/mode-manager-controller.js +0 -0
  293. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/animated-scroll-service.js +0 -0
  294. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/backlinks-panel-service.js +0 -0
  295. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/clipboard-shortcut-policy-service.js +0 -0
  296. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/collapse-affordance-service.js +0 -0
  297. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/collapse-editing-policy-service.js +0 -0
  298. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/date-filter-indicator-service.js +0 -0
  299. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/date-filter-service.js +0 -0
  300. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/edit-session-collapse-policy-service.js +0 -0
  301. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/edit-session-collapse-service.js +0 -0
  302. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/embedded-image-service.js +0 -0
  303. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/file-drop-policy-service.js +0 -0
  304. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/file-image-preview-service.js +0 -0
  305. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/file-reference-service.js +0 -0
  306. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/filtered-refresh-selection-service.js +0 -0
  307. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/image-context-menu-action-service.js +0 -0
  308. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/link-context-menu-action-service.js +0 -0
  309. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/markdown-render-service.js +0 -0
  310. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/note-click-target-service.js +0 -0
  311. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/note-clipboard-write-service.js +0 -0
  312. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/note-collapse-animation-service.js +0 -0
  313. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/note-context-menu-action-service.js +0 -0
  314. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/note-delete-shortcut-policy-service.js +0 -0
  315. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/note-drag-service.js +0 -0
  316. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/note-reposition-animation-service.js +0 -0
  317. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/note-split-service.js +0 -0
  318. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/password-clipboard-service.js +0 -0
  319. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/polling-service.js +0 -0
  320. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/remove-formatting-service.js +0 -0
  321. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/rhs-panel-service.js +0 -0
  322. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/root-date-separator-service.js +0 -0
  323. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/scroll-anchor-service.js +0 -0
  324. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/scroll-restoration-service.js +0 -0
  325. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/scroll-to-top-service.js +0 -0
  326. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/search-contexts-overlay-service.js +0 -0
  327. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/search-debounce-service.js +0 -0
  328. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/search-redaction-reveal-service.js +0 -0
  329. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/shell-output-service.js +0 -0
  330. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/tab-dom-cache-service.js +0 -0
  331. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/tab-duplication-service.js +0 -0
  332. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/tag-bar-service.js +0 -0
  333. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/tag-suggestions-service.js +0 -0
  334. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/todo-toggle-editing-service.js +0 -0
  335. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/mode-manager/services/view-mode-search-shortcut-service.js +0 -0
  336. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/password-generator.js +0 -0
  337. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/reminder-store.js +0 -0
  338. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/reminder-surface-service.js +0 -0
  339. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/selection-markers.js +0 -0
  340. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/session-auth.js +0 -0
  341. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/sound-service.js +0 -0
  342. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/modules/uuid.js +0 -0
  343. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/namespace-deleted.js +0 -0
  344. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/namespace-renamed.js +0 -0
  345. {metalist-0.3.11 → metalist-0.3.13}/app/static/js/vendor/markdown-it.min.js +0 -0
  346. {metalist-0.3.11 → metalist-0.3.13}/app/static/video/login-startup.mp4 +0 -0
  347. {metalist-0.3.11 → metalist-0.3.13}/app/templates/notes_list.html +0 -0
  348. {metalist-0.3.11 → metalist-0.3.13}/app/usecases/__init__.py +0 -0
  349. {metalist-0.3.11 → metalist-0.3.13}/app/usecases/alphabetize_root_notes.py +0 -0
  350. {metalist-0.3.11 → metalist-0.3.13}/app/usecases/base.py +0 -0
  351. {metalist-0.3.11 → metalist-0.3.13}/app/usecases/collapse.py +0 -0
  352. {metalist-0.3.11 → metalist-0.3.13}/app/usecases/copy_note.py +0 -0
  353. {metalist-0.3.11 → metalist-0.3.13}/app/usecases/create_child.py +0 -0
  354. {metalist-0.3.11 → metalist-0.3.13}/app/usecases/create_sibling.py +0 -0
  355. {metalist-0.3.11 → metalist-0.3.13}/app/usecases/expand.py +0 -0
  356. {metalist-0.3.11 → metalist-0.3.13}/app/usecases/indent.py +0 -0
  357. {metalist-0.3.11 → metalist-0.3.13}/app/usecases/lock.py +0 -0
  358. {metalist-0.3.11 → metalist-0.3.13}/app/usecases/move.py +0 -0
  359. {metalist-0.3.11 → metalist-0.3.13}/app/usecases/move_to_top.py +0 -0
  360. {metalist-0.3.11 → metalist-0.3.13}/app/usecases/outdent.py +0 -0
  361. {metalist-0.3.11 → metalist-0.3.13}/app/usecases/paste_child.py +0 -0
  362. {metalist-0.3.11 → metalist-0.3.13}/app/usecases/paste_sibling.py +0 -0
  363. {metalist-0.3.11 → metalist-0.3.13}/app/usecases/prioritize.py +0 -0
  364. {metalist-0.3.11 → metalist-0.3.13}/app/usecases/redo.py +0 -0
  365. {metalist-0.3.11 → metalist-0.3.13}/app/usecases/reset_updated_at.py +0 -0
  366. {metalist-0.3.11 → metalist-0.3.13}/app/usecases/resize_image.py +0 -0
  367. {metalist-0.3.11 → metalist-0.3.13}/app/usecases/set_collapse_bulk.py +0 -0
  368. {metalist-0.3.11 → metalist-0.3.13}/app/usecases/toggle_reference_mode.py +0 -0
  369. {metalist-0.3.11 → metalist-0.3.13}/app/usecases/toggle_todo_done.py +0 -0
  370. {metalist-0.3.11 → metalist-0.3.13}/app/usecases/undo.py +0 -0
  371. {metalist-0.3.11 → metalist-0.3.13}/app/usecases/unformat_content.py +0 -0
  372. {metalist-0.3.11 → metalist-0.3.13}/app/utils/__init__.py +0 -0
  373. {metalist-0.3.11 → metalist-0.3.13}/app/utils/encryption.py +0 -0
  374. {metalist-0.3.11 → metalist-0.3.13}/app/utils/text_utils.py +0 -0
  375. {metalist-0.3.11 → metalist-0.3.13}/convert-from-legacy.py +0 -0
  376. {metalist-0.3.11 → metalist-0.3.13}/metalist.egg-info/dependency_links.txt +0 -0
  377. {metalist-0.3.11 → metalist-0.3.13}/metalist.egg-info/entry_points.txt +0 -0
  378. {metalist-0.3.11 → metalist-0.3.13}/metalist.egg-info/top_level.txt +0 -0
  379. {metalist-0.3.11 → metalist-0.3.13}/scripts/generate-lan-cert.sh +0 -0
  380. {metalist-0.3.11 → metalist-0.3.13}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: metalist
3
- Version: 0.3.11
3
+ Version: 0.3.13
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
@@ -10,18 +10,23 @@ Description-Content-Type: text/markdown
10
10
  Requires-Dist: argon2-cffi==25.1.0
11
11
  Requires-Dist: cryptography==50.0.0
12
12
  Requires-Dist: fastapi==0.141.1
13
+ Requires-Dist: httpcore==1.0.9
13
14
  Requires-Dist: httpx==0.28.1
14
15
  Requires-Dist: latex2mathml==3.81.0
15
16
  Requires-Dist: loguru==0.7.3
16
17
  Requires-Dist: Mako==1.3.12
17
18
  Requires-Dist: mutagen==1.48.1
19
+ Requires-Dist: nh3==0.3.6
20
+ Requires-Dist: pillow==12.3.0
18
21
  Requires-Dist: pydantic==2.13.4
22
+ Requires-Dist: python-dotenv==1.2.2
19
23
  Requires-Dist: python-multipart==0.0.32
20
24
  Requires-Dist: starlette==1.3.1
21
25
  Requires-Dist: tqdm==4.70.0
22
26
  Requires-Dist: tree-sitter==0.25.2
23
27
  Requires-Dist: tree-sitter-javascript==0.25.0
24
28
  Requires-Dist: uvicorn==0.52.0
29
+ Requires-Dist: zxcvbn==4.5.0
25
30
  Provides-Extra: dev
26
31
  Requires-Dist: hypothesis==6.164.0; extra == "dev"
27
32
  Requires-Dist: pytest==9.1.1; extra == "dev"
@@ -80,7 +85,7 @@ After the first installation, update and restart MetaList with one cross-platfor
80
85
  ```bash
81
86
  metalist update
82
87
  ```
83
- The updater stops running namespaces, hands off to an external PowerShell process on Windows or `/bin/sh` on macOS/Linux so the installed environment can unlock, runs the forced cache-refreshed uv update, and launches MetaList again.
88
+ 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 stops running namespaces, hands off to an external PowerShell process on Windows or `/bin/sh` on macOS/Linux so the installed environment can unlock, installs the exact version reported by PyPI with a forced cache refresh, launches MetaList again, and reports the installed version (for example, `MetaList updated to v0.3.13.`).
84
89
 
85
90
  For pip, users can run `pip install metalist`. For a non-editable local install from this checkout, use `uv pip install .` or `pip install .` instead of the editable command below.
86
91
 
@@ -99,8 +104,22 @@ metalist
99
104
  ```
100
105
  For source-checkout compatibility, `python main.py` performs the same orchestration. Use `metalist work`, `python main.py --namespace work`, or `python main.py work` when you want one foreground namespace process.
101
106
 
102
- `metalist` and explicit single-namespace source runs bind HTTP on `0.0.0.0:8000` by default, matching the old MetaList LAN-friendly behavior.
103
- On first startup, MetaList also auto-generates a self-signed TLS pair at `~/MetaList/certs/metalist-cert.pem` and `~/MetaList/certs/metalist-key.pem`, then enables HTTPS on `0.0.0.0:8443`. If you already have real PEM files, point `METALIST_TLS_CERT` and `METALIST_TLS_KEY` at them instead. Set `METALIST_AUTO_GENERATE_TLS=0` only if you explicitly want HTTP-only startup.
107
+ Shell execution is disabled by default. To enable `@shell` for every namespace
108
+ started by the top-level orchestrator, use either:
109
+
110
+ ```bash
111
+ metalist --enable-shell
112
+ python main.py --enable-shell
113
+ ```
114
+
115
+ This flag is propagated to every namespace child process. The top-level process
116
+ prints a conspicuous shell-enabled banner before its namespace launch results.
117
+ Use `python main.py work --enable-shell` for one foreground namespace. Shell
118
+ routes remain restricted to loopback clients using a loopback request host,
119
+ even when the rest of MetaList is intentionally exposed to a LAN.
120
+
121
+ `metalist` and explicit single-namespace source runs bind to loopback at `127.0.0.1:8000` by default. This keeps a normal laptop launch off LAN and public interfaces unless remote access is explicitly configured.
122
+ On first startup, MetaList also auto-generates a self-signed TLS pair at `~/MetaList/certs/metalist-cert.pem` and `~/MetaList/certs/metalist-key.pem`, then enables HTTPS on the same bind host at port `8443`. If you already have real PEM files, point `METALIST_TLS_CERT` and `METALIST_TLS_KEY` at them instead. Set `METALIST_AUTO_GENERATE_TLS=0` only if you explicitly want HTTP-only startup.
104
123
 
105
124
  Database selection:
106
125
  - No explicit namespace on a single-namespace launch: `~/MetaList/namespaces/default/default.metalist.db`
@@ -116,20 +135,36 @@ Useful env flags:
116
135
  - `CRASH_SERVER_ON_FAIL=1` (default): fail-fast on validation errors
117
136
  - `API_PREFIX=/api2`: override API prefix (client assumes `/api2` by default)
118
137
  - `METALIST_NAMESPACE=work`: select `~/MetaList/namespaces/work/work.metalist.db`
119
- - `METALIST_HOST=0.0.0.0` (default): bind the main app to a different interface such as `127.0.0.1`
138
+ - `METALIST_HOST=127.0.0.1` (default): bind the main app to a specific interface; use a LAN IP or `0.0.0.0` only for intentional remote access
139
+ - `METALIST_ALLOWED_HOSTS=notes.example.com,192.168.1.20`: comma-separated public/LAN hostnames accepted in HTTP `Host` headers; loopback aliases and a specific non-wildcard `METALIST_HOST` are accepted automatically
120
140
  - `METALIST_PORT=8000` (default): bind the main app to a different port
121
141
  - `METALIST_HTTPS_PORT=8443`: override the HTTPS port when TLS is enabled
122
142
  - `METALIST_TLS_CERT=/path/to/fullchain.pem` + `METALIST_TLS_KEY=/path/to/privkey.pem`: override TLS paths
123
143
  - `METALIST_AUTO_GENERATE_TLS=0`: disable automatic creation of the default self-signed TLS pair
124
144
  - default TLS paths: `~/MetaList/certs/metalist-cert.pem` and `~/MetaList/certs/metalist-key.pem`
125
145
  - `METALIST_FORWARDED_ALLOW_IPS=127.0.0.1,::1` (default): trust proxy headers only from those reverse-proxy IPs
146
+ - `--enable-shell`: opt in to local `@shell` execution for this launch; shell routes require a loopback client and loopback request host, and the capability is never persisted in namespace data
126
147
 
127
148
  ### Remote Access / HTTPS
128
- Plain LAN or VPN HTTP works with a normal PyCharm run:
149
+ LAN or VPN access must be enabled explicitly. Prefer binding the machine's specific LAN address, which also adds that address to the accepted-host set:
129
150
  ```bash
130
- metalist
151
+ METALIST_HOST=192.168.1.20 metalist
131
152
  ```
132
- On a fresh machine, that first launch also creates the default TLS cert pair automatically. Then open either `http://<laptop-ip>:8000` or `https://<laptop-ip>:8443` from the other machine.
153
+ On a fresh machine, that first launch also creates the default TLS cert pair automatically. Then open either `http://192.168.1.20:8000` or `https://192.168.1.20:8443` from the other machine.
154
+
155
+ To keep `@shell` available on the host laptop while allowing another laptop to
156
+ use normal MetaList features, bind both interfaces and explicitly allow the LAN
157
+ address:
158
+
159
+ ```bash
160
+ METALIST_HOST=0.0.0.0 \
161
+ METALIST_ALLOWED_HOSTS=10.0.0.31 \
162
+ metalist --enable-shell
163
+ ```
164
+
165
+ Use `http://127.0.0.1:<namespace-http-port>` on the host laptop when running
166
+ `@shell`. Other devices may use `https://10.0.0.31:<namespace-https-port>`, but
167
+ their shell start/status requests receive `403`.
133
168
 
134
169
  Namespaced launch example:
135
170
  ```bash
@@ -147,6 +182,7 @@ and MetaList will reuse the saved HTTP / HTTPS ports for `work`. The same applie
147
182
  Equivalent explicit launch, if you want it:
148
183
  ```bash
149
184
  METALIST_HOST=0.0.0.0 \
185
+ METALIST_ALLOWED_HOSTS=192.168.1.20 \
150
186
  METALIST_PORT=8000 \
151
187
  METALIST_HTTPS_PORT=8443 \
152
188
  metalist
@@ -156,6 +192,7 @@ From the other machine, open `https://<laptop-ip>:8443`.
156
192
  If you already have a real certificate and key, use the same dual-listener flow:
157
193
  ```bash
158
194
  METALIST_HOST=0.0.0.0 \
195
+ METALIST_ALLOWED_HOSTS=192.168.1.20 \
159
196
  METALIST_PORT=8000 \
160
197
  METALIST_HTTPS_PORT=8443 \
161
198
  METALIST_TLS_CERT=/path/to/fullchain.pem \
@@ -175,11 +212,17 @@ When HTTPS is enabled:
175
212
  If TLS is terminated by a reverse proxy on the same machine instead, keep MetaList on loopback and let the proxy forward to it:
176
213
  ```bash
177
214
  METALIST_HOST=127.0.0.1 \
215
+ METALIST_ALLOWED_HOSTS=notes.example.com \
178
216
  METALIST_PORT=8000 \
179
217
  METALIST_FORWARDED_ALLOW_IPS=127.0.0.1,::1 \
180
218
  metalist
181
219
  ```
182
220
 
221
+ The reverse proxy must preserve the browser-facing `Host` header and set
222
+ `X-Forwarded-Proto`. MetaList never trusts `X-Forwarded-Host`; forwarded
223
+ scheme/client metadata is accepted only from `METALIST_FORWARDED_ALLOW_IPS`.
224
+ Do not widen that list beyond the actual proxy addresses.
225
+
183
226
  ### Legacy Import
184
227
  `convert-from-legacy.py` replaces the SQLite database referenced by `app.config.DATABASE_URL`, clears its files/sounds sidecar, and imports notes from a legacy JSON export.
185
228
 
@@ -226,6 +269,18 @@ node --test tests/unit/*.mjs
226
269
  .venv/bin/python -c "from pathlib import Path; import main; main._run_startup_sanity_gates(repo_root=Path.cwd())"
227
270
  ```
228
271
 
272
+ Source-checkout development launches can enable the mandatory Python and
273
+ JavaScript sanity gates with an ignored repository-root `.env` file:
274
+
275
+ ```dotenv
276
+ METALIST_ENVIRONMENT=development
277
+ ```
278
+
279
+ `main.py` prints the resolved environment at startup. An explicit process
280
+ environment value takes precedence over `.env`; only `development` and
281
+ `production` are accepted. When the variable and `.env` file are absent,
282
+ MetaList runs in production mode and skips the source sanity gates.
283
+
229
284
  `TEST_MODE=1` and `POST /api2/test/reset` still exist for deterministic browser automation if we decide to add a new harness later, but Cypress is not part of the current workflow.
230
285
 
231
286
  ### Diagrams
@@ -51,7 +51,7 @@ After the first installation, update and restart MetaList with one cross-platfor
51
51
  ```bash
52
52
  metalist update
53
53
  ```
54
- The updater stops running namespaces, hands off to an external PowerShell process on Windows or `/bin/sh` on macOS/Linux so the installed environment can unlock, runs the forced cache-refreshed uv update, and launches MetaList again.
54
+ 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 stops running namespaces, hands off to an external PowerShell process on Windows or `/bin/sh` on macOS/Linux so the installed environment can unlock, installs the exact version reported by PyPI with a forced cache refresh, launches MetaList again, and reports the installed version (for example, `MetaList updated to v0.3.13.`).
55
55
 
56
56
  For pip, users can run `pip install metalist`. For a non-editable local install from this checkout, use `uv pip install .` or `pip install .` instead of the editable command below.
57
57
 
@@ -70,8 +70,22 @@ metalist
70
70
  ```
71
71
  For source-checkout compatibility, `python main.py` performs the same orchestration. Use `metalist work`, `python main.py --namespace work`, or `python main.py work` when you want one foreground namespace process.
72
72
 
73
- `metalist` and explicit single-namespace source runs bind HTTP on `0.0.0.0:8000` by default, matching the old MetaList LAN-friendly behavior.
74
- On first startup, MetaList also auto-generates a self-signed TLS pair at `~/MetaList/certs/metalist-cert.pem` and `~/MetaList/certs/metalist-key.pem`, then enables HTTPS on `0.0.0.0:8443`. If you already have real PEM files, point `METALIST_TLS_CERT` and `METALIST_TLS_KEY` at them instead. Set `METALIST_AUTO_GENERATE_TLS=0` only if you explicitly want HTTP-only startup.
73
+ Shell execution is disabled by default. To enable `@shell` for every namespace
74
+ started by the top-level orchestrator, use either:
75
+
76
+ ```bash
77
+ metalist --enable-shell
78
+ python main.py --enable-shell
79
+ ```
80
+
81
+ This flag is propagated to every namespace child process. The top-level process
82
+ prints a conspicuous shell-enabled banner before its namespace launch results.
83
+ Use `python main.py work --enable-shell` for one foreground namespace. Shell
84
+ routes remain restricted to loopback clients using a loopback request host,
85
+ even when the rest of MetaList is intentionally exposed to a LAN.
86
+
87
+ `metalist` and explicit single-namespace source runs bind to loopback at `127.0.0.1:8000` by default. This keeps a normal laptop launch off LAN and public interfaces unless remote access is explicitly configured.
88
+ On first startup, MetaList also auto-generates a self-signed TLS pair at `~/MetaList/certs/metalist-cert.pem` and `~/MetaList/certs/metalist-key.pem`, then enables HTTPS on the same bind host at port `8443`. If you already have real PEM files, point `METALIST_TLS_CERT` and `METALIST_TLS_KEY` at them instead. Set `METALIST_AUTO_GENERATE_TLS=0` only if you explicitly want HTTP-only startup.
75
89
 
76
90
  Database selection:
77
91
  - No explicit namespace on a single-namespace launch: `~/MetaList/namespaces/default/default.metalist.db`
@@ -87,20 +101,36 @@ Useful env flags:
87
101
  - `CRASH_SERVER_ON_FAIL=1` (default): fail-fast on validation errors
88
102
  - `API_PREFIX=/api2`: override API prefix (client assumes `/api2` by default)
89
103
  - `METALIST_NAMESPACE=work`: select `~/MetaList/namespaces/work/work.metalist.db`
90
- - `METALIST_HOST=0.0.0.0` (default): bind the main app to a different interface such as `127.0.0.1`
104
+ - `METALIST_HOST=127.0.0.1` (default): bind the main app to a specific interface; use a LAN IP or `0.0.0.0` only for intentional remote access
105
+ - `METALIST_ALLOWED_HOSTS=notes.example.com,192.168.1.20`: comma-separated public/LAN hostnames accepted in HTTP `Host` headers; loopback aliases and a specific non-wildcard `METALIST_HOST` are accepted automatically
91
106
  - `METALIST_PORT=8000` (default): bind the main app to a different port
92
107
  - `METALIST_HTTPS_PORT=8443`: override the HTTPS port when TLS is enabled
93
108
  - `METALIST_TLS_CERT=/path/to/fullchain.pem` + `METALIST_TLS_KEY=/path/to/privkey.pem`: override TLS paths
94
109
  - `METALIST_AUTO_GENERATE_TLS=0`: disable automatic creation of the default self-signed TLS pair
95
110
  - default TLS paths: `~/MetaList/certs/metalist-cert.pem` and `~/MetaList/certs/metalist-key.pem`
96
111
  - `METALIST_FORWARDED_ALLOW_IPS=127.0.0.1,::1` (default): trust proxy headers only from those reverse-proxy IPs
112
+ - `--enable-shell`: opt in to local `@shell` execution for this launch; shell routes require a loopback client and loopback request host, and the capability is never persisted in namespace data
97
113
 
98
114
  ### Remote Access / HTTPS
99
- Plain LAN or VPN HTTP works with a normal PyCharm run:
115
+ LAN or VPN access must be enabled explicitly. Prefer binding the machine's specific LAN address, which also adds that address to the accepted-host set:
100
116
  ```bash
101
- metalist
117
+ METALIST_HOST=192.168.1.20 metalist
102
118
  ```
103
- On a fresh machine, that first launch also creates the default TLS cert pair automatically. Then open either `http://<laptop-ip>:8000` or `https://<laptop-ip>:8443` from the other machine.
119
+ On a fresh machine, that first launch also creates the default TLS cert pair automatically. Then open either `http://192.168.1.20:8000` or `https://192.168.1.20:8443` from the other machine.
120
+
121
+ To keep `@shell` available on the host laptop while allowing another laptop to
122
+ use normal MetaList features, bind both interfaces and explicitly allow the LAN
123
+ address:
124
+
125
+ ```bash
126
+ METALIST_HOST=0.0.0.0 \
127
+ METALIST_ALLOWED_HOSTS=10.0.0.31 \
128
+ metalist --enable-shell
129
+ ```
130
+
131
+ Use `http://127.0.0.1:<namespace-http-port>` on the host laptop when running
132
+ `@shell`. Other devices may use `https://10.0.0.31:<namespace-https-port>`, but
133
+ their shell start/status requests receive `403`.
104
134
 
105
135
  Namespaced launch example:
106
136
  ```bash
@@ -118,6 +148,7 @@ and MetaList will reuse the saved HTTP / HTTPS ports for `work`. The same applie
118
148
  Equivalent explicit launch, if you want it:
119
149
  ```bash
120
150
  METALIST_HOST=0.0.0.0 \
151
+ METALIST_ALLOWED_HOSTS=192.168.1.20 \
121
152
  METALIST_PORT=8000 \
122
153
  METALIST_HTTPS_PORT=8443 \
123
154
  metalist
@@ -127,6 +158,7 @@ From the other machine, open `https://<laptop-ip>:8443`.
127
158
  If you already have a real certificate and key, use the same dual-listener flow:
128
159
  ```bash
129
160
  METALIST_HOST=0.0.0.0 \
161
+ METALIST_ALLOWED_HOSTS=192.168.1.20 \
130
162
  METALIST_PORT=8000 \
131
163
  METALIST_HTTPS_PORT=8443 \
132
164
  METALIST_TLS_CERT=/path/to/fullchain.pem \
@@ -146,11 +178,17 @@ When HTTPS is enabled:
146
178
  If TLS is terminated by a reverse proxy on the same machine instead, keep MetaList on loopback and let the proxy forward to it:
147
179
  ```bash
148
180
  METALIST_HOST=127.0.0.1 \
181
+ METALIST_ALLOWED_HOSTS=notes.example.com \
149
182
  METALIST_PORT=8000 \
150
183
  METALIST_FORWARDED_ALLOW_IPS=127.0.0.1,::1 \
151
184
  metalist
152
185
  ```
153
186
 
187
+ The reverse proxy must preserve the browser-facing `Host` header and set
188
+ `X-Forwarded-Proto`. MetaList never trusts `X-Forwarded-Host`; forwarded
189
+ scheme/client metadata is accepted only from `METALIST_FORWARDED_ALLOW_IPS`.
190
+ Do not widen that list beyond the actual proxy addresses.
191
+
154
192
  ### Legacy Import
155
193
  `convert-from-legacy.py` replaces the SQLite database referenced by `app.config.DATABASE_URL`, clears its files/sounds sidecar, and imports notes from a legacy JSON export.
156
194
 
@@ -197,6 +235,18 @@ node --test tests/unit/*.mjs
197
235
  .venv/bin/python -c "from pathlib import Path; import main; main._run_startup_sanity_gates(repo_root=Path.cwd())"
198
236
  ```
199
237
 
238
+ Source-checkout development launches can enable the mandatory Python and
239
+ JavaScript sanity gates with an ignored repository-root `.env` file:
240
+
241
+ ```dotenv
242
+ METALIST_ENVIRONMENT=development
243
+ ```
244
+
245
+ `main.py` prints the resolved environment at startup. An explicit process
246
+ environment value takes precedence over `.env`; only `development` and
247
+ `production` are accepted. When the variable and `.env` file are absent,
248
+ MetaList runs in production mode and skips the source sanity gates.
249
+
200
250
  `TEST_MODE=1` and `POST /api2/test/reset` still exist for deterministic browser automation if we decide to add a new harness later, but Cypress is not part of the current workflow.
201
251
 
202
252
  ### Diagrams
@@ -7,30 +7,34 @@ from app.api.request_auth import read_request_auth_token
7
7
  from app.services.tokens import token_service
8
8
  from app.services.auth_service import AuthService
9
9
  from app.services.maintenance_mode import maintenance_service
10
- from app.services.runtime_lock import purge_decrypted_runtime_state
11
10
  from app.models.database import SafeSession
12
11
  from app.config import API_PREFIX, TEST_MODE
13
12
 
14
13
 
15
14
  class AuthMiddleware(BaseHTTPMiddleware):
16
15
  """Middleware to check authentication on protected routes."""
17
-
18
- # Paths that don't require authentication
19
- PUBLIC_PATHS = [
16
+
17
+ PUBLIC_EXACT_PATHS = frozenset({
18
+ "/",
20
19
  f"{API_PREFIX}/auth/login",
20
+ f"{API_PREFIX}/auth/login-namespaces",
21
+ f"{API_PREFIX}/auth/login-namespaces/open",
21
22
  f"{API_PREFIX}/auth/status",
22
23
  f"{API_PREFIX}/auth/session",
23
- f"{API_PREFIX}/auth/namespaces/delete-jobs/",
24
- f"{API_PREFIX}/auth/namespaces/rename-jobs/",
25
- "/namespace-deleted",
26
- "/namespace-renamed",
27
- "/static/", # CSS/JS files needed for login page
28
24
  "/favicon.ico",
29
25
  "/locked",
30
- ]
26
+ "/namespace-deleted",
27
+ "/namespace-deleted/open",
28
+ "/namespace-renamed",
29
+ "/namespace-renamed/open",
30
+ } | ({f"{API_PREFIX}/test/reset"} if TEST_MODE else set()))
31
31
 
32
- if TEST_MODE:
33
- PUBLIC_PATHS.append(f"{API_PREFIX}/test/reset")
32
+ PUBLIC_PREFIX_PATHS = (
33
+ f"{API_PREFIX}/auth/namespaces/delete-jobs/",
34
+ f"{API_PREFIX}/auth/namespaces/rename-jobs/",
35
+ "/static/", # CSS/JS files needed for login page
36
+ )
37
+ assert all(path.endswith("/") for path in PUBLIC_PREFIX_PATHS)
34
38
 
35
39
  # Paths to suppress verbose logging for (frequent polling endpoints)
36
40
  QUIET_PATHS = [
@@ -44,14 +48,19 @@ class AuthMiddleware(BaseHTTPMiddleware):
44
48
  ]
45
49
 
46
50
  # Note: /api/notes/* paths are NOT in this list - they require auth when password is set
51
+
52
+ @classmethod
53
+ def is_public_path(cls, *, path: str) -> bool:
54
+ if not isinstance(path, str) or not path.startswith("/"):
55
+ raise TypeError("path must be an absolute URL path")
56
+ if path in cls.PUBLIC_EXACT_PATHS:
57
+ return True
58
+ return any(path.startswith(prefix) for prefix in cls.PUBLIC_PREFIX_PATHS)
47
59
 
48
60
  async def dispatch(self, request: Request, call_next):
49
61
  """Check authentication for protected routes."""
50
62
  path = request.url.path
51
63
 
52
- if not token_service.has_active_tokens():
53
- purge_decrypted_runtime_state()
54
-
55
64
  # Block any v1 API usage with an explicit 410 Gone (no DB access)
56
65
  if path.startswith('/api') and not (path.startswith(API_PREFIX) or path == API_PREFIX):
57
66
  ref = request.headers.get('referer', '-')
@@ -74,22 +83,9 @@ class AuthMiddleware(BaseHTTPMiddleware):
74
83
  if not is_quiet:
75
84
  print(f"Middleware checking path: {path}")
76
85
 
77
- # Skip authentication for public paths
78
- public_match = None
79
-
80
- # Handle exact root path match
81
- if path == "/":
82
- public_match = "/ (root)"
83
- else:
84
- # Check other public paths with startswith
85
- for public in self.PUBLIC_PATHS:
86
- if path.startswith(public):
87
- public_match = public
88
- break
89
-
90
- if public_match:
86
+ if self.is_public_path(path=path):
91
87
  if not is_quiet:
92
- print(f"Path {path} is public (matched '{public_match}'), skipping auth")
88
+ print(f"Path {path} is explicitly public, skipping auth")
93
89
  return await call_next(request)
94
90
 
95
91
  if not is_quiet:
@@ -2,8 +2,19 @@ from __future__ import annotations
2
2
 
3
3
  from fastapi import HTTPException, Request, Response
4
4
 
5
+ from app.config import ACTIVE_NAMESPACE
6
+ from app.server_runtime import validate_namespace
5
7
 
6
- AUTH_COOKIE_NAME = "metalist_auth"
8
+
9
+ AUTH_COOKIE_PREFIX = "metalist_auth"
10
+
11
+
12
+ def auth_cookie_name_for_namespace(namespace: str) -> str:
13
+ normalized_namespace = validate_namespace(namespace=namespace)
14
+ return f"{AUTH_COOKIE_PREFIX}_{normalized_namespace}"
15
+
16
+
17
+ AUTH_COOKIE_NAME = auth_cookie_name_for_namespace(ACTIVE_NAMESPACE)
7
18
 
8
19
 
9
20
  def read_request_auth_token(request: Request) -> tuple[str | None, str | None]: