@jwilleke/ngdpbase-types 5.25.0 → 5.27.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 (89) hide show
  1. package/README.md +1 -1
  2. package/lib/packages/ngdpbase-types/index.d.ts +9 -2
  3. package/lib/packages/ngdpbase-types/testing.d.ts +7 -3
  4. package/lib/packages/ngdpbase-types/testing.js +7 -3
  5. package/lib/src/converters/DocxConverter.d.ts +30 -0
  6. package/lib/src/converters/MarkdownConverter.d.ts +31 -0
  7. package/lib/src/export/ChromeServicePdfProvider.d.ts +52 -0
  8. package/lib/src/export/ChromeServicePdfProvider.js +153 -0
  9. package/lib/src/export/LocalChromePdfProvider.d.ts +25 -0
  10. package/lib/src/export/LocalChromePdfProvider.js +33 -0
  11. package/lib/src/export/PdfProvider.d.ts +51 -0
  12. package/lib/src/export/PdfProvider.js +37 -0
  13. package/lib/src/export/pdfEngine.d.ts +113 -0
  14. package/lib/src/export/pdfEngine.js +195 -0
  15. package/lib/src/http/egressPolicy.js +61 -0
  16. package/lib/src/http/guardedElasticsearch.d.ts +27 -0
  17. package/lib/src/http/guardedElasticsearch.js +99 -0
  18. package/lib/src/ice/converterShim.d.ts +5 -0
  19. package/lib/src/ice/fileHandling.d.ts +30 -0
  20. package/lib/src/ice/ledger.d.ts +37 -0
  21. package/lib/src/ice/runImport.d.ts +51 -0
  22. package/lib/src/ice/types.d.ts +262 -0
  23. package/lib/src/mail/MailProvider.d.ts +15 -0
  24. package/lib/src/mail/NodemailerMailProvider.d.ts +1 -1
  25. package/lib/src/managers/AddonsManager.d.ts +55 -3
  26. package/lib/src/managers/AttachmentManager.d.ts +4 -5
  27. package/lib/src/managers/AuthManager.d.ts +150 -32
  28. package/lib/src/managers/BackgroundJobManager.d.ts +22 -12
  29. package/lib/src/managers/BackupManager.d.ts +779 -0
  30. package/lib/src/managers/BackupManager.js +2042 -0
  31. package/lib/src/managers/BaseManager.d.ts +156 -6
  32. package/lib/src/managers/BaseManager.js +64 -2
  33. package/lib/src/managers/CommentManager.d.ts +6 -6
  34. package/lib/src/managers/ConsentManager.d.ts +130 -0
  35. package/lib/src/managers/DatabaseManager.d.ts +6 -0
  36. package/lib/src/managers/DatabaseManager.js +25 -15
  37. package/lib/src/managers/EmailManager.d.ts +32 -5
  38. package/lib/src/managers/ExportManager.d.ts +62 -0
  39. package/lib/src/managers/ExportManager.js +147 -2
  40. package/lib/src/managers/FootnoteManager.d.ts +6 -6
  41. package/lib/src/managers/ImportManager.d.ts +590 -0
  42. package/lib/src/managers/OrganizationManager.d.ts +8 -6
  43. package/lib/src/managers/PageManager.d.ts +61 -1
  44. package/lib/src/managers/PersonManager.d.ts +8 -6
  45. package/lib/src/managers/RoleManager.d.ts +6 -8
  46. package/lib/src/providers/BaseAttachmentProvider.d.ts +4 -4
  47. package/lib/src/providers/BaseBackupProvider.d.ts +77 -0
  48. package/lib/src/providers/BaseBackupProvider.js +52 -0
  49. package/lib/src/providers/BasicAttachmentProvider.d.ts +4 -4
  50. package/lib/src/providers/FileBackupProvider.d.ts +34 -0
  51. package/lib/src/providers/FileBackupProvider.js +116 -0
  52. package/lib/src/providers/FileConsentProvider.d.ts +18 -0
  53. package/lib/src/providers/SqliteDatabaseProvider.d.ts +2 -2
  54. package/lib/src/providers/SqliteDatabaseProvider.js +12 -11
  55. package/lib/src/providers/attachmentFilesBackup.d.ts +5 -4
  56. package/lib/src/providers/databaseMigrations.js +45 -0
  57. package/lib/src/security/PolicyDecisionPoint.d.ts +14 -0
  58. package/lib/src/security/PolicyInformationPoint.d.ts +25 -2
  59. package/lib/src/types/Config.d.ts +2 -0
  60. package/lib/src/types/Consent.d.ts +90 -0
  61. package/lib/src/types/express.d.ts +6 -0
  62. package/lib/src/utils/addonHost.d.ts +45 -2
  63. package/lib/src/utils/addonHost.js +39 -3
  64. package/lib/src/utils/auditEventNames.generated.d.ts +20 -0
  65. package/lib/src/utils/auditEventNames.generated.js +20 -0
  66. package/lib/src/utils/backupCrypto.js +275 -0
  67. package/lib/src/utils/backupDocument.d.ts +36 -0
  68. package/lib/src/utils/backupDocument.js +99 -0
  69. package/lib/src/utils/browserDescription.d.ts +11 -0
  70. package/lib/src/utils/directoryBackup.d.ts +48 -48
  71. package/lib/src/utils/directoryBackup.js +291 -0
  72. package/lib/src/utils/frontmatterAccess.d.ts +54 -11
  73. package/lib/src/utils/importRunSummary.d.ts +64 -0
  74. package/lib/src/utils/instanceEnvBackup.d.ts +46 -0
  75. package/lib/src/utils/instanceEnvBackup.js +120 -0
  76. package/lib/src/utils/instanceEnvSecret.js +79 -0
  77. package/lib/src/utils/ipLocation.d.ts +11 -0
  78. package/lib/src/utils/ncmNotify.d.ts +30 -0
  79. package/lib/src/utils/privateStoreImport.d.ts +58 -0
  80. package/lib/src/utils/schedule.js +171 -0
  81. package/lib/src/utils/secretFileMode.js +78 -0
  82. package/lib/src/utils/siteRestore.d.ts +13 -16
  83. package/lib/src/utils/siteRestore.js +33 -6
  84. package/lib/src/utils/treeArchive.d.ts +2 -0
  85. package/lib/src/utils/treeArchive.js +242 -0
  86. package/lib/src/utils/version.js +408 -0
  87. package/lib/src/utils/zipArchive.d.ts +71 -0
  88. package/package.json +6 -1
  89. package/lib/src/utils/administrators.d.ts +0 -21
@@ -146,6 +146,20 @@ export declare class PolicyDecisionPoint extends BaseManager {
146
146
  * cannot be asked by accident. The subject is the PIP's, resolved live.
147
147
  */
148
148
  userHoldsPermission(username: string, action: string): Promise<boolean>;
149
+ /**
150
+ * The usernames of every account that holds a permission, each asked through
151
+ * {@link userHoldsPermission} (#1813; was `utils/administrators.ts`). With
152
+ * `admin-system` this is "who are the administrators": the people an
153
+ * operator problem is reported to (#1431 7b, #1916), never a role name.
154
+ *
155
+ * An empty answer means "nobody to tell", and a caller sending a
156
+ * notification must then only log it: an empty `targetUsers` list means
157
+ * every user in NotificationManager.
158
+ *
159
+ * @returns The usernames, or null when there is no UserManager to list
160
+ * accounts from (tests, a half-booted engine); treat that like nobody
161
+ */
162
+ usersHolding(action: string): Promise<string[] | null>;
149
163
  /**
150
164
  * The permissions a user's roles give them, for display (#1431 step 10).
151
165
  *
@@ -209,6 +209,12 @@ declare class PolicyInformationPoint extends BaseManager {
209
209
  * none when it is not running.
210
210
  */
211
211
  subjectEnabledAddons(ctx: ActorContext): Promise<string[]>;
212
+ /**
213
+ * {@link subjectEnabledAddons} for a page decision (#1964): none for no
214
+ * subject, and none when the lookup fails — an `addon:<slug>` entry then
215
+ * matches nobody, never everyone.
216
+ */
217
+ private enabledAddonsOf;
212
218
  private userManager;
213
219
  private roleManager;
214
220
  /**
@@ -326,7 +332,9 @@ declare class PolicyInformationPoint extends BaseManager {
326
332
  * - __Tier 0.5, author-lock__, `edit` only. It only denies: an author, or a
327
333
  * subject holding `admin-system` (#1431 7b), falls through to Tier 1+.
328
334
  * - __Tier 1, frontmatter__ `access[action]` / `audience`. Page-level, and
329
- * overrides global policy when it states a rule (#1054).
335
+ * overrides global policy when it states a rule (#1054). An `audience`
336
+ * covers every action, and a subject holding `admin-system` is its one
337
+ * exception; `access` has none (#1964).
330
338
  * - __Tier 2.__ For a share visitor the share IS the policy (#1222); for
331
339
  * anyone else, global policy.
332
340
  * - __Default deny.__ Nothing below Tier 2 grants — JSPWiki's page-body ACL
@@ -439,10 +447,25 @@ declare class PolicyInformationPoint extends BaseManager {
439
447
  */
440
448
  canUserAccessMediaItem(userContext: UserContext | null | undefined, item: MediaItem): Promise<boolean>;
441
449
  /**
442
- * Check front matter audience / access fields (Tier 1.5).
450
+ * Check front matter audience / access fields (Tier 1).
443
451
  * Returns a decision object; decided=false means no front matter restriction — fall through.
452
+ *
453
+ * An audience that leaves the subject out refuses every action, unless the
454
+ * subject holds `admin-system` (#1964, operator 2026-10-23): asked only
455
+ * then. `access[action]` has no such exception.
444
456
  */
445
457
  private checkFrontmatterAccess;
458
+ /**
459
+ * Does the page's `audience` admit this subject (#1964)? True when the page
460
+ * names no audience, the subject matches it, or the subject holds
461
+ * `admin-system`. The same rule Tier 1 applies, asked by PageManager's
462
+ * write door, so a write cannot reach a page its writer is outside the
463
+ * audience of — whatever route it came by. Records nothing; the door does.
464
+ *
465
+ * @param userContext - the subject, as given
466
+ * @param metadata - the page's current frontmatter
467
+ */
468
+ audienceAdmits(userContext: UserContext | null | undefined, metadata: PageFrontmatter | null | undefined): Promise<boolean>;
446
469
  /**
447
470
  * Record/audit an access decision.
448
471
  * Accepts either a single object or positional args for backward compatibility.
@@ -121,6 +121,8 @@ export interface WikiConfig {
121
121
  * counting every failure inside it (#1916). Default: 60.
122
122
  */
123
123
  'ngdpbase.mail.failure-notice.window-minutes': number;
124
+ /** The most a message's attachments may total, in bytes (#1974). Default: 10485760. */
125
+ 'ngdpbase.mail.attachments.max-bytes': number;
124
126
  /**
125
127
  * Anti-spam: max submissions per IP per `window-minutes` window before
126
128
  * the 429 trips (#670 Phase E). Default: 5.
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Consent to a site's documents (#1603): the shapes ConsentManager and its
3
+ * callers share, and what an add-on registers.
4
+ */
5
+ /** Whose document it is: core's (`core`) or an add-on's slug. */
6
+ export type ConsentScope = string;
7
+ /** Where a person is asked to accept (#1603): `?scope=` (core when absent) and `?returnTo=`. */
8
+ export declare const CONSENT_PATH = "/consent";
9
+ /** The scope of core's own documents, `ngdpbase.consent.documents`. */
10
+ export declare const CORE_CONSENT_SCOPE = "core";
11
+ /**
12
+ * A document a person is asked to accept, as it stands now: a page whose
13
+ * front matter carries `version:` and `effective:`. Read from the page each
14
+ * time, never copied.
15
+ */
16
+ export interface ConsentDocument {
17
+ /** The page's slug, which is also the document's id in a record (`terms-of-service`, `phr-privacy-policy`). */
18
+ id: string;
19
+ scope: ConsentScope;
20
+ /** The page's title, to show. */
21
+ title: string;
22
+ /** The page's `version:`, as a string. A change asks everyone again. */
23
+ version: string;
24
+ /** The page's `effective:` date (`YYYY-MM-DD`), or null when it names none. */
25
+ effective: string | null;
26
+ }
27
+ /** What a person saw when they accepted: each document and the version shown. */
28
+ export interface ConsentSeen {
29
+ id: string;
30
+ version: string;
31
+ }
32
+ /**
33
+ * One acceptance, one line of the person's file. Append-only: a later
34
+ * version is a later line, nothing is rewritten.
35
+ */
36
+ export interface ConsentRecord {
37
+ kind: 'accept';
38
+ document: string;
39
+ scope: ConsentScope;
40
+ version: string;
41
+ effective: string | null;
42
+ /** ISO 8601 time the person accepted. */
43
+ acceptedAt: string;
44
+ /**
45
+ * The account this was accepted on, by its creation time (#1937): a later
46
+ * account that takes the same username never inherits it.
47
+ */
48
+ account?: string;
49
+ /** Who and how: the account, where from, and the way they were asked (`sign-up`, `sign-in`, `add-on`). */
50
+ context: {
51
+ by: string;
52
+ how: string;
53
+ origin: string;
54
+ ipAddress?: string;
55
+ };
56
+ }
57
+ /** One document's state for a person, for "Your consents" on /profile. */
58
+ export interface ConsentStatus {
59
+ document: ConsentDocument;
60
+ /** Their acceptance of the current version, or null: not accepted (never, or only an older version). */
61
+ current: ConsentRecord | null;
62
+ /** Their latest acceptance of any version, or null. */
63
+ latest: ConsentRecord | null;
64
+ }
65
+ /** What an add-on registers at load (#1603). */
66
+ export interface AddonConsentRegistration {
67
+ /**
68
+ * Page slugs of the add-on's documents, each starting `<slug>-`
69
+ * (`phr-terms-of-service`, `phr-privacy-policy`). Shipped as the add-on's
70
+ * own pages, with `version:` and `effective:` front matter.
71
+ */
72
+ documents: string[];
73
+ /**
74
+ * URL path prefixes where a person uses the add-on in the browser
75
+ * (`/phr`). A person who has it on and has not accepted a changed version
76
+ * is asked there before going on. Optional: without it they are asked
77
+ * only when they next turn it on.
78
+ */
79
+ paths?: string[];
80
+ }
81
+ /**
82
+ * Thrown when a per-person add-on is turned on before its documents are
83
+ * accepted (#1603). `documents` names what is still to accept.
84
+ */
85
+ export declare class ConsentRequiredError extends Error {
86
+ readonly scope: ConsentScope;
87
+ readonly documents: string[];
88
+ readonly name = "ConsentRequiredError";
89
+ constructor(scope: ConsentScope, documents: string[]);
90
+ }
@@ -45,6 +45,12 @@ declare module 'express-session' {
45
45
  pendingRedirect?: string;
46
46
  /** A verified outside identity no account has connected, waiting for the person to sign in another way (#1743). */
47
47
  pendingConnection?: PendingConnection;
48
+ /**
49
+ * Set at sign-in when the person has core terms to accept at their current
50
+ * version (#1603); the consent gate holds the session to the prompt until
51
+ * they accept (or sign out). Cleared by the acceptance.
52
+ */
53
+ consentPending?: boolean;
48
54
  /** When this session last made a request, epoch ms — kept only while an idle timeout is set (#1546). */
49
55
  lastActivity?: number;
50
56
  /** When this session signed in, epoch ms: the start of `ngdpbase.session.max-age` (#1767). A re-authentication never moves it. */
@@ -15,6 +15,12 @@
15
15
  * the add-on (#1973);
16
16
  * - `setEnabledForPerson` sets this add-on's own per-person switch (#1963),
17
17
  * bound to its slug, so it can never set another add-on's;
18
+ * - `registerShim` and `registerReceiver` (#1979, ICE) register into the import
19
+ * engine under this add-on's slug, and only the names its manifest declares;
20
+ * - the egress tools (`resolveEgressPolicy`, `validateUrl`,
21
+ * `createGuardedElasticsearchClient`, `refusedNodeMessage`) and `isAtLeast`
22
+ * are core's own pure functions, handed on unchanged, so an add-on never
23
+ * imports them from `dist/` (#1813);
18
24
  * - the object is `Object.freeze`d, so no add-on can replace a value.
19
25
  *
20
26
  * Additive only: nothing here is removed or renamed without a major release.
@@ -26,8 +32,14 @@ import { actorOf, type ActorContext } from '../context/ActorContext.js';
26
32
  import { jobContextFromRequest, jobContextFromSystem, type JobContext } from '../context/JobContext.js';
27
33
  import { systemContext } from '../context/bootActions.js';
28
34
  import { guardedFetch } from '../http/guardedFetch.js';
35
+ import { resolveEgressPolicy } from '../http/egressPolicy.js';
36
+ import { validateUrl } from '../http/ssrf.js';
37
+ import { createGuardedElasticsearchClient, refusedNodeMessage } from '../http/guardedElasticsearch.js';
38
+ import { isAtLeast } from './version.js';
29
39
  import { recordAuditEvent } from './auditEvents.js';
30
40
  import { addonAuditEventName } from './auditEventNames.js';
41
+ import type { IceReceiver, IceShim } from '../ice/types.js';
42
+ import type { AddonManifest } from '../managers/AddonsManager.js';
31
43
  /** The values core offers an add-on, under the names they were imported as. */
32
44
  export interface AddonHost {
33
45
  readonly ApiContext: typeof ApiContext;
@@ -54,7 +66,35 @@ export interface AddonHost {
54
66
  * does not say `perPerson: true`, or the person may not manage their profile.
55
67
  */
56
68
  readonly setEnabledForPerson: PersonSwitchSetter;
69
+ /**
70
+ * The site's egress policy, read through `read` (a `ConfigurationManager.getProperty`
71
+ * reader) each time it is called, so an operator tightening it applies at once.
72
+ * Hand its `policy` to `guardedFetch` or `validateUrl`.
73
+ */
74
+ readonly resolveEgressPolicy: typeof resolveEgressPolicy;
75
+ /** Whether a URL may be fetched under an egress policy, before any socket: http(s) and an allowed literal address. */
76
+ readonly validateUrl: typeof validateUrl;
77
+ /** An Elasticsearch client whose every connection is judged by the egress policy; the only way to build one. */
78
+ readonly createGuardedElasticsearchClient: typeof createGuardedElasticsearchClient;
79
+ /** The one boot-time line for an Elasticsearch node the egress policy refuses. */
80
+ readonly refusedNodeMessage: typeof refusedNodeMessage;
81
+ /** Whether an `x.y.z` version is at least another; throws on a version that is not `x.y.z`. */
82
+ readonly isAtLeast: typeof isAtLeast;
83
+ /**
84
+ * #1979 (ICE, D6): register an import shim, as `<slug>.<shim.name>`. Call it
85
+ * in `register`. Refused when the manifest's `shims` does not name it.
86
+ * Returns the shim's id; site configuration switches it on and off.
87
+ */
88
+ readonly registerShim: (shim: IceShim) => string;
89
+ /**
90
+ * #1979 (ICE, D4): register a receiver — your manager's own door for what
91
+ * shims produce — as `<slug>.<receiver.name>`. Refused when the manifest's
92
+ * `receivers` does not name it. Returns the receiver's id.
93
+ */
94
+ readonly registerReceiver: (receiver: IceReceiver) => string;
57
95
  }
96
+ /** What the host may register for an add-on: the shim and receiver names its manifest declares (#1979). */
97
+ export type AddonIceDeclaration = Pick<AddonManifest, 'shims' | 'receivers'>;
58
98
  /** Sets one add-on's per-person switch; core binds the slug when it builds the host (#1963). */
59
99
  export type PersonSwitchSetter = (ctx: ActorContext, on: boolean) => Promise<void>;
60
100
  /**
@@ -72,6 +112,9 @@ export declare function addonDeclaredAuditEvents(addonDefaults: Record<string, u
72
112
  * @param setEnabledForPerson - This add-on's switch setter, slug already bound
73
113
  * (`AddonsManager` supplies it); without one, the host's setter refuses
74
114
  * @param engine - The running engine, which names the system principal for
75
- * `systemContext`; without one (a test) it is core's fallback principal
115
+ * `systemContext` and holds the import engine `registerShim` reaches;
116
+ * without one (a test) it is core's fallback principal, and no registry
117
+ * @param manifest - The add-on's manifest (`ngdpbase` in its package.json):
118
+ * the shims and receivers it may register (#1979)
76
119
  */
77
- export declare function buildAddonHost(slug: string, addonDefaults: Record<string, unknown>, setEnabledForPerson?: PersonSwitchSetter, engine?: Parameters<typeof systemContext>[0]): AddonHost;
120
+ export declare function buildAddonHost(slug: string, addonDefaults: Record<string, unknown>, setEnabledForPerson?: PersonSwitchSetter, engine?: Parameters<typeof systemContext>[0], manifest?: AddonIceDeclaration | null): AddonHost;
@@ -15,6 +15,12 @@
15
15
  * the add-on (#1973);
16
16
  * - `setEnabledForPerson` sets this add-on's own per-person switch (#1963),
17
17
  * bound to its slug, so it can never set another add-on's;
18
+ * - `registerShim` and `registerReceiver` (#1979, ICE) register into the import
19
+ * engine under this add-on's slug, and only the names its manifest declares;
20
+ * - the egress tools (`resolveEgressPolicy`, `validateUrl`,
21
+ * `createGuardedElasticsearchClient`, `refusedNodeMessage`) and `isAtLeast`
22
+ * are core's own pure functions, handed on unchanged, so an add-on never
23
+ * imports them from `dist/` (#1813);
18
24
  * - the object is `Object.freeze`d, so no add-on can replace a value.
19
25
  *
20
26
  * Additive only: nothing here is removed or renamed without a major release.
@@ -25,6 +31,10 @@ import { actorOf } from '../context/ActorContext.js';
25
31
  import { jobContextFromRequest, jobContextFromSystem } from '../context/JobContext.js';
26
32
  import { systemContext } from '../context/bootActions.js';
27
33
  import { guardedFetch } from '../http/guardedFetch.js';
34
+ import { resolveEgressPolicy } from '../http/egressPolicy.js';
35
+ import { validateUrl } from '../http/ssrf.js';
36
+ import { createGuardedElasticsearchClient, refusedNodeMessage } from '../http/guardedElasticsearch.js';
37
+ import { isAtLeast } from './version.js';
28
38
  import { recordAuditEvent } from './auditEvents.js';
29
39
  import { addonAuditEventName } from './auditEventNames.js';
30
40
  import { auditDeclarationsFrom } from './auditRegistry.js';
@@ -56,10 +66,29 @@ function refuseUndeclared(slug, name, declared) {
56
66
  * @param setEnabledForPerson - This add-on's switch setter, slug already bound
57
67
  * (`AddonsManager` supplies it); without one, the host's setter refuses
58
68
  * @param engine - The running engine, which names the system principal for
59
- * `systemContext`; without one (a test) it is core's fallback principal
69
+ * `systemContext` and holds the import engine `registerShim` reaches;
70
+ * without one (a test) it is core's fallback principal, and no registry
71
+ * @param manifest - The add-on's manifest (`ngdpbase` in its package.json):
72
+ * the shims and receivers it may register (#1979)
60
73
  */
61
- export function buildAddonHost(slug, addonDefaults, setEnabledForPerson = noPersonSwitch, engine) {
74
+ export function buildAddonHost(slug, addonDefaults, setEnabledForPerson = noPersonSwitch, engine, manifest) {
62
75
  const declared = addonDeclaredAuditEvents(addonDefaults);
76
+ const names = (list) => new Set(Array.isArray(list) ? list.filter((n) => typeof n === 'string') : []);
77
+ const iceDeclared = { shim: names(manifest?.shims), receiver: names(manifest?.receivers) };
78
+ const iceRegistry = (what, name) => {
79
+ const allowed = iceDeclared[what];
80
+ if (typeof name !== 'string' || !allowed.has(name)) {
81
+ const message = `Add-on '${slug}' may register only the ${what}s its manifest declares ("ngdpbase": { "${what}s": [...] } in package.json); ` +
82
+ `'${String(name)}' is not one of them (declared: ${allowed.size > 0 ? [...allowed].sort().join(', ') : 'none'}).`;
83
+ logger.error(`[addons] ${message}`);
84
+ throw new Error(message);
85
+ }
86
+ const registry = engine?.getManager('ImportManager');
87
+ if (typeof registry?.registerShim !== 'function' || typeof registry.registerReceiver !== 'function') {
88
+ throw new Error(`register${what === 'shim' ? 'Shim' : 'Receiver'} is not available: this host was built without a site's ImportManager`);
89
+ }
90
+ return registry;
91
+ };
63
92
  const hostAddonAuditEventName = (name) => {
64
93
  const checked = addonAuditEventName(name);
65
94
  refuseUndeclared(slug, name, declared);
@@ -81,6 +110,13 @@ export function buildAddonHost(slug, addonDefaults, setEnabledForPerson = noPers
81
110
  systemContext: (reason) => systemContext(engine, reason),
82
111
  logger: logger.child({ addon: slug }),
83
112
  guardedFetch,
84
- setEnabledForPerson
113
+ setEnabledForPerson,
114
+ registerShim: (shim) => iceRegistry('shim', shim?.name).registerShim(slug, shim),
115
+ registerReceiver: (receiver) => iceRegistry('receiver', receiver?.name).registerReceiver(slug, receiver),
116
+ resolveEgressPolicy,
117
+ validateUrl,
118
+ createGuardedElasticsearchClient,
119
+ refusedNodeMessage,
120
+ isAtLeast
85
121
  });
86
122
  }
@@ -50,6 +50,10 @@ export declare const AUDIT_EVENT: {
50
50
  readonly CONFIG_CHANGE: "config-change";
51
51
  /** Every custom configuration value discarded; recorded before the reset, which cannot proceed without it */
52
52
  readonly CONFIG_RESET: "config-reset";
53
+ /** A person accepted a document they are asked to accept (#1603): which document (core's terms-of-service or privacy-policy, or an add-on's), its version and effective date, and how (sign-up, sign-in, turning an add-on on). Recorded before the acceptance is stored, which cannot proceed without it: consent must be provable */
54
+ readonly CONSENT_GRANT: "consent-grant";
55
+ /** A person's acceptances ended (#1603): today only when their account is deleted, which removes their consent records; names the documents and versions they had accepted. Recorded before the records are removed */
56
+ readonly CONSENT_WITHDRAW: "consent-withdraw";
53
57
  /** Contact created, changed, deleted or linked to an account; metadata names the kind (person or organization), the operation and the fields changed, never their values */
54
58
  readonly CONTACT_MANAGE: "contact-manage";
55
59
  /** A page's footnote list changed — action add, import, transfer, update or delete; page content written on someone's behalf (#1233) */
@@ -140,6 +144,22 @@ export declare const AUDIT_EVENT: {
140
144
  readonly SHARE_EXTEND: "share-extend";
141
145
  /** Share link revoked; pairs with token-revoke */
142
146
  readonly SHARE_REVOKE: "share-revoke";
147
+ /** Sign-in approval: the browser that was waiting gave up the sign-in (#1532) */
148
+ readonly SIGNINAPPROVAL_ABANDON: "signinapproval-abandon";
149
+ /** Sign-in approval: the person pressed Approve (#1532) */
150
+ readonly SIGNINAPPROVAL_APPROVE: "signinapproval-approve";
151
+ /** Sign-in approval: the person pressed Deny; that sign-in will not complete (#1532) */
152
+ readonly SIGNINAPPROVAL_DENY: "signinapproval-deny";
153
+ /** Sign-in approval: a waiting sign-in expired before it was completed (#1532) */
154
+ readonly SIGNINAPPROVAL_EXPIRE: "signinapproval-expire";
155
+ /** Sign-in approval: the approval page was opened, with the opener's IP and browser; opening changes nothing (#1532) */
156
+ readonly SIGNINAPPROVAL_OPEN: "signinapproval-open";
157
+ /** Sign-in approval: an approval message was sent for a waiting sign-in, saying from where (IP, approximate place, browser) (#1532) */
158
+ readonly SIGNINAPPROVAL_REQUEST: "signinapproval-request";
159
+ /** Sign-in approval: the approval message could not be sent (transport error, or no channel configured) (#1532) */
160
+ readonly SIGNINAPPROVAL_SENDFAIL: "signinapproval-sendfail";
161
+ /** Sign-in approval: another approval message was asked for too soon and not sent (#1532) */
162
+ readonly SIGNINAPPROVAL_THROTTLE: "signinapproval-throttle";
143
163
  /** A user's private store copy created at its door (#1414) — with key material when sealed; never the words or a key in the record */
144
164
  readonly STORE_CREATE: "store-create";
145
165
  /** A takeout imported into its owner's private store; a bulk write — who, which store, pages and files written or skipped */
@@ -57,6 +57,10 @@ export const AUDIT_EVENT = {
57
57
  CONFIG_CHANGE: 'config-change',
58
58
  /** Every custom configuration value discarded; recorded before the reset, which cannot proceed without it */
59
59
  CONFIG_RESET: 'config-reset',
60
+ /** A person accepted a document they are asked to accept (#1603): which document (core's terms-of-service or privacy-policy, or an add-on's), its version and effective date, and how (sign-up, sign-in, turning an add-on on). Recorded before the acceptance is stored, which cannot proceed without it: consent must be provable */
61
+ CONSENT_GRANT: 'consent-grant',
62
+ /** A person's acceptances ended (#1603): today only when their account is deleted, which removes their consent records; names the documents and versions they had accepted. Recorded before the records are removed */
63
+ CONSENT_WITHDRAW: 'consent-withdraw',
60
64
  /** Contact created, changed, deleted or linked to an account; metadata names the kind (person or organization), the operation and the fields changed, never their values */
61
65
  CONTACT_MANAGE: 'contact-manage',
62
66
  /** A page's footnote list changed — action add, import, transfer, update or delete; page content written on someone's behalf (#1233) */
@@ -147,6 +151,22 @@ export const AUDIT_EVENT = {
147
151
  SHARE_EXTEND: 'share-extend',
148
152
  /** Share link revoked; pairs with token-revoke */
149
153
  SHARE_REVOKE: 'share-revoke',
154
+ /** Sign-in approval: the browser that was waiting gave up the sign-in (#1532) */
155
+ SIGNINAPPROVAL_ABANDON: 'signinapproval-abandon',
156
+ /** Sign-in approval: the person pressed Approve (#1532) */
157
+ SIGNINAPPROVAL_APPROVE: 'signinapproval-approve',
158
+ /** Sign-in approval: the person pressed Deny; that sign-in will not complete (#1532) */
159
+ SIGNINAPPROVAL_DENY: 'signinapproval-deny',
160
+ /** Sign-in approval: a waiting sign-in expired before it was completed (#1532) */
161
+ SIGNINAPPROVAL_EXPIRE: 'signinapproval-expire',
162
+ /** Sign-in approval: the approval page was opened, with the opener's IP and browser; opening changes nothing (#1532) */
163
+ SIGNINAPPROVAL_OPEN: 'signinapproval-open',
164
+ /** Sign-in approval: an approval message was sent for a waiting sign-in, saying from where (IP, approximate place, browser) (#1532) */
165
+ SIGNINAPPROVAL_REQUEST: 'signinapproval-request',
166
+ /** Sign-in approval: the approval message could not be sent (transport error, or no channel configured) (#1532) */
167
+ SIGNINAPPROVAL_SENDFAIL: 'signinapproval-sendfail',
168
+ /** Sign-in approval: another approval message was asked for too soon and not sent (#1532) */
169
+ SIGNINAPPROVAL_THROTTLE: 'signinapproval-throttle',
150
170
  /** A user's private store copy created at its door (#1414) — with key material when sealed; never the words or a key in the record */
151
171
  STORE_CREATE: 'store-create',
152
172
  /** A takeout imported into its owner's private store; a bulk write — who, which store, pages and files written or skipped */