@jwilleke/ngdpbase-types 0.0.0 → 5.19.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 (304) 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 +427 -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 +188 -0
  71. package/lib/src/managers/DatabaseManager.js +590 -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/sqliteBackup.d.ts +128 -0
  158. package/lib/src/providers/sqliteBackup.js +365 -0
  159. package/lib/src/providers/sqliteLocation.d.ts +17 -0
  160. package/lib/src/providers/sqliteLocation.js +55 -0
  161. package/lib/src/providers/sqliteMigrations.d.ts +48 -0
  162. package/lib/src/providers/sqliteMigrations.js +72 -0
  163. package/lib/src/rendering/githubAlerts.d.ts +22 -0
  164. package/lib/src/rendering/htmlPolicy.d.ts +76 -0
  165. package/lib/src/rendering/markdownConverter.d.ts +73 -0
  166. package/lib/src/security/PolicyDecisionPoint.d.ts +245 -0
  167. package/lib/src/security/PolicyInformationPoint.d.ts +448 -0
  168. package/lib/src/security/pageActions.d.ts +40 -0
  169. package/lib/src/security/permissions.generated.d.ts +78 -0
  170. package/lib/src/types/Asset.d.ts +414 -0
  171. package/lib/src/types/Catalog.d.ts +61 -0
  172. package/lib/src/types/Comment.d.ts +11 -0
  173. package/lib/src/types/Config.d.ts +388 -0
  174. package/lib/src/types/Organization.d.ts +78 -0
  175. package/lib/src/types/OrganizationProvider.d.ts +38 -0
  176. package/lib/src/types/Page.d.ts +220 -0
  177. package/lib/src/types/Person.d.ts +56 -0
  178. package/lib/src/types/PersonProvider.d.ts +25 -0
  179. package/lib/src/types/Policy.d.ts +139 -0
  180. package/lib/src/types/Policy.js +17 -0
  181. package/lib/src/types/Provider.d.ts +810 -0
  182. package/lib/src/types/Role.d.ts +84 -0
  183. package/lib/src/types/RoleProvider.d.ts +35 -0
  184. package/lib/src/types/Schema.d.ts +425 -0
  185. package/lib/src/types/Share.d.ts +172 -0
  186. package/lib/src/types/Share.js +81 -0
  187. package/lib/src/types/User.d.ts +304 -0
  188. package/lib/src/types/Version.d.ts +189 -0
  189. package/lib/src/types/WikiEngine.d.ts +128 -0
  190. package/lib/src/types/express.d.ts +120 -0
  191. package/lib/src/types/express.js +1 -0
  192. package/lib/src/types/guards.d.ts +78 -0
  193. package/lib/src/types/heic-decode.d.ts +16 -0
  194. package/lib/src/types/index.d.ts +19 -0
  195. package/lib/src/types/linkedom.d.ts +77 -0
  196. package/lib/src/types/markdown-it-plugins.d.ts +21 -0
  197. package/lib/src/utils/DeltaStorage.d.ts +118 -0
  198. package/lib/src/utils/LocaleUtils.d.ts +105 -0
  199. package/lib/src/utils/LocaleUtils.js +294 -0
  200. package/lib/src/utils/PageNameMatcher.d.ts +98 -0
  201. package/lib/src/utils/PathPreflight.d.ts +38 -0
  202. package/lib/src/utils/PathPreflight.js +50 -0
  203. package/lib/src/utils/SectionUtils.d.ts +40 -0
  204. package/lib/src/utils/addonConfigLayer.d.ts +144 -0
  205. package/lib/src/utils/addonConfigLayer.js +382 -0
  206. package/lib/src/utils/addonDatabaseRules.d.ts +25 -0
  207. package/lib/src/utils/addonDatabaseRules.js +57 -0
  208. package/lib/src/utils/addonHost.d.ts +51 -0
  209. package/lib/src/utils/addonHost.js +72 -0
  210. package/lib/src/utils/addonInstaller.d.ts +109 -0
  211. package/lib/src/utils/addonLock.d.ts +37 -0
  212. package/lib/src/utils/addonLock.js +48 -0
  213. package/lib/src/utils/addonPageSync.d.ts +45 -0
  214. package/lib/src/utils/addonProvenance.d.ts +48 -0
  215. package/lib/src/utils/addonTarball.d.ts +41 -0
  216. package/lib/src/utils/addonsPathResolver.d.ts +76 -0
  217. package/lib/src/utils/addonsPathResolver.js +129 -0
  218. package/lib/src/utils/assetMetadataTags.d.ts +66 -0
  219. package/lib/src/utils/atomicWrite.d.ts +28 -0
  220. package/lib/src/utils/auditConfigChange.d.ts +57 -0
  221. package/lib/src/utils/auditEventNames.d.ts +50 -0
  222. package/lib/src/utils/auditEventNames.generated.d.ts +169 -0
  223. package/lib/src/utils/auditEventNames.generated.js +174 -0
  224. package/lib/src/utils/auditEventNames.js +49 -0
  225. package/lib/src/utils/auditEvents.d.ts +265 -0
  226. package/lib/src/utils/auditEvents.js +309 -0
  227. package/lib/src/utils/auditRegistry.d.ts +102 -0
  228. package/lib/src/utils/auditRegistry.js +168 -0
  229. package/lib/src/utils/bip39English.d.ts +2 -0
  230. package/lib/src/utils/configEnvKeys.d.ts +68 -0
  231. package/lib/src/utils/configFiles.d.ts +74 -0
  232. package/lib/src/utils/configFiles.js +150 -0
  233. package/lib/src/utils/delegation.d.ts +48 -0
  234. package/lib/src/utils/deriveUsername.d.ts +21 -0
  235. package/lib/src/utils/explainMediaPath.d.ts +123 -0
  236. package/lib/src/utils/formerTitles.d.ts +69 -0
  237. package/lib/src/utils/frontmatterAccess.d.ts +54 -0
  238. package/lib/src/utils/headlessAdminPassword.d.ts +55 -0
  239. package/lib/src/utils/imageTransform.d.ts +52 -0
  240. package/lib/src/utils/instanceEnvSecret.d.ts +51 -0
  241. package/lib/src/utils/jobSlots.d.ts +43 -0
  242. package/lib/src/utils/keywordNormalizer.d.ts +127 -0
  243. package/lib/src/utils/logger.d.ts +70 -0
  244. package/lib/src/utils/logger.js +106 -0
  245. package/lib/src/utils/magicLinkDeviceState.d.ts +95 -0
  246. package/lib/src/utils/managerUtils.d.ts +40 -0
  247. package/lib/src/utils/migrateLegacyPrivateAttachments.d.ts +15 -0
  248. package/lib/src/utils/orgFilename.d.ts +22 -0
  249. package/lib/src/utils/pageFeature.d.ts +27 -0
  250. package/lib/src/utils/pageFrontmatter.d.ts +21 -0
  251. package/lib/src/utils/pageNotes.d.ts +150 -0
  252. package/lib/src/utils/pageTitleRule.d.ts +37 -0
  253. package/lib/src/utils/pageToArticle.d.ts +59 -0
  254. package/lib/src/utils/pageUrl.d.ts +18 -0
  255. package/lib/src/utils/passwordChange.d.ts +12 -0
  256. package/lib/src/utils/passwordHash.d.ts +60 -0
  257. package/lib/src/utils/permissionCatalog.d.ts +52 -0
  258. package/lib/src/utils/pluginFormatters.d.ts +452 -0
  259. package/lib/src/utils/pluginFormatters.js +714 -0
  260. package/lib/src/utils/privateLinkRewrite.d.ts +42 -0
  261. package/lib/src/utils/privateStoreAccess.d.ts +57 -0
  262. package/lib/src/utils/privateStoreAccess.js +65 -0
  263. package/lib/src/utils/privateStoreCatalogs.d.ts +40 -0
  264. package/lib/src/utils/privateStoreCrypto.d.ts +127 -0
  265. package/lib/src/utils/privateStoreDoor.d.ts +181 -0
  266. package/lib/src/utils/privateStoreExport.d.ts +72 -0
  267. package/lib/src/utils/privateStoreFiles.d.ts +120 -0
  268. package/lib/src/utils/privateStoreMeta.d.ts +64 -0
  269. package/lib/src/utils/privateStoreMigrations.d.ts +37 -0
  270. package/lib/src/utils/privateStorePath.d.ts +259 -0
  271. package/lib/src/utils/privateStorePath.js +436 -0
  272. package/lib/src/utils/privateStoreTakeout.d.ts +76 -0
  273. package/lib/src/utils/privateStoreUnlock.d.ts +175 -0
  274. package/lib/src/utils/proxyClaim.d.ts +59 -0
  275. package/lib/src/utils/proxyClaim.js +30 -0
  276. package/lib/src/utils/redactPrivateNames.d.ts +21 -0
  277. package/lib/src/utils/redactPrivateNames.js +89 -0
  278. package/lib/src/utils/redactSecrets.d.ts +58 -0
  279. package/lib/src/utils/redactSecrets.js +171 -0
  280. package/lib/src/utils/renameLinkRewrite.d.ts +112 -0
  281. package/lib/src/utils/roleGrants.d.ts +35 -0
  282. package/lib/src/utils/safeRedirect.d.ts +32 -0
  283. package/lib/src/utils/schedule.d.ts +54 -0
  284. package/lib/src/utils/secretFileMode.d.ts +17 -0
  285. package/lib/src/utils/seededShippedPages.d.ts +45 -0
  286. package/lib/src/utils/sensitiveValues.d.ts +59 -0
  287. package/lib/src/utils/sensitiveValues.js +106 -0
  288. package/lib/src/utils/sessionEnd.d.ts +12 -0
  289. package/lib/src/utils/sessionGeneration.d.ts +24 -0
  290. package/lib/src/utils/sessionIdle.d.ts +41 -0
  291. package/lib/src/utils/sessionLimits.d.ts +68 -0
  292. package/lib/src/utils/shareLockbox.d.ts +64 -0
  293. package/lib/src/utils/sigstoreTrustedRoot.d.ts +33 -0
  294. package/lib/src/utils/sniffMime.d.ts +21 -0
  295. package/lib/src/utils/storeSearchIndex.d.ts +75 -0
  296. package/lib/src/utils/subjectMayDo.d.ts +21 -0
  297. package/lib/src/utils/systemCategoryRules.d.ts +30 -0
  298. package/lib/src/utils/systemCategoryRules.js +41 -0
  299. package/lib/src/utils/userCreateError.d.ts +62 -0
  300. package/lib/src/utils/username.d.ts +53 -0
  301. package/lib/src/utils/vaultUrlRewrite.d.ts +27 -0
  302. package/lib/src/utils/version.d.ts +84 -0
  303. package/lib/src/utils/videoFrame.d.ts +21 -0
  304. package/package.json +54 -3
@@ -0,0 +1,74 @@
1
+ /**
2
+ * The configuration files: where they are, how they are read, and how the
3
+ * custom file merges over the shipped one (#1214).
4
+ *
5
+ * One implementation, used by `ConfigurationManager` after the engine exists
6
+ * and by `app.ts` before it does (the listen port, TLS at bind time, and the
7
+ * base-URL explicitness check all run before `engine.initialize()`). Until
8
+ * #1214 `app.ts` had its own copy: a shallow spread that replaced a whole map
9
+ * on override, kept `_comment` keys, and computed the paths a second and third
10
+ * time. It happened to agree with the manager only because the keys it read
11
+ * were scalars.
12
+ *
13
+ * What stays in the manager: the legacy-key migrations (#642, #1117). They
14
+ * log, and they run between reading and merging. A pre-engine read therefore
15
+ * does not see a base URL set under a legacy key; that is a known limit named
16
+ * in the issue, not a second rule.
17
+ */
18
+ export declare const DEFAULT_CONFIG_FILE = "app-default-config.json";
19
+ export declare const DEFAULT_CUSTOM_CONFIG_FILE = "app-custom-config.json";
20
+ type Env = Record<string, string | undefined>;
21
+ /**
22
+ * The marker the setup wizard (or a headless install) writes when a site is
23
+ * installed. Its presence alone says the site is installed (#1410).
24
+ */
25
+ export declare function installCompletePath(dataFolder: string): string;
26
+ /** Fast-storage data folder: FAST_STORAGE, then the legacy INSTANCE_DATA_FOLDER, then ./data. */
27
+ export declare function instanceDataFolder(env?: Env): string;
28
+ export interface ConfigFilePaths {
29
+ instanceDataFolder: string;
30
+ /** The shipped defaults, in the code checkout: ./config/app-default-config.json */
31
+ defaultConfigPath: string;
32
+ /** The instance's overrides: <instanceDataFolder>/config/<INSTANCE_CONFIG_FILE or app-custom-config.json> */
33
+ customConfigPath: string;
34
+ }
35
+ /** The one derivation of both paths. */
36
+ export declare function configFilePaths(env?: Env, cwd?: string): ConfigFilePaths;
37
+ export interface ConfigFiles {
38
+ /** Null when the shipped file is missing — the caller decides whether that is fatal. */
39
+ defaultConfig: Record<string, unknown> | null;
40
+ /** The custom file with `_`-prefixed comment keys dropped; empty when the file is absent. */
41
+ customConfig: Record<string, unknown>;
42
+ /** The keys the operator set themselves, for "explicit or inherited?" questions (#1163). */
43
+ customKeys: Set<string>;
44
+ customConfigFound: boolean;
45
+ }
46
+ /** Read both files. Synchronous: both callers run at boot, before anything is served. */
47
+ export declare function readConfigFilesSync(paths: ConfigFilePaths): ConfigFiles;
48
+ export declare function isPlainObject(value: unknown): value is Record<string, unknown>;
49
+ /**
50
+ * Merge two arrays.
51
+ *
52
+ * If both hold objects that share an identity field (`id`, `authproviderid`),
53
+ * merge by it: a later entry overrides the same one and adds new ones.
54
+ * Otherwise the custom array replaces the default entirely — which is why a set
55
+ * an operator or an add-on may extend one entry at a time is a map, never an
56
+ * array (#1612).
57
+ */
58
+ export declare function mergeArrays(defaultArray: unknown[], customArray: unknown[]): unknown[];
59
+ /** The entries of a set: a map's `true` keys, in order; a legacy array's strings. Anything else is empty. */
60
+ export declare function enabledEntries(value: unknown): string[];
61
+ /**
62
+ * Deep merge, custom over default.
63
+ *
64
+ * - plain objects: recursively, key by key
65
+ * - arrays: {@link mergeArrays}
66
+ * - an array of names onto a set map: the names are added (#1612)
67
+ * - `null`: an explicit removal — the custom file cannot express a deletion any other way
68
+ * - `undefined`: skipped
69
+ * - anything else: custom wins
70
+ */
71
+ export declare function deepMergeObjects(defaultObj: Record<string, unknown>, customObj: Record<string, unknown>): Record<string, unknown>;
72
+ /** The top-level merge is the same rule; the name records what the two inputs are. */
73
+ export declare function deepMergeConfigs<T extends Record<string, unknown>>(defaultConfig: T, customConfig: Partial<T>): T;
74
+ export {};
@@ -0,0 +1,150 @@
1
+ /**
2
+ * The configuration files: where they are, how they are read, and how the
3
+ * custom file merges over the shipped one (#1214).
4
+ *
5
+ * One implementation, used by `ConfigurationManager` after the engine exists
6
+ * and by `app.ts` before it does (the listen port, TLS at bind time, and the
7
+ * base-URL explicitness check all run before `engine.initialize()`). Until
8
+ * #1214 `app.ts` had its own copy: a shallow spread that replaced a whole map
9
+ * on override, kept `_comment` keys, and computed the paths a second and third
10
+ * time. It happened to agree with the manager only because the keys it read
11
+ * were scalars.
12
+ *
13
+ * What stays in the manager: the legacy-key migrations (#642, #1117). They
14
+ * log, and they run between reading and merging. A pre-engine read therefore
15
+ * does not see a base URL set under a legacy key; that is a known limit named
16
+ * in the issue, not a second rule.
17
+ */
18
+ import fs from 'fs';
19
+ import path from 'path';
20
+ export const DEFAULT_CONFIG_FILE = 'app-default-config.json';
21
+ export const DEFAULT_CUSTOM_CONFIG_FILE = 'app-custom-config.json';
22
+ /**
23
+ * The marker the setup wizard (or a headless install) writes when a site is
24
+ * installed. Its presence alone says the site is installed (#1410).
25
+ */
26
+ export function installCompletePath(dataFolder) {
27
+ return path.join(dataFolder, '.install-complete');
28
+ }
29
+ /** Fast-storage data folder: FAST_STORAGE, then the legacy INSTANCE_DATA_FOLDER, then ./data. */
30
+ export function instanceDataFolder(env = process.env) {
31
+ return env.FAST_STORAGE || env.INSTANCE_DATA_FOLDER || './data';
32
+ }
33
+ /** The one derivation of both paths. */
34
+ export function configFilePaths(env = process.env, cwd = process.cwd()) {
35
+ const dataFolder = instanceDataFolder(env);
36
+ return {
37
+ instanceDataFolder: dataFolder,
38
+ defaultConfigPath: path.join(cwd, 'config', DEFAULT_CONFIG_FILE),
39
+ customConfigPath: path.join(dataFolder, 'config', env.INSTANCE_CONFIG_FILE || DEFAULT_CUSTOM_CONFIG_FILE)
40
+ };
41
+ }
42
+ /** Read both files. Synchronous: both callers run at boot, before anything is served. */
43
+ export function readConfigFilesSync(paths) {
44
+ const defaultConfig = fs.existsSync(paths.defaultConfigPath)
45
+ ? JSON.parse(fs.readFileSync(paths.defaultConfigPath, 'utf8'))
46
+ : null;
47
+ const customConfig = {};
48
+ const customConfigFound = fs.existsSync(paths.customConfigPath);
49
+ if (customConfigFound) {
50
+ const raw = JSON.parse(fs.readFileSync(paths.customConfigPath, 'utf8'));
51
+ for (const [key, value] of Object.entries(raw)) {
52
+ if (!key.startsWith('_'))
53
+ customConfig[key] = value;
54
+ }
55
+ }
56
+ return { defaultConfig, customConfig, customKeys: new Set(Object.keys(customConfig)), customConfigFound };
57
+ }
58
+ export function isPlainObject(value) {
59
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
60
+ }
61
+ /**
62
+ * The fields that identify an entry in a list of objects: `id`, or
63
+ * `authproviderid` for `ngdpbase.auth.factors` (#1523, #1612).
64
+ */
65
+ const IDENTITY_FIELDS = ['id', 'authproviderid'];
66
+ function identityField(arr) {
67
+ if (arr.length === 0)
68
+ return null;
69
+ for (const field of IDENTITY_FIELDS) {
70
+ if (arr.every((e) => isPlainObject(e) && typeof e[field] === 'string'))
71
+ return field;
72
+ }
73
+ return null;
74
+ }
75
+ /**
76
+ * Merge two arrays.
77
+ *
78
+ * If both hold objects that share an identity field (`id`, `authproviderid`),
79
+ * merge by it: a later entry overrides the same one and adds new ones.
80
+ * Otherwise the custom array replaces the default entirely — which is why a set
81
+ * an operator or an add-on may extend one entry at a time is a map, never an
82
+ * array (#1612).
83
+ */
84
+ export function mergeArrays(defaultArray, customArray) {
85
+ const field = identityField(defaultArray);
86
+ if (field && identityField(customArray) === field) {
87
+ const merged = new Map();
88
+ for (const item of defaultArray)
89
+ merged.set(item[field], item);
90
+ for (const item of customArray)
91
+ merged.set(item[field], item);
92
+ return Array.from(merged.values());
93
+ }
94
+ return customArray;
95
+ }
96
+ /**
97
+ * A set kept as a map of entry → `true` (#1612): any layer — an add-on, the
98
+ * operator — adds an entry without restating the rest, and `false` removes one
99
+ * on the record. An array merged onto such a map adds its entries rather than
100
+ * replacing the map, so a layer written as a list (an older custom config, an
101
+ * add-on) still extends the set.
102
+ */
103
+ function isEntryMap(value) {
104
+ return isPlainObject(value)
105
+ && Object.keys(value).length > 0
106
+ && Object.values(value).every((v) => typeof v === 'boolean' || v === null);
107
+ }
108
+ /** The entries of a set: a map's `true` keys, in order; a legacy array's strings. Anything else is empty. */
109
+ export function enabledEntries(value) {
110
+ if (Array.isArray(value))
111
+ return value.filter((v) => typeof v === 'string');
112
+ if (isPlainObject(value))
113
+ return Object.entries(value).filter(([, v]) => v === true).map(([k]) => k);
114
+ return [];
115
+ }
116
+ /**
117
+ * Deep merge, custom over default.
118
+ *
119
+ * - plain objects: recursively, key by key
120
+ * - arrays: {@link mergeArrays}
121
+ * - an array of names onto a set map: the names are added (#1612)
122
+ * - `null`: an explicit removal — the custom file cannot express a deletion any other way
123
+ * - `undefined`: skipped
124
+ * - anything else: custom wins
125
+ */
126
+ export function deepMergeObjects(defaultObj, customObj) {
127
+ const result = { ...defaultObj };
128
+ for (const key of Object.keys(customObj)) {
129
+ const customValue = customObj[key];
130
+ const defaultValue = result[key];
131
+ if (customValue === undefined)
132
+ continue;
133
+ else if (customValue === null)
134
+ result[key] = customValue;
135
+ else if (Array.isArray(customValue) && Array.isArray(defaultValue))
136
+ result[key] = mergeArrays(defaultValue, customValue);
137
+ else if (Array.isArray(customValue) && isEntryMap(defaultValue) && customValue.every((e) => typeof e === 'string')) {
138
+ result[key] = { ...defaultValue, ...Object.fromEntries(customValue.map((e) => [e, true])) };
139
+ }
140
+ else if (isPlainObject(customValue) && isPlainObject(defaultValue))
141
+ result[key] = deepMergeObjects(defaultValue, customValue);
142
+ else
143
+ result[key] = customValue;
144
+ }
145
+ return result;
146
+ }
147
+ /** The top-level merge is the same rule; the name records what the two inputs are. */
148
+ export function deepMergeConfigs(defaultConfig, customConfig) {
149
+ return deepMergeObjects(defaultConfig, customConfig);
150
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * What a delegated credential may never carry (#946, #1198, #1576).
3
+ *
4
+ * A person delegates a subset of their own permissions to something acting
5
+ * for them: an agent token they mint, or an app they allow through the OpenID
6
+ * Connect provider. Two kinds of permission are never delegable, however
7
+ * privileged the person:
8
+ *
9
+ * - `admin-*` — administration stays with a person at the keyboard
10
+ * (#946 decision 3);
11
+ * - `token-mint` — a delegation never creates a standing credential, or a
12
+ * leaked one could breed (#1198);
13
+ * - `token-extend` — a delegation never lengthens a standing credential, or a
14
+ * leaked token could keep itself alive (#1734). Step-up already refuses it
15
+ * to a delegation, but a site may turn step-up off; this does not move;
16
+ * - `proxy-grant` — a token or an app never lets someone act for the person
17
+ * (#1762). A proxy grant itself may carry it (that is how a proxy passes
18
+ * access on), so this rule is for tokens and apps, not proxy grants;
19
+ * - `vault-proxy` — it means something only inside a proxy grant, where it
20
+ * lets the proxy into the person's vaults (#1762 slice 2); on a token or an
21
+ * app it would read as access it can never give.
22
+ *
23
+ * One rule for both delegations, so they cannot drift.
24
+ */
25
+ /** Actions a delegation may never carry, by prefix. */
26
+ export declare const FORBIDDEN_DELEGATED_PREFIX = "admin-";
27
+ /** The permission to mint a token — never carried by a delegation. */
28
+ export declare const MINT_PERMISSION = "token-mint";
29
+ /** The permission to extend a token — never carried by a delegation (#1734). */
30
+ export declare const EXTEND_PERMISSION = "token-extend";
31
+ /** The permission to make a proxy grant — never carried by a token or an app (#1762). */
32
+ export declare const PROXY_GRANT_PERMISSION = "proxy-grant";
33
+ /** The proxy grant's vault marker — never carried by a token or an app (#1762). */
34
+ export declare const VAULT_PROXY_PERMISSION = "vault-proxy";
35
+ /** Why a scope cannot be delegated, or null when it can. */
36
+ export declare function refusedDelegatedScope(scope: string): string | null;
37
+ /**
38
+ * A delegation's permission list as given (#946, #1762): at least one, each a
39
+ * non-empty string, de-duplicated in order. Throws a caller-safe message. One
40
+ * rule for agent tokens and proxy grants.
41
+ */
42
+ export declare function requireScopeList(scopes: unknown): string[];
43
+ /**
44
+ * "Delegate, not grant" (#1178, #1762): the scopes the delegator does not hold,
45
+ * in order. Empty means every scope is theirs to hand on. `holds` is asked of
46
+ * the policy decision point; with no answer there is no delegation.
47
+ */
48
+ export declare function lackingScopes(scopes: readonly string[], holds: (scope: string) => Promise<boolean>): Promise<string[]>;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Derive a username from an email address (#1026).
3
+ *
4
+ * Extracted from GoogleOIDCProvider so every auto-provisioning path — OIDC and
5
+ * magic link — produces the same username for the same address. Two rules that
6
+ * disagree would let one provider create `jim-smith` and the other `jimsmith`
7
+ * for the same person.
8
+ */
9
+ import type UserManager from '../managers/UserManager.js';
10
+ /**
11
+ * Turn an email address into an unused username.
12
+ *
13
+ * Local part, lowercased, with anything outside `[a-z0-9]` replaced by a
14
+ * hyphen; a numeric suffix is appended until the name is free.
15
+ *
16
+ * The result is only free as of this call — a caller that derives a name and
17
+ * creates the account later must be prepared for `createUser` to reject a
18
+ * duplicate that appeared in between.
19
+ */
20
+ export declare function deriveUsername(email: string, userManager: UserManager): Promise<string>;
21
+ export default deriveUsername;
@@ -0,0 +1,123 @@
1
+ /** Why a path is, or is not, in the index. */
2
+ export type MediaPathVerdict =
3
+ /** Present in the index under this exact path. */
4
+ 'indexed'
5
+ /** Folded into another item by the #515 alternate-format dedup. */
6
+ | 'alternate'
7
+ /** Outside every configured scan folder. */
8
+ | 'not-in-scanned-folder'
9
+ /** Name begins with a dot. */
10
+ | 'dotfile'
11
+ /** Extension is not in the configured set. */
12
+ | 'extension'
13
+ /** A path segment matches `ignoreDirs`. */
14
+ | 'ignore-dir'
15
+ /** Deeper than `maxDepth` below its scan root. */
16
+ | 'max-depth'
17
+ /** Matched a `.ngdpbaseignore` pattern — the file's own or an ancestor's. */
18
+ | 'ignore-pattern'
19
+ /** Carries the `ngdpbaseignore` EXIF/XMP keyword. */
20
+ | 'ignore-keyword'
21
+ /** Eligible, but not in the index — most likely never scanned. */
22
+ | 'eligible-not-indexed';
23
+ /**
24
+ * The subset of {@link MediaPathVerdict} that means "the scanner skipped this"
25
+ * (#1056). `indexed`, `alternate` and `eligible-not-indexed` are states rather
26
+ * than skips, so they are excluded.
27
+ *
28
+ * Shared with the scan-time skip report so the probe and the report cannot
29
+ * disagree about why a file is missing. Two vocabularies for one question is
30
+ * the drift this taxonomy exists to prevent.
31
+ */
32
+ export type MediaSkipReason = Extract<MediaPathVerdict, 'not-in-scanned-folder' | 'dotfile' | 'extension' | 'ignore-dir' | 'max-depth' | 'ignore-pattern' | 'ignore-keyword'>;
33
+ /** One file or directory the scanner passed over, and why. */
34
+ export interface SkippedEntry {
35
+ /** Absolute path. For a directory-level skip, the directory itself. */
36
+ path: string;
37
+ reason: MediaSkipReason;
38
+ /** True when `path` is a directory whose contents were never walked. */
39
+ isDirectory?: boolean;
40
+ /** The pattern or directory name that matched, when there was one. */
41
+ matched?: string;
42
+ }
43
+ /**
44
+ * The persisted skip report for the most recent scan (#1056).
45
+ *
46
+ * `totalSkipped` is always exact; `skipped` may be capped, in which case
47
+ * `truncated` is true. Reporting a shortened list as if it were complete is the
48
+ * failure this shape exists to prevent — "0 excluded" while a directory-level
49
+ * ignore quietly dropped a whole tree is what made the original counter
50
+ * useless.
51
+ */
52
+ export interface MediaSkipReport {
53
+ version: number;
54
+ /** ISO timestamp of the scan that produced it. */
55
+ scannedAt: string;
56
+ totalSkipped: number;
57
+ truncated: boolean;
58
+ /**
59
+ * Exact count per reason, never capped.
60
+ *
61
+ * Measured on the reference library, the capped list alone would have been
62
+ * close to useless: 14,746 skips, 14,714 of them `extension`, against a cap
63
+ * of 1,000. The list gives examples; these counts give the shape, and the
64
+ * shape is what tells an operator whether their file is one of 14,000
65
+ * sidecars or the single odd case.
66
+ */
67
+ byReason: Partial<Record<MediaSkipReason, number>>;
68
+ /**
69
+ * Exact count per matched value within a reason — extensions, ignored
70
+ * directory names, ignore patterns. Answers "is my .orf being dropped?"
71
+ * without needing the file to appear in the capped list at all.
72
+ *
73
+ * Entries with no `matched` (dotfiles) are absent by construction.
74
+ */
75
+ byMatched: Record<string, number>;
76
+ skipped: SkippedEntry[];
77
+ }
78
+ export interface MediaPathExplanation {
79
+ verdict: MediaPathVerdict;
80
+ /** One sentence an operator can act on. */
81
+ detail: string;
82
+ /** Index id, when the path resolves to an item. */
83
+ itemId?: string;
84
+ /** For `alternate`, the primary item this file was folded into. */
85
+ primaryPath?: string;
86
+ /** For `ignore-dir` / `ignore-pattern`, what actually matched. */
87
+ matched?: string;
88
+ }
89
+ /** What the classifier needs to know. Mirrors FileSystemMediaProviderConfig. */
90
+ export interface MediaPathRules {
91
+ /** Absolute scan roots. */
92
+ folders: string[];
93
+ /** Directory names skipped anywhere in the tree. */
94
+ ignoreDirs: string[];
95
+ /** 0 = unlimited. Depth is counted below the scan root. */
96
+ maxDepth: number;
97
+ /** Lowercase, no leading dot. */
98
+ extensions: Set<string>;
99
+ }
100
+ /** Index facts, resolved by the caller so this stays free of I/O. */
101
+ export interface MediaPathIndexFacts {
102
+ /** Item id when this exact path is indexed. */
103
+ indexedId?: string;
104
+ /** Set when the path is an alternate folded into another item. */
105
+ alternateOf?: {
106
+ id: string;
107
+ filePath: string;
108
+ };
109
+ /** `.ngdpbaseignore` pattern that matched, if the caller found one. */
110
+ ignorePatternMatch?: string;
111
+ /** True when the file carries the `ngdpbaseignore` EXIF/XMP keyword. */
112
+ hasIgnoreKeyword?: boolean;
113
+ }
114
+ /** Longest configured folder containing `target`, or null. */
115
+ export declare function scanRootFor(target: string, folders: string[]): string | null;
116
+ /**
117
+ * Classify one absolute path.
118
+ *
119
+ * Evaluated in scanner order. The caller supplies index facts and any
120
+ * `.ngdpbaseignore` match, because those need I/O and this deliberately does
121
+ * none — which is what makes every branch testable without a filesystem.
122
+ */
123
+ export declare function explainMediaPath(target: string, rules: MediaPathRules, facts?: MediaPathIndexFacts): MediaPathExplanation;
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Former-title tracking for renamed pages (#1105).
3
+ *
4
+ * A rename leaves every inbound link pointing at a name that no longer exists.
5
+ * `rewriteInboundLinksAfterRename` repairs the links *inside* pages, but it is
6
+ * structurally unable to help a bookmark, a search result, or a link on someone
7
+ * else's site — those are not ours to rewrite.
8
+ *
9
+ * The record therefore lives in the page's own frontmatter:
10
+ *
11
+ * ```yaml
12
+ * title: New Title
13
+ * formerTitles:
14
+ * - Old Title
15
+ * ```
16
+ *
17
+ * The page is its own durable record. No sidecar to drift from the pages it
18
+ * describes, no retention window to expire, and it survives backup/restore,
19
+ * export/import and a full index rebuild — because it *is* the data rather than
20
+ * a cache of it. This replaced an earlier design that rehydrated from
21
+ * `page-rename` audit events, which carry a 90-day retention: a page renamed and
22
+ * then left alone would have had its old URL start failing again months later,
23
+ * silently.
24
+ *
25
+ * Two rules carried over from the rename map this supersedes (#1082):
26
+ *
27
+ * **Consulted only after live resolution fails.** The caller tries the real page
28
+ * set first, so a former title can never shadow an existing page.
29
+ *
30
+ * **Ambiguity is refused, never guessed.** If one former title is claimed by more
31
+ * than one page, no answer is given. A confidently wrong redirect to a page that
32
+ * merely once shared a name is worse than the 404 it replaces, because a 404 is
33
+ * visibly broken and a wrong page is not.
34
+ */
35
+ /** Sentinel for a former title claimed by more than one page. */
36
+ export declare const AMBIGUOUS: unique symbol;
37
+ /** Minimal page shape needed to derive the index. */
38
+ export interface FormerTitleSource {
39
+ title: string;
40
+ formerTitles?: unknown;
41
+ }
42
+ /**
43
+ * Work out what `formerTitles` should be after a save.
44
+ *
45
+ * Returns `undefined` when there is nothing to record and nothing already held,
46
+ * so an ordinary save on a never-renamed page does not add an empty key to its
47
+ * frontmatter.
48
+ *
49
+ * @param existing - Current `formerTitles` value, straight off disk and untrusted
50
+ * @param previousTitle - The title the page had before this save
51
+ * @param newTitle - The title it is being given
52
+ * @returns The new list, or undefined when the field should stay absent
53
+ */
54
+ export declare function computeFormerTitles(existing: unknown, previousTitle: string | undefined | null, newTitle: string | undefined | null): string[] | undefined;
55
+ /**
56
+ * Derive a former-title → current-title lookup from the page set.
57
+ *
58
+ * Keys are lowercased, so resolution is case-insensitive in the same way the
59
+ * provider's title index is.
60
+ *
61
+ * A title held by a **live** page is marked ambiguous rather than resolving to
62
+ * whoever once held it: live resolution runs first and will have answered
63
+ * already, so reaching this map for a live title means something is wrong, and
64
+ * refusing is the safe reading.
65
+ *
66
+ * @param pages - Every page, with its title and raw `formerTitles` frontmatter
67
+ * @returns Map of lowercased former title → current title, or AMBIGUOUS
68
+ */
69
+ export declare function buildFormerTitleIndex(pages: readonly FormerTitleSource[]): Map<string, string | typeof AMBIGUOUS>;
@@ -0,0 +1,54 @@
1
+ /**
2
+ * frontmatterAccess — the single implementation of ACL Tier 1 (#1054).
3
+ *
4
+ * A page's frontmatter can restrict who may act on it, via `access[<action>]`
5
+ * or, for viewing, `audience`. Two subsystems needed that answer and each had
6
+ * its own version of it, which is how they came to disagree:
7
+ *
8
+ * - `PolicyInformationPoint.checkFrontmatterAccess` decided a request, correctly.
9
+ * - `VersioningFileProvider.getRecentChanges` decided a listing, and only
10
+ * consulted `audience` for pages already marked private — so every
11
+ * non-private page carrying an audience was listed to everyone, while
12
+ * `/view/` on the same page returned 403.
13
+ *
14
+ * Both now call this. The invariant worth keeping is that anything which LISTS
15
+ * pages agrees with whatever DECIDES access, so a page can never appear in a
16
+ * listing its viewer cannot open.
17
+ *
18
+ * Pure and dependency-free so the provider layer can use it without reaching
19
+ * up into a manager.
20
+ */
21
+ /** The frontmatter fields Tier 1 reads. */
22
+ export interface AccessMetadataLike {
23
+ /** `{ view: ['role'], edit: [...] }` — per-action principal lists. */
24
+ access?: unknown;
25
+ /** Shorthand for `access.view`. */
26
+ audience?: unknown;
27
+ }
28
+ export interface FrontmatterDecision {
29
+ /** False when the page carries no rule for this action — caller falls through. */
30
+ decided: boolean;
31
+ /** Meaningful only when `decided`. */
32
+ allowed: boolean;
33
+ /** The principal that matched, for logging. */
34
+ matched?: string;
35
+ }
36
+ /**
37
+ * Principals permitted to perform `action`, or null when the page states no
38
+ * rule and the caller should fall through to global policy.
39
+ *
40
+ * `access[action]` wins; `audience` is the shorthand and applies to `view`
41
+ * only. An empty list counts as no rule — a page saying `audience: []`
42
+ * restricts nobody, which matters because a bare `access:` key parses that way.
43
+ */
44
+ export declare function resolveFrontmatterPrincipals(metadata: AccessMetadataLike | null | undefined, action: string): string[] | null;
45
+ /**
46
+ * Decide Tier 1 for a viewer described as a flat principal list — their roles
47
+ * plus their username. Callers holding a `UserContext` should pass
48
+ * `[...roles, username]`; the provider layer already works in these terms.
49
+ *
50
+ * Denies when the page states a rule and nothing matches. That default is the
51
+ * point: a listing that treats "no match" as "show it" is the bug this exists
52
+ * to prevent.
53
+ */
54
+ export declare function decideFrontmatterAccess(metadata: AccessMetadataLike | null | undefined, viewerPrincipals: readonly string[], action: string): FrontmatterDecision;
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Headless-install guard for the bootstrap admin password (#1087).
3
+ *
4
+ * `InstallService` documented a safety property the code did not have:
5
+ *
6
+ * > "There is no default — a headless install with that variable unset refuses
7
+ * > to start."
8
+ *
9
+ * It did not refuse. `ngdpbase.user.security.defaultpassword` ships as the
10
+ * literal `admin123`, and `UserManager.getBootstrapPassword()` falls back to a
11
+ * matching hardcoded constant when the key is missing or blank. So a headless
12
+ * container or k8s deploy with `NGDPBASE_ADMIN_PASSWORD` unset came up with
13
+ * `admin` / `admin123` — failing *open*, onto a credential published in this
14
+ * repository, where the documentation said it failed *closed*.
15
+ *
16
+ * This makes the documented behaviour real, for headless installs only.
17
+ *
18
+ * ## Why only headless
19
+ *
20
+ * A fresh local install coming up unattended so the setup wizard is reachable
21
+ * is a deliberate, documented property (`config/app-default-config.json`, the
22
+ * `_comment_user_security_defaultpassword` entry). There is a human present who
23
+ * will see the startup banner that `isAdminUsingDefaultPassword()` drives, and
24
+ * refusing to boot would strand them with no way in.
25
+ *
26
+ * An unattended deploy has neither the human nor the banner. That asymmetry is
27
+ * the whole reason this guard is scoped the way it is.
28
+ *
29
+ * ## Why it compares the value rather than reading the variable
30
+ *
31
+ * The check cannot simply ask whether `NGDPBASE_ADMIN_PASSWORD` is set, because
32
+ * the env-ref is opt-in: an operator supplies the password either by exporting
33
+ * that variable *and* pointing the config key at it, or by setting the key
34
+ * directly in `app-custom-config.json`. Both are legitimate. What actually
35
+ * matters is whether the resolved password is still the well-known shipped one,
36
+ * which catches both "variable unset" and "operator never changed the config".
37
+ *
38
+ * The cost is that an operator who deliberately chooses `admin123` is treated as
39
+ * having chosen nothing. That is the right trade.
40
+ */
41
+ /** The bootstrap password shipped in `config/app-default-config.json`. */
42
+ export declare const SHIPPED_BOOTSTRAP_PASSWORD = "admin123";
43
+ /**
44
+ * Refuse a headless install that would create the admin account on the shipped
45
+ * password.
46
+ *
47
+ * Called only from the path that actually creates the account — an instance
48
+ * that already has an admin never reaches it, so an existing deployment is
49
+ * unaffected by a restart.
50
+ *
51
+ * @param resolvedPassword - The password `createDefaultAdmin` is about to use.
52
+ * @param isHeadless - Whether `HEADLESS_INSTALL=true`.
53
+ * @throws When headless and the password is absent or still the shipped one.
54
+ */
55
+ export declare function assertHeadlessBootstrapPassword(resolvedPassword: string, isHeadless: boolean): void;
@@ -0,0 +1,52 @@
1
+ /**
2
+ * imageTransform — shared image transform pipeline for Asset providers.
3
+ *
4
+ * Wraps sharp with a consistent options interface so all providers
5
+ * (BasicAttachmentProvider, FileSystemMediaProvider, future S3Provider, etc.)
6
+ * generate thumbnails and apply format conversions through a single code path.
7
+ *
8
+ * Part of Epic #405 Phase 6 — Transform pipeline.
9
+ */
10
+ /**
11
+ * Options for a single image transform operation.
12
+ */
13
+ export interface ImageTransformOptions {
14
+ /** Target width in pixels (omit to skip resizing) */
15
+ width?: number;
16
+ /** Target height in pixels (omit to skip resizing) */
17
+ height?: number;
18
+ /**
19
+ * Resize fit mode (default: 'inside').
20
+ * inside — preserve full image, letterbox to fit bounds
21
+ * cover — crop to fill bounds exactly
22
+ * contain — letterbox with background fill
23
+ * fill — stretch to exact bounds (may distort)
24
+ */
25
+ fit?: 'inside' | 'cover' | 'contain' | 'fill';
26
+ /** Output format (default: 'jpeg') */
27
+ format?: 'jpeg' | 'webp' | 'png';
28
+ /** Compression quality 1–100 (default: 85; ignored for png) */
29
+ quality?: number;
30
+ }
31
+ /**
32
+ * Transform an image using sharp.
33
+ *
34
+ * Accepts either a Buffer (e.g. a freshly uploaded file) or an absolute
35
+ * file path (e.g. a media-library file). Applies EXIF-based auto-rotation
36
+ * before resizing so orientation is always correct regardless of camera model.
37
+ *
38
+ * @param input - Image buffer or absolute path to the source file
39
+ * @param options - Resize / format options
40
+ * @returns - Transformed image as a Buffer
41
+ * @throws - Re-throws sharp errors (caller should handle)
42
+ */
43
+ export declare function transformImage(input: Buffer | string, options: ImageTransformOptions): Promise<Buffer>;
44
+ /**
45
+ * Parse a size string of the form "WxH" (e.g. "300x300", "150x150").
46
+ *
47
+ * @returns `{ width, height }` on success, or `null` if the string is malformed.
48
+ */
49
+ export declare function parseSize(size: string): {
50
+ width: number;
51
+ height: number;
52
+ } | null;