@burdenoff/microfe-vibecontrols 2026.601.21 → 2026.601.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/actions/ActionCard.js +77 -66
- package/dist/components/actions/ActionCard.js.map +1 -1
- package/dist/components/ai/AIContextsTab.js +186 -173
- package/dist/components/ai/AIContextsTab.js.map +1 -1
- package/dist/components/ai/AITemplatesTab.js +135 -125
- package/dist/components/ai/AITemplatesTab.js.map +1 -1
- package/dist/components/ai/InstructionFilesManager.js +151 -137
- package/dist/components/ai/InstructionFilesManager.js.map +1 -1
- package/dist/components/notes/NotesTabPanel.js +8 -8
- package/dist/components/sharing/EntityShareButton.js +58 -0
- package/dist/components/sharing/EntityShareButton.js.map +1 -0
- package/dist/components/sharing/entityShareOps.js +277 -0
- package/dist/components/sharing/entityShareOps.js.map +1 -0
- package/dist/components/sharing/index.js +3 -0
- package/dist/components/sharing/shareRegistry.js +25 -0
- package/dist/components/sharing/shareRegistry.js.map +1 -1
- package/dist/components/sharing/useEntityShareController.js +88 -0
- package/dist/components/sharing/useEntityShareController.js.map +1 -0
- package/dist/constants/permissions.js +5 -0
- package/dist/constants/permissions.js.map +1 -1
- package/dist/pages/ActionsPage.js +162 -162
- package/dist/pages/ActionsPage.js.map +1 -1
- package/dist/pages/VibeDeckPage.js +1 -1
- package/dist/pages/VibeDetailsPage.js +484 -484
- package/dist/pages/VibeDetailsPage.js.map +1 -1
- package/dist/pages/tunnels/TunnelDetailsPage.js +91 -77
- package/dist/pages/tunnels/TunnelDetailsPage.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { SHARE_REGISTRY as e } from "./shareRegistry.js";
|
|
2
|
+
import { useEntityShareController as t } from "./useEntityShareController.js";
|
|
3
|
+
import { useState as n } from "react";
|
|
4
|
+
import { Share2 as r } from "lucide-react";
|
|
5
|
+
import { getStoredWorkspaceId as i } from "@burdenoff/fe-libs/shared/graphql";
|
|
6
|
+
import { jsx as a, jsxs as o } from "react/jsx-runtime";
|
|
7
|
+
import { useFeatureFlag as s } from "@burdenoff/fe-libs/shared/feature-flags";
|
|
8
|
+
import { PermissionGate as c } from "@burdenoff/fe-libs/shared/components";
|
|
9
|
+
import { ShareDialog as l } from "@burdenoff/fe-libs/sharing";
|
|
10
|
+
//#region src/components/sharing/EntityShareButton.tsx
|
|
11
|
+
function u(t) {
|
|
12
|
+
return e[t];
|
|
13
|
+
}
|
|
14
|
+
function d({ entity: e, resource: d, label: f, variant: p = "icon" }) {
|
|
15
|
+
let [m, h] = n(!1), g = t(e, d), _ = u(e);
|
|
16
|
+
if (!s(_.featureFlag, _.defaultEnabled)) return null;
|
|
17
|
+
let v = `${e}-share-button`;
|
|
18
|
+
return /* @__PURE__ */ o(c, {
|
|
19
|
+
permission: _.permission,
|
|
20
|
+
children: [p === "button" ? /* @__PURE__ */ o("button", {
|
|
21
|
+
type: "button",
|
|
22
|
+
"data-testid": v,
|
|
23
|
+
onClick: (e) => {
|
|
24
|
+
e.stopPropagation(), h(!0);
|
|
25
|
+
},
|
|
26
|
+
title: f,
|
|
27
|
+
className: "flex items-center gap-1.5 px-2.5 py-1.5 sm:px-3 sm:py-2 text-xs sm:text-sm bg-bg-sunken text-text-primary rounded-md hover:bg-bg-sunken/80 transition-colors",
|
|
28
|
+
children: [/* @__PURE__ */ a(r, { className: "size-3.5 sm:size-4" }), /* @__PURE__ */ a("span", {
|
|
29
|
+
className: "hidden sm:inline",
|
|
30
|
+
children: f
|
|
31
|
+
})]
|
|
32
|
+
}) : /* @__PURE__ */ a("button", {
|
|
33
|
+
type: "button",
|
|
34
|
+
"data-testid": v,
|
|
35
|
+
onClick: (e) => {
|
|
36
|
+
e.stopPropagation(), h(!0);
|
|
37
|
+
},
|
|
38
|
+
title: f,
|
|
39
|
+
className: "p-1.5 rounded-md hover:bg-bg-elevated text-text-secondary transition-colors",
|
|
40
|
+
children: /* @__PURE__ */ a(r, { className: "size-3.5" })
|
|
41
|
+
}), /* @__PURE__ */ a(l, {
|
|
42
|
+
resource: {
|
|
43
|
+
type: e,
|
|
44
|
+
id: d.id,
|
|
45
|
+
name: d.name,
|
|
46
|
+
vibeId: d.vibeId ?? void 0
|
|
47
|
+
},
|
|
48
|
+
controller: g,
|
|
49
|
+
open: m,
|
|
50
|
+
onOpenChange: h,
|
|
51
|
+
workspaceId: i() ?? void 0
|
|
52
|
+
})]
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
//#endregion
|
|
56
|
+
export { d as EntityShareButton };
|
|
57
|
+
|
|
58
|
+
//# sourceMappingURL=EntityShareButton.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EntityShareButton.js","names":[],"sources":["../../../src/components/sharing/EntityShareButton.tsx"],"sourcesContent":["/**\n * `EntityShareButton` — the generic Share affordance for the five finishable\n * VibeControls entities (aiprompt / action / aicontext / instructionfile /\n * tunnel), mirroring {@link VibeShareButton}.\n *\n * Self-contained: it owns the open/close state, builds the share controller via\n * {@link useEntityShareController}, and renders the generic fe-libs\n * `<ShareDialog>`. Visibility is gated by the entity's entry in\n * {@link SHARE_REGISTRY} (RBAC permission + the `vibecontrols.sharing.<entity>`\n * feature flag, which defaults ON for these entities). Hooks run\n * unconditionally; the component returns `null` only after the flag check so\n * React hook ordering stays stable.\n *\n * Two render modes:\n * - `variant=\"icon\"` (default) — a compact icon button suited to per-row /\n * per-card action clusters (AI tabs, instruction-file rows, action cards).\n * - `variant=\"button\"` — an icon+label button matching the Vibe-detail header\n * affordance (tunnel detail page).\n */\n\nimport { useState } from 'react';\nimport { Share2 } from 'lucide-react';\nimport { ShareDialog } from '@burdenoff/fe-libs/sharing';\nimport { PermissionGate } from '@burdenoff/fe-libs/shared/components';\nimport { useFeatureFlag } from '@burdenoff/fe-libs/shared/feature-flags';\nimport { getStoredWorkspaceId } from '@burdenoff/fe-libs/shared/graphql';\n\nimport { SHARE_REGISTRY } from './shareRegistry';\nimport { useEntityShareController } from './useEntityShareController';\nimport type { GenericShareEntity } from './entityShareOps';\n\nexport interface EntityShareButtonProps {\n /** Which finishable entity is being shared. */\n entity: GenericShareEntity;\n /** Stable id of the resource row plus its optional vibe linkage. */\n resource: { id: string; name: string; vibeId?: string | null };\n /** Localized button label + tooltip. */\n label: string;\n /** Visual style — compact icon (default) vs icon+label button. */\n variant?: 'icon' | 'button';\n}\n\n/** Map the generic entity key onto the `SHARE_REGISTRY` entry. */\nfunction registryEntry(entity: GenericShareEntity) {\n return SHARE_REGISTRY[entity];\n}\n\nexport function EntityShareButton({\n entity,\n resource,\n label,\n variant = 'icon',\n}: EntityShareButtonProps) {\n const [open, setOpen] = useState(false);\n const controller = useEntityShareController(entity, resource);\n const entry = registryEntry(entity);\n const enabled = useFeatureFlag(entry.featureFlag, entry.defaultEnabled);\n\n if (!enabled) return null;\n\n const testId = `${entity}-share-button`;\n\n return (\n <PermissionGate permission={entry.permission}>\n {variant === 'button' ? (\n <button\n type=\"button\"\n data-testid={testId}\n onClick={(event) => {\n event.stopPropagation();\n setOpen(true);\n }}\n title={label}\n className=\"flex items-center gap-1.5 px-2.5 py-1.5 sm:px-3 sm:py-2 text-xs sm:text-sm bg-bg-sunken text-text-primary rounded-md hover:bg-bg-sunken/80 transition-colors\"\n >\n <Share2 className=\"size-3.5 sm:size-4\" />\n <span className=\"hidden sm:inline\">{label}</span>\n </button>\n ) : (\n <button\n type=\"button\"\n data-testid={testId}\n onClick={(event) => {\n event.stopPropagation();\n setOpen(true);\n }}\n title={label}\n className=\"p-1.5 rounded-md hover:bg-bg-elevated text-text-secondary transition-colors\"\n >\n <Share2 className=\"size-3.5\" />\n </button>\n )}\n <ShareDialog\n resource={{\n type: entity,\n id: resource.id,\n name: resource.name,\n vibeId: resource.vibeId ?? undefined,\n }}\n controller={controller}\n open={open}\n onOpenChange={setOpen}\n workspaceId={getStoredWorkspaceId() ?? undefined}\n />\n </PermissionGate>\n );\n}\n"],"mappings":";;;;;;;;;;AA2CA,SAAS,EAAc,GAA4B;AACjD,QAAO,EAAe;;AAGxB,SAAgB,EAAkB,EAChC,WACA,aACA,UACA,aAAU,UACe;CACzB,IAAM,CAAC,GAAM,KAAW,EAAS,GAAM,EACjC,IAAa,EAAyB,GAAQ,EAAS,EACvD,IAAQ,EAAc,EAAO;AAGnC,KAAI,CAFY,EAAe,EAAM,aAAa,EAAM,eAAe,CAEzD,QAAO;CAErB,IAAM,IAAS,GAAG,EAAO;AAEzB,QACE,kBAAC,GAAD;EAAgB,YAAY,EAAM;YAAlC,CACG,MAAY,WACX,kBAAC,UAAD;GACE,MAAK;GACL,eAAa;GACb,UAAU,MAAU;AAElB,IADA,EAAM,iBAAiB,EACvB,EAAQ,GAAK;;GAEf,OAAO;GACP,WAAU;aARZ,CAUE,kBAAC,GAAD,EAAQ,WAAU,sBAAuB,CAAA,EACzC,kBAAC,QAAD;IAAM,WAAU;cAAoB;IAAa,CAAA,CAC1C;OAET,kBAAC,UAAD;GACE,MAAK;GACL,eAAa;GACb,UAAU,MAAU;AAElB,IADA,EAAM,iBAAiB,EACvB,EAAQ,GAAK;;GAEf,OAAO;GACP,WAAU;aAEV,kBAAC,GAAD,EAAQ,WAAU,YAAa,CAAA;GACxB,CAAA,EAEX,kBAAC,GAAD;GACE,UAAU;IACR,MAAM;IACN,IAAI,EAAS;IACb,MAAM,EAAS;IACf,QAAQ,EAAS,UAAU,KAAA;IAC5B;GACW;GACN;GACN,cAAc;GACd,aAAa,GAAsB,IAAI,KAAA;GACvC,CAAA,CACa"}
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import { SHARE_GRANT_FIELDS as e } from "./shareControllerTypes.js";
|
|
2
|
+
import { gql as t } from "@apollo/client";
|
|
3
|
+
var n = {
|
|
4
|
+
aiprompt: {
|
|
5
|
+
readField: "aiPrompt",
|
|
6
|
+
createLinkField: "createAiPromptShareLink",
|
|
7
|
+
sharesQuery: t`
|
|
8
|
+
query AiPromptShares($id: ID!) {
|
|
9
|
+
aiPrompt(id: $id) {
|
|
10
|
+
id
|
|
11
|
+
name
|
|
12
|
+
vibeId
|
|
13
|
+
myRole
|
|
14
|
+
shares {
|
|
15
|
+
${e}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
`,
|
|
20
|
+
share: t`
|
|
21
|
+
mutation ShareAiPrompt($input: ShareEntityInput!) {
|
|
22
|
+
shareAiPrompt(input: $input) {
|
|
23
|
+
${e}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
`,
|
|
27
|
+
revokeShare: t`
|
|
28
|
+
mutation RevokeAiPromptShare($input: RevokeShareInput!) {
|
|
29
|
+
revokeAiPromptShare(input: $input) {
|
|
30
|
+
id
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
`,
|
|
34
|
+
updateShareRole: t`
|
|
35
|
+
mutation UpdateAiPromptShareRole($input: UpdateShareRoleInput!) {
|
|
36
|
+
updateAiPromptShareRole(input: $input) {
|
|
37
|
+
id
|
|
38
|
+
role
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
`,
|
|
42
|
+
createShareLink: t`
|
|
43
|
+
mutation CreateAiPromptShareLink($input: CreateShareGrantLinkInput!) {
|
|
44
|
+
createAiPromptShareLink(input: $input) {
|
|
45
|
+
${e}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
`,
|
|
49
|
+
revokeShareLink: t`
|
|
50
|
+
mutation RevokeAiPromptShareLink($input: RevokeShareInput!) {
|
|
51
|
+
revokeAiPromptShareLink(input: $input) {
|
|
52
|
+
id
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
`
|
|
56
|
+
},
|
|
57
|
+
action: {
|
|
58
|
+
readField: "action",
|
|
59
|
+
createLinkField: "createActionShareLink",
|
|
60
|
+
sharesQuery: t`
|
|
61
|
+
query ActionShares($id: ID!) {
|
|
62
|
+
action(id: $id) {
|
|
63
|
+
id
|
|
64
|
+
name
|
|
65
|
+
vibeId
|
|
66
|
+
hasShares
|
|
67
|
+
myRole
|
|
68
|
+
shares {
|
|
69
|
+
${e}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
`,
|
|
74
|
+
share: t`
|
|
75
|
+
mutation ShareAction($input: ShareEntityInput!) {
|
|
76
|
+
shareAction(input: $input) {
|
|
77
|
+
${e}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
`,
|
|
81
|
+
revokeShare: t`
|
|
82
|
+
mutation RevokeActionShare($input: RevokeShareInput!) {
|
|
83
|
+
revokeActionShare(input: $input) {
|
|
84
|
+
id
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
`,
|
|
88
|
+
updateShareRole: t`
|
|
89
|
+
mutation UpdateActionShareRole($input: UpdateShareRoleInput!) {
|
|
90
|
+
updateActionShareRole(input: $input) {
|
|
91
|
+
id
|
|
92
|
+
role
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
`,
|
|
96
|
+
createShareLink: t`
|
|
97
|
+
mutation CreateActionShareLink($input: CreateShareGrantLinkInput!) {
|
|
98
|
+
createActionShareLink(input: $input) {
|
|
99
|
+
${e}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
`,
|
|
103
|
+
revokeShareLink: t`
|
|
104
|
+
mutation RevokeActionShareLink($input: RevokeShareInput!) {
|
|
105
|
+
revokeActionShareLink(input: $input) {
|
|
106
|
+
id
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
`
|
|
110
|
+
},
|
|
111
|
+
aicontext: {
|
|
112
|
+
readField: "aiContext",
|
|
113
|
+
createLinkField: "createAiContextShareLink",
|
|
114
|
+
sharesQuery: t`
|
|
115
|
+
query AiContextShares($id: ID!) {
|
|
116
|
+
aiContext(id: $id) {
|
|
117
|
+
id
|
|
118
|
+
name
|
|
119
|
+
vibeId
|
|
120
|
+
hasShares
|
|
121
|
+
myRole
|
|
122
|
+
shares {
|
|
123
|
+
${e}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
`,
|
|
128
|
+
share: t`
|
|
129
|
+
mutation ShareAiContext($input: ShareEntityInput!) {
|
|
130
|
+
shareAiContext(input: $input) {
|
|
131
|
+
${e}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
`,
|
|
135
|
+
revokeShare: t`
|
|
136
|
+
mutation RevokeAiContextShare($input: RevokeShareInput!) {
|
|
137
|
+
revokeAiContextShare(input: $input) {
|
|
138
|
+
id
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
`,
|
|
142
|
+
updateShareRole: t`
|
|
143
|
+
mutation UpdateAiContextShareRole($input: UpdateShareRoleInput!) {
|
|
144
|
+
updateAiContextShareRole(input: $input) {
|
|
145
|
+
id
|
|
146
|
+
role
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
`,
|
|
150
|
+
createShareLink: t`
|
|
151
|
+
mutation CreateAiContextShareLink($input: CreateShareGrantLinkInput!) {
|
|
152
|
+
createAiContextShareLink(input: $input) {
|
|
153
|
+
${e}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
`,
|
|
157
|
+
revokeShareLink: t`
|
|
158
|
+
mutation RevokeAiContextShareLink($input: RevokeShareInput!) {
|
|
159
|
+
revokeAiContextShareLink(input: $input) {
|
|
160
|
+
id
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
`
|
|
164
|
+
},
|
|
165
|
+
instructionfile: {
|
|
166
|
+
readField: "agentInstructionFile",
|
|
167
|
+
createLinkField: "createAgentInstructionFileShareLink",
|
|
168
|
+
sharesQuery: t`
|
|
169
|
+
query AgentInstructionFileShares($id: ID!) {
|
|
170
|
+
agentInstructionFile(id: $id) {
|
|
171
|
+
id
|
|
172
|
+
effectiveFilename
|
|
173
|
+
vibeId
|
|
174
|
+
hasShares
|
|
175
|
+
myRole
|
|
176
|
+
shares {
|
|
177
|
+
${e}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
`,
|
|
182
|
+
share: t`
|
|
183
|
+
mutation ShareAgentInstructionFile($input: ShareEntityInput!) {
|
|
184
|
+
shareAgentInstructionFile(input: $input) {
|
|
185
|
+
${e}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
`,
|
|
189
|
+
revokeShare: t`
|
|
190
|
+
mutation RevokeAgentInstructionFileShare($input: RevokeShareInput!) {
|
|
191
|
+
revokeAgentInstructionFileShare(input: $input) {
|
|
192
|
+
id
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
`,
|
|
196
|
+
updateShareRole: t`
|
|
197
|
+
mutation UpdateAgentInstructionFileShareRole($input: UpdateShareRoleInput!) {
|
|
198
|
+
updateAgentInstructionFileShareRole(input: $input) {
|
|
199
|
+
id
|
|
200
|
+
role
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
`,
|
|
204
|
+
createShareLink: t`
|
|
205
|
+
mutation CreateAgentInstructionFileShareLink($input: CreateShareGrantLinkInput!) {
|
|
206
|
+
createAgentInstructionFileShareLink(input: $input) {
|
|
207
|
+
${e}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
`,
|
|
211
|
+
revokeShareLink: t`
|
|
212
|
+
mutation RevokeAgentInstructionFileShareLink($input: RevokeShareInput!) {
|
|
213
|
+
revokeAgentInstructionFileShareLink(input: $input) {
|
|
214
|
+
id
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
`
|
|
218
|
+
},
|
|
219
|
+
tunnel: {
|
|
220
|
+
readField: "tunnel",
|
|
221
|
+
createLinkField: "createTunnelShareLink",
|
|
222
|
+
sharesQuery: t`
|
|
223
|
+
query TunnelShares($id: ID!) {
|
|
224
|
+
tunnel(id: $id) {
|
|
225
|
+
id
|
|
226
|
+
name
|
|
227
|
+
vibeId
|
|
228
|
+
hasShares
|
|
229
|
+
myRole
|
|
230
|
+
shares {
|
|
231
|
+
${e}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
`,
|
|
236
|
+
share: t`
|
|
237
|
+
mutation ShareTunnel($input: ShareEntityInput!) {
|
|
238
|
+
shareTunnel(input: $input) {
|
|
239
|
+
${e}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
`,
|
|
243
|
+
revokeShare: t`
|
|
244
|
+
mutation RevokeTunnelShare($input: RevokeShareInput!) {
|
|
245
|
+
revokeTunnelShare(input: $input) {
|
|
246
|
+
id
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
`,
|
|
250
|
+
updateShareRole: t`
|
|
251
|
+
mutation UpdateTunnelShareRole($input: UpdateShareRoleInput!) {
|
|
252
|
+
updateTunnelShareRole(input: $input) {
|
|
253
|
+
id
|
|
254
|
+
role
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
`,
|
|
258
|
+
createShareLink: t`
|
|
259
|
+
mutation CreateTunnelShareLink($input: CreateShareGrantLinkInput!) {
|
|
260
|
+
createTunnelShareLink(input: $input) {
|
|
261
|
+
${e}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
`,
|
|
265
|
+
revokeShareLink: t`
|
|
266
|
+
mutation RevokeTunnelShareLink($input: RevokeShareInput!) {
|
|
267
|
+
revokeTunnelShareLink(input: $input) {
|
|
268
|
+
id
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
`
|
|
272
|
+
}
|
|
273
|
+
};
|
|
274
|
+
//#endregion
|
|
275
|
+
export { n as ENTITY_SHARE_OPS };
|
|
276
|
+
|
|
277
|
+
//# sourceMappingURL=entityShareOps.js.map
|
|
@@ -0,0 +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 */\n\nimport { gql, type DocumentNode } from '@apollo/client';\n\nimport { SHARE_GRANT_FIELDS } from './shareControllerTypes';\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\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/** Entity types served by the generic {@link useEntityShareController}. */\nexport type GenericShareEntity = 'aiprompt' | 'action' | 'aicontext' | 'instructionfile' | 'tunnel';\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};\n"],"mappings":";;AA0UA,IAAa,IAA+D;CAC1E,UA5RkC;EAClC,WAAW;EACX,iBAAiB;EACjB,aAAa,CAAG;;;;;;;;YAQN,EAAmB;;;;;EAK7B,OAAO,CAAG;;;UAGF,EAAmB;;;;EAI3B,aAAa,CAAG;;;;;;;EAOhB,iBAAiB,CAAG;;;;;;;;EAQpB,iBAAiB,CAAG;;;UAGZ,EAAmB;;;;EAI3B,iBAAiB,CAAG;;;;;;;EAOrB;CAyOC,QAtOgC;EAChC,WAAW;EACX,iBAAiB;EACjB,aAAa,CAAG;;;;;;;;;YASN,EAAmB;;;;;EAK7B,OAAO,CAAG;;;UAGF,EAAmB;;;;EAI3B,aAAa,CAAG;;;;;;;EAOhB,iBAAiB,CAAG;;;;;;;;EAQpB,iBAAiB,CAAG;;;UAGZ,EAAmB;;;;EAI3B,iBAAiB,CAAG;;;;;;;EAOrB;CAkLC,WA/KmC;EACnC,WAAW;EACX,iBAAiB;EACjB,aAAa,CAAG;;;;;;;;;YASN,EAAmB;;;;;EAK7B,OAAO,CAAG;;;UAGF,EAAmB;;;;EAI3B,aAAa,CAAG;;;;;;;EAOhB,iBAAiB,CAAG;;;;;;;;EAQpB,iBAAiB,CAAG;;;UAGZ,EAAmB;;;;EAI3B,iBAAiB,CAAG;;;;;;;EAOrB;CA2HC,iBAvHyC;EACzC,WAAW;EACX,iBAAiB;EACjB,aAAa,CAAG;;;;;;;;;YASN,EAAmB;;;;;EAK7B,OAAO,CAAG;;;UAGF,EAAmB;;;;EAI3B,aAAa,CAAG;;;;;;;EAOhB,iBAAiB,CAAG;;;;;;;;EAQpB,iBAAiB,CAAG;;;UAGZ,EAAmB;;;;EAI3B,iBAAiB,CAAG;;;;;;;EAOrB;CAmEC,QAhEgC;EAChC,WAAW;EACX,iBAAiB;EACjB,aAAa,CAAG;;;;;;;;;YASN,EAAmB;;;;;EAK7B,OAAO,CAAG;;;UAGF,EAAmB;;;;EAI3B,aAAa,CAAG;;;;;;;EAOhB,iBAAiB,CAAG;;;;;;;;EAQpB,iBAAiB,CAAG;;;UAGZ,EAAmB;;;;EAI3B,iBAAiB,CAAG;;;;;;;EAOrB;CAYA"}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import "./shareRegistry.js";
|
|
2
2
|
import "./useVibeShareController.js";
|
|
3
3
|
import "./useNoteShareController.js";
|
|
4
|
+
import "./entityShareOps.js";
|
|
5
|
+
import "./useEntityShareController.js";
|
|
4
6
|
import "./VibeShareButton.js";
|
|
7
|
+
import "./EntityShareButton.js";
|
|
5
8
|
import "./NoteShareDialog.js";
|
|
6
9
|
import "./SharedWithMePanel.js";
|
|
@@ -11,6 +11,31 @@ var t = (e) => `vibecontrols.sharing.${e}`, n = {
|
|
|
11
11
|
featureFlag: t("note"),
|
|
12
12
|
defaultEnabled: !0
|
|
13
13
|
},
|
|
14
|
+
aiprompt: {
|
|
15
|
+
permission: e.AIPROMPT_SHARE,
|
|
16
|
+
featureFlag: t("aiprompt"),
|
|
17
|
+
defaultEnabled: !0
|
|
18
|
+
},
|
|
19
|
+
action: {
|
|
20
|
+
permission: e.ACTION_SHARE,
|
|
21
|
+
featureFlag: t("action"),
|
|
22
|
+
defaultEnabled: !0
|
|
23
|
+
},
|
|
24
|
+
aicontext: {
|
|
25
|
+
permission: e.AICONTEXT_SHARE,
|
|
26
|
+
featureFlag: t("aicontext"),
|
|
27
|
+
defaultEnabled: !0
|
|
28
|
+
},
|
|
29
|
+
instructionfile: {
|
|
30
|
+
permission: e.INSTRUCTION_FILE_SHARE,
|
|
31
|
+
featureFlag: t("instructionfile"),
|
|
32
|
+
defaultEnabled: !0
|
|
33
|
+
},
|
|
34
|
+
tunnel: {
|
|
35
|
+
permission: e.TUNNEL_SHARE,
|
|
36
|
+
featureFlag: t("tunnel"),
|
|
37
|
+
defaultEnabled: !0
|
|
38
|
+
},
|
|
14
39
|
session: {
|
|
15
40
|
permission: e.SESSION_UPDATE,
|
|
16
41
|
featureFlag: t("session"),
|
|
@@ -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` ship ON (`defaultEnabled: true`) — the backend share\n *
|
|
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 * are declared for completeness but are wired to default-OFF flags and have\n * no Share button mounted yet. They exist so a future PR only has to flip the\n * flag + drop in a controller, not invent the registry shape.\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: declared, not wired, default-OFF ───────────────────────────\n catalog: {\n permission: VIBE_PERMISSIONS.VIBE_MANAGE,\n featureFlag: flagKey('catalog'),\n defaultEnabled: false,\n },\n component: {\n permission: VIBE_PERMISSIONS.VIBE_MANAGE,\n featureFlag: flagKey('component'),\n defaultEnabled: false,\n },\n template: {\n permission: VIBE_PERMISSIONS.VIBE_MANAGE,\n featureFlag: flagKey('template'),\n defaultEnabled: false,\n },\n scorecard: {\n permission: VIBE_PERMISSIONS.VIBE_MANAGE,\n featureFlag: flagKey('scorecard'),\n defaultEnabled: false,\n },\n target: {\n permission: VIBE_PERMISSIONS.TARGET_UPDATE,\n featureFlag: flagKey('target'),\n defaultEnabled: false,\n },\n docs: {\n permission: VIBE_PERMISSIONS.DOCS_PAGE_UPDATE,\n featureFlag: flagKey('docs'),\n defaultEnabled: false,\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":";;AA2DA,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"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { VIBE_SHARE_ROLES as e, partitionGrants as t } from "./shareControllerTypes.js";
|
|
2
|
+
import { ENTITY_SHARE_OPS as n } from "./entityShareOps.js";
|
|
3
|
+
import { useCallback as r, useMemo as i } from "react";
|
|
4
|
+
import { useMutation as a, useQuery as o } from "@apollo/client/react";
|
|
5
|
+
//#region src/components/sharing/useEntityShareController.ts
|
|
6
|
+
function s(s, c) {
|
|
7
|
+
let l = n[s], { data: u, loading: d, refetch: f } = o(l.sharesQuery, {
|
|
8
|
+
variables: { id: c.id },
|
|
9
|
+
skip: !c.id,
|
|
10
|
+
fetchPolicy: "cache-and-network"
|
|
11
|
+
}), [p] = a(l.share), [m] = a(l.revokeShare), [h] = a(l.updateShareRole), [g] = a(l.createShareLink), [_] = a(l.revokeShareLink), v = u?.[l.readField] ?? null, { grants: y, links: b } = i(() => t(v?.shares ?? []), [v?.shares]), x = v?.vibeId ?? c.vibeId ?? null;
|
|
12
|
+
return {
|
|
13
|
+
loading: d,
|
|
14
|
+
grants: y,
|
|
15
|
+
links: b,
|
|
16
|
+
refetch: r(() => {
|
|
17
|
+
f();
|
|
18
|
+
}, [f]),
|
|
19
|
+
createUserShare: r(async ({ email: e, role: t, message: n, expiresAt: r }) => {
|
|
20
|
+
await p({ variables: { input: {
|
|
21
|
+
resourceId: c.id,
|
|
22
|
+
email: e,
|
|
23
|
+
role: t,
|
|
24
|
+
message: n,
|
|
25
|
+
expiresAt: r
|
|
26
|
+
} } }), f();
|
|
27
|
+
}, [
|
|
28
|
+
p,
|
|
29
|
+
c.id,
|
|
30
|
+
f
|
|
31
|
+
]),
|
|
32
|
+
createLinkShare: r(async ({ role: e, expiresAt: t }) => {
|
|
33
|
+
let n = await g({ variables: { input: {
|
|
34
|
+
resourceId: c.id,
|
|
35
|
+
role: e,
|
|
36
|
+
expiresAt: t ?? null
|
|
37
|
+
} } });
|
|
38
|
+
return f(), { shareUrl: n.data?.[l.createLinkField]?.shareUrl ?? "" };
|
|
39
|
+
}, [
|
|
40
|
+
g,
|
|
41
|
+
c.id,
|
|
42
|
+
f,
|
|
43
|
+
l.createLinkField
|
|
44
|
+
]),
|
|
45
|
+
updateRole: r(async (e, t) => {
|
|
46
|
+
await h({ variables: { input: {
|
|
47
|
+
resourceId: c.id,
|
|
48
|
+
shareId: e,
|
|
49
|
+
role: t
|
|
50
|
+
} } }), f();
|
|
51
|
+
}, [
|
|
52
|
+
h,
|
|
53
|
+
c.id,
|
|
54
|
+
f
|
|
55
|
+
]),
|
|
56
|
+
revoke: r(async (e) => {
|
|
57
|
+
await m({ variables: { input: {
|
|
58
|
+
resourceId: c.id,
|
|
59
|
+
shareId: e
|
|
60
|
+
} } }), f();
|
|
61
|
+
}, [
|
|
62
|
+
m,
|
|
63
|
+
c.id,
|
|
64
|
+
f
|
|
65
|
+
]),
|
|
66
|
+
revokeLink: r(async (e) => {
|
|
67
|
+
await _({ variables: { input: {
|
|
68
|
+
resourceId: c.id,
|
|
69
|
+
shareId: e
|
|
70
|
+
} } }), f();
|
|
71
|
+
}, [
|
|
72
|
+
_,
|
|
73
|
+
c.id,
|
|
74
|
+
f
|
|
75
|
+
]),
|
|
76
|
+
capabilities: {
|
|
77
|
+
supportsUsers: !0,
|
|
78
|
+
supportsLink: !0,
|
|
79
|
+
supportsVibeShare: !!x,
|
|
80
|
+
supportsExpiry: !0,
|
|
81
|
+
roles: e
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
//#endregion
|
|
86
|
+
export { s as useEntityShareController };
|
|
87
|
+
|
|
88
|
+
//# sourceMappingURL=useEntityShareController.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useEntityShareController.js","names":[],"sources":["../../../src/components/sharing/useEntityShareController.ts"],"sourcesContent":["/**\n * `useEntityShareController` — a single, entity-parameterized share controller\n * mirroring `useVibeShareController` / `useNoteShareController`.\n *\n * Rather than hand-copy a 190-line controller five times (aiprompt, action,\n * aicontext, instructionfile, tunnel) — all of which expose the identical\n * `ShareEntityInput` / `RevokeShareInput` / `UpdateShareRoleInput` /\n * `CreateShareGrantLinkInput` backend contract — this hook takes the entity's\n * inline-`gql` document set from {@link ENTITY_SHARE_OPS} and projects the\n * response onto the fe-libs `ShareController`.\n *\n * It exposes every optional capability (links, role updates, revoke) since the\n * backend supports them all for these five entities. `supportsVibeShare` is\n * enabled only when the resource row carries a `vibeId` — a standalone resource\n * has no vibe audience to share with.\n */\n\nimport { useCallback, useMemo } from 'react';\nimport { useMutation, useQuery } from '@apollo/client/react';\nimport type { ShareController, ShareRole } from '@burdenoff/fe-libs/sharing';\n\nimport { VIBE_SHARE_ROLES, partitionGrants, type ShareGrantNode } from './shareControllerTypes';\nimport { ENTITY_SHARE_OPS, type GenericShareEntity } from './entityShareOps';\n\n/** Minimal shape the read query returns under `data[readField]`. */\ninterface EntityShareReadNode {\n id: string;\n vibeId?: string | null;\n myRole: ShareRole | null;\n shares: ShareGrantNode[];\n}\n\ntype EntitySharesData = Record<string, EntityShareReadNode | null>;\n\ninterface CreateLinkData {\n [field: string]: ShareGrantNode | undefined;\n}\n\n/**\n * Build a {@link ShareController} for a generic-sharing entity. Pass a stable\n * `{ id }` reference plus the entity's `vibeId` (when known) so the dialog can\n * surface the \"Everyone with Vibe\" mode.\n */\nexport function useEntityShareController(\n entity: GenericShareEntity,\n resource: { id: string; vibeId?: string | null }\n): ShareController {\n const ops = ENTITY_SHARE_OPS[entity];\n\n const { data, loading, refetch } = useQuery<EntitySharesData, { id: string }>(ops.sharesQuery, {\n variables: { id: resource.id },\n skip: !resource.id,\n fetchPolicy: 'cache-and-network',\n });\n\n const [shareEntity] = useMutation(ops.share);\n const [revokeEntityShare] = useMutation(ops.revokeShare);\n const [updateEntityShareRole] = useMutation(ops.updateShareRole);\n const [createEntityShareLink] = useMutation<CreateLinkData>(ops.createShareLink);\n const [revokeEntityShareLink] = useMutation(ops.revokeShareLink);\n\n const node = data?.[ops.readField] ?? null;\n\n const { grants, links } = useMemo(() => partitionGrants(node?.shares ?? []), [node?.shares]);\n\n // Prefer the freshly-read `vibeId` from the resource row; fall back to the\n // caller-provided hint when the read hasn't resolved yet.\n const vibeId = node?.vibeId ?? resource.vibeId ?? null;\n\n const doRefetch = useCallback(() => {\n void refetch();\n }, [refetch]);\n\n const createUserShare = useCallback<ShareController['createUserShare']>(\n async ({ email, role, message, expiresAt }) => {\n await shareEntity({\n variables: { input: { resourceId: resource.id, email, role, message, expiresAt } },\n });\n void refetch();\n },\n [shareEntity, resource.id, refetch]\n );\n\n const createLinkShare = useCallback<NonNullable<ShareController['createLinkShare']>>(\n async ({ role, expiresAt }) => {\n const result = await createEntityShareLink({\n variables: { input: { resourceId: resource.id, role, expiresAt: expiresAt ?? null } },\n });\n void refetch();\n return { shareUrl: result.data?.[ops.createLinkField]?.shareUrl ?? '' };\n },\n [createEntityShareLink, resource.id, refetch, ops.createLinkField]\n );\n\n const updateRole = useCallback<NonNullable<ShareController['updateRole']>>(\n async (grantId, role) => {\n await updateEntityShareRole({\n variables: { input: { resourceId: resource.id, shareId: grantId, role } },\n });\n void refetch();\n },\n [updateEntityShareRole, resource.id, refetch]\n );\n\n const revoke = useCallback<NonNullable<ShareController['revoke']>>(\n async (grantId) => {\n await revokeEntityShare({\n variables: { input: { resourceId: resource.id, shareId: grantId } },\n });\n void refetch();\n },\n [revokeEntityShare, resource.id, refetch]\n );\n\n const revokeLink = useCallback<NonNullable<ShareController['revokeLink']>>(\n async (grantId) => {\n await revokeEntityShareLink({\n variables: { input: { resourceId: resource.id, shareId: grantId } },\n });\n void refetch();\n },\n [revokeEntityShareLink, resource.id, refetch]\n );\n\n return {\n loading,\n grants,\n links,\n refetch: doRefetch,\n createUserShare,\n createLinkShare,\n updateRole,\n revoke,\n revokeLink,\n capabilities: {\n supportsUsers: true,\n supportsLink: true,\n supportsVibeShare: Boolean(vibeId),\n supportsExpiry: true,\n roles: VIBE_SHARE_ROLES,\n },\n };\n}\n"],"mappings":";;;;;AA2CA,SAAgB,EACd,GACA,GACiB;CACjB,IAAM,IAAM,EAAiB,IAEvB,EAAE,SAAM,YAAS,eAAY,EAA2C,EAAI,aAAa;EAC7F,WAAW,EAAE,IAAI,EAAS,IAAI;EAC9B,MAAM,CAAC,EAAS;EAChB,aAAa;EACd,CAAC,EAEI,CAAC,KAAe,EAAY,EAAI,MAAM,EACtC,CAAC,KAAqB,EAAY,EAAI,YAAY,EAClD,CAAC,KAAyB,EAAY,EAAI,gBAAgB,EAC1D,CAAC,KAAyB,EAA4B,EAAI,gBAAgB,EAC1E,CAAC,KAAyB,EAAY,EAAI,gBAAgB,EAE1D,IAAO,IAAO,EAAI,cAAc,MAEhC,EAAE,WAAQ,aAAU,QAAc,EAAgB,GAAM,UAAU,EAAE,CAAC,EAAE,CAAC,GAAM,OAAO,CAAC,EAItF,IAAS,GAAM,UAAU,EAAS,UAAU;AAyDlD,QAAO;EACL;EACA;EACA;EACA,SA3DgB,QAAkB;AAC7B,MAAS;KACb,CAAC,EAAQ,CAAC;EA0DX,iBAxDsB,EACtB,OAAO,EAAE,UAAO,SAAM,YAAS,mBAAgB;AAIxC,GAHL,MAAM,EAAY,EAChB,WAAW,EAAE,OAAO;IAAE,YAAY,EAAS;IAAI;IAAO;IAAM;IAAS;IAAW,EAAE,EACnF,CAAC,EACG,GAAS;KAEhB;GAAC;GAAa,EAAS;GAAI;GAAQ,CACpC;EAiDC,iBA/CsB,EACtB,OAAO,EAAE,SAAM,mBAAgB;GAC7B,IAAM,IAAS,MAAM,EAAsB,EACzC,WAAW,EAAE,OAAO;IAAE,YAAY,EAAS;IAAI;IAAM,WAAW,KAAa;IAAM,EAAE,EACtF,CAAC;AAEF,UADK,GAAS,EACP,EAAE,UAAU,EAAO,OAAO,EAAI,kBAAkB,YAAY,IAAI;KAEzE;GAAC;GAAuB,EAAS;GAAI;GAAS,EAAI;GAAgB,CACnE;EAuCC,YArCiB,EACjB,OAAO,GAAS,MAAS;AAIlB,GAHL,MAAM,EAAsB,EAC1B,WAAW,EAAE,OAAO;IAAE,YAAY,EAAS;IAAI,SAAS;IAAS;IAAM,EAAE,EAC1E,CAAC,EACG,GAAS;KAEhB;GAAC;GAAuB,EAAS;GAAI;GAAQ,CAC9C;EA8BC,QA5Ba,EACb,OAAO,MAAY;AAIZ,GAHL,MAAM,EAAkB,EACtB,WAAW,EAAE,OAAO;IAAE,YAAY,EAAS;IAAI,SAAS;IAAS,EAAE,EACpE,CAAC,EACG,GAAS;KAEhB;GAAC;GAAmB,EAAS;GAAI;GAAQ,CAC1C;EAqBC,YAnBiB,EACjB,OAAO,MAAY;AAIZ,GAHL,MAAM,EAAsB,EAC1B,WAAW,EAAE,OAAO;IAAE,YAAY,EAAS;IAAI,SAAS;IAAS,EAAE,EACpE,CAAC,EACG,GAAS;KAEhB;GAAC;GAAuB,EAAS;GAAI;GAAQ,CAC9C;EAYC,cAAc;GACZ,eAAe;GACf,cAAc;GACd,mBAAmB,EAAQ;GAC3B,gBAAgB;GAChB,OAAO;GACR;EACF"}
|
|
@@ -71,6 +71,10 @@ var e = {
|
|
|
71
71
|
ACTION_UPDATE: "action:update",
|
|
72
72
|
ACTION_DELETE: "action:delete",
|
|
73
73
|
ACTION_EXECUTE: "action:execute",
|
|
74
|
+
ACTION_SHARE: "action:share",
|
|
75
|
+
AIPROMPT_SHARE: "ai-prompt:share",
|
|
76
|
+
AICONTEXT_SHARE: "ai-context:share",
|
|
77
|
+
INSTRUCTION_FILE_SHARE: "instruction-file:share",
|
|
74
78
|
AUDIT_LIST: "audit:list",
|
|
75
79
|
AUDIT_READ: "audit:read",
|
|
76
80
|
AUDIT_DELETE: "audit:delete",
|
|
@@ -84,6 +88,7 @@ var e = {
|
|
|
84
88
|
TUNNEL_READ: "tunnel:read",
|
|
85
89
|
TUNNEL_CREATE: "tunnel:create",
|
|
86
90
|
TUNNEL_DELETE: "tunnel:delete",
|
|
91
|
+
TUNNEL_SHARE: "tunnel:share",
|
|
87
92
|
ANALYTICS_LIST: "analytics:list",
|
|
88
93
|
ANALYTICS_READ: "analytics:read",
|
|
89
94
|
LOG_LIST: "log:list",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permissions.js","names":[],"sources":["../../src/constants/permissions.ts"],"sourcesContent":["/**\n * VibeControls Permission Constants\n *\n * All permission strings for VibeControls resources.\n * Use with fe-libs usePermissions hook: hasPermission(VIBE_PERMISSIONS.VIBE_CREATE)\n *\n * Resource types:\n * - vibe: list, read, create, update, delete, scan, manage\n * - vibecommand: list, read, create, update, delete\n * - agent: list, read, create, update, delete\n * - session: list, read, create, update, delete, execute\n * - note: list, read, create, update, delete\n * - webhook: list, read, create, update, delete\n * - action: list, read, create, update, delete, execute\n * - calendar-agent-task: list, read, create, update, delete, execute\n * - configuration: list, read, create, update, delete\n * - docs_site: list, read, create, update, delete, execute\n * - docs_page: list, read, create, update, delete\n * - target: list, read, create, update, delete\n * - tunnel: list, read, create, delete\n * - analytics: list, read\n * - log: list, read\n */\n\nexport const VIBE_PERMISSIONS = {\n // Vibe resources\n VIBE_LIST: 'vibe:list',\n VIBE_READ: 'vibe:read',\n VIBE_CREATE: 'vibe:create',\n VIBE_UPDATE: 'vibe:update',\n VIBE_DELETE: 'vibe:delete',\n VIBE_SCAN: 'vibe:scan',\n VIBE_MANAGE: 'vibe:manage',\n\n // VibeCommand resources\n VIBECOMMAND_LIST: 'vibecommand:list',\n VIBECOMMAND_READ: 'vibecommand:read',\n VIBECOMMAND_CREATE: 'vibecommand:create',\n VIBECOMMAND_UPDATE: 'vibecommand:update',\n VIBECOMMAND_DELETE: 'vibecommand:delete',\n\n // Agent resources\n AGENT_LIST: 'agent:list',\n AGENT_READ: 'agent:read',\n AGENT_CREATE: 'agent:create',\n AGENT_UPDATE: 'agent:update',\n AGENT_DELETE: 'agent:delete',\n\n // Session resources\n SESSION_LIST: 'session:list',\n SESSION_READ: 'session:read',\n SESSION_CREATE: 'session:create',\n SESSION_UPDATE: 'session:update',\n SESSION_DELETE: 'session:delete',\n SESSION_EXECUTE: 'session:execute',\n\n // Note resources\n NOTE_LIST: 'note:list',\n NOTE_READ: 'note:read',\n NOTE_CREATE: 'note:create',\n NOTE_UPDATE: 'note:update',\n NOTE_DELETE: 'note:delete',\n\n // Webhook resources\n WEBHOOK_LIST: 'webhook:list',\n WEBHOOK_READ: 'webhook:read',\n WEBHOOK_CREATE: 'webhook:create',\n WEBHOOK_UPDATE: 'webhook:update',\n WEBHOOK_DELETE: 'webhook:delete',\n\n // VibeDeck resources\n VIBEDECK_LIST: 'vibedeck:list',\n VIBEDECK_READ: 'vibedeck:read',\n VIBEDECK_CREATE: 'vibedeck:create',\n VIBEDECK_UPDATE: 'vibedeck:update',\n VIBEDECK_DELETE: 'vibedeck:delete',\n VIBEDECK_EXECUTE: 'vibedeck:execute',\n VIBEDECK_SHARE: 'vibedeck:share',\n\n // Calendar Agent Task resources\n CALENDAR_AGENT_TASK_LIST: 'calendar-agent-task:list',\n CALENDAR_AGENT_TASK_READ: 'calendar-agent-task:read',\n CALENDAR_AGENT_TASK_CREATE: 'calendar-agent-task:create',\n CALENDAR_AGENT_TASK_UPDATE: 'calendar-agent-task:update',\n CALENDAR_AGENT_TASK_DELETE: 'calendar-agent-task:delete',\n CALENDAR_AGENT_TASK_EXECUTE: 'calendar-agent-task:execute',\n\n // Schedule resources (wspace-scheduler-svc — the unified-source\n // ScheduledJobs surfaced on the Calendar agenda live here).\n // `scheduledJob`/`scheduledJobs` enforce `schedule:read`;\n // `executeJobNow` enforces `schedule:execute`. Distinct from\n // `calendar-agent-task:*` so RBAC denials don't cross-bleed\n // between the two services.\n SCHEDULE_LIST: 'schedule:list',\n SCHEDULE_READ: 'schedule:read',\n SCHEDULE_EXECUTE: 'schedule:execute',\n\n // Configuration resources\n CONFIG_LIST: 'configuration:list',\n CONFIG_READ: 'configuration:read',\n CONFIG_CREATE: 'configuration:create',\n CONFIG_UPDATE: 'configuration:update',\n CONFIG_DELETE: 'configuration:delete',\n\n // Docs Site resources\n DOCS_SITE_LIST: 'docs_site:list',\n DOCS_SITE_READ: 'docs_site:read',\n DOCS_SITE_CREATE: 'docs_site:create',\n DOCS_SITE_UPDATE: 'docs_site:update',\n DOCS_SITE_DELETE: 'docs_site:delete',\n DOCS_COMPILE: 'docs_site:execute',\n\n // Docs Page resources\n DOCS_PAGE_LIST: 'docs_page:list',\n DOCS_PAGE_READ: 'docs_page:read',\n DOCS_PAGE_CREATE: 'docs_page:create',\n DOCS_PAGE_UPDATE: 'docs_page:update',\n DOCS_PAGE_DELETE: 'docs_page:delete',\n\n // Action resources\n ACTION_LIST: 'action:list',\n ACTION_READ: 'action:read',\n ACTION_CREATE: 'action:create',\n ACTION_UPDATE: 'action:update',\n ACTION_DELETE: 'action:delete',\n ACTION_EXECUTE: 'action:execute',\n\n // Audit resources\n AUDIT_LIST: 'audit:list',\n AUDIT_READ: 'audit:read',\n AUDIT_DELETE: 'audit:delete',\n AUDIT_EXPORT: 'audit:export',\n\n // Target resources — guards wired in BOFF-2034 (Remaining Pages Audit)\n TARGET_LIST: 'target:list',\n TARGET_READ: 'target:read',\n TARGET_CREATE: 'target:create',\n TARGET_UPDATE: 'target:update',\n TARGET_DELETE: 'target:delete',\n\n // Tunnel resources — no TUNNEL_UPDATE: tunnels are create-or-delete only\n TUNNEL_LIST: 'tunnel:list',\n TUNNEL_READ: 'tunnel:read',\n TUNNEL_CREATE: 'tunnel:create',\n TUNNEL_DELETE: 'tunnel:delete',\n\n // Analytics resources\n ANALYTICS_LIST: 'analytics:list',\n ANALYTICS_READ: 'analytics:read',\n\n // Log resources\n LOG_LIST: 'log:list',\n LOG_READ: 'log:read',\n} as const;\n\nexport type VibePermission = (typeof VIBE_PERMISSIONS)[keyof typeof VIBE_PERMISSIONS];\n"],"mappings":";AAwBA,IAAa,IAAmB;CAE9B,WAAW;CACX,WAAW;CACX,aAAa;CACb,aAAa;CACb,aAAa;CACb,WAAW;CACX,aAAa;CAGb,kBAAkB;CAClB,kBAAkB;CAClB,oBAAoB;CACpB,oBAAoB;CACpB,oBAAoB;CAGpB,YAAY;CACZ,YAAY;CACZ,cAAc;CACd,cAAc;CACd,cAAc;CAGd,cAAc;CACd,cAAc;CACd,gBAAgB;CAChB,gBAAgB;CAChB,gBAAgB;CAChB,iBAAiB;CAGjB,WAAW;CACX,WAAW;CACX,aAAa;CACb,aAAa;CACb,aAAa;CAGb,cAAc;CACd,cAAc;CACd,gBAAgB;CAChB,gBAAgB;CAChB,gBAAgB;CAGhB,eAAe;CACf,eAAe;CACf,iBAAiB;CACjB,iBAAiB;CACjB,iBAAiB;CACjB,kBAAkB;CAClB,gBAAgB;CAGhB,0BAA0B;CAC1B,0BAA0B;CAC1B,4BAA4B;CAC5B,4BAA4B;CAC5B,4BAA4B;CAC5B,6BAA6B;CAQ7B,eAAe;CACf,eAAe;CACf,kBAAkB;CAGlB,aAAa;CACb,aAAa;CACb,eAAe;CACf,eAAe;CACf,eAAe;CAGf,gBAAgB;CAChB,gBAAgB;CAChB,kBAAkB;CAClB,kBAAkB;CAClB,kBAAkB;CAClB,cAAc;CAGd,gBAAgB;CAChB,gBAAgB;CAChB,kBAAkB;CAClB,kBAAkB;CAClB,kBAAkB;CAGlB,aAAa;CACb,aAAa;CACb,eAAe;CACf,eAAe;CACf,eAAe;CACf,gBAAgB;CAGhB,YAAY;CACZ,YAAY;CACZ,cAAc;CACd,cAAc;CAGd,aAAa;CACb,aAAa;CACb,eAAe;CACf,eAAe;CACf,eAAe;CAGf,aAAa;CACb,aAAa;CACb,eAAe;CACf,eAAe;
|
|
1
|
+
{"version":3,"file":"permissions.js","names":[],"sources":["../../src/constants/permissions.ts"],"sourcesContent":["/**\n * VibeControls Permission Constants\n *\n * All permission strings for VibeControls resources.\n * Use with fe-libs usePermissions hook: hasPermission(VIBE_PERMISSIONS.VIBE_CREATE)\n *\n * Resource types:\n * - vibe: list, read, create, update, delete, scan, manage\n * - vibecommand: list, read, create, update, delete\n * - agent: list, read, create, update, delete\n * - session: list, read, create, update, delete, execute\n * - note: list, read, create, update, delete\n * - webhook: list, read, create, update, delete\n * - action: list, read, create, update, delete, execute\n * - calendar-agent-task: list, read, create, update, delete, execute\n * - configuration: list, read, create, update, delete\n * - docs_site: list, read, create, update, delete, execute\n * - docs_page: list, read, create, update, delete\n * - target: list, read, create, update, delete\n * - tunnel: list, read, create, delete\n * - analytics: list, read\n * - log: list, read\n */\n\nexport const VIBE_PERMISSIONS = {\n // Vibe resources\n VIBE_LIST: 'vibe:list',\n VIBE_READ: 'vibe:read',\n VIBE_CREATE: 'vibe:create',\n VIBE_UPDATE: 'vibe:update',\n VIBE_DELETE: 'vibe:delete',\n VIBE_SCAN: 'vibe:scan',\n VIBE_MANAGE: 'vibe:manage',\n\n // VibeCommand resources\n VIBECOMMAND_LIST: 'vibecommand:list',\n VIBECOMMAND_READ: 'vibecommand:read',\n VIBECOMMAND_CREATE: 'vibecommand:create',\n VIBECOMMAND_UPDATE: 'vibecommand:update',\n VIBECOMMAND_DELETE: 'vibecommand:delete',\n\n // Agent resources\n AGENT_LIST: 'agent:list',\n AGENT_READ: 'agent:read',\n AGENT_CREATE: 'agent:create',\n AGENT_UPDATE: 'agent:update',\n AGENT_DELETE: 'agent:delete',\n\n // Session resources\n SESSION_LIST: 'session:list',\n SESSION_READ: 'session:read',\n SESSION_CREATE: 'session:create',\n SESSION_UPDATE: 'session:update',\n SESSION_DELETE: 'session:delete',\n SESSION_EXECUTE: 'session:execute',\n\n // Note resources\n NOTE_LIST: 'note:list',\n NOTE_READ: 'note:read',\n NOTE_CREATE: 'note:create',\n NOTE_UPDATE: 'note:update',\n NOTE_DELETE: 'note:delete',\n\n // Webhook resources\n WEBHOOK_LIST: 'webhook:list',\n WEBHOOK_READ: 'webhook:read',\n WEBHOOK_CREATE: 'webhook:create',\n WEBHOOK_UPDATE: 'webhook:update',\n WEBHOOK_DELETE: 'webhook:delete',\n\n // VibeDeck resources\n VIBEDECK_LIST: 'vibedeck:list',\n VIBEDECK_READ: 'vibedeck:read',\n VIBEDECK_CREATE: 'vibedeck:create',\n VIBEDECK_UPDATE: 'vibedeck:update',\n VIBEDECK_DELETE: 'vibedeck:delete',\n VIBEDECK_EXECUTE: 'vibedeck:execute',\n VIBEDECK_SHARE: 'vibedeck:share',\n\n // Calendar Agent Task resources\n CALENDAR_AGENT_TASK_LIST: 'calendar-agent-task:list',\n CALENDAR_AGENT_TASK_READ: 'calendar-agent-task:read',\n CALENDAR_AGENT_TASK_CREATE: 'calendar-agent-task:create',\n CALENDAR_AGENT_TASK_UPDATE: 'calendar-agent-task:update',\n CALENDAR_AGENT_TASK_DELETE: 'calendar-agent-task:delete',\n CALENDAR_AGENT_TASK_EXECUTE: 'calendar-agent-task:execute',\n\n // Schedule resources (wspace-scheduler-svc — the unified-source\n // ScheduledJobs surfaced on the Calendar agenda live here).\n // `scheduledJob`/`scheduledJobs` enforce `schedule:read`;\n // `executeJobNow` enforces `schedule:execute`. Distinct from\n // `calendar-agent-task:*` so RBAC denials don't cross-bleed\n // between the two services.\n SCHEDULE_LIST: 'schedule:list',\n SCHEDULE_READ: 'schedule:read',\n SCHEDULE_EXECUTE: 'schedule:execute',\n\n // Configuration resources\n CONFIG_LIST: 'configuration:list',\n CONFIG_READ: 'configuration:read',\n CONFIG_CREATE: 'configuration:create',\n CONFIG_UPDATE: 'configuration:update',\n CONFIG_DELETE: 'configuration:delete',\n\n // Docs Site resources\n DOCS_SITE_LIST: 'docs_site:list',\n DOCS_SITE_READ: 'docs_site:read',\n DOCS_SITE_CREATE: 'docs_site:create',\n DOCS_SITE_UPDATE: 'docs_site:update',\n DOCS_SITE_DELETE: 'docs_site:delete',\n DOCS_COMPILE: 'docs_site:execute',\n\n // Docs Page resources\n DOCS_PAGE_LIST: 'docs_page:list',\n DOCS_PAGE_READ: 'docs_page:read',\n DOCS_PAGE_CREATE: 'docs_page:create',\n DOCS_PAGE_UPDATE: 'docs_page:update',\n DOCS_PAGE_DELETE: 'docs_page:delete',\n\n // Action resources\n ACTION_LIST: 'action:list',\n ACTION_READ: 'action:read',\n ACTION_CREATE: 'action:create',\n ACTION_UPDATE: 'action:update',\n ACTION_DELETE: 'action:delete',\n ACTION_EXECUTE: 'action:execute',\n ACTION_SHARE: 'action:share',\n\n // AI Prompt resources — generic-sharing surface (backend `shareAiPrompt`)\n AIPROMPT_SHARE: 'ai-prompt:share',\n\n // AI Context resources — generic-sharing surface (backend `shareAiContext`)\n AICONTEXT_SHARE: 'ai-context:share',\n\n // Agent Instruction File resources — generic-sharing surface\n // (backend `shareAgentInstructionFile`)\n INSTRUCTION_FILE_SHARE: 'instruction-file:share',\n\n // Audit resources\n AUDIT_LIST: 'audit:list',\n AUDIT_READ: 'audit:read',\n AUDIT_DELETE: 'audit:delete',\n AUDIT_EXPORT: 'audit:export',\n\n // Target resources — guards wired in BOFF-2034 (Remaining Pages Audit)\n TARGET_LIST: 'target:list',\n TARGET_READ: 'target:read',\n TARGET_CREATE: 'target:create',\n TARGET_UPDATE: 'target:update',\n TARGET_DELETE: 'target:delete',\n\n // Tunnel resources — no TUNNEL_UPDATE: tunnels are create-or-delete only\n TUNNEL_LIST: 'tunnel:list',\n TUNNEL_READ: 'tunnel:read',\n TUNNEL_CREATE: 'tunnel:create',\n TUNNEL_DELETE: 'tunnel:delete',\n TUNNEL_SHARE: 'tunnel:share',\n\n // Analytics resources\n ANALYTICS_LIST: 'analytics:list',\n ANALYTICS_READ: 'analytics:read',\n\n // Log resources\n LOG_LIST: 'log:list',\n LOG_READ: 'log:read',\n} as const;\n\nexport type VibePermission = (typeof VIBE_PERMISSIONS)[keyof typeof VIBE_PERMISSIONS];\n"],"mappings":";AAwBA,IAAa,IAAmB;CAE9B,WAAW;CACX,WAAW;CACX,aAAa;CACb,aAAa;CACb,aAAa;CACb,WAAW;CACX,aAAa;CAGb,kBAAkB;CAClB,kBAAkB;CAClB,oBAAoB;CACpB,oBAAoB;CACpB,oBAAoB;CAGpB,YAAY;CACZ,YAAY;CACZ,cAAc;CACd,cAAc;CACd,cAAc;CAGd,cAAc;CACd,cAAc;CACd,gBAAgB;CAChB,gBAAgB;CAChB,gBAAgB;CAChB,iBAAiB;CAGjB,WAAW;CACX,WAAW;CACX,aAAa;CACb,aAAa;CACb,aAAa;CAGb,cAAc;CACd,cAAc;CACd,gBAAgB;CAChB,gBAAgB;CAChB,gBAAgB;CAGhB,eAAe;CACf,eAAe;CACf,iBAAiB;CACjB,iBAAiB;CACjB,iBAAiB;CACjB,kBAAkB;CAClB,gBAAgB;CAGhB,0BAA0B;CAC1B,0BAA0B;CAC1B,4BAA4B;CAC5B,4BAA4B;CAC5B,4BAA4B;CAC5B,6BAA6B;CAQ7B,eAAe;CACf,eAAe;CACf,kBAAkB;CAGlB,aAAa;CACb,aAAa;CACb,eAAe;CACf,eAAe;CACf,eAAe;CAGf,gBAAgB;CAChB,gBAAgB;CAChB,kBAAkB;CAClB,kBAAkB;CAClB,kBAAkB;CAClB,cAAc;CAGd,gBAAgB;CAChB,gBAAgB;CAChB,kBAAkB;CAClB,kBAAkB;CAClB,kBAAkB;CAGlB,aAAa;CACb,aAAa;CACb,eAAe;CACf,eAAe;CACf,eAAe;CACf,gBAAgB;CAChB,cAAc;CAGd,gBAAgB;CAGhB,iBAAiB;CAIjB,wBAAwB;CAGxB,YAAY;CACZ,YAAY;CACZ,cAAc;CACd,cAAc;CAGd,aAAa;CACb,aAAa;CACb,eAAe;CACf,eAAe;CACf,eAAe;CAGf,aAAa;CACb,aAAa;CACb,eAAe;CACf,eAAe;CACf,cAAc;CAGd,gBAAgB;CAChB,gBAAgB;CAGhB,UAAU;CACV,UAAU;CACX"}
|