@antelopejs/interface-dms 0.10.3 → 0.12.0

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 (377) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/README.md +21 -10
  3. package/dist/attachments.d.ts +15 -2
  4. package/dist/attachments.js +14 -1
  5. package/dist/attachments.js.map +1 -1
  6. package/dist/auth/db/models/sessions.model.d.ts +7 -5
  7. package/dist/auth/db/models/sessions.model.js +2 -9
  8. package/dist/auth/db/models/sessions.model.js.map +1 -1
  9. package/dist/auth/db/models/userExternalIdentities.model.d.ts +7 -5
  10. package/dist/auth/db/models/users.model.d.ts +7 -5
  11. package/dist/auth/db/tables/users.table.d.ts +4 -2
  12. package/dist/auth/db/tables/users.table.js.map +1 -1
  13. package/dist/auth/index.d.ts +4 -4
  14. package/dist/auth/internal/jwt-auth-decorator.d.ts +1 -1
  15. package/dist/auth/internal/jwt-auth-decorator.js +6 -3
  16. package/dist/auth/internal/jwt-auth-decorator.js.map +1 -1
  17. package/dist/auth/internal/request-authenticators.d.ts +12 -0
  18. package/dist/auth/internal/request-authenticators.js +53 -10
  19. package/dist/auth/internal/request-authenticators.js.map +1 -1
  20. package/dist/base/activity-feed.d.ts +34 -32
  21. package/dist/base/activity-feed.js +2 -0
  22. package/dist/base/activity-feed.js.map +1 -1
  23. package/dist/base/banner.d.ts +12 -10
  24. package/dist/base/banner.js +2 -0
  25. package/dist/base/banner.js.map +1 -1
  26. package/dist/base/block-registry/internal/describe.js +3 -9
  27. package/dist/base/block-registry/internal/describe.js.map +1 -1
  28. package/dist/base/block-registry/internal/ui.js +1 -1
  29. package/dist/base/block-registry/internal/ui.js.map +1 -1
  30. package/dist/base/card.d.ts +11 -9
  31. package/dist/base/card.js +2 -0
  32. package/dist/base/card.js.map +1 -1
  33. package/dist/base/chart-card.d.ts +4 -2
  34. package/dist/base/chart-card.js +2 -0
  35. package/dist/base/chart-card.js.map +1 -1
  36. package/dist/base/chart-schemas.d.ts +148 -148
  37. package/dist/base/chart.d.ts +65 -0
  38. package/dist/base/chart.js +65 -0
  39. package/dist/base/chart.js.map +1 -1
  40. package/dist/base/code-block.d.ts +5 -3
  41. package/dist/base/code-block.js +2 -0
  42. package/dist/base/code-block.js.map +1 -1
  43. package/dist/base/custom.d.ts +5 -0
  44. package/dist/base/custom.js +5 -0
  45. package/dist/base/custom.js.map +1 -1
  46. package/dist/base/data-types/default/address.d.ts +5 -0
  47. package/dist/base/data-types/default/address.js +5 -0
  48. package/dist/base/data-types/default/address.js.map +1 -1
  49. package/dist/base/data-types/default/choices.d.ts +20 -0
  50. package/dist/base/data-types/default/choices.js +20 -0
  51. package/dist/base/data-types/default/choices.js.map +1 -1
  52. package/dist/base/data-types/default/files.d.ts +22 -5
  53. package/dist/base/data-types/default/files.js +20 -0
  54. package/dist/base/data-types/default/files.js.map +1 -1
  55. package/dist/base/data-types/default/numbers.d.ts +15 -0
  56. package/dist/base/data-types/default/numbers.js +25 -9
  57. package/dist/base/data-types/default/numbers.js.map +1 -1
  58. package/dist/base/data-types/default/relations.d.ts +10 -2
  59. package/dist/base/data-types/default/relations.js +9 -6
  60. package/dist/base/data-types/default/relations.js.map +1 -1
  61. package/dist/base/data-types/default/strings.d.ts +25 -0
  62. package/dist/base/data-types/default/strings.js +25 -0
  63. package/dist/base/data-types/default/strings.js.map +1 -1
  64. package/dist/base/data-types/default-types.d.ts +1 -1
  65. package/dist/base/data-types/field-types.d.ts +10 -0
  66. package/dist/base/data-types/field-types.js +10 -0
  67. package/dist/base/data-types/field-types.js.map +1 -1
  68. package/dist/base/data-types/internal/relation-endpoints.js +1 -0
  69. package/dist/base/data-types/internal/relation-endpoints.js.map +1 -1
  70. package/dist/base/data-types/status-type.d.ts +5 -0
  71. package/dist/base/data-types/status-type.js +5 -0
  72. package/dist/base/data-types/status-type.js.map +1 -1
  73. package/dist/base/display.d.ts +6 -6
  74. package/dist/base/empty-state.d.ts +15 -13
  75. package/dist/base/empty-state.js +2 -0
  76. package/dist/base/empty-state.js.map +1 -1
  77. package/dist/base/form-block-schema.d.ts +50 -50
  78. package/dist/base/form-schema.d.ts +2 -0
  79. package/dist/base/form-schema.js +2 -0
  80. package/dist/base/form-schema.js.map +1 -1
  81. package/dist/base/grid.d.ts +4 -0
  82. package/dist/base/grid.js +4 -0
  83. package/dist/base/grid.js.map +1 -1
  84. package/dist/base/guard.d.ts +30 -28
  85. package/dist/base/guard.js +2 -0
  86. package/dist/base/guard.js.map +1 -1
  87. package/dist/base/helpers/archive-mode-helpers.d.ts +1 -1
  88. package/dist/base/helpers/file-refs.js +15 -15
  89. package/dist/base/helpers/file-refs.js.map +1 -1
  90. package/dist/base/internal/form-schema-validation.js +7 -1
  91. package/dist/base/internal/form-schema-validation.js.map +1 -1
  92. package/dist/base/internal/realtime-topics.js.map +1 -1
  93. package/dist/base/internal/searchable.d.ts +2 -1
  94. package/dist/base/internal/searchable.js +1 -3
  95. package/dist/base/internal/searchable.js.map +1 -1
  96. package/dist/base/key-value-list.d.ts +21 -19
  97. package/dist/base/key-value-list.js +2 -0
  98. package/dist/base/key-value-list.js.map +1 -1
  99. package/dist/base/kpi-card.d.ts +4 -2
  100. package/dist/base/kpi-card.js +2 -0
  101. package/dist/base/kpi-card.js.map +1 -1
  102. package/dist/base/live-toggle.d.ts +2 -0
  103. package/dist/base/live-toggle.js +2 -0
  104. package/dist/base/live-toggle.js.map +1 -1
  105. package/dist/base/meter.d.ts +23 -21
  106. package/dist/base/meter.js +2 -0
  107. package/dist/base/meter.js.map +1 -1
  108. package/dist/base/nav-card-grid.d.ts +24 -19
  109. package/dist/base/nav-card-grid.js +5 -0
  110. package/dist/base/nav-card-grid.js.map +1 -1
  111. package/dist/base/page-toolbar.d.ts +2 -0
  112. package/dist/base/page-toolbar.js +2 -0
  113. package/dist/base/page-toolbar.js.map +1 -1
  114. package/dist/base/period-selector.d.ts +3 -1
  115. package/dist/base/period-selector.js +2 -0
  116. package/dist/base/period-selector.js.map +1 -1
  117. package/dist/base/placeholder.d.ts +2 -0
  118. package/dist/base/placeholder.js +2 -0
  119. package/dist/base/placeholder.js.map +1 -1
  120. package/dist/base/resource-form-schema.d.ts +2 -2
  121. package/dist/base/searchable.d.ts +3 -2
  122. package/dist/base/searchable.js +2 -2
  123. package/dist/base/searchable.js.map +1 -1
  124. package/dist/base/section.d.ts +6 -2
  125. package/dist/base/section.js +4 -0
  126. package/dist/base/section.js.map +1 -1
  127. package/dist/base/stack.d.ts +6 -0
  128. package/dist/base/stack.js +6 -0
  129. package/dist/base/stack.js.map +1 -1
  130. package/dist/base/stat-group.d.ts +16 -14
  131. package/dist/base/stat-group.js +2 -0
  132. package/dist/base/stat-group.js.map +1 -1
  133. package/dist/base/tab.d.ts +10 -8
  134. package/dist/base/tab.js +2 -0
  135. package/dist/base/tab.js.map +1 -1
  136. package/dist/base/table-view/column-display.d.ts +1 -1
  137. package/dist/base/table-view/column-display.js.map +1 -1
  138. package/dist/base/table-view/data-functions.d.ts +10 -4
  139. package/dist/base/table-view/data-functions.js.map +1 -1
  140. package/dist/base/table-view/factory.d.ts +5 -0
  141. package/dist/base/table-view/factory.js +8 -4
  142. package/dist/base/table-view/factory.js.map +1 -1
  143. package/dist/base/table-view/internal/auth.d.ts +17 -3
  144. package/dist/base/table-view/internal/auth.js +26 -5
  145. package/dist/base/table-view/internal/auth.js.map +1 -1
  146. package/dist/base/table-view/internal/column-conditions.d.ts +8 -1
  147. package/dist/base/table-view/internal/column-conditions.js +25 -13
  148. package/dist/base/table-view/internal/column-conditions.js.map +1 -1
  149. package/dist/base/table-view/internal/column-display.d.ts +1 -2
  150. package/dist/base/table-view/internal/column-display.js +3 -9
  151. package/dist/base/table-view/internal/column-display.js.map +1 -1
  152. package/dist/base/table-view/internal/factory-helpers.d.ts +1 -1
  153. package/dist/base/table-view/internal/factory-helpers.js +17 -14
  154. package/dist/base/table-view/internal/factory-helpers.js.map +1 -1
  155. package/dist/base/table-view/internal/factory-lifecycle-created.d.ts +2 -3
  156. package/dist/base/table-view/internal/factory-lifecycle-created.js +5 -5
  157. package/dist/base/table-view/internal/factory-lifecycle-created.js.map +1 -1
  158. package/dist/base/table-view/internal/factory-lifecycle-filter.d.ts +2 -2
  159. package/dist/base/table-view/internal/factory-private-actions.d.ts +2 -2
  160. package/dist/base/table-view/internal/files.d.ts +2 -1
  161. package/dist/base/table-view/internal/files.js +14 -5
  162. package/dist/base/table-view/internal/files.js.map +1 -1
  163. package/dist/base/table-view/internal/footer.d.ts +3 -3
  164. package/dist/base/table-view/internal/footer.js +16 -15
  165. package/dist/base/table-view/internal/footer.js.map +1 -1
  166. package/dist/base/table-view/internal/guards.d.ts +27 -5
  167. package/dist/base/table-view/internal/guards.js +127 -49
  168. package/dist/base/table-view/internal/guards.js.map +1 -1
  169. package/dist/base/table-view/internal/meta-helpers.d.ts +1 -1
  170. package/dist/base/table-view/internal/meta-helpers.js +3 -4
  171. package/dist/base/table-view/internal/meta-helpers.js.map +1 -1
  172. package/dist/base/table-view/internal/meta.js +2 -3
  173. package/dist/base/table-view/internal/meta.js.map +1 -1
  174. package/dist/base/table-view/internal/option-contract.d.ts +1 -1
  175. package/dist/base/table-view/internal/option-footer.d.ts +2 -2
  176. package/dist/base/table-view/internal/option-row-actions.d.ts +1 -1
  177. package/dist/base/table-view/internal/realtime.d.ts +52 -11
  178. package/dist/base/table-view/internal/realtime.js +23 -16
  179. package/dist/base/table-view/internal/realtime.js.map +1 -1
  180. package/dist/base/table-view/internal/resource-form.d.ts +1 -1
  181. package/dist/base/table-view/internal/resource-form.js +1 -1
  182. package/dist/base/table-view/internal/resource-form.js.map +1 -1
  183. package/dist/base/table-view/internal/row-actions-schema.d.ts +12 -12
  184. package/dist/base/table-view/internal/row-rule-shape.d.ts +11 -5
  185. package/dist/base/table-view/internal/row-rule-shape.js +60 -30
  186. package/dist/base/table-view/internal/row-rule-shape.js.map +1 -1
  187. package/dist/base/table-view/internal/row-rules.d.ts +28 -1
  188. package/dist/base/table-view/internal/row-rules.js +8 -19
  189. package/dist/base/table-view/internal/row-rules.js.map +1 -1
  190. package/dist/base/table-view/internal/tabs.d.ts +1 -1
  191. package/dist/base/table-view/internal/tabs.js +1 -4
  192. package/dist/base/table-view/internal/tabs.js.map +1 -1
  193. package/dist/base/table-view/internal/validation.d.ts +2 -2
  194. package/dist/base/table-view/internal/validation.js +7 -7
  195. package/dist/base/table-view/internal/validation.js.map +1 -1
  196. package/dist/base/table-view/meta.d.ts +7 -6
  197. package/dist/base/table-view/meta.js +12 -7
  198. package/dist/base/table-view/meta.js.map +1 -1
  199. package/dist/base/table-view/resource-form.d.ts +3 -1
  200. package/dist/base/table-view/resource-form.js +2 -0
  201. package/dist/base/table-view/resource-form.js.map +1 -1
  202. package/dist/base/table-view/routes.d.ts +73 -21
  203. package/dist/base/table-view/routes.js +13 -10
  204. package/dist/base/table-view/routes.js.map +1 -1
  205. package/dist/base/table-view/schema.d.ts +152 -152
  206. package/dist/base/table-view/source.js +4 -1
  207. package/dist/base/table-view/source.js.map +1 -1
  208. package/dist/base/table-view.d.ts +1 -1
  209. package/dist/base/table-view.js.map +1 -1
  210. package/dist/base/top-list-card.d.ts +35 -33
  211. package/dist/base/top-list-card.js +2 -0
  212. package/dist/base/top-list-card.js.map +1 -1
  213. package/dist/base/types/error.js +5 -2
  214. package/dist/base/types/error.js.map +1 -1
  215. package/dist/base/types/guards.d.ts +4 -4
  216. package/dist/base/types/json.d.ts +1 -10
  217. package/dist/base/types/row-action.d.ts +7 -7
  218. package/dist/component-options/confirm-dialog.d.ts +2 -0
  219. package/dist/component-options/confirm-dialog.js.map +1 -1
  220. package/dist/component-options/data-type.d.ts +2 -2
  221. package/dist/component-options/data-type.js +7 -7
  222. package/dist/component-options/data-type.js.map +1 -1
  223. package/dist/component-options/row-action.d.ts +14 -9
  224. package/dist/component-slots.d.ts +11 -2
  225. package/dist/component-slots.js +1 -0
  226. package/dist/component-slots.js.map +1 -1
  227. package/dist/component.d.ts +7 -8
  228. package/dist/component.js +17 -25
  229. package/dist/component.js.map +1 -1
  230. package/dist/data-controllers/members.d.ts +11 -7
  231. package/dist/data-controllers/members.js +1 -1
  232. package/dist/data-controllers/members.js.map +1 -1
  233. package/dist/data-controllers/roles.d.ts +32 -10
  234. package/dist/db/internal/exportJobs.model.d.ts +7 -5
  235. package/dist/db/internal/inviteResolutions.model.d.ts +7 -5
  236. package/dist/db/internal/tenantLifecycle.model.d.ts +7 -5
  237. package/dist/db/models/roles.model.d.ts +7 -5
  238. package/dist/db/models/tenantMembers.model.d.ts +7 -5
  239. package/dist/db/models/tenants.model.d.ts +7 -5
  240. package/dist/db/models/user_invites.model.d.ts +7 -5
  241. package/dist/db/tables/tenants.table.d.ts +9 -0
  242. package/dist/db/tables/tenants.table.js +4 -0
  243. package/dist/db/tables/tenants.table.js.map +1 -1
  244. package/dist/guards.d.ts +1 -1
  245. package/dist/hooks.d.ts +10 -9
  246. package/dist/hooks.js +42 -33
  247. package/dist/hooks.js.map +1 -1
  248. package/dist/internal/attachments.d.ts +2 -2
  249. package/dist/internal/component-builder.js +2 -1
  250. package/dist/internal/component-builder.js.map +1 -1
  251. package/dist/internal/component-serialization.d.ts +2 -4
  252. package/dist/internal/component-serialization.js +4 -3
  253. package/dist/internal/component-serialization.js.map +1 -1
  254. package/dist/internal/component-slots.d.ts +19 -2
  255. package/dist/internal/component-slots.js +35 -12
  256. package/dist/internal/component-slots.js.map +1 -1
  257. package/dist/internal/component-watch-filter.d.ts +11 -0
  258. package/dist/internal/component-watch-filter.js +22 -0
  259. package/dist/internal/component-watch-filter.js.map +1 -0
  260. package/dist/internal/component-watches.js +0 -1
  261. package/dist/internal/component-watches.js.map +1 -1
  262. package/dist/internal/own-entry.d.ts +7 -0
  263. package/dist/internal/own-entry.js +13 -0
  264. package/dist/internal/own-entry.js.map +1 -0
  265. package/dist/invite-extension-payloads.d.ts +14 -2
  266. package/dist/invite-extensions/internal/delivery.js +1 -2
  267. package/dist/invite-extensions/internal/delivery.js.map +1 -1
  268. package/dist/invite-extensions/internal/edit.d.ts +2 -1
  269. package/dist/invite-extensions/internal/edit.js +8 -9
  270. package/dist/invite-extensions/internal/edit.js.map +1 -1
  271. package/dist/invite-extensions/internal/form-slot.js +8 -15
  272. package/dist/invite-extensions/internal/form-slot.js.map +1 -1
  273. package/dist/invite-extensions/internal/payload-slices.d.ts +33 -3
  274. package/dist/invite-extensions/internal/payload-slices.js +84 -19
  275. package/dist/invite-extensions/internal/payload-slices.js.map +1 -1
  276. package/dist/invite-extensions/internal/types.d.ts +10 -1
  277. package/dist/invite-resolution.js +6 -4
  278. package/dist/invite-resolution.js.map +1 -1
  279. package/dist/json.d.ts +10 -0
  280. package/dist/json.js +3 -0
  281. package/dist/json.js.map +1 -0
  282. package/dist/layout-banners.d.ts +5 -2
  283. package/dist/layout-banners.js.map +1 -1
  284. package/dist/page/controllers.d.ts +2 -2
  285. package/dist/page/internal/extension-validation.js +3 -2
  286. package/dist/page/internal/extension-validation.js.map +1 -1
  287. package/dist/page/internal/metadata-layout.js +1 -1
  288. package/dist/page/internal/metadata-layout.js.map +1 -1
  289. package/dist/page/internal/metadata-publish.js +3 -2
  290. package/dist/page/internal/metadata-publish.js.map +1 -1
  291. package/dist/page/internal/metadata-registration.js +5 -4
  292. package/dist/page/internal/metadata-registration.js.map +1 -1
  293. package/dist/page/internal/metadata-upload-registration.d.ts +3 -1
  294. package/dist/page/internal/metadata-upload-registration.js +9 -0
  295. package/dist/page/internal/metadata-upload-registration.js.map +1 -1
  296. package/dist/page/internal/metadata-uploads.d.ts +18 -5
  297. package/dist/page/internal/metadata-uploads.js +7 -8
  298. package/dist/page/internal/metadata-uploads.js.map +1 -1
  299. package/dist/page/internal/page-record.d.ts +2 -3
  300. package/dist/page/internal/page-record.js +19 -14
  301. package/dist/page/internal/page-record.js.map +1 -1
  302. package/dist/page/layout-filter.js +17 -6
  303. package/dist/page/layout-filter.js.map +1 -1
  304. package/dist/page/metadata.js +5 -7
  305. package/dist/page/metadata.js.map +1 -1
  306. package/dist/request-tenant.d.ts +10 -4
  307. package/dist/request-tenant.js +16 -34
  308. package/dist/request-tenant.js.map +1 -1
  309. package/dist/tenant-export.d.ts +2 -1
  310. package/dist/tenant-lifecycle.d.ts +13 -4
  311. package/dist/tenant-lifecycle.js +51 -18
  312. package/dist/tenant-lifecycle.js.map +1 -1
  313. package/dist/types.d.ts +20 -0
  314. package/dist/uploads.js +42 -59
  315. package/dist/uploads.js.map +1 -1
  316. package/dist/utils/fire-and-forget.js.map +1 -1
  317. package/dist/utils/internal/decorated-class.d.ts +14 -0
  318. package/dist/utils/internal/decorated-class.js +37 -0
  319. package/dist/utils/internal/decorated-class.js.map +1 -0
  320. package/dist/utils/internal/type-check.d.ts +9 -0
  321. package/dist/utils/internal/type-check.js +13 -5
  322. package/dist/utils/internal/type-check.js.map +1 -1
  323. package/dist/utils/internal/value-parser.d.ts +1 -1
  324. package/dist/utils/internal/value-parser.js +22 -9
  325. package/dist/utils/internal/value-parser.js.map +1 -1
  326. package/dist/watch-actions.d.ts +1 -1
  327. package/docs/1.core/1.introduction.md +82 -77
  328. package/docs/1.core/10.layout-banners.md +57 -45
  329. package/docs/1.core/11.modules-and-dynamic-menus.md +178 -0
  330. package/docs/1.core/12.frontend-modules-and-request-helpers.md +155 -0
  331. package/docs/1.core/13.tenant-data-export.md +120 -0
  332. package/docs/1.core/2.pages-and-modules.md +140 -367
  333. package/docs/1.core/3.components.md +21 -22
  334. package/docs/1.core/4.permissions.md +92 -71
  335. package/docs/1.core/5.tenancy.md +112 -86
  336. package/docs/1.core/6.invites.md +90 -65
  337. package/docs/1.core/7.hooks.md +96 -166
  338. package/docs/1.core/8.realtime.md +44 -45
  339. package/docs/1.core/9.quick-actions.md +37 -30
  340. package/docs/2.auth/1.introduction.md +33 -35
  341. package/docs/2.auth/2.authentication.md +60 -38
  342. package/docs/2.auth/3.tokens-and-sessions.md +56 -55
  343. package/docs/2.auth/4.users.md +82 -52
  344. package/docs/2.auth/5.external-identities.md +25 -26
  345. package/docs/3.base/1.introduction.md +64 -60
  346. package/docs/3.base/10.display-blocks.md +15 -16
  347. package/docs/3.base/11.page-layouts.md +273 -0
  348. package/docs/3.base/12.table-row-actions.md +122 -0
  349. package/docs/3.base/13.table-filters-and-forms.md +104 -0
  350. package/docs/3.base/14.table-events-and-helpers.md +114 -0
  351. package/docs/3.base/15.table-sources-and-gates.md +24 -0
  352. package/docs/3.base/2.types.md +44 -41
  353. package/docs/3.base/3.forms.md +27 -28
  354. package/docs/3.base/4.tables.md +34 -367
  355. package/docs/3.base/5.charts-and-widgets.md +28 -29
  356. package/docs/3.base/6.layout.md +21 -270
  357. package/docs/3.base/8.data-types.md +39 -40
  358. package/docs/3.base/9.helpers.md +36 -38
  359. package/docs/4.notifications/1.introduction.md +22 -26
  360. package/docs/4.notifications/2.categories-and-subjects.md +58 -55
  361. package/docs/4.notifications/3.sending.md +72 -68
  362. package/docs/5.html-render/1.introduction.md +119 -81
  363. package/docs/5.html-render/2.built-in-emails.md +71 -51
  364. package/docs/index.md +18 -29
  365. package/docs/tsconfig.json +4 -0
  366. package/package.json +12 -12
  367. package/docs/images/emails-admin-invite.png +0 -0
  368. package/docs/images/emails-change-notice.png +0 -0
  369. package/docs/images/emails-change-verification.png +0 -0
  370. package/docs/images/emails-digest-logo-dark.png +0 -0
  371. package/docs/images/emails-digest-logo-light.png +0 -0
  372. package/docs/images/emails-digest.png +0 -0
  373. package/docs/images/emails-export-partial.png +0 -0
  374. package/docs/images/emails-export-ready.png +0 -0
  375. package/docs/images/emails-reset-password.png +0 -0
  376. package/docs/images/emails-two-factor.png +0 -0
  377. package/docs/images/emails-user-validation.png +0 -0
@@ -1,26 +1,25 @@
1
1
  ---
2
2
  title: "Authentication"
3
- description: "Authentication turns an incoming HTTP request into a `User` row."
3
+ description: "The authentication decorators, `authenticateRequestUser`, and the token input they share."
4
+ mode: reference
4
5
  ---
5
6
 
6
- # Authentication
7
-
8
7
  ## Overview
9
8
 
10
- Authentication turns an incoming HTTP request into a `User` row. The interface exposes one plain function, `authenticateRequestUser`, and four decorators with the `CreateAuthDecorator` contract of `@antelopejs/interface-auth`: `AuthRawUser`, `AuthUser`, `IfAuthUser` and `AuthOwnerOnly`. Each of them, and `authenticateRequestUser`, binds the verified user and tenant to the request, which [`getRequestTenantId`](/docs/interfaces/core/tenancy#resolve-the-requests-tenant) then answers.
9
+ Authentication turns an incoming HTTP request into a `User` row. `@antelopejs/interface-dms/auth` exports one plain function, `authenticateRequestUser`, and four decorators: `AuthRawUser`, `AuthUser`, `IfAuthUser` and `AuthOwnerOnly`. Each of them binds the verified user and tenant to the request, and [`getRequestTenantId`](/docs/interfaces/core/tenancy#resolve-the-requests-tenant) then returns that tenant.
11
10
 
12
- All of them read the bearer token from the request's `Authorization` header (`Authorization: Bearer <token>`) and run the same two steps:
11
+ All of them read the bearer token from the `Authorization` header of the request (`Authorization: Bearer <token>`) and run the same two steps:
13
12
 
14
- 1. **Authenticator** — decodes the token into a `TenantTokenInput`: the user id, the tenant id, and the undecoded token itself.
15
- 2. **Validator** — loads the user named by that id, verifies the token signature against that user, and applies the extra requirement the decorator stands for.
13
+ 1. The authenticator decodes the token into a `TenantTokenInput`: the user id, the tenant id, and the undecoded token itself.
14
+ 2. The validator loads the user named by that id and verifies the token against that user. It checks the signature, checks that the token was issued as an access token, and checks that the session the token names still exists. It then applies the extra requirement of the decorator.
16
15
 
17
- Whatever the validator returns is what gets injected. The four decorators differ only in the requirement they enforce and in what they do when it fails.
16
+ The decorator injects whatever the validator returns. The four decorators differ only in the requirement they enforce and in what they do when it fails.
18
17
 
19
- The `User` type they inject comes from the `/db` subpath and is documented in [Users](/docs/interfaces/auth/users). The tokens they consume are produced by the generators in [Tokens and Sessions](/docs/interfaces/auth/tokens-and-sessions).
18
+ The `User` type they inject comes from `@antelopejs/interface-dms/auth/db` and is described in [Users](/docs/interfaces/auth/users). The generators in [Tokens and sessions](/docs/interfaces/auth/tokens-and-sessions) produce the tokens they consume.
20
19
 
21
- ## Require an Authenticated User
20
+ ## Require an authenticated user
22
21
 
23
- `AuthUser` injects the `User` and enforces email validation when the deployment's authentication configuration requires it. Use it for any route that must have a signed-in caller.
22
+ `AuthUser` injects the `User`, and enforces email validation when the deployment sets `auth.mustValidateEmail`. A caller whose email is not validated then gets `401` (`Email not validated`). Use it on any route that must have a signed-in caller.
24
23
 
25
24
  ```typescript
26
25
  import { Controller, Get } from "@antelopejs/interface-api";
@@ -36,11 +35,11 @@ export class ProfileController extends Controller("/api/profile") {
36
35
  }
37
36
  ```
38
37
 
39
- The injected value is the full `User` row, including fields you do not want to return over HTTP. Pass it through `sanitizeUser` before serializing it — see [Users](/docs/interfaces/auth/users).
38
+ The injected value is the full `User` row, including fields you must not return over HTTP. Pass it through `sanitizeUser` before you serialize it, as described in [Users](/docs/interfaces/auth/users).
40
39
 
41
- ## Skip the Email-Validation Gate
40
+ ## Skip the email-validation gate
42
41
 
43
- `AuthRawUser` resolves the same `User` but does not apply the email-validation requirement. It is what the routes that exist *because* the email is not validated yet need — reading the current account, logging out, requesting a new validation mail — and it is also what modules use to gate their own API routes on a signed-in caller.
42
+ `AuthRawUser` resolves the same `User` but does not apply the email-validation requirement. The routes that exist because the email is not validated yet use it: reading the current account, logging out, and requesting a new validation email. Modules also use it to gate their own API routes on a signed-in caller.
44
43
 
45
44
  ```typescript
46
45
  import { Controller, Get, Post } from "@antelopejs/interface-api";
@@ -65,11 +64,11 @@ export class AccountController extends Controller("/api/account") {
65
64
  }
66
65
  ```
67
66
 
68
- Both decorators inject the raw database row; neither strips sensitive fields. "Raw" here refers to skipping the email-validation step, not to the shape of the object.
67
+ Both decorators inject the raw database row, and neither strips sensitive fields. "Raw" refers to the skipped email-validation step, not to the shape of the object.
69
68
 
70
- ## Accept Anonymous Callers
69
+ ## Accept anonymous callers
71
70
 
72
- `IfAuthUser` is the optional variant. It injects `User | undefined` and does not reject the request: a missing token, a malformed token and a token that fails validation all resolve to `undefined`.
71
+ `IfAuthUser` is the optional variant. It injects `User | undefined` and does not reject the request. A missing token, a malformed token, and a token that fails validation all resolve to `undefined`.
73
72
 
74
73
  ```typescript
75
74
  import { Controller, Get } from "@antelopejs/interface-api";
@@ -87,11 +86,11 @@ export class ArticleController extends Controller("/api/articles") {
87
86
  }
88
87
  ```
89
88
 
90
- Because an expired token resolves to `undefined` rather than a 401, a client-side refresh interceptor keyed on 401 responses does not fire for a route guarded this way. When a route must hard-fail on an expired session, guard it with `AuthUser` and give the anonymous path its own route.
89
+ An expired token resolves to `undefined`, not to a 401. A client-side refresh interceptor that reacts to 401 responses therefore does not fire on a route guarded this way. When a route must fail on an expired session, guard it with `AuthUser` and give the anonymous path its own route.
91
90
 
92
- ## Restrict a Route to Platform Owners
91
+ ## Restrict a route to platform owners
93
92
 
94
- `AuthOwnerOnly` requires the authenticated user to be a platform owner (`User.owner === true`). It answers `401` when no token is provided and `403` when the caller is authenticated but not an owner. The DMS applies it to pages under `/modules/`, which are owner-only administration spaces.
93
+ `AuthOwnerOnly` requires the authenticated user to be a platform owner (`User.owner === true`). It answers `401` when no token is provided and `403` (`Owner-only`) when the caller is authenticated but not an owner. The DMS applies it to the pages a module declares (`/modules/<id>/...`), which are owner-only administration spaces, unless the page is public or declares `authOnly`.
95
94
 
96
95
  ```typescript
97
96
  import { Controller, Get } from "@antelopejs/interface-api";
@@ -109,11 +108,11 @@ export class MaintenanceController extends Controller("/api/maintenance") {
109
108
  }
110
109
  ```
111
110
 
112
- `AuthOwnerOnly` is a plain function that returns a ready-to-apply decorator, so it is written `@AuthOwnerOnly()` exactly like the three decorator factories above. It takes no arguments, because it pre-applies its own validator.
111
+ `AuthOwnerOnly` is a plain function that returns a decorator ready to apply, so you write `@AuthOwnerOnly()` like the three decorator factories above. It takes no arguments, because it supplies its own validator.
113
112
 
114
- ## Gate Every Route on a Controller
113
+ ## Gate every route on a controller
115
114
 
116
- `AuthRawUser`, `AuthUser` and `IfAuthUser` follow the `CreateAuthDecorator` contract, so they apply to a parameter, to a property, or to the controller class itself. A property provider is a computed property of the controller, resolved on every request the controller handles whether or not the handler reads it — so a decorated property gates the whole controller and gives the handlers a typed `this.user`.
115
+ `AuthRawUser`, `AuthUser` and `IfAuthUser` apply to a parameter, to a property, or to the controller class itself. A property provider is a computed property of the controller. It is resolved on every request the controller handles, whether or not the handler reads it. A decorated property therefore gates the whole controller and gives the handlers a typed `this.user`.
117
116
 
118
117
  ```typescript
119
118
  import { Controller, Get, JSONBody, Post } from "@antelopejs/interface-api";
@@ -144,11 +143,11 @@ export class SettingsController extends Controller("/api/settings") {
144
143
  }
145
144
  ```
146
145
 
147
- This is the form the DMS uses when it wires authentication onto a page controller: the decorator is applied to the `user` property of the page class.
146
+ The DMS uses this form when it wires authentication onto a page controller. It applies the decorator to the `user` property of the page class.
148
147
 
149
- ## Read the Token Payload
148
+ ## Read the token payload
150
149
 
151
- `TenantTokenInput` is the value the authenticator step produces and the validator step consumes. It is exported from the root subpath.
150
+ `TenantTokenInput` is the value the authenticator step produces and the validator step consumes. It is exported from `@antelopejs/interface-dms/auth`.
152
151
 
153
152
  ```typescript
154
153
  export interface TenantTokenInput {
@@ -160,17 +159,17 @@ export interface TenantTokenInput {
160
159
 
161
160
  | Field | Type | Description |
162
161
  | ----- | ---- | ----------- |
163
- | `tenantId` | `string` | The tenant the token was issued for, taken from the token's `tenantId` claim. |
162
+ | `tenantId` | `string` | The tenant the token was issued for, taken from the `tenantId` claim of the token. |
164
163
  | `id` | `string` | The `_id` of the user the token was issued for. |
165
164
  | `rawToken` | `string` | The undecoded bearer token, used to verify the signature against the user. |
166
165
 
167
- The decoded payload carries no signature guarantee on its own: the validator is the step that verifies `rawToken` against the user it names.
166
+ The decoded payload carries no signature guarantee on its own. The validator is the step that verifies `rawToken` against the user it names.
168
167
 
169
- ## Authenticate Inside a Custom Provider
168
+ ## Authenticate inside a custom provider
170
169
 
171
- `authenticateRequestUser` performs the same authenticate-then-validate sequence outside the decorator machinery. Use it when you write your own parameter provider and need the user plus something else in one place.
170
+ `authenticateRequestUser` runs the same authenticator and validator outside a decorator. Use it when you write your own parameter provider and need the user and something else in one place.
172
171
 
173
- ```typescript
172
+ ```typescript fragment
174
173
  authenticateRequestUser(ctx: RequestContext): Promise<User>
175
174
  ```
176
175
 
@@ -178,7 +177,7 @@ authenticateRequestUser(ctx: RequestContext): Promise<User>
178
177
  | --------- | ----------- |
179
178
  | `ctx` | The request context handed to a parameter provider, from `@antelopejs/interface-api`. The function reads `ctx.rawRequest.headers.authorization`. |
180
179
 
181
- It runs the same validation as `AuthUser`, so the email-validation gate applies: a caller whose email is not validated is rejected when the deployment's configuration requires validation. Every failure throws an `HTTPResult` with status `401`.
180
+ It runs the same validation as `AuthUser`, so the email-validation gate applies. A caller whose email is not validated is rejected when the deployment requires validation. Every failure throws an `HTTPResult` with status `401`. It also throws `401` when the request is already bound to another user or tenant.
182
181
 
183
182
  ```typescript
184
183
  import {
@@ -204,19 +203,42 @@ export const AuthBetaTester = MakeParameterAndPropertyDecorator(
204
203
  );
205
204
  ```
206
205
 
207
- This is how the DMS builds its tenant guards: `AuthTenantOwner` and `AuthTenantMember` in `@antelopejs/interface-dms/guards` both start from `authenticateRequestUser`, then resolve the request's tenant and check the caller's membership on top of it.
206
+ The DMS builds its tenant guards the same way. `AuthTenantOwner` and `AuthTenantMember` in `@antelopejs/interface-dms/guards` authenticate the request, then resolve its tenant and check the caller's membership.
207
+
208
+ A provider is also the way to add a requirement and keep the built-in one. A call site can pass a replacement validator, as in `@AuthUser(callback)`. That callback replaces the whole validation step, signature check included, and its return type is `boolean | User`. Such a call binds no tenant to the request. This interface exports no token-verification function, so a replacement validator cannot redo the signature check it removes.
209
+
210
+ ## Accept another credential family
211
+
212
+ `@antelopejs/interface-dms/auth` also exports the `RequestPrincipal` and `RequestAuthenticator` types. A `RequestAuthenticator` lets one route accept a credential that is not a DMS JWT. The decorators on this page accept only the DMS JWT. To accept another credential, pass authenticators to `authenticateTenantRequest` in `@antelopejs/interface-dms/guards`, through its `authenticators` option.
213
+
214
+ ```typescript fragment
215
+ interface RequestPrincipal {
216
+ user: User;
217
+ tenantId: string;
218
+ }
219
+
220
+ interface RequestAuthenticator {
221
+ recognizes(token: string): boolean;
222
+ authenticate(token: string): Promise<RequestPrincipal>;
223
+ }
224
+ ```
225
+
226
+ | Member | Contract |
227
+ | ------ | -------- |
228
+ | `recognizes` | Claims the credential family from the bearer token, without trusting its contents. It must also recognize a malformed credential of its own family. |
229
+ | `authenticate` | Verifies the credential and reloads its user. It throws on an invalid, expired or revoked credential. |
208
230
 
209
- A provider is also the way to add a requirement without losing the built-in one. The `CreateAuthDecorator` contract lets a call site pass a replacement validator — `@AuthUser(callback)` — but that callback replaces the whole validation step, signature check included, and its return type is constrained to `boolean | User`; such a call binds no tenant to the request. This interface exports no token-verification primitive, so a replacement validator cannot redo the signature check it removes.
231
+ A token that no authenticator recognizes falls back to the DMS JWT. A token that two authenticators recognize is refused with `401`. A principal is identity and tenant established together. It is not an authorization.
210
232
 
211
- ## Decorator Reference
233
+ ## Decorator reference
212
234
 
213
235
  | Decorator | Injects | Email validation | On failure |
214
236
  | --------- | ------- | ---------------- | ---------- |
215
237
  | `AuthRawUser()` | `User` | Not checked | `401` |
216
238
  | `AuthUser()` | `User` | Enforced when the configuration requires it | `401` |
217
239
  | `IfAuthUser()` | `User \| undefined` | Enforced when the configuration requires it | Resolves to `undefined` |
218
- | `AuthOwnerOnly()` | `User` | Enforced when the configuration requires it | `401` without a token, `403` when not an owner |
240
+ | `AuthOwnerOnly()` | `User` | Enforced when the configuration requires it | `401` without a valid token, `403` when not an owner |
219
241
 
220
- ## Next Steps
242
+ ## Next steps
221
243
 
222
- Continue with [Tokens and Sessions](/docs/interfaces/auth/tokens-and-sessions) to see how the tokens these decorators consume are issued and validated.
244
+ Continue with [Tokens and sessions](/docs/interfaces/auth/tokens-and-sessions) to see how the DMS issues and validates the tokens these decorators consume.
@@ -1,28 +1,27 @@
1
1
  ---
2
- title: "Tokens and Sessions"
3
- description: "The interface issues four kinds of token, and it records a login as a row in the `sessions` table."
2
+ title: "Tokens and sessions"
3
+ description: "The four token kinds, their generators and validators, the token payload, and the `Session` table and model."
4
+ mode: reference
4
5
  ---
5
6
 
6
- # Tokens and Sessions
7
-
8
7
  ## Overview
9
8
 
10
- The interface issues four kinds of token, and it records a login as a row in the `sessions` table. Three of the four come with an exported validator; the access token is validated by the authentication decorators instead.
9
+ The interface issues four kinds of token, and it records a login as a row in the `sessions` table. Three of the four token kinds have an exported validator. The authentication decorators validate the access token.
11
10
 
12
11
  | Token | Generated by | Validated by | Carries |
13
12
  | ----- | ------------ | ------------ | ------- |
14
- | Access | `generateAccessToken` | The authentication decorators in [Authentication](/docs/interfaces/auth/authentication) | `id`, `tenantId`, optional `sessionId` |
15
- | Refresh | `generateRefreshToken` | `validateRefreshToken` | `id`, `tenantId`, optional `sessionId` |
13
+ | Access | `generateAccessToken` | The authentication decorators in [Authentication](/docs/interfaces/auth/authentication) | `id`, `tenantId`, optional `sessionId`, a purpose marker |
14
+ | Refresh | `generateRefreshToken` | `validateRefreshToken` | `id`, `tenantId`, optional `sessionId`, a purpose marker |
16
15
  | Two-factor | `generateTwoFactorToken` | `validateTwoFactorToken` | `id`, `tenantId`, a purpose marker |
17
16
  | Tenant assignment | `generateTenantAssignmentToken` | `validateTenantAssignmentToken` | `id`, a purpose marker |
18
17
 
19
- Every generator takes the `User` it signs for, and every validator loads that user back before it returns. All seven are interface functions, so every call returns a promise.
18
+ Every generator takes the `User` it signs for, and every validator loads that user before it returns. All seven functions are interface functions, so every call returns a promise. The purpose marker keeps one kind of token from being accepted as another. A refresh token sent as a bearer token fails authentication, for example.
20
19
 
21
- Access and refresh tokens are the pair a client holds: the access token goes in the `Authorization` header of ordinary requests, and the refresh token buys a new access token when it expires. Two-factor and tenant-assignment tokens are short-lived hand-offs that stand between a password check and a real session.
20
+ A client holds the access and refresh pair. The access token goes in the `Authorization` header of ordinary requests, and the refresh token gets a new access token when the old one expires. Two-factor and tenant-assignment tokens are short-lived steps between a password check and a real session.
22
21
 
23
- ## Issue an Access and Refresh Token Pair
22
+ ## Issue an access and refresh token pair
24
23
 
25
- ```typescript
24
+ ```typescript fragment
26
25
  generateAccessToken(
27
26
  tenantId: string,
28
27
  user: User,
@@ -38,11 +37,11 @@ generateRefreshToken(
38
37
 
39
38
  | Parameter | Description |
40
39
  | --------- | ----------- |
41
- | `tenantId` | The tenant the token is scoped to. It lands in the token's `tenantId` claim and is what the request's tenant resolution reads back. |
42
- | `user` | The `User` the token is issued for. The user's `authKey` takes part in the signing secret, so rotating `authKey` invalidates every token previously issued to that user. |
43
- | `sessionId` | The `_id` of the `Session` row that records this login. Optional: a token issued without one is valid but is not tied to a revocable session. An access token issued with one is refused as soon as that row is deleted. |
40
+ | `tenantId` | The tenant the token is scoped to. It goes in the `tenantId` claim of the token, and the request's tenant resolution reads it back. |
41
+ | `user` | The `User` the token is issued for. The user's `authKey` is part of the signing secret, so rotating `authKey` invalidates every token issued to that user before. |
42
+ | `sessionId` | The `_id` of the `Session` row that records this login. Optional. A token issued without it is valid but is not tied to a revocable session. An access token issued with it is refused as soon as that row is deleted. |
44
43
 
45
- Both return the signed `token` and its lifetime as `expiresIn` in milliseconds, taken from the deployment's `accessTokenLifetime` and `refreshTokenLifetime` configuration.
44
+ Both functions return the signed `token`, and its lifetime as `expiresIn` in milliseconds. The lifetimes come from the `accessTokenLifetime` and `refreshTokenLifetime` settings of the deployment.
46
45
 
47
46
  ```typescript
48
47
  import {
@@ -79,15 +78,15 @@ export async function startSession(
79
78
  }
80
79
  ```
81
80
 
82
- ## Validate a Refresh Token
81
+ ## Validate a refresh token
83
82
 
84
- ```typescript
83
+ ```typescript fragment
85
84
  validateRefreshToken(
86
85
  token: string,
87
86
  ): Promise<{ id: string; tenantId: string; sessionId?: string }>
88
87
  ```
89
88
 
90
- The function decodes the token, loads the user it names, and verifies the signature against that user. It throws `HTTPResult(401)` when the user no longer exists or the signature does not check out. It returns the claims only — confirming that the session still exists, that the token is still its current one (`isCurrentRefreshToken`), and that the user still has access to `tenantId` is the caller's job.
89
+ The function decodes the token, loads the user it names, and verifies the signature against that user. It also checks that the token was issued as a refresh token and carries non-empty `id` and `tenantId` claims. It throws `HTTPResult(401)` when the user no longer exists (`Invalid user`), and when the token is malformed, expired, badly signed or issued for another purpose. It returns the claims only. The caller must still confirm three things: that the session exists, that the token is its current one (`isCurrentRefreshToken`), and that the user still has access to `tenantId`.
91
90
 
92
91
  ```typescript
93
92
  import { HTTPResult } from "@antelopejs/interface-api";
@@ -130,13 +129,13 @@ export async function refresh(
130
129
  }
131
130
  ```
132
131
 
133
- Because the returned payload names a `tenantId`, the same call backs a tenant switch: validate the refresh token, check the user's membership of the target tenant, then issue a new pair for that tenant instead.
132
+ The returned payload names a `tenantId`, so the same call also backs a tenant switch. Validate the refresh token, check the user's membership of the target tenant, then issue a new pair for that tenant.
134
133
 
135
- ## Hand Off to a Second Factor
134
+ ## Hand off to a second factor
136
135
 
137
- When a user's credentials check out but the account has second factors enabled, issue a two-factor token instead of a session and let the client come back with the code.
136
+ When the credentials of a user check out but the account has second factors enabled, issue a two-factor token instead of a session. The client then comes back with the code.
138
137
 
139
- ```typescript
138
+ ```typescript fragment
140
139
  generateTwoFactorToken(
141
140
  tenantId: string,
142
141
  user: User,
@@ -150,7 +149,7 @@ validateTwoFactorToken(token: string): Promise<{
150
149
  }>
151
150
  ```
152
151
 
153
- `validateTwoFactorToken` rejects a token that was not issued for the two-factor purpose, and resolves the `User` for you so the verification route can read `twoFactorMethods`, `twoFactorSecret` and the rest without a second lookup. Whatever is wrong with the token (not a JWT, unknown user, bad signature, expired, another purpose), it throws the same `HTTPResult(401, "error.invalid_2fa_token")`, so a caller cannot tell which user ids exist. `expiresIn` is the token's lifetime in milliseconds.
152
+ A two-factor token lives five minutes, and `expiresIn` gives that lifetime in milliseconds. `validateTwoFactorToken` rejects a token that was not issued for the two-factor purpose. It resolves the `User` for you, so the verification route can read `twoFactorMethods`, `twoFactorSecret` and the other fields without a second lookup. Whatever is wrong with the token, it throws the same `HTTPResult(401, "error.invalid_2fa_token")`: not a JWT, unknown user, bad signature, expired, or another purpose. A caller therefore cannot tell which user ids exist.
154
153
 
155
154
  ```typescript
156
155
  import { createHash } from "node:crypto";
@@ -192,13 +191,13 @@ export async function requestEmailCode(
192
191
  }
193
192
  ```
194
193
 
195
- Once the code checks out, the route issues a real access and refresh pair with the `tenantId` the two-factor token carried. `send2FAEmail` and the other mail entry points are covered in [Users](/docs/interfaces/auth/users).
194
+ Once the code checks out, the route issues a real access and refresh pair for the `tenantId` the two-factor token carried. [Users](/docs/interfaces/auth/users) covers `send2FAEmail` and the other mail functions.
196
195
 
197
- ## Hand Off Tenant Assignment
196
+ ## Hand off tenant assignment
198
197
 
199
- A user whose credentials are valid but who belongs to no tenant yet cannot receive an access token, because an access token is always scoped to a tenant. `generateTenantAssignmentToken` covers that gap: it signs the user without a tenant claim so an onboarding flow can pick or create one.
198
+ A user whose credentials are valid but who belongs to no tenant yet cannot receive an access token, because an access token is always scoped to a tenant. `generateTenantAssignmentToken` fills that gap. It signs the user without a tenant claim, so an onboarding flow can pick or create a tenant.
200
199
 
201
- ```typescript
200
+ ```typescript fragment
202
201
  generateTenantAssignmentToken(
203
202
  user: User,
204
203
  ): Promise<{ token: string; expiresIn: number }>
@@ -206,7 +205,7 @@ generateTenantAssignmentToken(
206
205
  validateTenantAssignmentToken(token: string): Promise<{ id: string; user: User }>
207
206
  ```
208
207
 
209
- `validateTenantAssignmentToken` rejects a token that was not issued for the tenant-assignment purpose and returns the user id together with the loaded `User`. Like the two-factor check, every refusal is the same `HTTPResult(401, "Invalid tenant assignment token")`.
208
+ A tenant-assignment token lives fifteen minutes. `validateTenantAssignmentToken` rejects a token that was not issued for the tenant-assignment purpose, and returns the user id together with the loaded `User`. Like the two-factor check, every refusal is the same `HTTPResult(401, "Invalid tenant assignment token")`.
210
209
 
211
210
  ```typescript
212
211
  import {
@@ -231,7 +230,7 @@ export async function completeTenantAssignment(
231
230
  }
232
231
  ```
233
232
 
234
- ## The Token Payload
233
+ ## The token payload
235
234
 
236
235
  `JwtUserPayload` describes the claims an access or refresh token carries about its subject. Use it as the target type when you decode a token yourself.
237
236
 
@@ -247,15 +246,15 @@ export interface JwtUserPayload {
247
246
  | ----- | ---- | ----------- |
248
247
  | `id` | `string` | The `_id` of the user the token was issued for. |
249
248
  | `tenantId` | `string` | The tenant the token is scoped to. |
250
- | `sessionId` | `string \| undefined` | The `Session` row backing the token, when the token was issued with one. |
249
+ | `sessionId` | `string \| undefined` | The `Session` row behind the token, when the token was issued with one. |
251
250
 
252
- `TenantTokenInput` from [Authentication](/docs/interfaces/auth/authentication) names the same subject from the other side: it is what a validator receives — `id` and `tenantId` plus the undecoded `rawToken` — while `JwtUserPayload` is what the token itself says. The two overlap on `id` and `tenantId`; neither is a subset of the other.
251
+ `TenantTokenInput`, from [Authentication](/docs/interfaces/auth/authentication), describes the same subject from the other side. It is what a validator receives: `id` and `tenantId`, plus the undecoded `rawToken`. `JwtUserPayload` is what the token itself says. The two types share `id` and `tenantId`, and neither is a subset of the other.
253
252
 
254
- ## Record a Login Session
253
+ ## Record a login session
255
254
 
256
- `createSession` inserts a `Session` row for a login and returns its `_id`, ready to be passed as the `sessionId` of the token pair.
255
+ `createSession` inserts a `Session` row for a login and returns its `_id`. Pass that id as the `sessionId` of the token pair.
257
256
 
258
- ```typescript
257
+ ```typescript fragment
259
258
  createSession(
260
259
  sessionModel: SessionModel,
261
260
  userId: string,
@@ -268,14 +267,14 @@ createSession(
268
267
  | --------- | ----------- |
269
268
  | `sessionModel` | The `SessionModel` instance to insert through. |
270
269
  | `userId` | The `_id` of the user logging in. |
271
- | `userAgent` | The request's `User-Agent` header. It is parsed into the `browser`, `os` and `deviceType` fields; the raw string is kept in `userAgent`. |
272
- | `ip` | The caller's IP address, stored as-is. |
270
+ | `userAgent` | The `User-Agent` header of the request. The DMS parses it into the `browser`, `os` and `deviceType` fields and keeps the raw string in `userAgent`. |
271
+ | `ip` | The IP address of the caller, stored as given. |
273
272
 
274
- The row starts with an empty `refreshToken` and `location`, and with `createdAt` and `lastActiveAt` set to the current time. Record the refresh token with `sessionModel.replaceRefreshToken` once you have generated it, as in the first example on this page.
273
+ The row starts with no refresh token hash, an empty `location`, and `createdAt` and `lastActiveAt` set to the current time. Record the refresh token with `sessionModel.replaceRefreshToken` once you have generated it, as in the first example on this page.
275
274
 
276
- ## The Session Table
275
+ ## The session table
277
276
 
278
- `Session` is registered as the `sessions` table under the DMS core schema, so its rows are shared across tenants and its model is retrieved without a tenant instance. The class, its table-name constant and its model all live on the `/db` subpath.
277
+ `Session` is registered as the `sessions` table in the DMS core schema. Its rows are shared across tenants, and you obtain its model without a tenant instance. The class, its table-name constant and its model all live in `@antelopejs/interface-dms/auth/db`.
279
278
 
280
279
  ```typescript
281
280
  import {
@@ -287,10 +286,12 @@ import {
287
286
 
288
287
  | Field | Type | Description |
289
288
  | ----- | ---- | ----------- |
290
- | `_id` | `string` | Primary key. This is the value that travels in the token's `sessionId` claim. |
291
- | `userId` | `string` | The owning user's `_id`. Indexed, and declared as a relation to the `User` table. |
292
- | `refreshTokenHash` | `string \| null` | sha256 of the refresh token currently valid for this session. Matching it on refresh is what makes a session revocable; the token itself is never stored. |
293
- | `sealedRefreshToken` | `string \| null` | The current refresh token encrypted under a key derived from its predecessor, so a client still holding the predecessor during the rotation grace window can be handed the current token. Unreadable without the predecessor. |
289
+ | `_id` | `string` | Primary key. This value travels in the `sessionId` claim of the token. |
290
+ | `userId` | `string` | The `_id` of the owning user. Indexed, and declared as a relation to the `User` table. |
291
+ | `refreshTokenHash` | `string \| null`, optional | SHA-256 of the refresh token currently valid for this session. A refresh matches against it, which makes the session revocable. The token itself is never stored. |
292
+ | `sealedRefreshToken` | `string \| null`, optional | The current refresh token, encrypted under a key derived from its predecessor. A client that still holds the predecessor during the rotation grace window can get the current token back. Without the predecessor, the value is unreadable. |
293
+ | `previousRefreshTokenHash` | `string \| null`, optional | SHA-256 of the refresh token the last rotation replaced. |
294
+ | `refreshTokenRotatedAt` | `Date \| null`, optional | When the last rotation happened. It starts the grace window. |
294
295
  | `userAgent` | `string` | The raw `User-Agent` string captured at login. |
295
296
  | `ip` | `string` | The IP address captured at login. |
296
297
  | `browser` | `string` | Browser name and version parsed from `userAgent`, or `"Unknown"`. |
@@ -298,23 +299,23 @@ import {
298
299
  | `deviceType` | `string` | Device class parsed from `userAgent`: `"mobile"`, `"tablet"`, or `"desktop"` when neither applies. |
299
300
  | `location` | `string` | Free-form location label. `createSession` leaves it empty. |
300
301
  | `createdAt` | `Date` | Set on insert by the creation-time decorator. Indexed. |
301
- | `lastActiveAt` | `Date` | Last time the session was seen. Refresh handlers update it. Indexed: a daily job deletes the sessions last active longer ago than `refreshTokenLifetime`. |
302
+ | `lastActiveAt` | `Date` | The last time the session was used. Refresh handlers update it. Indexed. Every day at 03:30, a DMS job deletes the sessions last active longer ago than `refreshTokenLifetime`. |
302
303
 
303
304
  `SESSIONS_TABLE_NAME` holds the table name, `"sessions"`.
304
305
 
305
- `isCurrentRefreshToken(session, token)` tells whether a presented token is the session's current one, comparing hashes in constant time and still honouring a session written before hashing.
306
+ `isCurrentRefreshToken(session, token)` tells whether a presented token is the current one of the session. It compares hashes in constant time, and returns `false` when the session has no `refreshTokenHash`.
306
307
 
307
- ## Query Sessions with SessionModel
308
+ ## Query sessions with `SessionModel`
308
309
 
309
- `SessionModel` extends `BasicDataModel(Session, SESSIONS_TABLE_NAME)`, so it has the standard `get`, `getBy`, `getAll`, `insert`, `update` and `delete` operations, plus the refresh-token operations and two lookups by user.
310
+ `SessionModel` extends `BasicDataModel(Session, SESSIONS_TABLE_NAME)`. It has the standard `get`, `getBy`, `getAll`, `insert`, `update` and `delete` operations, plus the refresh-token operations and two lookups by user.
310
311
 
311
312
  | Method | Signature | Description |
312
313
  | ------ | --------- | ----------- |
313
- | `replaceRefreshToken` | `(sessionId: string, refreshToken: string) => Promise<void>` | Make a token the session's current one, storing only its hash. |
314
- | `rotateRefreshToken` | `(sessionId: string, presentedToken: string, refreshToken: string, rotatedAt?: Date) => Promise<string \| null>` | Atomically replace the presented token with a new one. A client presenting the immediate predecessor within the grace window gets the current token back; any other token gets `null`. |
315
- | `deleteInactiveSince` | `(threshold: Date) => Promise<void>` | Delete the sessions last active before a date. |
316
- | `getByUserId` | `(userId: string) => Promise<Session[]>` | Every session belonging to a user, read through the `userId` index. |
317
- | `deleteByUserId` | `(userId: string) => Promise<void>` | Delete every session belonging to a user. |
314
+ | `replaceRefreshToken` | `(sessionId: string, refreshToken: string) => Promise<void>` | Makes a token the current one of the session, storing only its hash. Clears the sealed token and the predecessor, so no grace window applies. |
315
+ | `rotateRefreshToken` | `(sessionId: string, presentedToken: string, refreshToken: string, rotatedAt?: Date) => Promise<string \| null>` | Replaces the presented token with a new one in one atomic update, and sets `lastActiveAt`. A client that presents the immediate predecessor within the 15-second grace window gets the current token back. Any other token gets `null`. |
316
+ | `deleteInactiveSince` | `(threshold: Date) => Promise<void>` | Deletes the sessions last active before a date. |
317
+ | `getByUserId` | `(userId: string) => Promise<Session[]>` | Every session of a user, read through the `userId` index. |
318
+ | `deleteByUserId` | `(userId: string) => Promise<void>` | Deletes every session of a user. |
318
319
 
319
320
  ```typescript
320
321
  import { Controller, Delete, Get } from "@antelopejs/interface-api";
@@ -345,8 +346,8 @@ export class SessionsController extends Controller("/api/sessions") {
345
346
  }
346
347
  ```
347
348
 
348
- Deleting a session stops refreshes from succeeding and cuts off the access tokens issued for it at once: the authentication decorators refuse an access token whose `sessionId` no longer names a session of its user. A token issued without a `sessionId` stays valid until it expires; to cut those off too, rotate the user's `authKey` as described in [Users](/docs/interfaces/auth/users).
349
+ Deleting a session stops its refreshes, and cuts off the access tokens issued for it at once. The authentication decorators refuse an access token whose `sessionId` no longer names a session of its user. A token issued without a `sessionId` stays valid until it expires. To cut those tokens off too, rotate the user's `authKey`, as described in [Users](/docs/interfaces/auth/users).
349
350
 
350
- ## Next Steps
351
+ ## Next steps
351
352
 
352
- Continue with [Users](/docs/interfaces/auth/users) for the `User` table, `UserModel`, `sanitizeUser`, and the account mail entry points.
353
+ Continue with [Users](/docs/interfaces/auth/users) for the `User` table, `UserModel`, `sanitizeUser`, and the account mail functions.