@jwilleke/ngdpbase-types 0.0.0 → 5.18.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 (302) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +16 -2
  3. package/lib/packages/ngdpbase-types/index.d.ts +32 -0
  4. package/lib/packages/ngdpbase-types/testing.d.ts +43 -0
  5. package/lib/packages/ngdpbase-types/testing.js +53 -0
  6. package/lib/src/cache/CacheDependencies.d.ts +50 -0
  7. package/lib/src/cache/CacheDependencies.js +50 -0
  8. package/lib/src/cache/ICacheAdapter.d.ts +86 -0
  9. package/lib/src/cache/RegionCache.d.ts +171 -0
  10. package/lib/src/context/ActorContext.d.ts +48 -0
  11. package/lib/src/context/ActorContext.js +33 -0
  12. package/lib/src/context/ApiContext.d.ts +194 -0
  13. package/lib/src/context/ApiContext.js +273 -0
  14. package/lib/src/context/BaseContext.d.ts +110 -0
  15. package/lib/src/context/BaseContext.js +143 -0
  16. package/lib/src/context/JobContext.d.ts +153 -0
  17. package/lib/src/context/JobContext.js +144 -0
  18. package/lib/src/context/WikiContext.d.ts +404 -0
  19. package/lib/src/context/bootActions.d.ts +64 -0
  20. package/lib/src/context/bootActions.js +111 -0
  21. package/lib/src/converters/HtmlConverter.d.ts +70 -0
  22. package/lib/src/converters/IContentConverter.d.ts +94 -0
  23. package/lib/src/converters/JSPWikiConverter.d.ts +117 -0
  24. package/lib/src/converters/conversionWarning.d.ts +15 -0
  25. package/lib/src/converters/ncm/bridge.d.ts +22 -0
  26. package/lib/src/converters/ncm/existing.d.ts +23 -0
  27. package/lib/src/converters/ncm/fix/blocks.d.ts +89 -0
  28. package/lib/src/converters/ncm/fix/bulletMarkers.d.ts +21 -0
  29. package/lib/src/converters/ncm/fix/index.d.ts +36 -0
  30. package/lib/src/converters/ncm/fix/jspwikiBullets.d.ts +20 -0
  31. package/lib/src/converters/ncm/fix/jspwikiCodeMarkers.d.ts +38 -0
  32. package/lib/src/converters/ncm/fix/jspwikiHeadings.d.ts +25 -0
  33. package/lib/src/converters/ncm/fix/jspwikiIndent.d.ts +24 -0
  34. package/lib/src/converters/ncm/fix/jspwikiInsert.d.ts +21 -0
  35. package/lib/src/converters/ncm/fix/jspwikiItalic.d.ts +29 -0
  36. package/lib/src/converters/ncm/fix/jspwikiLinkLeftovers.d.ts +27 -0
  37. package/lib/src/converters/ncm/fix/moreInformationFooter.d.ts +25 -0
  38. package/lib/src/converters/ncm/fix/styleClosers.d.ts +25 -0
  39. package/lib/src/converters/ncm/fix/tightenLists.d.ts +30 -0
  40. package/lib/src/converters/ncm/fix/types.d.ts +33 -0
  41. package/lib/src/converters/ncm/footnotes.d.ts +39 -0
  42. package/lib/src/converters/ncm/images.d.ts +49 -0
  43. package/lib/src/converters/ncm/index.d.ts +20 -0
  44. package/lib/src/converters/ncm/links.d.ts +21 -0
  45. package/lib/src/converters/ncm/normalize.d.ts +39 -0
  46. package/lib/src/converters/ncm/placeholder.d.ts +25 -0
  47. package/lib/src/converters/ncm/tables.d.ts +36 -0
  48. package/lib/src/converters/ncm/types.d.ts +42 -0
  49. package/lib/src/http/egressPolicy.d.ts +52 -0
  50. package/lib/src/http/guardedFetch.d.ts +89 -0
  51. package/lib/src/http/guardedFetch.js +113 -0
  52. package/lib/src/http/guardedLookup.d.ts +48 -0
  53. package/lib/src/http/guardedLookup.js +73 -0
  54. package/lib/src/http/ssrf.d.ts +83 -0
  55. package/lib/src/http/ssrf.js +311 -0
  56. package/lib/src/mail/MailProvider.d.ts +36 -0
  57. package/lib/src/mail/NodemailerMailProvider.d.ts +26 -0
  58. package/lib/src/managers/AddonsManager.d.ts +691 -0
  59. package/lib/src/managers/AgentTokenManager.d.ts +269 -0
  60. package/lib/src/managers/AssetManager.d.ts +116 -0
  61. package/lib/src/managers/AttachmentManager.d.ts +1032 -0
  62. package/lib/src/managers/AuthManager.d.ts +1257 -0
  63. package/lib/src/managers/BackgroundJobManager.d.ts +434 -0
  64. package/lib/src/managers/BaseManager.d.ts +391 -0
  65. package/lib/src/managers/BaseManager.js +415 -0
  66. package/lib/src/managers/CacheManager.d.ts +159 -0
  67. package/lib/src/managers/CatalogManager.d.ts +235 -0
  68. package/lib/src/managers/CommentManager.d.ts +75 -0
  69. package/lib/src/managers/ConfigurationManager.d.ts +747 -0
  70. package/lib/src/managers/DatabaseManager.d.ts +89 -0
  71. package/lib/src/managers/DatabaseManager.js +236 -0
  72. package/lib/src/managers/EmailManager.d.ts +47 -0
  73. package/lib/src/managers/ExportManager.d.ts +129 -0
  74. package/lib/src/managers/ExportManager.js +420 -0
  75. package/lib/src/managers/FootnoteManager.d.ts +118 -0
  76. package/lib/src/managers/MediaManager.d.ts +279 -0
  77. package/lib/src/managers/MetricsManager.d.ts +89 -0
  78. package/lib/src/managers/NotificationManager.d.ts +165 -0
  79. package/lib/src/managers/OidcManager.d.ts +210 -0
  80. package/lib/src/managers/OrganizationManager.d.ts +107 -0
  81. package/lib/src/managers/PageManager.d.ts +1645 -0
  82. package/lib/src/managers/PersonManager.d.ts +48 -0
  83. package/lib/src/managers/PluginManager.d.ts +179 -0
  84. package/lib/src/managers/PluginManager.js +393 -0
  85. package/lib/src/managers/PolicyEvaluator.d.ts +213 -0
  86. package/lib/src/managers/RenderingManager.d.ts +358 -0
  87. package/lib/src/managers/RoleManager.d.ts +134 -0
  88. package/lib/src/managers/SearchManager.d.ts +402 -0
  89. package/lib/src/managers/ShareManager.d.ts +251 -0
  90. package/lib/src/managers/TemplateManager.d.ts +176 -0
  91. package/lib/src/managers/ThemeManager.d.ts +56 -0
  92. package/lib/src/managers/UserManager.d.ts +480 -0
  93. package/lib/src/managers/ValidationManager.d.ts +426 -0
  94. package/lib/src/managers/VariableManager.d.ts +145 -0
  95. package/lib/src/middleware/csrf.d.ts +3 -0
  96. package/lib/src/parsers/LinkParser.d.ts +457 -0
  97. package/lib/src/parsers/MarkupParser.d.ts +769 -0
  98. package/lib/src/parsers/context/ParseContext.d.ts +314 -0
  99. package/lib/src/parsers/data/emoji-map.d.ts +18 -0
  100. package/lib/src/parsers/dom/DOMBuilder.d.ts +210 -0
  101. package/lib/src/parsers/dom/DOMParser.d.ts +252 -0
  102. package/lib/src/parsers/dom/Tokenizer.d.ts +358 -0
  103. package/lib/src/parsers/dom/WikiDocument.d.ts +272 -0
  104. package/lib/src/parsers/dom/handlers/DOMLinkHandler.d.ts +260 -0
  105. package/lib/src/parsers/dom/handlers/DOMPluginHandler.d.ts +212 -0
  106. package/lib/src/parsers/dom/handlers/DOMVariableHandler.d.ts +171 -0
  107. package/lib/src/parsers/filters/BaseFilter.d.ts +269 -0
  108. package/lib/src/parsers/filters/FilterChain.d.ts +320 -0
  109. package/lib/src/parsers/handlers/BaseSyntaxHandler.d.ts +331 -0
  110. package/lib/src/parsers/handlers/HandlerRegistry.d.ts +225 -0
  111. package/lib/src/parsers/handlers/JSPWikiPreprocessor.d.ts +89 -0
  112. package/lib/src/parsers/handlers/LinkParserHandler.d.ts +80 -0
  113. package/lib/src/parsers/handlers/PluginSyntaxHandler.d.ts +78 -0
  114. package/lib/src/parsers/handlers/WikiFormHandler.d.ts +149 -0
  115. package/lib/src/parsers/handlers/WikiTagHandler.d.ts +125 -0
  116. package/lib/src/parsers/jspwikiTableRow.d.ts +39 -0
  117. package/lib/src/parsers/styleBlockSyntax.d.ts +14 -0
  118. package/lib/src/plugins/types.d.ts +79 -0
  119. package/lib/src/providers/AgentTokenAuthProvider.d.ts +40 -0
  120. package/lib/src/providers/AuthentikBearerAuthProvider.d.ts +75 -0
  121. package/lib/src/providers/BaseAttachmentProvider.d.ts +197 -0
  122. package/lib/src/providers/BaseAuthProvider.d.ts +220 -0
  123. package/lib/src/providers/BaseCacheProvider.d.ts +140 -0
  124. package/lib/src/providers/BaseCredentialsProvider.d.ts +84 -0
  125. package/lib/src/providers/BaseDatabaseProvider.d.ts +22 -0
  126. package/lib/src/providers/BaseDatabaseProvider.js +12 -0
  127. package/lib/src/providers/BaseLoggingProvider.d.ts +68 -0
  128. package/lib/src/providers/BaseLoggingProvider.js +37 -0
  129. package/lib/src/providers/BaseMediaProvider.d.ts +308 -0
  130. package/lib/src/providers/BasePageProvider.d.ts +337 -0
  131. package/lib/src/providers/BaseProvider.d.ts +98 -0
  132. package/lib/src/providers/BaseProvider.js +74 -0
  133. package/lib/src/providers/BaseSearchProvider.d.ts +362 -0
  134. package/lib/src/providers/BasicAttachmentProvider.d.ts +599 -0
  135. package/lib/src/providers/CloudflareAccessAuthProvider.d.ts +72 -0
  136. package/lib/src/providers/FileCredentialsProvider.d.ts +33 -0
  137. package/lib/src/providers/FileJobStateProvider.d.ts +58 -0
  138. package/lib/src/providers/FileLoggingProvider.d.ts +43 -0
  139. package/lib/src/providers/FileLoggingProvider.js +120 -0
  140. package/lib/src/providers/FileOidcAdapter.d.ts +25 -0
  141. package/lib/src/providers/FileSystemMediaProvider.d.ts +403 -0
  142. package/lib/src/providers/LunrSearchProvider.d.ts +280 -0
  143. package/lib/src/providers/MagicLinkAuthProvider.d.ts +125 -0
  144. package/lib/src/providers/NullCacheProvider.d.ts +72 -0
  145. package/lib/src/providers/OidcAuthProvider.d.ts +180 -0
  146. package/lib/src/providers/OidcBearerAuthProvider.d.ts +30 -0
  147. package/lib/src/providers/PasskeyAuthProvider.d.ts +58 -0
  148. package/lib/src/providers/PasswordAuthProvider.d.ts +20 -0
  149. package/lib/src/providers/SqliteDatabaseProvider.d.ts +55 -0
  150. package/lib/src/providers/SqliteDatabaseProvider.js +90 -0
  151. package/lib/src/providers/SqliteJobStateProvider.d.ts +41 -0
  152. package/lib/src/providers/databaseMigrations.d.ts +8 -0
  153. package/lib/src/providers/databaseMigrations.js +47 -0
  154. package/lib/src/providers/jobState.d.ts +99 -0
  155. package/lib/src/providers/lunrQueryToMiniSearch.d.ts +32 -0
  156. package/lib/src/providers/mediaFilenameDate.d.ts +22 -0
  157. package/lib/src/providers/sqliteLocation.d.ts +17 -0
  158. package/lib/src/providers/sqliteLocation.js +55 -0
  159. package/lib/src/providers/sqliteMigrations.d.ts +48 -0
  160. package/lib/src/providers/sqliteMigrations.js +72 -0
  161. package/lib/src/rendering/githubAlerts.d.ts +22 -0
  162. package/lib/src/rendering/htmlPolicy.d.ts +76 -0
  163. package/lib/src/rendering/markdownConverter.d.ts +73 -0
  164. package/lib/src/security/PolicyDecisionPoint.d.ts +245 -0
  165. package/lib/src/security/PolicyInformationPoint.d.ts +448 -0
  166. package/lib/src/security/pageActions.d.ts +40 -0
  167. package/lib/src/security/permissions.generated.d.ts +78 -0
  168. package/lib/src/types/Asset.d.ts +414 -0
  169. package/lib/src/types/Catalog.d.ts +61 -0
  170. package/lib/src/types/Comment.d.ts +11 -0
  171. package/lib/src/types/Config.d.ts +388 -0
  172. package/lib/src/types/Organization.d.ts +78 -0
  173. package/lib/src/types/OrganizationProvider.d.ts +38 -0
  174. package/lib/src/types/Page.d.ts +220 -0
  175. package/lib/src/types/Person.d.ts +56 -0
  176. package/lib/src/types/PersonProvider.d.ts +25 -0
  177. package/lib/src/types/Policy.d.ts +139 -0
  178. package/lib/src/types/Policy.js +17 -0
  179. package/lib/src/types/Provider.d.ts +810 -0
  180. package/lib/src/types/Role.d.ts +84 -0
  181. package/lib/src/types/RoleProvider.d.ts +35 -0
  182. package/lib/src/types/Schema.d.ts +425 -0
  183. package/lib/src/types/Share.d.ts +172 -0
  184. package/lib/src/types/Share.js +81 -0
  185. package/lib/src/types/User.d.ts +304 -0
  186. package/lib/src/types/Version.d.ts +189 -0
  187. package/lib/src/types/WikiEngine.d.ts +128 -0
  188. package/lib/src/types/express.d.ts +120 -0
  189. package/lib/src/types/express.js +1 -0
  190. package/lib/src/types/guards.d.ts +78 -0
  191. package/lib/src/types/heic-decode.d.ts +16 -0
  192. package/lib/src/types/index.d.ts +19 -0
  193. package/lib/src/types/linkedom.d.ts +77 -0
  194. package/lib/src/types/markdown-it-plugins.d.ts +21 -0
  195. package/lib/src/utils/DeltaStorage.d.ts +118 -0
  196. package/lib/src/utils/LocaleUtils.d.ts +105 -0
  197. package/lib/src/utils/LocaleUtils.js +294 -0
  198. package/lib/src/utils/PageNameMatcher.d.ts +98 -0
  199. package/lib/src/utils/PathPreflight.d.ts +38 -0
  200. package/lib/src/utils/PathPreflight.js +50 -0
  201. package/lib/src/utils/SectionUtils.d.ts +40 -0
  202. package/lib/src/utils/addonConfigLayer.d.ts +144 -0
  203. package/lib/src/utils/addonConfigLayer.js +382 -0
  204. package/lib/src/utils/addonDatabaseRules.d.ts +25 -0
  205. package/lib/src/utils/addonDatabaseRules.js +57 -0
  206. package/lib/src/utils/addonHost.d.ts +51 -0
  207. package/lib/src/utils/addonHost.js +72 -0
  208. package/lib/src/utils/addonInstaller.d.ts +109 -0
  209. package/lib/src/utils/addonLock.d.ts +37 -0
  210. package/lib/src/utils/addonLock.js +48 -0
  211. package/lib/src/utils/addonPageSync.d.ts +45 -0
  212. package/lib/src/utils/addonProvenance.d.ts +48 -0
  213. package/lib/src/utils/addonTarball.d.ts +41 -0
  214. package/lib/src/utils/addonsPathResolver.d.ts +76 -0
  215. package/lib/src/utils/addonsPathResolver.js +129 -0
  216. package/lib/src/utils/assetMetadataTags.d.ts +66 -0
  217. package/lib/src/utils/atomicWrite.d.ts +28 -0
  218. package/lib/src/utils/auditConfigChange.d.ts +57 -0
  219. package/lib/src/utils/auditEventNames.d.ts +50 -0
  220. package/lib/src/utils/auditEventNames.generated.d.ts +163 -0
  221. package/lib/src/utils/auditEventNames.generated.js +168 -0
  222. package/lib/src/utils/auditEventNames.js +49 -0
  223. package/lib/src/utils/auditEvents.d.ts +265 -0
  224. package/lib/src/utils/auditEvents.js +309 -0
  225. package/lib/src/utils/auditRegistry.d.ts +102 -0
  226. package/lib/src/utils/auditRegistry.js +168 -0
  227. package/lib/src/utils/bip39English.d.ts +2 -0
  228. package/lib/src/utils/configEnvKeys.d.ts +68 -0
  229. package/lib/src/utils/configFiles.d.ts +74 -0
  230. package/lib/src/utils/configFiles.js +150 -0
  231. package/lib/src/utils/delegation.d.ts +48 -0
  232. package/lib/src/utils/deriveUsername.d.ts +21 -0
  233. package/lib/src/utils/explainMediaPath.d.ts +123 -0
  234. package/lib/src/utils/formerTitles.d.ts +69 -0
  235. package/lib/src/utils/frontmatterAccess.d.ts +54 -0
  236. package/lib/src/utils/headlessAdminPassword.d.ts +55 -0
  237. package/lib/src/utils/imageTransform.d.ts +52 -0
  238. package/lib/src/utils/instanceEnvSecret.d.ts +51 -0
  239. package/lib/src/utils/jobSlots.d.ts +43 -0
  240. package/lib/src/utils/keywordNormalizer.d.ts +127 -0
  241. package/lib/src/utils/logger.d.ts +70 -0
  242. package/lib/src/utils/logger.js +106 -0
  243. package/lib/src/utils/magicLinkDeviceState.d.ts +95 -0
  244. package/lib/src/utils/managerUtils.d.ts +40 -0
  245. package/lib/src/utils/migrateLegacyPrivateAttachments.d.ts +15 -0
  246. package/lib/src/utils/orgFilename.d.ts +22 -0
  247. package/lib/src/utils/pageFeature.d.ts +27 -0
  248. package/lib/src/utils/pageFrontmatter.d.ts +21 -0
  249. package/lib/src/utils/pageNotes.d.ts +150 -0
  250. package/lib/src/utils/pageTitleRule.d.ts +37 -0
  251. package/lib/src/utils/pageToArticle.d.ts +59 -0
  252. package/lib/src/utils/pageUrl.d.ts +18 -0
  253. package/lib/src/utils/passwordChange.d.ts +12 -0
  254. package/lib/src/utils/passwordHash.d.ts +60 -0
  255. package/lib/src/utils/permissionCatalog.d.ts +52 -0
  256. package/lib/src/utils/pluginFormatters.d.ts +452 -0
  257. package/lib/src/utils/pluginFormatters.js +714 -0
  258. package/lib/src/utils/privateLinkRewrite.d.ts +42 -0
  259. package/lib/src/utils/privateStoreAccess.d.ts +57 -0
  260. package/lib/src/utils/privateStoreAccess.js +65 -0
  261. package/lib/src/utils/privateStoreCatalogs.d.ts +40 -0
  262. package/lib/src/utils/privateStoreCrypto.d.ts +127 -0
  263. package/lib/src/utils/privateStoreDoor.d.ts +181 -0
  264. package/lib/src/utils/privateStoreExport.d.ts +72 -0
  265. package/lib/src/utils/privateStoreFiles.d.ts +120 -0
  266. package/lib/src/utils/privateStoreMeta.d.ts +64 -0
  267. package/lib/src/utils/privateStoreMigrations.d.ts +37 -0
  268. package/lib/src/utils/privateStorePath.d.ts +259 -0
  269. package/lib/src/utils/privateStorePath.js +436 -0
  270. package/lib/src/utils/privateStoreTakeout.d.ts +76 -0
  271. package/lib/src/utils/privateStoreUnlock.d.ts +175 -0
  272. package/lib/src/utils/proxyClaim.d.ts +59 -0
  273. package/lib/src/utils/proxyClaim.js +30 -0
  274. package/lib/src/utils/redactPrivateNames.d.ts +21 -0
  275. package/lib/src/utils/redactPrivateNames.js +89 -0
  276. package/lib/src/utils/redactSecrets.d.ts +58 -0
  277. package/lib/src/utils/redactSecrets.js +171 -0
  278. package/lib/src/utils/renameLinkRewrite.d.ts +112 -0
  279. package/lib/src/utils/roleGrants.d.ts +35 -0
  280. package/lib/src/utils/safeRedirect.d.ts +32 -0
  281. package/lib/src/utils/schedule.d.ts +54 -0
  282. package/lib/src/utils/secretFileMode.d.ts +17 -0
  283. package/lib/src/utils/seededShippedPages.d.ts +45 -0
  284. package/lib/src/utils/sensitiveValues.d.ts +59 -0
  285. package/lib/src/utils/sensitiveValues.js +106 -0
  286. package/lib/src/utils/sessionEnd.d.ts +12 -0
  287. package/lib/src/utils/sessionGeneration.d.ts +24 -0
  288. package/lib/src/utils/sessionIdle.d.ts +41 -0
  289. package/lib/src/utils/sessionLimits.d.ts +68 -0
  290. package/lib/src/utils/shareLockbox.d.ts +64 -0
  291. package/lib/src/utils/sigstoreTrustedRoot.d.ts +33 -0
  292. package/lib/src/utils/sniffMime.d.ts +21 -0
  293. package/lib/src/utils/storeSearchIndex.d.ts +75 -0
  294. package/lib/src/utils/subjectMayDo.d.ts +21 -0
  295. package/lib/src/utils/systemCategoryRules.d.ts +30 -0
  296. package/lib/src/utils/systemCategoryRules.js +41 -0
  297. package/lib/src/utils/userCreateError.d.ts +62 -0
  298. package/lib/src/utils/username.d.ts +53 -0
  299. package/lib/src/utils/vaultUrlRewrite.d.ts +27 -0
  300. package/lib/src/utils/version.d.ts +84 -0
  301. package/lib/src/utils/videoFrame.d.ts +21 -0
  302. package/package.json +54 -3
@@ -0,0 +1,309 @@
1
+ /**
2
+ * Audit event builders for content mutations (#1080).
3
+ *
4
+ * `AuditManager` was already mature — file provider with rotation, 90-day
5
+ * retention, search, stats, export, and an admin UI — but almost nothing
6
+ * called it. Outside the manager the only `logAuditEvent` call sites were
7
+ * `page-delete`, admin raw-edit, two session operations, and share
8
+ * issue/revoke. Ordinary page create, edit, and rename, and every attachment
9
+ * upload and delete, produced no audit record at all.
10
+ *
11
+ * That left "who changed this page, when, and through what?" answerable only
12
+ * from a version manifest: per-page, not queryable across pages, and present
13
+ * only when the deployment runs `versioningfileprovider` (the shipped default
14
+ * is `filesystemprovider`, which keeps no versions). There was no way to ask
15
+ * "everything this agent token wrote last Tuesday" — which is exactly the
16
+ * question agent tokens (#946) make worth asking, since a token writes
17
+ * unattended and the version manifest records only a username.
18
+ *
19
+ * These are pure builders so the event *shape* can be tested without an
20
+ * engine, a request, or a manager. The shape is the contract: `#1082` reads
21
+ * `page-rename`'s `fromPageName`/`pageName` pair to resolve a link that
22
+ * points at a page's former title, so those two fields are load-bearing
23
+ * rather than descriptive.
24
+ */
25
+ import logger from './logger.js';
26
+ import { auditEventDeclarations, AUDIT_EVENTS_KEY, isAuditEventEnabled, refusesOnFailure } from './auditRegistry.js';
27
+ import { AUDIT_EVENT, isCoreAuditEventName } from './auditEventNames.js';
28
+ import { proxyAttribution } from './proxyClaim.js';
29
+ /**
30
+ * The result vocabulary, as a runtime value (#1237).
31
+ *
32
+ * The type alone could not be offered as filter options, so the audit page
33
+ * hand-kept its own list — and it offered `allow`, `deny`, `error` while the
34
+ * log holds `success` (5,859), `deny` (896) and `failure` (79). Two of the
35
+ * three options matched zero records and the largest value was unfilterable.
36
+ * Exactly the #1115 failure, one field over.
37
+ */
38
+ export const AUDIT_RESULTS = ['success', 'failure', 'allow', 'deny', 'error', 'logout'];
39
+ // #1201: the builders look the name up rather than interpolating it, so the
40
+ // compiler — not a grep — knows which names each family can produce.
41
+ const PAGE_EVENT = {
42
+ create: AUDIT_EVENT.PAGE_CREATE,
43
+ edit: AUDIT_EVENT.PAGE_EDIT,
44
+ rename: AUDIT_EVENT.PAGE_RENAME,
45
+ 'link-rewrite': AUDIT_EVENT.PAGE_LINK_REWRITE
46
+ };
47
+ const ASSET_EVENT = {
48
+ upload: AUDIT_EVENT.ASSET_UPLOAD,
49
+ delete: AUDIT_EVENT.ASSET_DELETE
50
+ };
51
+ const TOKEN_EVENT = {
52
+ mint: AUDIT_EVENT.TOKEN_MINT,
53
+ revoke: AUDIT_EVENT.TOKEN_REVOKE,
54
+ extend: AUDIT_EVENT.TOKEN_EXTEND
55
+ };
56
+ /** A content row's "who" — `user`, `actor` and `ipAddress` — and the proxy grant's metadata. One place, read by every builder below. */
57
+ function whoOf(input) {
58
+ const { metadata, ...proxy } = proxyAttribution(input.viaProxy);
59
+ return { fields: { user: input.username ?? 'unknown', ...proxy, ipAddress: input.ipAddress }, metadata };
60
+ }
61
+ /**
62
+ * Token identity as metadata. Always present as explicit nulls for a human
63
+ * write so a query can filter on the field existing rather than having to
64
+ * treat "absent" and "not a token" as the same thing.
65
+ */
66
+ function tokenMetadata(viaToken) {
67
+ return {
68
+ viaTokenId: viaToken?.id ?? null,
69
+ viaTokenName: viaToken?.name ?? null
70
+ };
71
+ }
72
+ /**
73
+ * Build the audit event for a page create, edit, rename, or link rewrite.
74
+ *
75
+ * `result` is always `success`: these are recorded *after* the write lands,
76
+ * unlike `page-delete`, which logs `attempted` before unlinking so that a
77
+ * crash mid-delete still leaves a trace. A create or edit has the page file
78
+ * and its version history as its own record, so recording the attempt buys
79
+ * nothing the file does not already say.
80
+ */
81
+ export function buildPageMutationAuditEvent(input) {
82
+ const { op, pageName, uuid, fromPageName, rewriteOf, viaToken } = input;
83
+ const who = whoOf(input);
84
+ const metadata = {
85
+ pageName,
86
+ uuid: uuid ?? null,
87
+ ...tokenMetadata(viaToken),
88
+ ...who.metadata
89
+ };
90
+ // Only a rename has a previous title. Emitting `fromPageName: null` on
91
+ // every edit would make the field useless as a filter for #1082.
92
+ if (op === 'rename' && fromPageName) {
93
+ metadata.fromPageName = fromPageName;
94
+ }
95
+ // Which rename this rewrite belongs to. Emitted only for `link-rewrite`, for
96
+ // the same reason: a field present on every event is useless as a filter.
97
+ if (op === 'link-rewrite' && rewriteOf) {
98
+ metadata.rewriteFrom = rewriteOf.from;
99
+ metadata.rewriteTo = rewriteOf.to;
100
+ }
101
+ return {
102
+ eventType: PAGE_EVENT[op],
103
+ ...who.fields,
104
+ action: `page-${op}`,
105
+ result: 'success',
106
+ // A token write is worth surfacing above ordinary editing traffic, but an
107
+ // edit is not a delete — `page-delete` reserves `high` for tokens.
108
+ severity: viaToken ? 'medium' : 'low',
109
+ metadata
110
+ };
111
+ }
112
+ /**
113
+ * Build the audit event for a page view (#1129).
114
+ *
115
+ * Emission is a deployment posture: `page-read` ships `enabled: false` in
116
+ * `ngdpbase.audit.events` (#1203), and `recordAuditEvent` honours the switch.
117
+ * Off, a general-purpose deployment does not drown its log in reads; on, a
118
+ * records-style deployment gets the access accounting — who looked at what —
119
+ * that read auditing exists for.
120
+ */
121
+ export function buildPageViewAuditEvent(input) {
122
+ const { pageName, uuid, viaToken } = input;
123
+ const who = whoOf(input);
124
+ return {
125
+ eventType: AUDIT_EVENT.PAGE_READ,
126
+ ...who.fields,
127
+ action: 'page-read',
128
+ result: 'success',
129
+ // Same convention as the mutations: an unattended (token-driven) read is
130
+ // the one a reviewer is scanning for.
131
+ severity: viaToken ? 'medium' : 'low',
132
+ metadata: {
133
+ pageName,
134
+ uuid: uuid ?? null,
135
+ ...tokenMetadata(viaToken),
136
+ ...who.metadata
137
+ }
138
+ };
139
+ }
140
+ /**
141
+ * Build the audit event for an attachment upload or delete.
142
+ *
143
+ * A delete outranks an upload because it is the one that loses data, and a
144
+ * token-driven delete matches `page-delete`'s `high` for the same reason:
145
+ * unattended destruction is the case someone reviewing the log is looking for.
146
+ */
147
+ export function buildAttachmentAuditEvent(input) {
148
+ const { op, attachmentId, filename, pageName, sizeBytes, viaToken } = input;
149
+ const who = whoOf(input);
150
+ const metadata = {
151
+ attachmentId,
152
+ filename,
153
+ ...tokenMetadata(viaToken),
154
+ ...who.metadata
155
+ };
156
+ if (pageName)
157
+ metadata.pageName = pageName;
158
+ if (typeof sizeBytes === 'number')
159
+ metadata.sizeBytes = sizeBytes;
160
+ const severity = op === 'delete'
161
+ ? (viaToken ? 'high' : 'medium')
162
+ : (viaToken ? 'medium' : 'low');
163
+ return {
164
+ eventType: ASSET_EVENT[op],
165
+ ...who.fields,
166
+ action: `asset-${op}`,
167
+ result: 'success',
168
+ severity,
169
+ metadata
170
+ };
171
+ }
172
+ const dropStats = { dropped: 0, lastEventType: null, lastError: null, lastAt: null };
173
+ /** Audit writes lost since boot. Read-only snapshot. */
174
+ export function getAuditDropStats() {
175
+ return { ...dropStats };
176
+ }
177
+ /** Reset the counter. For tests; nothing in the running app calls this. */
178
+ export function resetAuditDropStats() {
179
+ dropStats.dropped = 0;
180
+ dropStats.lastEventType = null;
181
+ dropStats.lastError = null;
182
+ dropStats.lastAt = null;
183
+ }
184
+ /**
185
+ * Loud on the first loss, then at each power of ten.
186
+ *
187
+ * One line per dropped event would bury the signal in the noise of whatever
188
+ * outage caused it — and the first loss is the one that matters, because it is
189
+ * the moment the log stopped being complete.
190
+ */
191
+ function shouldShout(count) {
192
+ if (count === 1)
193
+ return true;
194
+ let threshold = 10;
195
+ while (threshold <= count) {
196
+ if (threshold === count)
197
+ return true;
198
+ threshold *= 10;
199
+ }
200
+ return false;
201
+ }
202
+ export async function recordAuditEvent(sink, event, onError) {
203
+ // #1638: an addon's name is checked here, against the merged registry, not
204
+ // by the compiler. One nobody declares — the addon is disabled, or its
205
+ // config/default-config.json never named it — is refused loudly rather than
206
+ // recorded under a name with no on-failure rule. Core names are the
207
+ // generated union and keep their existing path.
208
+ if (!isCoreAuditEventName(event.eventType) && !auditEventDeclarations()[event.eventType]) {
209
+ const message = `Audit event '${event.eventType}' is not declared (as a permission entry's audit block, or in ${AUDIT_EVENTS_KEY}). ` +
210
+ 'An addon declares its events in its config/default-config.json, and they count only while the addon is enabled.';
211
+ logger.error(`[audit] ${message}`);
212
+ throw new Error(message);
213
+ }
214
+ // #1203: `enabled: false` on the event in `ngdpbase.audit.events` is a
215
+ // decision on the record. The emitter still exists and still calls this;
216
+ // the switch is honoured here, once, rather than at every call site.
217
+ if (!isAuditEventEnabled(event.eventType))
218
+ return 'not-enabled';
219
+ // An absent sink is a configuration state, not a failure. Counting it would
220
+ // make the number meaningless on any instance that never enabled auditing —
221
+ // and it must not turn every critical action into an error either, since
222
+ // auditing being off is already visible through #1118's posture.
223
+ if (!sink?.logAuditEvent)
224
+ return 'no-sink';
225
+ const critical = refusesOnFailure(event.eventType);
226
+ if (critical && !sink.flushAuditQueue) {
227
+ const message = `Audit sink cannot guarantee durability for ${event.eventType}, which is declared on-failure: refuse. ` +
228
+ 'The action was refused rather than completed without a record.';
229
+ logger.error(`[audit] ${message}`);
230
+ throw new Error(message);
231
+ }
232
+ try {
233
+ await sink.logAuditEvent(event);
234
+ if (critical)
235
+ await sink.flushAuditQueue?.();
236
+ return 'recorded';
237
+ }
238
+ catch (err) {
239
+ dropStats.dropped += 1;
240
+ dropStats.lastEventType = event.eventType;
241
+ dropStats.lastError = err instanceof Error ? err.message : String(err);
242
+ dropStats.lastAt = new Date().toISOString();
243
+ if (shouldShout(dropStats.dropped)) {
244
+ logger.error(`[audit] ${dropStats.dropped} audit event(s) lost since boot — latest ${event.eventType}: ${dropStats.lastError}. ` +
245
+ 'The write itself succeeded; only its audit record was lost.');
246
+ }
247
+ onError?.(err);
248
+ // A critical event's failure is the caller's problem: it must be able to
249
+ // abandon the action rather than complete it unrecorded.
250
+ if (critical) {
251
+ throw new Error(`Audit write failed for ${event.eventType}, which is declared on-failure: refuse: ${dropStats.lastError}`, { cause: err });
252
+ }
253
+ return 'dropped';
254
+ }
255
+ }
256
+ /**
257
+ * Build the audit event for an agent token mint, extend or revoke (#1111, #1734).
258
+ *
259
+ * Before this, the token store was the only record that a credential had ever
260
+ * existed — and `purgeExpired()` claimed otherwise in a comment ("Audit is
261
+ * unaffected") while nothing emitted anything. That made `retention-days`
262
+ * load-bearing by accident: hash-bearing records were kept a month past
263
+ * usefulness purely so somebody could answer "what could this token do, and
264
+ * who stopped it?" With the lifecycle audited, the store can keep only what it
265
+ * needs to authenticate.
266
+ *
267
+ * Emitted from the manager rather than the route, unlike `page.*`. A page
268
+ * mutation logged at the HTTP layer misses an internal caller and that is
269
+ * survivable; an unaudited mint is a credential nobody knows exists.
270
+ *
271
+ * `scopes` appear on a mint only, `expiresAt` on a mint and an extend (with
272
+ * `previousExpiresAt` on an extend, #1734), and `revokedBy` on a revoke only —
273
+ * the same rule `page-rename` follows for `fromPageName`. A field present on
274
+ * every event is useless as a filter.
275
+ */
276
+ export function buildTokenAuditEvent(input) {
277
+ const { op, id, owner, name, scopes, expiresAt, previousExpiresAt, revokedBy, viaToken } = input;
278
+ const who = whoOf(input);
279
+ const metadata = {
280
+ id,
281
+ owner,
282
+ name: name ?? null,
283
+ ...tokenMetadata(viaToken),
284
+ ...who.metadata
285
+ };
286
+ if (op === 'mint') {
287
+ metadata.scopes = [...(scopes ?? [])];
288
+ metadata.expiresAt = expiresAt;
289
+ }
290
+ if (op === 'extend') {
291
+ metadata.previousExpiresAt = previousExpiresAt;
292
+ metadata.expiresAt = expiresAt;
293
+ }
294
+ if (op === 'revoke' && revokedBy) {
295
+ metadata.revokedBy = revokedBy;
296
+ }
297
+ return {
298
+ eventType: TOKEN_EVENT[op],
299
+ ...who.fields,
300
+ action: `token-${op}`,
301
+ result: 'success',
302
+ // Every credential event outranks ordinary content traffic: a token acts
303
+ // unattended, so its creation and its revocation are what a reader of the
304
+ // log is looking for. A token minted BY a token is higher still — that is
305
+ // delegation widening on its own, and the case worth surfacing loudest.
306
+ severity: viaToken ? 'high' : 'medium',
307
+ metadata
308
+ };
309
+ }
@@ -0,0 +1,102 @@
1
+ /**
2
+ * The audit event registry, read from configuration (#1200, epic #1208).
3
+ *
4
+ * `ngdpbase.audit.events` in `config/app-default-config.json` names every
5
+ * recorded action, what happens when its record cannot be written, and whether it fires. This module is
6
+ * a reader over that map: nothing here declares an event.
7
+ *
8
+ * Until #1200 the declarations lived in this file, deliberately, on the
9
+ * argument that an operator who could edit them could narrow what the system
10
+ * claims to audit. The operator's decision on 2026-09-04 is that this is the
11
+ * point: configuration is authoritative, and narrowing is on the record —
12
+ * an admin UI edit emits `config-change`, and a disk edit is reported by
13
+ * `posture-recorded` at the next boot. See docs/audit-posture.md.
14
+ *
15
+ * #1638 (operator, 2026-10-05): a permission and its action are one thing. An
16
+ * event that records a permission's action is declared on the permission
17
+ * entry itself — `ngdpbase.permissions.definitions.<name>.audit` — and
18
+ * `ngdpbase.audit.events` holds only events that are not a permission's
19
+ * action. {@link auditDeclarationsFrom} reads both, and is the one reader:
20
+ * the runtime, the generator, the lint, the doc generator and the boot check
21
+ * all call it, so they cannot disagree.
22
+ *
23
+ * What stays in code is the emitters. `scripts/audit-coverage.ts` proves the
24
+ * map and the emitters agree.
25
+ */
26
+ export declare const AUDIT_EVENTS_KEY = "ngdpbase.audit.events";
27
+ /** The permission registry; an entry's `audit` field declares its event (#1638). */
28
+ export declare const PERMISSION_DEFINITIONS_KEY = "ngdpbase.permissions.definitions";
29
+ /**
30
+ * What happens when the record cannot be written (#1121, #1158, #1218).
31
+ *
32
+ * - `refuse` — the action must not complete unless the record does; the
33
+ * write is flushed to the device before the action proceeds
34
+ * - `continue` — the action proceeds; the lost record is counted and surfaced
35
+ *
36
+ * This is failure handling, not importance. How important an event is lives
37
+ * on each record as `severity`. Until #1218 this field was called `tier` with
38
+ * values `critical` / `standard` / `volume`, which read as an importance
39
+ * scale that it never was; `volume` was `continue` plus `enabled: false`.
40
+ */
41
+ export type AuditOnFailure = 'refuse' | 'continue';
42
+ /** One entry of `ngdpbase.audit.events`. */
43
+ export interface AuditEventDeclaration {
44
+ 'on-failure': AuditOnFailure;
45
+ /** Whether the emitter fires. Omitted means true; `false` is a decision on the record. */
46
+ enabled?: boolean;
47
+ /** One line, shown in the admin filter and the documented table. */
48
+ description: string;
49
+ }
50
+ /** The shape of `ConfigurationManager.getProperty`, so this module needs no manager import. */
51
+ export type AuditEventsSource = (key: string, defaultValue?: unknown) => unknown;
52
+ /**
53
+ * Bind the live configuration. `AuditManager.initialize` calls this before it
54
+ * loads a provider, so every tier consulted from then on is the operator's.
55
+ *
56
+ * There is no fallback to the shipped file: reading
57
+ * `config/app-default-config.json` here would be a second reader over the
58
+ * configuration store, and a value could then come from the file when the live
59
+ * configuration says otherwise. Tests bind from the shipped file themselves
60
+ * (`vitest.setup.ts`), which is the one honest direct read.
61
+ */
62
+ export declare function bindAuditEvents(source: AuditEventsSource | null): void;
63
+ /**
64
+ * Every declared event in a configuration (#1638): the entries of
65
+ * `ngdpbase.audit.events`, plus every permission entry carrying `audit`, under
66
+ * the permission's name. A permission's `audit.description` defaults to the
67
+ * permission's own description.
68
+ *
69
+ * A name in both places is a declaration made twice. The shipped file never
70
+ * does it (`npm run lint:audit` fails); an operator's custom file that still
71
+ * sets a moved event under `ngdpbase.audit.events` is honoured — its fields
72
+ * override the permission's — and said once, so it is never silent.
73
+ */
74
+ export declare function auditDeclarationsFrom(read: AuditEventsSource): Record<string, AuditEventDeclaration>;
75
+ /** Every declared event, from the bound configuration. Empty, and said once, before binding. */
76
+ export declare function auditEventDeclarations(): Record<string, AuditEventDeclaration>;
77
+ /** The declaration for one event, or null when configuration does not name it. */
78
+ export declare function auditEventDeclaration(eventType: string): AuditEventDeclaration | null;
79
+ /** Every declared event type, sorted. */
80
+ export declare function auditEventTypes(): string[];
81
+ /** Every event type this system undertakes to emit: declared and not switched off. */
82
+ export declare function requiredEventTypes(): string[];
83
+ /** Is this event switched on? An undeclared event is not switched off. */
84
+ export declare function isAuditEventEnabled(eventType: string): boolean;
85
+ /**
86
+ * Does this event refuse the action when its record cannot be written
87
+ * (#1121, #1158)?
88
+ *
89
+ * Two layers need the same answer and must not be able to disagree:
90
+ * `recordAuditEvent` decides whether a failure rejects the action, and
91
+ * `FileAuditProvider.writeEvent` decides whether the record is fsynced before
92
+ * the write resolves. A rule that meant one thing to the caller and another to
93
+ * the writer would be the #1148 defect again.
94
+ */
95
+ export declare function refusesOnFailure(eventType: string): boolean;
96
+ /** Every event type that refuses on failure, for reporting what the rule covers. */
97
+ export declare function refuseOnFailureEventTypes(): string[];
98
+ /** Events declared and switched off, with the reason. The honest half of the answer. */
99
+ export declare function disabledEventTypes(): Array<{
100
+ eventType: string;
101
+ description: string;
102
+ }>;
@@ -0,0 +1,168 @@
1
+ /**
2
+ * The audit event registry, read from configuration (#1200, epic #1208).
3
+ *
4
+ * `ngdpbase.audit.events` in `config/app-default-config.json` names every
5
+ * recorded action, what happens when its record cannot be written, and whether it fires. This module is
6
+ * a reader over that map: nothing here declares an event.
7
+ *
8
+ * Until #1200 the declarations lived in this file, deliberately, on the
9
+ * argument that an operator who could edit them could narrow what the system
10
+ * claims to audit. The operator's decision on 2026-09-04 is that this is the
11
+ * point: configuration is authoritative, and narrowing is on the record —
12
+ * an admin UI edit emits `config-change`, and a disk edit is reported by
13
+ * `posture-recorded` at the next boot. See docs/audit-posture.md.
14
+ *
15
+ * #1638 (operator, 2026-10-05): a permission and its action are one thing. An
16
+ * event that records a permission's action is declared on the permission
17
+ * entry itself — `ngdpbase.permissions.definitions.<name>.audit` — and
18
+ * `ngdpbase.audit.events` holds only events that are not a permission's
19
+ * action. {@link auditDeclarationsFrom} reads both, and is the one reader:
20
+ * the runtime, the generator, the lint, the doc generator and the boot check
21
+ * all call it, so they cannot disagree.
22
+ *
23
+ * What stays in code is the emitters. `scripts/audit-coverage.ts` proves the
24
+ * map and the emitters agree.
25
+ */
26
+ import logger from './logger.js';
27
+ export const AUDIT_EVENTS_KEY = 'ngdpbase.audit.events';
28
+ /** The permission registry; an entry's `audit` field declares its event (#1638). */
29
+ export const PERMISSION_DEFINITIONS_KEY = 'ngdpbase.permissions.definitions';
30
+ let boundSource = null;
31
+ let warnedUnbound = false;
32
+ const warnedUndeclared = new Set();
33
+ /**
34
+ * Bind the live configuration. `AuditManager.initialize` calls this before it
35
+ * loads a provider, so every tier consulted from then on is the operator's.
36
+ *
37
+ * There is no fallback to the shipped file: reading
38
+ * `config/app-default-config.json` here would be a second reader over the
39
+ * configuration store, and a value could then come from the file when the live
40
+ * configuration says otherwise. Tests bind from the shipped file themselves
41
+ * (`vitest.setup.ts`), which is the one honest direct read.
42
+ */
43
+ export function bindAuditEvents(source) {
44
+ boundSource = source;
45
+ warnedUnbound = false;
46
+ }
47
+ function asDeclarations(value) {
48
+ if (!value || typeof value !== 'object' || Array.isArray(value))
49
+ return {};
50
+ const out = {};
51
+ for (const [name, entry] of Object.entries(value)) {
52
+ // A custom config removes a shipped entry by setting it to null.
53
+ if (!entry || typeof entry !== 'object')
54
+ continue;
55
+ out[name] = entry;
56
+ }
57
+ return out;
58
+ }
59
+ const warnedDoubled = new Set();
60
+ /**
61
+ * Every declared event in a configuration (#1638): the entries of
62
+ * `ngdpbase.audit.events`, plus every permission entry carrying `audit`, under
63
+ * the permission's name. A permission's `audit.description` defaults to the
64
+ * permission's own description.
65
+ *
66
+ * A name in both places is a declaration made twice. The shipped file never
67
+ * does it (`npm run lint:audit` fails); an operator's custom file that still
68
+ * sets a moved event under `ngdpbase.audit.events` is honoured — its fields
69
+ * override the permission's — and said once, so it is never silent.
70
+ */
71
+ export function auditDeclarationsFrom(read) {
72
+ const events = asDeclarations(read(AUDIT_EVENTS_KEY, {}));
73
+ const permissions = read(PERMISSION_DEFINITIONS_KEY, {});
74
+ const out = {};
75
+ if (permissions && typeof permissions === 'object' && !Array.isArray(permissions)) {
76
+ for (const [name, entry] of Object.entries(permissions)) {
77
+ const audit = entry?.audit;
78
+ if (!audit || typeof audit !== 'object')
79
+ continue;
80
+ const description = entry.description;
81
+ out[name] = { description: typeof description === 'string' ? description : name, ...audit };
82
+ }
83
+ }
84
+ // A custom file written before #1638 removed an event with null in the
85
+ // events map; that still removes it, wherever it is now declared.
86
+ const rawEvents = read(AUDIT_EVENTS_KEY, {});
87
+ if (rawEvents && typeof rawEvents === 'object' && !Array.isArray(rawEvents)) {
88
+ for (const [name, entry] of Object.entries(rawEvents)) {
89
+ if (entry === null)
90
+ delete out[name];
91
+ }
92
+ }
93
+ for (const [name, d] of Object.entries(events)) {
94
+ if (out[name] && !warnedDoubled.has(name)) {
95
+ warnedDoubled.add(name);
96
+ logger.warn(`[audit] '${name}' is declared in ${AUDIT_EVENTS_KEY} and on its permission entry; the ${AUDIT_EVENTS_KEY} entry wins. Move it to ${PERMISSION_DEFINITIONS_KEY}.${name}.audit (#1638).`);
97
+ }
98
+ out[name] = { ...out[name], ...d };
99
+ }
100
+ return out;
101
+ }
102
+ /** Every declared event, from the bound configuration. Empty, and said once, before binding. */
103
+ export function auditEventDeclarations() {
104
+ if (!boundSource) {
105
+ if (!warnedUnbound) {
106
+ warnedUnbound = true;
107
+ logger.warn(`[audit] ${AUDIT_EVENTS_KEY} is not bound yet; every event is treated as on-failure: continue until AuditManager initialises`);
108
+ }
109
+ return {};
110
+ }
111
+ return auditDeclarationsFrom(boundSource);
112
+ }
113
+ /** The declaration for one event, or null when configuration does not name it. */
114
+ export function auditEventDeclaration(eventType) {
115
+ const d = auditEventDeclarations()[eventType];
116
+ if (d)
117
+ return d;
118
+ // Never silent: an emitter producing a name configuration does not declare
119
+ // is treated as `standard` and said once, so the gap is visible in the log
120
+ // rather than in an assessor's report.
121
+ if (eventType && !warnedUndeclared.has(eventType)) {
122
+ warnedUndeclared.add(eventType);
123
+ logger.warn(`[audit] '${eventType}' is emitted but not declared in ${AUDIT_EVENTS_KEY}; treated as on-failure: continue`);
124
+ }
125
+ return null;
126
+ }
127
+ /** Every declared event type, sorted. */
128
+ export function auditEventTypes() {
129
+ return Object.keys(auditEventDeclarations()).sort();
130
+ }
131
+ /** Every event type this system undertakes to emit: declared and not switched off. */
132
+ export function requiredEventTypes() {
133
+ return Object.entries(auditEventDeclarations())
134
+ .filter(([, d]) => d.enabled !== false)
135
+ .map(([name]) => name)
136
+ .sort();
137
+ }
138
+ /** Is this event switched on? An undeclared event is not switched off. */
139
+ export function isAuditEventEnabled(eventType) {
140
+ return auditEventDeclaration(eventType)?.enabled !== false;
141
+ }
142
+ /**
143
+ * Does this event refuse the action when its record cannot be written
144
+ * (#1121, #1158)?
145
+ *
146
+ * Two layers need the same answer and must not be able to disagree:
147
+ * `recordAuditEvent` decides whether a failure rejects the action, and
148
+ * `FileAuditProvider.writeEvent` decides whether the record is fsynced before
149
+ * the write resolves. A rule that meant one thing to the caller and another to
150
+ * the writer would be the #1148 defect again.
151
+ */
152
+ export function refusesOnFailure(eventType) {
153
+ return auditEventDeclaration(eventType)?.['on-failure'] === 'refuse';
154
+ }
155
+ /** Every event type that refuses on failure, for reporting what the rule covers. */
156
+ export function refuseOnFailureEventTypes() {
157
+ return Object.entries(auditEventDeclarations())
158
+ .filter(([, d]) => d['on-failure'] === 'refuse' && d.enabled !== false)
159
+ .map(([name]) => name)
160
+ .sort();
161
+ }
162
+ /** Events declared and switched off, with the reason. The honest half of the answer. */
163
+ export function disabledEventTypes() {
164
+ return Object.entries(auditEventDeclarations())
165
+ .filter(([, d]) => d.enabled === false)
166
+ .map(([eventType, d]) => ({ eventType, description: d.description }))
167
+ .sort((a, b) => a.eventType.localeCompare(b.eventType));
168
+ }
@@ -0,0 +1,2 @@
1
+ /** BIP-0039 English wordlist (official 2048 words). */
2
+ export declare const BIP39_ENGLISH: readonly string[];
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Environment-owned configuration keys (#1089).
3
+ *
4
+ * Six keys used to be owned by two layers at once: the environment, via a
5
+ * hardcoded map inside `ConfigurationManager.getProperty()` that nothing
6
+ * outside could see, and the admin configuration screen, which accepted and
7
+ * persisted edits to them that could never take effect — the override was
8
+ * checked *before* the merged config, so the write was inert immediately, not
9
+ * merely on next boot.
10
+ *
11
+ * The rule this restores: **a configuration key is owned by exactly one layer,
12
+ * never both.** Ownership is now declared in `ngdpbase.config.env-keys`,
13
+ * mirroring the `ngdpbase.config.sensitive-values` (its `secret` entries) precedent — a map rather than an
14
+ * array, because the UI needs the variable's name to tell an operator where the
15
+ * value actually lives.
16
+ *
17
+ * Two decisions worth keeping straight, both settled deliberately:
18
+ *
19
+ * - **Ownership is not conditional on the variable being set.** A key in the
20
+ * map is env-owned whether or not anything is currently exporting it. Making
21
+ * it conditional would hand the UI the source of truth whenever the variable
22
+ * is absent, which is precisely the ambiguity being removed.
23
+ * - **The shipped value is a boot fallback, not a setting.** It exists so a
24
+ * fresh install comes up. `describePropertySource` still reports it as the
25
+ * *effective* value when nothing overrides it, because the screen must show
26
+ * what is actually in force — but the field stays read-only either way.
27
+ */
28
+ /** Config key holding the declared map of env-owned keys. */
29
+ export declare const ENV_KEYS_CONFIG_KEY = "ngdpbase.config.env-keys";
30
+ /** key → environment variable that supplies it. */
31
+ export type EnvKeyMap = Record<string, string>;
32
+ export interface PropertyDescription {
33
+ /** Whether this key is declared env-owned. Independent of whether the variable is set. */
34
+ envControlled: boolean;
35
+ /** The variable that owns it, or null when not env-owned. */
36
+ envVar: string | null;
37
+ /** The value actually in force right now. */
38
+ effective: unknown;
39
+ /** Where `effective` came from. */
40
+ source: 'env' | 'config';
41
+ }
42
+ /**
43
+ * Coerce an environment value to the type of the shipped default.
44
+ *
45
+ * Environment values are always strings, but the rest of the code expects the
46
+ * declared type — `ngdpbase.server.port` is `number` in `src/types/Config.ts`
47
+ * and ships as `3000`, so `NGDPBASE_PORT=3001` must not arrive as `"3001"` and
48
+ * quietly fail an arithmetic comparison somewhere downstream.
49
+ *
50
+ * Using the default's own type rather than a per-key table means there is one
51
+ * rule and nothing to keep in sync as keys are added.
52
+ *
53
+ * When the value cannot be coerced — a non-numeric string against a numeric
54
+ * default — the raw string is returned. Handing the caller something visibly
55
+ * wrong beats handing them a silent `NaN`.
56
+ */
57
+ export declare function coerceToTypeOf(value: string, defaultValue: unknown): unknown;
58
+ /**
59
+ * Describe where a config key's value comes from.
60
+ *
61
+ * @param key - The config key.
62
+ * @param envKeys - The declared map, or null when unavailable.
63
+ * @param env - Environment to read, normally `process.env`. Injected so this
64
+ * stays pure and testable.
65
+ * @param configValue - The merged config value, used both as the fallback and
66
+ * as the type to coerce an environment value to.
67
+ */
68
+ export declare function describePropertySource(key: string, envKeys: EnvKeyMap | null | undefined, env: Record<string, string | undefined>, configValue: unknown): PropertyDescription;