@burdenoff/microfe-vibecontrols 2026.602.2 → 2026.602.4

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 (33) hide show
  1. package/dist/components/actions/ActionCard.js +87 -74
  2. package/dist/components/actions/ActionCard.js.map +1 -1
  3. package/dist/components/ai/InstructionFilesManager.js +149 -141
  4. package/dist/components/ai/InstructionFilesManager.js.map +1 -1
  5. package/dist/components/sessions/SessionShareDialog.js +24 -462
  6. package/dist/components/sessions/SessionShareDialog.js.map +1 -1
  7. package/dist/components/shared/EntityVibeLinkControl.js +204 -0
  8. package/dist/components/shared/EntityVibeLinkControl.js.map +1 -0
  9. package/dist/components/shared/index.js +1 -0
  10. package/dist/components/sharing/entityShareOps.js +106 -0
  11. package/dist/components/sharing/entityShareOps.js.map +1 -1
  12. package/dist/components/sharing/shareRegistry.js +3 -3
  13. package/dist/components/sharing/shareRegistry.js.map +1 -1
  14. package/dist/components/tunnels/TunnelCard.js +51 -43
  15. package/dist/components/tunnels/TunnelCard.js.map +1 -1
  16. package/dist/components/vibe/VibeLinkedEntitiesPanel.js +117 -89
  17. package/dist/components/vibe/VibeLinkedEntitiesPanel.js.map +1 -1
  18. package/dist/components/vibedeck/VibeDeckShareDialog.js +19 -335
  19. package/dist/components/vibedeck/VibeDeckShareDialog.js.map +1 -1
  20. package/dist/constants/permissions.js +1 -0
  21. package/dist/constants/permissions.js.map +1 -1
  22. package/dist/generated/wspace-operations.js +1618 -1593
  23. package/dist/generated/wspace-operations.js.map +1 -1
  24. package/dist/generated/wspace-types.js +10 -10
  25. package/dist/generated/wspace-types.js.map +1 -1
  26. package/dist/index.js +10 -10
  27. package/dist/pages/SessionsPage.js +1011 -1007
  28. package/dist/pages/SessionsPage.js.map +1 -1
  29. package/dist/pages/VibeDeckPage.js +218 -210
  30. package/dist/pages/VibeDeckPage.js.map +1 -1
  31. package/package.json +1 -1
  32. package/dist/utils/shareUrl.js +0 -41
  33. package/dist/utils/shareUrl.js.map +0 -1
@@ -0,0 +1,204 @@
1
+ import { useLinkEntityToVibeMutation as e, useListVibesQuery as t, useUnlinkEntityFromVibeMutation as n, useUpdateEntityVisibilityMutation as r } from "../../generated/wspace-operations.js";
2
+ import { useTr as i } from "../../shared/hooks/useTr.js";
3
+ import { VibeVisibility as a } from "../../generated/wspace-types.js";
4
+ import { useEffect as o, useMemo as s, useRef as c, useState as l } from "react";
5
+ import { Check as u, Link2 as d, Loader2 as f, Unlink as p } from "lucide-react";
6
+ import { jsx as m, jsxs as h } from "react/jsx-runtime";
7
+ //#region src/components/shared/EntityVibeLinkControl.tsx
8
+ function g({ entityType: g, entityId: _, currentVibeId: v, currentVisibility: y, refetchQueries: b, className: x = "" }) {
9
+ let S = i(), [C, w] = l(!1), [T, E] = l(v), [D, O] = l(y ?? a.SharedWithVibe), [k, A] = l(!1), [j, M] = l(null), N = c(null), { data: P, loading: F } = t({
10
+ variables: { pagination: { limit: 200 } },
11
+ fetchPolicy: "cache-first"
12
+ }), I = s(() => (P?.vibes?.items ?? []).map((e) => ({
13
+ id: e.id,
14
+ name: e.name
15
+ })), [P?.vibes?.items]), L = s(() => v ? I.find((e) => e.id === v)?.name ?? null : null, [v, I]), R = s(() => Array.from(new Set(["GetVibeLinkedEntities", ...b ?? []])), [b]), [z] = e(), [B] = n(), [V] = r();
16
+ o(() => {
17
+ C && (E(v), O(y ?? a.SharedWithVibe), M(null));
18
+ }, [
19
+ C,
20
+ v,
21
+ y
22
+ ]), o(() => {
23
+ if (!C) return;
24
+ let e = (e) => {
25
+ N.current?.contains(e.target) || w(!1);
26
+ };
27
+ return document.addEventListener("mousedown", e), () => document.removeEventListener("mousedown", e);
28
+ }, [C]);
29
+ let H = !!v, U = y === a.SharedWithVibe, W = async (e) => {
30
+ A(!0), M(null);
31
+ try {
32
+ await e(), w(!1);
33
+ } catch (e) {
34
+ M(e instanceof Error ? e.message : S("vibecontrols.entityVibeLink.error", "Could not update the vibe link."));
35
+ } finally {
36
+ A(!1);
37
+ }
38
+ };
39
+ return /* @__PURE__ */ h("div", {
40
+ className: "relative",
41
+ ref: N,
42
+ children: [/* @__PURE__ */ h("button", {
43
+ type: "button",
44
+ onClick: (e) => {
45
+ e.stopPropagation(), w((e) => !e);
46
+ },
47
+ "aria-haspopup": "dialog",
48
+ "aria-expanded": C,
49
+ title: H ? S("vibecontrols.entityVibeLink.linkedTo", "Linked to a vibe — click to manage") : S("vibecontrols.entityVibeLink.notLinked", "Link this to a vibe"),
50
+ className: `inline-flex max-w-[180px] items-center gap-1.5 rounded-md border px-2 py-1 text-xs transition-colors ${H ? "border-action-primary-bg/40 bg-action-primary-bg/10 text-action-primary-bg hover:bg-action-primary-bg/15" : "border-border-default text-text-secondary hover:bg-bg-elevated"} ${x}`,
51
+ children: [
52
+ /* @__PURE__ */ m(d, {
53
+ size: 13,
54
+ className: "flex-shrink-0"
55
+ }),
56
+ /* @__PURE__ */ m("span", {
57
+ className: "truncate",
58
+ children: H ? L ?? S("vibecontrols.entityVibeLink.aVibe", "Linked vibe") : S("vibecontrols.entityVibeLink.link", "Link to vibe")
59
+ }),
60
+ H && /* @__PURE__ */ m("span", {
61
+ className: `ml-0.5 inline-block size-1.5 flex-shrink-0 rounded-full ${U ? "bg-status-success-text" : "bg-text-tertiary"}`,
62
+ "aria-hidden": !0
63
+ })
64
+ ]
65
+ }), C && /* @__PURE__ */ h("div", {
66
+ role: "dialog",
67
+ "aria-label": S("vibecontrols.entityVibeLink.manage", "Manage vibe link"),
68
+ onClick: (e) => e.stopPropagation(),
69
+ className: "absolute right-0 z-30 mt-1 w-72 rounded-lg border border-border-default bg-bg-elevated p-3 shadow-lg",
70
+ children: [
71
+ /* @__PURE__ */ m("p", {
72
+ className: "mb-2 text-xs font-medium text-text-secondary",
73
+ children: S("vibecontrols.entityVibeLink.title", "Linked vibe")
74
+ }),
75
+ /* @__PURE__ */ h("select", {
76
+ value: T ?? "",
77
+ disabled: k,
78
+ onChange: (e) => E(e.target.value === "" ? null : e.target.value),
79
+ "aria-label": S("vibecontrols.entityVibeLink.pickAria", "Pick a vibe to link"),
80
+ className: "w-full rounded-md border border-border-default bg-bg-sunken px-2.5 py-1.5 text-sm text-text-primary focus:outline-none focus:ring-1 focus:ring-action-primary-bg",
81
+ children: [/* @__PURE__ */ m("option", {
82
+ value: "",
83
+ children: F ? S("vibecontrols.entityVibeLink.loading", "Loading vibes…") : S("vibecontrols.entityVibeLink.none", "Not linked to any vibe")
84
+ }), I.map((e) => /* @__PURE__ */ m("option", {
85
+ value: e.id,
86
+ children: e.name
87
+ }, e.id))]
88
+ }),
89
+ T && /* @__PURE__ */ h("div", {
90
+ role: "radiogroup",
91
+ "aria-label": S("vibecontrols.entityVibeLink.visibility", "Who can see it"),
92
+ className: "mt-2.5 space-y-1.5",
93
+ children: [/* @__PURE__ */ h("label", {
94
+ className: "flex cursor-pointer items-start gap-2 text-xs text-text-primary",
95
+ children: [/* @__PURE__ */ m("input", {
96
+ type: "radio",
97
+ name: `entity-vibe-visibility-${_}`,
98
+ value: a.SharedWithVibe,
99
+ checked: D === a.SharedWithVibe,
100
+ disabled: k,
101
+ onChange: () => O(a.SharedWithVibe),
102
+ className: "mt-0.5"
103
+ }), /* @__PURE__ */ m("span", { children: S("vibecontrols.entityVibeLink.shared", "Shared with vibe — visible to everyone with access") })]
104
+ }), /* @__PURE__ */ h("label", {
105
+ className: "flex cursor-pointer items-start gap-2 text-xs text-text-primary",
106
+ children: [/* @__PURE__ */ m("input", {
107
+ type: "radio",
108
+ name: `entity-vibe-visibility-${_}`,
109
+ value: a.Private,
110
+ checked: D === a.Private,
111
+ disabled: k,
112
+ onChange: () => O(a.Private),
113
+ className: "mt-0.5"
114
+ }), /* @__PURE__ */ m("span", { children: S("vibecontrols.entityVibeLink.private", "Private to me") })]
115
+ })]
116
+ }),
117
+ j && /* @__PURE__ */ m("p", {
118
+ className: "mt-2 text-xs text-status-error-text",
119
+ children: j
120
+ }),
121
+ /* @__PURE__ */ h("div", {
122
+ className: "mt-3 flex items-center justify-between gap-2",
123
+ children: [H ? /* @__PURE__ */ h("button", {
124
+ type: "button",
125
+ onClick: async () => {
126
+ await W(() => B({
127
+ variables: {
128
+ entityType: g,
129
+ entityId: _
130
+ },
131
+ refetchQueries: R,
132
+ awaitRefetchQueries: !0
133
+ }));
134
+ },
135
+ disabled: k,
136
+ className: "inline-flex items-center gap-1 rounded-md px-2 py-1 text-xs text-status-error-text hover:bg-status-error-bg/20 disabled:opacity-50",
137
+ children: [/* @__PURE__ */ m(p, { size: 13 }), S("vibecontrols.entityVibeLink.unlink", "Unlink")]
138
+ }) : /* @__PURE__ */ m("span", {}), /* @__PURE__ */ h("div", {
139
+ className: "flex items-center gap-2",
140
+ children: [/* @__PURE__ */ m("button", {
141
+ type: "button",
142
+ onClick: () => w(!1),
143
+ disabled: k,
144
+ className: "rounded-md px-2 py-1 text-xs text-text-secondary hover:bg-bg-sunken disabled:opacity-50",
145
+ children: S("common.cancel", "Cancel")
146
+ }), /* @__PURE__ */ h("button", {
147
+ type: "button",
148
+ onClick: async () => {
149
+ let e = {
150
+ refetchQueries: R,
151
+ awaitRefetchQueries: !0
152
+ };
153
+ if (!T) {
154
+ v ? await W(() => B({
155
+ variables: {
156
+ entityType: g,
157
+ entityId: _
158
+ },
159
+ ...e
160
+ })) : w(!1);
161
+ return;
162
+ }
163
+ if (T !== v) {
164
+ await W(() => z({
165
+ variables: { input: {
166
+ entityType: g,
167
+ entityId: _,
168
+ vibeId: T,
169
+ visibility: D
170
+ } },
171
+ ...e
172
+ }));
173
+ return;
174
+ }
175
+ if (D !== (y ?? a.SharedWithVibe)) {
176
+ await W(() => V({
177
+ variables: {
178
+ entityType: g,
179
+ entityId: _,
180
+ visibility: D
181
+ },
182
+ ...e
183
+ }));
184
+ return;
185
+ }
186
+ w(!1);
187
+ },
188
+ disabled: k,
189
+ className: "inline-flex items-center gap-1 rounded-md bg-action-primary-bg px-2.5 py-1 text-xs font-medium text-action-primary-text hover:bg-action-primary-bg-hover disabled:opacity-50",
190
+ children: [k ? /* @__PURE__ */ m(f, {
191
+ size: 13,
192
+ className: "animate-spin"
193
+ }) : /* @__PURE__ */ m(u, { size: 13 }), S("common.save", "Save")]
194
+ })]
195
+ })]
196
+ })
197
+ ]
198
+ })]
199
+ });
200
+ }
201
+ //#endregion
202
+ export { g as EntityVibeLinkControl };
203
+
204
+ //# sourceMappingURL=EntityVibeLinkControl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EntityVibeLinkControl.js","names":[],"sources":["../../../src/components/shared/EntityVibeLinkControl.tsx"],"sourcesContent":["import { useEffect, useMemo, useRef, useState } from 'react';\nimport { Link2, Loader2, Unlink, Check } from 'lucide-react';\nimport {\n useListVibesQuery,\n useLinkEntityToVibeMutation,\n useUnlinkEntityFromVibeMutation,\n useUpdateEntityVisibilityMutation,\n} from '@/generated/wspace-operations';\nimport { VibeEntityType, VibeVisibility } from '@/generated/wspace-types';\nimport { useTr } from '../../shared/hooks/useTr';\n\ninterface EntityVibeLinkControlProps {\n /** Which kind of entity this control manages (ACTION, TUNNEL, …). */\n entityType: VibeEntityType;\n /** The entity's id. */\n entityId: string;\n /** Currently-linked vibe id, or null when unlinked. */\n currentVibeId: string | null;\n /** Current visibility; defaults to PRIVATE when the entity is unlinked. */\n currentVisibility?: VibeVisibility | null;\n /**\n * Apollo query names to refetch after a successful mutation. The Vibe-detail\n * linked-entity panels (GetVibeLinkedEntities) are always refetched on top of\n * whatever the host list page passes here so both directions stay in sync.\n */\n refetchQueries?: string[];\n /** Extra classes for the trigger button. */\n className?: string;\n}\n\n/**\n * Per-entity \"Linked Vibe\" control for detail headers and list rows. Shows the\n * vibe an entity is currently mapped to (resolved by name) and lets the user\n * map / re-map / unmap it and flip its visibility — the reverse direction of the\n * Vibe-detail linked-entity tabs. Operates on EXISTING entities via the generic\n * linkEntityToVibe / unlinkEntityFromVibe / updateEntityVisibility mutations, so\n * it works uniformly across every owned entity type (Action, Tunnel, VibeDeck,\n * AiPrompt, AiContext, AgentInstructionFile).\n *\n * Distinct from `LinkToVibePanel`, which is the create-form control for choosing\n * a link at creation time.\n */\nexport function EntityVibeLinkControl({\n entityType,\n entityId,\n currentVibeId,\n currentVisibility,\n refetchQueries,\n className = '',\n}: EntityVibeLinkControlProps) {\n const tr = useTr();\n const [open, setOpen] = useState(false);\n const [draftVibeId, setDraftVibeId] = useState<string | null>(currentVibeId);\n const [draftVisibility, setDraftVisibility] = useState<VibeVisibility>(\n currentVisibility ?? VibeVisibility.SharedWithVibe\n );\n const [saving, setSaving] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const containerRef = useRef<HTMLDivElement | null>(null);\n\n const { data, loading: vibesLoading } = useListVibesQuery({\n variables: { pagination: { limit: 200 } },\n fetchPolicy: 'cache-first',\n });\n\n const vibeOptions = useMemo(\n () =>\n (data?.vibes?.items ?? []).map((v: { id: string; name: string }) => ({\n id: v.id,\n name: v.name,\n })),\n [data?.vibes?.items]\n );\n\n const linkedVibeName = useMemo(() => {\n if (!currentVibeId) return null;\n return (\n vibeOptions.find((v: { id: string; name: string }) => v.id === currentVibeId)?.name ?? null\n );\n }, [currentVibeId, vibeOptions]);\n\n // Always refresh the Vibe-detail panels; merge in any host-supplied list\n // queries (deduped) so the source list reflects the new linkage too.\n const mergedRefetch = useMemo(\n () => Array.from(new Set(['GetVibeLinkedEntities', ...(refetchQueries ?? [])])),\n [refetchQueries]\n );\n\n const [linkEntity] = useLinkEntityToVibeMutation();\n const [unlinkEntity] = useUnlinkEntityFromVibeMutation();\n const [updateVisibility] = useUpdateEntityVisibilityMutation();\n\n // Re-seed drafts whenever the popover opens or the source values change so the\n // form always starts from the entity's live state.\n useEffect(() => {\n if (open) {\n setDraftVibeId(currentVibeId);\n setDraftVisibility(currentVisibility ?? VibeVisibility.SharedWithVibe);\n setError(null);\n }\n }, [open, currentVibeId, currentVisibility]);\n\n useEffect(() => {\n if (!open) return;\n const onDocClick = (e: MouseEvent) => {\n if (!containerRef.current?.contains(e.target as Node)) setOpen(false);\n };\n document.addEventListener('mousedown', onDocClick);\n return () => document.removeEventListener('mousedown', onDocClick);\n }, [open]);\n\n const isLinked = Boolean(currentVibeId);\n const isShared = currentVisibility === VibeVisibility.SharedWithVibe;\n\n const runMutation = async (fn: () => Promise<unknown>) => {\n setSaving(true);\n setError(null);\n try {\n await fn();\n setOpen(false);\n } catch (err) {\n setError(\n err instanceof Error\n ? err.message\n : tr('vibecontrols.entityVibeLink.error', 'Could not update the vibe link.')\n );\n } finally {\n setSaving(false);\n }\n };\n\n const handleSave = async () => {\n const mutationOptions = { refetchQueries: mergedRefetch, awaitRefetchQueries: true };\n // No vibe selected → unlink (only meaningful when currently linked).\n if (!draftVibeId) {\n if (currentVibeId) {\n await runMutation(() =>\n unlinkEntity({ variables: { entityType, entityId }, ...mutationOptions })\n );\n } else {\n setOpen(false);\n }\n return;\n }\n // Vibe added or changed → (re)link with the chosen visibility.\n if (draftVibeId !== currentVibeId) {\n await runMutation(() =>\n linkEntity({\n variables: {\n input: { entityType, entityId, vibeId: draftVibeId, visibility: draftVisibility },\n },\n ...mutationOptions,\n })\n );\n return;\n }\n // Same vibe, visibility changed → visibility-only update. Compare against\n // the effective current visibility (matching how the draft is seeded) so an\n // unchanged selection on an entity whose visibility arrived nullish does not\n // fire a redundant no-op mutation.\n const effectiveVisibility = currentVisibility ?? VibeVisibility.SharedWithVibe;\n if (draftVisibility !== effectiveVisibility) {\n await runMutation(() =>\n updateVisibility({\n variables: { entityType, entityId, visibility: draftVisibility },\n ...mutationOptions,\n })\n );\n return;\n }\n // Nothing changed.\n setOpen(false);\n };\n\n const handleUnlink = async () => {\n await runMutation(() =>\n unlinkEntity({\n variables: { entityType, entityId },\n refetchQueries: mergedRefetch,\n awaitRefetchQueries: true,\n })\n );\n };\n\n return (\n <div className=\"relative\" ref={containerRef}>\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n setOpen((v) => !v);\n }}\n aria-haspopup=\"dialog\"\n aria-expanded={open}\n title={\n isLinked\n ? tr('vibecontrols.entityVibeLink.linkedTo', 'Linked to a vibe — click to manage')\n : tr('vibecontrols.entityVibeLink.notLinked', 'Link this to a vibe')\n }\n className={`inline-flex max-w-[180px] items-center gap-1.5 rounded-md border px-2 py-1 text-xs transition-colors ${\n isLinked\n ? 'border-action-primary-bg/40 bg-action-primary-bg/10 text-action-primary-bg hover:bg-action-primary-bg/15'\n : 'border-border-default text-text-secondary hover:bg-bg-elevated'\n } ${className}`}\n >\n <Link2 size={13} className=\"flex-shrink-0\" />\n <span className=\"truncate\">\n {isLinked\n ? (linkedVibeName ?? tr('vibecontrols.entityVibeLink.aVibe', 'Linked vibe'))\n : tr('vibecontrols.entityVibeLink.link', 'Link to vibe')}\n </span>\n {isLinked && (\n <span\n className={`ml-0.5 inline-block size-1.5 flex-shrink-0 rounded-full ${\n isShared ? 'bg-status-success-text' : 'bg-text-tertiary'\n }`}\n aria-hidden\n />\n )}\n </button>\n\n {open && (\n <div\n role=\"dialog\"\n aria-label={tr('vibecontrols.entityVibeLink.manage', 'Manage vibe link')}\n onClick={(e) => e.stopPropagation()}\n className=\"absolute right-0 z-30 mt-1 w-72 rounded-lg border border-border-default bg-bg-elevated p-3 shadow-lg\"\n >\n <p className=\"mb-2 text-xs font-medium text-text-secondary\">\n {tr('vibecontrols.entityVibeLink.title', 'Linked vibe')}\n </p>\n\n <select\n value={draftVibeId ?? ''}\n disabled={saving}\n onChange={(e) => setDraftVibeId(e.target.value === '' ? null : e.target.value)}\n aria-label={tr('vibecontrols.entityVibeLink.pickAria', 'Pick a vibe to link')}\n className=\"w-full rounded-md border border-border-default bg-bg-sunken px-2.5 py-1.5 text-sm text-text-primary focus:outline-none focus:ring-1 focus:ring-action-primary-bg\"\n >\n <option value=\"\">\n {vibesLoading\n ? tr('vibecontrols.entityVibeLink.loading', 'Loading vibes…')\n : tr('vibecontrols.entityVibeLink.none', 'Not linked to any vibe')}\n </option>\n {vibeOptions.map((opt: { id: string; name: string }) => (\n <option key={opt.id} value={opt.id}>\n {opt.name}\n </option>\n ))}\n </select>\n\n {draftVibeId && (\n <div\n role=\"radiogroup\"\n aria-label={tr('vibecontrols.entityVibeLink.visibility', 'Who can see it')}\n className=\"mt-2.5 space-y-1.5\"\n >\n <label className=\"flex cursor-pointer items-start gap-2 text-xs text-text-primary\">\n <input\n type=\"radio\"\n name={`entity-vibe-visibility-${entityId}`}\n value={VibeVisibility.SharedWithVibe}\n checked={draftVisibility === VibeVisibility.SharedWithVibe}\n disabled={saving}\n onChange={() => setDraftVisibility(VibeVisibility.SharedWithVibe)}\n className=\"mt-0.5\"\n />\n <span>\n {tr(\n 'vibecontrols.entityVibeLink.shared',\n 'Shared with vibe — visible to everyone with access'\n )}\n </span>\n </label>\n <label className=\"flex cursor-pointer items-start gap-2 text-xs text-text-primary\">\n <input\n type=\"radio\"\n name={`entity-vibe-visibility-${entityId}`}\n value={VibeVisibility.Private}\n checked={draftVisibility === VibeVisibility.Private}\n disabled={saving}\n onChange={() => setDraftVisibility(VibeVisibility.Private)}\n className=\"mt-0.5\"\n />\n <span>{tr('vibecontrols.entityVibeLink.private', 'Private to me')}</span>\n </label>\n </div>\n )}\n\n {error && <p className=\"mt-2 text-xs text-status-error-text\">{error}</p>}\n\n <div className=\"mt-3 flex items-center justify-between gap-2\">\n {isLinked ? (\n <button\n type=\"button\"\n onClick={handleUnlink}\n disabled={saving}\n className=\"inline-flex items-center gap-1 rounded-md px-2 py-1 text-xs text-status-error-text hover:bg-status-error-bg/20 disabled:opacity-50\"\n >\n <Unlink size={13} />\n {tr('vibecontrols.entityVibeLink.unlink', 'Unlink')}\n </button>\n ) : (\n <span />\n )}\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={() => setOpen(false)}\n disabled={saving}\n className=\"rounded-md px-2 py-1 text-xs text-text-secondary hover:bg-bg-sunken disabled:opacity-50\"\n >\n {tr('common.cancel', 'Cancel')}\n </button>\n <button\n type=\"button\"\n onClick={handleSave}\n disabled={saving}\n className=\"inline-flex items-center gap-1 rounded-md bg-action-primary-bg px-2.5 py-1 text-xs font-medium text-action-primary-text hover:bg-action-primary-bg-hover disabled:opacity-50\"\n >\n {saving ? <Loader2 size={13} className=\"animate-spin\" /> : <Check size={13} />}\n {tr('common.save', 'Save')}\n </button>\n </div>\n </div>\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -16,6 +16,7 @@ import "./StatCard.js";
16
16
  import "./InstallTabs.js";
17
17
  import "./AgentSetupBanner.js";
18
18
  import "./LinkToVibePanel.js";
19
+ import "./EntityVibeLinkControl.js";
19
20
  import "./GetHelpButton.js";
20
21
  import "./SearchableSelect.js";
21
22
  import "./SessionNotificationBanner.js";
@@ -594,6 +594,112 @@ var n = {
594
594
  id
595
595
  }
596
596
  }
597
+ `
598
+ },
599
+ session: {
600
+ readField: "session",
601
+ createLinkField: "createSessionGrantShareLink",
602
+ sharesQuery: t`
603
+ query SessionShares($id: ID!) {
604
+ session(id: $id) {
605
+ id
606
+ name
607
+ vibeId
608
+ myRole: myGrantRole
609
+ shares: shareGrants {
610
+ ${e}
611
+ }
612
+ }
613
+ }
614
+ `,
615
+ share: t`
616
+ mutation ShareSessionGrant($input: ShareEntityInput!) {
617
+ shareSessionGrant(input: $input) {
618
+ ${e}
619
+ }
620
+ }
621
+ `,
622
+ revokeShare: t`
623
+ mutation RevokeSessionGrantShare($input: RevokeShareInput!) {
624
+ revokeSessionGrantShare(input: $input) {
625
+ id
626
+ }
627
+ }
628
+ `,
629
+ updateShareRole: t`
630
+ mutation UpdateSessionGrantShareRole($input: UpdateShareRoleInput!) {
631
+ updateSessionGrantShareRole(input: $input) {
632
+ id
633
+ role
634
+ }
635
+ }
636
+ `,
637
+ createShareLink: t`
638
+ mutation CreateSessionGrantShareLink($input: CreateShareGrantLinkInput!) {
639
+ createSessionGrantShareLink(input: $input) {
640
+ ${e}
641
+ }
642
+ }
643
+ `,
644
+ revokeShareLink: t`
645
+ mutation RevokeSessionGrantShareLink($input: RevokeShareInput!) {
646
+ revokeSessionGrantShareLink(input: $input) {
647
+ id
648
+ }
649
+ }
650
+ `
651
+ },
652
+ vibedeck: {
653
+ readField: "vibeDeck",
654
+ createLinkField: "createVibeDeckGrantShareLink",
655
+ sharesQuery: t`
656
+ query VibeDeckShares($id: ID!) {
657
+ vibeDeck(id: $id) {
658
+ id
659
+ name
660
+ vibeId
661
+ myRole: myGrantRole
662
+ shares: shareGrants {
663
+ ${e}
664
+ }
665
+ }
666
+ }
667
+ `,
668
+ share: t`
669
+ mutation ShareVibeDeckGrant($input: ShareEntityInput!) {
670
+ shareVibeDeckGrant(input: $input) {
671
+ ${e}
672
+ }
673
+ }
674
+ `,
675
+ revokeShare: t`
676
+ mutation RevokeVibeDeckGrantShare($input: RevokeShareInput!) {
677
+ revokeVibeDeckGrantShare(input: $input) {
678
+ id
679
+ }
680
+ }
681
+ `,
682
+ updateShareRole: t`
683
+ mutation UpdateVibeDeckGrantShareRole($input: UpdateShareRoleInput!) {
684
+ updateVibeDeckGrantShareRole(input: $input) {
685
+ id
686
+ role
687
+ }
688
+ }
689
+ `,
690
+ createShareLink: t`
691
+ mutation CreateVibeDeckGrantShareLink($input: CreateShareGrantLinkInput!) {
692
+ createVibeDeckGrantShareLink(input: $input) {
693
+ ${e}
694
+ }
695
+ }
696
+ `,
697
+ revokeShareLink: t`
698
+ mutation RevokeVibeDeckGrantShareLink($input: RevokeShareInput!) {
699
+ revokeVibeDeckGrantShareLink(input: $input) {
700
+ id
701
+ }
702
+ }
597
703
  `
598
704
  }
599
705
  };
@@ -1 +1 @@
1
- {"version":3,"file":"entityShareOps.js","names":[],"sources":["../../../src/components/sharing/entityShareOps.ts"],"sourcesContent":["/**\n * Per-entity GraphQL document set for the generic-sharing controllers\n * (`useEntityShareController`).\n *\n * The generic-sharing operations (`shareAiPrompt`, `aiPrompt.shares`, `myRole`,\n * …) are NOT in the committed `graphql/wspace.graphql` snapshot the codegen\n * reads, so — exactly like `useVibeShareController` / `useNoteShareController` —\n * we hand-write the documents with inline `gql` against the MFE's Apollo client.\n *\n * Each {@link EntityShareOps} bundles the five mutations + the read query for a\n * single entity. The read query projects the resource's `shares`/`myRole` (and,\n * where the backend exposes it, `hasShares`) onto the fe-libs `ShareController`\n * contract. The mutation/read-field names below were verified 1:1 against the\n * deployed `wspace-vibecontrols-svc/.hive-schema.graphql`.\n *\n * Notable per-entity shape differences captured here:\n * - `aiPrompt` has NO `hasShares` field — its read query omits it.\n * - `agentInstructionFile` has NO `name`; it exposes `effectiveFilename`\n * (non-null) + `customName`, so its read query selects those instead.\n * - `vibecontrolsScorecard` and `vibecontrolsDocsSite` have NO read-by-`id`\n * query — the only reads are `(ownerId, ownerType)`. Their `sharesQuery`\n * therefore takes `($ownerId, $ownerType)` and the entity declares\n * `readVariables` to map the controller's `{ id, owner }` onto those args.\n * `scorecard` additionally has NO display-name field, so the call site uses\n * the resource `id` as the dialog title.\n */\n\nimport { gql, type DocumentNode } from '@apollo/client';\n\nimport { SHARE_GRANT_FIELDS } from './shareControllerTypes';\n\n/**\n * Identity the generic controller resolves a resource by. Most entities read by\n * `id`; the two owner-keyed entities (scorecard, docs) additionally carry the\n * `(ownerId, ownerType)` pair their read query requires.\n */\nexport interface EntityShareIdentity {\n /** Stable resource id (always present once the surface has loaded the row). */\n id: string;\n /** `(ownerId, ownerType)` for entities read by owner instead of by id. */\n owner?: { ownerId: string; ownerType: string } | null;\n}\n\n/** The five share mutation documents + read query for one entity. */\nexport interface EntityShareOps {\n /** Reads the resource's `shares` / `myRole` (+ display name + optional `vibeId`). */\n sharesQuery: DocumentNode;\n /** `share<Entity>(input: ShareEntityInput!)`. */\n share: DocumentNode;\n /** `revoke<Entity>Share(input: RevokeShareInput!)`. */\n revokeShare: DocumentNode;\n /** `update<Entity>ShareRole(input: UpdateShareRoleInput!)`. */\n updateShareRole: DocumentNode;\n /** `create<Entity>ShareLink(input: CreateShareGrantLinkInput!)`. */\n createShareLink: DocumentNode;\n /** `revoke<Entity>ShareLink(input: RevokeShareInput!)`. */\n revokeShareLink: DocumentNode;\n /** Top-level read field name (`aiPrompt`, `action`, …) used to read the response. */\n readField: string;\n /** Mutation field name that returns the created link grant (for `shareUrl`). */\n createLinkField: string;\n /**\n * Maps the resource identity onto the variables {@link sharesQuery} expects.\n * Defaults to `{ id }` for the standard `($id: ID!)` read. Entities read by\n * owner (scorecard, docs) override this to emit `{ ownerId, ownerType }`.\n */\n readVariables?: (identity: EntityShareIdentity) => Record<string, unknown>;\n}\n\n// ── aiprompt ────────────────────────────────────────────────────────────────\n// AiPrompt has NO `hasShares` field — read query omits it.\nconst aiPromptOps: EntityShareOps = {\n readField: 'aiPrompt',\n createLinkField: 'createAiPromptShareLink',\n sharesQuery: gql`\n query AiPromptShares($id: ID!) {\n aiPrompt(id: $id) {\n id\n name\n vibeId\n myRole\n shares {\n ${SHARE_GRANT_FIELDS}\n }\n }\n }\n `,\n share: gql`\n mutation ShareAiPrompt($input: ShareEntityInput!) {\n shareAiPrompt(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShare: gql`\n mutation RevokeAiPromptShare($input: RevokeShareInput!) {\n revokeAiPromptShare(input: $input) {\n id\n }\n }\n `,\n updateShareRole: gql`\n mutation UpdateAiPromptShareRole($input: UpdateShareRoleInput!) {\n updateAiPromptShareRole(input: $input) {\n id\n role\n }\n }\n `,\n createShareLink: gql`\n mutation CreateAiPromptShareLink($input: CreateShareGrantLinkInput!) {\n createAiPromptShareLink(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShareLink: gql`\n mutation RevokeAiPromptShareLink($input: RevokeShareInput!) {\n revokeAiPromptShareLink(input: $input) {\n id\n }\n }\n `,\n};\n\n// ── action ──────────────────────────────────────────────────────────────────\nconst actionOps: EntityShareOps = {\n readField: 'action',\n createLinkField: 'createActionShareLink',\n sharesQuery: gql`\n query ActionShares($id: ID!) {\n action(id: $id) {\n id\n name\n vibeId\n hasShares\n myRole\n shares {\n ${SHARE_GRANT_FIELDS}\n }\n }\n }\n `,\n share: gql`\n mutation ShareAction($input: ShareEntityInput!) {\n shareAction(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShare: gql`\n mutation RevokeActionShare($input: RevokeShareInput!) {\n revokeActionShare(input: $input) {\n id\n }\n }\n `,\n updateShareRole: gql`\n mutation UpdateActionShareRole($input: UpdateShareRoleInput!) {\n updateActionShareRole(input: $input) {\n id\n role\n }\n }\n `,\n createShareLink: gql`\n mutation CreateActionShareLink($input: CreateShareGrantLinkInput!) {\n createActionShareLink(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShareLink: gql`\n mutation RevokeActionShareLink($input: RevokeShareInput!) {\n revokeActionShareLink(input: $input) {\n id\n }\n }\n `,\n};\n\n// ── aicontext ─────────────────────────────────────────────────────────────────\nconst aiContextOps: EntityShareOps = {\n readField: 'aiContext',\n createLinkField: 'createAiContextShareLink',\n sharesQuery: gql`\n query AiContextShares($id: ID!) {\n aiContext(id: $id) {\n id\n name\n vibeId\n hasShares\n myRole\n shares {\n ${SHARE_GRANT_FIELDS}\n }\n }\n }\n `,\n share: gql`\n mutation ShareAiContext($input: ShareEntityInput!) {\n shareAiContext(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShare: gql`\n mutation RevokeAiContextShare($input: RevokeShareInput!) {\n revokeAiContextShare(input: $input) {\n id\n }\n }\n `,\n updateShareRole: gql`\n mutation UpdateAiContextShareRole($input: UpdateShareRoleInput!) {\n updateAiContextShareRole(input: $input) {\n id\n role\n }\n }\n `,\n createShareLink: gql`\n mutation CreateAiContextShareLink($input: CreateShareGrantLinkInput!) {\n createAiContextShareLink(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShareLink: gql`\n mutation RevokeAiContextShareLink($input: RevokeShareInput!) {\n revokeAiContextShareLink(input: $input) {\n id\n }\n }\n `,\n};\n\n// ── instructionfile ───────────────────────────────────────────────────────────\n// AgentInstructionFile has NO `name`; the display name is `effectiveFilename`.\nconst instructionFileOps: EntityShareOps = {\n readField: 'agentInstructionFile',\n createLinkField: 'createAgentInstructionFileShareLink',\n sharesQuery: gql`\n query AgentInstructionFileShares($id: ID!) {\n agentInstructionFile(id: $id) {\n id\n effectiveFilename\n vibeId\n hasShares\n myRole\n shares {\n ${SHARE_GRANT_FIELDS}\n }\n }\n }\n `,\n share: gql`\n mutation ShareAgentInstructionFile($input: ShareEntityInput!) {\n shareAgentInstructionFile(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShare: gql`\n mutation RevokeAgentInstructionFileShare($input: RevokeShareInput!) {\n revokeAgentInstructionFileShare(input: $input) {\n id\n }\n }\n `,\n updateShareRole: gql`\n mutation UpdateAgentInstructionFileShareRole($input: UpdateShareRoleInput!) {\n updateAgentInstructionFileShareRole(input: $input) {\n id\n role\n }\n }\n `,\n createShareLink: gql`\n mutation CreateAgentInstructionFileShareLink($input: CreateShareGrantLinkInput!) {\n createAgentInstructionFileShareLink(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShareLink: gql`\n mutation RevokeAgentInstructionFileShareLink($input: RevokeShareInput!) {\n revokeAgentInstructionFileShareLink(input: $input) {\n id\n }\n }\n `,\n};\n\n// ── tunnel ────────────────────────────────────────────────────────────────────\nconst tunnelOps: EntityShareOps = {\n readField: 'tunnel',\n createLinkField: 'createTunnelShareLink',\n sharesQuery: gql`\n query TunnelShares($id: ID!) {\n tunnel(id: $id) {\n id\n name\n vibeId\n hasShares\n myRole\n shares {\n ${SHARE_GRANT_FIELDS}\n }\n }\n }\n `,\n share: gql`\n mutation ShareTunnel($input: ShareEntityInput!) {\n shareTunnel(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShare: gql`\n mutation RevokeTunnelShare($input: RevokeShareInput!) {\n revokeTunnelShare(input: $input) {\n id\n }\n }\n `,\n updateShareRole: gql`\n mutation UpdateTunnelShareRole($input: UpdateShareRoleInput!) {\n updateTunnelShareRole(input: $input) {\n id\n role\n }\n }\n `,\n createShareLink: gql`\n mutation CreateTunnelShareLink($input: CreateShareGrantLinkInput!) {\n createTunnelShareLink(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShareLink: gql`\n mutation RevokeTunnelShareLink($input: RevokeShareInput!) {\n revokeTunnelShareLink(input: $input) {\n id\n }\n }\n `,\n};\n\n// ── catalog ─────────────────────────────────────────────────────────────────\n// VibecontrolsCatalog has `name`, `hasShares`, `myRole`; NO `vibeId`.\nconst catalogOps: EntityShareOps = {\n readField: 'vibecontrolsCatalog',\n createLinkField: 'createCatalogShareLink',\n sharesQuery: gql`\n query CatalogShares($id: ID!) {\n vibecontrolsCatalog(id: $id) {\n id\n name\n hasShares\n myRole\n shares {\n ${SHARE_GRANT_FIELDS}\n }\n }\n }\n `,\n share: gql`\n mutation ShareCatalog($input: ShareEntityInput!) {\n shareCatalog(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShare: gql`\n mutation RevokeCatalogShare($input: RevokeShareInput!) {\n revokeCatalogShare(input: $input) {\n id\n }\n }\n `,\n updateShareRole: gql`\n mutation UpdateCatalogShareRole($input: UpdateShareRoleInput!) {\n updateCatalogShareRole(input: $input) {\n id\n role\n }\n }\n `,\n createShareLink: gql`\n mutation CreateCatalogShareLink($input: CreateShareGrantLinkInput!) {\n createCatalogShareLink(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShareLink: gql`\n mutation RevokeCatalogShareLink($input: RevokeShareInput!) {\n revokeCatalogShareLink(input: $input) {\n id\n }\n }\n `,\n};\n\n// ── component ───────────────────────────────────────────────────────────────\n// VibecontrolsComponent has `name`, `hasShares`, `myRole`; NO `vibeId`.\nconst componentOps: EntityShareOps = {\n readField: 'vibecontrolsComponent',\n createLinkField: 'createComponentShareLink',\n sharesQuery: gql`\n query ComponentShares($id: ID!) {\n vibecontrolsComponent(id: $id) {\n id\n name\n hasShares\n myRole\n shares {\n ${SHARE_GRANT_FIELDS}\n }\n }\n }\n `,\n share: gql`\n mutation ShareComponent($input: ShareEntityInput!) {\n shareComponent(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShare: gql`\n mutation RevokeComponentShare($input: RevokeShareInput!) {\n revokeComponentShare(input: $input) {\n id\n }\n }\n `,\n updateShareRole: gql`\n mutation UpdateComponentShareRole($input: UpdateShareRoleInput!) {\n updateComponentShareRole(input: $input) {\n id\n role\n }\n }\n `,\n createShareLink: gql`\n mutation CreateComponentShareLink($input: CreateShareGrantLinkInput!) {\n createComponentShareLink(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShareLink: gql`\n mutation RevokeComponentShareLink($input: RevokeShareInput!) {\n revokeComponentShareLink(input: $input) {\n id\n }\n }\n `,\n};\n\n// ── template ────────────────────────────────────────────────────────────────\n// VibecontrolsTemplate has `name`, `hasShares`, `myRole`; NO `vibeId`.\nconst templateOps: EntityShareOps = {\n readField: 'vibecontrolsTemplate',\n createLinkField: 'createTemplateShareLink',\n sharesQuery: gql`\n query TemplateShares($id: ID!) {\n vibecontrolsTemplate(id: $id) {\n id\n name\n hasShares\n myRole\n shares {\n ${SHARE_GRANT_FIELDS}\n }\n }\n }\n `,\n share: gql`\n mutation ShareTemplate($input: ShareEntityInput!) {\n shareTemplate(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShare: gql`\n mutation RevokeTemplateShare($input: RevokeShareInput!) {\n revokeTemplateShare(input: $input) {\n id\n }\n }\n `,\n updateShareRole: gql`\n mutation UpdateTemplateShareRole($input: UpdateShareRoleInput!) {\n updateTemplateShareRole(input: $input) {\n id\n role\n }\n }\n `,\n createShareLink: gql`\n mutation CreateTemplateShareLink($input: CreateShareGrantLinkInput!) {\n createTemplateShareLink(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShareLink: gql`\n mutation RevokeTemplateShareLink($input: RevokeShareInput!) {\n revokeTemplateShareLink(input: $input) {\n id\n }\n }\n `,\n};\n\n// ── scorecard ───────────────────────────────────────────────────────────────\n// VibecontrolsScorecard has NO `name` and NO read-by-`id` query — only\n// `vibecontrolsScorecard(ownerId, ownerType)`. The read takes `($ownerId,\n// $ownerType)` and `readVariables` maps the identity's owner pair onto them.\n// The call site uses the resource `id` as the dialog title (no name field).\nconst scorecardOps: EntityShareOps = {\n readField: 'vibecontrolsScorecard',\n createLinkField: 'createScorecardShareLink',\n readVariables: ({ owner }) => ({\n ownerId: owner?.ownerId ?? '',\n ownerType: owner?.ownerType ?? '',\n }),\n sharesQuery: gql`\n query ScorecardShares($ownerId: ID!, $ownerType: ScorecardOwnerType!) {\n vibecontrolsScorecard(ownerId: $ownerId, ownerType: $ownerType) {\n id\n hasShares\n myRole\n shares {\n ${SHARE_GRANT_FIELDS}\n }\n }\n }\n `,\n share: gql`\n mutation ShareScorecard($input: ShareEntityInput!) {\n shareScorecard(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShare: gql`\n mutation RevokeScorecardShare($input: RevokeShareInput!) {\n revokeScorecardShare(input: $input) {\n id\n }\n }\n `,\n updateShareRole: gql`\n mutation UpdateScorecardShareRole($input: UpdateShareRoleInput!) {\n updateScorecardShareRole(input: $input) {\n id\n role\n }\n }\n `,\n createShareLink: gql`\n mutation CreateScorecardShareLink($input: CreateShareGrantLinkInput!) {\n createScorecardShareLink(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShareLink: gql`\n mutation RevokeScorecardShareLink($input: RevokeShareInput!) {\n revokeScorecardShareLink(input: $input) {\n id\n }\n }\n `,\n};\n\n// ── target ──────────────────────────────────────────────────────────────────\n// Target (bare type) has `name`, `hasShares`, `myRole`; NO `vibeId`.\nconst targetOps: EntityShareOps = {\n readField: 'target',\n createLinkField: 'createTargetShareLink',\n sharesQuery: gql`\n query TargetShares($id: ID!) {\n target(id: $id) {\n id\n name\n hasShares\n myRole\n shares {\n ${SHARE_GRANT_FIELDS}\n }\n }\n }\n `,\n share: gql`\n mutation ShareTarget($input: ShareEntityInput!) {\n shareTarget(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShare: gql`\n mutation RevokeTargetShare($input: RevokeShareInput!) {\n revokeTargetShare(input: $input) {\n id\n }\n }\n `,\n updateShareRole: gql`\n mutation UpdateTargetShareRole($input: UpdateShareRoleInput!) {\n updateTargetShareRole(input: $input) {\n id\n role\n }\n }\n `,\n createShareLink: gql`\n mutation CreateTargetShareLink($input: CreateShareGrantLinkInput!) {\n createTargetShareLink(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShareLink: gql`\n mutation RevokeTargetShareLink($input: RevokeShareInput!) {\n revokeTargetShareLink(input: $input) {\n id\n }\n }\n `,\n};\n\n// ── docs ────────────────────────────────────────────────────────────────────\n// VibecontrolsDocsSite has `name`, `hasShares`, `myRole`, AND `vibeId`, but NO\n// read-by-`id` query — only `vibecontrolsDocsSiteByOwner(ownerId, ownerType)`.\n// The read takes `($ownerId, $ownerType)` and `readVariables` maps the owner\n// pair onto them; `vibeId` still flows through for \"Everyone with Vibe\" mode.\nconst docsOps: EntityShareOps = {\n readField: 'vibecontrolsDocsSiteByOwner',\n createLinkField: 'createDocsShareLink',\n readVariables: ({ owner }) => ({\n ownerId: owner?.ownerId ?? '',\n ownerType: owner?.ownerType ?? '',\n }),\n sharesQuery: gql`\n query DocsSiteShares($ownerId: ID!, $ownerType: VibecontrolsDocsSiteOwnerType!) {\n vibecontrolsDocsSiteByOwner(ownerId: $ownerId, ownerType: $ownerType) {\n id\n name\n vibeId\n hasShares\n myRole\n shares {\n ${SHARE_GRANT_FIELDS}\n }\n }\n }\n `,\n share: gql`\n mutation ShareDocs($input: ShareEntityInput!) {\n shareDocs(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShare: gql`\n mutation RevokeDocsShare($input: RevokeShareInput!) {\n revokeDocsShare(input: $input) {\n id\n }\n }\n `,\n updateShareRole: gql`\n mutation UpdateDocsShareRole($input: UpdateShareRoleInput!) {\n updateDocsShareRole(input: $input) {\n id\n role\n }\n }\n `,\n createShareLink: gql`\n mutation CreateDocsShareLink($input: CreateShareGrantLinkInput!) {\n createDocsShareLink(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShareLink: gql`\n mutation RevokeDocsShareLink($input: RevokeShareInput!) {\n revokeDocsShareLink(input: $input) {\n id\n }\n }\n `,\n};\n\n/** Entity types served by the generic {@link useEntityShareController}. */\nexport type GenericShareEntity =\n | 'aiprompt'\n | 'action'\n | 'aicontext'\n | 'instructionfile'\n | 'tunnel'\n | 'catalog'\n | 'component'\n | 'template'\n | 'scorecard'\n | 'target'\n | 'docs';\n\n/** Resolve the inline-`gql` document set for a generic-sharing entity. */\nexport const ENTITY_SHARE_OPS: Record<GenericShareEntity, EntityShareOps> = {\n aiprompt: aiPromptOps,\n action: actionOps,\n aicontext: aiContextOps,\n instructionfile: instructionFileOps,\n tunnel: tunnelOps,\n catalog: catalogOps,\n component: componentOps,\n template: templateOps,\n scorecard: scorecardOps,\n target: targetOps,\n docs: docsOps,\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"entityShareOps.js","names":[],"sources":["../../../src/components/sharing/entityShareOps.ts"],"sourcesContent":["/**\n * Per-entity GraphQL document set for the generic-sharing controllers\n * (`useEntityShareController`).\n *\n * The generic-sharing operations (`shareAiPrompt`, `aiPrompt.shares`, `myRole`,\n * …) are NOT in the committed `graphql/wspace.graphql` snapshot the codegen\n * reads, so — exactly like `useVibeShareController` / `useNoteShareController` —\n * we hand-write the documents with inline `gql` against the MFE's Apollo client.\n *\n * Each {@link EntityShareOps} bundles the five mutations + the read query for a\n * single entity. The read query projects the resource's `shares`/`myRole` (and,\n * where the backend exposes it, `hasShares`) onto the fe-libs `ShareController`\n * contract. The mutation/read-field names below were verified 1:1 against the\n * deployed `wspace-vibecontrols-svc/.hive-schema.graphql`.\n *\n * Notable per-entity shape differences captured here:\n * - `aiPrompt` has NO `hasShares` field — its read query omits it.\n * - `agentInstructionFile` has NO `name`; it exposes `effectiveFilename`\n * (non-null) + `customName`, so its read query selects those instead.\n * - `vibecontrolsScorecard` and `vibecontrolsDocsSite` have NO read-by-`id`\n * query — the only reads are `(ownerId, ownerType)`. Their `sharesQuery`\n * therefore takes `($ownerId, $ownerType)` and the entity declares\n * `readVariables` to map the controller's `{ id, owner }` onto those args.\n * `scorecard` additionally has NO display-name field, so the call site uses\n * the resource `id` as the dialog title.\n */\n\nimport { gql, type DocumentNode } from '@apollo/client';\n\nimport { SHARE_GRANT_FIELDS } from './shareControllerTypes';\n\n/**\n * Identity the generic controller resolves a resource by. Most entities read by\n * `id`; the two owner-keyed entities (scorecard, docs) additionally carry the\n * `(ownerId, ownerType)` pair their read query requires.\n */\nexport interface EntityShareIdentity {\n /** Stable resource id (always present once the surface has loaded the row). */\n id: string;\n /** `(ownerId, ownerType)` for entities read by owner instead of by id. */\n owner?: { ownerId: string; ownerType: string } | null;\n}\n\n/** The five share mutation documents + read query for one entity. */\nexport interface EntityShareOps {\n /** Reads the resource's `shares` / `myRole` (+ display name + optional `vibeId`). */\n sharesQuery: DocumentNode;\n /** `share<Entity>(input: ShareEntityInput!)`. */\n share: DocumentNode;\n /** `revoke<Entity>Share(input: RevokeShareInput!)`. */\n revokeShare: DocumentNode;\n /** `update<Entity>ShareRole(input: UpdateShareRoleInput!)`. */\n updateShareRole: DocumentNode;\n /** `create<Entity>ShareLink(input: CreateShareGrantLinkInput!)`. */\n createShareLink: DocumentNode;\n /** `revoke<Entity>ShareLink(input: RevokeShareInput!)`. */\n revokeShareLink: DocumentNode;\n /** Top-level read field name (`aiPrompt`, `action`, …) used to read the response. */\n readField: string;\n /** Mutation field name that returns the created link grant (for `shareUrl`). */\n createLinkField: string;\n /**\n * Maps the resource identity onto the variables {@link sharesQuery} expects.\n * Defaults to `{ id }` for the standard `($id: ID!)` read. Entities read by\n * owner (scorecard, docs) override this to emit `{ ownerId, ownerType }`.\n */\n readVariables?: (identity: EntityShareIdentity) => Record<string, unknown>;\n}\n\n// ── aiprompt ────────────────────────────────────────────────────────────────\n// AiPrompt has NO `hasShares` field — read query omits it.\nconst aiPromptOps: EntityShareOps = {\n readField: 'aiPrompt',\n createLinkField: 'createAiPromptShareLink',\n sharesQuery: gql`\n query AiPromptShares($id: ID!) {\n aiPrompt(id: $id) {\n id\n name\n vibeId\n myRole\n shares {\n ${SHARE_GRANT_FIELDS}\n }\n }\n }\n `,\n share: gql`\n mutation ShareAiPrompt($input: ShareEntityInput!) {\n shareAiPrompt(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShare: gql`\n mutation RevokeAiPromptShare($input: RevokeShareInput!) {\n revokeAiPromptShare(input: $input) {\n id\n }\n }\n `,\n updateShareRole: gql`\n mutation UpdateAiPromptShareRole($input: UpdateShareRoleInput!) {\n updateAiPromptShareRole(input: $input) {\n id\n role\n }\n }\n `,\n createShareLink: gql`\n mutation CreateAiPromptShareLink($input: CreateShareGrantLinkInput!) {\n createAiPromptShareLink(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShareLink: gql`\n mutation RevokeAiPromptShareLink($input: RevokeShareInput!) {\n revokeAiPromptShareLink(input: $input) {\n id\n }\n }\n `,\n};\n\n// ── action ──────────────────────────────────────────────────────────────────\nconst actionOps: EntityShareOps = {\n readField: 'action',\n createLinkField: 'createActionShareLink',\n sharesQuery: gql`\n query ActionShares($id: ID!) {\n action(id: $id) {\n id\n name\n vibeId\n hasShares\n myRole\n shares {\n ${SHARE_GRANT_FIELDS}\n }\n }\n }\n `,\n share: gql`\n mutation ShareAction($input: ShareEntityInput!) {\n shareAction(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShare: gql`\n mutation RevokeActionShare($input: RevokeShareInput!) {\n revokeActionShare(input: $input) {\n id\n }\n }\n `,\n updateShareRole: gql`\n mutation UpdateActionShareRole($input: UpdateShareRoleInput!) {\n updateActionShareRole(input: $input) {\n id\n role\n }\n }\n `,\n createShareLink: gql`\n mutation CreateActionShareLink($input: CreateShareGrantLinkInput!) {\n createActionShareLink(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShareLink: gql`\n mutation RevokeActionShareLink($input: RevokeShareInput!) {\n revokeActionShareLink(input: $input) {\n id\n }\n }\n `,\n};\n\n// ── aicontext ─────────────────────────────────────────────────────────────────\nconst aiContextOps: EntityShareOps = {\n readField: 'aiContext',\n createLinkField: 'createAiContextShareLink',\n sharesQuery: gql`\n query AiContextShares($id: ID!) {\n aiContext(id: $id) {\n id\n name\n vibeId\n hasShares\n myRole\n shares {\n ${SHARE_GRANT_FIELDS}\n }\n }\n }\n `,\n share: gql`\n mutation ShareAiContext($input: ShareEntityInput!) {\n shareAiContext(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShare: gql`\n mutation RevokeAiContextShare($input: RevokeShareInput!) {\n revokeAiContextShare(input: $input) {\n id\n }\n }\n `,\n updateShareRole: gql`\n mutation UpdateAiContextShareRole($input: UpdateShareRoleInput!) {\n updateAiContextShareRole(input: $input) {\n id\n role\n }\n }\n `,\n createShareLink: gql`\n mutation CreateAiContextShareLink($input: CreateShareGrantLinkInput!) {\n createAiContextShareLink(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShareLink: gql`\n mutation RevokeAiContextShareLink($input: RevokeShareInput!) {\n revokeAiContextShareLink(input: $input) {\n id\n }\n }\n `,\n};\n\n// ── instructionfile ───────────────────────────────────────────────────────────\n// AgentInstructionFile has NO `name`; the display name is `effectiveFilename`.\nconst instructionFileOps: EntityShareOps = {\n readField: 'agentInstructionFile',\n createLinkField: 'createAgentInstructionFileShareLink',\n sharesQuery: gql`\n query AgentInstructionFileShares($id: ID!) {\n agentInstructionFile(id: $id) {\n id\n effectiveFilename\n vibeId\n hasShares\n myRole\n shares {\n ${SHARE_GRANT_FIELDS}\n }\n }\n }\n `,\n share: gql`\n mutation ShareAgentInstructionFile($input: ShareEntityInput!) {\n shareAgentInstructionFile(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShare: gql`\n mutation RevokeAgentInstructionFileShare($input: RevokeShareInput!) {\n revokeAgentInstructionFileShare(input: $input) {\n id\n }\n }\n `,\n updateShareRole: gql`\n mutation UpdateAgentInstructionFileShareRole($input: UpdateShareRoleInput!) {\n updateAgentInstructionFileShareRole(input: $input) {\n id\n role\n }\n }\n `,\n createShareLink: gql`\n mutation CreateAgentInstructionFileShareLink($input: CreateShareGrantLinkInput!) {\n createAgentInstructionFileShareLink(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShareLink: gql`\n mutation RevokeAgentInstructionFileShareLink($input: RevokeShareInput!) {\n revokeAgentInstructionFileShareLink(input: $input) {\n id\n }\n }\n `,\n};\n\n// ── tunnel ────────────────────────────────────────────────────────────────────\nconst tunnelOps: EntityShareOps = {\n readField: 'tunnel',\n createLinkField: 'createTunnelShareLink',\n sharesQuery: gql`\n query TunnelShares($id: ID!) {\n tunnel(id: $id) {\n id\n name\n vibeId\n hasShares\n myRole\n shares {\n ${SHARE_GRANT_FIELDS}\n }\n }\n }\n `,\n share: gql`\n mutation ShareTunnel($input: ShareEntityInput!) {\n shareTunnel(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShare: gql`\n mutation RevokeTunnelShare($input: RevokeShareInput!) {\n revokeTunnelShare(input: $input) {\n id\n }\n }\n `,\n updateShareRole: gql`\n mutation UpdateTunnelShareRole($input: UpdateShareRoleInput!) {\n updateTunnelShareRole(input: $input) {\n id\n role\n }\n }\n `,\n createShareLink: gql`\n mutation CreateTunnelShareLink($input: CreateShareGrantLinkInput!) {\n createTunnelShareLink(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShareLink: gql`\n mutation RevokeTunnelShareLink($input: RevokeShareInput!) {\n revokeTunnelShareLink(input: $input) {\n id\n }\n }\n `,\n};\n\n// ── catalog ─────────────────────────────────────────────────────────────────\n// VibecontrolsCatalog has `name`, `hasShares`, `myRole`; NO `vibeId`.\nconst catalogOps: EntityShareOps = {\n readField: 'vibecontrolsCatalog',\n createLinkField: 'createCatalogShareLink',\n sharesQuery: gql`\n query CatalogShares($id: ID!) {\n vibecontrolsCatalog(id: $id) {\n id\n name\n hasShares\n myRole\n shares {\n ${SHARE_GRANT_FIELDS}\n }\n }\n }\n `,\n share: gql`\n mutation ShareCatalog($input: ShareEntityInput!) {\n shareCatalog(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShare: gql`\n mutation RevokeCatalogShare($input: RevokeShareInput!) {\n revokeCatalogShare(input: $input) {\n id\n }\n }\n `,\n updateShareRole: gql`\n mutation UpdateCatalogShareRole($input: UpdateShareRoleInput!) {\n updateCatalogShareRole(input: $input) {\n id\n role\n }\n }\n `,\n createShareLink: gql`\n mutation CreateCatalogShareLink($input: CreateShareGrantLinkInput!) {\n createCatalogShareLink(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShareLink: gql`\n mutation RevokeCatalogShareLink($input: RevokeShareInput!) {\n revokeCatalogShareLink(input: $input) {\n id\n }\n }\n `,\n};\n\n// ── component ───────────────────────────────────────────────────────────────\n// VibecontrolsComponent has `name`, `hasShares`, `myRole`; NO `vibeId`.\nconst componentOps: EntityShareOps = {\n readField: 'vibecontrolsComponent',\n createLinkField: 'createComponentShareLink',\n sharesQuery: gql`\n query ComponentShares($id: ID!) {\n vibecontrolsComponent(id: $id) {\n id\n name\n hasShares\n myRole\n shares {\n ${SHARE_GRANT_FIELDS}\n }\n }\n }\n `,\n share: gql`\n mutation ShareComponent($input: ShareEntityInput!) {\n shareComponent(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShare: gql`\n mutation RevokeComponentShare($input: RevokeShareInput!) {\n revokeComponentShare(input: $input) {\n id\n }\n }\n `,\n updateShareRole: gql`\n mutation UpdateComponentShareRole($input: UpdateShareRoleInput!) {\n updateComponentShareRole(input: $input) {\n id\n role\n }\n }\n `,\n createShareLink: gql`\n mutation CreateComponentShareLink($input: CreateShareGrantLinkInput!) {\n createComponentShareLink(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShareLink: gql`\n mutation RevokeComponentShareLink($input: RevokeShareInput!) {\n revokeComponentShareLink(input: $input) {\n id\n }\n }\n `,\n};\n\n// ── template ────────────────────────────────────────────────────────────────\n// VibecontrolsTemplate has `name`, `hasShares`, `myRole`; NO `vibeId`.\nconst templateOps: EntityShareOps = {\n readField: 'vibecontrolsTemplate',\n createLinkField: 'createTemplateShareLink',\n sharesQuery: gql`\n query TemplateShares($id: ID!) {\n vibecontrolsTemplate(id: $id) {\n id\n name\n hasShares\n myRole\n shares {\n ${SHARE_GRANT_FIELDS}\n }\n }\n }\n `,\n share: gql`\n mutation ShareTemplate($input: ShareEntityInput!) {\n shareTemplate(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShare: gql`\n mutation RevokeTemplateShare($input: RevokeShareInput!) {\n revokeTemplateShare(input: $input) {\n id\n }\n }\n `,\n updateShareRole: gql`\n mutation UpdateTemplateShareRole($input: UpdateShareRoleInput!) {\n updateTemplateShareRole(input: $input) {\n id\n role\n }\n }\n `,\n createShareLink: gql`\n mutation CreateTemplateShareLink($input: CreateShareGrantLinkInput!) {\n createTemplateShareLink(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShareLink: gql`\n mutation RevokeTemplateShareLink($input: RevokeShareInput!) {\n revokeTemplateShareLink(input: $input) {\n id\n }\n }\n `,\n};\n\n// ── scorecard ───────────────────────────────────────────────────────────────\n// VibecontrolsScorecard has NO `name` and NO read-by-`id` query — only\n// `vibecontrolsScorecard(ownerId, ownerType)`. The read takes `($ownerId,\n// $ownerType)` and `readVariables` maps the identity's owner pair onto them.\n// The call site uses the resource `id` as the dialog title (no name field).\nconst scorecardOps: EntityShareOps = {\n readField: 'vibecontrolsScorecard',\n createLinkField: 'createScorecardShareLink',\n readVariables: ({ owner }) => ({\n ownerId: owner?.ownerId ?? '',\n ownerType: owner?.ownerType ?? '',\n }),\n sharesQuery: gql`\n query ScorecardShares($ownerId: ID!, $ownerType: ScorecardOwnerType!) {\n vibecontrolsScorecard(ownerId: $ownerId, ownerType: $ownerType) {\n id\n hasShares\n myRole\n shares {\n ${SHARE_GRANT_FIELDS}\n }\n }\n }\n `,\n share: gql`\n mutation ShareScorecard($input: ShareEntityInput!) {\n shareScorecard(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShare: gql`\n mutation RevokeScorecardShare($input: RevokeShareInput!) {\n revokeScorecardShare(input: $input) {\n id\n }\n }\n `,\n updateShareRole: gql`\n mutation UpdateScorecardShareRole($input: UpdateShareRoleInput!) {\n updateScorecardShareRole(input: $input) {\n id\n role\n }\n }\n `,\n createShareLink: gql`\n mutation CreateScorecardShareLink($input: CreateShareGrantLinkInput!) {\n createScorecardShareLink(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShareLink: gql`\n mutation RevokeScorecardShareLink($input: RevokeShareInput!) {\n revokeScorecardShareLink(input: $input) {\n id\n }\n }\n `,\n};\n\n// ── target ──────────────────────────────────────────────────────────────────\n// Target (bare type) has `name`, `hasShares`, `myRole`; NO `vibeId`.\nconst targetOps: EntityShareOps = {\n readField: 'target',\n createLinkField: 'createTargetShareLink',\n sharesQuery: gql`\n query TargetShares($id: ID!) {\n target(id: $id) {\n id\n name\n hasShares\n myRole\n shares {\n ${SHARE_GRANT_FIELDS}\n }\n }\n }\n `,\n share: gql`\n mutation ShareTarget($input: ShareEntityInput!) {\n shareTarget(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShare: gql`\n mutation RevokeTargetShare($input: RevokeShareInput!) {\n revokeTargetShare(input: $input) {\n id\n }\n }\n `,\n updateShareRole: gql`\n mutation UpdateTargetShareRole($input: UpdateShareRoleInput!) {\n updateTargetShareRole(input: $input) {\n id\n role\n }\n }\n `,\n createShareLink: gql`\n mutation CreateTargetShareLink($input: CreateShareGrantLinkInput!) {\n createTargetShareLink(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShareLink: gql`\n mutation RevokeTargetShareLink($input: RevokeShareInput!) {\n revokeTargetShareLink(input: $input) {\n id\n }\n }\n `,\n};\n\n// ── docs ────────────────────────────────────────────────────────────────────\n// VibecontrolsDocsSite has `name`, `hasShares`, `myRole`, AND `vibeId`, but NO\n// read-by-`id` query — only `vibecontrolsDocsSiteByOwner(ownerId, ownerType)`.\n// The read takes `($ownerId, $ownerType)` and `readVariables` maps the owner\n// pair onto them; `vibeId` still flows through for \"Everyone with Vibe\" mode.\nconst docsOps: EntityShareOps = {\n readField: 'vibecontrolsDocsSiteByOwner',\n createLinkField: 'createDocsShareLink',\n readVariables: ({ owner }) => ({\n ownerId: owner?.ownerId ?? '',\n ownerType: owner?.ownerType ?? '',\n }),\n sharesQuery: gql`\n query DocsSiteShares($ownerId: ID!, $ownerType: VibecontrolsDocsSiteOwnerType!) {\n vibecontrolsDocsSiteByOwner(ownerId: $ownerId, ownerType: $ownerType) {\n id\n name\n vibeId\n hasShares\n myRole\n shares {\n ${SHARE_GRANT_FIELDS}\n }\n }\n }\n `,\n share: gql`\n mutation ShareDocs($input: ShareEntityInput!) {\n shareDocs(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShare: gql`\n mutation RevokeDocsShare($input: RevokeShareInput!) {\n revokeDocsShare(input: $input) {\n id\n }\n }\n `,\n updateShareRole: gql`\n mutation UpdateDocsShareRole($input: UpdateShareRoleInput!) {\n updateDocsShareRole(input: $input) {\n id\n role\n }\n }\n `,\n createShareLink: gql`\n mutation CreateDocsShareLink($input: CreateShareGrantLinkInput!) {\n createDocsShareLink(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShareLink: gql`\n mutation RevokeDocsShareLink($input: RevokeShareInput!) {\n revokeDocsShareLink(input: $input) {\n id\n }\n }\n `,\n};\n\n// ── session ───────────────────────────────────────────────────────────────────\n// Session exposes the generic share grants under DISTINCT field names from the\n// other entities: `shareGrants: [ShareGrant!]!` (not `shares`) and\n// `myGrantRole: ShareRole` (not `myRole`) — because the legacy `shares` field\n// still returns the bespoke `[SessionShare!]!` (the dual-write target). We alias\n// `shareGrants → shares` and `myGrantRole → myRole` so the response projects\n// onto the shared `useEntityShareController` contract unchanged. The five grant\n// mutations carry the `Grant` infix (`shareSessionGrant`,\n// `revokeSessionGrantShare`, …), distinct from the legacy `shareSession` /\n// `revokeSessionShare` ops the old `SessionShareDialog` used. NO `hasShares`.\nconst sessionOps: EntityShareOps = {\n readField: 'session',\n createLinkField: 'createSessionGrantShareLink',\n sharesQuery: gql`\n query SessionShares($id: ID!) {\n session(id: $id) {\n id\n name\n vibeId\n myRole: myGrantRole\n shares: shareGrants {\n ${SHARE_GRANT_FIELDS}\n }\n }\n }\n `,\n share: gql`\n mutation ShareSessionGrant($input: ShareEntityInput!) {\n shareSessionGrant(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShare: gql`\n mutation RevokeSessionGrantShare($input: RevokeShareInput!) {\n revokeSessionGrantShare(input: $input) {\n id\n }\n }\n `,\n updateShareRole: gql`\n mutation UpdateSessionGrantShareRole($input: UpdateShareRoleInput!) {\n updateSessionGrantShareRole(input: $input) {\n id\n role\n }\n }\n `,\n createShareLink: gql`\n mutation CreateSessionGrantShareLink($input: CreateShareGrantLinkInput!) {\n createSessionGrantShareLink(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShareLink: gql`\n mutation RevokeSessionGrantShareLink($input: RevokeShareInput!) {\n revokeSessionGrantShareLink(input: $input) {\n id\n }\n }\n `,\n};\n\n// ── vibedeck ──────────────────────────────────────────────────────────────────\n// VibeDeck mirrors Session: generic grants live under `shareGrants` +\n// `myGrantRole` (the legacy `shareLinks` field is the bespoke dual-write\n// target), so we alias `shareGrants → shares` / `myGrantRole → myRole`. The five\n// grant mutations carry the `Grant` infix (`shareVibeDeckGrant`,\n// `revokeVibeDeckGrantShare`, …), distinct from the legacy\n// `createVibeDeckShareLink` the old `VibeDeckShareDialog` used. Carries `vibeId`\n// (so \"Everyone with Vibe\" mode is available); NO `hasShares`.\nconst vibeDeckOps: EntityShareOps = {\n readField: 'vibeDeck',\n createLinkField: 'createVibeDeckGrantShareLink',\n sharesQuery: gql`\n query VibeDeckShares($id: ID!) {\n vibeDeck(id: $id) {\n id\n name\n vibeId\n myRole: myGrantRole\n shares: shareGrants {\n ${SHARE_GRANT_FIELDS}\n }\n }\n }\n `,\n share: gql`\n mutation ShareVibeDeckGrant($input: ShareEntityInput!) {\n shareVibeDeckGrant(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShare: gql`\n mutation RevokeVibeDeckGrantShare($input: RevokeShareInput!) {\n revokeVibeDeckGrantShare(input: $input) {\n id\n }\n }\n `,\n updateShareRole: gql`\n mutation UpdateVibeDeckGrantShareRole($input: UpdateShareRoleInput!) {\n updateVibeDeckGrantShareRole(input: $input) {\n id\n role\n }\n }\n `,\n createShareLink: gql`\n mutation CreateVibeDeckGrantShareLink($input: CreateShareGrantLinkInput!) {\n createVibeDeckGrantShareLink(input: $input) {\n ${SHARE_GRANT_FIELDS}\n }\n }\n `,\n revokeShareLink: gql`\n mutation RevokeVibeDeckGrantShareLink($input: RevokeShareInput!) {\n revokeVibeDeckGrantShareLink(input: $input) {\n id\n }\n }\n `,\n};\n\n/** Entity types served by the generic {@link useEntityShareController}. */\nexport type GenericShareEntity =\n | 'aiprompt'\n | 'action'\n | 'aicontext'\n | 'instructionfile'\n | 'tunnel'\n | 'catalog'\n | 'component'\n | 'template'\n | 'scorecard'\n | 'target'\n | 'docs'\n | 'session'\n | 'vibedeck';\n\n/** Resolve the inline-`gql` document set for a generic-sharing entity. */\nexport const ENTITY_SHARE_OPS: Record<GenericShareEntity, EntityShareOps> = {\n aiprompt: aiPromptOps,\n action: actionOps,\n aicontext: aiContextOps,\n instructionfile: instructionFileOps,\n tunnel: tunnelOps,\n catalog: catalogOps,\n component: componentOps,\n template: templateOps,\n scorecard: scorecardOps,\n target: targetOps,\n docs: docsOps,\n session: sessionOps,\n vibedeck: vibeDeckOps,\n};\n"],"mappings":"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"}
@@ -37,14 +37,14 @@ var t = (e) => `vibecontrols.sharing.${e}`, n = {
37
37
  defaultEnabled: !0
38
38
  },
39
39
  session: {
40
- permission: e.SESSION_UPDATE,
40
+ permission: e.SESSION_SHARE,
41
41
  featureFlag: t("session"),
42
- defaultEnabled: !1
42
+ defaultEnabled: !0
43
43
  },
44
44
  vibedeck: {
45
45
  permission: e.VIBEDECK_SHARE,
46
46
  featureFlag: t("vibedeck"),
47
- defaultEnabled: !1
47
+ defaultEnabled: !0
48
48
  },
49
49
  catalog: {
50
50
  permission: e.CATALOG_SHARE,
@@ -1 +1 @@
1
- {"version":3,"file":"shareRegistry.js","names":[],"sources":["../../../src/components/sharing/shareRegistry.ts"],"sourcesContent":["/**\n * Central registry mapping a VibeControls entity type to the RBAC permission\n * that gates its Share affordance plus the platform feature flag that toggles\n * the generic-sharing UI for that entity.\n *\n * Why a registry: the generic sharing dialog (`@burdenoff/fe-libs/sharing`) is\n * entity-agnostic. Each surface that wants a Share button looks its entity up\n * here so the permission string + feature flag stay in one place rather than\n * being re-typed at every call site.\n *\n * Rollout posture:\n * - `vibe` / `note` / `aiprompt` / `action` / `aicontext` / `instructionfile` /\n * `tunnel` ship ON (`defaultEnabled: true`) — the backend share mutations are\n * deployed in prod and the FE controllers in this folder are complete for them\n * (`useVibeShareController`, `useNoteShareController`, and the generic\n * `useEntityShareController` cover the latter five).\n * - `session` / `vibedeck` keep `defaultEnabled: false`: they already have\n * bespoke share dialogs (`SessionShareDialog`, `VibeDeckShareDialog`) that we\n * must NOT break, so the generic surface stays dark until they migrate.\n * - The long-tail entries (catalog/component/template/scorecard/target/docs)\n * now ship ON (`defaultEnabled: true`): their backend share mutations exist\n * and the generic `useEntityShareController` serves them via the inline-`gql`\n * document sets in `entityShareOps.ts`. Each is gated on its own `<entity>\n * :share` RBAC permission (catalog/component/template/scorecard/target →\n * `<entity>:share`; docs → `docs_site:share`).\n */\n\nimport { VIBE_PERMISSIONS } from '@/constants/permissions';\n\n/** A single entity's sharing wiring. */\nexport interface ShareRegistryEntry {\n /** RBAC permission required to open the Share dialog for this entity. */\n permission: string;\n /** Platform feature flag key that toggles the generic-sharing surface. */\n featureFlag: string;\n /**\n * Default value for {@link useFeatureFlag} when the flag is absent.\n * `true` = generic sharing live for this entity; `false` = hidden until the\n * flag is explicitly enabled (long-tail + legacy-dialog entities).\n */\n defaultEnabled: boolean;\n}\n\n/** Every entity type the registry knows about. */\nexport type ShareEntityType =\n | 'vibe'\n | 'note'\n | 'aiprompt'\n | 'action'\n | 'aicontext'\n | 'instructionfile'\n | 'tunnel'\n | 'session'\n | 'vibedeck'\n | 'catalog'\n | 'component'\n | 'template'\n | 'scorecard'\n | 'target'\n | 'docs';\n\nconst flagKey = (entity: ShareEntityType): string => `vibecontrols.sharing.${entity}`;\n\nexport const SHARE_REGISTRY: Record<ShareEntityType, ShareRegistryEntry> = {\n // ── finishable: generic sharing ON ───────────────────────────────────────\n vibe: {\n permission: VIBE_PERMISSIONS.VIBE_MANAGE,\n featureFlag: flagKey('vibe'),\n defaultEnabled: true,\n },\n note: {\n permission: VIBE_PERMISSIONS.NOTE_UPDATE,\n featureFlag: flagKey('note'),\n defaultEnabled: true,\n },\n aiprompt: {\n permission: VIBE_PERMISSIONS.AIPROMPT_SHARE,\n featureFlag: flagKey('aiprompt'),\n defaultEnabled: true,\n },\n action: {\n permission: VIBE_PERMISSIONS.ACTION_SHARE,\n featureFlag: flagKey('action'),\n defaultEnabled: true,\n },\n aicontext: {\n permission: VIBE_PERMISSIONS.AICONTEXT_SHARE,\n featureFlag: flagKey('aicontext'),\n defaultEnabled: true,\n },\n instructionfile: {\n permission: VIBE_PERMISSIONS.INSTRUCTION_FILE_SHARE,\n featureFlag: flagKey('instructionfile'),\n defaultEnabled: true,\n },\n tunnel: {\n permission: VIBE_PERMISSIONS.TUNNEL_SHARE,\n featureFlag: flagKey('tunnel'),\n defaultEnabled: true,\n },\n\n // ── legacy bespoke dialogs: generic surface default-OFF ───────────────────\n session: {\n permission: VIBE_PERMISSIONS.SESSION_UPDATE,\n featureFlag: flagKey('session'),\n defaultEnabled: false,\n },\n vibedeck: {\n permission: VIBE_PERMISSIONS.VIBEDECK_SHARE,\n featureFlag: flagKey('vibedeck'),\n defaultEnabled: false,\n },\n\n // ── long-tail: generic sharing ON ─────────────────────────────────────────\n catalog: {\n permission: VIBE_PERMISSIONS.CATALOG_SHARE,\n featureFlag: flagKey('catalog'),\n defaultEnabled: true,\n },\n component: {\n permission: VIBE_PERMISSIONS.COMPONENT_SHARE,\n featureFlag: flagKey('component'),\n defaultEnabled: true,\n },\n template: {\n permission: VIBE_PERMISSIONS.TEMPLATE_SHARE,\n featureFlag: flagKey('template'),\n defaultEnabled: true,\n },\n scorecard: {\n permission: VIBE_PERMISSIONS.SCORECARD_SHARE,\n featureFlag: flagKey('scorecard'),\n defaultEnabled: true,\n },\n target: {\n permission: VIBE_PERMISSIONS.TARGET_SHARE,\n featureFlag: flagKey('target'),\n defaultEnabled: true,\n },\n docs: {\n permission: VIBE_PERMISSIONS.DOCS_SITE_SHARE,\n featureFlag: flagKey('docs'),\n defaultEnabled: true,\n },\n};\n\n/** Lookup helper; returns `undefined` for unknown entity types. */\nexport function getShareRegistryEntry(entity: ShareEntityType): ShareRegistryEntry | undefined {\n return SHARE_REGISTRY[entity];\n}\n"],"mappings":";;AA6DA,IAAM,KAAW,MAAoC,wBAAwB,KAEhE,IAA8D;CAEzE,MAAM;EACJ,YAAY,EAAiB;EAC7B,aAAa,EAAQ,OAAO;EAC5B,gBAAgB;EACjB;CACD,MAAM;EACJ,YAAY,EAAiB;EAC7B,aAAa,EAAQ,OAAO;EAC5B,gBAAgB;EACjB;CACD,UAAU;EACR,YAAY,EAAiB;EAC7B,aAAa,EAAQ,WAAW;EAChC,gBAAgB;EACjB;CACD,QAAQ;EACN,YAAY,EAAiB;EAC7B,aAAa,EAAQ,SAAS;EAC9B,gBAAgB;EACjB;CACD,WAAW;EACT,YAAY,EAAiB;EAC7B,aAAa,EAAQ,YAAY;EACjC,gBAAgB;EACjB;CACD,iBAAiB;EACf,YAAY,EAAiB;EAC7B,aAAa,EAAQ,kBAAkB;EACvC,gBAAgB;EACjB;CACD,QAAQ;EACN,YAAY,EAAiB;EAC7B,aAAa,EAAQ,SAAS;EAC9B,gBAAgB;EACjB;CAGD,SAAS;EACP,YAAY,EAAiB;EAC7B,aAAa,EAAQ,UAAU;EAC/B,gBAAgB;EACjB;CACD,UAAU;EACR,YAAY,EAAiB;EAC7B,aAAa,EAAQ,WAAW;EAChC,gBAAgB;EACjB;CAGD,SAAS;EACP,YAAY,EAAiB;EAC7B,aAAa,EAAQ,UAAU;EAC/B,gBAAgB;EACjB;CACD,WAAW;EACT,YAAY,EAAiB;EAC7B,aAAa,EAAQ,YAAY;EACjC,gBAAgB;EACjB;CACD,UAAU;EACR,YAAY,EAAiB;EAC7B,aAAa,EAAQ,WAAW;EAChC,gBAAgB;EACjB;CACD,WAAW;EACT,YAAY,EAAiB;EAC7B,aAAa,EAAQ,YAAY;EACjC,gBAAgB;EACjB;CACD,QAAQ;EACN,YAAY,EAAiB;EAC7B,aAAa,EAAQ,SAAS;EAC9B,gBAAgB;EACjB;CACD,MAAM;EACJ,YAAY,EAAiB;EAC7B,aAAa,EAAQ,OAAO;EAC5B,gBAAgB;EACjB;CACF"}
1
+ {"version":3,"file":"shareRegistry.js","names":[],"sources":["../../../src/components/sharing/shareRegistry.ts"],"sourcesContent":["/**\n * Central registry mapping a VibeControls entity type to the RBAC permission\n * that gates its Share affordance plus the platform feature flag that toggles\n * the generic-sharing UI for that entity.\n *\n * Why a registry: the generic sharing dialog (`@burdenoff/fe-libs/sharing`) is\n * entity-agnostic. Each surface that wants a Share button looks its entity up\n * here so the permission string + feature flag stay in one place rather than\n * being re-typed at every call site.\n *\n * Rollout posture:\n * - `vibe` / `note` / `aiprompt` / `action` / `aicontext` / `instructionfile` /\n * `tunnel` ship ON (`defaultEnabled: true`) — the backend share mutations are\n * deployed in prod and the FE controllers in this folder are complete for them\n * (`useVibeShareController`, `useNoteShareController`, and the generic\n * `useEntityShareController` cover the latter five).\n * - `session` / `vibedeck` now ship ON (`defaultEnabled: true`): their former\n * bespoke share dialogs (`SessionShareDialog`, `VibeDeckShareDialog`) were\n * pure share-record management (not entangled with realtime collaboration —\n * that lives in `SharedTerminalPanel`/`SharedSessionPage`), so we replaced\n * their share UI with the generic `<ShareDialog>` via the inline-`gql` op sets\n * in `entityShareOps.ts`. They gate on `session:share` / `vibedeck:share`.\n * - The long-tail entries (catalog/component/template/scorecard/target/docs)\n * now ship ON (`defaultEnabled: true`): their backend share mutations exist\n * and the generic `useEntityShareController` serves them via the inline-`gql`\n * document sets in `entityShareOps.ts`. Each is gated on its own `<entity>\n * :share` RBAC permission (catalog/component/template/scorecard/target →\n * `<entity>:share`; docs → `docs_site:share`).\n */\n\nimport { VIBE_PERMISSIONS } from '@/constants/permissions';\n\n/** A single entity's sharing wiring. */\nexport interface ShareRegistryEntry {\n /** RBAC permission required to open the Share dialog for this entity. */\n permission: string;\n /** Platform feature flag key that toggles the generic-sharing surface. */\n featureFlag: string;\n /**\n * Default value for {@link useFeatureFlag} when the flag is absent.\n * `true` = generic sharing live for this entity; `false` = hidden until the\n * flag is explicitly enabled (long-tail + legacy-dialog entities).\n */\n defaultEnabled: boolean;\n}\n\n/** Every entity type the registry knows about. */\nexport type ShareEntityType =\n | 'vibe'\n | 'note'\n | 'aiprompt'\n | 'action'\n | 'aicontext'\n | 'instructionfile'\n | 'tunnel'\n | 'session'\n | 'vibedeck'\n | 'catalog'\n | 'component'\n | 'template'\n | 'scorecard'\n | 'target'\n | 'docs';\n\nconst flagKey = (entity: ShareEntityType): string => `vibecontrols.sharing.${entity}`;\n\nexport const SHARE_REGISTRY: Record<ShareEntityType, ShareRegistryEntry> = {\n // ── finishable: generic sharing ON ───────────────────────────────────────\n vibe: {\n permission: VIBE_PERMISSIONS.VIBE_MANAGE,\n featureFlag: flagKey('vibe'),\n defaultEnabled: true,\n },\n note: {\n permission: VIBE_PERMISSIONS.NOTE_UPDATE,\n featureFlag: flagKey('note'),\n defaultEnabled: true,\n },\n aiprompt: {\n permission: VIBE_PERMISSIONS.AIPROMPT_SHARE,\n featureFlag: flagKey('aiprompt'),\n defaultEnabled: true,\n },\n action: {\n permission: VIBE_PERMISSIONS.ACTION_SHARE,\n featureFlag: flagKey('action'),\n defaultEnabled: true,\n },\n aicontext: {\n permission: VIBE_PERMISSIONS.AICONTEXT_SHARE,\n featureFlag: flagKey('aicontext'),\n defaultEnabled: true,\n },\n instructionfile: {\n permission: VIBE_PERMISSIONS.INSTRUCTION_FILE_SHARE,\n featureFlag: flagKey('instructionfile'),\n defaultEnabled: true,\n },\n tunnel: {\n permission: VIBE_PERMISSIONS.TUNNEL_SHARE,\n featureFlag: flagKey('tunnel'),\n defaultEnabled: true,\n },\n\n // ── migrated from bespoke dialogs: generic sharing ON ─────────────────────\n // `session` / `vibedeck` previously rode bespoke share dialogs\n // (`SessionShareDialog`, `VibeDeckShareDialog`). Those dialogs were pure\n // share-record management (create/list/revoke grants + links) and were NOT\n // entangled with realtime collaboration — live presence / terminal control\n // handoff lives in the separate `SharedTerminalPanel` / `SharedSessionPage`,\n // driven by the session's collaborator list, never by the share dialog. So we\n // replaced the bespoke share UI with the richer generic `<ShareDialog>`\n // (email invite + accept-gate + 4 visibility modes + expiry + public link)\n // and flipped these ON. The generic grant mutations gate on `action:\"share\"`\n // (`session:share` / `vibedeck:share`), distinct from the legacy\n // `action:\"update\"` dual-write mutations.\n session: {\n permission: VIBE_PERMISSIONS.SESSION_SHARE,\n featureFlag: flagKey('session'),\n defaultEnabled: true,\n },\n vibedeck: {\n permission: VIBE_PERMISSIONS.VIBEDECK_SHARE,\n featureFlag: flagKey('vibedeck'),\n defaultEnabled: true,\n },\n\n // ── long-tail: generic sharing ON ─────────────────────────────────────────\n catalog: {\n permission: VIBE_PERMISSIONS.CATALOG_SHARE,\n featureFlag: flagKey('catalog'),\n defaultEnabled: true,\n },\n component: {\n permission: VIBE_PERMISSIONS.COMPONENT_SHARE,\n featureFlag: flagKey('component'),\n defaultEnabled: true,\n },\n template: {\n permission: VIBE_PERMISSIONS.TEMPLATE_SHARE,\n featureFlag: flagKey('template'),\n defaultEnabled: true,\n },\n scorecard: {\n permission: VIBE_PERMISSIONS.SCORECARD_SHARE,\n featureFlag: flagKey('scorecard'),\n defaultEnabled: true,\n },\n target: {\n permission: VIBE_PERMISSIONS.TARGET_SHARE,\n featureFlag: flagKey('target'),\n defaultEnabled: true,\n },\n docs: {\n permission: VIBE_PERMISSIONS.DOCS_SITE_SHARE,\n featureFlag: flagKey('docs'),\n defaultEnabled: true,\n },\n};\n\n/** Lookup helper; returns `undefined` for unknown entity types. */\nexport function getShareRegistryEntry(entity: ShareEntityType): ShareRegistryEntry | undefined {\n return SHARE_REGISTRY[entity];\n}\n"],"mappings":";;AAgEA,IAAM,KAAW,MAAoC,wBAAwB,KAEhE,IAA8D;CAEzE,MAAM;EACJ,YAAY,EAAiB;EAC7B,aAAa,EAAQ,OAAO;EAC5B,gBAAgB;EACjB;CACD,MAAM;EACJ,YAAY,EAAiB;EAC7B,aAAa,EAAQ,OAAO;EAC5B,gBAAgB;EACjB;CACD,UAAU;EACR,YAAY,EAAiB;EAC7B,aAAa,EAAQ,WAAW;EAChC,gBAAgB;EACjB;CACD,QAAQ;EACN,YAAY,EAAiB;EAC7B,aAAa,EAAQ,SAAS;EAC9B,gBAAgB;EACjB;CACD,WAAW;EACT,YAAY,EAAiB;EAC7B,aAAa,EAAQ,YAAY;EACjC,gBAAgB;EACjB;CACD,iBAAiB;EACf,YAAY,EAAiB;EAC7B,aAAa,EAAQ,kBAAkB;EACvC,gBAAgB;EACjB;CACD,QAAQ;EACN,YAAY,EAAiB;EAC7B,aAAa,EAAQ,SAAS;EAC9B,gBAAgB;EACjB;CAcD,SAAS;EACP,YAAY,EAAiB;EAC7B,aAAa,EAAQ,UAAU;EAC/B,gBAAgB;EACjB;CACD,UAAU;EACR,YAAY,EAAiB;EAC7B,aAAa,EAAQ,WAAW;EAChC,gBAAgB;EACjB;CAGD,SAAS;EACP,YAAY,EAAiB;EAC7B,aAAa,EAAQ,UAAU;EAC/B,gBAAgB;EACjB;CACD,WAAW;EACT,YAAY,EAAiB;EAC7B,aAAa,EAAQ,YAAY;EACjC,gBAAgB;EACjB;CACD,UAAU;EACR,YAAY,EAAiB;EAC7B,aAAa,EAAQ,WAAW;EAChC,gBAAgB;EACjB;CACD,WAAW;EACT,YAAY,EAAiB;EAC7B,aAAa,EAAQ,YAAY;EACjC,gBAAgB;EACjB;CACD,QAAQ;EACN,YAAY,EAAiB;EAC7B,aAAa,EAAQ,SAAS;EAC9B,gBAAgB;EACjB;CACD,MAAM;EACJ,YAAY,EAAiB;EAC7B,aAAa,EAAQ,OAAO;EAC5B,gBAAgB;EACjB;CACF"}