@jini-ai/admin 0.1.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 (235) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +138 -0
  3. package/dist/browser/index.d.ts +8 -0
  4. package/dist/browser/index.d.ts.map +1 -0
  5. package/dist/browser/index.js +8 -0
  6. package/dist/browser/index.js.map +1 -0
  7. package/dist/browser/navigation.d.ts +39 -0
  8. package/dist/browser/navigation.d.ts.map +1 -0
  9. package/dist/browser/navigation.js +113 -0
  10. package/dist/browser/navigation.js.map +1 -0
  11. package/dist/core/gated/types.d.ts +87 -0
  12. package/dist/core/gated/types.d.ts.map +1 -0
  13. package/dist/core/gated/types.js +37 -0
  14. package/dist/core/gated/types.js.map +1 -0
  15. package/dist/core/index.d.ts +20 -0
  16. package/dist/core/index.d.ts.map +1 -0
  17. package/dist/core/index.js +15 -0
  18. package/dist/core/index.js.map +1 -0
  19. package/dist/core/manifest/rules.d.ts +84 -0
  20. package/dist/core/manifest/rules.d.ts.map +1 -0
  21. package/dist/core/manifest/rules.js +130 -0
  22. package/dist/core/manifest/rules.js.map +1 -0
  23. package/dist/core/manifest/types.d.ts +154 -0
  24. package/dist/core/manifest/types.d.ts.map +1 -0
  25. package/dist/core/manifest/types.js +31 -0
  26. package/dist/core/manifest/types.js.map +1 -0
  27. package/dist/core/permissions/rules.d.ts +32 -0
  28. package/dist/core/permissions/rules.d.ts.map +1 -0
  29. package/dist/core/permissions/rules.js +34 -0
  30. package/dist/core/permissions/rules.js.map +1 -0
  31. package/dist/core/ports/analytics.d.ts +35 -0
  32. package/dist/core/ports/analytics.d.ts.map +1 -0
  33. package/dist/core/ports/analytics.js +14 -0
  34. package/dist/core/ports/analytics.js.map +1 -0
  35. package/dist/core/ports/auth.d.ts +49 -0
  36. package/dist/core/ports/auth.d.ts.map +1 -0
  37. package/dist/core/ports/auth.js +19 -0
  38. package/dist/core/ports/auth.js.map +1 -0
  39. package/dist/core/ports/comments.d.ts +90 -0
  40. package/dist/core/ports/comments.d.ts.map +1 -0
  41. package/dist/core/ports/comments.js +24 -0
  42. package/dist/core/ports/comments.js.map +1 -0
  43. package/dist/core/ports/database.d.ts +101 -0
  44. package/dist/core/ports/database.d.ts.map +1 -0
  45. package/dist/core/ports/database.js +2 -0
  46. package/dist/core/ports/database.js.map +1 -0
  47. package/dist/core/ports/forms.d.ts +130 -0
  48. package/dist/core/ports/forms.d.ts.map +1 -0
  49. package/dist/core/ports/forms.js +62 -0
  50. package/dist/core/ports/forms.js.map +1 -0
  51. package/dist/core/ports/identity.d.ts +114 -0
  52. package/dist/core/ports/identity.d.ts.map +1 -0
  53. package/dist/core/ports/identity.js +28 -0
  54. package/dist/core/ports/identity.js.map +1 -0
  55. package/dist/core/ports/index.d.ts +21 -0
  56. package/dist/core/ports/index.d.ts.map +1 -0
  57. package/dist/core/ports/index.js +6 -0
  58. package/dist/core/ports/index.js.map +1 -0
  59. package/dist/core/ports/integrations.d.ts +81 -0
  60. package/dist/core/ports/integrations.d.ts.map +1 -0
  61. package/dist/core/ports/integrations.js +21 -0
  62. package/dist/core/ports/integrations.js.map +1 -0
  63. package/dist/core/ports/media.d.ts +74 -0
  64. package/dist/core/ports/media.d.ts.map +1 -0
  65. package/dist/core/ports/media.js +28 -0
  66. package/dist/core/ports/media.js.map +1 -0
  67. package/dist/core/ports/members.d.ts +50 -0
  68. package/dist/core/ports/members.d.ts.map +1 -0
  69. package/dist/core/ports/members.js +17 -0
  70. package/dist/core/ports/members.js.map +1 -0
  71. package/dist/core/ports/menus.d.ts +179 -0
  72. package/dist/core/ports/menus.d.ts.map +1 -0
  73. package/dist/core/ports/menus.js +70 -0
  74. package/dist/core/ports/menus.js.map +1 -0
  75. package/dist/core/ports/plugins.d.ts +68 -0
  76. package/dist/core/ports/plugins.d.ts.map +1 -0
  77. package/dist/core/ports/plugins.js +27 -0
  78. package/dist/core/ports/plugins.js.map +1 -0
  79. package/dist/core/ports/recovery.d.ts +171 -0
  80. package/dist/core/ports/recovery.d.ts.map +1 -0
  81. package/dist/core/ports/recovery.js +2 -0
  82. package/dist/core/ports/recovery.js.map +1 -0
  83. package/dist/core/ports/redirects.d.ts +139 -0
  84. package/dist/core/ports/redirects.d.ts.map +1 -0
  85. package/dist/core/ports/redirects.js +55 -0
  86. package/dist/core/ports/redirects.js.map +1 -0
  87. package/dist/core/ports/seo.d.ts +147 -0
  88. package/dist/core/ports/seo.d.ts.map +1 -0
  89. package/dist/core/ports/seo.js +39 -0
  90. package/dist/core/ports/seo.js.map +1 -0
  91. package/dist/core/ports/settings.d.ts +87 -0
  92. package/dist/core/ports/settings.d.ts.map +1 -0
  93. package/dist/core/ports/settings.js +23 -0
  94. package/dist/core/ports/settings.js.map +1 -0
  95. package/dist/core/ports/workspace.d.ts +44 -0
  96. package/dist/core/ports/workspace.d.ts.map +1 -0
  97. package/dist/core/ports/workspace.js +29 -0
  98. package/dist/core/ports/workspace.js.map +1 -0
  99. package/dist/core/routing/rules.d.ts +54 -0
  100. package/dist/core/routing/rules.d.ts.map +1 -0
  101. package/dist/core/routing/rules.js +113 -0
  102. package/dist/core/routing/rules.js.map +1 -0
  103. package/dist/core/routing/types.d.ts +36 -0
  104. package/dist/core/routing/types.d.ts.map +1 -0
  105. package/dist/core/routing/types.js +17 -0
  106. package/dist/core/routing/types.js.map +1 -0
  107. package/dist/core/transport/errors.d.ts +53 -0
  108. package/dist/core/transport/errors.d.ts.map +1 -0
  109. package/dist/core/transport/errors.js +63 -0
  110. package/dist/core/transport/errors.js.map +1 -0
  111. package/dist/core/transport/http.d.ts +63 -0
  112. package/dist/core/transport/http.d.ts.map +1 -0
  113. package/dist/core/transport/http.js +63 -0
  114. package/dist/core/transport/http.js.map +1 -0
  115. package/dist/core/transport/index.d.ts +5 -0
  116. package/dist/core/transport/index.d.ts.map +1 -0
  117. package/dist/core/transport/index.js +3 -0
  118. package/dist/core/transport/index.js.map +1 -0
  119. package/dist/core/transport/types.d.ts +81 -0
  120. package/dist/core/transport/types.d.ts.map +1 -0
  121. package/dist/core/transport/types.js +43 -0
  122. package/dist/core/transport/types.js.map +1 -0
  123. package/dist/react/components/ConfirmButton/ConfirmButton.d.ts +40 -0
  124. package/dist/react/components/ConfirmButton/ConfirmButton.d.ts.map +1 -0
  125. package/dist/react/components/ConfirmButton/ConfirmButton.hooks.d.ts +22 -0
  126. package/dist/react/components/ConfirmButton/ConfirmButton.hooks.d.ts.map +1 -0
  127. package/dist/react/components/ConfirmButton/ConfirmButton.hooks.js +59 -0
  128. package/dist/react/components/ConfirmButton/ConfirmButton.hooks.js.map +1 -0
  129. package/dist/react/components/ConfirmButton/ConfirmButton.js +40 -0
  130. package/dist/react/components/ConfirmButton/ConfirmButton.js.map +1 -0
  131. package/dist/react/components/ConfirmButton.d.ts +39 -0
  132. package/dist/react/components/ConfirmButton.d.ts.map +1 -0
  133. package/dist/react/components/ConfirmButton.js +79 -0
  134. package/dist/react/components/ConfirmButton.js.map +1 -0
  135. package/dist/react/components/ConfirmDialog/ConfirmDialog.d.ts +90 -0
  136. package/dist/react/components/ConfirmDialog/ConfirmDialog.d.ts.map +1 -0
  137. package/dist/react/components/ConfirmDialog/ConfirmDialog.hooks.d.ts +49 -0
  138. package/dist/react/components/ConfirmDialog/ConfirmDialog.hooks.d.ts.map +1 -0
  139. package/dist/react/components/ConfirmDialog/ConfirmDialog.hooks.js +81 -0
  140. package/dist/react/components/ConfirmDialog/ConfirmDialog.hooks.js.map +1 -0
  141. package/dist/react/components/ConfirmDialog/ConfirmDialog.js +92 -0
  142. package/dist/react/components/ConfirmDialog/ConfirmDialog.js.map +1 -0
  143. package/dist/react/components/ConfirmDialog.d.ts +57 -0
  144. package/dist/react/components/ConfirmDialog.d.ts.map +1 -0
  145. package/dist/react/components/ConfirmDialog.js +85 -0
  146. package/dist/react/components/ConfirmDialog.js.map +1 -0
  147. package/dist/react/components/DataTable.d.ts +97 -0
  148. package/dist/react/components/DataTable.d.ts.map +1 -0
  149. package/dist/react/components/DataTable.js +20 -0
  150. package/dist/react/components/DataTable.js.map +1 -0
  151. package/dist/react/components/InteractiveHtmlEditor/InteractiveHtmlEditor.d.ts +25 -0
  152. package/dist/react/components/InteractiveHtmlEditor/InteractiveHtmlEditor.d.ts.map +1 -0
  153. package/dist/react/components/InteractiveHtmlEditor/InteractiveHtmlEditor.js +148 -0
  154. package/dist/react/components/InteractiveHtmlEditor/InteractiveHtmlEditor.js.map +1 -0
  155. package/dist/react/components/RowMenu/RowMenu.d.ts +77 -0
  156. package/dist/react/components/RowMenu/RowMenu.d.ts.map +1 -0
  157. package/dist/react/components/RowMenu/RowMenu.hooks.d.ts +30 -0
  158. package/dist/react/components/RowMenu/RowMenu.hooks.d.ts.map +1 -0
  159. package/dist/react/components/RowMenu/RowMenu.hooks.js +154 -0
  160. package/dist/react/components/RowMenu/RowMenu.hooks.js.map +1 -0
  161. package/dist/react/components/RowMenu/RowMenu.js +46 -0
  162. package/dist/react/components/RowMenu/RowMenu.js.map +1 -0
  163. package/dist/react/components/RowMenu.d.ts +44 -0
  164. package/dist/react/components/RowMenu.d.ts.map +1 -0
  165. package/dist/react/components/RowMenu.js +149 -0
  166. package/dist/react/components/RowMenu.js.map +1 -0
  167. package/dist/react/components/Sidebar.d.ts +128 -0
  168. package/dist/react/components/Sidebar.d.ts.map +1 -0
  169. package/dist/react/components/Sidebar.js +168 -0
  170. package/dist/react/components/Sidebar.js.map +1 -0
  171. package/dist/react/hooks/use-nav-sections.d.ts +50 -0
  172. package/dist/react/hooks/use-nav-sections.d.ts.map +1 -0
  173. package/dist/react/hooks/use-nav-sections.js +112 -0
  174. package/dist/react/hooks/use-nav-sections.js.map +1 -0
  175. package/dist/react/hooks/use-sidebar-rail.d.ts +39 -0
  176. package/dist/react/hooks/use-sidebar-rail.d.ts.map +1 -0
  177. package/dist/react/hooks/use-sidebar-rail.js +93 -0
  178. package/dist/react/hooks/use-sidebar-rail.js.map +1 -0
  179. package/dist/react/index.d.ts +53 -0
  180. package/dist/react/index.d.ts.map +1 -0
  181. package/dist/react/index.js +53 -0
  182. package/dist/react/index.js.map +1 -0
  183. package/dist/react/types.d.ts +28 -0
  184. package/dist/react/types.d.ts.map +1 -0
  185. package/dist/react/types.js +23 -0
  186. package/dist/react/types.js.map +1 -0
  187. package/dist/server/composio/bounded-data.d.ts +36 -0
  188. package/dist/server/composio/bounded-data.d.ts.map +1 -0
  189. package/dist/server/composio/bounded-data.js +181 -0
  190. package/dist/server/composio/bounded-data.js.map +1 -0
  191. package/dist/server/composio/catalog.d.ts +147 -0
  192. package/dist/server/composio/catalog.d.ts.map +1 -0
  193. package/dist/server/composio/catalog.js +126 -0
  194. package/dist/server/composio/catalog.js.map +1 -0
  195. package/dist/server/composio/composio-config.d.ts +42 -0
  196. package/dist/server/composio/composio-config.d.ts.map +1 -0
  197. package/dist/server/composio/composio-config.js +145 -0
  198. package/dist/server/composio/composio-config.js.map +1 -0
  199. package/dist/server/composio/composio-descriptions.d.ts +16 -0
  200. package/dist/server/composio/composio-descriptions.d.ts.map +1 -0
  201. package/dist/server/composio/composio-descriptions.js +766 -0
  202. package/dist/server/composio/composio-descriptions.js.map +1 -0
  203. package/dist/server/composio/composio.d.ts +364 -0
  204. package/dist/server/composio/composio.d.ts.map +1 -0
  205. package/dist/server/composio/composio.js +1902 -0
  206. package/dist/server/composio/composio.js.map +1 -0
  207. package/dist/server/composio/errors.d.ts +15 -0
  208. package/dist/server/composio/errors.d.ts.map +1 -0
  209. package/dist/server/composio/errors.js +16 -0
  210. package/dist/server/composio/errors.js.map +1 -0
  211. package/dist/server/composio/file-lock.d.ts +13 -0
  212. package/dist/server/composio/file-lock.d.ts.map +1 -0
  213. package/dist/server/composio/file-lock.js +92 -0
  214. package/dist/server/composio/file-lock.js.map +1 -0
  215. package/dist/server/composio/index.d.ts +18 -0
  216. package/dist/server/composio/index.d.ts.map +1 -0
  217. package/dist/server/composio/index.js +7 -0
  218. package/dist/server/composio/index.js.map +1 -0
  219. package/dist/server/composio/json-schema.d.ts +93 -0
  220. package/dist/server/composio/json-schema.d.ts.map +1 -0
  221. package/dist/server/composio/json-schema.js +498 -0
  222. package/dist/server/composio/json-schema.js.map +1 -0
  223. package/dist/server/composio/output-protection.d.ts +32 -0
  224. package/dist/server/composio/output-protection.d.ts.map +1 -0
  225. package/dist/server/composio/output-protection.js +105 -0
  226. package/dist/server/composio/output-protection.js.map +1 -0
  227. package/dist/server/composio/service.d.ts +181 -0
  228. package/dist/server/composio/service.d.ts.map +1 -0
  229. package/dist/server/composio/service.js +758 -0
  230. package/dist/server/composio/service.js.map +1 -0
  231. package/dist/server/index.d.ts +15 -0
  232. package/dist/server/index.d.ts.map +1 -0
  233. package/dist/server/index.js +15 -0
  234. package/dist/server/index.js.map +1 -0
  235. package/package.json +92 -0
@@ -0,0 +1,179 @@
1
+ /**
2
+ * @file `AdminMenusPort` — editable navigation trees (menus), and their assignment to named theme
3
+ * locations.
4
+ *
5
+ * ## `AdminMenuTarget` and the content-model leak
6
+ *
7
+ * The reference implementation's own link-target union ties two of its four kinds directly to its
8
+ * content model: `entryRef` points at a content-item id, `termRef` points at a taxonomy-term id plus its
9
+ * taxonomy name. Baking exactly those four kinds into this port as a CLOSED union would mean any
10
+ * host without an "entry"/"taxonomy term" concept (or with additional native reference kinds of
11
+ * its own — a product, a collection, ...) could never express its own link targets through this
12
+ * contract at all; it would have to fake them as `url` targets, defeating the point of a typed
13
+ * target. `AdminMenuTarget` therefore keeps the 4 reference-implementation kinds as their own typed
14
+ * variants (they are reasonably generic CMS concepts, not literally "post"/"page") but adds
15
+ * `AdminMenuCustomTarget` as a fifth, open-`kind` escape hatch for anything else a host needs.
16
+ *
17
+ * This has a real, deliberate type-safety cost worth knowing before you rely on it: because
18
+ * `AdminMenuCustomTarget.kind` is `string & {}`, it structurally overlaps every literal kind below
19
+ * it — narrowing `AdminMenuTarget` by `target.kind === "entryRef"` does not, on its own, fully
20
+ * exclude `AdminMenuCustomTarget` from the narrowed type the way it would exclude
21
+ * `AdminMenuTermTarget`/`AdminMenuUrlTarget`/`AdminMenuRouteTarget`. In practice this only shows up
22
+ * as a compile error if you then try to access a known-target-only field (e.g. `.entryId`) without
23
+ * having ruled out the custom-target case first, since `AdminMenuCustomTarget` carries no such
24
+ * field — TypeScript will refuse the access rather than silently mistype it. A `switch` over all 5
25
+ * `kind` values (with `AdminMenuCustomTarget` as the `default` arm) is the straightforward way to
26
+ * stay correct.
27
+ *
28
+ * **This is a deliberately deferred decision, not a settled one — record it as such.** `entryRef`/
29
+ * `termRef` encode a host content model (an "entry" and a "taxonomy term" are the reference
30
+ * implementation's own vocabulary for its content system, not a vendor-neutral abstraction this
31
+ * package has designed). A host with no entries or taxonomies should emit only `url`/`route`
32
+ * targets and ignore those two variants entirely; it is not expected to reinterpret them. This was
33
+ * deliberately NOT generalized into a single vendor-neutral "content reference" shape, because
34
+ * there is exactly one host implementation in this corpus today — designing a generic content-reference abstraction from a single
35
+ * example is how a package acquires the wrong abstraction permanently, not how it becomes generic.
36
+ * Widening `kind` (this file) costs nothing and preserves the option without committing to a shape.
37
+ * **Trigger for revisiting:** a second host needs a link-target kind that is neither `entryRef`,
38
+ * `termRef`, `url`, nor `route` — at that point there are two real examples to generalize from
39
+ * instead of one, and a genuine vendor-neutral reference shape (rather than another bespoke
40
+ * `kind`-per-host member) becomes the right call.
41
+ *
42
+ * ## `deleteMenu` is a two-rung ladder driven by call count, not by `force` alone
43
+ *
44
+ * A single method models a two-step deletion flow: the FIRST call against a non-trashed menu
45
+ * always soft-deletes it (status flips, resolves `{ purged: false }`) regardless of `force` or
46
+ * location bindings. Only a SECOND call — against a menu that is already trashed — attempts the
47
+ * real purge, which is rejected (conflict-class, with the still-bound location keys) if the menu is
48
+ * still assigned to any theme location, unless `options.force` is set. This is a third distinct
49
+ * deletion shape in this port set, different from both `AdminIntegrationsPort`'s permanent-soft-
50
+ * delete-only and `AdminMediaPort`'s two-separate-methods (`trashMedia`/`deleteMedia`) split: here
51
+ * it is the SAME method, and which rung it hits depends on the menu's current state, not on an
52
+ * argument you pass. A panel must track (or re-fetch) whether a menu is already trashed to know
53
+ * what calling `deleteMenu` again will actually do.
54
+ *
55
+ * ## `assignMenuLocation` can displace another menu (last-writer-wins)
56
+ *
57
+ * Assigning a menu to a location key that is already bound to a *different* menu unassigns that
58
+ * other menu from the location (dropping the key from its own `locations`) rather than rejecting
59
+ * the call. `AdminAssignMenuLocationResult.displacedMenu` carries that menu's post-displacement
60
+ * state so a panel can show what changed; it is `null` when the location was unbound or already
61
+ * held by the menu being assigned.
62
+ *
63
+ * ## Open vs. closed unions
64
+ *
65
+ * `NavTargetKind` and `MenuStatus` are reference-implementation-specific vocabularies (the former further discussed
66
+ * above) — OPEN, via the `T | (string & {})` idiom `seo.ts`'s file header introduces for this port
67
+ * set.
68
+ */
69
+ /** The known target-kind discriminants — open, see file header. */
70
+ export type NavTargetKind = "entryRef" | "termRef" | "url" | "route" | (string & {});
71
+ /** A link to another content item, by opaque id. */
72
+ export interface AdminMenuEntryTarget {
73
+ readonly kind: "entryRef";
74
+ readonly entryId: string;
75
+ }
76
+ /** A link to a taxonomy term (category/tag archive, or a host's closest equivalent grouping). */
77
+ export interface AdminMenuTermTarget {
78
+ readonly kind: "termRef";
79
+ readonly termId: string;
80
+ /** Which taxonomy `termId` belongs to. */
81
+ readonly taxonomy: string;
82
+ }
83
+ /** An absolute or site-relative external URL. */
84
+ export interface AdminMenuUrlTarget {
85
+ readonly kind: "url";
86
+ readonly href: string;
87
+ }
88
+ /** A named host route (e.g. `home`, `search`). */
89
+ export interface AdminMenuRouteTarget {
90
+ readonly kind: "route";
91
+ readonly route: string;
92
+ readonly params?: Record<string, unknown>;
93
+ }
94
+ /** A host-specific target kind beyond the 4 above — see file header for the narrowing tradeoff
95
+ * this member introduces. `data` is opaque to this port; the host defines its own shape. */
96
+ export interface AdminMenuCustomTarget {
97
+ readonly kind: string & {};
98
+ readonly data?: Record<string, unknown>;
99
+ }
100
+ export type AdminMenuTarget = AdminMenuEntryTarget | AdminMenuTermTarget | AdminMenuUrlTarget | AdminMenuRouteTarget | AdminMenuCustomTarget;
101
+ export interface AdminMenuItemAttrs {
102
+ readonly openInNewTab?: boolean;
103
+ /** `rel` tokens (e.g. `nofollow`). */
104
+ readonly rel?: string;
105
+ readonly cssClass?: string;
106
+ readonly description?: string;
107
+ readonly icon?: string;
108
+ }
109
+ /** One node in a menu's item tree. Ordering is array order among siblings; nesting is `children`.
110
+ * `id` must be stable across edits (see `updateMenuTree`) — never regenerate it on reorder. */
111
+ export interface AdminMenuItem {
112
+ readonly id: string;
113
+ /** As stored — this port does not fall back to the target's own title when absent. (The
114
+ * reference implementation only applies that fallback in its separate, unexposed render-time
115
+ * resolution model; the raw item this port returns leaves an absent label absent.) A panel
116
+ * wanting a display fallback must compute one itself. */
117
+ readonly label?: string;
118
+ readonly target: AdminMenuTarget;
119
+ readonly attrs?: AdminMenuItemAttrs;
120
+ readonly children?: readonly AdminMenuItem[];
121
+ }
122
+ /** Lifecycle of a menu itself — open, see file header. */
123
+ export type MenuStatus = "draft" | "published" | "trash" | (string & {});
124
+ export interface AdminMenu {
125
+ readonly id: string;
126
+ readonly slug: string;
127
+ readonly title: string;
128
+ readonly status: MenuStatus;
129
+ readonly items: readonly AdminMenuItem[];
130
+ /** Theme-location keys this menu currently fills. */
131
+ readonly locations: readonly string[];
132
+ readonly updatedAt: string;
133
+ readonly version: number;
134
+ }
135
+ export interface AdminMenuCreateInput {
136
+ readonly title: string;
137
+ readonly slug: string;
138
+ /** Defaults to an empty menu when omitted. Every item needs a stable `id`. */
139
+ readonly items?: readonly AdminMenuItem[];
140
+ }
141
+ export interface AdminMenuUpdateTreeInput {
142
+ /** The `version` this edit was based on — optimistic-concurrency guard; expect a conflict-class
143
+ * rejection if the menu was modified since. */
144
+ readonly expectedVersion: number;
145
+ readonly title?: string;
146
+ readonly slug?: string;
147
+ /** The FULL replacement tree — this is a whole-tree replace, not a per-item patch. */
148
+ readonly items: readonly AdminMenuItem[];
149
+ }
150
+ export interface AdminMenuBinding {
151
+ readonly locationKey: string;
152
+ readonly menuId: string;
153
+ readonly boundAt: string;
154
+ }
155
+ export interface AdminAssignMenuLocationResult {
156
+ readonly menu: AdminMenu;
157
+ readonly binding: AdminMenuBinding;
158
+ /** See file header (last-writer-wins displacement). */
159
+ readonly displacedMenu: AdminMenu | null;
160
+ }
161
+ export interface AdminDeleteMenuResult {
162
+ /** Null only after a successful purge (the second-rung outcome) — see file header. */
163
+ readonly menu: AdminMenu | null;
164
+ readonly purged: boolean;
165
+ }
166
+ export interface AdminMenusPort {
167
+ listMenus(): Promise<readonly AdminMenu[]>;
168
+ getMenu(id: string): Promise<AdminMenu>;
169
+ createMenu(input: AdminMenuCreateInput): Promise<AdminMenu>;
170
+ updateMenuTree(id: string, input: AdminMenuUpdateTreeInput): Promise<AdminMenu>;
171
+ /** Two-rung ladder driven by the menu's current trashed state, not solely by `options.force` —
172
+ * see file header before assuming what a given call will do. */
173
+ deleteMenu(id: string, options?: {
174
+ force?: boolean;
175
+ }): Promise<AdminDeleteMenuResult>;
176
+ /** May displace another menu already bound to `locationKey` — see file header. */
177
+ assignMenuLocation(id: string, locationKey: string): Promise<AdminAssignMenuLocationResult>;
178
+ }
179
+ //# sourceMappingURL=menus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"menus.d.ts","sourceRoot":"","sources":["../../../src/core/ports/menus.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * @file `AdminMenusPort` — editable navigation trees (menus), and their assignment to named theme
3
+ * locations.
4
+ *
5
+ * ## `AdminMenuTarget` and the content-model leak
6
+ *
7
+ * The reference implementation's own link-target union ties two of its four kinds directly to its
8
+ * content model: `entryRef` points at a content-item id, `termRef` points at a taxonomy-term id plus its
9
+ * taxonomy name. Baking exactly those four kinds into this port as a CLOSED union would mean any
10
+ * host without an "entry"/"taxonomy term" concept (or with additional native reference kinds of
11
+ * its own — a product, a collection, ...) could never express its own link targets through this
12
+ * contract at all; it would have to fake them as `url` targets, defeating the point of a typed
13
+ * target. `AdminMenuTarget` therefore keeps the 4 reference-implementation kinds as their own typed
14
+ * variants (they are reasonably generic CMS concepts, not literally "post"/"page") but adds
15
+ * `AdminMenuCustomTarget` as a fifth, open-`kind` escape hatch for anything else a host needs.
16
+ *
17
+ * This has a real, deliberate type-safety cost worth knowing before you rely on it: because
18
+ * `AdminMenuCustomTarget.kind` is `string & {}`, it structurally overlaps every literal kind below
19
+ * it — narrowing `AdminMenuTarget` by `target.kind === "entryRef"` does not, on its own, fully
20
+ * exclude `AdminMenuCustomTarget` from the narrowed type the way it would exclude
21
+ * `AdminMenuTermTarget`/`AdminMenuUrlTarget`/`AdminMenuRouteTarget`. In practice this only shows up
22
+ * as a compile error if you then try to access a known-target-only field (e.g. `.entryId`) without
23
+ * having ruled out the custom-target case first, since `AdminMenuCustomTarget` carries no such
24
+ * field — TypeScript will refuse the access rather than silently mistype it. A `switch` over all 5
25
+ * `kind` values (with `AdminMenuCustomTarget` as the `default` arm) is the straightforward way to
26
+ * stay correct.
27
+ *
28
+ * **This is a deliberately deferred decision, not a settled one — record it as such.** `entryRef`/
29
+ * `termRef` encode a host content model (an "entry" and a "taxonomy term" are the reference
30
+ * implementation's own vocabulary for its content system, not a vendor-neutral abstraction this
31
+ * package has designed). A host with no entries or taxonomies should emit only `url`/`route`
32
+ * targets and ignore those two variants entirely; it is not expected to reinterpret them. This was
33
+ * deliberately NOT generalized into a single vendor-neutral "content reference" shape, because
34
+ * there is exactly one host implementation in this corpus today — designing a generic content-reference abstraction from a single
35
+ * example is how a package acquires the wrong abstraction permanently, not how it becomes generic.
36
+ * Widening `kind` (this file) costs nothing and preserves the option without committing to a shape.
37
+ * **Trigger for revisiting:** a second host needs a link-target kind that is neither `entryRef`,
38
+ * `termRef`, `url`, nor `route` — at that point there are two real examples to generalize from
39
+ * instead of one, and a genuine vendor-neutral reference shape (rather than another bespoke
40
+ * `kind`-per-host member) becomes the right call.
41
+ *
42
+ * ## `deleteMenu` is a two-rung ladder driven by call count, not by `force` alone
43
+ *
44
+ * A single method models a two-step deletion flow: the FIRST call against a non-trashed menu
45
+ * always soft-deletes it (status flips, resolves `{ purged: false }`) regardless of `force` or
46
+ * location bindings. Only a SECOND call — against a menu that is already trashed — attempts the
47
+ * real purge, which is rejected (conflict-class, with the still-bound location keys) if the menu is
48
+ * still assigned to any theme location, unless `options.force` is set. This is a third distinct
49
+ * deletion shape in this port set, different from both `AdminIntegrationsPort`'s permanent-soft-
50
+ * delete-only and `AdminMediaPort`'s two-separate-methods (`trashMedia`/`deleteMedia`) split: here
51
+ * it is the SAME method, and which rung it hits depends on the menu's current state, not on an
52
+ * argument you pass. A panel must track (or re-fetch) whether a menu is already trashed to know
53
+ * what calling `deleteMenu` again will actually do.
54
+ *
55
+ * ## `assignMenuLocation` can displace another menu (last-writer-wins)
56
+ *
57
+ * Assigning a menu to a location key that is already bound to a *different* menu unassigns that
58
+ * other menu from the location (dropping the key from its own `locations`) rather than rejecting
59
+ * the call. `AdminAssignMenuLocationResult.displacedMenu` carries that menu's post-displacement
60
+ * state so a panel can show what changed; it is `null` when the location was unbound or already
61
+ * held by the menu being assigned.
62
+ *
63
+ * ## Open vs. closed unions
64
+ *
65
+ * `NavTargetKind` and `MenuStatus` are reference-implementation-specific vocabularies (the former further discussed
66
+ * above) — OPEN, via the `T | (string & {})` idiom `seo.ts`'s file header introduces for this port
67
+ * set.
68
+ */
69
+ export {};
70
+ //# sourceMappingURL=menus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"menus.js","sourceRoot":"","sources":["../../../src/core/ports/menus.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmEG"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * @file `AdminExtensionsPort` — installed extensions (the reference implementation calls them
3
+ * "plugins") and their
4
+ * enabled/disabled state.
5
+ *
6
+ * ## Why the port is "Extensions" but the DTO and methods say "Plugin"
7
+ *
8
+ * The port interface is named generically because not every host will call this mechanism
9
+ * "plugins" — some call the same concept "add-ons" or "extensions" in their own product copy.
10
+ * The DTO (`AdminPlugin`) and method names (`listPlugins`/`setPluginEnabled`) keep the reference
11
+ * implementation's own vocabulary rather than being renamed to match, because "plugin" is itself
12
+ * already a generic, industry-standard term (not product-specific jargon the way `workspace-local`
13
+ * or `/api/admin/v1` are) and because the calling code this port replaces already uses these exact
14
+ * names — renaming
15
+ * both the port and its members would be a bigger, noisier diff for no behavioral gain. A host
16
+ * that genuinely prefers "extension" throughout is free to alias at the call site.
17
+ *
18
+ * ## `changeSetId` is an opaque audit handle, not a claim every host has "change sets"
19
+ *
20
+ * `setExtensionEnabled`'s response carries a `changeSetId` because the reference implementation
21
+ * versions every mutating admin action through a change-set/revert subsystem. This port keeps the
22
+ * field — real callers may want to link to an audit trail — but treats it as an opaque string a
23
+ * host can use however its own audit mechanism works, not a promise that "change set" is a concept
24
+ * every implementation shares.
25
+ */
26
+ /** An installed extension and its trust/validity state. */
27
+ export interface AdminPlugin {
28
+ readonly id: string;
29
+ readonly name: string;
30
+ readonly version: string;
31
+ /** `"built-in"` ships with the host itself; `"site"` was installed for this particular
32
+ * installation/tenant. */
33
+ readonly source: "built-in" | "site";
34
+ /** Trust tier driving how much a panel should warn before enabling this extension — lower
35
+ * numbers are more trusted. Not ordered numerically on the wire on purpose (host-defined
36
+ * labels), see `../transport/errors.ts`'s header for the same "vocabulary belongs to the host"
37
+ * reasoning applied to error codes. */
38
+ readonly tier: "tier-1" | "tier-2" | "tier-3";
39
+ /** Whether the extension currently passes the host's own structural/compatibility checks —
40
+ * independent of `enabled`. An extension can be `"valid"` and still `enabled: false`, or
41
+ * `"invalid"`/`"incompatible"` while still `enabled: true` from a prior state the host has not
42
+ * auto-disabled. */
43
+ readonly status: "valid" | "invalid" | "incompatible";
44
+ readonly enabled: boolean;
45
+ readonly errors: readonly {
46
+ code: string;
47
+ file: string | null;
48
+ message: string;
49
+ }[];
50
+ }
51
+ /** `setExtensionEnabled`'s response — a trimmed extension summary plus an audit handle, not the
52
+ * full `AdminPlugin`. See the file header on `changeSetId`. */
53
+ export interface AdminExtensionEnabledResult {
54
+ readonly extension: {
55
+ id: string;
56
+ version: string;
57
+ enabled: boolean;
58
+ updatedAt: string;
59
+ };
60
+ readonly changeSetId: string;
61
+ }
62
+ export interface AdminExtensionsPort {
63
+ listPlugins(): Promise<readonly AdminPlugin[]>;
64
+ setPluginEnabled(id: string, input: {
65
+ enabled: boolean;
66
+ }): Promise<AdminExtensionEnabledResult>;
67
+ }
68
+ //# sourceMappingURL=plugins.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugins.d.ts","sourceRoot":"","sources":["../../../src/core/ports/plugins.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,2DAA2D;AAC3D,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB;+BAC2B;IAC3B,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAAC;IACrC;;;4CAGwC;IACxC,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAC9C;;;yBAGqB;IACrB,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,cAAc,CAAC;IACtD,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,SAAS;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACpF;AAED;gEACgE;AAChE,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,SAAS,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IACzF,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,mBAAmB;IAClC,WAAW,IAAI,OAAO,CAAC,SAAS,WAAW,EAAE,CAAC,CAAC;IAC/C,gBAAgB,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,2BAA2B,CAAC,CAAC;CACjG"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * @file `AdminExtensionsPort` — installed extensions (the reference implementation calls them
3
+ * "plugins") and their
4
+ * enabled/disabled state.
5
+ *
6
+ * ## Why the port is "Extensions" but the DTO and methods say "Plugin"
7
+ *
8
+ * The port interface is named generically because not every host will call this mechanism
9
+ * "plugins" — some call the same concept "add-ons" or "extensions" in their own product copy.
10
+ * The DTO (`AdminPlugin`) and method names (`listPlugins`/`setPluginEnabled`) keep the reference
11
+ * implementation's own vocabulary rather than being renamed to match, because "plugin" is itself
12
+ * already a generic, industry-standard term (not product-specific jargon the way `workspace-local`
13
+ * or `/api/admin/v1` are) and because the calling code this port replaces already uses these exact
14
+ * names — renaming
15
+ * both the port and its members would be a bigger, noisier diff for no behavioral gain. A host
16
+ * that genuinely prefers "extension" throughout is free to alias at the call site.
17
+ *
18
+ * ## `changeSetId` is an opaque audit handle, not a claim every host has "change sets"
19
+ *
20
+ * `setExtensionEnabled`'s response carries a `changeSetId` because the reference implementation
21
+ * versions every mutating admin action through a change-set/revert subsystem. This port keeps the
22
+ * field — real callers may want to link to an audit trail — but treats it as an opaque string a
23
+ * host can use however its own audit mechanism works, not a promise that "change set" is a concept
24
+ * every implementation shares.
25
+ */
26
+ export {};
27
+ //# sourceMappingURL=plugins.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugins.js","sourceRoot":"","sources":["../../../src/core/ports/plugins.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG"}
@@ -0,0 +1,171 @@
1
+ /**
2
+ * @file `AdminRecoveryPort` — point-in-time restore: what can be restored to, what would be lost,
3
+ * and the restore ceremony itself.
4
+ *
5
+ * `AdminRestorePoint` is imported from `./database.js` rather than redeclared — see that file's
6
+ * header for why Database and Recovery are two views onto one persisted set.
7
+ *
8
+ * ## The restore triad IS a `GatedOperation` — with operation-specific confirm/execute input
9
+ *
10
+ * `./database.js`'s `migrateForward` is the simple case: none of its three calls needs input
11
+ * beyond the token the previous step produced. Restore needs two more fields —
12
+ *
13
+ * - `confirm` also carries `disclosureAcknowledged`: the operator must affirmatively accept the
14
+ * data-loss disclosure `computeRecoveryDisclosure` computed, not merely echo back a token; and
15
+ * - `execute` also carries `restorePointId`: belt-and-suspenders against a confirmation token
16
+ * being replayed against a different target than the one it was confirmed for.
17
+ *
18
+ * `GatedOperation` carries `TConfirmInput`/`TExecuteInput` type parameters (defaulting to `string`)
19
+ * for exactly this, so restore is declared as a real `GatedOperation` rather than three loose
20
+ * methods. See `../gated/types.js` for the full rationale — in short, `disclosureAcknowledged`
21
+ * shows the protocol is *recorded informed consent* rather than a two-step token handshake, and
22
+ * restore is the most destructive operation a host exposes, so it is the last thing that should sit
23
+ * outside the abstraction built for that ceremony.
24
+ *
25
+ * A first draft of this file argued the opposite, against an earlier `confirm(token: string)`
26
+ * signature, and predicted the widening that has since happened. Kept as a note because the
27
+ * inference was right: if a fourth ceremony needs something this shape still cannot express, that
28
+ * is a signal about `GatedOperation`, not a reason for the caller to opt out of it.
29
+ *
30
+ * ## The deep-link envelope carries display continuity only, never authority
31
+ *
32
+ * `DatabaseContextEnvelope` (used by `resolveRecoveryDeepLink`) is how a panel preserves "which
33
+ * restore point was I just looking at" across a navigation — e.g. a link from the database timeline
34
+ * into recovery. A host must always re-verify `restorePointId` server-side rather than trusting the
35
+ * envelope's contents as authorization; the envelope existing does not mean the operation it
36
+ * references is still valid or still permitted for the caller presenting it.
37
+ */
38
+ import type { AdminRestorePoint, RestorePointCostClass } from './database.js';
39
+ import type { GatedOperation } from '../gated/types.js';
40
+ /** A count that may be unknown rather than a real number — used where computing an exact count
41
+ * would be prohibitively expensive for at least one category. */
42
+ export type CategoryCount = number | "unknown";
43
+ /**
44
+ * What would be lost or affected by restoring to a given point, broken down by category. `partial`
45
+ * is always `true`: this is a best-effort disclosure, not a guarantee that no other consequence
46
+ * exists — see `watermarkBaselineAvailable` for one specific case where the disclosure itself is
47
+ * degraded.
48
+ */
49
+ export interface AdminDisclosureResult {
50
+ readonly partial: true;
51
+ /** `false` means the disclosure could not establish a watermark baseline to diff against — the
52
+ * `counts` below may be less trustworthy than usual, and a panel should say so rather than
53
+ * present them with the same confidence as a normal disclosure. */
54
+ readonly watermarkBaselineAvailable: boolean;
55
+ readonly counts: Readonly<Record<string, CategoryCount>>;
56
+ }
57
+ /** Reasons the recovery feature itself may be degraded right now, independent of any one restore
58
+ * point — surfaced by `getRecoveryStatus` so a panel can explain *why* recovery is unavailable
59
+ * rather than just failing silently. */
60
+ export type DegradedBannerKind = "migration-interrupted" | "pending-migration" | "operation-in-flight" | "cost-unavailable" | "watermark-baseline-unavailable";
61
+ export type DegradedBannerActionKind = "deep-link-to-database-migration" | "unblock-interrupted-migration" | "none";
62
+ export interface AdminDegradedBanner {
63
+ readonly kind: DegradedBannerKind;
64
+ /** Pre-composed, host-owned copy — render as-is rather than deriving text from `kind`, for the
65
+ * same reason `GatedPlanResult.warnings` is rendered as-is (see `../gated/types.ts`). */
66
+ readonly accessibleText: string;
67
+ readonly actionKind: DegradedBannerActionKind;
68
+ }
69
+ export interface AdminRecoveryStatus {
70
+ readonly costClass: RestorePointCostClass;
71
+ readonly banner: AdminDegradedBanner | null;
72
+ }
73
+ /**
74
+ * An opaque envelope a panel round-trips through a deep link to preserve display continuity across
75
+ * navigation. Treat every field as informational — see the file header on why `restorePointId`
76
+ * here is never authoritative.
77
+ */
78
+ export interface DatabaseContextEnvelope {
79
+ readonly v: number;
80
+ readonly correlationId: string;
81
+ readonly siteId: string;
82
+ readonly ledgerEventId: string | null;
83
+ readonly restorePointId: string | null;
84
+ /** Host-defined description of how far the envelope's view of the world has drifted from
85
+ * current reality by the time it is resolved (e.g. `"none"`, `"stale"`). */
86
+ readonly drift: string;
87
+ /** What the envelope was created to let the operator do (e.g. `"view"`, `"restore"`). */
88
+ readonly intent: string;
89
+ readonly issuedAt: string;
90
+ }
91
+ export interface AdminRecoveryDeepLinkResult {
92
+ readonly found: boolean;
93
+ readonly restorePoint: {
94
+ restorePointId: string;
95
+ capturedAt: string;
96
+ } | null;
97
+ }
98
+ /**
99
+ * What `restore.confirm` takes. The `token` comes from `restore.plan`'s `GatedPlanResult`.
100
+ *
101
+ * ## Adapter obligation: `token` is opaque, and a host may have to compose it
102
+ *
103
+ * Deliberately one opaque `token`, not the reference host's raw field pair. Its wire protocol
104
+ * confirms a restore with `{planId, planHash}` — two fields — and its plan step returns them
105
+ * separately. Exposing that pair here would contradict `GatedPlanResult.token`'s own contract
106
+ * ("opaque; panels must not parse or construct these"): a panel assembling `planId` + `planHash`
107
+ * into a confirm call *is* reconstructing the token, which is the thing that contract forbids.
108
+ *
109
+ * So the composition is the **route-factory adapter's** job, not the panel's: encode the host's
110
+ * plan identity into one string on the way out of `plan`, decode it on the way into `confirm`. A
111
+ * host whose protocol already uses a single token does nothing. This is the same division of labour
112
+ * as `settings.ts`'s `value`, where the adapter owns any JSON encoding the wire format needs.
113
+ *
114
+ * Whoever writes the reference implementation's adapter: this is a real responsibility with no compiler support. Getting it
115
+ * wrong surfaces as a confirm that is rejected server-side for a plan the operator can see on
116
+ * screen — so encode both halves, and fail loudly on a token you cannot decode rather than sending
117
+ * a partial one.
118
+ */
119
+ export interface RestoreConfirmInput {
120
+ readonly token: string;
121
+ /**
122
+ * Must be `true` — the operator has seen `computeRecoveryDisclosure`'s result and accepted it.
123
+ *
124
+ * A host must **reject** the confirm outright when this is `false`, not merely warn. This field
125
+ * is the recorded-consent half of the ceremony; treating it as advisory turns the whole gated
126
+ * protocol back into a confirmation dialog.
127
+ */
128
+ readonly disclosureAcknowledged: boolean;
129
+ }
130
+ /** What `restore.execute` takes. `confirmToken` comes from `restore.confirm`'s result. */
131
+ export interface RestoreExecuteInput {
132
+ readonly confirmToken: string;
133
+ /** Re-stated so the server can verify the token was confirmed for *this* target. A host must
134
+ * re-verify server-side rather than trusting the caller-supplied id. */
135
+ readonly restorePointId: string;
136
+ }
137
+ /** `restore.execute`'s terminal result. */
138
+ export interface RestoreExecuteResult {
139
+ readonly restoreRunId: string;
140
+ /** Host-defined run state (e.g. `"completed"`, `"failed"`). */
141
+ readonly state: string;
142
+ readonly databaseTimelineDeepLink?: {
143
+ v: 1;
144
+ siteId: string;
145
+ intent: "view";
146
+ };
147
+ /**
148
+ * `true` when the restore physically swapped the underlying database and the server process
149
+ * needs an operator-triggered restart to pick it up. Until restarted, the running process may
150
+ * keep serving pre-restore data from an already-open file handle — a panel should surface this
151
+ * as a required follow-up action, not a background detail.
152
+ */
153
+ readonly restartRequired?: boolean;
154
+ }
155
+ export interface AdminRecoveryPort {
156
+ /** Same underlying set as `AdminDatabasePort.listDatabaseRestorePoints` — see the file header. */
157
+ listRecoveryRestorePoints(): Promise<readonly AdminRestorePoint[]>;
158
+ computeRecoveryDisclosure(restorePointId: string): Promise<AdminDisclosureResult>;
159
+ /** Resolves a deep-link envelope back into a restore point reference. `found: false` means the
160
+ * envelope no longer resolves to anything (e.g. the restore point it named was since purged) —
161
+ * not an error, a valid negative result a panel should render distinctly from a thrown error. */
162
+ resolveRecoveryDeepLink(envelope: DatabaseContextEnvelope): Promise<AdminRecoveryDeepLinkResult>;
163
+ getRecoveryStatus(): Promise<AdminRecoveryStatus>;
164
+ /**
165
+ * The restore ceremony: `restore.plan(restorePointId)` -> `restore.confirm(...)` ->
166
+ * `restore.execute(...)`. A real `GatedOperation`, so a shared confirmation component can drive
167
+ * it without knowing it is a restore — see the file header.
168
+ */
169
+ readonly restore: GatedOperation<string, unknown, RestoreExecuteResult, RestoreConfirmInput, RestoreExecuteInput>;
170
+ }
171
+ //# sourceMappingURL=recovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recovery.d.ts","sourceRoot":"","sources":["../../../src/core/ports/recovery.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=recovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recovery.js","sourceRoot":"","sources":["../../../src/core/ports/recovery.ts"],"names":[],"mappings":""}