@hollware/core 0.9.1 → 0.11.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/dist/index.d.mts CHANGED
@@ -315,11 +315,18 @@ interface SiteDefinition {
315
315
  /** The Worker secret that signs; Hollware's own sealed one when it is left out. */
316
316
  readonly secret?: string;
317
317
  }[];
318
- /** Tells IndexNow the URLs that changed; `key` names the Worker secret with the key. */
318
+ /** Tells IndexNow the URLs that changed; `key` is the key itself, which is public. */
319
319
  readonly indexNow?: {
320
320
  readonly key: string;
321
321
  };
322
322
  };
323
+ /** What the site's activity log keeps (ADR-037): no addresses, and forever, by default. */
324
+ readonly audit?: {
325
+ /** `hashed` keeps a keyed hash of the address of each request; `off` keeps nothing of it. */
326
+ readonly ipAddresses?: 'off' | 'hashed';
327
+ /** How many days a line is kept, 30 to 3650; `null` keeps the log as long as the site. */
328
+ readonly retentionDays?: number | null;
329
+ };
323
330
  }
324
331
  /** What `hollware.config.ts` exports. */
325
332
  interface HollwareConfig {
@@ -369,6 +376,12 @@ interface ResolvedSite {
369
376
  readonly origins: readonly string[];
370
377
  };
371
378
  readonly events: ResolvedEvents;
379
+ readonly audit: ResolvedAudit;
380
+ }
381
+ /** What the activity log of a site keeps (ADR-037). */
382
+ interface ResolvedAudit {
383
+ readonly ipAddresses: 'off' | 'hashed';
384
+ readonly retentionDays: number | null;
372
385
  }
373
386
  /**
374
387
  * A webhook of a site. `secret` names the Worker secret that signs its deliveries; `null` when the
@@ -442,6 +455,22 @@ export declare class ConfigError extends Error {
442
455
  constructor(problems: readonly ConfigProblem[]);
443
456
  }
444
457
  //#endregion
458
+ //#region src/config/events.d.ts
459
+ /**
460
+ * An IndexNow key, which is public by design (search engines fetch it at `/<key>.txt`): the
461
+ * definition holds the key itself, never the name of a Worker secret, so no value of the Worker
462
+ * can be sent to IndexNow (T-69 of docs/security/threat-model.md).
463
+ */
464
+ export declare const INDEXNOW_KEY: RegExp;
465
+ //#endregion
466
+ //#region src/config/audit.d.ts
467
+ /** The fewest days a site may keep its activity log for, when it sets a retention (ADR-037). */
468
+ export declare const AUDIT_RETENTION_MIN_DAYS = 30;
469
+ /** The most days a retention may be: ten years. Beyond that, keep it with no retention. */
470
+ export declare const AUDIT_RETENTION_MAX_DAYS = 3650;
471
+ /** What a site that says nothing keeps: no addresses, and the log for as long as the site exists. */
472
+ export declare const DEFAULT_AUDIT: ResolvedAudit;
473
+ //#endregion
445
474
  //#region src/config/constants.d.ts
446
475
  /** The largest Markdown file a collection accepts when its config does not say, 512 KiB. */
447
476
  export declare const DEFAULT_MAX_MARKDOWN_BYTES = 524288;
@@ -541,6 +570,7 @@ declare const entrySummary: z.ZodObject<{
541
570
  hasUnpublishedChanges: z.ZodBoolean;
542
571
  publishedAt: z.ZodNullable<z.ZodString>;
543
572
  scheduledAt: z.ZodNullable<z.ZodString>;
573
+ deletedAt: z.ZodNullable<z.ZodString>;
544
574
  updatedAt: z.ZodString;
545
575
  }, z.core.$strip>;
546
576
  declare const publication: z.ZodObject<{
@@ -604,6 +634,7 @@ declare const entry: z.ZodObject<{
604
634
  hasUnpublishedChanges: z.ZodBoolean;
605
635
  publishedAt: z.ZodNullable<z.ZodString>;
606
636
  scheduledAt: z.ZodNullable<z.ZodString>;
637
+ deletedAt: z.ZodNullable<z.ZodString>;
607
638
  updatedAt: z.ZodString;
608
639
  revision: z.ZodString;
609
640
  verdict: z.ZodObject<{
@@ -1114,6 +1145,34 @@ export declare const SITE_KEY_MAX_LENGTH = 64;
1114
1145
  /** Whether a value is a site key: a string that fits `SITE_KEY_PATTERN` and is not too long. */
1115
1146
  export declare function isSiteKey(value: unknown): value is string;
1116
1147
  //#endregion
1148
+ //#region src/audit/index.d.ts
1149
+ /**
1150
+ * The actions of the activity log (ADR-037). A line names one of these, and nothing else: a new
1151
+ * operation or route that changes something is not logged until it is named here.
1152
+ */
1153
+ /** Every operation that is not a read: each call of one is a line, whatever its outcome. */
1154
+ export declare const OPERATION_AUDIT_ACTIONS: readonly ['create_draft', 'update_draft', 'publish', 'unpublish', 'delete_entry', 'restore_entry', 'approve_review', 'request_review', 'comment_review', 'request_changes', 'update_site', 'set_collection', 'create_site', 'delete_site', 'restore_site', 'make_webhook_secret'];
1155
+ /** What people do outside the operations: their tokens, members, passkeys, sessions and apps. */
1156
+ export declare const IDENTITY_AUDIT_ACTIONS: readonly ['token.create',
1157
+ /** A person asked for a link that shows an entry's latest revision on the site (T-103). */
1158
+ 'preview.create', 'token.revoke', 'member.role', 'member.remove', 'invitation.create', 'invitation.accept', 'session.sign_in', 'session.sign_out', 'session.end_all', 'passkey.remove', 'app.allow', 'app.revoke',
1159
+ /** A refresh token was used again after it was spent, so its grant was revoked (T-34). */
1160
+ 'app.refresh_reused',
1161
+ /** The cron published an entry whose time had come, for the person who scheduled it. */
1162
+ 'schedule.publish'];
1163
+ export declare const AUDIT_ACTIONS: readonly ["create_draft", "update_draft", "publish", "unpublish", "delete_entry", "restore_entry", "approve_review", "request_review", "comment_review", "request_changes", "update_site", "set_collection", "create_site", "delete_site", "restore_site", "make_webhook_secret", "token.create", "preview.create", "token.revoke", "member.role", "member.remove", "invitation.create", "invitation.accept", "session.sign_in", "session.sign_out", "session.end_all", "passkey.remove", "app.allow", "app.revoke", "app.refresh_reused", "schedule.publish"];
1164
+ export type AuditAction = (typeof AUDIT_ACTIONS)[number];
1165
+ /** `denied`: a scope or a role was missing; `failed`: any other error the caller got. */
1166
+ export declare const AUDIT_OUTCOMES: readonly ['ok', 'denied', 'failed'];
1167
+ export type AuditOutcome = (typeof AUDIT_OUTCOMES)[number];
1168
+ /**
1169
+ * Who acted: a person in the admin, a personal token, an app a person allowed through OAuth, or
1170
+ * the deployment itself (its cron).
1171
+ */
1172
+ export declare const AUDIT_ACTOR_KINDS: readonly ['user', 'token', 'oauth_client', 'system'];
1173
+ export type AuditActorKind = (typeof AUDIT_ACTOR_KINDS)[number];
1174
+ export declare function isAuditAction(value: string): value is AuditAction;
1175
+ //#endregion
1117
1176
  //#region src/structure/compile.d.ts
1118
1177
  /** The definitions of the sites, read from D1 as JSON, checked and resolved. */
1119
1178
  export declare function compileSites(definitions: Readonly<Record<string, unknown>>): ResolvedConfig;
@@ -1179,6 +1238,13 @@ export declare const siteDefinitionData: z.ZodObject<{
1179
1238
  key: z.ZodString;
1180
1239
  }, z.core.$strict>>>;
1181
1240
  }, z.core.$strict>>;
1241
+ audit: z.ZodDefault<z.ZodObject<{
1242
+ ipAddresses: z.ZodDefault<z.ZodEnum<{
1243
+ hashed: "hashed";
1244
+ off: "off";
1245
+ }>>;
1246
+ retentionDays: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
1247
+ }, z.core.$strict>>;
1182
1248
  collections: z.ZodRecord<z.ZodString, z.ZodObject<{
1183
1249
  schema: z.ZodRecord<z.ZodString, z.ZodUnknown>;
1184
1250
  routes: z.ZodRecord<z.ZodString, z.ZodString>;
@@ -1253,6 +1319,8 @@ export declare const ERROR_CODES: readonly [
1253
1319
  'unknown_collection',
1254
1320
  /** The input names a locale the site does not have. */
1255
1321
  'unknown_locale',
1322
+ /** A preview link that has expired, or is not one Hollware made for this site (T-103). */
1323
+ 'invalid_preview',
1256
1324
  /** The token lacks a scope the operation requires; the message names every missing scope. */
1257
1325
  'insufficient_scope',
1258
1326
  /** The answer would exceed the output cap. Hollware never truncates content. */
@@ -1283,6 +1351,7 @@ export declare class HollwareError extends Error {
1283
1351
  */
1284
1352
  /** The kinds of ids and their prefixes. A new kind adds its prefix here. */
1285
1353
  export declare const ID_PREFIXES: {
1354
+ readonly auditLine: 'aud';
1286
1355
  readonly challenge: 'chl';
1287
1356
  readonly delivery: 'dlv';
1288
1357
  readonly embedding: 'emb';
@@ -1454,6 +1523,7 @@ export declare const listEntries: OperationSpec<"list_entries", z.ZodObject<{
1454
1523
  published: "published";
1455
1524
  scheduled: "scheduled";
1456
1525
  }>>;
1526
+ trashed: z.ZodOptional<z.ZodBoolean>;
1457
1527
  limit: z.ZodDefault<z.ZodNumber>;
1458
1528
  cursor: z.ZodOptional<z.ZodString>;
1459
1529
  }, z.core.$strict>, z.ZodObject<{
@@ -1477,6 +1547,7 @@ export declare const listEntries: OperationSpec<"list_entries", z.ZodObject<{
1477
1547
  hasUnpublishedChanges: z.ZodBoolean;
1478
1548
  publishedAt: z.ZodNullable<z.ZodString>;
1479
1549
  scheduledAt: z.ZodNullable<z.ZodString>;
1550
+ deletedAt: z.ZodNullable<z.ZodString>;
1480
1551
  updatedAt: z.ZodString;
1481
1552
  }, z.core.$strip>>;
1482
1553
  nextCursor: z.ZodNullable<z.ZodString>;
@@ -1518,6 +1589,7 @@ export declare const search: OperationSpec<"search", z.ZodObject<{
1518
1589
  hasUnpublishedChanges: z.ZodBoolean;
1519
1590
  publishedAt: z.ZodNullable<z.ZodString>;
1520
1591
  scheduledAt: z.ZodNullable<z.ZodString>;
1592
+ deletedAt: z.ZodNullable<z.ZodString>;
1521
1593
  updatedAt: z.ZodString;
1522
1594
  }, z.core.$strip>;
1523
1595
  snippet: z.ZodString;
@@ -1557,6 +1629,7 @@ export declare const getEntry: OperationSpec<"get_entry", z.ZodObject<{
1557
1629
  hasUnpublishedChanges: z.ZodBoolean;
1558
1630
  publishedAt: z.ZodNullable<z.ZodString>;
1559
1631
  scheduledAt: z.ZodNullable<z.ZodString>;
1632
+ deletedAt: z.ZodNullable<z.ZodString>;
1560
1633
  updatedAt: z.ZodString;
1561
1634
  revision: z.ZodString;
1562
1635
  verdict: z.ZodObject<{
@@ -1652,6 +1725,7 @@ export declare const getEntry: OperationSpec<"get_entry", z.ZodObject<{
1652
1725
  hasUnpublishedChanges: z.ZodBoolean;
1653
1726
  publishedAt: z.ZodNullable<z.ZodString>;
1654
1727
  scheduledAt: z.ZodNullable<z.ZodString>;
1728
+ deletedAt: z.ZodNullable<z.ZodString>;
1655
1729
  updatedAt: z.ZodString;
1656
1730
  }, z.core.$strip>>>;
1657
1731
  }, z.core.$strip>>;
@@ -1680,6 +1754,7 @@ export declare const getTranslations: OperationSpec<"get_translations", z.ZodObj
1680
1754
  hasUnpublishedChanges: z.ZodBoolean;
1681
1755
  publishedAt: z.ZodNullable<z.ZodString>;
1682
1756
  scheduledAt: z.ZodNullable<z.ZodString>;
1757
+ deletedAt: z.ZodNullable<z.ZodString>;
1683
1758
  updatedAt: z.ZodString;
1684
1759
  }, z.core.$strip>>>;
1685
1760
  }, z.core.$strip>>;
@@ -1690,6 +1765,7 @@ export declare const createDraft: OperationSpec<"create_draft", z.ZodObject<{
1690
1765
  markdown: z.ZodString;
1691
1766
  }, z.core.$strict>, z.ZodObject<{
1692
1767
  outcome: z.ZodEnum<{
1768
+ in_trash: "in_trash";
1693
1769
  refused: "refused";
1694
1770
  saved: "saved";
1695
1771
  }>;
@@ -1710,6 +1786,7 @@ export declare const createDraft: OperationSpec<"create_draft", z.ZodObject<{
1710
1786
  hasUnpublishedChanges: z.ZodBoolean;
1711
1787
  publishedAt: z.ZodNullable<z.ZodString>;
1712
1788
  scheduledAt: z.ZodNullable<z.ZodString>;
1789
+ deletedAt: z.ZodNullable<z.ZodString>;
1713
1790
  updatedAt: z.ZodString;
1714
1791
  }, z.core.$strip>>;
1715
1792
  verdict: z.ZodOptional<z.ZodObject<{
@@ -1772,6 +1849,7 @@ export declare const updateDraft: OperationSpec<"update_draft", z.ZodObject<{
1772
1849
  hasUnpublishedChanges: z.ZodBoolean;
1773
1850
  publishedAt: z.ZodNullable<z.ZodString>;
1774
1851
  scheduledAt: z.ZodNullable<z.ZodString>;
1852
+ deletedAt: z.ZodNullable<z.ZodString>;
1775
1853
  updatedAt: z.ZodString;
1776
1854
  }, z.core.$strip>>;
1777
1855
  verdict: z.ZodOptional<z.ZodObject<{
@@ -1888,6 +1966,7 @@ export declare const publish: OperationSpec<"publish", z.ZodObject<{
1888
1966
  hasUnpublishedChanges: z.ZodBoolean;
1889
1967
  publishedAt: z.ZodNullable<z.ZodString>;
1890
1968
  scheduledAt: z.ZodNullable<z.ZodString>;
1969
+ deletedAt: z.ZodNullable<z.ZodString>;
1891
1970
  updatedAt: z.ZodString;
1892
1971
  }, z.core.$strip>>;
1893
1972
  verdict: z.ZodOptional<z.ZodObject<{
@@ -1967,6 +2046,71 @@ export declare const unpublish: OperationSpec<"unpublish", z.ZodObject<{
1967
2046
  hasUnpublishedChanges: z.ZodBoolean;
1968
2047
  publishedAt: z.ZodNullable<z.ZodString>;
1969
2048
  scheduledAt: z.ZodNullable<z.ZodString>;
2049
+ deletedAt: z.ZodNullable<z.ZodString>;
2050
+ updatedAt: z.ZodString;
2051
+ }, z.core.$strip>>;
2052
+ }, z.core.$strip>>;
2053
+ export declare const deleteEntry: OperationSpec<"delete_entry", z.ZodObject<{
2054
+ id: z.ZodString;
2055
+ version: z.ZodNumber;
2056
+ }, z.core.$strict>, z.ZodObject<{
2057
+ outcome: z.ZodEnum<{
2058
+ conflict: "conflict";
2059
+ not_found: "not_found";
2060
+ published: "published";
2061
+ trashed: "trashed";
2062
+ }>;
2063
+ entry: z.ZodOptional<z.ZodObject<{
2064
+ id: z.ZodString;
2065
+ collection: z.ZodString;
2066
+ locale: z.ZodString;
2067
+ slug: z.ZodString;
2068
+ translationGroup: z.ZodNullable<z.ZodString>;
2069
+ status: z.ZodEnum<{
2070
+ draft: "draft";
2071
+ published: "published";
2072
+ scheduled: "scheduled";
2073
+ }>;
2074
+ version: z.ZodNumber;
2075
+ frontmatter: z.ZodRecord<z.ZodString, z.ZodUnknown>;
2076
+ tags: z.ZodArray<z.ZodString>;
2077
+ hasUnpublishedChanges: z.ZodBoolean;
2078
+ publishedAt: z.ZodNullable<z.ZodString>;
2079
+ scheduledAt: z.ZodNullable<z.ZodString>;
2080
+ deletedAt: z.ZodNullable<z.ZodString>;
2081
+ updatedAt: z.ZodString;
2082
+ }, z.core.$strip>>;
2083
+ conflict: z.ZodOptional<z.ZodObject<{
2084
+ currentVersion: z.ZodNumber;
2085
+ headRevision: z.ZodString;
2086
+ }, z.core.$strip>>;
2087
+ }, z.core.$strip>>;
2088
+ export declare const restoreEntry: OperationSpec<"restore_entry", z.ZodObject<{
2089
+ id: z.ZodString;
2090
+ }, z.core.$strict>, z.ZodObject<{
2091
+ outcome: z.ZodEnum<{
2092
+ not_found: "not_found";
2093
+ not_trashed: "not_trashed";
2094
+ restored: "restored";
2095
+ }>;
2096
+ entry: z.ZodOptional<z.ZodObject<{
2097
+ id: z.ZodString;
2098
+ collection: z.ZodString;
2099
+ locale: z.ZodString;
2100
+ slug: z.ZodString;
2101
+ translationGroup: z.ZodNullable<z.ZodString>;
2102
+ status: z.ZodEnum<{
2103
+ draft: "draft";
2104
+ published: "published";
2105
+ scheduled: "scheduled";
2106
+ }>;
2107
+ version: z.ZodNumber;
2108
+ frontmatter: z.ZodRecord<z.ZodString, z.ZodUnknown>;
2109
+ tags: z.ZodArray<z.ZodString>;
2110
+ hasUnpublishedChanges: z.ZodBoolean;
2111
+ publishedAt: z.ZodNullable<z.ZodString>;
2112
+ scheduledAt: z.ZodNullable<z.ZodString>;
2113
+ deletedAt: z.ZodNullable<z.ZodString>;
1970
2114
  updatedAt: z.ZodString;
1971
2115
  }, z.core.$strip>>;
1972
2116
  }, z.core.$strip>>;
@@ -2015,6 +2159,7 @@ export declare const listReviews: OperationSpec<"list_reviews", z.ZodObject<{
2015
2159
  hasUnpublishedChanges: z.ZodBoolean;
2016
2160
  publishedAt: z.ZodNullable<z.ZodString>;
2017
2161
  scheduledAt: z.ZodNullable<z.ZodString>;
2162
+ deletedAt: z.ZodNullable<z.ZodString>;
2018
2163
  updatedAt: z.ZodString;
2019
2164
  }, z.core.$strip>;
2020
2165
  comments: z.ZodArray<z.ZodObject<{
@@ -2075,6 +2220,7 @@ export declare const approveReview: OperationSpec<"approve_review", z.ZodObject<
2075
2220
  hasUnpublishedChanges: z.ZodBoolean;
2076
2221
  publishedAt: z.ZodNullable<z.ZodString>;
2077
2222
  scheduledAt: z.ZodNullable<z.ZodString>;
2223
+ deletedAt: z.ZodNullable<z.ZodString>;
2078
2224
  updatedAt: z.ZodString;
2079
2225
  }, z.core.$strip>>;
2080
2226
  verdict: z.ZodOptional<z.ZodObject<{
@@ -2140,6 +2286,7 @@ export declare const requestReview: OperationSpec<"request_review", z.ZodObject<
2140
2286
  hasUnpublishedChanges: z.ZodBoolean;
2141
2287
  publishedAt: z.ZodNullable<z.ZodString>;
2142
2288
  scheduledAt: z.ZodNullable<z.ZodString>;
2289
+ deletedAt: z.ZodNullable<z.ZodString>;
2143
2290
  updatedAt: z.ZodString;
2144
2291
  }, z.core.$strip>>;
2145
2292
  verdict: z.ZodOptional<z.ZodObject<{
@@ -2268,6 +2415,7 @@ export declare const contentStats: OperationSpec<"content_stats", z.ZodObject<{
2268
2415
  hasUnpublishedChanges: z.ZodBoolean;
2269
2416
  publishedAt: z.ZodNullable<z.ZodString>;
2270
2417
  scheduledAt: z.ZodNullable<z.ZodString>;
2418
+ deletedAt: z.ZodNullable<z.ZodString>;
2271
2419
  updatedAt: z.ZodString;
2272
2420
  }, z.core.$strip>>;
2273
2421
  }, z.core.$strip>>>;
@@ -2321,6 +2469,7 @@ export declare const OPERATIONS: readonly [OperationSpec<"approve_review", z.Zod
2321
2469
  hasUnpublishedChanges: z.ZodBoolean;
2322
2470
  publishedAt: z.ZodNullable<z.ZodString>;
2323
2471
  scheduledAt: z.ZodNullable<z.ZodString>;
2472
+ deletedAt: z.ZodNullable<z.ZodString>;
2324
2473
  updatedAt: z.ZodString;
2325
2474
  }, z.core.$strip>>;
2326
2475
  verdict: z.ZodOptional<z.ZodObject<{
@@ -2399,6 +2548,7 @@ export declare const OPERATIONS: readonly [OperationSpec<"approve_review", z.Zod
2399
2548
  hasUnpublishedChanges: z.ZodBoolean;
2400
2549
  publishedAt: z.ZodNullable<z.ZodString>;
2401
2550
  scheduledAt: z.ZodNullable<z.ZodString>;
2551
+ deletedAt: z.ZodNullable<z.ZodString>;
2402
2552
  updatedAt: z.ZodString;
2403
2553
  }, z.core.$strip>>;
2404
2554
  }, z.core.$strip>>>;
@@ -2409,6 +2559,7 @@ export declare const OPERATIONS: readonly [OperationSpec<"approve_review", z.Zod
2409
2559
  markdown: z.ZodString;
2410
2560
  }, z.core.$strict>, z.ZodObject<{
2411
2561
  outcome: z.ZodEnum<{
2562
+ in_trash: "in_trash";
2412
2563
  refused: "refused";
2413
2564
  saved: "saved";
2414
2565
  }>;
@@ -2429,6 +2580,7 @@ export declare const OPERATIONS: readonly [OperationSpec<"approve_review", z.Zod
2429
2580
  hasUnpublishedChanges: z.ZodBoolean;
2430
2581
  publishedAt: z.ZodNullable<z.ZodString>;
2431
2582
  scheduledAt: z.ZodNullable<z.ZodString>;
2583
+ deletedAt: z.ZodNullable<z.ZodString>;
2432
2584
  updatedAt: z.ZodString;
2433
2585
  }, z.core.$strip>>;
2434
2586
  verdict: z.ZodOptional<z.ZodObject<{
@@ -2481,6 +2633,13 @@ export declare const OPERATIONS: readonly [OperationSpec<"approve_review", z.Zod
2481
2633
  key: z.ZodString;
2482
2634
  }, z.core.$strict>>>;
2483
2635
  }, z.core.$strict>>;
2636
+ audit: z.ZodDefault<z.ZodObject<{
2637
+ ipAddresses: z.ZodDefault<z.ZodEnum<{
2638
+ hashed: "hashed";
2639
+ off: "off";
2640
+ }>>;
2641
+ retentionDays: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
2642
+ }, z.core.$strict>>;
2484
2643
  collections: z.ZodRecord<z.ZodString, z.ZodObject<{
2485
2644
  schema: z.ZodRecord<z.ZodString, z.ZodUnknown>;
2486
2645
  routes: z.ZodRecord<z.ZodString, z.ZodString>;
@@ -2517,6 +2676,40 @@ export declare const OPERATIONS: readonly [OperationSpec<"approve_review", z.Zod
2517
2676
  message: z.ZodString;
2518
2677
  fix: z.ZodString;
2519
2678
  }, z.core.$strip>>>;
2679
+ }, z.core.$strip>>, OperationSpec<"delete_entry", z.ZodObject<{
2680
+ id: z.ZodString;
2681
+ version: z.ZodNumber;
2682
+ }, z.core.$strict>, z.ZodObject<{
2683
+ outcome: z.ZodEnum<{
2684
+ conflict: "conflict";
2685
+ not_found: "not_found";
2686
+ published: "published";
2687
+ trashed: "trashed";
2688
+ }>;
2689
+ entry: z.ZodOptional<z.ZodObject<{
2690
+ id: z.ZodString;
2691
+ collection: z.ZodString;
2692
+ locale: z.ZodString;
2693
+ slug: z.ZodString;
2694
+ translationGroup: z.ZodNullable<z.ZodString>;
2695
+ status: z.ZodEnum<{
2696
+ draft: "draft";
2697
+ published: "published";
2698
+ scheduled: "scheduled";
2699
+ }>;
2700
+ version: z.ZodNumber;
2701
+ frontmatter: z.ZodRecord<z.ZodString, z.ZodUnknown>;
2702
+ tags: z.ZodArray<z.ZodString>;
2703
+ hasUnpublishedChanges: z.ZodBoolean;
2704
+ publishedAt: z.ZodNullable<z.ZodString>;
2705
+ scheduledAt: z.ZodNullable<z.ZodString>;
2706
+ deletedAt: z.ZodNullable<z.ZodString>;
2707
+ updatedAt: z.ZodString;
2708
+ }, z.core.$strip>>;
2709
+ conflict: z.ZodOptional<z.ZodObject<{
2710
+ currentVersion: z.ZodNumber;
2711
+ headRevision: z.ZodString;
2712
+ }, z.core.$strip>>;
2520
2713
  }, z.core.$strip>>, OperationSpec<"delete_site", z.ZodObject<{
2521
2714
  key: z.ZodString & z.ZodType<string, string, z.core.$ZodTypeInternals<string, string>>;
2522
2715
  confirm: z.ZodDefault<z.ZodBoolean>;
@@ -2599,6 +2792,7 @@ export declare const OPERATIONS: readonly [OperationSpec<"approve_review", z.Zod
2599
2792
  hasUnpublishedChanges: z.ZodBoolean;
2600
2793
  publishedAt: z.ZodNullable<z.ZodString>;
2601
2794
  scheduledAt: z.ZodNullable<z.ZodString>;
2795
+ deletedAt: z.ZodNullable<z.ZodString>;
2602
2796
  updatedAt: z.ZodString;
2603
2797
  revision: z.ZodString;
2604
2798
  verdict: z.ZodObject<{
@@ -2694,6 +2888,7 @@ export declare const OPERATIONS: readonly [OperationSpec<"approve_review", z.Zod
2694
2888
  hasUnpublishedChanges: z.ZodBoolean;
2695
2889
  publishedAt: z.ZodNullable<z.ZodString>;
2696
2890
  scheduledAt: z.ZodNullable<z.ZodString>;
2891
+ deletedAt: z.ZodNullable<z.ZodString>;
2697
2892
  updatedAt: z.ZodString;
2698
2893
  }, z.core.$strip>>>;
2699
2894
  }, z.core.$strip>>, OperationSpec<"get_structure", z.ZodObject<{}, z.core.$strict>, z.ZodObject<{
@@ -2720,6 +2915,13 @@ export declare const OPERATIONS: readonly [OperationSpec<"approve_review", z.Zod
2720
2915
  key: z.ZodString;
2721
2916
  }, z.core.$strict>>>;
2722
2917
  }, z.core.$strict>>;
2918
+ audit: z.ZodDefault<z.ZodObject<{
2919
+ ipAddresses: z.ZodDefault<z.ZodEnum<{
2920
+ hashed: "hashed";
2921
+ off: "off";
2922
+ }>>;
2923
+ retentionDays: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
2924
+ }, z.core.$strict>>;
2723
2925
  collections: z.ZodRecord<z.ZodString, z.ZodObject<{
2724
2926
  schema: z.ZodRecord<z.ZodString, z.ZodUnknown>;
2725
2927
  routes: z.ZodRecord<z.ZodString, z.ZodString>;
@@ -2774,6 +2976,7 @@ export declare const OPERATIONS: readonly [OperationSpec<"approve_review", z.Zod
2774
2976
  hasUnpublishedChanges: z.ZodBoolean;
2775
2977
  publishedAt: z.ZodNullable<z.ZodString>;
2776
2978
  scheduledAt: z.ZodNullable<z.ZodString>;
2979
+ deletedAt: z.ZodNullable<z.ZodString>;
2777
2980
  updatedAt: z.ZodString;
2778
2981
  }, z.core.$strip>>>;
2779
2982
  }, z.core.$strip>>, OperationSpec<"list_entries", z.ZodObject<{
@@ -2785,6 +2988,7 @@ export declare const OPERATIONS: readonly [OperationSpec<"approve_review", z.Zod
2785
2988
  published: "published";
2786
2989
  scheduled: "scheduled";
2787
2990
  }>>;
2991
+ trashed: z.ZodOptional<z.ZodBoolean>;
2788
2992
  limit: z.ZodDefault<z.ZodNumber>;
2789
2993
  cursor: z.ZodOptional<z.ZodString>;
2790
2994
  }, z.core.$strict>, z.ZodObject<{
@@ -2808,6 +3012,7 @@ export declare const OPERATIONS: readonly [OperationSpec<"approve_review", z.Zod
2808
3012
  hasUnpublishedChanges: z.ZodBoolean;
2809
3013
  publishedAt: z.ZodNullable<z.ZodString>;
2810
3014
  scheduledAt: z.ZodNullable<z.ZodString>;
3015
+ deletedAt: z.ZodNullable<z.ZodString>;
2811
3016
  updatedAt: z.ZodString;
2812
3017
  }, z.core.$strip>>;
2813
3018
  nextCursor: z.ZodNullable<z.ZodString>;
@@ -2856,6 +3061,7 @@ export declare const OPERATIONS: readonly [OperationSpec<"approve_review", z.Zod
2856
3061
  hasUnpublishedChanges: z.ZodBoolean;
2857
3062
  publishedAt: z.ZodNullable<z.ZodString>;
2858
3063
  scheduledAt: z.ZodNullable<z.ZodString>;
3064
+ deletedAt: z.ZodNullable<z.ZodString>;
2859
3065
  updatedAt: z.ZodString;
2860
3066
  }, z.core.$strip>;
2861
3067
  comments: z.ZodArray<z.ZodObject<{
@@ -2915,6 +3121,7 @@ export declare const OPERATIONS: readonly [OperationSpec<"approve_review", z.Zod
2915
3121
  hasUnpublishedChanges: z.ZodBoolean;
2916
3122
  publishedAt: z.ZodNullable<z.ZodString>;
2917
3123
  scheduledAt: z.ZodNullable<z.ZodString>;
3124
+ deletedAt: z.ZodNullable<z.ZodString>;
2918
3125
  updatedAt: z.ZodString;
2919
3126
  }, z.core.$strip>>;
2920
3127
  verdict: z.ZodOptional<z.ZodObject<{
@@ -3027,6 +3234,7 @@ export declare const OPERATIONS: readonly [OperationSpec<"approve_review", z.Zod
3027
3234
  hasUnpublishedChanges: z.ZodBoolean;
3028
3235
  publishedAt: z.ZodNullable<z.ZodString>;
3029
3236
  scheduledAt: z.ZodNullable<z.ZodString>;
3237
+ deletedAt: z.ZodNullable<z.ZodString>;
3030
3238
  updatedAt: z.ZodString;
3031
3239
  }, z.core.$strip>>;
3032
3240
  verdict: z.ZodOptional<z.ZodObject<{
@@ -3080,6 +3288,34 @@ export declare const OPERATIONS: readonly [OperationSpec<"approve_review", z.Zod
3080
3288
  decidedAt: z.ZodNullable<z.ZodString>;
3081
3289
  note: z.ZodNullable<z.ZodString>;
3082
3290
  }, z.core.$strip>>;
3291
+ }, z.core.$strip>>, OperationSpec<"restore_entry", z.ZodObject<{
3292
+ id: z.ZodString;
3293
+ }, z.core.$strict>, z.ZodObject<{
3294
+ outcome: z.ZodEnum<{
3295
+ not_found: "not_found";
3296
+ not_trashed: "not_trashed";
3297
+ restored: "restored";
3298
+ }>;
3299
+ entry: z.ZodOptional<z.ZodObject<{
3300
+ id: z.ZodString;
3301
+ collection: z.ZodString;
3302
+ locale: z.ZodString;
3303
+ slug: z.ZodString;
3304
+ translationGroup: z.ZodNullable<z.ZodString>;
3305
+ status: z.ZodEnum<{
3306
+ draft: "draft";
3307
+ published: "published";
3308
+ scheduled: "scheduled";
3309
+ }>;
3310
+ version: z.ZodNumber;
3311
+ frontmatter: z.ZodRecord<z.ZodString, z.ZodUnknown>;
3312
+ tags: z.ZodArray<z.ZodString>;
3313
+ hasUnpublishedChanges: z.ZodBoolean;
3314
+ publishedAt: z.ZodNullable<z.ZodString>;
3315
+ scheduledAt: z.ZodNullable<z.ZodString>;
3316
+ deletedAt: z.ZodNullable<z.ZodString>;
3317
+ updatedAt: z.ZodString;
3318
+ }, z.core.$strip>>;
3083
3319
  }, z.core.$strip>>, OperationSpec<"restore_site", z.ZodObject<{
3084
3320
  key: z.ZodString & z.ZodType<string, string, z.core.$ZodTypeInternals<string, string>>;
3085
3321
  }, z.core.$strict>, z.ZodObject<{
@@ -3124,6 +3360,7 @@ export declare const OPERATIONS: readonly [OperationSpec<"approve_review", z.Zod
3124
3360
  hasUnpublishedChanges: z.ZodBoolean;
3125
3361
  publishedAt: z.ZodNullable<z.ZodString>;
3126
3362
  scheduledAt: z.ZodNullable<z.ZodString>;
3363
+ deletedAt: z.ZodNullable<z.ZodString>;
3127
3364
  updatedAt: z.ZodString;
3128
3365
  }, z.core.$strip>;
3129
3366
  snippet: z.ZodString;
@@ -3210,6 +3447,7 @@ export declare const OPERATIONS: readonly [OperationSpec<"approve_review", z.Zod
3210
3447
  hasUnpublishedChanges: z.ZodBoolean;
3211
3448
  publishedAt: z.ZodNullable<z.ZodString>;
3212
3449
  scheduledAt: z.ZodNullable<z.ZodString>;
3450
+ deletedAt: z.ZodNullable<z.ZodString>;
3213
3451
  updatedAt: z.ZodString;
3214
3452
  }, z.core.$strip>>;
3215
3453
  }, z.core.$strip>>, OperationSpec<"update_draft", z.ZodObject<{
@@ -3241,6 +3479,7 @@ export declare const OPERATIONS: readonly [OperationSpec<"approve_review", z.Zod
3241
3479
  hasUnpublishedChanges: z.ZodBoolean;
3242
3480
  publishedAt: z.ZodNullable<z.ZodString>;
3243
3481
  scheduledAt: z.ZodNullable<z.ZodString>;
3482
+ deletedAt: z.ZodNullable<z.ZodString>;
3244
3483
  updatedAt: z.ZodString;
3245
3484
  }, z.core.$strip>>;
3246
3485
  verdict: z.ZodOptional<z.ZodObject<{
@@ -3297,6 +3536,13 @@ export declare const OPERATIONS: readonly [OperationSpec<"approve_review", z.Zod
3297
3536
  key: z.ZodString;
3298
3537
  }, z.core.$strict>>>;
3299
3538
  }, z.core.$strict>>;
3539
+ audit: z.ZodDefault<z.ZodObject<{
3540
+ ipAddresses: z.ZodDefault<z.ZodEnum<{
3541
+ hashed: "hashed";
3542
+ off: "off";
3543
+ }>>;
3544
+ retentionDays: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
3545
+ }, z.core.$strict>>;
3300
3546
  collections: z.ZodRecord<z.ZodString, z.ZodObject<{
3301
3547
  schema: z.ZodRecord<z.ZodString, z.ZodUnknown>;
3302
3548
  routes: z.ZodRecord<z.ZodString, z.ZodString>;
@@ -3449,13 +3695,140 @@ export interface WebhookCheck {
3449
3695
  /** Now, in seconds since the epoch; the system clock when absent. */
3450
3696
  readonly now?: number;
3451
3697
  readonly toleranceSeconds?: number;
3698
+ /**
3699
+ * Whether the receiver sees this event for the first time, given its id, and records it (T-67):
3700
+ * a request captured and sent again within the tolerance is then refused. The id is read from
3701
+ * the signed body, never from `hollware-event-id`, which no signature covers. A retry of a
3702
+ * delivery carries the same id, so a receiver that records an id only once it has handled the
3703
+ * event lets a failed delivery be retried. Keep each id for longer than the tolerance.
3704
+ */
3705
+ readonly isNew?: (eventId: string) => boolean | Promise<boolean>;
3452
3706
  }
3453
3707
  /**
3454
3708
  * Whether a request is a webhook of Hollware: its signature matches the body and the secret, and
3455
- * its timestamp is within the tolerance, so a captured request cannot be replayed later.
3709
+ * its timestamp is within the tolerance, so a captured request cannot be replayed later; with
3710
+ * `isNew`, also that its event was not received before, so it cannot be replayed sooner either.
3456
3711
  */
3457
3712
  export declare function verifyWebhook(check: WebhookCheck): Promise<boolean>;
3458
3713
  //#endregion
3714
+ //#region src/preview.d.ts
3715
+ /**
3716
+ * The preview token (T-103 of docs/security/threat-model.md): a signed, stateless proof that a person of a site may read the
3717
+ * latest revision of one entry, for one hour. A site that reads published content only (the
3718
+ * binding of RPC, the read API) reads that entry's head instead when it presents one.
3719
+ *
3720
+ * hw_prv_<payload>.<signature>
3721
+ *
3722
+ * The payload is base64url of `{ "s": site, "e": entryId, "x": expiresAtSeconds }`, and the
3723
+ * signature the base64url HMAC-SHA256 of the payload text under a key that HKDF-SHA256 derives
3724
+ * from the Worker secret `HOLLWARE_SECRET`, bound to the site. Nothing is stored: a token cannot
3725
+ * be revoked, only wait out its hour, and rotating the secret ends every one.
3726
+ */
3727
+ export declare const PREVIEW_TOKEN_PREFIX = "hw_prv_";
3728
+ /** The query parameter a site's page takes the token from. */
3729
+ export declare const PREVIEW_QUERY_PARAM = "hollware-preview";
3730
+ /** How long a token lasts, in seconds. */
3731
+ export declare const PREVIEW_TTL_SECONDS = 3600;
3732
+ /** The least characters of `HOLLWARE_SECRET` that Hollware signs anything with. */
3733
+ export declare const PREVIEW_SECRET_MIN_LENGTH = 32;
3734
+ /** Why a token was not accepted: for the log of the operator, never for the caller. */
3735
+ type PreviewRefusal = 'no_secret' | 'malformed' | 'signature' | 'site' | 'expired';
3736
+ type PreviewCheck = {
3737
+ readonly ok: true;
3738
+ readonly entryId: string;
3739
+ readonly expiresAt: string;
3740
+ } | {
3741
+ readonly ok: false;
3742
+ readonly reason: PreviewRefusal;
3743
+ };
3744
+ /** Whether a Worker's secret can sign previews: present and long enough. */
3745
+ export declare function canSignPreviews(secret: string | undefined): secret is string;
3746
+ /** A token for one entry of one site, valid for `PREVIEW_TTL_SECONDS` from `now`. */
3747
+ export declare function makePreviewToken(input: {
3748
+ readonly secret: string;
3749
+ readonly site: string;
3750
+ readonly entryId: string;
3751
+ readonly now: Date;
3752
+ }): Promise<{
3753
+ readonly token: string;
3754
+ readonly expiresAt: string;
3755
+ }>;
3756
+ /**
3757
+ * Checks a token for a site. The signature is verified (in constant time, by `crypto.subtle`)
3758
+ * before the payload is parsed, under the key of the site that is asked: a token made for another
3759
+ * site fails there. The entry the token names is the caller's to compare with the entry it read.
3760
+ */
3761
+ export declare function verifyPreviewToken(input: {
3762
+ readonly secret: string | undefined;
3763
+ readonly site: string;
3764
+ readonly token: string;
3765
+ readonly now: Date;
3766
+ }): Promise<PreviewCheck>;
3767
+ //#endregion
3768
+ //#region src/events.d.ts
3769
+ /** A publish or an unpublish: the entry, and where it lives on the site. */
3770
+ export declare const entryEvent: z.ZodObject<{
3771
+ id: z.ZodString;
3772
+ site: z.ZodString;
3773
+ at: z.ZodString;
3774
+ cacheTags: z.ZodArray<z.ZodString>;
3775
+ kind: z.ZodEnum<{
3776
+ "entry.published": "entry.published";
3777
+ "entry.unpublished": "entry.unpublished";
3778
+ }>;
3779
+ entry: z.ZodObject<{
3780
+ id: z.ZodString;
3781
+ collection: z.ZodString;
3782
+ locale: z.ZodString;
3783
+ slug: z.ZodString;
3784
+ translationGroup: z.ZodNullable<z.ZodString>;
3785
+ }, z.core.$strip>;
3786
+ path: z.ZodNullable<z.ZodString>;
3787
+ url: z.ZodNullable<z.ZodString>;
3788
+ }, z.core.$strip>;
3789
+ /** A change of the site's structure: no entry, the tags to purge. */
3790
+ export declare const siteEvent: z.ZodObject<{
3791
+ id: z.ZodString;
3792
+ site: z.ZodString;
3793
+ at: z.ZodString;
3794
+ cacheTags: z.ZodArray<z.ZodString>;
3795
+ kind: z.ZodLiteral<"site.changed">;
3796
+ }, z.core.$strip>;
3797
+ /** Every event a webhook gets. */
3798
+ export declare const hollwareEvent: z.ZodDiscriminatedUnion<[z.ZodObject<{
3799
+ id: z.ZodString;
3800
+ site: z.ZodString;
3801
+ at: z.ZodString;
3802
+ cacheTags: z.ZodArray<z.ZodString>;
3803
+ kind: z.ZodEnum<{
3804
+ "entry.published": "entry.published";
3805
+ "entry.unpublished": "entry.unpublished";
3806
+ }>;
3807
+ entry: z.ZodObject<{
3808
+ id: z.ZodString;
3809
+ collection: z.ZodString;
3810
+ locale: z.ZodString;
3811
+ slug: z.ZodString;
3812
+ translationGroup: z.ZodNullable<z.ZodString>;
3813
+ }, z.core.$strip>;
3814
+ path: z.ZodNullable<z.ZodString>;
3815
+ url: z.ZodNullable<z.ZodString>;
3816
+ }, z.core.$strip>, z.ZodObject<{
3817
+ id: z.ZodString;
3818
+ site: z.ZodString;
3819
+ at: z.ZodString;
3820
+ cacheTags: z.ZodArray<z.ZodString>;
3821
+ kind: z.ZodLiteral<"site.changed">;
3822
+ }, z.core.$strip>], "kind">;
3823
+ type EntryEvent = z.infer<typeof entryEvent>;
3824
+ type SiteEvent = z.infer<typeof siteEvent>;
3825
+ type HollwareEvent = z.infer<typeof hollwareEvent>;
3826
+ /**
3827
+ * The event of a webhook's body, once its signature holds, or `null` for a body that is not one
3828
+ * of the events this version knows (a newer kind, say): a receiver skips it.
3829
+ */
3830
+ export declare function parseHollwareEvent(body: string): HollwareEvent | null;
3831
+ //#endregion
3459
3832
  //#region src/search/chunks.d.ts
3460
3833
  /**
3461
3834
  * The pieces of an entry that semantic search embeds (v0.5): one summary, and one piece for each
@@ -3521,8 +3894,15 @@ export declare function tagsOfEntries(entries: readonly TaggedEntry[]): string[]
3521
3894
  * collection in its locale and in every locale, and the pages that link to its translations.
3522
3895
  */
3523
3896
  export declare function tagsOfChange(entry: TaggedEntry): string[];
3897
+ /**
3898
+ * The tags a change of a site's structure invalidates (ADR-033): the pages that show the structure
3899
+ * (`site`, such as a navigation), and every list of its collections in each locale and in every
3900
+ * locale, as a list may change with a schema, a route or a collection that goes. `collections` and
3901
+ * `locales` are those of the definition before and after the change, together.
3902
+ */
3903
+ export declare function tagsOfSiteChange(collections: readonly string[], locales: readonly string[]): string[];
3524
3904
  //#endregion
3525
3905
  //#region src/index.d.ts
3526
3906
  export declare const name = "@hollware/core";
3527
3907
  //#endregion
3528
- export { type AcknowledgedWarning, type AuthDefinition, type BuiltInContractId, type BuiltInOptions, type CatalogRule, type Chunk, type CollectionDefinition, type CollectionDefinitionData, type ComponentDefinition, type ComponentUse, type ConfigProblem, type Contract, type ContractContext, type ContractDescription, type ContractFinding, type ContractText, type CustomContractOptions, type DescribedSchema, type DisallowedMarker, type Effect, type EntryDocument, type EntryFacts, type EntryLookup, type EntryRef, type ErrorCode, type ExtractedContent, type Heading, type HollwareConfig, type IdPrefix, type ImageRef, type LinkRef, type LinkTarget, type Operation, type OperationByName, type OperationName, type OperationSpec, type OutcomeInfo, type OutcomeOf, type Phase, type Preset, type ProcessMarkdown, type ProcessMarkdownOptions, type ProcessResult, type ProcessedMarkdown, type RenderHtml, type ResolveConfig, type ResolvedAuth, type ResolvedCollection, type ResolvedConfig, type ResolvedSite, type RuleDefinition, type RunContractsInput, type SchemaOutput, type Scope, type Severity, type SiteDefinition, type SiteDefinitionData, type SiteDefinitionInput, type SiteDescription, type TaggedEntry, type Verdict, type Violation, schemas_d_exports as schemas };
3908
+ export { type AcknowledgedWarning, type AuthDefinition, type BuiltInContractId, type BuiltInOptions, type CatalogRule, type Chunk, type CollectionDefinition, type CollectionDefinitionData, type ComponentDefinition, type ComponentUse, type ConfigProblem, type Contract, type ContractContext, type ContractDescription, type ContractFinding, type ContractText, type CustomContractOptions, type DescribedSchema, type DisallowedMarker, type Effect, type EntryDocument, type EntryEvent, type EntryFacts, type EntryLookup, type EntryRef, type ErrorCode, type ExtractedContent, type Heading, type HollwareConfig, type HollwareEvent, type IdPrefix, type ImageRef, type LinkRef, type LinkTarget, type Operation, type OperationByName, type OperationName, type OperationSpec, type OutcomeInfo, type OutcomeOf, type Phase, type Preset, type PreviewCheck, type PreviewRefusal, type ProcessMarkdown, type ProcessMarkdownOptions, type ProcessResult, type ProcessedMarkdown, type RenderHtml, type ResolveConfig, type ResolvedAudit, type ResolvedAuth, type ResolvedCollection, type ResolvedConfig, type ResolvedSite, type RuleDefinition, type RunContractsInput, type SchemaOutput, type Scope, type Severity, type SiteDefinition, type SiteDefinitionData, type SiteDefinitionInput, type SiteDescription, type SiteEvent, type TaggedEntry, type Verdict, type Violation, schemas_d_exports as schemas };