@kernhq/module-quire 0.11.0 → 0.12.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 (48) hide show
  1. package/dist/contract/models.d.ts +46 -0
  2. package/dist/contract/models.d.ts.map +1 -1
  3. package/dist/contract/models.js +73 -0
  4. package/dist/contract/models.js.map +1 -1
  5. package/dist/contract/permissions.d.ts +17 -1
  6. package/dist/contract/permissions.d.ts.map +1 -1
  7. package/dist/contract/permissions.js +34 -0
  8. package/dist/contract/permissions.js.map +1 -1
  9. package/dist/contract/router.d.ts +670 -0
  10. package/dist/contract/router.d.ts.map +1 -1
  11. package/dist/contract/router.js +273 -2
  12. package/dist/contract/router.js.map +1 -1
  13. package/dist/server/_impl.d.ts +770 -0
  14. package/dist/server/_impl.d.ts.map +1 -1
  15. package/dist/server/_impl.js +264 -2
  16. package/dist/server/_impl.js.map +1 -1
  17. package/dist/server/schema.d.ts +318 -1
  18. package/dist/server/schema.d.ts.map +1 -1
  19. package/dist/server/schema.js +86 -0
  20. package/dist/server/schema.js.map +1 -1
  21. package/dist/server/services/access.d.ts +1 -0
  22. package/dist/server/services/access.d.ts.map +1 -1
  23. package/dist/server/services/index.d.ts +3 -0
  24. package/dist/server/services/index.d.ts.map +1 -1
  25. package/dist/server/services/index.js +5 -1
  26. package/dist/server/services/index.js.map +1 -1
  27. package/dist/server/services/pages.d.ts.map +1 -1
  28. package/dist/server/services/pages.js +6 -0
  29. package/dist/server/services/pages.js.map +1 -1
  30. package/dist/server/services/publications.d.ts +177 -0
  31. package/dist/server/services/publications.d.ts.map +1 -0
  32. package/dist/server/services/publications.js +553 -0
  33. package/dist/server/services/publications.js.map +1 -0
  34. package/dist/server/services/versions.d.ts +4 -0
  35. package/dist/server/services/versions.d.ts.map +1 -1
  36. package/migrations/0008_publications.sql +140 -0
  37. package/migrations/meta/_journal.json +7 -0
  38. package/package.json +1 -1
  39. package/src/client/components/PublishDialog.svelte +857 -0
  40. package/src/client/i18n.ts +434 -0
  41. package/src/client/index.ts +21 -0
  42. package/src/client/mock.ts +426 -2
  43. package/src/client/pages/PageView.svelte +196 -5
  44. package/src/client/public-url.ts +64 -0
  45. package/src/client/query.ts +16 -0
  46. package/src/contract/models.ts +77 -0
  47. package/src/contract/permissions.ts +53 -1
  48. package/src/contract/router.ts +302 -1
@@ -51,6 +51,115 @@ export declare const WatchState: z.ZodObject<{
51
51
  watchers: z.ZodArray<z.core.$ZodBranded<z.ZodUUID, "UserId", "out">>;
52
52
  }, z.core.$strip>;
53
53
  export type WatchState = z.infer<typeof WatchState>;
54
+ /**
55
+ * A published site addresses its pages by **path, never by id**, and that is a security decision
56
+ * rather than a matter of taste.
57
+ *
58
+ * Every id in a public response is a string somebody can try somewhere else, and the only way to be
59
+ * sure none of them opens a door is for there to be none. So the whole `public.*` surface below
60
+ * carries no page id, no space id, no version id, no user id and no workspace id — a nav entry, a
61
+ * breadcrumb, a search hit and a sitemap line are all `path`, and `path` is built from titles by the
62
+ * server. `publications.int.test.ts` walks every public response and fails on any uuid belonging to
63
+ * anything in the fixture, which is what keeps this true as the shapes grow.
64
+ *
65
+ * The root page's path is the empty string; a child's is its ancestors' slugs joined with `/`, each
66
+ * slug being its title reduced to letters, digits and dashes (Unicode letters, so a Persian title
67
+ * keeps a Persian slug) and suffixed `-2`, `-3` when two siblings would collide.
68
+ */
69
+ export declare const PublicNavEntry: z.ZodObject<{
70
+ path: z.ZodString;
71
+ parentPath: z.ZodNullable<z.ZodString>;
72
+ title: z.ZodString;
73
+ icon: z.ZodNullable<z.ZodString>;
74
+ }, z.core.$strip>;
75
+ export type PublicNavEntry = z.infer<typeof PublicNavEntry>;
76
+ /** What is worth saying about a published site once a reader is allowed to see it. */
77
+ export declare const PublicSiteDetail: z.ZodObject<{
78
+ title: z.ZodString;
79
+ description: z.ZodString;
80
+ ogImageUrl: z.ZodNullable<z.ZodString>;
81
+ indexable: z.ZodBoolean;
82
+ updatedAt: z.ZodISODateTime;
83
+ nav: z.ZodArray<z.ZodObject<{
84
+ path: z.ZodString;
85
+ parentPath: z.ZodNullable<z.ZodString>;
86
+ title: z.ZodString;
87
+ icon: z.ZodNullable<z.ZodString>;
88
+ }, z.core.$strip>>;
89
+ }, z.core.$strip>;
90
+ export type PublicSiteDetail = z.infer<typeof PublicSiteDetail>;
91
+ /**
92
+ * A published site, or the door to it.
93
+ *
94
+ * `locked` is the one thing a password-protected site admits before the password: that there is a
95
+ * door. Everything else — the title, the description, the shape of the tree — is behind it, because
96
+ * a nav tree is a table of contents and a table of contents is most of what a private handbook is.
97
+ * `theme` comes out anyway so the challenge screen is not white on a site that is not.
98
+ */
99
+ export declare const PublicSite: z.ZodObject<{
100
+ slug: z.ZodString;
101
+ theme: z.ZodEnum<{
102
+ auto: "auto";
103
+ light: "light";
104
+ dark: "dark";
105
+ }>;
106
+ locked: z.ZodBoolean;
107
+ site: z.ZodNullable<z.ZodObject<{
108
+ title: z.ZodString;
109
+ description: z.ZodString;
110
+ ogImageUrl: z.ZodNullable<z.ZodString>;
111
+ indexable: z.ZodBoolean;
112
+ updatedAt: z.ZodISODateTime;
113
+ nav: z.ZodArray<z.ZodObject<{
114
+ path: z.ZodString;
115
+ parentPath: z.ZodNullable<z.ZodString>;
116
+ title: z.ZodString;
117
+ icon: z.ZodNullable<z.ZodString>;
118
+ }, z.core.$strip>>;
119
+ }, z.core.$strip>>;
120
+ }, z.core.$strip>;
121
+ export type PublicSite = z.infer<typeof PublicSite>;
122
+ export declare const PublicBreadcrumb: z.ZodObject<{
123
+ path: z.ZodString;
124
+ title: z.ZodString;
125
+ }, z.core.$strip>;
126
+ export type PublicBreadcrumb = z.infer<typeof PublicBreadcrumb>;
127
+ export declare const PublicPage: z.ZodObject<{
128
+ path: z.ZodString;
129
+ title: z.ZodString;
130
+ icon: z.ZodNullable<z.ZodString>;
131
+ coverUrl: z.ZodNullable<z.ZodString>;
132
+ html: z.ZodString;
133
+ publishedAt: z.ZodISODateTime;
134
+ etag: z.ZodString;
135
+ breadcrumbs: z.ZodArray<z.ZodObject<{
136
+ path: z.ZodString;
137
+ title: z.ZodString;
138
+ }, z.core.$strip>>;
139
+ }, z.core.$strip>;
140
+ export type PublicPage = z.infer<typeof PublicPage>;
141
+ export declare const PublicSearchHit: z.ZodObject<{
142
+ path: z.ZodString;
143
+ title: z.ZodString;
144
+ snippet: z.ZodString;
145
+ }, z.core.$strip>;
146
+ export type PublicSearchHit = z.infer<typeof PublicSearchHit>;
147
+ export declare const PublicSitemapEntry: z.ZodObject<{
148
+ path: z.ZodString;
149
+ lastModified: z.ZodISODateTime;
150
+ }, z.core.$strip>;
151
+ /**
152
+ * The URL prefix the route layer serves this site under, so a link between two published pages is a
153
+ * link and not a dead mention.
154
+ *
155
+ * The module knows a page's path inside its publication and nothing about the address it is served
156
+ * at — one instance mounts a site at `/p/<workspace>/<slug>/`, another at the root of its own
157
+ * domain. Rather than guess, it takes the prefix and refuses anything that is not one: it has to
158
+ * start and end with `/`, and its segments are unreserved characters only. That refusal is the
159
+ * point. `//evil.example/` is a protocol-relative URL wearing the costume of a local path, and a
160
+ * caller that could set it would have every link on somebody's published site point off-site.
161
+ */
162
+ export declare const PublicBasePath: z.ZodDefault<z.ZodString>;
54
163
  export declare const quireContract: {
55
164
  readonly spaces: {
56
165
  readonly list: import("@orpc/contract").ContractProcedureBuilderWithInputOutput<z.ZodObject<{
@@ -309,6 +418,8 @@ export declare const quireContract: {
309
418
  icon: z.ZodNullable<z.ZodString>;
310
419
  hasChildren: z.ZodBoolean;
311
420
  archivedAt: z.ZodNullable<z.ZodISODateTime>;
421
+ excludedFromPublic: z.ZodDefault<z.ZodBoolean>;
422
+ hasPublishedVersion: z.ZodDefault<z.ZodBoolean>;
312
423
  }, z.core.$strip>>, import("@orpc/contract").MergedErrorMap<Record<never, never>, {
313
424
  BAD_REQUEST: {
314
425
  data: z.ZodOptional<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
@@ -3350,6 +3461,565 @@ export declare const quireContract: {
3350
3461
  };
3351
3462
  }>, Record<never, never>>;
3352
3463
  };
3464
+ /**
3465
+ * Who has published what, from the inside. Every procedure here is authenticated and asks
3466
+ * `quire.page.publish` about the **root page**, because that is the page whose subtree is being
3467
+ * handed to the internet.
3468
+ */
3469
+ readonly publications: {
3470
+ readonly list: import("@orpc/contract").ContractProcedureBuilderWithInputOutput<z.ZodObject<{
3471
+ workspaceId: z.core.$ZodBranded<z.ZodUUID, "WorkspaceId", "out">;
3472
+ spaceId: z.ZodUUID;
3473
+ }, z.core.$strip>, z.ZodArray<z.ZodObject<{
3474
+ id: z.ZodUUID;
3475
+ workspaceId: z.core.$ZodBranded<z.ZodUUID, "WorkspaceId", "out">;
3476
+ rootPageId: z.ZodUUID;
3477
+ includeDescendants: z.ZodBoolean;
3478
+ slug: z.ZodString;
3479
+ hasPassword: z.ZodBoolean;
3480
+ expiresAt: z.ZodNullable<z.ZodISODateTime>;
3481
+ seoTitle: z.ZodString;
3482
+ seoDescription: z.ZodString;
3483
+ ogImageUrl: z.ZodNullable<z.ZodString>;
3484
+ indexable: z.ZodBoolean;
3485
+ theme: z.ZodEnum<{
3486
+ auto: "auto";
3487
+ light: "light";
3488
+ dark: "dark";
3489
+ }>;
3490
+ createdBy: z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "UserId", "out">>;
3491
+ createdAt: z.ZodISODateTime;
3492
+ updatedAt: z.ZodISODateTime;
3493
+ }, z.core.$strip>>, import("@orpc/contract").MergedErrorMap<Record<never, never>, {
3494
+ BAD_REQUEST: {
3495
+ data: z.ZodOptional<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
3496
+ };
3497
+ UNAUTHORIZED: {};
3498
+ FORBIDDEN: {
3499
+ data: z.ZodOptional<z.ZodObject<{
3500
+ permission: z.ZodOptional<z.ZodString>;
3501
+ }, z.core.$strip>>;
3502
+ };
3503
+ NOT_FOUND: {};
3504
+ CONFLICT: {
3505
+ data: z.ZodOptional<z.ZodObject<{
3506
+ reason: z.ZodOptional<z.ZodString>;
3507
+ }, z.core.$strip>>;
3508
+ };
3509
+ RATE_LIMITED: {};
3510
+ MODULE_DISABLED: {
3511
+ data: z.ZodObject<{
3512
+ module: z.ZodString;
3513
+ }, z.core.$strip>;
3514
+ };
3515
+ }>, Record<never, never>>;
3516
+ readonly get: import("@orpc/contract").ContractProcedureBuilderWithInputOutput<z.ZodObject<{
3517
+ workspaceId: z.core.$ZodBranded<z.ZodUUID, "WorkspaceId", "out">;
3518
+ publicationId: z.ZodUUID;
3519
+ }, z.core.$strip>, z.ZodObject<{
3520
+ id: z.ZodUUID;
3521
+ workspaceId: z.core.$ZodBranded<z.ZodUUID, "WorkspaceId", "out">;
3522
+ rootPageId: z.ZodUUID;
3523
+ includeDescendants: z.ZodBoolean;
3524
+ slug: z.ZodString;
3525
+ hasPassword: z.ZodBoolean;
3526
+ expiresAt: z.ZodNullable<z.ZodISODateTime>;
3527
+ seoTitle: z.ZodString;
3528
+ seoDescription: z.ZodString;
3529
+ ogImageUrl: z.ZodNullable<z.ZodString>;
3530
+ indexable: z.ZodBoolean;
3531
+ theme: z.ZodEnum<{
3532
+ auto: "auto";
3533
+ light: "light";
3534
+ dark: "dark";
3535
+ }>;
3536
+ createdBy: z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "UserId", "out">>;
3537
+ createdAt: z.ZodISODateTime;
3538
+ updatedAt: z.ZodISODateTime;
3539
+ }, z.core.$strip>, import("@orpc/contract").MergedErrorMap<Record<never, never>, {
3540
+ BAD_REQUEST: {
3541
+ data: z.ZodOptional<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
3542
+ };
3543
+ UNAUTHORIZED: {};
3544
+ FORBIDDEN: {
3545
+ data: z.ZodOptional<z.ZodObject<{
3546
+ permission: z.ZodOptional<z.ZodString>;
3547
+ }, z.core.$strip>>;
3548
+ };
3549
+ NOT_FOUND: {};
3550
+ CONFLICT: {
3551
+ data: z.ZodOptional<z.ZodObject<{
3552
+ reason: z.ZodOptional<z.ZodString>;
3553
+ }, z.core.$strip>>;
3554
+ };
3555
+ RATE_LIMITED: {};
3556
+ MODULE_DISABLED: {
3557
+ data: z.ZodObject<{
3558
+ module: z.ZodString;
3559
+ }, z.core.$strip>;
3560
+ };
3561
+ }>, Record<never, never>>;
3562
+ readonly create: import("@orpc/contract").ContractProcedureBuilderWithInputOutput<z.ZodObject<{
3563
+ workspaceId: z.core.$ZodBranded<z.ZodUUID, "WorkspaceId", "out">;
3564
+ rootPageId: z.ZodUUID;
3565
+ slug: z.ZodString;
3566
+ includeDescendants: z.ZodDefault<z.ZodBoolean>;
3567
+ password: z.ZodDefault<z.ZodNullable<z.ZodString>>;
3568
+ expiresAt: z.ZodDefault<z.ZodNullable<z.ZodISODateTime>>;
3569
+ seoTitle: z.ZodDefault<z.ZodString>;
3570
+ seoDescription: z.ZodDefault<z.ZodString>;
3571
+ ogImageUrl: z.ZodDefault<z.ZodNullable<z.ZodString>>;
3572
+ indexable: z.ZodDefault<z.ZodBoolean>;
3573
+ theme: z.ZodDefault<z.ZodEnum<{
3574
+ auto: "auto";
3575
+ light: "light";
3576
+ dark: "dark";
3577
+ }>>;
3578
+ }, z.core.$strip>, z.ZodObject<{
3579
+ id: z.ZodUUID;
3580
+ workspaceId: z.core.$ZodBranded<z.ZodUUID, "WorkspaceId", "out">;
3581
+ rootPageId: z.ZodUUID;
3582
+ includeDescendants: z.ZodBoolean;
3583
+ slug: z.ZodString;
3584
+ hasPassword: z.ZodBoolean;
3585
+ expiresAt: z.ZodNullable<z.ZodISODateTime>;
3586
+ seoTitle: z.ZodString;
3587
+ seoDescription: z.ZodString;
3588
+ ogImageUrl: z.ZodNullable<z.ZodString>;
3589
+ indexable: z.ZodBoolean;
3590
+ theme: z.ZodEnum<{
3591
+ auto: "auto";
3592
+ light: "light";
3593
+ dark: "dark";
3594
+ }>;
3595
+ createdBy: z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "UserId", "out">>;
3596
+ createdAt: z.ZodISODateTime;
3597
+ updatedAt: z.ZodISODateTime;
3598
+ }, z.core.$strip>, import("@orpc/contract").MergedErrorMap<Record<never, never>, {
3599
+ BAD_REQUEST: {
3600
+ data: z.ZodOptional<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
3601
+ };
3602
+ UNAUTHORIZED: {};
3603
+ FORBIDDEN: {
3604
+ data: z.ZodOptional<z.ZodObject<{
3605
+ permission: z.ZodOptional<z.ZodString>;
3606
+ }, z.core.$strip>>;
3607
+ };
3608
+ NOT_FOUND: {};
3609
+ CONFLICT: {
3610
+ data: z.ZodOptional<z.ZodObject<{
3611
+ reason: z.ZodOptional<z.ZodString>;
3612
+ }, z.core.$strip>>;
3613
+ };
3614
+ RATE_LIMITED: {};
3615
+ MODULE_DISABLED: {
3616
+ data: z.ZodObject<{
3617
+ module: z.ZodString;
3618
+ }, z.core.$strip>;
3619
+ };
3620
+ }>, Record<never, never>>;
3621
+ /**
3622
+ * `password` is three-valued on purpose: a string sets one, `null` removes it, and leaving the
3623
+ * key out changes nothing. A two-valued field would make every "rename the site" request also
3624
+ * an "unlock the site" request, which is the shape that quietly takes the door off a handbook.
3625
+ */
3626
+ readonly update: import("@orpc/contract").ContractProcedureBuilderWithInputOutput<z.ZodObject<{
3627
+ workspaceId: z.core.$ZodBranded<z.ZodUUID, "WorkspaceId", "out">;
3628
+ publicationId: z.ZodUUID;
3629
+ slug: z.ZodOptional<z.ZodString>;
3630
+ includeDescendants: z.ZodOptional<z.ZodBoolean>;
3631
+ password: z.ZodOptional<z.ZodNullable<z.ZodString>>;
3632
+ expiresAt: z.ZodOptional<z.ZodNullable<z.ZodISODateTime>>;
3633
+ seoTitle: z.ZodOptional<z.ZodString>;
3634
+ seoDescription: z.ZodOptional<z.ZodString>;
3635
+ ogImageUrl: z.ZodOptional<z.ZodNullable<z.ZodString>>;
3636
+ indexable: z.ZodOptional<z.ZodBoolean>;
3637
+ theme: z.ZodOptional<z.ZodEnum<{
3638
+ auto: "auto";
3639
+ light: "light";
3640
+ dark: "dark";
3641
+ }>>;
3642
+ }, z.core.$strip>, z.ZodObject<{
3643
+ id: z.ZodUUID;
3644
+ workspaceId: z.core.$ZodBranded<z.ZodUUID, "WorkspaceId", "out">;
3645
+ rootPageId: z.ZodUUID;
3646
+ includeDescendants: z.ZodBoolean;
3647
+ slug: z.ZodString;
3648
+ hasPassword: z.ZodBoolean;
3649
+ expiresAt: z.ZodNullable<z.ZodISODateTime>;
3650
+ seoTitle: z.ZodString;
3651
+ seoDescription: z.ZodString;
3652
+ ogImageUrl: z.ZodNullable<z.ZodString>;
3653
+ indexable: z.ZodBoolean;
3654
+ theme: z.ZodEnum<{
3655
+ auto: "auto";
3656
+ light: "light";
3657
+ dark: "dark";
3658
+ }>;
3659
+ createdBy: z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "UserId", "out">>;
3660
+ createdAt: z.ZodISODateTime;
3661
+ updatedAt: z.ZodISODateTime;
3662
+ }, z.core.$strip>, import("@orpc/contract").MergedErrorMap<Record<never, never>, {
3663
+ BAD_REQUEST: {
3664
+ data: z.ZodOptional<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
3665
+ };
3666
+ UNAUTHORIZED: {};
3667
+ FORBIDDEN: {
3668
+ data: z.ZodOptional<z.ZodObject<{
3669
+ permission: z.ZodOptional<z.ZodString>;
3670
+ }, z.core.$strip>>;
3671
+ };
3672
+ NOT_FOUND: {};
3673
+ CONFLICT: {
3674
+ data: z.ZodOptional<z.ZodObject<{
3675
+ reason: z.ZodOptional<z.ZodString>;
3676
+ }, z.core.$strip>>;
3677
+ };
3678
+ RATE_LIMITED: {};
3679
+ MODULE_DISABLED: {
3680
+ data: z.ZodObject<{
3681
+ module: z.ZodString;
3682
+ }, z.core.$strip>;
3683
+ };
3684
+ }>, Record<never, never>>;
3685
+ /** The row is the grant, so removing it takes the site down. Nothing else is deleted. */
3686
+ readonly remove: import("@orpc/contract").ContractProcedureBuilderWithInputOutput<z.ZodObject<{
3687
+ workspaceId: z.core.$ZodBranded<z.ZodUUID, "WorkspaceId", "out">;
3688
+ publicationId: z.ZodUUID;
3689
+ }, z.core.$strip>, z.ZodObject<{
3690
+ ok: z.ZodLiteral<true>;
3691
+ }, z.core.$strip>, import("@orpc/contract").MergedErrorMap<Record<never, never>, {
3692
+ BAD_REQUEST: {
3693
+ data: z.ZodOptional<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
3694
+ };
3695
+ UNAUTHORIZED: {};
3696
+ FORBIDDEN: {
3697
+ data: z.ZodOptional<z.ZodObject<{
3698
+ permission: z.ZodOptional<z.ZodString>;
3699
+ }, z.core.$strip>>;
3700
+ };
3701
+ NOT_FOUND: {};
3702
+ CONFLICT: {
3703
+ data: z.ZodOptional<z.ZodObject<{
3704
+ reason: z.ZodOptional<z.ZodString>;
3705
+ }, z.core.$strip>>;
3706
+ };
3707
+ RATE_LIMITED: {};
3708
+ MODULE_DISABLED: {
3709
+ data: z.ZodObject<{
3710
+ module: z.ZodString;
3711
+ }, z.core.$strip>;
3712
+ };
3713
+ }>, Record<never, never>>;
3714
+ /**
3715
+ * Keep one page — and therefore everything under it — out of every publication, present and
3716
+ * future.
3717
+ *
3718
+ * Absolute rather than per-publication, and that is the whole reason it is a flag on the page:
3719
+ * an opt-out recorded against one publication says nothing about a publication somebody roots
3720
+ * above the page next month, and its author would never see it. This one holds against
3721
+ * publications that do not exist yet.
3722
+ */
3723
+ readonly optOut: import("@orpc/contract").ContractProcedureBuilderWithInputOutput<z.ZodObject<{
3724
+ workspaceId: z.core.$ZodBranded<z.ZodUUID, "WorkspaceId", "out">;
3725
+ pageId: z.ZodUUID;
3726
+ excluded: z.ZodDefault<z.ZodBoolean>;
3727
+ }, z.core.$strip>, z.ZodObject<{
3728
+ pageId: z.ZodUUID;
3729
+ excluded: z.ZodBoolean;
3730
+ }, z.core.$strip>, import("@orpc/contract").MergedErrorMap<Record<never, never>, {
3731
+ BAD_REQUEST: {
3732
+ data: z.ZodOptional<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
3733
+ };
3734
+ UNAUTHORIZED: {};
3735
+ FORBIDDEN: {
3736
+ data: z.ZodOptional<z.ZodObject<{
3737
+ permission: z.ZodOptional<z.ZodString>;
3738
+ }, z.core.$strip>>;
3739
+ };
3740
+ NOT_FOUND: {};
3741
+ CONFLICT: {
3742
+ data: z.ZodOptional<z.ZodObject<{
3743
+ reason: z.ZodOptional<z.ZodString>;
3744
+ }, z.core.$strip>>;
3745
+ };
3746
+ RATE_LIMITED: {};
3747
+ MODULE_DISABLED: {
3748
+ data: z.ZodObject<{
3749
+ module: z.ZodString;
3750
+ }, z.core.$strip>;
3751
+ };
3752
+ }>, Record<never, never>>;
3753
+ };
3754
+ /**
3755
+ * The signed-out surface. **This is the only part of Kern with no principal behind it.**
3756
+ *
3757
+ * Five rules hold here, and each of them is a test in `publications.int.test.ts`:
3758
+ *
3759
+ * 1. A page is public only if it is inside the publication's subtree, not opted out, not
3760
+ * archived, not trashed, and has a published version that has been rendered. Failing any one
3761
+ * of those is **404, never 403** — a refusal that distinguishes "not yours" from "not there"
3762
+ * confirms the page exists to whoever is guessing.
3763
+ * 2. Guessing a sibling, a parent, a page in another space or another workspace gets 404 too,
3764
+ * which is free here because nothing is addressed by id: `path` names a place in *this*
3765
+ * publication's tree or it names nothing.
3766
+ * 3. No response carries a draft, a comment, an author, a version list, or any id.
3767
+ * 4. A password-protected publication answers a challenge and nothing else. `unlock` mints a
3768
+ * **capability token, not a session**: an AES-GCM envelope sealed with the instance secret,
3769
+ * bound by its associated data to this one publication, carrying an expiry and no identity.
3770
+ * The server keeps nothing. The route layer is expected to hold it in an HttpOnly cookie and
3771
+ * pass it back — never to put it in a link, because a token in a URL is a token in a referrer
3772
+ * header and in somebody's access log.
3773
+ * 5. An expired publication is 404, checked on the request rather than by a sweep.
3774
+ *
3775
+ * `workspaceId` is in the path because *anonymous means no principal, not no tenant*: the request
3776
+ * has to name a workspace before anything touches `mod_quire`, or row-level security has nothing
3777
+ * to fence with. See the note at the top of `migrations/0008_publications.sql`.
3778
+ */
3779
+ readonly public: {
3780
+ readonly site: import("@orpc/contract").ContractProcedureBuilderWithInputOutput<z.ZodObject<{
3781
+ workspaceId: z.core.$ZodBranded<z.ZodUUID, "WorkspaceId", "out">;
3782
+ slug: z.ZodString;
3783
+ token: z.ZodDefault<z.ZodNullable<z.ZodString>>;
3784
+ }, z.core.$strip>, z.ZodObject<{
3785
+ slug: z.ZodString;
3786
+ theme: z.ZodEnum<{
3787
+ auto: "auto";
3788
+ light: "light";
3789
+ dark: "dark";
3790
+ }>;
3791
+ locked: z.ZodBoolean;
3792
+ site: z.ZodNullable<z.ZodObject<{
3793
+ title: z.ZodString;
3794
+ description: z.ZodString;
3795
+ ogImageUrl: z.ZodNullable<z.ZodString>;
3796
+ indexable: z.ZodBoolean;
3797
+ updatedAt: z.ZodISODateTime;
3798
+ nav: z.ZodArray<z.ZodObject<{
3799
+ path: z.ZodString;
3800
+ parentPath: z.ZodNullable<z.ZodString>;
3801
+ title: z.ZodString;
3802
+ icon: z.ZodNullable<z.ZodString>;
3803
+ }, z.core.$strip>>;
3804
+ }, z.core.$strip>>;
3805
+ }, z.core.$strip>, import("@orpc/contract").MergedErrorMap<Record<never, never>, {
3806
+ BAD_REQUEST: {
3807
+ data: z.ZodOptional<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
3808
+ };
3809
+ UNAUTHORIZED: {};
3810
+ FORBIDDEN: {
3811
+ data: z.ZodOptional<z.ZodObject<{
3812
+ permission: z.ZodOptional<z.ZodString>;
3813
+ }, z.core.$strip>>;
3814
+ };
3815
+ NOT_FOUND: {};
3816
+ CONFLICT: {
3817
+ data: z.ZodOptional<z.ZodObject<{
3818
+ reason: z.ZodOptional<z.ZodString>;
3819
+ }, z.core.$strip>>;
3820
+ };
3821
+ RATE_LIMITED: {};
3822
+ MODULE_DISABLED: {
3823
+ data: z.ZodObject<{
3824
+ module: z.ZodString;
3825
+ }, z.core.$strip>;
3826
+ };
3827
+ }>, Record<never, never>>;
3828
+ /**
3829
+ * One page of a published site.
3830
+ *
3831
+ * `path` is a query parameter rather than a path segment because it contains slashes: a nested
3832
+ * page's address is `guide/install`, and oRPC's route matcher takes one segment per parameter.
3833
+ */
3834
+ readonly page: import("@orpc/contract").ContractProcedureBuilderWithInputOutput<z.ZodObject<{
3835
+ workspaceId: z.core.$ZodBranded<z.ZodUUID, "WorkspaceId", "out">;
3836
+ slug: z.ZodString;
3837
+ path: z.ZodDefault<z.ZodString>;
3838
+ basePath: z.ZodDefault<z.ZodString>;
3839
+ token: z.ZodDefault<z.ZodNullable<z.ZodString>>;
3840
+ }, z.core.$strip>, z.ZodObject<{
3841
+ path: z.ZodString;
3842
+ title: z.ZodString;
3843
+ icon: z.ZodNullable<z.ZodString>;
3844
+ coverUrl: z.ZodNullable<z.ZodString>;
3845
+ html: z.ZodString;
3846
+ publishedAt: z.ZodISODateTime;
3847
+ etag: z.ZodString;
3848
+ breadcrumbs: z.ZodArray<z.ZodObject<{
3849
+ path: z.ZodString;
3850
+ title: z.ZodString;
3851
+ }, z.core.$strip>>;
3852
+ }, z.core.$strip>, import("@orpc/contract").MergedErrorMap<Record<never, never>, {
3853
+ BAD_REQUEST: {
3854
+ data: z.ZodOptional<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
3855
+ };
3856
+ UNAUTHORIZED: {};
3857
+ FORBIDDEN: {
3858
+ data: z.ZodOptional<z.ZodObject<{
3859
+ permission: z.ZodOptional<z.ZodString>;
3860
+ }, z.core.$strip>>;
3861
+ };
3862
+ NOT_FOUND: {};
3863
+ CONFLICT: {
3864
+ data: z.ZodOptional<z.ZodObject<{
3865
+ reason: z.ZodOptional<z.ZodString>;
3866
+ }, z.core.$strip>>;
3867
+ };
3868
+ RATE_LIMITED: {};
3869
+ MODULE_DISABLED: {
3870
+ data: z.ZodObject<{
3871
+ module: z.ZodString;
3872
+ }, z.core.$strip>;
3873
+ };
3874
+ }>, Record<never, never>>;
3875
+ /**
3876
+ * Search inside this publication and nowhere else.
3877
+ *
3878
+ * It reads the **published version's** flattened text, not `pages.text`. That column mirrors the
3879
+ * live document, so searching it would put a sentence somebody has not published yet into a
3880
+ * snippet on the public internet — the one place in this module where the draft and the
3881
+ * published copy differ and the difference is the whole point.
3882
+ */
3883
+ readonly search: import("@orpc/contract").ContractProcedureBuilderWithInputOutput<z.ZodObject<{
3884
+ workspaceId: z.core.$ZodBranded<z.ZodUUID, "WorkspaceId", "out">;
3885
+ slug: z.ZodString;
3886
+ q: z.ZodString;
3887
+ limit: z.ZodDefault<z.ZodNumber>;
3888
+ token: z.ZodDefault<z.ZodNullable<z.ZodString>>;
3889
+ }, z.core.$strip>, z.ZodObject<{
3890
+ items: z.ZodArray<z.ZodObject<{
3891
+ path: z.ZodString;
3892
+ title: z.ZodString;
3893
+ snippet: z.ZodString;
3894
+ }, z.core.$strip>>;
3895
+ }, z.core.$strip>, import("@orpc/contract").MergedErrorMap<Record<never, never>, {
3896
+ BAD_REQUEST: {
3897
+ data: z.ZodOptional<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
3898
+ };
3899
+ UNAUTHORIZED: {};
3900
+ FORBIDDEN: {
3901
+ data: z.ZodOptional<z.ZodObject<{
3902
+ permission: z.ZodOptional<z.ZodString>;
3903
+ }, z.core.$strip>>;
3904
+ };
3905
+ NOT_FOUND: {};
3906
+ CONFLICT: {
3907
+ data: z.ZodOptional<z.ZodObject<{
3908
+ reason: z.ZodOptional<z.ZodString>;
3909
+ }, z.core.$strip>>;
3910
+ };
3911
+ RATE_LIMITED: {};
3912
+ MODULE_DISABLED: {
3913
+ data: z.ZodObject<{
3914
+ module: z.ZodString;
3915
+ }, z.core.$strip>;
3916
+ };
3917
+ }>, Record<never, never>>;
3918
+ /**
3919
+ * What a crawler may index, which is not the same list as what a reader may open: a site behind
3920
+ * a password, or marked `indexable: false`, has an empty sitemap rather than a private one.
3921
+ */
3922
+ readonly sitemap: import("@orpc/contract").ContractProcedureBuilderWithInputOutput<z.ZodObject<{
3923
+ workspaceId: z.core.$ZodBranded<z.ZodUUID, "WorkspaceId", "out">;
3924
+ slug: z.ZodString;
3925
+ }, z.core.$strip>, z.ZodObject<{
3926
+ entries: z.ZodArray<z.ZodObject<{
3927
+ path: z.ZodString;
3928
+ lastModified: z.ZodISODateTime;
3929
+ }, z.core.$strip>>;
3930
+ }, z.core.$strip>, import("@orpc/contract").MergedErrorMap<Record<never, never>, {
3931
+ BAD_REQUEST: {
3932
+ data: z.ZodOptional<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
3933
+ };
3934
+ UNAUTHORIZED: {};
3935
+ FORBIDDEN: {
3936
+ data: z.ZodOptional<z.ZodObject<{
3937
+ permission: z.ZodOptional<z.ZodString>;
3938
+ }, z.core.$strip>>;
3939
+ };
3940
+ NOT_FOUND: {};
3941
+ CONFLICT: {
3942
+ data: z.ZodOptional<z.ZodObject<{
3943
+ reason: z.ZodOptional<z.ZodString>;
3944
+ }, z.core.$strip>>;
3945
+ };
3946
+ RATE_LIMITED: {};
3947
+ MODULE_DISABLED: {
3948
+ data: z.ZodObject<{
3949
+ module: z.ZodString;
3950
+ }, z.core.$strip>;
3951
+ };
3952
+ }>, Record<never, never>>;
3953
+ /**
3954
+ * The one procedure here that never distinguishes one slug from another.
3955
+ *
3956
+ * A crawler asking about a slug that does not exist, one that has expired, and one behind a
3957
+ * password must all get the same answer, or `robots` becomes the oracle every other procedure
3958
+ * refuses to be. So it succeeds for all three and says "do not index". (A workspace with the
3959
+ * module switched off is still a 404, from the middleware — that is a statement about the
3960
+ * workspace, which the path already named, and not about any slug.)
3961
+ */
3962
+ readonly robots: import("@orpc/contract").ContractProcedureBuilderWithInputOutput<z.ZodObject<{
3963
+ workspaceId: z.core.$ZodBranded<z.ZodUUID, "WorkspaceId", "out">;
3964
+ slug: z.ZodString;
3965
+ }, z.core.$strip>, z.ZodObject<{
3966
+ indexable: z.ZodBoolean;
3967
+ sitemapPath: z.ZodNullable<z.ZodString>;
3968
+ }, z.core.$strip>, import("@orpc/contract").MergedErrorMap<Record<never, never>, {
3969
+ BAD_REQUEST: {
3970
+ data: z.ZodOptional<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
3971
+ };
3972
+ UNAUTHORIZED: {};
3973
+ FORBIDDEN: {
3974
+ data: z.ZodOptional<z.ZodObject<{
3975
+ permission: z.ZodOptional<z.ZodString>;
3976
+ }, z.core.$strip>>;
3977
+ };
3978
+ NOT_FOUND: {};
3979
+ CONFLICT: {
3980
+ data: z.ZodOptional<z.ZodObject<{
3981
+ reason: z.ZodOptional<z.ZodString>;
3982
+ }, z.core.$strip>>;
3983
+ };
3984
+ RATE_LIMITED: {};
3985
+ MODULE_DISABLED: {
3986
+ data: z.ZodObject<{
3987
+ module: z.ZodString;
3988
+ }, z.core.$strip>;
3989
+ };
3990
+ }>, Record<never, never>>;
3991
+ /** Present the password, get a token. A site with no password has no door, and answers 404. */
3992
+ readonly unlock: import("@orpc/contract").ContractProcedureBuilderWithInputOutput<z.ZodObject<{
3993
+ workspaceId: z.core.$ZodBranded<z.ZodUUID, "WorkspaceId", "out">;
3994
+ slug: z.ZodString;
3995
+ password: z.ZodString;
3996
+ }, z.core.$strip>, z.ZodObject<{
3997
+ token: z.ZodString;
3998
+ expiresAt: z.ZodISODateTime;
3999
+ }, z.core.$strip>, import("@orpc/contract").MergedErrorMap<Record<never, never>, {
4000
+ BAD_REQUEST: {
4001
+ data: z.ZodOptional<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
4002
+ };
4003
+ UNAUTHORIZED: {};
4004
+ FORBIDDEN: {
4005
+ data: z.ZodOptional<z.ZodObject<{
4006
+ permission: z.ZodOptional<z.ZodString>;
4007
+ }, z.core.$strip>>;
4008
+ };
4009
+ NOT_FOUND: {};
4010
+ CONFLICT: {
4011
+ data: z.ZodOptional<z.ZodObject<{
4012
+ reason: z.ZodOptional<z.ZodString>;
4013
+ }, z.core.$strip>>;
4014
+ };
4015
+ RATE_LIMITED: {};
4016
+ MODULE_DISABLED: {
4017
+ data: z.ZodObject<{
4018
+ module: z.ZodString;
4019
+ }, z.core.$strip>;
4020
+ };
4021
+ }>, Record<never, never>>;
4022
+ };
3353
4023
  };
3354
4024
  export type QuireContract = typeof quireContract;
3355
4025
  export { Ok };