@jwilleke/ngdpbase-types 0.0.0 → 5.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +16 -2
- package/lib/packages/ngdpbase-types/index.d.ts +32 -0
- package/lib/packages/ngdpbase-types/testing.d.ts +43 -0
- package/lib/packages/ngdpbase-types/testing.js +53 -0
- package/lib/src/cache/CacheDependencies.d.ts +50 -0
- package/lib/src/cache/CacheDependencies.js +50 -0
- package/lib/src/cache/ICacheAdapter.d.ts +86 -0
- package/lib/src/cache/RegionCache.d.ts +171 -0
- package/lib/src/context/ActorContext.d.ts +48 -0
- package/lib/src/context/ActorContext.js +33 -0
- package/lib/src/context/ApiContext.d.ts +194 -0
- package/lib/src/context/ApiContext.js +273 -0
- package/lib/src/context/BaseContext.d.ts +110 -0
- package/lib/src/context/BaseContext.js +143 -0
- package/lib/src/context/JobContext.d.ts +153 -0
- package/lib/src/context/JobContext.js +144 -0
- package/lib/src/context/WikiContext.d.ts +404 -0
- package/lib/src/context/bootActions.d.ts +64 -0
- package/lib/src/context/bootActions.js +111 -0
- package/lib/src/converters/HtmlConverter.d.ts +70 -0
- package/lib/src/converters/IContentConverter.d.ts +94 -0
- package/lib/src/converters/JSPWikiConverter.d.ts +117 -0
- package/lib/src/converters/conversionWarning.d.ts +15 -0
- package/lib/src/converters/ncm/bridge.d.ts +22 -0
- package/lib/src/converters/ncm/existing.d.ts +23 -0
- package/lib/src/converters/ncm/fix/blocks.d.ts +89 -0
- package/lib/src/converters/ncm/fix/bulletMarkers.d.ts +21 -0
- package/lib/src/converters/ncm/fix/index.d.ts +36 -0
- package/lib/src/converters/ncm/fix/jspwikiBullets.d.ts +20 -0
- package/lib/src/converters/ncm/fix/jspwikiCodeMarkers.d.ts +38 -0
- package/lib/src/converters/ncm/fix/jspwikiHeadings.d.ts +25 -0
- package/lib/src/converters/ncm/fix/jspwikiIndent.d.ts +24 -0
- package/lib/src/converters/ncm/fix/jspwikiInsert.d.ts +21 -0
- package/lib/src/converters/ncm/fix/jspwikiItalic.d.ts +29 -0
- package/lib/src/converters/ncm/fix/jspwikiLinkLeftovers.d.ts +27 -0
- package/lib/src/converters/ncm/fix/moreInformationFooter.d.ts +25 -0
- package/lib/src/converters/ncm/fix/styleClosers.d.ts +25 -0
- package/lib/src/converters/ncm/fix/tightenLists.d.ts +30 -0
- package/lib/src/converters/ncm/fix/types.d.ts +33 -0
- package/lib/src/converters/ncm/footnotes.d.ts +39 -0
- package/lib/src/converters/ncm/images.d.ts +49 -0
- package/lib/src/converters/ncm/index.d.ts +20 -0
- package/lib/src/converters/ncm/links.d.ts +21 -0
- package/lib/src/converters/ncm/normalize.d.ts +39 -0
- package/lib/src/converters/ncm/placeholder.d.ts +25 -0
- package/lib/src/converters/ncm/tables.d.ts +36 -0
- package/lib/src/converters/ncm/types.d.ts +42 -0
- package/lib/src/http/egressPolicy.d.ts +52 -0
- package/lib/src/http/guardedFetch.d.ts +89 -0
- package/lib/src/http/guardedFetch.js +113 -0
- package/lib/src/http/guardedLookup.d.ts +48 -0
- package/lib/src/http/guardedLookup.js +73 -0
- package/lib/src/http/ssrf.d.ts +83 -0
- package/lib/src/http/ssrf.js +311 -0
- package/lib/src/mail/MailProvider.d.ts +36 -0
- package/lib/src/mail/NodemailerMailProvider.d.ts +26 -0
- package/lib/src/managers/AddonsManager.d.ts +691 -0
- package/lib/src/managers/AgentTokenManager.d.ts +269 -0
- package/lib/src/managers/AssetManager.d.ts +116 -0
- package/lib/src/managers/AttachmentManager.d.ts +1032 -0
- package/lib/src/managers/AuthManager.d.ts +1257 -0
- package/lib/src/managers/BackgroundJobManager.d.ts +434 -0
- package/lib/src/managers/BaseManager.d.ts +391 -0
- package/lib/src/managers/BaseManager.js +415 -0
- package/lib/src/managers/CacheManager.d.ts +159 -0
- package/lib/src/managers/CatalogManager.d.ts +235 -0
- package/lib/src/managers/CommentManager.d.ts +75 -0
- package/lib/src/managers/ConfigurationManager.d.ts +747 -0
- package/lib/src/managers/DatabaseManager.d.ts +89 -0
- package/lib/src/managers/DatabaseManager.js +236 -0
- package/lib/src/managers/EmailManager.d.ts +47 -0
- package/lib/src/managers/ExportManager.d.ts +129 -0
- package/lib/src/managers/ExportManager.js +420 -0
- package/lib/src/managers/FootnoteManager.d.ts +118 -0
- package/lib/src/managers/MediaManager.d.ts +279 -0
- package/lib/src/managers/MetricsManager.d.ts +89 -0
- package/lib/src/managers/NotificationManager.d.ts +165 -0
- package/lib/src/managers/OidcManager.d.ts +210 -0
- package/lib/src/managers/OrganizationManager.d.ts +107 -0
- package/lib/src/managers/PageManager.d.ts +1645 -0
- package/lib/src/managers/PersonManager.d.ts +48 -0
- package/lib/src/managers/PluginManager.d.ts +179 -0
- package/lib/src/managers/PluginManager.js +393 -0
- package/lib/src/managers/PolicyEvaluator.d.ts +213 -0
- package/lib/src/managers/RenderingManager.d.ts +358 -0
- package/lib/src/managers/RoleManager.d.ts +134 -0
- package/lib/src/managers/SearchManager.d.ts +402 -0
- package/lib/src/managers/ShareManager.d.ts +251 -0
- package/lib/src/managers/TemplateManager.d.ts +176 -0
- package/lib/src/managers/ThemeManager.d.ts +56 -0
- package/lib/src/managers/UserManager.d.ts +480 -0
- package/lib/src/managers/ValidationManager.d.ts +426 -0
- package/lib/src/managers/VariableManager.d.ts +145 -0
- package/lib/src/middleware/csrf.d.ts +3 -0
- package/lib/src/parsers/LinkParser.d.ts +457 -0
- package/lib/src/parsers/MarkupParser.d.ts +769 -0
- package/lib/src/parsers/context/ParseContext.d.ts +314 -0
- package/lib/src/parsers/data/emoji-map.d.ts +18 -0
- package/lib/src/parsers/dom/DOMBuilder.d.ts +210 -0
- package/lib/src/parsers/dom/DOMParser.d.ts +252 -0
- package/lib/src/parsers/dom/Tokenizer.d.ts +358 -0
- package/lib/src/parsers/dom/WikiDocument.d.ts +272 -0
- package/lib/src/parsers/dom/handlers/DOMLinkHandler.d.ts +260 -0
- package/lib/src/parsers/dom/handlers/DOMPluginHandler.d.ts +212 -0
- package/lib/src/parsers/dom/handlers/DOMVariableHandler.d.ts +171 -0
- package/lib/src/parsers/filters/BaseFilter.d.ts +269 -0
- package/lib/src/parsers/filters/FilterChain.d.ts +320 -0
- package/lib/src/parsers/handlers/BaseSyntaxHandler.d.ts +331 -0
- package/lib/src/parsers/handlers/HandlerRegistry.d.ts +225 -0
- package/lib/src/parsers/handlers/JSPWikiPreprocessor.d.ts +89 -0
- package/lib/src/parsers/handlers/LinkParserHandler.d.ts +80 -0
- package/lib/src/parsers/handlers/PluginSyntaxHandler.d.ts +78 -0
- package/lib/src/parsers/handlers/WikiFormHandler.d.ts +149 -0
- package/lib/src/parsers/handlers/WikiTagHandler.d.ts +125 -0
- package/lib/src/parsers/jspwikiTableRow.d.ts +39 -0
- package/lib/src/parsers/styleBlockSyntax.d.ts +14 -0
- package/lib/src/plugins/types.d.ts +79 -0
- package/lib/src/providers/AgentTokenAuthProvider.d.ts +40 -0
- package/lib/src/providers/AuthentikBearerAuthProvider.d.ts +75 -0
- package/lib/src/providers/BaseAttachmentProvider.d.ts +197 -0
- package/lib/src/providers/BaseAuthProvider.d.ts +220 -0
- package/lib/src/providers/BaseCacheProvider.d.ts +140 -0
- package/lib/src/providers/BaseCredentialsProvider.d.ts +84 -0
- package/lib/src/providers/BaseDatabaseProvider.d.ts +22 -0
- package/lib/src/providers/BaseDatabaseProvider.js +12 -0
- package/lib/src/providers/BaseLoggingProvider.d.ts +68 -0
- package/lib/src/providers/BaseLoggingProvider.js +37 -0
- package/lib/src/providers/BaseMediaProvider.d.ts +308 -0
- package/lib/src/providers/BasePageProvider.d.ts +337 -0
- package/lib/src/providers/BaseProvider.d.ts +98 -0
- package/lib/src/providers/BaseProvider.js +74 -0
- package/lib/src/providers/BaseSearchProvider.d.ts +362 -0
- package/lib/src/providers/BasicAttachmentProvider.d.ts +599 -0
- package/lib/src/providers/CloudflareAccessAuthProvider.d.ts +72 -0
- package/lib/src/providers/FileCredentialsProvider.d.ts +33 -0
- package/lib/src/providers/FileJobStateProvider.d.ts +58 -0
- package/lib/src/providers/FileLoggingProvider.d.ts +43 -0
- package/lib/src/providers/FileLoggingProvider.js +120 -0
- package/lib/src/providers/FileOidcAdapter.d.ts +25 -0
- package/lib/src/providers/FileSystemMediaProvider.d.ts +403 -0
- package/lib/src/providers/LunrSearchProvider.d.ts +280 -0
- package/lib/src/providers/MagicLinkAuthProvider.d.ts +125 -0
- package/lib/src/providers/NullCacheProvider.d.ts +72 -0
- package/lib/src/providers/OidcAuthProvider.d.ts +180 -0
- package/lib/src/providers/OidcBearerAuthProvider.d.ts +30 -0
- package/lib/src/providers/PasskeyAuthProvider.d.ts +58 -0
- package/lib/src/providers/PasswordAuthProvider.d.ts +20 -0
- package/lib/src/providers/SqliteDatabaseProvider.d.ts +55 -0
- package/lib/src/providers/SqliteDatabaseProvider.js +90 -0
- package/lib/src/providers/SqliteJobStateProvider.d.ts +41 -0
- package/lib/src/providers/databaseMigrations.d.ts +8 -0
- package/lib/src/providers/databaseMigrations.js +47 -0
- package/lib/src/providers/jobState.d.ts +99 -0
- package/lib/src/providers/lunrQueryToMiniSearch.d.ts +32 -0
- package/lib/src/providers/mediaFilenameDate.d.ts +22 -0
- package/lib/src/providers/sqliteLocation.d.ts +17 -0
- package/lib/src/providers/sqliteLocation.js +55 -0
- package/lib/src/providers/sqliteMigrations.d.ts +48 -0
- package/lib/src/providers/sqliteMigrations.js +72 -0
- package/lib/src/rendering/githubAlerts.d.ts +22 -0
- package/lib/src/rendering/htmlPolicy.d.ts +76 -0
- package/lib/src/rendering/markdownConverter.d.ts +73 -0
- package/lib/src/security/PolicyDecisionPoint.d.ts +245 -0
- package/lib/src/security/PolicyInformationPoint.d.ts +448 -0
- package/lib/src/security/pageActions.d.ts +40 -0
- package/lib/src/security/permissions.generated.d.ts +78 -0
- package/lib/src/types/Asset.d.ts +414 -0
- package/lib/src/types/Catalog.d.ts +61 -0
- package/lib/src/types/Comment.d.ts +11 -0
- package/lib/src/types/Config.d.ts +388 -0
- package/lib/src/types/Organization.d.ts +78 -0
- package/lib/src/types/OrganizationProvider.d.ts +38 -0
- package/lib/src/types/Page.d.ts +220 -0
- package/lib/src/types/Person.d.ts +56 -0
- package/lib/src/types/PersonProvider.d.ts +25 -0
- package/lib/src/types/Policy.d.ts +139 -0
- package/lib/src/types/Policy.js +17 -0
- package/lib/src/types/Provider.d.ts +810 -0
- package/lib/src/types/Role.d.ts +84 -0
- package/lib/src/types/RoleProvider.d.ts +35 -0
- package/lib/src/types/Schema.d.ts +425 -0
- package/lib/src/types/Share.d.ts +172 -0
- package/lib/src/types/Share.js +81 -0
- package/lib/src/types/User.d.ts +304 -0
- package/lib/src/types/Version.d.ts +189 -0
- package/lib/src/types/WikiEngine.d.ts +128 -0
- package/lib/src/types/express.d.ts +120 -0
- package/lib/src/types/express.js +1 -0
- package/lib/src/types/guards.d.ts +78 -0
- package/lib/src/types/heic-decode.d.ts +16 -0
- package/lib/src/types/index.d.ts +19 -0
- package/lib/src/types/linkedom.d.ts +77 -0
- package/lib/src/types/markdown-it-plugins.d.ts +21 -0
- package/lib/src/utils/DeltaStorage.d.ts +118 -0
- package/lib/src/utils/LocaleUtils.d.ts +105 -0
- package/lib/src/utils/LocaleUtils.js +294 -0
- package/lib/src/utils/PageNameMatcher.d.ts +98 -0
- package/lib/src/utils/PathPreflight.d.ts +38 -0
- package/lib/src/utils/PathPreflight.js +50 -0
- package/lib/src/utils/SectionUtils.d.ts +40 -0
- package/lib/src/utils/addonConfigLayer.d.ts +144 -0
- package/lib/src/utils/addonConfigLayer.js +382 -0
- package/lib/src/utils/addonDatabaseRules.d.ts +25 -0
- package/lib/src/utils/addonDatabaseRules.js +57 -0
- package/lib/src/utils/addonHost.d.ts +51 -0
- package/lib/src/utils/addonHost.js +72 -0
- package/lib/src/utils/addonInstaller.d.ts +109 -0
- package/lib/src/utils/addonLock.d.ts +37 -0
- package/lib/src/utils/addonLock.js +48 -0
- package/lib/src/utils/addonPageSync.d.ts +45 -0
- package/lib/src/utils/addonProvenance.d.ts +48 -0
- package/lib/src/utils/addonTarball.d.ts +41 -0
- package/lib/src/utils/addonsPathResolver.d.ts +76 -0
- package/lib/src/utils/addonsPathResolver.js +129 -0
- package/lib/src/utils/assetMetadataTags.d.ts +66 -0
- package/lib/src/utils/atomicWrite.d.ts +28 -0
- package/lib/src/utils/auditConfigChange.d.ts +57 -0
- package/lib/src/utils/auditEventNames.d.ts +50 -0
- package/lib/src/utils/auditEventNames.generated.d.ts +163 -0
- package/lib/src/utils/auditEventNames.generated.js +168 -0
- package/lib/src/utils/auditEventNames.js +49 -0
- package/lib/src/utils/auditEvents.d.ts +265 -0
- package/lib/src/utils/auditEvents.js +309 -0
- package/lib/src/utils/auditRegistry.d.ts +102 -0
- package/lib/src/utils/auditRegistry.js +168 -0
- package/lib/src/utils/bip39English.d.ts +2 -0
- package/lib/src/utils/configEnvKeys.d.ts +68 -0
- package/lib/src/utils/configFiles.d.ts +74 -0
- package/lib/src/utils/configFiles.js +150 -0
- package/lib/src/utils/delegation.d.ts +48 -0
- package/lib/src/utils/deriveUsername.d.ts +21 -0
- package/lib/src/utils/explainMediaPath.d.ts +123 -0
- package/lib/src/utils/formerTitles.d.ts +69 -0
- package/lib/src/utils/frontmatterAccess.d.ts +54 -0
- package/lib/src/utils/headlessAdminPassword.d.ts +55 -0
- package/lib/src/utils/imageTransform.d.ts +52 -0
- package/lib/src/utils/instanceEnvSecret.d.ts +51 -0
- package/lib/src/utils/jobSlots.d.ts +43 -0
- package/lib/src/utils/keywordNormalizer.d.ts +127 -0
- package/lib/src/utils/logger.d.ts +70 -0
- package/lib/src/utils/logger.js +106 -0
- package/lib/src/utils/magicLinkDeviceState.d.ts +95 -0
- package/lib/src/utils/managerUtils.d.ts +40 -0
- package/lib/src/utils/migrateLegacyPrivateAttachments.d.ts +15 -0
- package/lib/src/utils/orgFilename.d.ts +22 -0
- package/lib/src/utils/pageFeature.d.ts +27 -0
- package/lib/src/utils/pageFrontmatter.d.ts +21 -0
- package/lib/src/utils/pageNotes.d.ts +150 -0
- package/lib/src/utils/pageTitleRule.d.ts +37 -0
- package/lib/src/utils/pageToArticle.d.ts +59 -0
- package/lib/src/utils/pageUrl.d.ts +18 -0
- package/lib/src/utils/passwordChange.d.ts +12 -0
- package/lib/src/utils/passwordHash.d.ts +60 -0
- package/lib/src/utils/permissionCatalog.d.ts +52 -0
- package/lib/src/utils/pluginFormatters.d.ts +452 -0
- package/lib/src/utils/pluginFormatters.js +714 -0
- package/lib/src/utils/privateLinkRewrite.d.ts +42 -0
- package/lib/src/utils/privateStoreAccess.d.ts +57 -0
- package/lib/src/utils/privateStoreAccess.js +65 -0
- package/lib/src/utils/privateStoreCatalogs.d.ts +40 -0
- package/lib/src/utils/privateStoreCrypto.d.ts +127 -0
- package/lib/src/utils/privateStoreDoor.d.ts +181 -0
- package/lib/src/utils/privateStoreExport.d.ts +72 -0
- package/lib/src/utils/privateStoreFiles.d.ts +120 -0
- package/lib/src/utils/privateStoreMeta.d.ts +64 -0
- package/lib/src/utils/privateStoreMigrations.d.ts +37 -0
- package/lib/src/utils/privateStorePath.d.ts +259 -0
- package/lib/src/utils/privateStorePath.js +436 -0
- package/lib/src/utils/privateStoreTakeout.d.ts +76 -0
- package/lib/src/utils/privateStoreUnlock.d.ts +175 -0
- package/lib/src/utils/proxyClaim.d.ts +59 -0
- package/lib/src/utils/proxyClaim.js +30 -0
- package/lib/src/utils/redactPrivateNames.d.ts +21 -0
- package/lib/src/utils/redactPrivateNames.js +89 -0
- package/lib/src/utils/redactSecrets.d.ts +58 -0
- package/lib/src/utils/redactSecrets.js +171 -0
- package/lib/src/utils/renameLinkRewrite.d.ts +112 -0
- package/lib/src/utils/roleGrants.d.ts +35 -0
- package/lib/src/utils/safeRedirect.d.ts +32 -0
- package/lib/src/utils/schedule.d.ts +54 -0
- package/lib/src/utils/secretFileMode.d.ts +17 -0
- package/lib/src/utils/seededShippedPages.d.ts +45 -0
- package/lib/src/utils/sensitiveValues.d.ts +59 -0
- package/lib/src/utils/sensitiveValues.js +106 -0
- package/lib/src/utils/sessionEnd.d.ts +12 -0
- package/lib/src/utils/sessionGeneration.d.ts +24 -0
- package/lib/src/utils/sessionIdle.d.ts +41 -0
- package/lib/src/utils/sessionLimits.d.ts +68 -0
- package/lib/src/utils/shareLockbox.d.ts +64 -0
- package/lib/src/utils/sigstoreTrustedRoot.d.ts +33 -0
- package/lib/src/utils/sniffMime.d.ts +21 -0
- package/lib/src/utils/storeSearchIndex.d.ts +75 -0
- package/lib/src/utils/subjectMayDo.d.ts +21 -0
- package/lib/src/utils/systemCategoryRules.d.ts +30 -0
- package/lib/src/utils/systemCategoryRules.js +41 -0
- package/lib/src/utils/userCreateError.d.ts +62 -0
- package/lib/src/utils/username.d.ts +53 -0
- package/lib/src/utils/vaultUrlRewrite.d.ts +27 -0
- package/lib/src/utils/version.d.ts +84 -0
- package/lib/src/utils/videoFrame.d.ts +21 -0
- package/package.json +54 -3
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A secret that must be defined in the instance `.env`, generated once when
|
|
3
|
+
* nothing supplies it (#1194, generalised for #1524).
|
|
4
|
+
*
|
|
5
|
+
* The session secret was the first; the credentials-store key is the second.
|
|
6
|
+
* Both follow one rule, so it is written once:
|
|
7
|
+
*
|
|
8
|
+
* 1. Set in the environment — use it, write nothing.
|
|
9
|
+
* 2. Blank in the environment, but the instance `.env` has a usable line — use
|
|
10
|
+
* that (a launcher passing `NAME=` empty would otherwise regenerate on every
|
|
11
|
+
* boot).
|
|
12
|
+
* 3. Otherwise generate, append one commented line to `<instanceDataDir>/.env`
|
|
13
|
+
* (created `0600` when new), and use it.
|
|
14
|
+
*
|
|
15
|
+
* The repo-root `.env` is never written: it is shared by every instance that
|
|
16
|
+
* launches from the checkout.
|
|
17
|
+
*/
|
|
18
|
+
/** Filesystem seams, injected so the backfill is testable in a scratch dir. */
|
|
19
|
+
export interface InstanceEnvFs {
|
|
20
|
+
readFile: (path: string) => string | null;
|
|
21
|
+
appendFile: (path: string, line: string, createMode: number) => void;
|
|
22
|
+
randomSecret: () => string;
|
|
23
|
+
}
|
|
24
|
+
/** Where the value the process is using came from. */
|
|
25
|
+
export type InstanceEnvSecretOrigin = {
|
|
26
|
+
kind: 'env';
|
|
27
|
+
} | {
|
|
28
|
+
kind: 'instance-env-file';
|
|
29
|
+
path: string;
|
|
30
|
+
} | {
|
|
31
|
+
kind: 'generated';
|
|
32
|
+
path: string;
|
|
33
|
+
};
|
|
34
|
+
export interface InstanceEnvSecretSpec {
|
|
35
|
+
/** The variable, e.g. `NGDPBASE_SESSION_SECRET`. */
|
|
36
|
+
name: string;
|
|
37
|
+
/** The comment line written above a generated value (without `# `). */
|
|
38
|
+
comment: string;
|
|
39
|
+
/** Checks a found value and returns it, or throws (a placeholder, say). */
|
|
40
|
+
accept?: (value: string) => string;
|
|
41
|
+
/** The error thrown when the generated line cannot be written. */
|
|
42
|
+
refusal: (envPath: string, cause: Error) => Error;
|
|
43
|
+
}
|
|
44
|
+
export declare function ensureInstanceEnvSecret(spec: InstanceEnvSecretSpec, env: Readonly<Record<string, string | undefined>>, instanceDataDir: string, fs: InstanceEnvFs): {
|
|
45
|
+
secret: string;
|
|
46
|
+
origin: InstanceEnvSecretOrigin;
|
|
47
|
+
};
|
|
48
|
+
/** The last `NAME=` line in a dotenv file, unquoted; null when absent or blank. */
|
|
49
|
+
export declare function readEnvLine(content: string, name: string): string | null;
|
|
50
|
+
/** The real filesystem behind every generated `.env` secret. */
|
|
51
|
+
export declare const nodeInstanceEnvFs: InstanceEnvFs;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which due slots of a scheduled job run, and which are skipped (#1715, epic
|
|
3
|
+
* #1611). Pure: the scheduler in `BackgroundJobManager` hands it the slots
|
|
4
|
+
* that are due and when the job was last busy, and records what it returns.
|
|
5
|
+
*
|
|
6
|
+
* A slot is due when its time has come and it has not been handled. Due slots
|
|
7
|
+
* come in two kinds, and each has its own rule:
|
|
8
|
+
*
|
|
9
|
+
* - **came due while the job was running** (before `busyUntil`): the job's
|
|
10
|
+
* `overlap` rule. `queue` keeps one waiting slot, the newest; `skip` keeps
|
|
11
|
+
* none. One job never runs twice at once.
|
|
12
|
+
* - **came due while the job was idle, or the server was down**: the job's
|
|
13
|
+
* `catchUp` rule. A slot that came due within `onTimeMs` is on time, not
|
|
14
|
+
* missed: `none` runs only on-time slots, `latest` runs the newest due slot,
|
|
15
|
+
* `all` runs the newest {@link CATCH_UP_ALL_CAP}, oldest first.
|
|
16
|
+
*
|
|
17
|
+
* Every due slot not run is skipped, so the caller records it: a slot is
|
|
18
|
+
* never dropped without a trace (operator, 2026-10-08).
|
|
19
|
+
*
|
|
20
|
+
* @module utils/jobSlots
|
|
21
|
+
*/
|
|
22
|
+
export type CatchUp = 'none' | 'latest' | 'all';
|
|
23
|
+
export type Overlap = 'queue' | 'skip';
|
|
24
|
+
/** `catchUp: 'all'` runs at most this many missed slots; older ones are skipped. */
|
|
25
|
+
export declare const CATCH_UP_ALL_CAP = 12;
|
|
26
|
+
export interface SlotSelectionInput {
|
|
27
|
+
/** The due slots, oldest first. */
|
|
28
|
+
due: Date[];
|
|
29
|
+
now: Date;
|
|
30
|
+
/** When this job's last run in this process ended; null when it has not run since start. */
|
|
31
|
+
busyUntil: Date | null;
|
|
32
|
+
/** A slot that came due at most this long ago is on time, not missed. */
|
|
33
|
+
onTimeMs: number;
|
|
34
|
+
catchUp: CatchUp;
|
|
35
|
+
overlap: Overlap;
|
|
36
|
+
}
|
|
37
|
+
export interface SlotSelection {
|
|
38
|
+
/** Slots to run, oldest first, one at a time. */
|
|
39
|
+
run: Date[];
|
|
40
|
+
/** Slots passed over, oldest first. */
|
|
41
|
+
skip: Date[];
|
|
42
|
+
}
|
|
43
|
+
export declare function selectSlots(input: SlotSelectionInput): SlotSelection;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keyword normalizer (#869) — the title↔value canonical form for the unified
|
|
3
|
+
* keyword vocabulary.
|
|
4
|
+
*
|
|
5
|
+
* Per the epic's design principle #2, every keyword is `{ value, title }`:
|
|
6
|
+
* - `title` (CatalogTerm.label) — display form, kept verbatim, written to files.
|
|
7
|
+
* - `value` (CatalogTerm.term) — ngdpbase-internal canonical form: lowercase,
|
|
8
|
+
* spaces/punctuation → single hyphens, diacritics transliterated, ≤ 64 chars
|
|
9
|
+
* (IPTC IIM 2:25 limit), comma-free (comma is a list delimiter in many tools).
|
|
10
|
+
*
|
|
11
|
+
* `value` is what the media index, search, page metadata and URLs key on, so two
|
|
12
|
+
* titles that differ only by case/spacing/accent collapse to ONE value — the
|
|
13
|
+
* mechanism that makes `Dining` and `dining` impossible to hold as distinct
|
|
14
|
+
* keywords. This module is pure (no I/O); enforcement (routing all keyword input
|
|
15
|
+
* through it) is wired by its consumers.
|
|
16
|
+
*
|
|
17
|
+
* Differs deliberately from `simpleSlug` (pluginFormatters): that DROPS accented
|
|
18
|
+
* characters (`José` → `jos`), which would silently corrupt personal-name
|
|
19
|
+
* keywords; this TRANSLITERATES them (`José` → `jose`) and enforces the length
|
|
20
|
+
* cap.
|
|
21
|
+
*/
|
|
22
|
+
/** Max length of a keyword value (IPTC IIM 2:25 keyword field limit). */
|
|
23
|
+
export declare const KEYWORD_VALUE_MAX = 64;
|
|
24
|
+
/**
|
|
25
|
+
* Canonical value for a keyword title. Idempotent: `normalizeKeywordValue(v)`
|
|
26
|
+
* equals `v` for any already-valid value. Returns '' when the title has no
|
|
27
|
+
* usable alphanumeric content.
|
|
28
|
+
*/
|
|
29
|
+
export declare function normalizeKeywordValue(title: string): string;
|
|
30
|
+
/**
|
|
31
|
+
* True when `value` is already a canonical keyword value: non-empty, ≤ 64 chars,
|
|
32
|
+
* comma-free, lowercase alphanumeric segments joined by single hyphens.
|
|
33
|
+
*/
|
|
34
|
+
export declare function isValidKeywordValue(value: string): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* True when two titles normalize to the same (non-empty) value — i.e. they are
|
|
37
|
+
* case/space/accent variants of one keyword.
|
|
38
|
+
*/
|
|
39
|
+
export declare function keywordsCollide(a: string, b: string): boolean;
|
|
40
|
+
/** Build a `{ term, label }` pair (CatalogTerm shape) from a display title. */
|
|
41
|
+
export declare function toKeywordTerm(title: string): {
|
|
42
|
+
term: string;
|
|
43
|
+
label: string;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Parse hierarchical tag values (#917) into `/`-joined canonical-value paths.
|
|
47
|
+
* digiKam/Lightroom store the tag tree two ways; both are unioned + deduped:
|
|
48
|
+
* - `XMP-lr:HierarchicalSubject` — `|`-separated (`Places|USA|Colorado|Denver`)
|
|
49
|
+
* - `XMP-digiKam:TagsList` — `/`-separated (`Places/USA/Colorado/Denver`)
|
|
50
|
+
* Each segment is run through `normalizeKeywordValue`, so a path becomes
|
|
51
|
+
* `places/usa/colorado/denver` (leaf = last segment). Empty segments are
|
|
52
|
+
* dropped; a value that is a scalar string is treated as a single-entry list.
|
|
53
|
+
*/
|
|
54
|
+
export declare function parseHierarchicalTags(hierarchicalSubject: unknown, tagsList: unknown): string[];
|
|
55
|
+
/**
|
|
56
|
+
* Reconcile a file's hierarchical tag tree against an edited flat keyword list
|
|
57
|
+
* (#918). Preserves the operator's digiKam hierarchy through an ngdpbase edit —
|
|
58
|
+
* paths are kept in their original DISPLAY form (never rewritten to slugs, which
|
|
59
|
+
* would corrupt the tree on re-read).
|
|
60
|
+
*
|
|
61
|
+
* Rules (only when the file already carries hierarchy — a flat-only file gets
|
|
62
|
+
* `null`, i.e. leave it flat):
|
|
63
|
+
* - a KEPT keyword keeps its existing path (`~WHO/Crotty/Lyman …` stays);
|
|
64
|
+
* - a REMOVED keyword's path is dropped;
|
|
65
|
+
* - `auto/*` machine-tag paths are always preserved untouched (principle #5);
|
|
66
|
+
* - a NEW keyword lands at the ROOT as a single-segment path in its display
|
|
67
|
+
* form. (Cross-library placement at a known leaf path — via #917's leaf map
|
|
68
|
+
* in display form — is a later refinement; root is the safe default.)
|
|
69
|
+
*
|
|
70
|
+
* `hierarchicalSubject`/`tagsList` are the file's current raw tag values (string
|
|
71
|
+
* or string[]). Returns the new values for BOTH encodings, or null to leave the
|
|
72
|
+
* file's hierarchy untouched.
|
|
73
|
+
*/
|
|
74
|
+
export declare function reconcileHierarchicalTags(keywords: readonly string[], hierarchicalSubject: unknown, tagsList: unknown): {
|
|
75
|
+
hierarchicalSubject: string[];
|
|
76
|
+
tagsList: string[];
|
|
77
|
+
} | null;
|
|
78
|
+
/**
|
|
79
|
+
* Build a leaf→path map from many hierarchical paths (#917) — the library-wide
|
|
80
|
+
* "where does this leaf keyword live" lookup #918 uses to place a newly-added
|
|
81
|
+
* keyword at its known hierarchical home. Leaf = last path segment; on conflict
|
|
82
|
+
* the most frequently-seen path wins (ties broken by longest, then first).
|
|
83
|
+
*/
|
|
84
|
+
export declare function buildLeafPathMap(paths: Iterable<string>): Map<string, string>;
|
|
85
|
+
/** One keyword display form seen somewhere, with where it was seen (#919). */
|
|
86
|
+
export interface KeywordFormStat {
|
|
87
|
+
form: string;
|
|
88
|
+
pageCount?: number;
|
|
89
|
+
mediaCount?: number;
|
|
90
|
+
catalogued?: boolean;
|
|
91
|
+
catalogId?: string;
|
|
92
|
+
}
|
|
93
|
+
/** A cluster of display forms that share one canonical value (#919). */
|
|
94
|
+
export interface KeywordVariantGroup {
|
|
95
|
+
value: string;
|
|
96
|
+
canonicalForm: string;
|
|
97
|
+
canonicalId?: string;
|
|
98
|
+
forms: Array<{
|
|
99
|
+
form: string;
|
|
100
|
+
pageCount: number;
|
|
101
|
+
mediaCount: number;
|
|
102
|
+
catalogued: boolean;
|
|
103
|
+
catalogId?: string;
|
|
104
|
+
}>;
|
|
105
|
+
total: number;
|
|
106
|
+
mergeable: boolean;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Group keyword display forms into variant clusters (#919, #869 Slice 4).
|
|
110
|
+
* Forms are deduped by exact string (summing counts), grouped by
|
|
111
|
+
* `normalizeKeywordValue` (folds case/space/accent/punctuation — stronger than
|
|
112
|
+
* a lowercase match), and only values carried by **2+ distinct forms** are
|
|
113
|
+
* returned. Canonical form = the catalogued form if any, else the most-used.
|
|
114
|
+
* `mergeable` is true when the canonical and at least one other form are both
|
|
115
|
+
* catalog terms (the page-retag merge keys on catalog ids). Pure.
|
|
116
|
+
*/
|
|
117
|
+
export declare function groupKeywordVariants(forms: readonly KeywordFormStat[]): KeywordVariantGroup[];
|
|
118
|
+
/**
|
|
119
|
+
* Collapse a keyword list to one entry per canonical value (#869 dedup
|
|
120
|
+
* enforcement): case/space/accent variants of the same keyword are merged,
|
|
121
|
+
* first occurrence wins ordering, empties dropped. When `canonicalByValue`
|
|
122
|
+
* (value → registry title) is supplied, a kept keyword is snapped to the
|
|
123
|
+
* registry's display title so `dining` converges on catalogued `Dining`;
|
|
124
|
+
* otherwise the first-seen form is kept trimmed. Pure — the registry lookup
|
|
125
|
+
* is passed in, not fetched here.
|
|
126
|
+
*/
|
|
127
|
+
export declare function dedupeKeywords(keywords: readonly string[], canonicalByValue?: ReadonlyMap<string, string>): string[];
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple logging framework using winston
|
|
3
|
+
*
|
|
4
|
+
* Provides centralized logging for the entire ngdpbase application with
|
|
5
|
+
* file rotation, console output, and configurable log levels.
|
|
6
|
+
*
|
|
7
|
+
* Issue #169: transport + format construction is delegated to a
|
|
8
|
+
* {@link BaseLoggingProvider} (default {@link FileLoggingProvider}) so the
|
|
9
|
+
* storage backend is swappable. The exported `logger` API is unchanged —
|
|
10
|
+
* call sites need no edits. The provider is deliberately engine-free: the
|
|
11
|
+
* logger bootstraps before WikiEngine/ConfigurationManager exist and is
|
|
12
|
+
* imported by nearly every module, so provider *selection* happens later in
|
|
13
|
+
* `WikiEngine.initialize()` via {@link setLoggingProvider}.
|
|
14
|
+
*
|
|
15
|
+
* @module logger
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* import logger from './utils/logger';
|
|
19
|
+
* logger.info('Application started');
|
|
20
|
+
* logger.error('Error occurred', { error });
|
|
21
|
+
*/
|
|
22
|
+
import { Logger } from 'winston';
|
|
23
|
+
import BaseLoggingProvider from '../providers/BaseLoggingProvider.js';
|
|
24
|
+
/**
|
|
25
|
+
* Logger configuration options
|
|
26
|
+
*/
|
|
27
|
+
export interface LoggerConfig {
|
|
28
|
+
/** Log level (error, warn, info, debug) */
|
|
29
|
+
level?: string;
|
|
30
|
+
/** Log directory path */
|
|
31
|
+
dir?: string;
|
|
32
|
+
/** Max log file size in bytes or string format (e.g., '1MB') */
|
|
33
|
+
maxSize?: number | string;
|
|
34
|
+
/** Max number of rotated log files */
|
|
35
|
+
maxFiles?: number;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Resolve a provider name (e.g. `'fileloggingprovider'`) to an instance.
|
|
39
|
+
* Unknown names fall back to FileLoggingProvider — logging must never fail
|
|
40
|
+
* to initialize because of a misconfigured provider key.
|
|
41
|
+
*
|
|
42
|
+
* @param name - Lowercase provider name from `ngdpbase.logging.provider`
|
|
43
|
+
* @returns A logging provider instance
|
|
44
|
+
*/
|
|
45
|
+
export declare function resolveLoggingProvider(name: string | undefined): BaseLoggingProvider;
|
|
46
|
+
/**
|
|
47
|
+
* Set the active logging provider. Called by WikiEngine after
|
|
48
|
+
* ConfigurationManager resolves `ngdpbase.logging.provider`. Does not rebuild
|
|
49
|
+
* the running logger on its own — {@link reconfigureLogger} does that.
|
|
50
|
+
*
|
|
51
|
+
* @param provider - The provider instance to activate
|
|
52
|
+
*/
|
|
53
|
+
export declare function setLoggingProvider(provider: BaseLoggingProvider): void;
|
|
54
|
+
/**
|
|
55
|
+
* Creates a winston logger instance with the specified configuration.
|
|
56
|
+
* Transports and format are produced by the active logging provider.
|
|
57
|
+
*
|
|
58
|
+
* @param config - Logger configuration
|
|
59
|
+
* @returns Winston logger instance
|
|
60
|
+
*/
|
|
61
|
+
export declare function createLoggerWithConfig(config?: LoggerConfig): Logger;
|
|
62
|
+
/**
|
|
63
|
+
* Reconfigures the global logger instance with new settings
|
|
64
|
+
*
|
|
65
|
+
* @param config - New logger configuration
|
|
66
|
+
* @returns Updated logger instance
|
|
67
|
+
*/
|
|
68
|
+
export declare function reconfigureLogger(config: LoggerConfig): Logger;
|
|
69
|
+
declare const loggerInstance: Logger;
|
|
70
|
+
export default loggerInstance;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple logging framework using winston
|
|
3
|
+
*
|
|
4
|
+
* Provides centralized logging for the entire ngdpbase application with
|
|
5
|
+
* file rotation, console output, and configurable log levels.
|
|
6
|
+
*
|
|
7
|
+
* Issue #169: transport + format construction is delegated to a
|
|
8
|
+
* {@link BaseLoggingProvider} (default {@link FileLoggingProvider}) so the
|
|
9
|
+
* storage backend is swappable. The exported `logger` API is unchanged —
|
|
10
|
+
* call sites need no edits. The provider is deliberately engine-free: the
|
|
11
|
+
* logger bootstraps before WikiEngine/ConfigurationManager exist and is
|
|
12
|
+
* imported by nearly every module, so provider *selection* happens later in
|
|
13
|
+
* `WikiEngine.initialize()` via {@link setLoggingProvider}.
|
|
14
|
+
*
|
|
15
|
+
* @module logger
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* import logger from './utils/logger';
|
|
19
|
+
* logger.info('Application started');
|
|
20
|
+
* logger.error('Error occurred', { error });
|
|
21
|
+
*/
|
|
22
|
+
import { createLogger } from 'winston';
|
|
23
|
+
import FileLoggingProvider from '../providers/FileLoggingProvider.js';
|
|
24
|
+
// Default config (can be overridden)
|
|
25
|
+
// Note: File transport is only added when 'dir' is explicitly provided
|
|
26
|
+
// (e.g., during reconfiguration from WikiEngine after ConfigurationManager resolves paths)
|
|
27
|
+
const defaultConfig = {
|
|
28
|
+
level: 'info',
|
|
29
|
+
maxSize: 1048576, // 1MB
|
|
30
|
+
maxFiles: 5
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* The active logging provider. Defaults to FileLoggingProvider (the pre-#169
|
|
34
|
+
* behaviour). Swapped via {@link setLoggingProvider} once config is resolved.
|
|
35
|
+
*/
|
|
36
|
+
let activeProvider = new FileLoggingProvider();
|
|
37
|
+
/**
|
|
38
|
+
* Resolve a provider name (e.g. `'fileloggingprovider'`) to an instance.
|
|
39
|
+
* Unknown names fall back to FileLoggingProvider — logging must never fail
|
|
40
|
+
* to initialize because of a misconfigured provider key.
|
|
41
|
+
*
|
|
42
|
+
* @param name - Lowercase provider name from `ngdpbase.logging.provider`
|
|
43
|
+
* @returns A logging provider instance
|
|
44
|
+
*/
|
|
45
|
+
export function resolveLoggingProvider(name) {
|
|
46
|
+
switch ((name ?? '').toLowerCase()) {
|
|
47
|
+
case 'fileloggingprovider':
|
|
48
|
+
case '':
|
|
49
|
+
return new FileLoggingProvider();
|
|
50
|
+
default:
|
|
51
|
+
// No logger guarantees available here yet; fall back silently to the
|
|
52
|
+
// default rather than throwing during bootstrap.
|
|
53
|
+
return new FileLoggingProvider();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Set the active logging provider. Called by WikiEngine after
|
|
58
|
+
* ConfigurationManager resolves `ngdpbase.logging.provider`. Does not rebuild
|
|
59
|
+
* the running logger on its own — {@link reconfigureLogger} does that.
|
|
60
|
+
*
|
|
61
|
+
* @param provider - The provider instance to activate
|
|
62
|
+
*/
|
|
63
|
+
export function setLoggingProvider(provider) {
|
|
64
|
+
activeProvider = provider;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Creates a winston logger instance with the specified configuration.
|
|
68
|
+
* Transports and format are produced by the active logging provider.
|
|
69
|
+
*
|
|
70
|
+
* @param config - Logger configuration
|
|
71
|
+
* @returns Winston logger instance
|
|
72
|
+
*/
|
|
73
|
+
export function createLoggerWithConfig(config = {}) {
|
|
74
|
+
const logConfig = { ...defaultConfig, ...config };
|
|
75
|
+
return createLogger({
|
|
76
|
+
level: logConfig.level,
|
|
77
|
+
format: activeProvider.createFormat(),
|
|
78
|
+
transports: activeProvider.createTransports(logConfig)
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Reconfigures the global logger instance with new settings
|
|
83
|
+
*
|
|
84
|
+
* @param config - New logger configuration
|
|
85
|
+
* @returns Updated logger instance
|
|
86
|
+
*/
|
|
87
|
+
export function reconfigureLogger(config) {
|
|
88
|
+
if (!loggerInstance) {
|
|
89
|
+
throw new Error('Logger instance not initialized');
|
|
90
|
+
}
|
|
91
|
+
const currentLogger = loggerInstance; // Capture for closure
|
|
92
|
+
const newLogger = createLoggerWithConfig(config);
|
|
93
|
+
// Clear existing transports
|
|
94
|
+
currentLogger.clear();
|
|
95
|
+
// Add new transports from the reconfigured logger
|
|
96
|
+
newLogger.transports.forEach(transport => {
|
|
97
|
+
currentLogger.add(transport);
|
|
98
|
+
});
|
|
99
|
+
// Update logger level
|
|
100
|
+
currentLogger.level = newLogger.level;
|
|
101
|
+
return currentLogger;
|
|
102
|
+
}
|
|
103
|
+
// Create default logger instance - always initialized before export
|
|
104
|
+
const loggerInstance = createLoggerWithConfig();
|
|
105
|
+
// Export the logger instance as default
|
|
106
|
+
export default loggerInstance;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Magic-link device binding (#1022).
|
|
3
|
+
*
|
|
4
|
+
* A magic link is bearer-only: whoever holds the URL can sign in. A forwarded
|
|
5
|
+
* email, a link pasted into a chat, or a mailbox a second person can read is a
|
|
6
|
+
* complete account takeover — no second factor, and nothing in the log saying
|
|
7
|
+
* the redemption came from somewhere unexpected.
|
|
8
|
+
*
|
|
9
|
+
* The mitigation is to remember which browser asked for the link (an opaque
|
|
10
|
+
* value in an HTTP-only cookie, stored alongside the token) and check it at
|
|
11
|
+
* redemption.
|
|
12
|
+
*
|
|
13
|
+
* ## Why this is two features, not one
|
|
14
|
+
*
|
|
15
|
+
* Strict binding breaks the most common real flow: request the link on a
|
|
16
|
+
* laptop, open the mail on a phone. That is not an edge case, and silently
|
|
17
|
+
* breaking it would be worse than the risk being mitigated. So:
|
|
18
|
+
*
|
|
19
|
+
* - **Observability is always on.** Every redemption records whether the
|
|
20
|
+
* browser matched, plus IP and User-Agent, through `AuditManager` so it is
|
|
21
|
+
* queryable rather than buried in the app log. Costs nothing in UX.
|
|
22
|
+
* - **Enforcement is opt-in**, behind
|
|
23
|
+
* `ngdpbase.auth.magic-link.bind-to-requesting-device` (default `false`).
|
|
24
|
+
*
|
|
25
|
+
* ## The direction that must not be got wrong
|
|
26
|
+
*
|
|
27
|
+
* An absent cookie is `absent`, never `match`. A forwarded link arrives with no
|
|
28
|
+
* cookie at all, so treating "no cookie" as a pass would make the enforcement
|
|
29
|
+
* setting do nothing against the exact attacker it exists to stop.
|
|
30
|
+
*
|
|
31
|
+
* A token carrying no stored state is a separate case (`unknown`) and is always
|
|
32
|
+
* allowed: tokens live in memory for ~15 minutes, so on the deploy that ships
|
|
33
|
+
* this there are live tokens issued before the feature existed. Refusing those
|
|
34
|
+
* would sign people out mid-flow for no security gain.
|
|
35
|
+
*/
|
|
36
|
+
/** Cookie carrying the opaque per-request state value. */
|
|
37
|
+
export declare const DEVICE_STATE_COOKIE = "ngdp_ml_state";
|
|
38
|
+
/**
|
|
39
|
+
* The same binding for an OAuth sign-in (#1630): the browser that started the
|
|
40
|
+
* flow is the one the callback must come back to. Its own cookie, so a
|
|
41
|
+
* magic-link request and a Google sign-in in flight together do not overwrite
|
|
42
|
+
* each other. Unlike the magic link there is no cross-device flow here — the
|
|
43
|
+
* provider redirects the same browser back — so it is always enforced.
|
|
44
|
+
*/
|
|
45
|
+
export declare const OAUTH_STATE_COOKIE = "ngdp_oauth_state";
|
|
46
|
+
export type DeviceBindingOutcome =
|
|
47
|
+
/** Cookie present and equal to the value stored with the token. */
|
|
48
|
+
'match'
|
|
49
|
+
/** Cookie present but different — a different browser is redeeming. */
|
|
50
|
+
| 'mismatch'
|
|
51
|
+
/** No cookie presented. The cross-device flow, and also the forwarded-link attack. */
|
|
52
|
+
| 'absent'
|
|
53
|
+
/** Token predates this feature, or was issued without state. Not evidence either way. */
|
|
54
|
+
| 'unknown';
|
|
55
|
+
export interface DeviceBindingResult {
|
|
56
|
+
outcome: DeviceBindingOutcome;
|
|
57
|
+
/** Whether the sign-in may proceed, given the enforcement setting. */
|
|
58
|
+
allowed: boolean;
|
|
59
|
+
}
|
|
60
|
+
export interface DeviceBindingInput {
|
|
61
|
+
/** State stored with the token when the link was requested. */
|
|
62
|
+
stored: string | null | undefined;
|
|
63
|
+
/** State presented by the redeeming browser's cookie. */
|
|
64
|
+
presented: string | null | undefined;
|
|
65
|
+
/** Whether `bind-to-requesting-device` is enabled. */
|
|
66
|
+
enforce: boolean;
|
|
67
|
+
}
|
|
68
|
+
/** A fresh opaque state value. 32 bytes of CSPRNG, hex-encoded. */
|
|
69
|
+
export declare function newDeviceState(): string;
|
|
70
|
+
/**
|
|
71
|
+
* Cookie options for the state cookie.
|
|
72
|
+
*
|
|
73
|
+
* `SameSite=Lax` rather than `Strict` is deliberate: the redemption arrives as
|
|
74
|
+
* a top-level navigation from a mail client or webmail tab, and `Strict` would
|
|
75
|
+
* withhold the cookie on that cross-site click — making every ordinary
|
|
76
|
+
* redemption look like a mismatch, which is the failure mode most likely to get
|
|
77
|
+
* this feature switched off.
|
|
78
|
+
*
|
|
79
|
+
* `httpOnly` keeps page scripts from reading or forging it. `maxAge` tracks the
|
|
80
|
+
* token TTL so the cookie does not outlive what it describes.
|
|
81
|
+
*/
|
|
82
|
+
export declare function deviceStateCookieOptions(ttlMs: number, secure?: boolean): {
|
|
83
|
+
httpOnly: true;
|
|
84
|
+
sameSite: 'lax';
|
|
85
|
+
maxAge: number;
|
|
86
|
+
path: '/';
|
|
87
|
+
secure: boolean;
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Decide what the presented cookie says about the redeeming browser.
|
|
91
|
+
*
|
|
92
|
+
* Never throws: this runs on the sign-in path, and an exception here would turn
|
|
93
|
+
* a legitimate login into a 500.
|
|
94
|
+
*/
|
|
95
|
+
export declare function evaluateDeviceBinding(input: DeviceBindingInput): DeviceBindingResult;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared utilities for manager-to-plugin content methods.
|
|
3
|
+
*
|
|
4
|
+
* Managers import from here to implement methods like toMarqueeText() or
|
|
5
|
+
* toSlideshowContent() in a consistent way. Plugin code never imports from
|
|
6
|
+
* this file — plugins only receive the formatted output string.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Common options for manager methods that feed plugin content.
|
|
10
|
+
* Passed as a raw key=value object from the plugin's fetch= parameter.
|
|
11
|
+
* Domain-specific options (e.g. alertLevel, colorCode) are handled per-manager.
|
|
12
|
+
*/
|
|
13
|
+
export interface ManagerFetchOptions {
|
|
14
|
+
/** Max items to return. 0 = unlimited. */
|
|
15
|
+
limit?: number;
|
|
16
|
+
/** Field name to sort by — each manager defines valid values. */
|
|
17
|
+
sortBy?: string;
|
|
18
|
+
/** Sort direction. */
|
|
19
|
+
sortOrder?: 'asc' | 'desc';
|
|
20
|
+
/** ISO date string — include only items at or after this date. */
|
|
21
|
+
since?: string;
|
|
22
|
+
/** ISO date string — include only items before this date. */
|
|
23
|
+
before?: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Parse a raw key=value args object (from a plugin fetch= parameter) into
|
|
27
|
+
* a typed ManagerFetchOptions. Unknown keys are silently ignored — each
|
|
28
|
+
* manager is responsible for reading its own domain-specific keys from the
|
|
29
|
+
* same raw object.
|
|
30
|
+
*
|
|
31
|
+
* Convenience shorthand: `sort='date-desc'` expands to
|
|
32
|
+
* `{ sortBy: 'date', sortOrder: 'desc' }`.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* // fetch='HansDataManager.toMarqueeText(limit=3,sort=date-desc)'
|
|
36
|
+
* // raw = { limit: '3', sort: 'date-desc' }
|
|
37
|
+
* const opts = parseManagerFetchOptions(raw);
|
|
38
|
+
* // opts = { limit: 3, sortBy: 'date', sortOrder: 'desc' }
|
|
39
|
+
*/
|
|
40
|
+
export declare function parseManagerFetchOptions(raw?: Record<string, string>): ManagerFetchOptions;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Move `{attachmentStoragedir}/{legacyprivateroot}/{user}/hash.ext` into
|
|
3
|
+
* `{pages}/{privateroot}/{user}/{defaultstoreid}/{attachmentsdir}/` (#1386).
|
|
4
|
+
*
|
|
5
|
+
* Destination is the page store. Leave sealed stores' leftover files alone.
|
|
6
|
+
* `legacyprivateroot` is migrate-FROM only — not a live write target.
|
|
7
|
+
*/
|
|
8
|
+
import { type PrivateStoreLayoutOverrides } from './privateStorePath.js';
|
|
9
|
+
export declare function migrateLegacyPrivateAttachments(opts: {
|
|
10
|
+
attachmentsPrivateDir: string;
|
|
11
|
+
pagesDirectory: string;
|
|
12
|
+
layout?: PrivateStoreLayoutOverrides;
|
|
13
|
+
}): Promise<{
|
|
14
|
+
moved: number;
|
|
15
|
+
}>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* URL-first filename derivation for organization JSON-LD files (#617,
|
|
3
|
+
* locked decision #9).
|
|
4
|
+
*
|
|
5
|
+
* Domain names are guaranteed unique by registry, so URL-derived slugs are
|
|
6
|
+
* the strongest uniqueness anchor for the on-disk filename. Falls back to
|
|
7
|
+
* the org name when no URL is available, then to a literal `organization`
|
|
8
|
+
* last-ditch default.
|
|
9
|
+
*
|
|
10
|
+
* filenameFromOrg({ url: 'https://fairwayscondos.org/' })
|
|
11
|
+
* → 'fairwayscondos-org.json'
|
|
12
|
+
* filenameFromOrg({ url: 'www.fairwayscondos.org' })
|
|
13
|
+
* → 'www-fairwayscondos-org.json'
|
|
14
|
+
* filenameFromOrg({ name: 'The Fairways' })
|
|
15
|
+
* → 'the-fairways.json'
|
|
16
|
+
* filenameFromOrg({})
|
|
17
|
+
* → 'organization.json'
|
|
18
|
+
*/
|
|
19
|
+
export declare function filenameFromOrg({ url, name }: {
|
|
20
|
+
url?: string;
|
|
21
|
+
name?: string;
|
|
22
|
+
}): string;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A page that belongs to a feature is not there while the feature is off (#1677).
|
|
3
|
+
*
|
|
4
|
+
* A shipped help page for capture still told readers to open `/capture/install`
|
|
5
|
+
* on a site where capture is off, and that route answered 404. A page names
|
|
6
|
+
* the switch it belongs to in frontmatter — `requires-setting:
|
|
7
|
+
* ngdpbase.capture.enabled` — and while that setting is not `true`, reading the
|
|
8
|
+
* page answers "not found" and listings leave it out, as profile already
|
|
9
|
+
* leaves out its Captures row (#1004).
|
|
10
|
+
*
|
|
11
|
+
* One predicate, asked by both doors that decide a page: PageManager's
|
|
12
|
+
* deciding read (so the reader gets the ordinary not-found) and the
|
|
13
|
+
* PolicyInformationPoint's page tiers (so listings and every other caller of
|
|
14
|
+
* the decider agree). Only `view` is affected; editing the page is unchanged.
|
|
15
|
+
*/
|
|
16
|
+
/** The frontmatter key naming the boolean setting a page belongs to. */
|
|
17
|
+
export declare const REQUIRES_SETTING = "requires-setting";
|
|
18
|
+
interface SettingReader {
|
|
19
|
+
getProperty(key: string, fallback: unknown): unknown;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* True when the page names a setting and that setting is not `true`.
|
|
23
|
+
* A page naming no setting is never hidden. Without a configuration reader
|
|
24
|
+
* nothing is hidden: absence of configuration is not a switch turned off.
|
|
25
|
+
*/
|
|
26
|
+
export declare function hiddenByFeature(metadata: Record<string, unknown> | null | undefined, config: SettingReader | null | undefined): boolean;
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export interface ParsedPageFile {
|
|
2
|
+
data: Record<string, unknown>;
|
|
3
|
+
content: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* A name value as text, for values that no longer carry their written form
|
|
7
|
+
* (metadata already parsed elsewhere). A Date becomes its ISO string, which is
|
|
8
|
+
* what an imported timestamp title was written as.
|
|
9
|
+
*/
|
|
10
|
+
export declare function nameAsText(value: unknown): string | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* Make a metadata object's name fields text in place, and return it.
|
|
13
|
+
*
|
|
14
|
+
* For callers holding metadata that was parsed without
|
|
15
|
+
* `parsePageFrontmatter`; a save must never meet a boolean or Date title.
|
|
16
|
+
*/
|
|
17
|
+
export declare function namesAsText<T extends Record<string, unknown>>(data: T): T;
|
|
18
|
+
/**
|
|
19
|
+
* Parse a page file. Name fields come back as the text written in the file.
|
|
20
|
+
*/
|
|
21
|
+
export declare function parsePageFrontmatter(raw: string): ParsedPageFile;
|