@stigmer/react 3.0.7 → 3.0.8-dev.20260612062921
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/access/ManageAccessButton.d.ts +47 -0
- package/access/ManageAccessButton.d.ts.map +1 -0
- package/access/ManageAccessButton.js +45 -0
- package/access/ManageAccessButton.js.map +1 -0
- package/access/ManageAccessDialog.d.ts +60 -0
- package/access/ManageAccessDialog.d.ts.map +1 -0
- package/access/ManageAccessDialog.js +83 -0
- package/access/ManageAccessDialog.js.map +1 -0
- package/access/index.d.ts +5 -0
- package/access/index.d.ts.map +1 -0
- package/access/index.js +7 -0
- package/access/index.js.map +1 -0
- package/access/types.d.ts +56 -0
- package/access/types.d.ts.map +1 -0
- package/access/types.js +2 -0
- package/access/types.js.map +1 -0
- package/access/useManageAccess.d.ts +60 -0
- package/access/useManageAccess.d.ts.map +1 -0
- package/access/useManageAccess.js +41 -0
- package/access/useManageAccess.js.map +1 -0
- package/agent/AgentDetailView.d.ts.map +1 -1
- package/agent/AgentDetailView.js +34 -4
- package/agent/AgentDetailView.js.map +1 -1
- package/agent-instance/AgentInstanceDetailPanel.d.ts.map +1 -1
- package/agent-instance/AgentInstanceDetailPanel.js +14 -4
- package/agent-instance/AgentInstanceDetailPanel.js.map +1 -1
- package/iam-policy/GrantAccessForm.d.ts +15 -5
- package/iam-policy/GrantAccessForm.d.ts.map +1 -1
- package/iam-policy/GrantAccessForm.js +15 -12
- package/iam-policy/GrantAccessForm.js.map +1 -1
- package/iam-policy/OrgMembersPanel.d.ts.map +1 -1
- package/iam-policy/OrgMembersPanel.js +2 -1
- package/iam-policy/OrgMembersPanel.js.map +1 -1
- package/iam-policy/PeopleWithAccess.d.ts +34 -0
- package/iam-policy/PeopleWithAccess.d.ts.map +1 -0
- package/iam-policy/PeopleWithAccess.js +55 -0
- package/iam-policy/PeopleWithAccess.js.map +1 -0
- package/iam-policy/PrincipalPicker.d.ts +48 -0
- package/iam-policy/PrincipalPicker.d.ts.map +1 -0
- package/iam-policy/PrincipalPicker.js +139 -0
- package/iam-policy/PrincipalPicker.js.map +1 -0
- package/iam-policy/ProviderBadge.d.ts +28 -0
- package/iam-policy/ProviderBadge.d.ts.map +1 -0
- package/iam-policy/ProviderBadge.js +31 -0
- package/iam-policy/ProviderBadge.js.map +1 -0
- package/iam-policy/SharePanel.d.ts +13 -5
- package/iam-policy/SharePanel.d.ts.map +1 -1
- package/iam-policy/SharePanel.js +9 -34
- package/iam-policy/SharePanel.js.map +1 -1
- package/iam-policy/index.d.ts +3 -0
- package/iam-policy/index.d.ts.map +1 -1
- package/iam-policy/index.js +3 -0
- package/iam-policy/index.js.map +1 -1
- package/index.d.ts +7 -5
- package/index.d.ts.map +1 -1
- package/index.js +6 -3
- package/index.js.map +1 -1
- package/mcp-server/McpServerDetailView.d.ts.map +1 -1
- package/mcp-server/McpServerDetailView.js +41 -12
- package/mcp-server/McpServerDetailView.js.map +1 -1
- package/organization/OrgProvider.d.ts +9 -0
- package/organization/OrgProvider.d.ts.map +1 -1
- package/organization/OrgProvider.js +12 -0
- package/organization/OrgProvider.js.map +1 -1
- package/organization/index.d.ts +1 -1
- package/organization/index.d.ts.map +1 -1
- package/organization/index.js +1 -1
- package/organization/index.js.map +1 -1
- package/package.json +12 -12
- package/skill/SkillDetailView.d.ts.map +1 -1
- package/skill/SkillDetailView.js +31 -3
- package/skill/SkillDetailView.js.map +1 -1
- package/src/access/ManageAccessButton.tsx +115 -0
- package/src/access/ManageAccessDialog.tsx +239 -0
- package/src/access/__tests__/ManageAccessButton.test.tsx +62 -0
- package/src/access/__tests__/ManageAccessDialog.test.tsx +146 -0
- package/src/access/index.ts +21 -0
- package/src/access/types.ts +58 -0
- package/src/access/useManageAccess.tsx +101 -0
- package/src/agent/AgentDetailView.tsx +50 -21
- package/src/agent-instance/AgentInstanceDetailPanel.tsx +24 -42
- package/src/iam-policy/GrantAccessForm.tsx +30 -35
- package/src/iam-policy/OrgMembersPanel.tsx +2 -0
- package/src/iam-policy/PeopleWithAccess.tsx +220 -0
- package/src/iam-policy/PrincipalPicker.tsx +347 -0
- package/src/iam-policy/ProviderBadge.tsx +53 -0
- package/src/iam-policy/SharePanel.tsx +20 -165
- package/src/iam-policy/index.ts +17 -0
- package/src/index.ts +30 -0
- package/src/mcp-server/McpServerDetailView.tsx +37 -9
- package/src/organization/OrgProvider.tsx +13 -0
- package/src/organization/index.ts +1 -1
- package/src/skill/SkillDetailView.tsx +34 -9
- package/src/workflow/WorkflowDetailView.tsx +49 -22
- package/src/workflow/WorkflowExecutionHeader.tsx +12 -1
- package/src/workflow/WorkflowExecutionViewer.tsx +8 -1
- package/src/workflow/index.ts +4 -0
- package/src/workflow/instance/RunVisibilityControl.tsx +116 -0
- package/src/workflow/instance/WorkflowInstanceDetailPanel.tsx +55 -42
- package/src/workflow/instance/index.ts +5 -0
- package/src/workflow/instance/useUpdateWorkflowInstanceExecutionVisibility.ts +74 -0
- package/styles.css +1 -1
- package/workflow/WorkflowDetailView.d.ts.map +1 -1
- package/workflow/WorkflowDetailView.js +31 -3
- package/workflow/WorkflowDetailView.js.map +1 -1
- package/workflow/WorkflowExecutionHeader.d.ts +7 -0
- package/workflow/WorkflowExecutionHeader.d.ts.map +1 -1
- package/workflow/WorkflowExecutionHeader.js +2 -2
- package/workflow/WorkflowExecutionHeader.js.map +1 -1
- package/workflow/WorkflowExecutionViewer.d.ts +6 -1
- package/workflow/WorkflowExecutionViewer.d.ts.map +1 -1
- package/workflow/WorkflowExecutionViewer.js +2 -2
- package/workflow/WorkflowExecutionViewer.js.map +1 -1
- package/workflow/index.d.ts +1 -1
- package/workflow/index.d.ts.map +1 -1
- package/workflow/index.js +1 -1
- package/workflow/index.js.map +1 -1
- package/workflow/instance/RunVisibilityControl.d.ts +25 -0
- package/workflow/instance/RunVisibilityControl.d.ts.map +1 -0
- package/workflow/instance/RunVisibilityControl.js +56 -0
- package/workflow/instance/RunVisibilityControl.js.map +1 -0
- package/workflow/instance/WorkflowInstanceDetailPanel.d.ts.map +1 -1
- package/workflow/instance/WorkflowInstanceDetailPanel.js +30 -4
- package/workflow/instance/WorkflowInstanceDetailPanel.js.map +1 -1
- package/workflow/instance/index.d.ts +2 -0
- package/workflow/instance/index.d.ts.map +1 -1
- package/workflow/instance/index.js +2 -0
- package/workflow/instance/index.js.map +1 -1
- package/workflow/instance/useUpdateWorkflowInstanceExecutionVisibility.d.ts +30 -0
- package/workflow/instance/useUpdateWorkflowInstanceExecutionVisibility.d.ts.map +1 -0
- package/workflow/instance/useUpdateWorkflowInstanceExecutionVisibility.js +39 -0
- package/workflow/instance/useUpdateWorkflowInstanceExecutionVisibility.js.map +1 -0
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import { useCallback, useState } from "react";
|
|
4
3
|
import type { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
|
|
5
|
-
import type { PrincipalAccess } from "@stigmer/protos/ai/stigmer/iam/iampolicy/v1/io_pb";
|
|
6
4
|
import { cn } from "@stigmer/theme";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { GrantAccessForm } from "./GrantAccessForm";
|
|
5
|
+
import type { ShareFlowResource } from "./useShareFlow";
|
|
6
|
+
import { PeopleWithAccess } from "./PeopleWithAccess";
|
|
10
7
|
|
|
11
8
|
/** Props for {@link SharePanel}. */
|
|
12
9
|
export interface SharePanelProps {
|
|
@@ -16,6 +13,11 @@ export interface SharePanelProps {
|
|
|
16
13
|
readonly resourceKindString: string;
|
|
17
14
|
/** ApiResourceKind enum value for grantable-role lookup. */
|
|
18
15
|
readonly resourceKind: ApiResourceKind;
|
|
16
|
+
/**
|
|
17
|
+
* Organization the resource belongs to (`metadata.org`). Drives the
|
|
18
|
+
* org-member typeahead in the grant form.
|
|
19
|
+
*/
|
|
20
|
+
readonly orgId: string;
|
|
19
21
|
/** Fired when the user closes the panel. */
|
|
20
22
|
readonly onClose?: () => void;
|
|
21
23
|
/** Additional CSS class names for the root container. */
|
|
@@ -26,9 +28,11 @@ export interface SharePanelProps {
|
|
|
26
28
|
* Self-contained sharing panel that displays who has access to a
|
|
27
29
|
* resource and allows granting/revoking access.
|
|
28
30
|
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
31
|
+
* A thin header-and-close wrapper around {@link PeopleWithAccess} — the same
|
|
32
|
+
* "people with access" body the unified Manage access dialog renders — so the
|
|
33
|
+
* two surfaces stay byte-for-byte consistent. Suitable for embedding in a
|
|
34
|
+
* popover or sidebar; for the full visibility + people experience use the
|
|
35
|
+
* Manage access dialog instead.
|
|
32
36
|
*
|
|
33
37
|
* All visual properties flow through `--stgm-*` design tokens.
|
|
34
38
|
*
|
|
@@ -38,6 +42,7 @@ export interface SharePanelProps {
|
|
|
38
42
|
* resource={{ kind: "session", id: sessionId, resourceKind: ApiResourceKind.session }}
|
|
39
43
|
* resourceKindString="session"
|
|
40
44
|
* resourceKind={ApiResourceKind.session}
|
|
45
|
+
* orgId={orgId}
|
|
41
46
|
* onClose={() => setOpen(false)}
|
|
42
47
|
* />
|
|
43
48
|
* ```
|
|
@@ -46,22 +51,10 @@ export function SharePanel({
|
|
|
46
51
|
resource,
|
|
47
52
|
resourceKindString,
|
|
48
53
|
resourceKind,
|
|
54
|
+
orgId,
|
|
49
55
|
onClose,
|
|
50
56
|
className,
|
|
51
57
|
}: SharePanelProps) {
|
|
52
|
-
const {
|
|
53
|
-
accessList,
|
|
54
|
-
isLoading,
|
|
55
|
-
fetchError,
|
|
56
|
-
revokeAccess,
|
|
57
|
-
isRevoking,
|
|
58
|
-
revokeError,
|
|
59
|
-
refetch,
|
|
60
|
-
hasGrantableRoles,
|
|
61
|
-
} = useShareFlow(resource);
|
|
62
|
-
|
|
63
|
-
const [showGrantForm, setShowGrantForm] = useState(false);
|
|
64
|
-
|
|
65
58
|
return (
|
|
66
59
|
<div
|
|
67
60
|
className={cn("flex flex-col gap-4 p-4", className)}
|
|
@@ -88,146 +81,16 @@ export function SharePanel({
|
|
|
88
81
|
)}
|
|
89
82
|
</div>
|
|
90
83
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
</p>
|
|
98
|
-
|
|
99
|
-
{fetchError && (
|
|
100
|
-
<p className="text-destructive text-[0.65rem]" role="alert">
|
|
101
|
-
{getUserMessage(fetchError)}
|
|
102
|
-
</p>
|
|
103
|
-
)}
|
|
104
|
-
|
|
105
|
-
{!isLoading && accessList.length > 0 && (
|
|
106
|
-
<ul className="space-y-1 mt-2" aria-label="People with access">
|
|
107
|
-
{accessList.map((entry) => (
|
|
108
|
-
<AccessEntry
|
|
109
|
-
key={entry.principal?.id ?? "unknown"}
|
|
110
|
-
entry={entry}
|
|
111
|
-
resourceKindString={resourceKindString}
|
|
112
|
-
resourceId={resource.id}
|
|
113
|
-
onRevoke={revokeAccess}
|
|
114
|
-
isRevoking={isRevoking}
|
|
115
|
-
/>
|
|
116
|
-
))}
|
|
117
|
-
</ul>
|
|
118
|
-
)}
|
|
119
|
-
|
|
120
|
-
{revokeError && (
|
|
121
|
-
<p className="text-destructive text-[0.65rem]" role="alert">
|
|
122
|
-
{getUserMessage(revokeError)}
|
|
123
|
-
</p>
|
|
124
|
-
)}
|
|
125
|
-
</div>
|
|
126
|
-
|
|
127
|
-
{/* Grant form */}
|
|
128
|
-
{hasGrantableRoles && (
|
|
129
|
-
<div className="border-t border-border pt-3">
|
|
130
|
-
{showGrantForm ? (
|
|
131
|
-
<GrantAccessForm
|
|
132
|
-
resourceKind={resourceKind}
|
|
133
|
-
resourceKindString={resourceKindString}
|
|
134
|
-
resourceId={resource.id}
|
|
135
|
-
onGranted={() => {
|
|
136
|
-
setShowGrantForm(false);
|
|
137
|
-
refetch();
|
|
138
|
-
}}
|
|
139
|
-
onCancel={() => setShowGrantForm(false)}
|
|
140
|
-
/>
|
|
141
|
-
) : (
|
|
142
|
-
<button
|
|
143
|
-
type="button"
|
|
144
|
-
onClick={() => setShowGrantForm(true)}
|
|
145
|
-
className={cn(
|
|
146
|
-
"w-full rounded-md px-3 py-1.5 text-xs font-medium text-center",
|
|
147
|
-
"border border-dashed border-border",
|
|
148
|
-
"text-muted-foreground hover:text-foreground hover:border-foreground/30",
|
|
149
|
-
"hover:bg-accent-hover transition-colors",
|
|
150
|
-
)}
|
|
151
|
-
>
|
|
152
|
-
+ Add people
|
|
153
|
-
</button>
|
|
154
|
-
)}
|
|
155
|
-
</div>
|
|
156
|
-
)}
|
|
84
|
+
<PeopleWithAccess
|
|
85
|
+
resource={resource}
|
|
86
|
+
resourceKindString={resourceKindString}
|
|
87
|
+
resourceKind={resourceKind}
|
|
88
|
+
orgId={orgId}
|
|
89
|
+
/>
|
|
157
90
|
</div>
|
|
158
91
|
);
|
|
159
92
|
}
|
|
160
93
|
|
|
161
|
-
// ---------------------------------------------------------------------------
|
|
162
|
-
// Internal subcomponents
|
|
163
|
-
// ---------------------------------------------------------------------------
|
|
164
|
-
|
|
165
|
-
function AccessEntry({
|
|
166
|
-
entry,
|
|
167
|
-
resourceKindString,
|
|
168
|
-
resourceId,
|
|
169
|
-
onRevoke,
|
|
170
|
-
isRevoking,
|
|
171
|
-
}: {
|
|
172
|
-
readonly entry: PrincipalAccess;
|
|
173
|
-
readonly resourceKindString: string;
|
|
174
|
-
readonly resourceId: string;
|
|
175
|
-
readonly onRevoke: (principalId: string, role: string) => Promise<void>;
|
|
176
|
-
readonly isRevoking: boolean;
|
|
177
|
-
}) {
|
|
178
|
-
const principal = entry.principal;
|
|
179
|
-
const roles = entry.roles;
|
|
180
|
-
|
|
181
|
-
const displayName = principal?.name || principal?.email || principal?.id || "Unknown";
|
|
182
|
-
const primaryRole = roles[0]?.role;
|
|
183
|
-
|
|
184
|
-
const handleRevoke = useCallback(async () => {
|
|
185
|
-
if (!principal?.id || !primaryRole?.code) return;
|
|
186
|
-
await onRevoke(principal.id, primaryRole.code);
|
|
187
|
-
}, [principal?.id, primaryRole?.code, onRevoke]);
|
|
188
|
-
|
|
189
|
-
return (
|
|
190
|
-
<li className="flex items-center justify-between gap-2 rounded-md px-2 py-1.5 hover:bg-accent-hover group">
|
|
191
|
-
<div className="flex items-center gap-2 min-w-0">
|
|
192
|
-
<div
|
|
193
|
-
className="h-6 w-6 rounded-full bg-muted flex items-center justify-center text-[0.6rem] font-medium text-muted-foreground shrink-0"
|
|
194
|
-
aria-hidden="true"
|
|
195
|
-
>
|
|
196
|
-
{(principal?.name?.[0] ?? principal?.email?.[0] ?? "?").toUpperCase()}
|
|
197
|
-
</div>
|
|
198
|
-
<div className="min-w-0">
|
|
199
|
-
<p className="text-xs text-foreground truncate">{displayName}</p>
|
|
200
|
-
{principal?.email && principal.name && (
|
|
201
|
-
<p className="text-[0.6rem] text-muted-foreground truncate">
|
|
202
|
-
{principal.email}
|
|
203
|
-
</p>
|
|
204
|
-
)}
|
|
205
|
-
</div>
|
|
206
|
-
</div>
|
|
207
|
-
|
|
208
|
-
<div className="flex items-center gap-1.5 shrink-0">
|
|
209
|
-
<span className="text-[0.6rem] text-muted-foreground capitalize">
|
|
210
|
-
{primaryRole?.name ?? primaryRole?.code ?? "—"}
|
|
211
|
-
</span>
|
|
212
|
-
<button
|
|
213
|
-
type="button"
|
|
214
|
-
onClick={handleRevoke}
|
|
215
|
-
disabled={isRevoking}
|
|
216
|
-
aria-label={`Remove ${displayName}'s access`}
|
|
217
|
-
className={cn(
|
|
218
|
-
"rounded p-0.5 text-muted-foreground opacity-0 group-hover:opacity-100",
|
|
219
|
-
"hover:text-destructive hover:bg-destructive/10",
|
|
220
|
-
"disabled:pointer-events-none disabled:opacity-50",
|
|
221
|
-
"transition-opacity",
|
|
222
|
-
)}
|
|
223
|
-
>
|
|
224
|
-
<RemoveIcon />
|
|
225
|
-
</button>
|
|
226
|
-
</div>
|
|
227
|
-
</li>
|
|
228
|
-
);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
94
|
function CloseIcon() {
|
|
232
95
|
return (
|
|
233
96
|
<svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" aria-hidden="true">
|
|
@@ -235,11 +98,3 @@ function CloseIcon() {
|
|
|
235
98
|
</svg>
|
|
236
99
|
);
|
|
237
100
|
}
|
|
238
|
-
|
|
239
|
-
function RemoveIcon() {
|
|
240
|
-
return (
|
|
241
|
-
<svg width="12" height="12" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" aria-hidden="true">
|
|
242
|
-
<path d="M4 4l8 8M12 4l-8 8" />
|
|
243
|
-
</svg>
|
|
244
|
-
);
|
|
245
|
-
}
|
package/src/iam-policy/index.ts
CHANGED
|
@@ -43,8 +43,25 @@ export {
|
|
|
43
43
|
|
|
44
44
|
export { RoleSelector, type RoleSelectorProps } from "./RoleSelector";
|
|
45
45
|
|
|
46
|
+
export {
|
|
47
|
+
PrincipalPicker,
|
|
48
|
+
type PrincipalPickerProps,
|
|
49
|
+
type SelectedPrincipal,
|
|
50
|
+
} from "./PrincipalPicker";
|
|
51
|
+
|
|
52
|
+
export {
|
|
53
|
+
ProviderBadge,
|
|
54
|
+
providerLabel,
|
|
55
|
+
type ProviderBadgeProps,
|
|
56
|
+
} from "./ProviderBadge";
|
|
57
|
+
|
|
46
58
|
export { GrantAccessForm, type GrantAccessFormProps } from "./GrantAccessForm";
|
|
47
59
|
|
|
60
|
+
export {
|
|
61
|
+
PeopleWithAccess,
|
|
62
|
+
type PeopleWithAccessProps,
|
|
63
|
+
} from "./PeopleWithAccess";
|
|
64
|
+
|
|
48
65
|
export {
|
|
49
66
|
OrgMembersPanel,
|
|
50
67
|
type OrgMembersPanelProps,
|
package/src/index.ts
CHANGED
|
@@ -588,7 +588,11 @@ export {
|
|
|
588
588
|
useShareFlow,
|
|
589
589
|
useCheckPermission,
|
|
590
590
|
RoleSelector,
|
|
591
|
+
PrincipalPicker,
|
|
592
|
+
ProviderBadge,
|
|
593
|
+
providerLabel,
|
|
591
594
|
GrantAccessForm,
|
|
595
|
+
PeopleWithAccess,
|
|
592
596
|
OrgMembersPanel,
|
|
593
597
|
SharePanel,
|
|
594
598
|
PermissionGate,
|
|
@@ -610,17 +614,39 @@ export type {
|
|
|
610
614
|
UseCheckPermissionReturn,
|
|
611
615
|
PermissionCheckResource,
|
|
612
616
|
RoleSelectorProps,
|
|
617
|
+
PrincipalPickerProps,
|
|
618
|
+
SelectedPrincipal,
|
|
619
|
+
ProviderBadgeProps,
|
|
613
620
|
GrantAccessFormProps,
|
|
621
|
+
PeopleWithAccessProps,
|
|
614
622
|
OrgMembersPanelProps,
|
|
615
623
|
SharePanelProps,
|
|
616
624
|
PermissionGateProps,
|
|
617
625
|
} from "./iam-policy";
|
|
618
626
|
|
|
627
|
+
// Access — unified "Manage access" experience (visibility + people) as one
|
|
628
|
+
// dialog, with a kebab hook and a visible-button trigger.
|
|
629
|
+
export {
|
|
630
|
+
ManageAccessDialog,
|
|
631
|
+
ManageAccessButton,
|
|
632
|
+
useManageAccess,
|
|
633
|
+
} from "./access";
|
|
634
|
+
export type {
|
|
635
|
+
ManageAccessDialogProps,
|
|
636
|
+
ManageAccessButtonProps,
|
|
637
|
+
UseManageAccessArgs,
|
|
638
|
+
UseManageAccessReturn,
|
|
639
|
+
AccessResource,
|
|
640
|
+
AccessVisibility,
|
|
641
|
+
AccessExtraSection,
|
|
642
|
+
} from "./access";
|
|
643
|
+
|
|
619
644
|
// Organization — context provider, hooks, data hooks, behavior hooks, styled form, profile panel, and org switcher
|
|
620
645
|
export {
|
|
621
646
|
OrgProvider,
|
|
622
647
|
useOrg,
|
|
623
648
|
useActiveOrgSlug,
|
|
649
|
+
useActiveOrgId,
|
|
624
650
|
useOrgGate,
|
|
625
651
|
useOrganization,
|
|
626
652
|
useCreateOrganization,
|
|
@@ -1240,11 +1266,13 @@ export {
|
|
|
1240
1266
|
useWorkflowInstance,
|
|
1241
1267
|
useCreateWorkflowInstance,
|
|
1242
1268
|
useUpdateWorkflowInstance,
|
|
1269
|
+
useUpdateWorkflowInstanceExecutionVisibility,
|
|
1243
1270
|
useDeleteWorkflowInstance,
|
|
1244
1271
|
WorkflowInstanceEmptyState,
|
|
1245
1272
|
WorkflowInstanceList,
|
|
1246
1273
|
CreateWorkflowInstanceDialog,
|
|
1247
1274
|
WorkflowInstanceDetailPanel,
|
|
1275
|
+
RunVisibilityControl,
|
|
1248
1276
|
// T15: Workflow Template Gallery
|
|
1249
1277
|
PATTERN_LABELS,
|
|
1250
1278
|
WORKFLOW_CATEGORY_LABELS,
|
|
@@ -1367,11 +1395,13 @@ export type {
|
|
|
1367
1395
|
UseWorkflowInstanceReturn,
|
|
1368
1396
|
UseCreateWorkflowInstanceReturn,
|
|
1369
1397
|
UseUpdateWorkflowInstanceReturn,
|
|
1398
|
+
UseUpdateWorkflowInstanceExecutionVisibilityReturn,
|
|
1370
1399
|
UseDeleteWorkflowInstanceReturn,
|
|
1371
1400
|
WorkflowInstanceEmptyStateProps,
|
|
1372
1401
|
WorkflowInstanceListProps,
|
|
1373
1402
|
CreateWorkflowInstanceDialogProps,
|
|
1374
1403
|
WorkflowInstanceDetailPanelProps,
|
|
1404
|
+
RunVisibilityControlProps,
|
|
1375
1405
|
// T15: Workflow Template Gallery types
|
|
1376
1406
|
WorkflowTemplateData,
|
|
1377
1407
|
WorkflowTemplateCategory,
|
|
@@ -23,10 +23,12 @@ import type { OAuthConnectPhase } from "./useMcpServerOAuthConnect";
|
|
|
23
23
|
import { useDisconnectOAuth } from "./useDisconnectOAuth";
|
|
24
24
|
import { useOrgOAuthApp } from "./useOrgOAuthApp";
|
|
25
25
|
import { OAuthAppForm } from "./OAuthAppForm";
|
|
26
|
+
import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
|
|
26
27
|
import { ErrorMessage } from "../error/ErrorMessage";
|
|
27
28
|
import { EnvVarForm } from "../environment/EnvVarForm";
|
|
28
29
|
import type { EnvVarFormVariable } from "../environment/EnvVarForm";
|
|
29
|
-
import {
|
|
30
|
+
import { VisibilityBadge } from "../library/VisibilitySelector";
|
|
31
|
+
import { useManageAccess } from "../access/useManageAccess";
|
|
30
32
|
import { Tabs, type TabItem } from "../tabs/Tabs";
|
|
31
33
|
import { ResourceDetailShell } from "../resource-detail/ResourceDetailShell";
|
|
32
34
|
import { Section } from "../resource-detail/Section";
|
|
@@ -338,6 +340,29 @@ export function McpServerDetailView({
|
|
|
338
340
|
oauth.clearError();
|
|
339
341
|
}, [connection, oauth]);
|
|
340
342
|
|
|
343
|
+
// Unified Manage access — visibility (General access) over explicit grants
|
|
344
|
+
// (People), opened from the kebab. Closes the blueprint share gap for MCP
|
|
345
|
+
// servers.
|
|
346
|
+
const access = useManageAccess({
|
|
347
|
+
resource: mcpServer?.metadata
|
|
348
|
+
? {
|
|
349
|
+
kind: ApiResourceKind.mcp_server,
|
|
350
|
+
kindString: "mcp_server",
|
|
351
|
+
id: mcpServer.metadata.id,
|
|
352
|
+
org: mcpServer.metadata.org,
|
|
353
|
+
name: mcpServer.metadata.name,
|
|
354
|
+
}
|
|
355
|
+
: null,
|
|
356
|
+
visibility: mcpServer?.metadata
|
|
357
|
+
? {
|
|
358
|
+
kind: "mcpServer",
|
|
359
|
+
current: mcpServer.metadata.visibility,
|
|
360
|
+
org: mcpServer.metadata.org,
|
|
361
|
+
onChanged: refetch,
|
|
362
|
+
}
|
|
363
|
+
: undefined,
|
|
364
|
+
});
|
|
365
|
+
|
|
341
366
|
if (isLoading) return <LoadingSkeleton className={className} />;
|
|
342
367
|
if (error)
|
|
343
368
|
return <ErrorMessage error={error} retry={refetch} className={className} />;
|
|
@@ -380,16 +405,16 @@ export function McpServerDetailView({
|
|
|
380
405
|
updatedAt: specAudit?.updatedAt ? timestampDate(specAudit.updatedAt) : null,
|
|
381
406
|
};
|
|
382
407
|
|
|
408
|
+
// Inline visibility is read-only (at-a-glance); editing lives in the
|
|
409
|
+
// Manage access dialog, the single writer for both access axes.
|
|
383
410
|
const visibilityControl = meta ? (
|
|
384
|
-
<
|
|
385
|
-
kind="mcpServer"
|
|
386
|
-
resourceId={meta.id}
|
|
387
|
-
visibility={meta.visibility}
|
|
388
|
-
org={meta.org || org}
|
|
389
|
-
onChanged={refetch}
|
|
390
|
-
/>
|
|
411
|
+
<VisibilityBadge visibility={meta.visibility} />
|
|
391
412
|
) : undefined;
|
|
392
413
|
|
|
414
|
+
const mergedActions = access.action
|
|
415
|
+
? [...(actions ?? []), access.action]
|
|
416
|
+
: actions;
|
|
417
|
+
|
|
393
418
|
const headerMetaExtra = (
|
|
394
419
|
<>
|
|
395
420
|
{status && <ValidationStateBadge state={status.validationState} />}
|
|
@@ -409,13 +434,14 @@ export function McpServerDetailView({
|
|
|
409
434
|
) : undefined;
|
|
410
435
|
|
|
411
436
|
return (
|
|
437
|
+
<>
|
|
412
438
|
<ResourceDetailShell
|
|
413
439
|
header={headerMeta}
|
|
414
440
|
visibilityControl={visibilityControl}
|
|
415
441
|
headerMetaExtra={headerMetaExtra}
|
|
416
442
|
headerBanner={headerBanner}
|
|
417
443
|
primaryAction={primaryAction}
|
|
418
|
-
actions={
|
|
444
|
+
actions={mergedActions}
|
|
419
445
|
className={className}
|
|
420
446
|
>
|
|
421
447
|
{(editable || spec?.description) && (
|
|
@@ -576,6 +602,8 @@ export function McpServerDetailView({
|
|
|
576
602
|
<TagsSection tags={spec?.tags ?? []} editable={editable} isSaving={isUpdating} saveMcpField={saveMcpField} />
|
|
577
603
|
)}
|
|
578
604
|
</ResourceDetailShell>
|
|
605
|
+
{access.dialog}
|
|
606
|
+
</>
|
|
579
607
|
);
|
|
580
608
|
}
|
|
581
609
|
|
|
@@ -182,3 +182,16 @@ export function useActiveOrgSlug(): string {
|
|
|
182
182
|
const { activeOrg } = useOrg();
|
|
183
183
|
return activeOrg?.metadata?.slug ?? "";
|
|
184
184
|
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Convenience accessor: returns the active org's system ID (`metadata.id`),
|
|
188
|
+
* or an empty string when no org is selected.
|
|
189
|
+
*
|
|
190
|
+
* This is the identifier used as the `organization` object in authorization
|
|
191
|
+
* (FGA) — e.g. for member lookups in the share picker — as opposed to the
|
|
192
|
+
* human-readable slug returned by {@link useActiveOrgSlug}.
|
|
193
|
+
*/
|
|
194
|
+
export function useActiveOrgId(): string {
|
|
195
|
+
const { activeOrg } = useOrg();
|
|
196
|
+
return activeOrg?.metadata?.id ?? "";
|
|
197
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { OrgProvider, useOrg, useActiveOrgSlug } from "./OrgProvider";
|
|
1
|
+
export { OrgProvider, useOrg, useActiveOrgSlug, useActiveOrgId } from "./OrgProvider";
|
|
2
2
|
export type { OrgContextValue } from "./OrgProvider";
|
|
3
3
|
export { useOrgGate } from "./useOrgGate";
|
|
4
4
|
export type {
|
|
@@ -7,10 +7,12 @@ import { timestampDate } from "@bufbuild/protobuf/wkt";
|
|
|
7
7
|
import type { Skill } from "@stigmer/protos/ai/stigmer/agentic/skill/v1/api_pb";
|
|
8
8
|
import type { GitProvenance } from "@stigmer/protos/ai/stigmer/agentic/skill/v1/status_pb";
|
|
9
9
|
import { SkillState } from "@stigmer/protos/ai/stigmer/agentic/skill/v1/status_pb";
|
|
10
|
+
import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
|
|
10
11
|
import { useSkill } from "./useSkill";
|
|
11
12
|
import { SkillFileBrowser } from "./SkillFileBrowser";
|
|
12
13
|
import { ErrorMessage } from "../error/ErrorMessage";
|
|
13
|
-
import {
|
|
14
|
+
import { VisibilityBadge } from "../library/VisibilitySelector";
|
|
15
|
+
import { useManageAccess } from "../access/useManageAccess";
|
|
14
16
|
import { MARKDOWN_COMPONENTS, REMARK_PLUGINS, stripFrontmatter } from "../internal/markdown-components";
|
|
15
17
|
import { ResourceDetailShell } from "../resource-detail/ResourceDetailShell";
|
|
16
18
|
import { Section } from "../resource-detail/Section";
|
|
@@ -207,6 +209,28 @@ export function SkillDetailView({
|
|
|
207
209
|
}
|
|
208
210
|
}, [skill]);
|
|
209
211
|
|
|
212
|
+
// Unified Manage access — visibility (General access) over explicit grants
|
|
213
|
+
// (People), opened from the kebab. Closes the blueprint share gap for skills.
|
|
214
|
+
const access = useManageAccess({
|
|
215
|
+
resource: skill?.metadata
|
|
216
|
+
? {
|
|
217
|
+
kind: ApiResourceKind.skill,
|
|
218
|
+
kindString: "skill",
|
|
219
|
+
id: skill.metadata.id,
|
|
220
|
+
org: skill.metadata.org,
|
|
221
|
+
name: skill.metadata.name,
|
|
222
|
+
}
|
|
223
|
+
: null,
|
|
224
|
+
visibility: skill?.metadata
|
|
225
|
+
? {
|
|
226
|
+
kind: "skill",
|
|
227
|
+
current: skill.metadata.visibility,
|
|
228
|
+
org: skill.metadata.org,
|
|
229
|
+
onChanged: refetch,
|
|
230
|
+
}
|
|
231
|
+
: undefined,
|
|
232
|
+
});
|
|
233
|
+
|
|
210
234
|
if (isLoading) return <LoadingSkeleton className={className} />;
|
|
211
235
|
if (error)
|
|
212
236
|
return <ErrorMessage error={error} retry={refetch} className={className} />;
|
|
@@ -230,16 +254,16 @@ export function SkillDetailView({
|
|
|
230
254
|
statusLabel: status ? skillStateLabel(status.state) : undefined,
|
|
231
255
|
};
|
|
232
256
|
|
|
257
|
+
// Inline visibility is read-only (at-a-glance); editing lives in the
|
|
258
|
+
// Manage access dialog, the single writer for both access axes.
|
|
233
259
|
const visibilityControl = meta ? (
|
|
234
|
-
<
|
|
235
|
-
kind="skill"
|
|
236
|
-
resourceId={meta.id}
|
|
237
|
-
visibility={meta.visibility}
|
|
238
|
-
org={meta.org || org}
|
|
239
|
-
onChanged={refetch}
|
|
240
|
-
/>
|
|
260
|
+
<VisibilityBadge visibility={meta.visibility} />
|
|
241
261
|
) : undefined;
|
|
242
262
|
|
|
263
|
+
const mergedActions = access.action
|
|
264
|
+
? [...(actions ?? []), access.action]
|
|
265
|
+
: actions;
|
|
266
|
+
|
|
243
267
|
let tabContent: React.ReactNode;
|
|
244
268
|
if (activeAdditionalTab) {
|
|
245
269
|
tabContent = activeAdditionalTab.content;
|
|
@@ -267,7 +291,7 @@ export function SkillDetailView({
|
|
|
267
291
|
header={headerMeta}
|
|
268
292
|
visibilityControl={visibilityControl}
|
|
269
293
|
primaryAction={primaryAction}
|
|
270
|
-
actions={
|
|
294
|
+
actions={mergedActions}
|
|
271
295
|
tabs={effectiveTabs}
|
|
272
296
|
activeTab={effectiveTabs ? effectiveActiveTab : undefined}
|
|
273
297
|
onTabChange={effectiveTabs ? effectiveOnTabChange : undefined}
|
|
@@ -276,6 +300,7 @@ export function SkillDetailView({
|
|
|
276
300
|
>
|
|
277
301
|
{tabContent}
|
|
278
302
|
</ResourceDetailShell>
|
|
303
|
+
{access.dialog}
|
|
279
304
|
<SkillDiffDialog state={diffState} onClose={closeDiff} />
|
|
280
305
|
</>
|
|
281
306
|
);
|
|
@@ -22,7 +22,9 @@ import { WorkflowInstanceList } from "./instance/WorkflowInstanceList";
|
|
|
22
22
|
import { WorkflowVersionsTab } from "./WorkflowVersionsTab";
|
|
23
23
|
import { useWorkflowVersions } from "./useWorkflowVersions";
|
|
24
24
|
import { ErrorMessage } from "../error/ErrorMessage";
|
|
25
|
-
import {
|
|
25
|
+
import { VisibilityBadge } from "../library/VisibilitySelector";
|
|
26
|
+
import { useManageAccess } from "../access/useManageAccess";
|
|
27
|
+
import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
|
|
26
28
|
import { formatDurationSec } from "./format-utils";
|
|
27
29
|
import { ResourceDetailShell } from "../resource-detail/ResourceDetailShell";
|
|
28
30
|
import { Section } from "../resource-detail/Section";
|
|
@@ -232,6 +234,28 @@ export function WorkflowDetailView({
|
|
|
232
234
|
}
|
|
233
235
|
}, [workflow]);
|
|
234
236
|
|
|
237
|
+
// Unified Manage access — visibility (General access) over explicit grants
|
|
238
|
+
// (People), opened from the kebab. Replaces the host's bespoke share popover.
|
|
239
|
+
const access = useManageAccess({
|
|
240
|
+
resource: workflow?.metadata
|
|
241
|
+
? {
|
|
242
|
+
kind: ApiResourceKind.workflow,
|
|
243
|
+
kindString: "workflow",
|
|
244
|
+
id: workflow.metadata.id,
|
|
245
|
+
org: workflow.metadata.org || org,
|
|
246
|
+
name: workflow.metadata.name,
|
|
247
|
+
}
|
|
248
|
+
: null,
|
|
249
|
+
visibility: workflow?.metadata
|
|
250
|
+
? {
|
|
251
|
+
kind: "workflow",
|
|
252
|
+
current: workflow.metadata.visibility,
|
|
253
|
+
org: workflow.metadata.org || org,
|
|
254
|
+
onChanged: refetch,
|
|
255
|
+
}
|
|
256
|
+
: undefined,
|
|
257
|
+
});
|
|
258
|
+
|
|
235
259
|
if (isLoading) return <LoadingSkeleton className={className} />;
|
|
236
260
|
if (error)
|
|
237
261
|
return <ErrorMessage error={error} retry={refetch} className={className} />;
|
|
@@ -257,16 +281,16 @@ export function WorkflowDetailView({
|
|
|
257
281
|
<ValidationIndicator state={validationState} />
|
|
258
282
|
) : undefined;
|
|
259
283
|
|
|
284
|
+
// Inline visibility is read-only (at-a-glance); editing lives in the
|
|
285
|
+
// Manage access dialog, the single writer for both access axes.
|
|
260
286
|
const visibilityControl = meta ? (
|
|
261
|
-
<
|
|
262
|
-
kind="workflow"
|
|
263
|
-
resourceId={meta.id}
|
|
264
|
-
visibility={meta.visibility}
|
|
265
|
-
org={meta.org || org}
|
|
266
|
-
onChanged={refetch}
|
|
267
|
-
/>
|
|
287
|
+
<VisibilityBadge visibility={meta.visibility} />
|
|
268
288
|
) : undefined;
|
|
269
289
|
|
|
290
|
+
const mergedActions = access.action
|
|
291
|
+
? [...(actions ?? []), access.action]
|
|
292
|
+
: actions;
|
|
293
|
+
|
|
270
294
|
let tabContent: React.ReactNode;
|
|
271
295
|
if (activeAdditionalTab) {
|
|
272
296
|
tabContent = activeAdditionalTab.content;
|
|
@@ -309,20 +333,23 @@ export function WorkflowDetailView({
|
|
|
309
333
|
}
|
|
310
334
|
|
|
311
335
|
return (
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
336
|
+
<>
|
|
337
|
+
<ResourceDetailShell
|
|
338
|
+
header={headerMeta}
|
|
339
|
+
visibilityControl={visibilityControl}
|
|
340
|
+
headerMetaExtra={headerMetaExtra}
|
|
341
|
+
primaryAction={primaryAction}
|
|
342
|
+
actions={mergedActions}
|
|
343
|
+
tabs={effectiveTabs}
|
|
344
|
+
activeTab={effectiveActiveTab}
|
|
345
|
+
onTabChange={effectiveOnTabChange}
|
|
346
|
+
tabsAriaLabel="Workflow detail tabs"
|
|
347
|
+
className={className}
|
|
348
|
+
>
|
|
349
|
+
{tabContent}
|
|
350
|
+
</ResourceDetailShell>
|
|
351
|
+
{access.dialog}
|
|
352
|
+
</>
|
|
326
353
|
);
|
|
327
354
|
}
|
|
328
355
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import { memo, useMemo } from "react";
|
|
3
|
+
import { memo, useMemo, type ReactNode } from "react";
|
|
4
4
|
import type { WorkflowExecution } from "@stigmer/protos/ai/stigmer/agentic/workflowexecution/v1/api_pb";
|
|
5
5
|
import { ExecutionPhase } from "@stigmer/protos/ai/stigmer/agentic/workflowexecution/v1/enum_pb";
|
|
6
6
|
import { cn } from "@stigmer/theme";
|
|
@@ -21,6 +21,12 @@ export interface WorkflowExecutionHeaderProps {
|
|
|
21
21
|
readonly isDiagnosing?: boolean;
|
|
22
22
|
/** Called when the user clicks "Compare with..." on a terminal execution. */
|
|
23
23
|
readonly onCompare?: () => void;
|
|
24
|
+
/**
|
|
25
|
+
* Host-supplied action elements rendered at the trailing edge of the
|
|
26
|
+
* header (e.g. a Share control). Kept routing/auth-agnostic per DD-004 —
|
|
27
|
+
* the SDK renders the slot; the host owns its behavior.
|
|
28
|
+
*/
|
|
29
|
+
readonly headerActions?: ReactNode;
|
|
24
30
|
readonly className?: string;
|
|
25
31
|
}
|
|
26
32
|
|
|
@@ -53,6 +59,7 @@ export const WorkflowExecutionHeader = memo(function WorkflowExecutionHeader({
|
|
|
53
59
|
onDiagnose,
|
|
54
60
|
isDiagnosing,
|
|
55
61
|
onCompare,
|
|
62
|
+
headerActions,
|
|
56
63
|
className,
|
|
57
64
|
}: WorkflowExecutionHeaderProps) {
|
|
58
65
|
const phase = execution.status?.phase ?? ExecutionPhase.EXECUTION_PHASE_UNSPECIFIED;
|
|
@@ -160,6 +167,10 @@ export const WorkflowExecutionHeader = memo(function WorkflowExecutionHeader({
|
|
|
160
167
|
/>
|
|
161
168
|
</>
|
|
162
169
|
)}
|
|
170
|
+
|
|
171
|
+
{headerActions && (
|
|
172
|
+
<div className="relative flex items-center">{headerActions}</div>
|
|
173
|
+
)}
|
|
163
174
|
</div>
|
|
164
175
|
</header>
|
|
165
176
|
);
|