@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
@@ -0,0 +1,262 @@
1
+ /**
2
+ * ICE — import, convert, export (#1979): the shapes the engine, its shims and
3
+ * its receivers share. The design and every decision (D1–D11) are in
4
+ * docs/planning/ice-planing.md; this file is their code form.
5
+ *
6
+ * - A __shim__ knows one outside format and nothing else (D2). It declares
7
+ * its direction, what it accepts, what it produces and which receivers it
8
+ * may hand to (D3, D7). Shims chain: one's output is the next one's input (D9).
9
+ * - A __receiver__ is a door that already exists — PageManager for pages, the
10
+ * upload door for files, an add-on's own manager for its records (D4). The
11
+ * engine hands it each result and never writes storage itself. The receiver
12
+ * checks its own existing permission with the context the run carries (D5).
13
+ * - The __engine__ (ImportManager) owns everything else: sources, unzip, the
14
+ * noise filter, fingerprints, skipping unchanged files, per-file status,
15
+ * keeping the original, and running the work as a background job.
16
+ *
17
+ * Only importing is built in the first slice. `out` / `both` shims and the
18
+ * `write` half are declared so export (#1974) and feeds (D10) fit later
19
+ * without changing these shapes.
20
+ */
21
+ import type { ActorContext } from '../context/ActorContext.js';
22
+ import type { GuardedFetchOptions, GuardedResponse } from '../http/guardedFetch.js';
23
+ /** D3: which way a shim moves data. Most are `in`; PDF (#1974) would be `both`. */
24
+ export type ShimDirection = 'in' | 'out' | 'both';
25
+ /**
26
+ * The kind of a piece of content moving through the engine. `file` is raw
27
+ * input bytes; `html` and `ncm` are core's; an add-on's own kinds are named
28
+ * `<slug>.<kind>`, e.g. `phr.health-record`.
29
+ */
30
+ export type IceKind = string;
31
+ /** A structured note from a shim, the same shape as a converter's warning. */
32
+ export interface IceWarning {
33
+ kind: string;
34
+ detail: string;
35
+ }
36
+ /**
37
+ * One piece of content: a file the engine read, or what a shim produced from
38
+ * it. A shim's output becomes the next shim's input, or a receiver's.
39
+ */
40
+ export interface IceItem {
41
+ kind: IceKind;
42
+ /** The name it arrived under: the upload's file name, or `archive.zip/inner/path`. */
43
+ name: string;
44
+ mediaType?: string;
45
+ /** Raw bytes (a `file`, or binary output). */
46
+ bytes?: Buffer;
47
+ /** Text content (`html`, `ncm`, an XML document). */
48
+ text?: string;
49
+ /** A structured record, for record kinds such as health records. */
50
+ data?: unknown;
51
+ /** Facts about the content: a title, an author, a source system's id. */
52
+ metadata?: Record<string, unknown>;
53
+ warnings?: IceWarning[];
54
+ /**
55
+ * The item's own id or time, for a shim whose duplicates are per item
56
+ * (a feed entry): an item whose key the engine has seen before is skipped.
57
+ */
58
+ itemKey?: string;
59
+ }
60
+ /** What a shim takes. A file matches by extension or media type; a chained input by kind. */
61
+ export interface ShimAccepts {
62
+ /** Lower-case, with the dot: `['.xml']`. */
63
+ extensions?: string[];
64
+ mediaTypes?: string[];
65
+ /** Kinds produced by another shim that this one reads (D9), e.g. `['html']`. */
66
+ kinds?: IceKind[];
67
+ /**
68
+ * "Can I read this?" (D7), on the content. When present it must answer yes
69
+ * even for a file whose extension matches; it is also how a file with no
70
+ * matching extension is claimed.
71
+ */
72
+ canRead?(input: IceItem): boolean;
73
+ }
74
+ /** What the engine hands a shim besides its input. */
75
+ export interface ShimTools {
76
+ /**
77
+ * Follow-up fetches go through the engine (design rule): the one guarded
78
+ * path, with the site's egress policy, User-Agent and timeout.
79
+ */
80
+ fetch(url: string, options?: Omit<GuardedFetchOptions, 'policy' | 'transport' | 'resolver'>): Promise<GuardedResponse>;
81
+ /** This shim's options from site configuration (D6): `ngdpbase.import.shims.<id>.options`. */
82
+ options: Record<string, unknown>;
83
+ }
84
+ /** What a shim's read returns. */
85
+ export interface ShimReadResult {
86
+ items: IceItem[];
87
+ /**
88
+ * Set when the shim read only part of its input (phr's `readCcda` returns
89
+ * records plus a partial note): the file's status is then `partial`, with this.
90
+ */
91
+ partial?: string;
92
+ }
93
+ /**
94
+ * A shim as its author writes it (D7). `name` is unique within its owner; the
95
+ * engine names it `<owner>.<name>` — `core.markdown`, `phr.ccda`.
96
+ */
97
+ export interface IceShim {
98
+ name: string;
99
+ /** Shown to people choosing a format. */
100
+ label?: string;
101
+ direction: ShimDirection;
102
+ accepts: ShimAccepts;
103
+ /** The kind its output items have. */
104
+ produces: IceKind;
105
+ /**
106
+ * Receivers it may hand to directly (ids, `core.pages` or `<slug>.<name>`).
107
+ * Empty for a shim whose output only feeds another shim.
108
+ */
109
+ receivers: string[];
110
+ /** Two duplicate kinds (design rule): a whole file by fingerprint, or each item by `itemKey`. Default `file`. */
111
+ duplicates?: 'file' | 'item';
112
+ /** Inbound: read one input. Required for `in` and `both`. */
113
+ read?(input: IceItem, tools: ShimTools): Promise<ShimReadResult>;
114
+ /** Outbound (export, #1974): not run in the first slice. Required for `out` and `both`. */
115
+ write?(items: IceItem[], tools: ShimTools): Promise<IceItem[]>;
116
+ }
117
+ /** A shim the engine holds: its full id, and who registered it. */
118
+ export interface RegisteredShim extends IceShim {
119
+ id: string;
120
+ owner: string;
121
+ }
122
+ /** D11: what the person importing chose to do with the original file. */
123
+ export type OriginalChoice = 'cite' | 'keep' | 'none';
124
+ /** A citation to the origin (D11): the receiver renders it, as a footnote on a page. */
125
+ export interface IceCitation {
126
+ name: string;
127
+ sha256: string;
128
+ importedAt: string;
129
+ }
130
+ /** Where a kept original went (D11). */
131
+ export interface KeptOriginal {
132
+ name: string;
133
+ sha256: string;
134
+ /** The keeping door's own reference: an attachment id, a record id. */
135
+ ref: string;
136
+ }
137
+ /** What a receiver is told about the item it is handed. */
138
+ export interface ReceiveInfo {
139
+ runId: string;
140
+ /** The file the item came from. */
141
+ source: {
142
+ name: string;
143
+ sha256: string;
144
+ };
145
+ /** The shims the item passed through, in order. */
146
+ chain: string[];
147
+ citation?: IceCitation;
148
+ original?: KeptOriginal;
149
+ }
150
+ /** A receiver's answer for one item. `refused` is its existing permission saying no (D5). */
151
+ export interface ReceiveOutcome {
152
+ status: 'stored' | 'duplicate' | 'refused';
153
+ /** Where it went: a page name, an attachment id, a record id. */
154
+ ref?: string;
155
+ message?: string;
156
+ }
157
+ /**
158
+ * A receiver as its owner writes it (D4). Its doors are the receiver's own
159
+ * existing ones; each checks its own permission with the context given (D5).
160
+ */
161
+ export interface IceReceiver {
162
+ name: string;
163
+ label?: string;
164
+ /** The kinds it takes, e.g. `['ncm']`, `['file']`, `['phr.health-record']`. */
165
+ accepts: IceKind[];
166
+ /** May this context use this receiver? Its existing permission — the import screen shows only these (D5). */
167
+ mayUse(ctx: ActorContext): Promise<boolean>;
168
+ /** Hand one item to the receiver's own door. */
169
+ receive(item: IceItem, ctx: ActorContext, info: ReceiveInfo): Promise<ReceiveOutcome>;
170
+ /**
171
+ * Keep the original file itself (D11: phr keeps originals in its own
172
+ * store). Without this, `keep` hands the original to the files receiver.
173
+ */
174
+ keepOriginal?(original: IceItem, ctx: ActorContext): Promise<ReceiveOutcome>;
175
+ }
176
+ export interface RegisteredReceiver extends IceReceiver {
177
+ id: string;
178
+ owner: string;
179
+ }
180
+ /** One file handed to the engine. A `.zip` is unpacked by the engine. */
181
+ export interface IceUpload {
182
+ name: string;
183
+ bytes: Buffer;
184
+ mediaType?: string;
185
+ }
186
+ /**
187
+ * A source (D1). The first slice reads uploads; a URL fetched on a schedule
188
+ * (D10, feeds) and a server folder join this union later.
189
+ */
190
+ export type IceSource = {
191
+ type: 'upload';
192
+ files: IceUpload[];
193
+ };
194
+ /** One import, as a caller asks for it. */
195
+ export interface IceRunRequest {
196
+ source: IceSource;
197
+ /** The receiver id the results go to: `core.pages`, `phr.health-records`. */
198
+ receiver: string;
199
+ /** Pin the first shim (a format the person chose) instead of detecting one. */
200
+ shim?: string;
201
+ /** D11. Default `ngdpbase.import.engine.default-original`. */
202
+ original?: OriginalChoice;
203
+ /**
204
+ * Whose fingerprints and item keys this run is checked against. Default
205
+ * `<receiver>/<username>`: the same file imported again by the same person
206
+ * into the same receiver is skipped. A caller with its own notion of a
207
+ * source (phr's source id) passes it.
208
+ */
209
+ scope?: string;
210
+ }
211
+ /** Per-file status (first slice). */
212
+ export type IceFileStatus = 'imported' | 'partial' | 'unchanged' | 'duplicate' | 'noise' | 'unreadable' | 'refused' | 'failed';
213
+ export interface IceFileReport {
214
+ name: string;
215
+ sha256?: string;
216
+ size: number;
217
+ status: IceFileStatus;
218
+ message?: string;
219
+ /** The shims the file went through. */
220
+ chain: string[];
221
+ /** Where each item went. */
222
+ refs: string[];
223
+ /** Items stored, and items skipped as already seen. */
224
+ stored: number;
225
+ duplicates: number;
226
+ original?: KeptOriginal;
227
+ warnings: IceWarning[];
228
+ }
229
+ export interface IceRunReport {
230
+ runId: string;
231
+ receiver: string;
232
+ scope: string;
233
+ /** Who it ran as. */
234
+ username: string;
235
+ state: 'queued' | 'running' | 'done' | 'failed';
236
+ startedAt?: string;
237
+ finishedAt?: string;
238
+ error?: string;
239
+ files: IceFileReport[];
240
+ }
241
+ /** What the engine remembers about one file in a scope. */
242
+ export interface LedgerFileEntry {
243
+ name: string;
244
+ sha256: string;
245
+ size: number;
246
+ status: IceFileStatus;
247
+ message?: string;
248
+ at: string;
249
+ refs: string[];
250
+ }
251
+ /**
252
+ * Where the engine keeps fingerprints, per-file status and item keys, per
253
+ * scope. One interface so a database table can replace the file store when
254
+ * the application database is on.
255
+ */
256
+ export interface IceLedger {
257
+ lastFile(scope: string, sha256: string): Promise<LedgerFileEntry | null>;
258
+ recordFile(scope: string, entry: LedgerFileEntry): Promise<void>;
259
+ hasItem(scope: string, itemKey: string): Promise<boolean>;
260
+ recordItem(scope: string, itemKey: string): Promise<void>;
261
+ files(scope: string): Promise<LedgerFileEntry[]>;
262
+ }
@@ -20,7 +20,22 @@ export interface MailMessage {
20
20
  text: string;
21
21
  /** Optional HTML body */
22
22
  html?: string;
23
+ /** Files sent with the message (#1974); their total is capped by `ngdpbase.mail.attachments.max-bytes`. */
24
+ attachments?: MailAttachment[];
23
25
  }
26
+ /**
27
+ * One file attached to a message (#1974), as Nodemailer takes it. The content
28
+ * is never logged: a log line says how many files and how many bytes.
29
+ */
30
+ export interface MailAttachment {
31
+ /** The name the recipient sees, e.g. `invoice-2026-0042.pdf`. */
32
+ filename: string;
33
+ /** Its media type, e.g. `application/pdf`. */
34
+ contentType: string;
35
+ content: Buffer;
36
+ }
37
+ /** How many files and bytes a message carries — the only thing a log line says about attachments. */
38
+ export declare function describeAttachments(attachments: MailAttachment[] | undefined): string;
24
39
  /**
25
40
  * Common interface for all mail transports.
26
41
  */
@@ -9,7 +9,7 @@
9
9
  * ngdpbase.mail.provider.smtp.pass
10
10
  * ngdpbase.mail.provider.smtp.from
11
11
  */
12
- import type { MailMessage, MailProvider } from './MailProvider.js';
12
+ import { type MailMessage, type MailProvider } from './MailProvider.js';
13
13
  export interface SmtpConfig {
14
14
  host: string;
15
15
  port: number;
@@ -11,12 +11,14 @@
11
11
  * @see {@link https://github.com/jwilleke/ngdpbase/issues/158}
12
12
  */
13
13
  import { type ActorContext } from '../context/ActorContext.js';
14
+ import type { BackupFolder } from './BaseManager.js';
14
15
  import BaseManager from './BaseManager.js';
15
16
  import type { BackupData } from './BaseManager.js';
16
17
  import type { WikiEngine } from '../types/WikiEngine.js';
17
18
  import type { User } from '../types/User.js';
18
19
  import { type StoreOwnerState } from '../utils/privateStoreDoor.js';
19
20
  import { type AddonHost } from '../utils/addonHost.js';
21
+ import { ConsentRequiredError } from '../types/Consent.js';
20
22
  /**
21
23
  * Type passed to `AddonModule.profileSection()` (#534). Matches what
22
24
  * `UserManager.getUser()` returns at runtime — `User` minus the password
@@ -76,6 +78,14 @@ export interface AddonModule {
76
78
  * frozen. An add-on that takes two arguments keeps working until it moves.
77
79
  */
78
80
  register(engine: WikiEngine, config: Record<string, unknown>, host?: AddonHost): Promise<void> | void;
81
+ /**
82
+ * Folders it keeps data in besides its `dataPath` (#1985), given its
83
+ * configuration. Its `dataPath` is backed up and restored without being
84
+ * declared; an add-on declares only further folders, and writes no backup
85
+ * code. BackupManager archives each one, stages it in a site restore, and
86
+ * puts it in place before `register()` runs at the next start.
87
+ */
88
+ backupFolders?(config: Record<string, unknown>): BackupFolder[];
79
89
  /**
80
90
  * Optional health check returning add-on status details.
81
91
  */
@@ -228,6 +238,19 @@ export interface AddonManifest {
228
238
  family?: string;
229
239
  /** #1965: `false` keeps plumbing (e.g. elasticsearch) out of the add-on listings. */
230
240
  listed?: boolean;
241
+ /**
242
+ * #1979 (ICE, D6): the names of the import shims this add-on registers at
243
+ * load with `host.registerShim`, e.g. `["ccda", "fhir"]` (ids `<slug>.ccda`,
244
+ * `<slug>.fhir`). The host refuses a shim not named here. Site configuration
245
+ * switches each one: `ngdpbase.import.shims.<slug>.<name>.enabled`.
246
+ */
247
+ shims?: string[];
248
+ /**
249
+ * #1979 (ICE, D4): the names of the receivers this add-on registers with
250
+ * `host.registerReceiver` — its own manager's door for what shims produce,
251
+ * e.g. `["health-records"]`. The host refuses a receiver not named here.
252
+ */
253
+ receivers?: string[];
231
254
  }
232
255
  /**
233
256
  * One add-on as the listings show it (#1965), from `AddonsManager.listedAddons()`.
@@ -464,6 +487,20 @@ declare class AddonsManager extends BaseManager {
464
487
  * not registered yet says nothing about whether it still provides it.
465
488
  */
466
489
  addonsLoaded(): boolean;
490
+ /**
491
+ * An add-on's folders (#1985): its `dataPath` — `ngdpbase.addons.<slug>.dataPath`,
492
+ * or `<FAST_STORAGE>/<slug>` when that is not set, as the bundled add-ons
493
+ * read it — under the part name of its slug, then any further folders its
494
+ * module declares. A `dataPath` that is the instance data folder, or holds
495
+ * it, is never one: a restore would swap the whole site's data.
496
+ */
497
+ private addonFolders;
498
+ /** Each loaded add-on's `dataPath` and declared folders (#1985), in load order: what BackupManager backs up for it. */
499
+ addonBackupFolders(): Array<{
500
+ slug: string;
501
+ dataPath: string | null;
502
+ folders: BackupFolder[];
503
+ }>;
467
504
  /**
468
505
  * Get add-on specific configuration
469
506
  */
@@ -671,16 +708,31 @@ declare class AddonsManager extends BaseManager {
671
708
  *
672
709
  * Errors are caught per-addon and logged so one bad addon cannot block
673
710
  * other addons' saves or the core-preferences save.
711
+ *
712
+ * #1603: an add-on whose switch was refused because its documents are not
713
+ * accepted yet (`ConsentRequiredError`) is returned, so the route can tell
714
+ * the person what to accept instead of the save failing silently.
674
715
  */
675
- saveProfileSections(ctx: ActorContext, body: Record<string, unknown>): Promise<void>;
716
+ saveProfileSections(ctx: ActorContext, body: Record<string, unknown>): Promise<{
717
+ consentRequired: ConsentRequiredError[];
718
+ }>;
676
719
  /**
677
720
  * The add-ons the site's listings show (#1965): enabled, and not
678
721
  * `listed: false` in their manifest, in load order. Cheap: it calls no
679
722
  * add-on's status(), so a page can render it.
680
723
  */
681
724
  listedAddons(): AddonListing[];
682
- /** #1963: the loaded add-ons whose manifest says `perPerson: true`, in load order. */
683
- private perPersonAddons;
725
+ /**
726
+ * Whether `slug` is an add-on whose manifest says `perPerson: true` (#1963),
727
+ * loaded or still loading. ConsentManager asks it when an add-on registers
728
+ * documents: they guard the per-person switch, so only such an add-on has any.
729
+ */
730
+ isPerPerson(slug: string): boolean;
731
+ /**
732
+ * #1963: the loaded add-ons whose manifest says `perPerson: true`, in load
733
+ * order — every slug an `addon:<slug>` page audience can match (#1964).
734
+ */
735
+ perPersonAddons(): string[];
684
736
  /**
685
737
  * The per-person add-ons this subject has turned on (#1963): each loaded
686
738
  * add-on whose manifest says `perPerson: true` and whose switch, the
@@ -1,6 +1,5 @@
1
- import BaseManager, { BackupData, type ManagerBackupOptions, type ManagerRestoreOptions, type ManagerStats } from './BaseManager.js';
1
+ import BaseManager, { BackupData, type BackupArchiveTarget, type ManagerBackupOptions, type ManagerRestoreOptions, type ManagerStats, type SiteRestoreStaging, type StagedRestoreAtStart } from './BaseManager.js';
2
2
  import type { AttachmentFilesBackupData, AttachmentFilesBackupOutcome } from '../providers/attachmentFilesBackup.js';
3
- import type { PartOutcome } from '../utils/siteRestore.js';
4
3
  import { type ActorContext } from '../context/ActorContext.js';
5
4
  /**
6
5
  * Marks an error as "the audit record could not be written", not "the action
@@ -36,11 +35,11 @@ interface BaseAttachmentProvider {
36
35
  backup(): Promise<unknown>;
37
36
  restore(backupData: unknown): Promise<void>;
38
37
  /** #1876: the files themselves beside the backup document, and their staged restore. */
39
- backupFiles?(directory: string, stem: string): Promise<AttachmentFilesBackupOutcome>;
40
- stageFilesRestore?(providerBackup: Record<string, unknown>, files: AttachmentFilesBackupData, directory: string, siteRestore: string): Promise<{
38
+ backupFiles?(archive: (part: string) => BackupArchiveTarget): Promise<AttachmentFilesBackupOutcome>;
39
+ stageFilesRestore?(providerBackup: Record<string, unknown>, files: AttachmentFilesBackupData, readArchive: NonNullable<ManagerRestoreOptions['readArchive']>, siteRestore: SiteRestoreStaging): Promise<{
41
40
  skippedVaults: string[];
42
41
  }>;
43
- takeRestoreAtStart?(): PartOutcome | null;
42
+ takeRestoreAtStart?(): StagedRestoreAtStart | null;
44
43
  shutdown(): Promise<void>;
45
44
  getProviderInfo(): {
46
45
  features: string[];