ldap-rest 1.2.1 → 2.0.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 (358) hide show
  1. package/bin/sync-james.mjs +13 -2
  2. package/dist/abstract/ldapFlat.js +1 -1
  3. package/dist/abstract/plugin.js +1 -1
  4. package/dist/abstract/twakePlugin.js +1 -1
  5. package/dist/bin/index.js +1 -1
  6. package/dist/config/args.js +1 -1
  7. package/dist/config/options.js +1 -0
  8. package/dist/config/schema.js +1 -1
  9. package/dist/lib/auth/base.js +1 -1
  10. package/dist/lib/authz/base.js +1 -1
  11. package/dist/lib/entitySchema/validator.js +1 -1
  12. package/dist/lib/errors.js +1 -1
  13. package/dist/lib/expressFormatedResponses.js +1 -1
  14. package/dist/lib/health.js +1 -1
  15. package/dist/lib/hookBus.js +1 -0
  16. package/dist/lib/instanceProviders.js +1 -1
  17. package/dist/lib/ldap/callerView.js +1 -0
  18. package/dist/lib/ldap/pool.js +1 -0
  19. package/dist/lib/ldap/schema.js +1 -0
  20. package/dist/lib/ldap/searchCache.js +1 -0
  21. package/dist/lib/ldapActions.js +1 -1
  22. package/dist/lib/ldapSchema.js +1 -1
  23. package/dist/lib/parseConfig.js +1 -1
  24. package/dist/lib/route.js +1 -0
  25. package/dist/lib/schemaFile.js +1 -1
  26. package/dist/lib/services/index.js +1 -0
  27. package/dist/lib/storage/store.js +1 -1
  28. package/dist/lib/utils.js +1 -1
  29. package/dist/lib/version.js +1 -0
  30. package/dist/logger/winston.js +1 -1
  31. package/dist/plugins/auth/auth.options.js +1 -0
  32. package/dist/plugins/auth/authzDynamic.js +1 -1
  33. package/dist/plugins/auth/authzLinid1.js +1 -1
  34. package/dist/plugins/auth/authzPerBranch.js +1 -1
  35. package/dist/plugins/auth/authzPerRoute.js +1 -1
  36. package/dist/plugins/auth/authzScope.js +1 -1
  37. package/dist/plugins/auth/crowdsec.js +1 -1
  38. package/dist/plugins/auth/fake.js +1 -1
  39. package/dist/plugins/auth/hmac.js +1 -1
  40. package/dist/plugins/auth/llng.js +1 -1
  41. package/dist/plugins/auth/openidconnect.js +1 -1
  42. package/dist/plugins/auth/rateLimit.js +1 -1
  43. package/dist/plugins/auth/token.js +1 -1
  44. package/dist/plugins/auth/totp.js +1 -1
  45. package/dist/plugins/auth/trustedProxy.js +1 -1
  46. package/dist/plugins/bcl.js +1 -1
  47. package/dist/plugins/bcl.options.js +1 -0
  48. package/dist/plugins/configApi.js +1 -1
  49. package/dist/plugins/demo/helloworld.js +1 -1
  50. package/dist/plugins/ldap/accountLifecycle.js +1 -1
  51. package/dist/plugins/ldap/bulkImport.js +1 -1
  52. package/dist/plugins/ldap/departmentSync.js +1 -1
  53. package/dist/plugins/ldap/enterpriseRules.js +1 -1
  54. package/dist/plugins/ldap/externalUsersInGroups.js +1 -1
  55. package/dist/plugins/ldap/flatGeneric.js +1 -1
  56. package/dist/plugins/ldap/groups.js +1 -1
  57. package/dist/plugins/ldap/ldap.options.js +1 -0
  58. package/dist/plugins/ldap/onChange.js +1 -1
  59. package/dist/plugins/ldap/organizations.js +1 -1
  60. package/dist/plugins/ldap/passwordPolicy.js +1 -1
  61. package/dist/plugins/ldap/raw.js +1 -1
  62. package/dist/plugins/ldap/trash.js +1 -1
  63. package/dist/plugins/metrics.js +1 -1
  64. package/dist/plugins/metrics.options.js +1 -0
  65. package/dist/plugins/rabbitmq.js +1 -1
  66. package/dist/plugins/rabbitmq.options.js +1 -0
  67. package/dist/plugins/scim/baseResolver.js +1 -1
  68. package/dist/plugins/scim/bulk.js +1 -1
  69. package/dist/plugins/scim/discovery.js +1 -1
  70. package/dist/plugins/scim/errors.js +1 -1
  71. package/dist/plugins/scim/filter.js +1 -1
  72. package/dist/plugins/scim/groups.js +1 -1
  73. package/dist/plugins/scim/mapping.js +1 -1
  74. package/dist/plugins/scim/patch.js +1 -1
  75. package/dist/plugins/scim/scim.js +1 -1
  76. package/dist/plugins/scim/scim.options.js +1 -0
  77. package/dist/plugins/scim/users.js +1 -1
  78. package/dist/plugins/static.js +1 -1
  79. package/dist/plugins/static.options.js +1 -0
  80. package/dist/plugins/storage/file.js +1 -1
  81. package/dist/plugins/storage/ldap.js +1 -1
  82. package/dist/plugins/storage/postgres.js +1 -1
  83. package/dist/plugins/storage/valkey.js +1 -1
  84. package/dist/plugins/storage.js +1 -1
  85. package/dist/plugins/storage.options.js +1 -0
  86. package/dist/plugins/twake/appAccounts.options.js +1 -0
  87. package/dist/plugins/twake/appAccountsApi.js +1 -1
  88. package/dist/plugins/twake/appAccountsConsistency.js +1 -1
  89. package/dist/plugins/twake/calendar.js +1 -1
  90. package/dist/plugins/twake/calendar.options.js +1 -0
  91. package/dist/plugins/twake/calendarResources.js +1 -1
  92. package/dist/plugins/twake/cloudery.options.js +1 -0
  93. package/dist/plugins/twake/clouderyProvision.js +1 -1
  94. package/dist/plugins/twake/cozy.options.js +1 -0
  95. package/dist/plugins/twake/cozyProvision.js +1 -1
  96. package/dist/plugins/twake/drive.js +1 -1
  97. package/dist/plugins/twake/drive.options.js +1 -0
  98. package/dist/plugins/twake/groups.js +1 -1
  99. package/dist/plugins/twake/instances.js +1 -1
  100. package/dist/plugins/twake/james.js +1 -1
  101. package/dist/plugins/twake/james.options.js +1 -0
  102. package/dist/plugins/twake/lifecycleAttributes.js +1 -1
  103. package/dist/plugins/twake/lifecycleEvents.js +1 -1
  104. package/dist/plugins/twake/migrationProxy.js +1 -1
  105. package/dist/plugins/twake/migrationProxy.options.js +1 -0
  106. package/dist/plugins/twake/spaces.js +1 -1
  107. package/dist/plugins/twake/tombstone.js +1 -1
  108. package/dist/plugins/twake/twakeGroups.options.js +1 -0
  109. package/dist/plugins/twake/twakeInstances.options.js +1 -0
  110. package/dist/plugins/twake/twakeLifecycle.options.js +1 -0
  111. package/dist/plugins/twake/twakeSpaces.options.js +1 -0
  112. package/dist/plugins/twake/twakeTombstone.options.js +1 -0
  113. package/dist/plugins/weblogs.js +1 -1
  114. package/dist/src/abstract/ldapFlat.d.ts +41 -10
  115. package/dist/src/abstract/plugin.d.ts +31 -5
  116. package/dist/src/abstract/twakePlugin.d.ts +14 -4
  117. package/dist/src/bin/index.d.ts +35 -4
  118. package/dist/src/config/args.d.ts +2 -4
  119. package/dist/src/config/options.d.ts +104 -0
  120. package/dist/src/config/schema.d.ts +50 -1
  121. package/dist/src/hooks.d.ts +60 -22
  122. package/dist/src/lib/authz/base.d.ts +4 -51
  123. package/dist/src/lib/authz/composition.d.ts +2 -2
  124. package/dist/src/lib/entitySchema/validator.d.ts +63 -6
  125. package/dist/src/lib/errors.d.ts +57 -1
  126. package/dist/src/lib/expressFormatedResponses.d.ts +49 -7
  127. package/dist/src/lib/hookBus.d.ts +226 -0
  128. package/dist/src/lib/instanceProviders.d.ts +0 -8
  129. package/dist/src/lib/ldap/callerView.d.ts +45 -0
  130. package/dist/src/lib/ldap/pool.d.ts +108 -0
  131. package/dist/src/lib/ldap/schema.d.ts +157 -0
  132. package/dist/src/lib/ldap/searchCache.d.ts +112 -0
  133. package/dist/src/lib/ldapActions.d.ts +26 -256
  134. package/dist/src/lib/parseConfig.d.ts +31 -2
  135. package/dist/src/lib/route.d.ts +99 -0
  136. package/dist/src/lib/services/index.d.ts +56 -0
  137. package/dist/src/lib/utils.d.ts +100 -36
  138. package/dist/src/lib/version.d.ts +12 -0
  139. package/dist/src/plugins/auth/auth.options.d.ts +88 -0
  140. package/dist/src/plugins/auth/authzDynamic.d.ts +10 -1
  141. package/dist/src/plugins/auth/authzLinid1.d.ts +6 -0
  142. package/dist/src/plugins/auth/authzPerBranch.d.ts +9 -0
  143. package/dist/src/plugins/auth/authzPerRoute.d.ts +3 -0
  144. package/dist/src/plugins/auth/authzScope.d.ts +23 -14
  145. package/dist/src/plugins/auth/crowdsec.d.ts +5 -0
  146. package/dist/src/plugins/auth/fake.d.ts +3 -0
  147. package/dist/src/plugins/auth/hmac.d.ts +4 -0
  148. package/dist/src/plugins/auth/llng.d.ts +4 -0
  149. package/dist/src/plugins/auth/openidconnect.d.ts +7 -0
  150. package/dist/src/plugins/auth/rateLimit.d.ts +4 -0
  151. package/dist/src/plugins/auth/token.d.ts +3 -0
  152. package/dist/src/plugins/auth/totp.d.ts +5 -0
  153. package/dist/src/plugins/auth/trustedProxy.d.ts +4 -0
  154. package/dist/src/plugins/bcl.d.ts +3 -0
  155. package/dist/src/plugins/bcl.options.d.ts +8 -0
  156. package/dist/src/plugins/configApi.d.ts +24 -5
  157. package/dist/src/plugins/demo/helloworld.d.ts +8 -19
  158. package/dist/src/plugins/ldap/accountLifecycle.d.ts +17 -0
  159. package/dist/src/plugins/ldap/bulkImport.d.ts +6 -76
  160. package/dist/src/plugins/ldap/departmentSync.d.ts +1 -0
  161. package/dist/src/plugins/ldap/enterpriseRules.d.ts +8 -15
  162. package/dist/src/plugins/ldap/externalUsersInGroups.d.ts +4 -0
  163. package/dist/src/plugins/ldap/flatGeneric.d.ts +4 -0
  164. package/dist/src/plugins/ldap/groups.d.ts +27 -11
  165. package/dist/src/plugins/ldap/ldap.options.d.ts +75 -0
  166. package/dist/src/plugins/ldap/onChange.d.ts +10 -2
  167. package/dist/src/plugins/ldap/organizations.d.ts +16 -0
  168. package/dist/src/plugins/ldap/passwordPolicy.d.ts +35 -3
  169. package/dist/src/plugins/ldap/raw.d.ts +50 -19
  170. package/dist/src/plugins/ldap/trash.d.ts +6 -0
  171. package/dist/src/plugins/metrics.d.ts +3 -0
  172. package/dist/src/plugins/metrics.options.d.ts +8 -0
  173. package/dist/src/plugins/rabbitmq.d.ts +3 -0
  174. package/dist/src/plugins/rabbitmq.options.d.ts +8 -0
  175. package/dist/src/plugins/scim/baseResolver.d.ts +2 -1
  176. package/dist/src/plugins/scim/bulk.d.ts +6 -7
  177. package/dist/src/plugins/scim/discovery.d.ts +3 -0
  178. package/dist/src/plugins/scim/errors.d.ts +2 -1
  179. package/dist/src/plugins/scim/groups.d.ts +6 -4
  180. package/dist/src/plugins/scim/mapping.d.ts +16 -3
  181. package/dist/src/plugins/scim/scim.d.ts +37 -3
  182. package/dist/src/plugins/scim/scim.options.d.ts +35 -0
  183. package/dist/src/plugins/scim/types.d.ts +2 -0
  184. package/dist/src/plugins/scim/users.d.ts +6 -7
  185. package/dist/src/plugins/static.d.ts +9 -0
  186. package/dist/src/plugins/static.options.d.ts +13 -0
  187. package/dist/src/plugins/storage.d.ts +12 -1
  188. package/dist/src/plugins/storage.options.d.ts +16 -0
  189. package/dist/src/plugins/twake/appAccounts.options.d.ts +13 -0
  190. package/dist/src/plugins/twake/appAccountsApi.d.ts +18 -0
  191. package/dist/src/plugins/twake/appAccountsConsistency.d.ts +8 -0
  192. package/dist/src/plugins/twake/calendar.d.ts +25 -2
  193. package/dist/src/plugins/twake/calendar.options.d.ts +19 -0
  194. package/dist/src/plugins/twake/cloudery.options.d.ts +26 -0
  195. package/dist/src/plugins/twake/clouderyProvision.d.ts +18 -0
  196. package/dist/src/plugins/twake/cozy.options.d.ts +23 -0
  197. package/dist/src/plugins/twake/cozyProvision.d.ts +14 -0
  198. package/dist/src/plugins/twake/drive.d.ts +7 -0
  199. package/dist/src/plugins/twake/drive.options.d.ts +15 -0
  200. package/dist/src/plugins/twake/groups.d.ts +29 -1
  201. package/dist/src/plugins/twake/instances.d.ts +74 -10
  202. package/dist/src/plugins/twake/james.d.ts +17 -0
  203. package/dist/src/plugins/twake/james.options.d.ts +21 -0
  204. package/dist/src/plugins/twake/lifecycleAttributes.d.ts +13 -2
  205. package/dist/src/plugins/twake/lifecycleEvents.d.ts +12 -0
  206. package/dist/src/plugins/twake/migrationProxy.d.ts +11 -11
  207. package/dist/src/plugins/twake/migrationProxy.options.d.ts +16 -0
  208. package/dist/src/plugins/twake/spaces.d.ts +30 -0
  209. package/dist/src/plugins/twake/tombstone.d.ts +25 -16
  210. package/dist/src/plugins/twake/twakeGroups.options.d.ts +20 -0
  211. package/dist/src/plugins/twake/twakeInstances.options.d.ts +43 -0
  212. package/dist/src/plugins/twake/twakeLifecycle.options.d.ts +21 -0
  213. package/dist/src/plugins/twake/twakeSpaces.options.d.ts +19 -0
  214. package/dist/src/plugins/twake/twakeTombstone.options.d.ts +17 -0
  215. package/docs/README.md +17 -2
  216. package/docs/client-development/api/rest-api.md +13 -3
  217. package/docs/client-development/schemas/README.md +96 -32
  218. package/docs/development/contracts.md +109 -0
  219. package/docs/plugin-development/README.md +53 -95
  220. package/docs/plugin-development/dependencies.md +24 -8
  221. package/docs/plugin-development/hooks.md +143 -23
  222. package/docs/plugin-development/openapi.md +14 -1
  223. package/docs/plugin-development/options.md +136 -0
  224. package/docs/plugin-development/routes.md +152 -0
  225. package/docs/plugin-development/services.md +95 -0
  226. package/docs/plugin-development/testing.md +3 -3
  227. package/docs/usage/configuration.md +18 -11
  228. package/docs/usage/operations.md +28 -4
  229. package/docs/usage/plugins/integrations/instances.md +11 -3
  230. package/docs/usage/plugins/integrations/lifecycle-events.md +4 -1
  231. package/docs/usage/plugins/integrations/scim.md +20 -18
  232. package/docs/usage/plugins/integrations/tombstone.md +10 -6
  233. package/docs/usage/plugins/ldap/enterprise-rules.md +10 -1
  234. package/docs/usage/plugins/ldap/flat-generic.md +11 -0
  235. package/docs/usage/plugins/ldap/groups.md +4 -1
  236. package/docs/usage/plugins/ldap/password-policy.md +7 -0
  237. package/docs/usage/plugins/ldap/raw.md +17 -1
  238. package/docs/usage/upgrading.md +253 -0
  239. package/package.json +372 -286
  240. package/static/browser/ldap-browser/LdapBrowser.js +8 -6
  241. package/static/browser/ldap-browser/LdapBrowser.js.map +1 -1
  242. package/static/browser/ldap-browser/api/RawApiClient.js +2 -0
  243. package/static/browser/ldap-browser/api/RawApiClient.js.map +1 -1
  244. package/static/browser/ldap-browser/components/EntryTree.js +9 -5
  245. package/static/browser/ldap-browser/components/EntryTree.js.map +1 -1
  246. package/static/browser/ldap-browser/components/EntryView.js +2 -0
  247. package/static/browser/ldap-browser/components/EntryView.js.map +1 -1
  248. package/static/browser/ldap-browser/schema.js +3 -2
  249. package/static/browser/ldap-browser/schema.js.map +1 -1
  250. package/static/browser/ldap-browser.esm.js +27 -18
  251. package/static/browser/ldap-browser.esm.js.map +1 -1
  252. package/static/browser/ldap-browser.js +27 -18
  253. package/static/browser/ldap-browser.js.map +1 -1
  254. package/static/browser/ldap-browser.min.js +1 -1
  255. package/static/browser/ldap-browser.min.js.map +1 -1
  256. package/static/browser/ldap-group-editor/LdapGroupEditor.js +8 -6
  257. package/static/browser/ldap-group-editor/LdapGroupEditor.js.map +1 -1
  258. package/static/browser/ldap-group-editor/api/GroupApiClient.js +1 -0
  259. package/static/browser/ldap-group-editor/api/GroupApiClient.js.map +1 -1
  260. package/static/browser/ldap-group-editor/components/CreateGroupModal.js +5 -1
  261. package/static/browser/ldap-group-editor/components/CreateGroupModal.js.map +1 -1
  262. package/static/browser/ldap-group-editor/components/GroupPropertyEditor.js +6 -3
  263. package/static/browser/ldap-group-editor/components/GroupPropertyEditor.js.map +1 -1
  264. package/static/browser/ldap-group-editor/components/GroupTree.js +6 -3
  265. package/static/browser/ldap-group-editor/components/GroupTree.js.map +1 -1
  266. package/static/browser/ldap-group-editor/components/MoveGroupModal.js +6 -3
  267. package/static/browser/ldap-group-editor/components/MoveGroupModal.js.map +1 -1
  268. package/static/browser/ldap-group-editor.esm.js +32 -16
  269. package/static/browser/ldap-group-editor.esm.js.map +1 -1
  270. package/static/browser/ldap-group-editor.js +32 -16
  271. package/static/browser/ldap-group-editor.js.map +1 -1
  272. package/static/browser/ldap-group-editor.min.js +1 -1
  273. package/static/browser/ldap-group-editor.min.js.map +1 -1
  274. package/static/browser/ldap-resource-editor/api/ResourceApiClient.js +3 -0
  275. package/static/browser/ldap-resource-editor/api/ResourceApiClient.js.map +1 -1
  276. package/static/browser/ldap-resource-editor/cache/CacheManager.js +3 -1
  277. package/static/browser/ldap-resource-editor/cache/CacheManager.js.map +1 -1
  278. package/static/browser/ldap-tree-viewer/LdapTreeViewer.js +6 -1
  279. package/static/browser/ldap-tree-viewer/LdapTreeViewer.js.map +1 -1
  280. package/static/browser/ldap-tree-viewer/api/LdapApiClient.js +2 -0
  281. package/static/browser/ldap-tree-viewer/api/LdapApiClient.js.map +1 -1
  282. package/static/browser/ldap-tree-viewer/components/TreeNode.js +4 -0
  283. package/static/browser/ldap-tree-viewer/components/TreeNode.js.map +1 -1
  284. package/static/browser/ldap-tree-viewer/components/TreeRoot.js +3 -0
  285. package/static/browser/ldap-tree-viewer/components/TreeRoot.js.map +1 -1
  286. package/static/browser/ldap-tree-viewer/store/Store.js +3 -1
  287. package/static/browser/ldap-tree-viewer/store/Store.js.map +1 -1
  288. package/static/browser/ldap-tree-viewer.esm.js +18 -2
  289. package/static/browser/ldap-tree-viewer.esm.js.map +1 -1
  290. package/static/browser/ldap-tree-viewer.js +18 -2
  291. package/static/browser/ldap-tree-viewer.js.map +1 -1
  292. package/static/browser/ldap-tree-viewer.min.js +1 -1
  293. package/static/browser/ldap-tree-viewer.min.js.map +1 -1
  294. package/static/browser/ldap-unit-editor/LdapUnitEditor.js +7 -5
  295. package/static/browser/ldap-unit-editor/LdapUnitEditor.js.map +1 -1
  296. package/static/browser/ldap-unit-editor/api/UnitApiClient.js +1 -0
  297. package/static/browser/ldap-unit-editor/api/UnitApiClient.js.map +1 -1
  298. package/static/browser/ldap-unit-editor/components/MoveUnitModal.js +7 -4
  299. package/static/browser/ldap-unit-editor/components/MoveUnitModal.js.map +1 -1
  300. package/static/browser/ldap-unit-editor/components/UnitPropertyEditor.js +7 -4
  301. package/static/browser/ldap-unit-editor/components/UnitPropertyEditor.js.map +1 -1
  302. package/static/browser/ldap-unit-editor/components/UnitTree.js +6 -3
  303. package/static/browser/ldap-unit-editor/components/UnitTree.js.map +1 -1
  304. package/static/browser/ldap-unit-editor.esm.js +28 -16
  305. package/static/browser/ldap-unit-editor.esm.js.map +1 -1
  306. package/static/browser/ldap-unit-editor.js +28 -16
  307. package/static/browser/ldap-unit-editor.js.map +1 -1
  308. package/static/browser/ldap-unit-editor.min.js +1 -1
  309. package/static/browser/ldap-unit-editor.min.js.map +1 -1
  310. package/static/browser/ldap-user-editor/LdapUserEditor.js +9 -7
  311. package/static/browser/ldap-user-editor/LdapUserEditor.js.map +1 -1
  312. package/static/browser/ldap-user-editor/api/UserApiClient.js +2 -0
  313. package/static/browser/ldap-user-editor/api/UserApiClient.js.map +1 -1
  314. package/static/browser/ldap-user-editor/cache/CacheManager.js +3 -1
  315. package/static/browser/ldap-user-editor/cache/CacheManager.js.map +1 -1
  316. package/static/browser/ldap-user-editor/components/MoveUserModal.js +7 -4
  317. package/static/browser/ldap-user-editor/components/MoveUserModal.js.map +1 -1
  318. package/static/browser/ldap-user-editor/components/PointerField.js +6 -1
  319. package/static/browser/ldap-user-editor/components/PointerField.js.map +1 -1
  320. package/static/browser/ldap-user-editor/components/UserEditor.js +10 -5
  321. package/static/browser/ldap-user-editor/components/UserEditor.js.map +1 -1
  322. package/static/browser/ldap-user-editor/components/UserList.js +8 -4
  323. package/static/browser/ldap-user-editor/components/UserList.js.map +1 -1
  324. package/static/browser/ldap-user-editor/components/UserTree.js +7 -3
  325. package/static/browser/ldap-user-editor/components/UserTree.js.map +1 -1
  326. package/static/browser/ldap-user-editor.esm.js +55 -30
  327. package/static/browser/ldap-user-editor.esm.js.map +1 -1
  328. package/static/browser/ldap-user-editor.js +55 -30
  329. package/static/browser/ldap-user-editor.js.map +1 -1
  330. package/static/browser/ldap-user-editor.min.js +1 -1
  331. package/static/browser/ldap-user-editor.min.js.map +1 -1
  332. package/static/browser/shared/components/DisposableComponent.js +3 -5
  333. package/static/browser/shared/components/DisposableComponent.js.map +1 -1
  334. package/static/browser/shared/components/Modal.js +2 -1
  335. package/static/browser/shared/components/Modal.js.map +1 -1
  336. package/static/browser/shared/components/StatusMessage.js +3 -2
  337. package/static/browser/shared/components/StatusMessage.js.map +1 -1
  338. package/static/browser/shared/utils/form.js.map +1 -1
  339. package/static/browser/shared/utils/hmac.js +1 -0
  340. package/static/browser/shared/utils/hmac.js.map +1 -1
  341. package/static/browser/shared/utils/totp.js +1 -0
  342. package/static/browser/shared/utils/totp.js.map +1 -1
  343. package/static/browser/shared.esm.js +9 -8
  344. package/static/browser/shared.esm.js.map +1 -1
  345. package/static/browser/shared.js +9 -8
  346. package/static/browser/shared.js.map +1 -1
  347. package/static/browser/shared.min.js +1 -1
  348. package/static/browser/shared.min.js.map +1 -1
  349. package/static/schemas/ad/groups.json +1 -1
  350. package/static/schemas/ad/users.json +3 -3
  351. package/static/schemas/example/organizations.json +2 -2
  352. package/static/schemas/example/users.json +2 -2
  353. package/static/schemas/obm/users.json +2 -2
  354. package/static/schemas/standard/groups.json +1 -1
  355. package/static/schemas/standard/users.json +2 -2
  356. package/static/schemas/twake/groups.json +4 -4
  357. package/static/schemas/twake/teamMailboxes.json +3 -3
  358. package/static/schemas/twake/users.json +7 -7
@@ -149,6 +149,11 @@ of the environment variable. An empty value on the command line, such as an
149
149
  unset variable expanding to nothing, stops the server: leave the option out
150
150
  to keep the default.
151
151
 
152
+ An option or `DM_*` variable that no declared option reads is named in a
153
+ warning at startup. `--strict-options` refuses it instead. Kubernetes injects
154
+ `DM_*` variables for services whose name starts with `dm`; leave the flag off
155
+ where those names are in use.
156
+
152
157
  ## General Options
153
158
 
154
159
  | CLI | Plural | Env | Default | Description |
@@ -160,6 +165,7 @@ to keep the default.
160
165
  | `--logger` | | `DM_LOGGER` | `console` | `console` or `file`, see [Logger](#logger---logger) |
161
166
  | `--log-file` | | `DM_LOG_FILE` | `error.log` | File `--logger file` writes to |
162
167
  | `--debug` | | `DM_DEBUG` | `false` | Name the failure in the 5xx answers of the error middleware and `serverError`; not for production |
168
+ | `--strict-options` | | `DM_STRICT_OPTIONS` | `false` | Refuse an option or `DM_*` variable no declared option reads |
163
169
  | `--api-prefix` | | `DM_API_PREFIX` | `/api` | API URL prefix |
164
170
  | `--mail-domain` | `--mail-domains` | `DM_MAIL_DOMAIN` | `[]` | Mail domains |
165
171
  | `--schemas-path` | | `DM_SCHEMAS_PATH` | `static/schemas` | Path to JSON schemas |
@@ -229,15 +235,15 @@ at `0` otherwise.
229
235
 
230
236
  #### `core/ldap/groups`
231
237
 
232
- | CLI | Plural | Env | Default | Description |
233
- | ---------------------------------- | ----------------- | ------------------------------- | ---------------------------------- | --------------------------- |
234
- | `--ldap-group-base` | | `DM_LDAP_GROUP_BASE` | | Groups base DN |
235
- | `--ldap-groups-main-attribute` | | `DM_LDAP_GROUPS_MAIN_ATTRIBUTE` | `cn` | Group identifier attribute |
236
- | `--group-class` | `--group-classes` | `DM_GROUP_CLASSES` | `top,groupOfNames` | Group objectClasses |
237
- | `--group-allow-unexistent-members` | | `DM_ALLOW_UNEXISTENT_MEMBERS` | `false` | Allow non-existent members |
238
- | `--group-default-attributes` | | `DM_GROUP_DEFAULT_ATTRIBUTES` | `{}` | Default attributes (JSON) |
239
- | `--group-dummy-user` | | `DM_GROUP_DUMMY_USER` | `cn=fakeuser` | Dummy user for empty groups |
240
- | `--group-schema` | | `DM_GROUP_SCHEMA` | `static/schemas/twake/groups.json` | Group JSON schema path |
238
+ | CLI | Plural | Env | Default | Description |
239
+ | ----------------------------------- | ----------------- | ------------------------------- | ---------------------------------- | --------------------------- |
240
+ | `--ldap-group-base` | | `DM_LDAP_GROUP_BASE` | | Groups base DN |
241
+ | `--ldap-groups-main-attribute` | | `DM_LDAP_GROUPS_MAIN_ATTRIBUTE` | `cn` | Group identifier attribute |
242
+ | `--group-class` | `--group-classes` | `DM_GROUP_CLASSES` | `top,groupOfNames` | Group objectClasses |
243
+ | `--groups-allow-unexistent-members` | | `DM_ALLOW_UNEXISTENT_MEMBERS` | `false` | Allow non-existent members |
244
+ | `--group-default-attributes` | | `DM_GROUP_DEFAULT_ATTRIBUTES` | `{}` | Default attributes (JSON) |
245
+ | `--group-dummy-user` | | `DM_GROUP_DUMMY_USER` | `cn=fakeuser` | Dummy user for empty groups |
246
+ | `--group-schema` | | `DM_GROUP_SCHEMA` | `static/schemas/twake/groups.json` | Group JSON schema path |
241
247
 
242
248
  #### `core/ldap/externalUsersInGroups`
243
249
 
@@ -429,6 +435,7 @@ whichever of the two names it selects. A value other than `req.user` or
429
435
  | ---------------------------------- | ----------------------------------- | ------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
430
436
  | `--authz-per-branch-config` | `DM_AUTHZ_PER_BRANCH_CONFIG` | `{default:{read:true,write:false,delete:false}}` | Authorization config (JSON) |
431
437
  | `--authz-per-branch-cache-ttl` | `DM_AUTHZ_PER_BRANCH_CACHE_TTL` | `60` | Cache TTL (seconds) |
438
+ | `--ldap-group-member-attribute` | `DM_LDAP_GROUP_MEMBER_ATTRIBUTE` | `member` | Attribute a group lists its members in |
432
439
  | `--authz-filter-attached-entries` | `DM_AUTHZ_FILTER_ATTACHED_ENTRIES` | `false` | Judge an attached entry by the organization it hangs off, and filter listings accordingly. Honoured by `authzPerBranch`; always on under `authzLinid1`; does nothing under `authzDynamic`. |
433
440
  | `--authz-transit-branch` | `DM_AUTHZ_TRANSIT_BRANCH` | | Organization entries are handed over through when they are judged by attachment: every administrator sees and may claim what is there, and puts an entry there with write on the organization it leaves. An entry attached to no organization is in transit too. See [authzLinid1](plugins/auth/authz-linid1.md#transit-handing-an-entry-over). |
434
441
  | `--authz-transit-origin-attribute` | `DM_AUTHZ_TRANSIT_ORIGIN_ATTRIBUTE` | | Attribute an entry put in transit keeps the organization it leaves in, removed when it is claimed. Empty records nothing; it must exist in the directory's schema. See [authzLinid1](plugins/auth/authz-linid1.md#where-an-entry-comes-from). |
@@ -523,7 +530,7 @@ Formerly `core/twake/calendarResources`, still accepted as a deprecated alias.
523
530
  | `--calendar-concurrency` | `DM_CALENDAR_CONCURRENCY` | `10` | API concurrency |
524
531
  | `--calendar-resource-base` | `DM_CALENDAR_RESOURCE_BASE` | | Resource base DN |
525
532
  | `--calendar-resource-objectclass` | `DM_CALENDAR_RESOURCE_OBJECTCLASS` | | Resource objectClass |
526
- | `--calendar-resource-creator` | `DM_CALENDAR_RESOURCE_CREATOR` | | Resource creator |
533
+ | `--calendar-resource-creator` | `DM_CALENDAR_RESOURCE_CREATOR` | `admin@example.com` | Resource creator |
527
534
  | `--calendar-resource-domain` | `DM_CALENDAR_RESOURCE_DOMAIN` | | Resource domain |
528
535
  | `--calendar-firstname-attribute` | `DM_CALENDAR_FIRSTNAME_ATTRIBUTE` | `givenName` | Registered user first name |
529
536
  | `--calendar-lastname-attribute` | `DM_CALENDAR_LASTNAME_ATTRIBUTE` | `sn` | Registered user last name |
@@ -722,7 +729,7 @@ see [Storage](plugins/utilities/storage.md).
722
729
 
723
730
  #### `core/configApi`
724
731
 
725
- Exposes API configuration at `/api/v1/config` for client applications. Returns available features, schemas, and endpoints. No configuration options.
732
+ Exposes API configuration at `/api/v1/config` for client applications. Returns available features, schemas, endpoints, and the server's `version` — read from the `package.json` that ships with it, so a client can tell an administrator the server is older than it supports. No configuration options.
726
733
 
727
734
  ## Configuration File
728
735
 
@@ -41,7 +41,26 @@ and `/readyz` names the loaded plugins that report: on an ingress exposing
41
41
  the server to the internet, keep the two paths to the cluster.
42
42
 
43
43
  The Helm chart probes both routes over HTTP (`livenessProbe` and
44
- `readinessProbe` in `values.yaml`).
44
+ `readinessProbe` in `values.yaml`). The published image also declares a
45
+ `HEALTHCHECK` calling `GET /healthz` from inside the container, on `DM_PORT`:
46
+ `docker ps` reports the container unhealthy when it stops answering, and a
47
+ `--restart` policy restarts it as it would after a crash, while an
48
+ orchestrator with probes of its own ignores the declaration. A port given
49
+ any other way (`--port` in a configuration file, a plugin) leaves the check
50
+ on 8081.
51
+
52
+ The image runs as its unprivileged `node` user: with `docker run`, a
53
+ `DM_PORT` below 1024 stops the server at startup, where the default 8081
54
+ changes nothing.
55
+
56
+ The image is built in two stages: a builder produces the package and installs
57
+ its production dependencies, the runtime stage copies them and carries no
58
+ compiler nor package manager cache. Its base image is pinned by digest in
59
+ `scripts/buildDockerfile.ts`, so the image built is the one reviewed even if
60
+ the tag moves; the digest follows the tag it names, taken from the
61
+ [Docker Hub tag page](https://hub.docker.com/_/node/tags?name=25-alpine) and
62
+ updated by hand with it. Dependabot ignores the image: it would open a change
63
+ to the generated `Dockerfile`, which the drift check refuses.
45
64
 
46
65
  ### What the shipped plugins report
47
66
 
@@ -110,6 +129,7 @@ the rate limiting and the request id, to keep to the cluster or the host.
110
129
  | `ldap_rest_ldap_pool_wait_seconds` | histogram | | Time to get a pooled connection, opening one included |
111
130
  | `ldap_rest_ldap_pool_connections` | gauge | `state` | Pooled connections, `busy` or `idle` |
112
131
  | `ldap_rest_ldap_pool_waiting` | gauge | | Operations waiting for a connection, the pool being full |
132
+ | `ldap_rest_ldap_pool_opening` | gauge | | Connections being opened, within `--ldap-pool-size` |
113
133
  | `ldap_rest_ldap_pool_max` | gauge | | `--ldap-pool-size` |
114
134
  | `ldap_rest_ldap_search_cache_total` | counter | `result` | Cacheable searches, `hit` or `miss`; nothing when the cache is off |
115
135
  | `ldap_rest_hook_failures_total` | counter | `hook`, `plugin` | Notification hooks (`*done`, `onLdap*`) that threw, which the server logs and goes on |
@@ -117,6 +137,10 @@ the rate limiting and the request id, to keep to the cluster or the host.
117
137
  | `ldap_rest_unhandled_rejections_total` | counter | | Promise rejections nothing handled; counted by the binary, a host skipping `exitOnCrash()` leaves it at zero |
118
138
  | `process_*`, `nodejs_*` | | | The process: CPU, memory, event loop lag, handles, GC |
119
139
 
140
+ A burst of requests that has to open connections no longer opens one per
141
+ request: a connection being opened takes its place in the pool, and the
142
+ requests over `--ldap-pool-size` wait for a free one.
143
+
120
144
  A search the caller pages is timed page by page, what the caller does
121
145
  between two pages left out; the readiness ping is not timed. The route
122
146
  label is the template a route was declared with, never the URL: a label
@@ -128,9 +152,9 @@ James's does, is a call like another. A plugin calling a service through
128
152
  `this.fetch` has its calls counted under its name; the OpenID Connect
129
153
  client's calls to its provider are made by its library, and not timed.
130
154
 
131
- The instruments come from `prom-client` 15, kept while the server supports
132
- Node 20, which its successor `@prometheus-io/client` dropped: the
133
- deprecation notice `npm install` prints is expected.
155
+ The instruments come from `prom-client` 15, which `npm install` reports as
156
+ deprecated: its successor `@prometheus-io/client` is the migration to make,
157
+ and the notice is expected until it is done.
134
158
 
135
159
  The port listens on every interface. What to alert on: `/readyz` for a
136
160
  replica out of rotation, `result="error"` in
@@ -19,7 +19,13 @@ gets no instance.
19
19
  An entry holding `--twake-instance-skip-value` in
20
20
  `--twake-instance-skip-attribute`, a technical account for instance, gets
21
21
  none, and neither does a tombstone
22
- (`--twake-lifecycle-deleted-attribute`) put back in place.
22
+ (`--twake-lifecycle-deleted-attribute`) put back in place. Each expression
23
+ is tried against the canonical DN first, then against the DN as sent: an
24
+ account created under a branch written with other spacing or case is still
25
+ one, and an expression written with the directory's own spelling (`\2C`, a
26
+ doubled space) still matches. An expression naming a value that holds a
27
+ comma writes it `\2C` or `\,`: a value comma never stands in for an RDN
28
+ separator in the form matched.
23
29
  - The address (`--twake-instance-fqdn-attribute`) and the mark
24
30
  (`--twake-instance-sent-attribute`) are this plugin's to write: an add that
25
31
  carries them has them removed, and an address written by a modify is taken
@@ -80,8 +86,10 @@ before it takes its members' `user.created`. Then `organization.created` is
80
86
  published on the b2b exchange, and the entry is marked. The message carries
81
87
  the organization's id, address, domain, and its name as `organization`, read
82
88
  from `--twake-instance-organization-name-attribute`, which
83
- `ensureOrganization` fills from `name` when the entry has none. The mark, not
84
- the address, says the organization is done.
89
+ `ensureOrganization` fills from `name` when the entry has none. An id captured
90
+ from a `--twake-instance-dn` group is read from the organization entry when
91
+ one exists, so the case a caller spells the branch in is not sent. The mark,
92
+ not the address, says the organization is done.
85
93
 
86
94
  With the Cloudery, a member's `user.created` waits for its organization's: a
87
95
  member under an organization entry that is not marked yet gets its address
@@ -110,7 +110,10 @@ operational one such as `pwdAccountLockedTime` is seen on both sides.
110
110
  means entries are never tombstones, and only a removal publishes `deleted`.
111
111
  - `--twake-lifecycle-deleted-at-attribute`,
112
112
  `--twake-lifecycle-deleted-at-format` (`iso8601`, the default, or
113
- `generalizedTime`): the deletion date. It is always published as ISO 8601.
113
+ `generalizedTime`): the deletion date. It is read whether it is written as
114
+ a GeneralizedTime or as an ISO 8601 date, and always published as ISO 8601;
115
+ a value of neither shape is left out. A GeneralizedTime needs its zone; an
116
+ ISO 8601 date and time without one is read in the server's time zone.
114
117
  - `--twake-lifecycle-member-attribute` (default `member`): the attribute
115
118
  `memberAdded`, `memberRemoved` and member lists read.
116
119
  - `--twake-lifecycle-rules`: a JSON file, or the JSON itself.
@@ -223,16 +223,17 @@ and `--scim-group-mapping`.
223
223
 
224
224
  Each element of `entries` is a `MappingEntry` with the following optional fields:
225
225
 
226
- | Field | Purpose |
227
- | --------------- | -------------------------------------------------------------------------------------------------------------------- |
228
- | `scim` | **Required.** Top-level SCIM attribute name (`userName`, `displayName`, `emails`, …). |
229
- | `ldap` | Simple 1:1 mapping to an LDAP attribute. |
230
- | `ldapPrimary` | For multi-valued SCIM attributes (`emails`, `phoneNumbers`, …), the LDAP attribute that stores the _primary_ value. |
231
- | `ldapSecondary` | LDAP attribute that stores the _non-primary_ values of the same SCIM attribute (array). |
232
- | `sub` | Object that maps SCIM sub-attributes to LDAP attributes. Used for complex SCIM values like `name.familyName` → `sn`. |
233
- | `multi` | `"array"` or `"single"` (default) — hints array serialization for `ldap`. |
234
- | `readOnly` | `true` to skip this attribute on write (create/update ignore it). |
235
- | `operational` | `true` for LDAP operational attributes (e.g. `entryUUID`) — loaded on read only. |
226
+ | Field | Purpose |
227
+ | --------------- | ----------------------------------------------------------------------------------------------------------------------------- |
228
+ | `scim` | **Required.** Top-level SCIM attribute name (`userName`, `displayName`, `emails`, …). |
229
+ | `ldap` | Simple 1:1 mapping to an LDAP attribute. |
230
+ | `ldapPrimary` | For multi-valued SCIM attributes (`emails`, `phoneNumbers`, …), the LDAP attribute that stores the _primary_ value. |
231
+ | `ldapSecondary` | LDAP attribute that stores the _non-primary_ values of the same SCIM attribute (array). |
232
+ | `sub` | Object that maps SCIM sub-attributes to LDAP attributes. Used for complex SCIM values like `name.familyName` → `sn`. |
233
+ | `subDn` | Sub-attribute names in `sub` whose value is a DN (for example `["value"]` for `manager`); they are held to RFC 4514 on write. |
234
+ | `multi` | `"array"` or `"single"` (default) — hints array serialization for `ldap`. |
235
+ | `readOnly` | `true` to skip this attribute on write (create/update ignore it). |
236
+ | `operational` | `true` for LDAP operational attributes (e.g. `entryUUID`) — loaded on read only. |
236
237
 
237
238
  ### Merging
238
239
 
@@ -269,7 +270,8 @@ override only what's different and inherit the rest.
269
270
  },
270
271
  {
271
272
  "scim": "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:manager",
272
- "sub": { "value": "manager" }
273
+ "sub": { "value": "manager" },
274
+ "subDn": ["value"]
273
275
  }
274
276
  ]
275
277
  }
@@ -317,7 +319,11 @@ of them; a complex attribute takes an object whose sub-attributes are scalars
317
319
  multi-valued complex attribute such as `emails` takes a list of objects whose
318
320
  `value` is a scalar. Anything else is answered
319
321
  `400 invalidValue`, as is a PATCH operation that is not an object or whose
320
- `op` is not a string.
322
+ `op` is not a string. A reference the mapping declares a DN (`subDn`) is
323
+ refused with `400 invalidValue` when its value holds an escape RFC 4514 does
324
+ not define, as the flat routes hold a client-written DN. The directory
325
+ refuses such a value itself on an attribute of DN syntax; this names the
326
+ escape in the SCIM answer and applies wherever the mapping declares one.
321
327
 
322
328
  A PATCH `add`, or a `remove` naming values, changes only the values it names:
323
329
  values the caller's read did not show, such as group members an
@@ -715,18 +721,14 @@ Response shape (truncated):
715
721
  "id",
716
722
  "active"
717
723
  ],
718
- "mapping": [
719
- /* same shape as default-mapping.json */
720
- ]
724
+ "mapping": [/* same shape as default-mapping.json */]
721
725
  },
722
726
  {
723
727
  "id": "Group",
724
728
  "endpoint": "/scim/v2/Groups",
725
729
  "schema": "urn:ietf:params:scim:schemas:core:2.0:Group",
726
730
  "rdnAttribute": "cn",
727
- "mapping": [
728
- /* ... */
729
- ]
731
+ "mapping": [/* ... */]
730
732
  }
731
733
  ],
732
734
  "idStrategy": "rdn",
@@ -10,10 +10,13 @@ is old enough, or right away when forced.
10
10
 
11
11
  ## Behaviour
12
12
 
13
- - A delete of an entry whose DN matches `--twake-tombstone-dn` writes, in one
14
- modify: the deleted attribute, the deletion date (now), the reason, the
15
- lock, and removes `--twake-tombstone-clear-attributes`. Other entries are
16
- deleted as usual.
13
+ - A delete of an entry whose DN matches `--twake-tombstone-dn` — under any
14
+ spelling the directory folds, so spaces, case and escapes do not matter —
15
+ writes, in one modify: the deleted attribute, the deletion date (now), the
16
+ reason, the lock, and removes `--twake-tombstone-clear-attributes`. Other
17
+ entries are deleted as usual. A multi-valued RDN may not match: an
18
+ expression anchored on `uid=` misses a DN written `cn=…+uid=…`, and that
19
+ delete removes the entry for good.
17
20
  - A delete of an existing tombstone writes nothing and answers as a delete.
18
21
  It fires the `twakedeletionreplay` hook with the tombstone, so
19
22
  [lifecycle events](lifecycle-events.md) publishes the deletion again, with
@@ -62,8 +65,9 @@ Content-Type: application/json
62
65
 
63
66
  - `200`: erased.
64
67
  - `404`: no tombstone at this DN.
65
- - `409`: the deletion is younger than `--twake-tombstone-erase-min-age` and
66
- `force` is not true.
68
+ - `409`: `force` is not true, and either the deletion is younger than
69
+ `--twake-tombstone-erase-min-age` or its date cannot be read as
70
+ [lifecycle events](lifecycle-events.md) reads it.
67
71
 
68
72
  Other plugins call `erase(dn, { force, req })`.
69
73
 
@@ -119,7 +119,10 @@ whenever the link changes. Mark the path `generated` so a client cannot set it.
119
119
 
120
120
  `5GB`, `500 MB`, `2KB` and `2048` all become a number of bytes, with decimal
121
121
  multipliers (1 GB = 10⁹ bytes) as mail servers count them. The same conversion
122
- applies to creations and to updates.
122
+ applies to creations and to updates. A size above 2⁵³ − 1 bytes is refused
123
+ (400), since its number of bytes would be rounded. A schema `number` or
124
+ `integer` refuses a whole number beyond 2⁵³ on its own, whatever the type;
125
+ see [what a value must look like](../../../client-development/schemas/README.md#what-a-value-must-look-like).
123
126
 
124
127
  ### Server-owned defaults
125
128
 
@@ -144,6 +147,12 @@ An `accountExpiry` attribute must not carry a date already past. The comparison
144
147
  is against the start of the current day, so scheduling something for today is
145
148
  allowed.
146
149
 
150
+ The date is an LDAP generalized time, read as written: the year keeps its
151
+ four digits (`0029123123` is a date of year 29, not 1929), and a leap second
152
+ (`20991231235960Z`) is the instant that follows the day. The zone is `Z` or a
153
+ difference of hours and minutes from UTC (`+00`, `+02`, `-0530`, `+14:00`); a
154
+ value past 23 hours or 59 minutes is answered 400 as invalid.
155
+
147
156
  ### Deletion and references
148
157
 
149
158
  ```json
@@ -451,6 +451,17 @@ Content-Type: application/json
451
451
  }
452
452
  ```
453
453
 
454
+ The identifier may also be the whole DN of the entry, in the entity's
455
+ branch: `"uid": "uid=Smith\\,John,ou=users,dc=example,dc=com"` creates the
456
+ entry `Smith,John`, whose DN spells the name with its escapes. The DN must
457
+ use the escapes RFC 4514 defines; an escape it does not define (`\q`) is
458
+ refused with a `400`. Send the bare value to have the server escape it.
459
+
460
+ The name written is the value the RDN gives under the folding the directory
461
+ applies (Unicode NFKC, and its insignificant spaces): `uid=\ zoë` and
462
+ `uid=zoë` name one entry, written `uid=zoë`, and a name sent decomposed is
463
+ stored composed.
464
+
454
465
  ### Modify Entry
455
466
 
456
467
  ```bash
@@ -157,7 +157,10 @@ POST /api/v1/ldap/groups
157
157
 
158
158
  **Notes:**
159
159
 
160
- - `cn` is required
160
+ - `cn` is required; it is a name, or the group's DN in the groups branch,
161
+ whose first RDN gives the name, folded as the directory folds it. The DN
162
+ form follows the same
163
+ [escape rule as a flat entity's identifier](flat-generic.md#create-entry)
161
164
  - `member` can be a string (single member) or array (multiple members)
162
165
  - If no members provided, a dummy member is automatically added, and it is
163
166
  left out of `member` when the group is read back, on both the list and the
@@ -155,6 +155,10 @@ curl "http://localhost:8081/api/v1/users/uid%3Djohn.doe%2Cou%3Dusers%2Cdc%3Dexam
155
155
  }
156
156
  ```
157
157
 
158
+ A `pwdMaxAge` large enough to put the expiry beyond the representable date
159
+ range is reported as no expiry: `expiresAt` and `daysUntilExpiration` are
160
+ `null`, and `isExpired` stays `false`.
161
+
158
162
  ### Unlock User Account
159
163
 
160
164
  ```http
@@ -337,6 +341,9 @@ curl -X PATCH "http://localhost:8081/api/v1/password-policies/default" \
337
341
 
338
342
  - `pwdAttribute` and `pwdCheckModule` are read-only. Before OpenLDAP 2.6,
339
343
  `pwdCheckModule` is the path of a library slapd loads; set it in slapd.
344
+ - Durations and counts are integers from 0 to 9007199254740991 (2⁵³ − 1),
345
+ the largest a JSON number holds exactly: a larger value, or one sent as an
346
+ exponent such as `1e21`, is refused with a `400`.
340
347
  - `pwdCheckModuleArg`, the configuration of the quality-check module (ppm,
341
348
  for instance), is a string, usually of several lines. Writing it, or
342
349
  `pwdUseCheckModule`, gives the entry the `pwdPolicyChecker` class. Both
@@ -181,6 +181,22 @@ Site-specific attributes are added with `--ldap-raw-hidden-attribute`, which sta
181
181
  --ldap-raw-hidden-attribute twakeApiKey --ldap-raw-hidden-attribute employeeNumber
182
182
  ```
183
183
 
184
+ A hidden attribute is resolved to its directory type, so the type's OID and
185
+ every alias it declares are hidden too — asking for `2.5.4.35` or
186
+ `homePhone` does not serve `userPassword` or a configured
187
+ `homeTelephoneNumber`. A search filter that tests a hidden type, at any
188
+ depth and under any of its names, is refused with a 400: the search runs with
189
+ the service account's rights, so leaving it through would answer the same
190
+ question one match at a time. An assertion on a supertype of a hidden type is
191
+ refused as well, since the directory evaluates an attribute's subtypes. An
192
+ extensible match without an attribute (`(:octetStringMatch:=…)`) runs over
193
+ every attribute and is refused too while attributes are hidden.
194
+
195
+ When the directory schema cannot be read, an entry read or a search is
196
+ refused with a 503 rather than answered with only the configured names
197
+ compared, which could serve an alias or an OID. The root DSE still answers:
198
+ it carries no entry values and is how a client discovers the schema.
199
+
184
200
  Note that hiding an attribute here keeps it out of the API, not out of the directory: an account able to bind to LDAP directly still reads it. This is a guard against casual exposure through the browsing UI, not an access control — use [authz-per-branch](../auth/authz-per-branch.md) or directory ACLs for that.
185
201
 
186
202
  ## Security
@@ -189,7 +205,7 @@ Access is restricted in three independent layers:
189
205
 
190
206
  1. **Exposed bases** — any DN outside `--ldap-raw-base` is refused with a 403, whatever the caller's rights.
191
207
  2. **Authorization hooks** — every entry read, children listing and search goes through `server.ldap`, so the authorization plugins ([authz-per-branch](../auth/authz-per-branch.md), authz-dynamic, …) apply exactly as on the high-level APIs.
192
- 3. **Hidden attributes** — credential attributes, plus anything in `--ldap-raw-hidden-attribute`, are removed from every response, including searches. See [Hidden attributes](#hidden-attributes).
208
+ 3. **Hidden attributes** — credential attributes, plus anything in `--ldap-raw-hidden-attribute`, are removed from every response, including searches, under every name their type answers to; a filter that tests one is refused with a 400. See [Hidden attributes](#hidden-attributes).
193
209
 
194
210
  Two exceptions, both deliberate: the **root DSE** and the **schema** are read with the service account, not with the caller's rights. They are directory metadata and carry no user data; reading them with a restricted account would leave the UI unable to name and type attributes. Do not expose this plugin publicly if your directory publishes sensitive information in its root DSE.
195
211