@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,599 @@
1
+ import BaseAttachmentProvider, { FileInfo, User, AttachmentResult } from './BaseAttachmentProvider.js';
2
+ import type { ProviderInfo, StoreFileEntry, StoreFileLocation } from '../types/Provider.js';
3
+ import { AttachmentMetadata } from '../types/index.js';
4
+ import type { AssetProvider, AssetRecord, AssetQuery, AssetPage, AssetInput, AssetMetadata, AssetMetadataPatch } from '../types/Asset.js';
5
+ import type { CreativeWork } from '../types/Schema.js';
6
+ import type { ActorContext } from '../context/ActorContext.js';
7
+ import type { WikiEngine } from '../types/WikiEngine.js';
8
+ /**
9
+ * Schema.org Person metadata
10
+ */
11
+ interface SchemaPerson {
12
+ '@type': 'Person';
13
+ name: string;
14
+ email?: string;
15
+ }
16
+ /**
17
+ * Schema.org mention reference
18
+ */
19
+ interface SchemaMention {
20
+ '@type'?: 'Thing';
21
+ name?: string;
22
+ url?: string;
23
+ }
24
+ /**
25
+ * Schema.org CreativeWork metadata for attachments
26
+ */
27
+ interface SchemaCreativeWork {
28
+ '@context': 'https://schema.org';
29
+ '@type': 'CreativeWork';
30
+ identifier: string;
31
+ name: string;
32
+ description?: string;
33
+ author?: SchemaPerson;
34
+ editor?: SchemaPerson;
35
+ dateCreated: string;
36
+ dateModified: string;
37
+ encodingFormat: string;
38
+ contentSize: number;
39
+ url: string;
40
+ storageLocation: string;
41
+ isFamilyFriendly?: boolean;
42
+ isBasedOn?: string;
43
+ mentions: SchemaMention[];
44
+ /** Whether this attachment belongs to a private page */
45
+ isPrivate?: boolean;
46
+ /** Username of the page creator; set when isPrivate is true */
47
+ creator?: string;
48
+ /** Private-store id when the file lives in the page store (#1386) */
49
+ store?: string;
50
+ /** Structured metadata extracted at upload time (EXIF via sharp) — Phase 5 #405 */
51
+ assetMetadata?: AssetMetadata;
52
+ /** Title embedded in the document (PDF /Info Title; docx core.xml dc:title). Distinct from the uploaded filename. */
53
+ documentTitle?: string;
54
+ /** Author embedded in the document (PDF /Info Author; docx dc:creator). Distinct from the uploader's user. */
55
+ documentAuthor?: string;
56
+ /** Subject / abstract embedded in the document (PDF /Info Subject; docx dc:description). */
57
+ documentSubject?: string;
58
+ /** Keywords / tags embedded in the document (PDF /Info Keywords; docx dc:subject). String array, deduplicated. */
59
+ documentKeywords?: string[];
60
+ /** Document's own CreationDate (when the file was first authored). Distinct from upload time. */
61
+ documentDateCreated?: string;
62
+ /** Document's own ModDate (last edit before upload). Distinct from upload time. */
63
+ documentDateModified?: string;
64
+ /** BCP-47 language tag from the document (PDF /Lang; docx core.xml dc:language). */
65
+ inLanguage?: string;
66
+ }
67
+ /**
68
+ * Backup data structure
69
+ */
70
+ interface BackupData extends Record<string, unknown> {
71
+ providerName: string;
72
+ timestamp: string;
73
+ metadataFile: string;
74
+ storageDirectory: string;
75
+ attachments: Array<[string, SchemaCreativeWork]>;
76
+ }
77
+ /**
78
+ * The extension to store a file under, given what the uploader called it and
79
+ * what they said it was.
80
+ *
81
+ * A stored file is named `{generated-id}{ext}`. The id is ours; the extension
82
+ * used to be whatever `path.extname()` returned for the uploaded name — and
83
+ * that function does not promise an extension, it promises everything after
84
+ * the last dot in the basename. For `photo.jpg` that is `.jpg`. For a name
85
+ * written by hand in the request, such as `x.\..\..\etc\passwd`, it is
86
+ * `.\etc\passwd`, and we pasted it onto the id without ever asking whether it
87
+ * looked like an extension. Harmless on Linux, where `\` is an ordinary
88
+ * character — but it is untrusted text in a filename we construct, which it
89
+ * should never have been.
90
+ *
91
+ * So an extension is now defined rather than inherited: a short run of letters
92
+ * and digits, and nothing else. It comes from
93
+ *
94
+ * 1. the uploaded name, when that already matches the definition — which is
95
+ * every real file, and keeps `.docx`, `.heic` and the rest that no table
96
+ * here lists; or
97
+ * 2. the declared MIME type through the table above, a closed set we own; or
98
+ * 3. nowhere, and the file is stored as the bare id, exactly as an
99
+ * extensionless upload has always been.
100
+ *
101
+ * Nothing downstream depends on this: a download's Content-Type comes from the
102
+ * recorded `encodingFormat`, and the only reader of the stored extension is the
103
+ * orphan-recovery scan, which maps it back through this same table.
104
+ */
105
+ export declare function safeStoredExtension(originalName: string, mimeType?: string): string;
106
+ /**
107
+ * BasicAttachmentProvider - Filesystem-based attachment storage
108
+ *
109
+ * Implements attachment storage using filesystem with Schema.org CreativeWork metadata.
110
+ * Attachments are stored in a shared directory structure, not tied to individual pages.
111
+ * Page references are tracked via the "mentions" array in metadata.
112
+ *
113
+ * Based on JSPWiki's BasicAttachmentProvider:
114
+ * https://github.com/apache/jspwiki/blob/master/jspwiki-main/src/main/java/org/apache/wiki/providers/BasicAttachmentProvider.java
115
+ *
116
+ * Features:
117
+ * - Filesystem storage with SHA-256 content hashing
118
+ * - Schema.org CreativeWork metadata format
119
+ * - Shared storage model with page mentions tracking
120
+ * - Automatic metadata persistence
121
+ * - Backup/restore support
122
+ */
123
+ declare class BasicAttachmentProvider extends BaseAttachmentProvider implements AssetProvider {
124
+ private storageDirectory;
125
+ /** Pre-#1386 attachments/{legacyprivateroot}/{user}/ — migrate-FROM and read fallback only. */
126
+ private legacyPrivateDir;
127
+ private pagesDirectory;
128
+ private privateStoreLayout;
129
+ private thumbDir;
130
+ private metadataFile;
131
+ private attachmentMetadata;
132
+ private maxFileSize;
133
+ private allowedMimeTypes;
134
+ private hashMethod;
135
+ /**
136
+ * Lazily-instantiated ExifTool worker (Slice 5 of #755 / #759).
137
+ * Used to extract embedded document metadata from PDFs / docx at upload
138
+ * time. Created on first use to avoid spawning a perl process when the
139
+ * provider initialises but never sees a PDF or docx upload.
140
+ */
141
+ private _exiftool;
142
+ private exiftool;
143
+ /**
144
+ * MIME types that carry extractable document metadata.
145
+ * exiftool reads both via its PDF / OOXML modules.
146
+ */
147
+ private static readonly DOC_METADATA_MIME_TYPES;
148
+ constructor(engine: WikiEngine);
149
+ /**
150
+ * Initialize the provider
151
+ * All configuration access via ConfigurationManager
152
+ */
153
+ initialize(): Promise<void>;
154
+ /**
155
+ * Verify that the attachment storage directory is accessible.
156
+ *
157
+ * Returns false when the directory cannot be read — e.g. a NAS or SLOW_STORAGE
158
+ * volume that has been unmounted or an SMB share that has dropped. AssetManager
159
+ * uses this to skip the provider during fan-out rather than surfacing I/O errors
160
+ * to end users.
161
+ */
162
+ healthCheck(): Promise<boolean>;
163
+ /**
164
+ * Format bytes to human-readable size
165
+ * @param bytes - Size in bytes
166
+ * @returns Formatted size
167
+ * @private
168
+ */
169
+ private formatSize;
170
+ /**
171
+ * Rewrite stale storageLocation paths after a data migration.
172
+ *
173
+ * Compares each entry's directory against the current storageDirectory.
174
+ * If they differ, the absolute path is replaced with the correct one
175
+ * (preserving the basename/hash filename) and metadata is saved once.
176
+ * Private attachments are corrected to the page store (legacy leftovers
177
+ * stay at attachments/{legacyprivateroot} until the file itself moves).
178
+ */
179
+ private migrateStaleStoragePaths;
180
+ /**
181
+ * On-disk path for an attachment. Private files live in the page store;
182
+ * a leftover under attachments/{legacyprivateroot} is read fallback only.
183
+ */
184
+ private resolveAttachmentFilePath;
185
+ /**
186
+ * Load metadata from JSON file
187
+ * @private
188
+ */
189
+ private loadMetadata;
190
+ /**
191
+ * Save metadata to JSON file
192
+ * @private
193
+ */
194
+ private saveMetadata;
195
+ /**
196
+ * Generate unique attachment ID using SHA-256 hash of content
197
+ * @param buffer - File data
198
+ * @returns Attachment ID (hash)
199
+ * @private
200
+ */
201
+ private generateAttachmentId;
202
+ /**
203
+ * Validate file against constraints
204
+ * @param fileInfo - File information
205
+ * @private
206
+ */
207
+ private validateFile;
208
+ /**
209
+ * Store an attachment with metadata (internal method using Schema.org format)
210
+ * @param fileBuffer - File data
211
+ * @param fileInfo - { originalName, mimeType, size }
212
+ * @param metadata - Schema.org CreativeWork metadata
213
+ * @param user - User object { name, email }
214
+ * @param options - Privacy-aware storage options
215
+ * @returns Complete attachment metadata
216
+ * @private
217
+ */
218
+ private storeAttachmentInternal;
219
+ /**
220
+ * Store an attachment with metadata (BaseAttachmentProvider interface method)
221
+ * @param fileBuffer - File data
222
+ * @param fileInfo - { originalName, mimeType, size }
223
+ * @param metadata - Attachment metadata
224
+ * @param user - User object
225
+ * @returns Attachment metadata
226
+ */
227
+ storeAttachment(fileBuffer: Buffer, fileInfo: FileInfo, metadata?: Partial<AttachmentMetadata>, user?: User | null): Promise<AttachmentMetadata>;
228
+ /**
229
+ * Get attachment file and metadata
230
+ *
231
+ * Falls back to a disk scan when metadata is missing but a file matching
232
+ * `{attachmentId}.*` exists in the storage directory (orphaned file). This
233
+ * handles the case where attachment metadata was lost without requiring a
234
+ * data repair before the file can be served. A warning is logged so operators
235
+ * know the metadata repair is still needed.
236
+ *
237
+ * @param attachmentId - Attachment identifier
238
+ * @returns File buffer and metadata or null
239
+ */
240
+ getAttachment(attachmentId: string): Promise<AttachmentResult | null>;
241
+ /**
242
+ * Disk-scan fallback for orphaned attachment files (file on disk, no metadata record).
243
+ * @param attachmentId - Attachment identifier (SHA-256 hash)
244
+ * @returns File buffer and synthetic metadata, or null if not found
245
+ * @private
246
+ */
247
+ private getOrphanedAttachment;
248
+ private storeIndexFile;
249
+ private storeFilePath;
250
+ private requirePagesDirectory;
251
+ private readStoreIndex;
252
+ private writeStoreIndex;
253
+ storeFileInStore(location: StoreFileLocation, bytes: Buffer, file: {
254
+ originalName: string;
255
+ mimeType: string;
256
+ description: string;
257
+ author?: string;
258
+ pageName?: string;
259
+ }): Promise<StoreFileEntry>;
260
+ getFileInStore(location: StoreFileLocation, id: string): Promise<{
261
+ entry: StoreFileEntry;
262
+ bytes: Buffer;
263
+ } | null>;
264
+ /** Everything this store lists, newest first — the store's half of a merged list (#1460). */
265
+ listFilesInStore(location: StoreFileLocation): Promise<StoreFileEntry[]>;
266
+ filesInStoreForPage(location: StoreFileLocation, pageName: string): Promise<StoreFileEntry[]>;
267
+ /**
268
+ * Add or remove `pageName` in one store file's mentions (#1460) — the store
269
+ * index's half of save-time mention sync. `false` when this store does not
270
+ * list `id`, so a caller can try the next of its own stores.
271
+ */
272
+ setFileMentionInStore(location: StoreFileLocation, id: string, pageName: string, mentioned: boolean): Promise<boolean>;
273
+ /**
274
+ * Move one record out of the global `attachment-metadata.json` and into its
275
+ * store's own index (#1460), bytes and all.
276
+ *
277
+ * The file KEEPS the name it has: renaming it would break nothing that is
278
+ * written down, but it would rewrite a file for no reason, and a store is
279
+ * meant to be a directory an operator can read. The entry keeps the record's
280
+ * identifier too — that id is the `/attachments/{id}` URL on every page that
281
+ * references the file.
282
+ *
283
+ * Idempotent: a record already gone from the map, or a store that already
284
+ * lists the id, is a no-op that answers `null`. The move itself is skipped
285
+ * when the bytes are already in place.
286
+ *
287
+ * @returns the store entry it wrote, or null when there was nothing to move
288
+ */
289
+ adoptRecordIntoStore(location: StoreFileLocation, id: string): Promise<StoreFileEntry | null>;
290
+ /**
291
+ * The private records still sitting in the shared index (#1460) — what the
292
+ * start-up migration has to move. Identifier, owner and store only: enough
293
+ * to place the file, and nothing of its name leaves this method.
294
+ *
295
+ * Two ways a record says it is private, in order:
296
+ *
297
+ * - `isPrivate`, #1398's flag, written by `storeAttachmentInternal` together
298
+ * with `creator` and `store`. That is the record deciding from itself.
299
+ * - failing that, a mention naming a private page — `private/{owner}/{store}/{title}`
300
+ * since #1456. The record is then placed by the page it is attached to,
301
+ * with `owner: null` so the caller confirms it through PageManager, which
302
+ * is what actually knows whose store a page is in.
303
+ *
304
+ * A record that is neither is a public attachment and is not listed: the
305
+ * shared pool is exactly what stays behind.
306
+ */
307
+ privateRecordsInSharedIndex(): Array<{
308
+ id: string;
309
+ owner: string | null;
310
+ store: string | null;
311
+ pages: string[];
312
+ }>;
313
+ deleteFileInStore(location: StoreFileLocation, id: string): Promise<StoreFileEntry | null>;
314
+ /**
315
+ * Copy a shared-pool file into a store under the same id, mentioned by
316
+ * `pageName` there. The shared record is left as it is. A store that already
317
+ * lists the id just gains the mention.
318
+ *
319
+ * @returns the store entry, or null when the pool has no such file
320
+ */
321
+ copyRecordIntoStore(location: StoreFileLocation, id: string, pageName: string): Promise<StoreFileEntry | null>;
322
+ /**
323
+ * Copy a store's file into another store under the same id, mentioned by
324
+ * `pageName` there. A destination that already lists the id just gains the
325
+ * mention.
326
+ *
327
+ * @returns the destination's entry, or null when the source does not list it
328
+ */
329
+ copyStoreFileToStore(from: StoreFileLocation, to: StoreFileLocation, id: string, pageName: string): Promise<StoreFileEntry | null>;
330
+ /**
331
+ * Copy a store's file into the shared pool under the same id, opened, and
332
+ * mentioned by `pageName` (a public page). A pool that already holds the id
333
+ * just gains the mention.
334
+ *
335
+ * @returns true when the pool holds the file afterwards
336
+ */
337
+ copyStoreFileToPool(from: StoreFileLocation, id: string, pageName: string): Promise<boolean>;
338
+ /**
339
+ * Take a file out of the shared pool: its record, its bytes and any cached
340
+ * thumbnails of it (#1842) — used when the file has moved into a vault and
341
+ * no public page uses it any more, so no public copy of it is left.
342
+ */
343
+ removeRecordFromPool(id: string): Promise<boolean>;
344
+ /**
345
+ * Set a shared-pool record's mentions to exactly `names` (#1842), keeping the
346
+ * mention objects it already has for those names.
347
+ */
348
+ setPoolMentions(id: string, names: string[]): Promise<boolean>;
349
+ /**
350
+ * Get attachment metadata only
351
+ * @param attachmentId - Attachment identifier
352
+ * @returns Attachment metadata or null
353
+ */
354
+ getAttachmentMetadata(attachmentId: string): Promise<AttachmentMetadata | null>;
355
+ /**
356
+ * Update attachment metadata
357
+ * @param attachmentId - Attachment identifier
358
+ * @param updates - Metadata updates
359
+ * @returns Success status
360
+ */
361
+ updateAttachmentMetadata(attachmentId: string, updates: Partial<AttachmentMetadata>): Promise<boolean>;
362
+ /**
363
+ * Delete an attachment
364
+ * @param attachmentId - Attachment identifier
365
+ * @returns True if deleted, false if not found
366
+ */
367
+ deleteAttachment(attachmentId: string): Promise<boolean>;
368
+ /**
369
+ * Check if attachment exists
370
+ * @param attachmentId - Attachment identifier
371
+ * @returns True if exists
372
+ */
373
+ attachmentExists(attachmentId: string): Promise<boolean>;
374
+ /**
375
+ * Get all attachments metadata
376
+ * @returns Array of attachment metadata
377
+ */
378
+ getAllAttachments(): Promise<AttachmentMetadata[]>;
379
+ /**
380
+ * Get attachments used by a specific page
381
+ * @param pageName - Page name/title
382
+ * @returns Array of attachment metadata
383
+ */
384
+ getAttachmentsForPage(pageName: string): Promise<AttachmentMetadata[]>;
385
+ /**
386
+ * Find an attachment by its original filename across all attachments
387
+ * @param filename - Original filename to search for
388
+ * @returns Matching attachment metadata or null
389
+ */
390
+ getAttachmentByFilename(filename: string): Promise<AttachmentMetadata | null>;
391
+ /**
392
+ * List attachments for a page (AttachmentProvider interface method)
393
+ * @param pageUuid - Page UUID
394
+ * @returns Array of attachment metadata
395
+ */
396
+ listAttachments(pageUuid: string): Promise<AttachmentMetadata[]>;
397
+ /**
398
+ * Delete all attachments for a page
399
+ * @param pageUuid - Page UUID
400
+ * @returns Number of attachments deleted
401
+ */
402
+ deletePageAttachments(pageUuid: string): Promise<number>;
403
+ /**
404
+ * Refresh attachment list (rescan storage)
405
+ * @returns Promise that resolves when complete
406
+ */
407
+ refreshAttachmentList(): Promise<void>;
408
+ /**
409
+ * #865 Slice 2: basenames of all stored attachment files on disk (top-level
410
+ * storage dir; excludes .json bookkeeping). Used by the health report to
411
+ * find recordless files and missing-file records.
412
+ */
413
+ listStorageFiles(): Promise<string[]>;
414
+ /**
415
+ * #865 Slice 3: move an attachment (record + stored file) into the
416
+ * quarantine subdirectory instead of hard-deleting. The record is removed
417
+ * from live metadata and appended to a per-run manifest inside quarantine/
418
+ * so the operation is reversible by hand. Skips (returns false) on any
419
+ * error — never deletes on failure (media-prune #867 precedent).
420
+ */
421
+ quarantineAttachment(identifier: string, manifestPath: string): Promise<boolean>;
422
+ /**
423
+ * #865 Slice 3: move a recordless disk file into quarantine. Skips on error.
424
+ */
425
+ quarantineFile(basename: string): Promise<boolean>;
426
+ /** #865 Slice 3: absolute quarantine directory path (for manifests/report). */
427
+ getQuarantineDir(): string | null;
428
+ /**
429
+ * Get provider information
430
+ * @returns Provider metadata
431
+ */
432
+ getProviderInfo(): ProviderInfo;
433
+ /**
434
+ * Backup provider data
435
+ * @returns Backup data
436
+ */
437
+ backup(): Promise<BackupData>;
438
+ /**
439
+ * Restore provider data from backup
440
+ * @param backupData - Backup data
441
+ * @returns Promise that resolves when complete
442
+ */
443
+ restore(backupData: Record<string, unknown>): Promise<void>;
444
+ readonly id = "local";
445
+ readonly displayName = "Local Attachments";
446
+ readonly capabilities: import('../types/Asset.js').ProviderCapability[];
447
+ /**
448
+ * AssetProvider.getThumbnail() — generate (and cache) a JPEG thumbnail for image attachments.
449
+ * Returns null for non-image attachments or when the source file cannot be processed.
450
+ */
451
+ getThumbnail(id: string, size: string): Promise<Buffer | null>;
452
+ /**
453
+ * Extract embedded document metadata via ExifTool (Slice 5 of #755 / #759).
454
+ *
455
+ * Handles PDFs and Office Open XML (`.docx`, `.xlsx`, `.pptx`). Returns the
456
+ * subset of fields we map into `SchemaCreativeWork` per the schemas.md
457
+ * `DigitalDocument` per-source mapping. Returns null for non-document MIME
458
+ * types or when extraction fails (treated as non-fatal — uploads always
459
+ * succeed even if metadata extraction trips).
460
+ */
461
+ private extractDocMetadata;
462
+ /**
463
+ * Slice 5b of #760 (#763) — walk every stored attachment and re-extract
464
+ * embedded document metadata for the supported doc MIMEs. Backfills the
465
+ * seven Slice-5 fields (documentTitle / documentAuthor / documentSubject /
466
+ * documentKeywords / documentDateCreated / documentDateModified /
467
+ * inLanguage) on pre-v3.27.0 records that never went through the
468
+ * Slice-5 extraction path at upload time.
469
+ *
470
+ * Per-file failures are non-fatal (logged + counted) — mirrors the
471
+ * existing `extractDocMetadata` contract where uploads succeed even when
472
+ * exiftool trips. Non-document MIMEs are skipped without modification.
473
+ * Returns a summary suitable for the background-job report.
474
+ */
475
+ backfillDocMetadata(onProgress?: (processed: number, total: number) => void): Promise<{
476
+ scanned: number;
477
+ updated: number;
478
+ skipped: number;
479
+ errors: number;
480
+ }>;
481
+ /**
482
+ * Apply extracted doc-metadata to a stored record field-by-field. Sets each
483
+ * field when the extracted value exists; clears when extraction returned
484
+ * null/undefined for that field. Per-field mutation so a partial re-extract
485
+ * doesn't drop unrelated existing data. Returns true when the record
486
+ * changed (caller decides whether to persist).
487
+ *
488
+ * Shared by `backfillDocMetadata` (Slice 5b / #763) and
489
+ * `storeAttachmentInternal`'s dedup-by-hash branch (#764). Keeping the
490
+ * two call sites on the same helper ensures their "set vs clear stale"
491
+ * semantics stay in lockstep.
492
+ */
493
+ private applyDocMetadataFields;
494
+ /**
495
+ * Format an exiftool-vendored date value to ISO-ish "YYYY-MM-DD HH:MM:SS".
496
+ * Accepts the `ExifDateTime` shape (object with year/month/etc.) or a string
497
+ * passthrough. Returns undefined for anything unparseable.
498
+ */
499
+ private formatExifDate;
500
+ /**
501
+ * Convert a SchemaCreativeWork record to a schema.org-shaped CreativeWork
502
+ * (Slice 5 of #755 / #759).
503
+ *
504
+ * For PDF / docx / xlsx / pptx attachments → `DigitalDocument` with embedded
505
+ * doc-metadata fields populated. For everything else → a base CreativeWork
506
+ * (no subtype specialisation) — image/video attachments that need full
507
+ * ImageObject / VideoObject treatment are out-of-scope for this slice
508
+ * (they go through the media path).
509
+ *
510
+ * Public so AttachmentManager (the registered `CatalogSource`) can call it
511
+ * without exposing the internal SchemaCreativeWork shape.
512
+ */
513
+ toCreativeWork(schema: SchemaCreativeWork): CreativeWork;
514
+ /** Convert a SchemaCreativeWork record to a unified AssetRecord. */
515
+ private schemaToAssetRecord;
516
+ /**
517
+ * AssetProvider.search() — searches by filename and description.
518
+ *
519
+ * The shared pool only. A private store's files are in no shared index, so
520
+ * they are searched through {@link searchFilesInStore}, by the one caller
521
+ * that has the requester's context to say which stores are theirs (#1460).
522
+ */
523
+ search(query: AssetQuery): Promise<AssetPage>;
524
+ /**
525
+ * One private store's files as search results (#1460) — the store's half of
526
+ * an asset search, matched by the SAME rules the shared pool is, so a
527
+ * private file is findable the way a public one is and no filter exists in
528
+ * two places. Merging, sorting and paging are the caller's: it has the other
529
+ * halves.
530
+ */
531
+ searchFilesInStore(location: StoreFileLocation, query: AssetQuery): Promise<AssetRecord[]>;
532
+ /**
533
+ * A store file as the CreativeWork shape the rest of this provider speaks
534
+ * (#1460), so one converter, one filter and one record shape serve both
535
+ * halves of a merged list. `storageLocation` is deliberately absent: where a
536
+ * private file sits on disk is not something a search result carries.
537
+ */
538
+ private storeEntryToSchema;
539
+ /** The free-text and MIME-category rules of an asset search, in one place (#1460). */
540
+ private matchSchemas;
541
+ /**
542
+ * AssetProvider.updateMetadata() — edit an attachment's descriptive metadata (#999).
543
+ *
544
+ * **SIDECAR ONLY. This must never write into the file.**
545
+ *
546
+ * Attachment IDs are CONTENT HASHES — see `calculateHash`, and note the
547
+ * stored filename is `<sha256>.<ext>`. Media items are not content-addressed;
548
+ * attachments are. Writing embedded metadata (EXIF/IPTC/XMP) rewrites the
549
+ * file, so the id and filename stop matching the bytes they name:
550
+ *
551
+ * id c3939c4391744bc8006f726c4e8333...
552
+ * file sha c7ae23c100d515d5... <- after a single metadata write
553
+ *
554
+ * Nothing errors; dedup and any integrity check simply stop being true. An
555
+ * earlier version of this method did exactly that and was backed out
556
+ * (`ffe16c0d`); the failure was only caught because restoring a test file
557
+ * with `cmp` failed on a byte comparison.
558
+ *
559
+ * Operator decision (2026-07-28): sidecar over re-hash-and-re-key. Re-keying
560
+ * would be more honest — the file and its name would stay in agreement — but
561
+ * the id is the URL, so every existing `[{ATTACH}]` reference on every page
562
+ * would break on an edit. Content addressing is worth more than embedded
563
+ * fidelity here.
564
+ *
565
+ * **The consequence, which is real:** an attachment's ngdpbase metadata and
566
+ * its embedded metadata diverge after an edit, and a download carries the
567
+ * file's original values. Media items do not behave this way. If embedded
568
+ * fidelity matters for a given file, it belongs in the media library, which
569
+ * is not content-addressed and does write through.
570
+ *
571
+ * The tag mapping in `utils/assetMetadataTags` is deliberately NOT used here.
572
+ * It is correct, and it is for providers that write to files.
573
+ *
574
+ * @param id - Attachment identifier (content hash)
575
+ * @param patch - Fields to change; `null` clears, omission leaves alone
576
+ * @returns The refreshed record, or null when the attachment is unknown
577
+ * @throws Error when `dateTimeOriginal` is present but unparseable
578
+ */
579
+ updateMetadata(id: string, patch: AssetMetadataPatch): Promise<AssetRecord | null>;
580
+ /**
581
+ * AssetProvider.getById() — returns AssetRecord for the given attachment ID.
582
+ */
583
+ getById(id: string): Promise<AssetRecord | null>;
584
+ /**
585
+ * AssetProvider.store() — routed through the asset-upload door,
586
+ * AttachmentManager.uploadAttachment (#1629), so it gets the same
587
+ * permission check, destination rules and audit record as every upload.
588
+ */
589
+ store(buffer: Buffer, info: AssetInput, ctx: ActorContext): Promise<AssetRecord>;
590
+ /**
591
+ * AssetProvider.delete() — delegates to deleteAttachment().
592
+ */
593
+ delete(id: string): Promise<boolean>;
594
+ /**
595
+ * AssetProvider.stream() — opens a read stream for the attachment file.
596
+ */
597
+ stream(id: string): Promise<NodeJS.ReadableStream | null>;
598
+ }
599
+ export default BasicAttachmentProvider;
@@ -0,0 +1,72 @@
1
+ /**
2
+ * CloudflareAccessAuthProvider — JWT-based trust of Cloudflare Access (#649).
3
+ *
4
+ * Cloudflare Access is a zero-trust gateway: it authenticates users at the
5
+ * edge (against your IdP) and forwards a signed JWT to the origin in the
6
+ * `Cf-Access-Jwt-Assertion` header. This provider verifies that JWT and
7
+ * coordinates the identity to a local User record.
8
+ *
9
+ * Design decisions (per #649 operator-confirmed 2026-05-25):
10
+ * - Q1 — User coordination by **email** (`identity.email` from the JWT).
11
+ * - Q2 — Unknown user → **JIT-provision** with default-role (overridable
12
+ * per CF group via `group-map`).
13
+ * - Q3 — CF `identity.groups[]` → ngdpbase roles via **config-map**.
14
+ *
15
+ * Cloudflare-Access-specific — not a generalised federated-IdP abstraction.
16
+ *
17
+ * Wire-up: this provider is invoked by the request-time middleware in
18
+ * `src/app.ts` (header → verify → JIT-or-lookup → `req.session.username`).
19
+ * It does NOT participate in the explicit /login flow; routes call AuthManager
20
+ * with `providerId='cloudflare-access'` only from the middleware path.
21
+ *
22
+ * Token verification uses `jose.createRemoteJWKSet` against
23
+ * `https://<team-domain>/cdn-cgi/access/certs` — keys are fetched on demand
24
+ * and cached + rotated by jose internally.
25
+ */
26
+ import { type JWTVerifyGetKey } from 'jose';
27
+ import type { WikiEngine } from '../types/WikiEngine.js';
28
+ import type { AuthProvider, AuthVerifyCredentials, AuthResult, FactorDescription } from './BaseAuthProvider.js';
29
+ export interface CloudflareAccessConfig {
30
+ /** Cloudflare team domain, e.g. `mjwilleke.cloudflareaccess.com`. */
31
+ teamDomain: string;
32
+ /** Application AUD tag (one per CF Access Application). */
33
+ applicationAud: string;
34
+ /** Role assigned to JIT-provisioned users when no CF group maps. */
35
+ defaultRole: string;
36
+ /**
37
+ * Map of CF group name → ngdpbase role name. CF groups absent from this
38
+ * map are silently ignored at provisioning time (user still gets defaultRole).
39
+ */
40
+ groupMap: Record<string, string>;
41
+ }
42
+ export declare class CloudflareAccessAuthProvider implements AuthProvider {
43
+ readonly id = "cloudflare-access";
44
+ readonly displayName = "Cloudflare Access";
45
+ /** An identity provider, as Google: AAL1 with no `amr` of its own (#1523). */
46
+ readonly factor: FactorDescription;
47
+ private readonly engine;
48
+ private readonly config;
49
+ private readonly jwks;
50
+ private readonly issuer;
51
+ /**
52
+ * @param jwksOverride optional pre-built JWKS getter for tests; production
53
+ * omits this and uses `createRemoteJWKSet` against the team-domain certs
54
+ * endpoint.
55
+ */
56
+ constructor(engine: WikiEngine, config: CloudflareAccessConfig, jwksOverride?: JWTVerifyGetKey);
57
+ /**
58
+ * Verify the Cloudflare Access JWT and resolve (or provision) the local user.
59
+ * `credentials.token` is the raw JWT lifted from the `Cf-Access-Jwt-Assertion`
60
+ * header by the request-time middleware.
61
+ */
62
+ verify(credentials: AuthVerifyCredentials): Promise<AuthResult | null>;
63
+ private resolveOrProvision;
64
+ /**
65
+ * Map CF identity.groups[] to ngdpbase role names. Groups without an
66
+ * entry in config.groupMap are dropped silently. Result always contains
67
+ * config.defaultRole — even with no group hits, user gets the default.
68
+ */
69
+ private mapGroupsToRoles;
70
+ private findUserByEmail;
71
+ private deriveUniqueUsername;
72
+ }