@tiddlywiki/mws 0.0.21 → 0.1.1

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 (202) hide show
  1. package/README.md +42 -9
  2. package/dist/metafile-esm.json +1 -0
  3. package/dist/mws.d.ts +1 -0
  4. package/dist/mws.js +34710 -0
  5. package/dist/mws.js.map +1 -0
  6. package/editions/mws-docs/tiddlers/$__StoryList.tid +1 -2
  7. package/editions/mws-docs/tiddlers/2025-02-18 - User Management.md.meta +2 -2
  8. package/editions/mws-docs/tiddlers/2025-04-14 - client plugins /342/234/224/357/270/217.md" +31 -0
  9. package/editions/mws-docs/tiddlers/2025-04-14 - client plugins /342/234/224/357/270/217.md.meta" +5 -0
  10. package/editions/mws-docs/tiddlers/{2025-05-04.md → 2025-05-04 - event hooks /342/234/224/357/270/217.md" } +7 -1
  11. package/editions/mws-docs/tiddlers/2025-05-04 - event hooks /342/234/224/357/270/217.md.meta" +5 -0
  12. package/editions/mws-docs/tiddlers/{2025-05-06.md → 2025-05-06 - syncer design.md } +0 -4
  13. package/editions/mws-docs/tiddlers/2025-05-06 - syncer design.md.meta +5 -0
  14. package/editions/mws-docs/tiddlers/Allowed Methods.tid +8 -0
  15. package/editions/mws-docs/tiddlers/Application Access & Security.md +14 -84
  16. package/editions/mws-docs/tiddlers/Application Access & Security.md.meta +1 -1
  17. package/editions/mws-docs/tiddlers/Body Format.md +19 -0
  18. package/editions/mws-docs/tiddlers/Body Format.md.meta +4 -0
  19. package/editions/mws-docs/tiddlers/Checklists and Features.md +0 -3
  20. package/editions/mws-docs/tiddlers/Checklists and Features.md.meta +1 -1
  21. package/editions/mws-docs/tiddlers/Client Plugins.md +17 -0
  22. package/editions/mws-docs/tiddlers/Client Plugins.md.meta +5 -0
  23. package/editions/mws-docs/tiddlers/HTTP API.md +4 -3
  24. package/editions/mws-docs/tiddlers/HTTP API.md.meta +1 -1
  25. package/editions/mws-docs/tiddlers/HelloThere.tid +2 -2
  26. package/editions/mws-docs/tiddlers/Installation.tid +2 -3
  27. package/editions/mws-docs/tiddlers/MWS Architecture.tid +6 -1
  28. package/editions/mws-docs/tiddlers/Multi-user Trust.md +12 -0
  29. package/editions/mws-docs/tiddlers/Multi-user Trust.md.meta +5 -0
  30. package/editions/mws-docs/tiddlers/Notes.tid +5 -3
  31. package/editions/mws-docs/tiddlers/Oracle Attacks.md +29 -0
  32. package/editions/mws-docs/tiddlers/Oracle Attacks.md.meta +5 -0
  33. package/editions/mws-docs/tiddlers/Reference.md +1 -0
  34. package/editions/mws-docs/tiddlers/Reference.md.meta +1 -1
  35. package/editions/mws-docs/tiddlers/Request Handling.md +53 -0
  36. package/editions/mws-docs/tiddlers/Request Handling.md.meta +5 -0
  37. package/editions/mws-docs/tiddlers/Roadmap.tid +7 -0
  38. package/editions/mws-docs/tiddlers/Route Definers.md +206 -0
  39. package/editions/mws-docs/tiddlers/Route Definers.md.meta +5 -0
  40. package/editions/mws-docs/tiddlers/Security.md +75 -0
  41. package/editions/mws-docs/tiddlers/Security.md.meta +5 -0
  42. package/editions/mws-docs/tiddlers/Server Plugins.md +7 -0
  43. package/editions/mws-docs/tiddlers/Server Plugins.md.meta +5 -0
  44. package/editions/mws-docs/tiddlers/Startup Cache.md +28 -0
  45. package/editions/mws-docs/tiddlers/Startup Cache.md.meta +5 -0
  46. package/editions/mws-docs/tiddlers/TiddlerFields.md +5 -0
  47. package/editions/mws-docs/tiddlers/TiddlerFields.md.meta +4 -0
  48. package/editions/mws-docs/tiddlers/Usage.tid +2 -2
  49. package/editions/mws-docs/tiddlers/system/$__mws_cssvar-macro.tid +10 -0
  50. package/editions/mws-docs/tiddlers/system/$__palettes_MUI +143 -0
  51. package/editions/mws-docs/tiddlers/system/$__palettes_MUI.meta +7 -0
  52. package/editions/mws-docs/tiddlers/system/$__palettes_MUI_styles.css +567 -0
  53. package/editions/mws-docs/tiddlers/system/$__palettes_MUI_styles.css.meta +6 -0
  54. package/editions/mws-docs/tiddlers/system/$__theme.tid +6 -0
  55. package/editions/mws-docs/tiddlers/system/SplashScreen.tid +21 -0
  56. package/editions/mws-docs/tiddlers/system/StaticBanner.tid +1 -1
  57. package/editions/mws-docs/tiddlers/system/Styles.tid +13 -0
  58. package/editions/mws-docs/tiddlers/system/palette.tid +4 -1
  59. package/editions/mws-docs/tiddlers/system/sidebarlayout.tid +4 -1
  60. package/editions/mws-docs/tiddlers/x-mws-tiddler.md +35 -0
  61. package/editions/mws-docs/tiddlers/x-mws-tiddler.md.meta +5 -0
  62. package/mws.run.mjs +30 -0
  63. package/package.json +47 -36
  64. package/plugins/client/package-lock.json +46 -83
  65. package/plugins/client/package.json +1 -6
  66. package/plugins/client/plugin.info +2 -2
  67. package/plugins/client/src/fflate.d.ts +1501 -0
  68. package/plugins/client/src/multiwikiclientadaptor.ts +768 -317
  69. package/plugins/client/src/mws.d.ts +4 -0
  70. package/plugins/client/src/types.d.ts +3928 -0
  71. package/plugins/client/tiddlers/en-US.multids +3 -0
  72. package/plugins/client/tiddlers/status/SaveWikiButtonTemplate.tid +3 -0
  73. package/plugins/client/tiddlers/status/icon-cloud.tid +4 -0
  74. package/plugins/client/tiddlers/status/info-segment.tid +8 -0
  75. package/plugins/client/tiddlers/status/readonly-styles.tid +27 -0
  76. package/plugins/client/tiddlers/status/save-offline.tid +7 -0
  77. package/plugins/client/tiddlers/status/save-wiki-button.tid +26 -0
  78. package/plugins/client/tiddlers/status/styles.tid +44 -0
  79. package/plugins/client/tiddlers/status/syncer-actions-copy-logs.tid +6 -0
  80. package/plugins/client/tiddlers/status/syncer-actions-login-status.tid +9 -0
  81. package/plugins/client/tiddlers/status/syncer-actions-login.tid +8 -0
  82. package/plugins/client/tiddlers/status/syncer-actions-logout.tid +8 -0
  83. package/plugins/client/tiddlers/status/syncer-actions-refresh.tid +9 -0
  84. package/plugins/client/tiddlers/status/syncer-actions-save-snapshot.tid +9 -0
  85. package/plugins/client/tiddlers/status/tags-syncerdropdown.tid +2 -0
  86. package/plugins/client/tiddlers/syncer/multiwikiclientadaptor.js +640 -0
  87. package/plugins/client/tiddlers/syncer/syncer.js +831 -0
  88. package/plugins/client/tsconfig.json +19 -16
  89. package/plugins/filter-ast-to-sql/example-run-series.ts +146 -0
  90. package/plugins/server/SplashScreen.tid +150 -0
  91. package/plugins/server/fflate.js +9 -0
  92. package/plugins/server/plugin.info +8 -0
  93. package/plugins/server/readme +1 -0
  94. package/plugins/server/url-polyfill.js +294 -0
  95. package/prisma/client/client.d.ts +1 -0
  96. package/prisma/client/client.js +3 -0
  97. package/prisma/client/default.d.ts +1 -0
  98. package/prisma/client/default.js +3 -0
  99. package/prisma/client/edge.d.ts +1 -0
  100. package/prisma/client/edge.js +297 -0
  101. package/prisma/client/index-browser.js +275 -0
  102. package/prisma/client/index.d.ts +17770 -0
  103. package/prisma/client/index.js +324 -0
  104. package/prisma/client/package.json +173 -0
  105. package/prisma/client/query_engine_bg.js +811 -0
  106. package/prisma/client/query_engine_bg.wasm +0 -0
  107. package/prisma/client/runtime/edge-esm.js +10000 -0
  108. package/prisma/client/runtime/edge.js +10036 -0
  109. package/prisma/client/runtime/index-browser.d.ts +370 -0
  110. package/prisma/client/runtime/index-browser.js +2300 -0
  111. package/prisma/client/runtime/library.d.ts +3681 -0
  112. package/prisma/client/runtime/library.js +10604 -0
  113. package/prisma/client/runtime/react-native.js +10629 -0
  114. package/prisma/client/runtime/wasm-compiler-edge.js +11238 -0
  115. package/prisma/client/runtime/wasm-engine-edge.js +7801 -0
  116. package/prisma/client/schema.prisma +156 -0
  117. package/prisma/client/wasm-edge-light-loader.mjs +4 -0
  118. package/prisma/client/wasm-worker-loader.mjs +4 -0
  119. package/prisma/client/wasm.d.ts +1 -0
  120. package/prisma/client/wasm.js +304 -0
  121. package/prisma/global.ts +53 -0
  122. package/prisma/migrations/{20250406213424_init → 20250606001949_init}/migration.sql +46 -48
  123. package/prisma/migrations/20250613000526_remove_group/migration.sql +22 -0
  124. package/prisma/migrations/20250620014502_settings/migration.sql +5 -0
  125. package/prisma/migrations/20250707205229_recipes/migration.sql +20 -0
  126. package/prisma/migrations/migration_lock.toml +1 -1
  127. package/prisma/notes.md +1 -2
  128. package/prisma/schema.prisma +52 -49
  129. package/prisma/test.sqlite +0 -0
  130. package/prisma/test.sqlite-journal +0 -0
  131. package/public/react-admin/android-chrome-192x192.png +0 -0
  132. package/public/react-admin/android-chrome-512x512.png +0 -0
  133. package/public/react-admin/apple-touch-icon.png +0 -0
  134. package/{react-user-mgmt/public/esm-QKDFEP3B.js → public/react-admin/esm-L4WLVWJN.js} +1 -1
  135. package/public/react-admin/esm-L4WLVWJN.js.map +7 -0
  136. package/public/react-admin/esm-QMNGI3LF.js +3 -0
  137. package/public/react-admin/favicon-16x16.png +0 -0
  138. package/public/react-admin/favicon-32x32.png +0 -0
  139. package/public/react-admin/favicon.ico +0 -0
  140. package/public/react-admin/index.html +36 -0
  141. package/public/react-admin/main.js +268 -0
  142. package/public/react-admin/main.js.map +7 -0
  143. package/public/react-admin/site.webmanifest +20 -0
  144. package/public/react-admin/stats.json +1 -0
  145. package/scripts.mjs +134 -25
  146. package/dist/server.d.ts +0 -945
  147. package/dist/server.js +0 -20775
  148. package/dist/server.js.map +0 -1
  149. package/editions/mws-docs/tiddlers/2025-04-03 - Phases of Development.md +0 -64
  150. package/editions/mws-docs/tiddlers/2025-04-03 - Phases of Development.md.meta +0 -5
  151. package/editions/mws-docs/tiddlers/2025-04-13 - Plugins.md +0 -18
  152. package/editions/mws-docs/tiddlers/2025-04-13 - Plugins.md.meta +0 -5
  153. package/editions/mws-docs/tiddlers/2025-05-04.md.meta +0 -5
  154. package/editions/mws-docs/tiddlers/2025-05-06.md.meta +0 -5
  155. package/editions/mws-docs/tiddlers/Moduler Design.md +0 -29
  156. package/editions/mws-docs/tiddlers/Moduler Design.md.meta +0 -5
  157. package/editions/mws-docs/tiddlers/Request Server.md +0 -20
  158. package/editions/mws-docs/tiddlers/Request Server.md.meta +0 -5
  159. package/editions/mws-docs/tiddlers/system/$__palettes_MUI-Dark +0 -173
  160. package/editions/mws-docs/tiddlers/system/$__palettes_MUI-Dark.meta +0 -6
  161. package/editions/mws-docs/tiddlers/system/$__palettes_MUI-Light +0 -172
  162. package/editions/mws-docs/tiddlers/system/$__palettes_MUI-Light.meta +0 -6
  163. package/plugins/client/tiddlers/config-tiddlers-filter.tid +0 -2
  164. package/plugins/client/tiddlers/config-use-server-sent-events.tid +0 -2
  165. package/plugins/client/tiddlers/info-segment.tid +0 -8
  166. package/plugins/client/tiddlers/multiwikiclientadaptor.js +0 -444
  167. package/prisma/migrations/20250407002306_disconnect_user_tables/migration.sql +0 -52
  168. package/prisma/old-db.sql +0 -144
  169. package/react-user-mgmt/README.md +0 -50
  170. package/react-user-mgmt/eslint.config.js +0 -28
  171. package/react-user-mgmt/package-lock.json +0 -2738
  172. package/react-user-mgmt/package.json +0 -31
  173. package/react-user-mgmt/public/index.html +0 -1
  174. package/react-user-mgmt/public/main.js +0 -295
  175. package/react-user-mgmt/public/main.js.map +0 -7
  176. package/react-user-mgmt/public/stats.json +0 -1
  177. package/react-user-mgmt/tsconfig.json +0 -40
  178. package/react-user-mgmt/types.d.ts +0 -2
  179. package/tiddlywiki-types/boot/boot.d.ts +0 -378
  180. package/tiddlywiki-types/boot/bootprefix.d.ts +0 -110
  181. package/tiddlywiki-types/core/modules/filters.d.ts +0 -107
  182. package/tiddlywiki-types/core/modules/tiddler.d.ts +0 -47
  183. package/tiddlywiki-types/core/modules/wiki-bulkops.d.ts +0 -36
  184. package/tiddlywiki-types/core/modules/wiki.d.ts +0 -208
  185. package/tiddlywiki-types/index.d.ts +0 -7
  186. package/tiddlywiki-types/package.json +0 -3
  187. /package/plugins/client/tiddlers/{sidebarsegment.tid → status/sidebarsegment.tid} +0 -0
  188. /package/plugins/client/tiddlers/{GettingStarted.tid → syncer/GettingStarted.tid} +0 -0
  189. /package/plugins/client/tiddlers/{config-incoming-updates-filter.tid → syncer/config-incoming-updates-filter.tid} +0 -0
  190. /package/plugins/client/tiddlers/{readme.tid → syncer/readme.tid} +0 -0
  191. /package/{react-user-mgmt/public → public/react-admin}/chunk-YALWN5OT.js +0 -0
  192. /package/{react-user-mgmt/public → public/react-admin}/chunk-YALWN5OT.js.map +0 -0
  193. /package/{react-user-mgmt/public/esm-QKDFEP3B.js.map → public/react-admin/esm-QMNGI3LF.js.map} +0 -0
  194. /package/{react-user-mgmt/public → public/react-admin}/favicon.png +0 -0
  195. /package/{react-user-mgmt/public → public/react-admin}/missing-favicon.png +0 -0
  196. /package/{react-user-mgmt/public → public/react-admin}/motovun-jack.jpg +0 -0
  197. /package/{react-user-mgmt/public → public/react-admin}/mws-icon.png +0 -0
  198. /package/{react-user-mgmt/public → public/react-admin}/stats.css +0 -0
  199. /package/{react-user-mgmt/public → public/react-admin}/stats.html +0 -0
  200. /package/{react-user-mgmt/public → public/react-admin}/stats.js +0 -0
  201. /package/{react-user-mgmt/public → public/react-admin}/stats.svg +0 -0
  202. /package/{react-user-mgmt/public → public/react-admin}/vite.svg +0 -0
@@ -1,3 +1,2 @@
1
1
  list: HelloThere Installation Usage Reference
2
- title: $:/StoryList
3
- type: text/vnd.tiddlywiki
2
+ title: $:/StoryList
@@ -1,5 +1,5 @@
1
1
  created: 20250507122308262
2
- modified: 20250507123125166
3
- tags: Notes
2
+ modified: 20250624124256654
3
+ tags: Notes Roadmap
4
4
  title: 2025-02-18 - User Management
5
5
  type: text/markdown
@@ -0,0 +1,31 @@
1
+ Currently we're adding recipe tiddlers into the wiki page dynamically, which is expected, but there are like six tiddlers that are being rendered statically, which doesn't really make sense. It also doesn't make sense that we're dumping some plugins into the database but rendering core from tiddlywiki, since this results in a version mismatch.
2
+
3
+ At the same time, we really don't want to be rendering plugins every time. They do need to be cached somewhere so they can be loaded quickly. I wonder if it would work to cache them in the wiki folder, per tiddlywiki version, so if you upgrade it would just create a new folder. The boot tiddlers would be cached in the folder as well. If we do it right, we wouldn't even have to parse the file, just read it onto the wire. We'd probably need an index file to keep everything straight. We could add plugins/themes/languages support to the wiki folder as well, which would also get cached in the same way. We could make a way for caching to be disabled, perhaps by adding a field to `plugin.info`.
4
+
5
+ It would be useful if the plugin syntax could specify NPM modules. We already have the `+` and `++` syntax. I'm not sure exactly how it'd work, but the NPM package would need to determine it's own path, which is fairly simple, and then export that so it can be imported via the standard import mechanism. Obviously the package would need to be installed, and it should probably be imported into the run file and then added as an absolute path to the list of imports. Actually, I guess that's already possible, so I just need to add the list of imports part of it.
6
+
7
+ ----
8
+
9
+ ### Add a tiddler cache folder and render the tiddlers on startup
10
+
11
+ - Store them either in-memory or in the file-system, depending on user preference.
12
+ - The core tiddler and boot tiddlers could be stored in memory regardless because they are always served.
13
+ - Would it save some memory to store them as a buffer?
14
+ - The stored content would be read directly onto the wire, optionally checking the hash.
15
+
16
+ ### Add a plugin selector to the recipes form
17
+
18
+ - The loading order needs to be changeable.
19
+ - It would just be an array of titles, and possibly other describing fields.
20
+
21
+ ### Add a plugin field to the recipes table
22
+
23
+ - Not sure if I need to create a plugins table but I probably just need a string array of plugin names. Titles tend to be authoritative in TiddlyWiki so the plugin title should be enough. Plugin titles which cannot be found would be somehow marked as not found, probably with a custom disabled plugin tiddler in the client and logging a warning in the server.
24
+
25
+ ### What about SQL Filters?
26
+
27
+ - I don't know, but we would be caching plugins either way. Everything about it is handled differently, so no matter what, there is almost guaranteed to be a clear separation between the two kinds of bags anyway. We'll worry about that when we get there.
28
+
29
+ ## Retrospective - 2025-06-24
30
+
31
+ I ended up caching it according to the file path. The tiddlywiki file path works fine for those plugins. Third-party plugins will need to declare their own folder name somehow. The files are compressed and stored on disk. The cache is built on startup. The cache stores a `json`, `js`, and `js.gz` version of each plugin.
@@ -0,0 +1,5 @@
1
+ created: 20250624124545657
2
+ modified: 20250624130605815
3
+ tags: Roadmap
4
+ title: 2025-04-14 - client plugins ✔️
5
+ type: text/markdown
@@ -10,4 +10,10 @@ I probably need a startup state object, which basically has the site config and
10
10
 
11
11
  I guess this is actually a significant rewrite, so once I get some of the initial pieces done, it should be more obvious.
12
12
 
13
- -- Arlen22
13
+ -- Arlen22
14
+
15
+ ## Retrospective - 2025-06-24
16
+
17
+ It was a significant rewrite. I separated MWS into three packages, one package for the events, one package for generic web server stuff, and one package for all the MWS logic. Getting config from the database is pretty simple. We do it on startup and then if a setting can be changed live, we just update the config property. For those settings, we store the value in the request state to make sure each request uses the same setting for the duration of the request.
18
+
19
+ The only downside is that we have to make sure we import all the files that use the server events, but that's a small price to pay for the much higher flexibility. I'm sure there's a lint rule we could create somehow, but I haven't gotten to that yet.
@@ -0,0 +1,5 @@
1
+ created: 20250507122508552
2
+ modified: 20250624130052652
3
+ tags: Notes Roadmap
4
+ title: 2025-05-04 - event hooks ✔️
5
+ type: text/markdown
@@ -12,8 +12,4 @@ There also isn't a good way to move tiddlers between levels. Admins will need to
12
12
 
13
13
  I'm not good at wikitext, but I can provide the endpoints for all of these operations as well as the client-side adapters and actions to use them.
14
14
 
15
- I also don't know why we aren't using the wiki mount point for the API, and putting the react UI under admin, since then it would free up the entire path space to use for a tree path structure.
16
-
17
- I'm working on simplifying the internal code structure yet again, still focusing on getting everything up to speed with my latest ideas.
18
-
19
15
  -- Arlen22
@@ -0,0 +1,5 @@
1
+ created: 20250507031006573
2
+ modified: 20250624130310879
3
+ tags: Notes Roadmap
4
+ title: 2025-05-06 - syncer design
5
+ type: text/markdown
@@ -0,0 +1,8 @@
1
+ created: 20250513222435866
2
+ modified: 20250513222701838
3
+ title: Allowed Methods
4
+ type: text/vnd.tiddlywiki
5
+
6
+ `OPTIONS, GET, HEAD, POST, PUT, DELETE`
7
+
8
+ HTTP allows any methods so I have no idea why I should only allow these. We could really go all out.
@@ -1,98 +1,28 @@
1
1
 
2
- Users can be administered through two interfaces:
3
-
4
- 1. Web-based Administrative Interface
5
- - Accessible to all users.
6
- - Provides graphical interface for user operations
7
- - Real-time validation and feedback
8
- 1. Command-line Interface (CLI) Tools
9
- - Only available to server owner.
10
- - Suitable for automation and scripting
11
- - Enables batch operations
12
- - Useful for system initialization
13
-
14
- Each user account contains the following essential components:
15
-
16
- - **Username**
17
- - Must be unique across the system
18
- - Case-sensitive
19
- - Used for authentication and audit trails
20
- - **Password**
21
- - Stored using secure hashing algorithms
22
- - Never stored in plaintext
23
- - Subject to complexity requirements
24
- - **Email**
25
- - Eventually used for the obvious password reset.
26
- - **Role Assignments**
27
- - Multiple roles can be assigned
28
- - Inherited permissions from all assigned roles
29
- - Dynamic permission calculation based on role combination
30
-
31
- ## Access Levels
32
-
33
- Conceptually, there are 6 access levels.
2
+ ## Permissions
34
3
 
35
- - **Site owner** - has file system access to the server, and can run CLI commands. Presumably they also have a site admin account.
36
- - **Site admin** - Users with the admin *role*. They can assign owners and change permissions, and have full read and write access. Most ACL checks are skipped for the admin role.
37
- - **Entity owner** - Users who "own" an entity (bag or recipe). They can change permissions for that entity, and have full read and write access. *Entity admins* cannot change the owner.
38
- - **Entity admin** - Users granted the admin *permission* on an entity. They cannot change the owner, but they can change the permissions of other users for that entity.
39
- - **Entity write** - Users granted the write *permission* on an enitity. They can list, read, create, update, and delete tiddlers, but cannot change permissions.
40
- - **Entity read** - Users granted the read *permission* on an entity. They can list and read tiddlers, but cannot do anything else.
4
+ - **READ** - Read tiddlers from an entity.
5
+ - **WRITE** - Write tiddlers to an entity.
6
+ - **ADMIN** - Update ACL for an entity.
41
7
 
42
8
  ## Entities
43
9
 
44
10
  - **Bag** - A collection of tiddlers with unique titles
45
11
  - **Recipe** - A stack of bags in a specific order. Bags may inherit the ACL of a recipe they are included in.
46
12
 
47
- ## Roles
13
+ ## Roles (aka Groups)
48
14
 
49
15
  - Roles have names and descriptions
50
16
  - Multiple users can be assigned to a role
17
+ - Roles are given *permissions* on *entities*
51
18
 
52
- ## Permissions
53
-
54
- - **READ** - Read tiddlers from an entity.
55
- - **WRITE** - Write tiddlers to an entity.
56
- - **ADMIN** - Update ACL for an entity.
57
-
58
- ## Admin
59
-
60
- - There is an admin *role* and an admin *permission*.
61
- - Roles are given specific permissions for specific entities (bags and recipes).
62
- - The admin *role* has automatic admin *permission* for everything.
63
-
64
- ## ACL
65
-
66
- - Grants the **Permission** for an **Entity** to a **Role**.
67
- - Entities without an ACL are either public or private (configurable).
68
-
69
- ## Ownership
70
-
71
- - Ownership of an entity grants the "admin" *permission*.
72
- - Only site admins can change the owner of an entity.
73
- - Users with "admin" *permission* **cannot** change ownership.
74
-
75
- ## User Types
76
-
77
- #### Administrator (ADMIN) Role
78
-
79
- - Full system access and configuration rights
80
- - Most access checks are skipped
81
- - Can create, modify, and delete user accounts
82
- - Manages role assignments and permissions
83
- - Has full permissions on all recipes and bags
84
-
85
- #### Regular Users
86
-
87
- - Created by administrators
88
- - Permissions determined by assigned roles
89
- - Access limited to specific recipes based on role permissions
90
- - Access to recipes without an ACL is based on recipe config
19
+ ## Access Levels
91
20
 
92
- #### Guest Users
21
+ Conceptually, there are 6 access levels.
93
22
 
94
- - Users not logged in.
95
- - No inherent permissions
96
- - Can access recipes which allow it
97
- - Read/write can be enabled by server config
98
- - Useful for public wikis or documentation sites
23
+ - **Site owner** - has file system access to the server, and can run CLI commands. Presumably they also have a site admin account and they can always create one via the CLI.
24
+ - **Site admin** - Users with the admin *role*. They can assign owners and change permissions, and have full read and write access.
25
+ - **Entity owner** - Owner of an entity (bag or recipe). They can change permissions for that entity, and have full read and write access.
26
+ - **Entity admin** - Granted admin *permission*, they can manage permissions for the entity.
27
+ - **Entity write** - Granted write *permission*, they can list, read, create, update, and delete tiddlers, but cannot change permissions.
28
+ - **Entity read** - Granted read *permission* on an entity. They can list and read tiddlers, but cannot do anything else.
@@ -1,5 +1,5 @@
1
1
  created: 20250428144431745
2
- modified: 20250428152640317
2
+ modified: 20250613001943111
3
3
  tags: Reference
4
4
  title: Application Access & Security
5
5
  type: text/markdown
@@ -0,0 +1,19 @@
1
+
2
+ `ignore`
3
+ : `state.data` will be undefined. `state.reader` will be draining or already closed.
4
+
5
+ `stream`
6
+ : `state.data` will be undefined. You must call `state.reader` to get the request.
7
+
8
+ `buffer`
9
+ : `state.data` will be a Buffer.
10
+
11
+ `string`
12
+ : `state.data` will be a string.
13
+
14
+ `json`
15
+ : `state.data` will be read as a string, same as `string` and then parsed as JSON, with some sanity checks. If the string is zero-length, undefined will be returned without attempting to parse. This is the only case where undefined can be returned. If the JSON fails to parse, a `400 INVALID` response will be sent. `__proto__` and `constructor.prototype` are also checked.
16
+
17
+ `www-form-urlencoded` and `www-form-urlencoded-urlsearchparams`
18
+ : Parse the body using `URLSearchParams` optionally calling `Object.entries` on it.
19
+ : <div style="color: rgb(212, 212, 212); background-color: rgb(30, 30, 30); font-family: &quot;Fira Code&quot;, &quot;Cascadia Code&quot;, Consolas, &quot;Courier New&quot;, monospace, Consolas, &quot;Courier New&quot;, monospace; font-size: 15px; line-height: 20px; white-space: pre;"><div><span style="color: #569cd6;">const</span> <span style="color: #4fc1ff;">data</span> = <span style="color: #4fc1ff;">state</span>.<span style="color: #9cdcfe;">data</span> = <span style="color: #569cd6;">new</span> <span style="color: #4ec9b0;">URLSearchParams</span>((<span style="color: #c586c0;">await</span> <span style="color: #4fc1ff;">state</span>.<span style="color: #dcdcaa;">readBody</span>()).<span style="color: #dcdcaa;">toString</span>(<span style="color: #ce9178;">"utf8"</span>));</div><div><span style="color: #c586c0;">if</span> (<span style="color: #4fc1ff;">state</span>.<span style="color: #9cdcfe;">bodyFormat</span> === <span style="color: #ce9178;">"www-form-urlencoded"</span>) <span style="color: #4fc1ff;">state</span>.<span style="color: #9cdcfe;">data</span> = <span style="color: #4ec9b0;">Object</span>.<span style="color: #dcdcaa;">fromEntries</span>(<span style="color: #4fc1ff;">data</span>);</div></div>
@@ -0,0 +1,4 @@
1
+ created: 20250513231403024
2
+ modified: 20250514014327153
3
+ title: Body Format
4
+ type: text/markdown
@@ -10,6 +10,3 @@
10
10
  - Verify that all admin permissions are based on the admin role, not the first user.
11
11
  - Verify that admin's cannot remove the admin role from themselves.
12
12
 
13
- ## Recipes
14
-
15
- -
@@ -1,5 +1,5 @@
1
1
  created: 20250505141032240
2
- modified: 20250505145404612
2
+ modified: 20250613003924069
3
3
  tags: Reference
4
4
  title: Checklists and Features
5
5
  type: text/markdown
@@ -0,0 +1,17 @@
1
+ [[Client Plugins]] are normal [[TiddlyWiki]] plugins. They are cached on the server and served directly to the client as needed. [[Server Plugins]], perhaps acting as third-party plugin libraries, may register additional [[Client Plugins]] and either add them to the cache immediately (if it's some small built-in plugin) or only when a recipe requires them (like a plugin library would).
2
+
3
+ On startup, all server plugins are called to generate their client plugins. The client plugins are saved in `cache/${path}/plugin.*`, using a relative path of the plugin's choosing. The same thing happens when a recipe's list of plugins changes.
4
+
5
+ The wiki index file itself is also rendered with an empty store and saved at `cache/tiddlywiki5.html`.
6
+
7
+ When a wiki page is opened, the index file is loaded and parsed. Plugins are either read directly into the store area, or script tags are inserted which point to the location of the cache folder.
8
+
9
+ MWS saves a hash of the plugin in memory so it can be served as an external JavaScript file with the script integrity attribute. The advantage of external JavaScript files is that the browser can cache them on subsequent page loads, reducing bytes transferred. Plugins can also be served directly in the index file, just like a normal single-file TiddlyWiki would. Regardless of which option is used, MWS optimizes memory usage by piping the file directly into the response (and onto the network) rather than reading everything into memory first.
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+
@@ -0,0 +1,5 @@
1
+ created: 20250513192622877
2
+ modified: 20250613004524168
3
+ tags: Architecture
4
+ title: Client Plugins
5
+ type: text/markdown
@@ -3,15 +3,16 @@ The MultiWikiServer HTTP API provides management and tiddler endpoints.
3
3
  The design goals of the API are:
4
4
 
5
5
  - Connect the client and server as transparently as possible.
6
- - Be easy to understand and use via Javascript.
6
+ - Be easy to understand and use via JavaScript.
7
7
  - Have strict validation of incoming requests.
8
8
 
9
9
  ## Management
10
10
 
11
11
  - On the client, most request paths are defined by a single adaptor function which accepts the input for the server and returns a promise which resolves to the server's parsed response.
12
12
  - The server may throw a user error (or a string), which is expected to return to the client. It should give them an actionable understanding of what went wrong.
13
- - The API essentially forwards a function call from the client to the server, using `fetch`. It expects a Javascript client, and is not intended to support form submissions directly.
14
13
 
15
14
  ## Tiddler
16
15
 
17
- The tiddler API was based on [the API of TiddlyWeb](https://tank.peermore.com/tanks/tiddlyweb/HTTP%20API), first developed in 2008 by Chris Dent, but is more oriented around JSON and Typescript. The concept of resources remains and in the future it will hopefully be adapted to serve static versions of tiddlers.
16
+ The tiddler API was based on [the API of TiddlyWeb](https://tank.peermore.com/tanks/tiddlyweb/HTTP%20API), first developed in 2008 by Chris Dent, but is more oriented around JSON and Typescript.
17
+
18
+ The concept of resources is central to the API and in the future it will hopefully be adapted to serve static versions of tiddlers.
@@ -1,5 +1,5 @@
1
1
  created: 20250428152532763
2
- modified: 20250428152617476
2
+ modified: 20250613003613708
3
3
  tags: Reference
4
4
  title: HTTP API
5
5
  type: text/markdown
@@ -1,5 +1,5 @@
1
1
  created: 20250417170314382
2
- modified: 20250417170403098
2
+ modified: 20250612222324438
3
3
  tags: TableOfContents
4
4
  title: HelloThere
5
5
  type: text/vnd.tiddlywiki
@@ -19,4 +19,4 @@ Planned features include:
19
19
  * Instantaneous synchronisation of changes between the server and all connected clients
20
20
  * Workflow processing on the server, for example to automatically compress images, or to archive webpages
21
21
 
22
- MWS is currently [[under development at GitHub|https://github.com/TiddlyWiki/MultiWikiServer]] but it is already functional and usable.
22
+ MWS is currently [[under development at GitHub|https://github.com/TiddlyWiki/MultiWikiServer]] but it is already functional and usable, [[except for user security|Security]].
@@ -1,5 +1,5 @@
1
1
  created: 20241105133737778
2
- modified: 20250428144159846
2
+ modified: 20250612235731394
3
3
  tags: TableOfContents
4
4
  title: Installation
5
5
  type: text/vnd.tiddlywiki
@@ -25,9 +25,8 @@ To update your copy of MWS in the future with newer changes will require re-down
25
25
 
26
26
  !!! Git repo
27
27
 
28
- It is optionally recommended to save a history of your project configuration using git.
28
+ It is recommended to save a history of your project configuration using git,
29
29
 
30
30
  * On Windows you can use [[GitHub Desktop|https://github.com/apps/desktop]].
31
31
  * On Linux, git is usually preinstalled or available via the default package manager for your distro.
32
32
 
33
- If you decide to do this, you should move the wiki folder out of the project folder, and change the `wikiPath` setting accordingly.
@@ -1,2 +1,7 @@
1
- title: Architecture
1
+ created: 20250612170433199
2
+ modified: 20250612170434896
2
3
  tags: TableOfContents
4
+ title: Architecture
5
+ type: text/vnd.tiddlywiki
6
+
7
+ <<toc>>
@@ -0,0 +1,12 @@
1
+
2
+ If a user can write to a bag in a recipe, they can insert wiki-text which exports all the tiddlers in all recipes which contain that bag.
3
+
4
+ There are no real mitigations to this which can mitigate this completely, but there are some partial solutions which may help.
5
+
6
+ - Only allow loading modules from some bags.
7
+ - Partitioned bags which only allow each user to write tiddlers prefixed with their username.
8
+ - Use Content-Security-Policy headers to make the webpage read-only and block network requests.
9
+
10
+ I think what it really comes down to is that if you can't trust your users, don't give them write access.
11
+
12
+ Don't add untrusted bags to your recipes.
@@ -0,0 +1,5 @@
1
+ created: 20250525173734256
2
+ modified: 20250528202138460
3
+ tags: Security
4
+ title: Multi-user Trust
5
+ type: text/markdown
@@ -1,5 +1,7 @@
1
1
  created: 20250507122827955
2
- modified: 20250507122829535
3
- tags: TableOfContents
2
+ modified: 20250624125741539
3
+ tags:
4
4
  title: Notes
5
- type: text/vnd.tiddlywiki
5
+ type: text/vnd.tiddlywiki
6
+
7
+ <<toc>>
@@ -0,0 +1,29 @@
1
+ Oracles are clues that give information about a response without revealing the actual response.
2
+
3
+ Obviously none of this matters if your data isn't encrypted with HTTPS, since it's all open for everyone to read. But if it's encrypted, there are still ways of determining content.
4
+
5
+ ## Compression Oracles
6
+
7
+ A compression oracle is when an attack takes advantage of the deduplication that compression attempts to do by somehow managing to get their own plaintext inserted into the compression stream and then checking whether the compressed output increases in size or not. If it doesn't, then obviously that particularly plaintext was already in the response for that request.
8
+
9
+ ## Length Oracle
10
+
11
+ A similar attack involves inspecting the request length to determine whether a request returned any results. This is especially true of search features. A very big response implies returned results and a very tiny response implies no results. But there are also other ways to use the length which can come down to determining the exact number of bytes returned.
12
+
13
+ ### Mitigations for normal oracles
14
+
15
+ The attacks are usually done based on the timing of the response, so even if the response itself is opaque, the timing can usually still be inferred.
16
+
17
+ - Disable compression (ultimate mitigation but there are better solutions)
18
+ - Disable third-party cookies (SameSite=strict) so cookies are only sent for requests that originate from a loaded webpage. However, this prevents the cookie from being sent to the initial page load.
19
+ - We could set two cookies and only enable compression if the cookie with SameSite=strict is present. Any code which can make a SameSite=strict request is normally considered privelaged code anyway, so we have bigger problems if an attacker can do that.
20
+
21
+ ## MWS-specific oracles
22
+
23
+ A cross-bag compression oracle would allow an attacker with write access in one bag to infer the contents of a different bag in the recipe which they do not have access to by somehow attacking someone who does have access to that recipe and watching how the browser compresses various things. Without directly reading the bag's contents, they can write to the bag they have access to and watch the responses being sent to the other user to infer the contents of the recipe overall.
24
+
25
+ If batching is enabled, and if updates have side effects which trigger a save which is then loaded by other browsers, and if the attacker manages to add a second save with the correct timing to load in the same batch as the update of the side effect, an oracle attack can occur.
26
+
27
+ ## MWS mitigations
28
+
29
+ - The simplest mitigation is to never compress the contents of two bags together.
@@ -0,0 +1,5 @@
1
+ created: 20250522165353915
2
+ modified: 20250525173758686
3
+ tags: Security
4
+ title: Oracle Attacks
5
+ type: text/markdown
@@ -0,0 +1 @@
1
+ <<toc>>
@@ -1,5 +1,5 @@
1
1
  created: 20250428144428969
2
- modified: 20250428152626286
2
+ modified: 20250612170354797
3
3
  tags: TableOfContents
4
4
  title: Reference
5
5
  type: text/x-markdown
@@ -0,0 +1,53 @@
1
+
2
+ 1. **Entry Point**: `Router.handle()`
3
+ - Takes HTTP/HTTP2 request and response objects
4
+ - Wraps `handleRequest()` in error handling
5
+
6
+ 2. **Main Request Processing**: `Router.handleRequest()`
7
+ - Emit middleware event
8
+ - Apply Helmet middleware
9
+ - Create Streamer instance
10
+ - Call `handleStreamer()`
11
+
12
+ 3. **Stream Processing**: `Router.handleStreamer()`
13
+ - Emits streamer event
14
+ - Finds matching route using `findRoute()`
15
+ - Performs security checks (CSRF protection)
16
+ - Processes request body based on `bodyFormat`
17
+ - Creates `ServerRequest` instance
18
+ - Calls `handleRoute()`
19
+
20
+ 4. **Route Matching**: `Router.findRoute()` and `findRouteRecursive()`
21
+ - Recursively matches URL path against defined routes
22
+ - Handles nested routes
23
+ - Matches HTTP methods
24
+ - Returns array of matched route segments
25
+
26
+ 5. **Route Handling**: `Router.handleRoute()`
27
+ - Executes handlers for matched routes in sequence
28
+ - Emits handle event
29
+ - Falls back to 404 if no handler sends response
30
+
31
+ ## Body Format Processing
32
+
33
+ The router supports multiple body formats:
34
+ - `stream`: Raw streaming data
35
+ - `string`: UTF-8 string
36
+ - `json`: Parsed JSON data
37
+ - `buffer`: Raw buffer
38
+ - `www-form-urlencoded`: Parsed form data as object
39
+ - `www-form-urlencoded-urlsearchparams`: Form data as URLSearchParams
40
+ - `ignore`: Ignores request body (default for GET/HEAD)
41
+
42
+ ## Security Features
43
+
44
+ - Built-in Helmet middleware for security headers
45
+ - CSRF protection via `x-requested-with` header checks
46
+ - JSON security parsing (protects against prototype pollution)
47
+ - Method matching validation
48
+ - Path validation
49
+
50
+
51
+ The routes are hierarchical, allowing for nested routes with inherited properties and progressive URL path matching.
52
+
53
+ It is important that the entire request path be awaited and eventually resolve or reject. A promise should never be left hanging. The Router class takes care of making sure every request has finished with some response, but if the promise never resolves or rejects, the request will eventually time out.
@@ -0,0 +1,5 @@
1
+ created: 20250601093342424
2
+ modified: 20250613012220446
3
+ tags: Architecture
4
+ title: Request Handling
5
+ type: text/markdown
@@ -0,0 +1,7 @@
1
+ created: 20250624123955289
2
+ modified: 20250624124015029
3
+ tags: TableOfContents
4
+ title: Roadmap
5
+ type: text/vnd.tiddlywiki
6
+
7
+ <<toc>>