@agent-native/dispatch 0.6.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/actions/create-pylon-ticket.d.ts +3 -0
- package/dist/actions/create-pylon-ticket.d.ts.map +1 -0
- package/dist/actions/create-pylon-ticket.js +94 -0
- package/dist/actions/create-pylon-ticket.js.map +1 -0
- package/dist/actions/create-vault-grant.js +1 -1
- package/dist/actions/create-vault-grant.js.map +1 -1
- package/dist/actions/create-vault-secret.d.ts.map +1 -1
- package/dist/actions/create-vault-secret.js +4 -3
- package/dist/actions/create-vault-secret.js.map +1 -1
- package/dist/actions/get-vault-access-settings.d.ts +3 -0
- package/dist/actions/get-vault-access-settings.d.ts.map +1 -0
- package/dist/actions/get-vault-access-settings.js +10 -0
- package/dist/actions/get-vault-access-settings.js.map +1 -0
- package/dist/actions/grant-vault-secrets-to-app.js +1 -1
- package/dist/actions/grant-vault-secrets-to-app.js.map +1 -1
- package/dist/actions/index.d.ts.map +1 -1
- package/dist/actions/index.js +8 -0
- package/dist/actions/index.js.map +1 -1
- package/dist/actions/list-integrations-catalog.js +1 -1
- package/dist/actions/list-integrations-catalog.js.map +1 -1
- package/dist/actions/list-vault-grants.js +1 -1
- package/dist/actions/list-vault-grants.js.map +1 -1
- package/dist/actions/list-workspace-apps.d.ts.map +1 -1
- package/dist/actions/list-workspace-apps.js +5 -1
- package/dist/actions/list-workspace-apps.js.map +1 -1
- package/dist/actions/set-vault-access-settings.d.ts +3 -0
- package/dist/actions/set-vault-access-settings.d.ts.map +1 -0
- package/dist/actions/set-vault-access-settings.js +13 -0
- package/dist/actions/set-vault-access-settings.js.map +1 -0
- package/dist/actions/start-workspace-app-creation.d.ts.map +1 -1
- package/dist/actions/start-workspace-app-creation.js +6 -0
- package/dist/actions/start-workspace-app-creation.js.map +1 -1
- package/dist/actions/sync-vault-to-app.js +1 -1
- package/dist/actions/sync-vault-to-app.js.map +1 -1
- package/dist/actions/update-workspace-app-metadata.d.ts +3 -0
- package/dist/actions/update-workspace-app-metadata.d.ts.map +1 -0
- package/dist/actions/update-workspace-app-metadata.js +30 -0
- package/dist/actions/update-workspace-app-metadata.js.map +1 -0
- package/dist/actions/view-screen.d.ts.map +1 -1
- package/dist/actions/view-screen.js +4 -2
- package/dist/actions/view-screen.js.map +1 -1
- package/dist/components/app-keys-popover.js +16 -5
- package/dist/components/app-keys-popover.js.map +1 -1
- package/dist/components/create-app-popover.d.ts.map +1 -1
- package/dist/components/create-app-popover.js +38 -14
- package/dist/components/create-app-popover.js.map +1 -1
- package/dist/components/dispatch-shell.d.ts +4 -4
- package/dist/components/dispatch-shell.d.ts.map +1 -1
- package/dist/components/dispatch-shell.js +6 -6
- package/dist/components/dispatch-shell.js.map +1 -1
- package/dist/components/layout/Layout.d.ts.map +1 -1
- package/dist/components/layout/Layout.js +10 -3
- package/dist/components/layout/Layout.js.map +1 -1
- package/dist/components/messaging-setup-panel.d.ts.map +1 -1
- package/dist/components/messaging-setup-panel.js +2 -2
- package/dist/components/messaging-setup-panel.js.map +1 -1
- package/dist/components/workspace-app-card.d.ts.map +1 -1
- package/dist/components/workspace-app-card.js +41 -2
- package/dist/components/workspace-app-card.js.map +1 -1
- package/dist/hooks/use-navigation-state.js +12 -5
- package/dist/hooks/use-navigation-state.js.map +1 -1
- package/dist/lib/catch-all-target.d.ts +2 -0
- package/dist/lib/catch-all-target.d.ts.map +1 -0
- package/dist/lib/catch-all-target.js +95 -0
- package/dist/lib/catch-all-target.js.map +1 -0
- package/dist/lib/workspace-apps.d.ts +9 -0
- package/dist/lib/workspace-apps.d.ts.map +1 -1
- package/dist/lib/workspace-apps.js.map +1 -1
- package/dist/routes/pages/$appId.d.ts +2 -2
- package/dist/routes/pages/$appId.d.ts.map +1 -1
- package/dist/routes/pages/$appId.js +17 -8
- package/dist/routes/pages/$appId.js.map +1 -1
- package/dist/routes/pages/integrations.d.ts.map +1 -1
- package/dist/routes/pages/integrations.js +20 -15
- package/dist/routes/pages/integrations.js.map +1 -1
- package/dist/routes/pages/new-app.js +1 -1
- package/dist/routes/pages/new-app.js.map +1 -1
- package/dist/routes/pages/overview.d.ts.map +1 -1
- package/dist/routes/pages/overview.js +5 -1
- package/dist/routes/pages/overview.js.map +1 -1
- package/dist/routes/pages/vault.d.ts.map +1 -1
- package/dist/routes/pages/vault.js +23 -5
- package/dist/routes/pages/vault.js.map +1 -1
- package/dist/server/lib/app-creation-store.d.ts +13 -0
- package/dist/server/lib/app-creation-store.d.ts.map +1 -1
- package/dist/server/lib/app-creation-store.js +295 -9
- package/dist/server/lib/app-creation-store.js.map +1 -1
- package/dist/server/lib/env-config.d.ts.map +1 -1
- package/dist/server/lib/env-config.js +5 -0
- package/dist/server/lib/env-config.js.map +1 -1
- package/dist/server/lib/onboarding-steps.d.ts +12 -0
- package/dist/server/lib/onboarding-steps.d.ts.map +1 -0
- package/dist/server/lib/onboarding-steps.js +47 -0
- package/dist/server/lib/onboarding-steps.js.map +1 -0
- package/dist/server/lib/vault-store.d.ts +55 -0
- package/dist/server/lib/vault-store.d.ts.map +1 -1
- package/dist/server/lib/vault-store.js +210 -41
- package/dist/server/lib/vault-store.js.map +1 -1
- package/dist/server/plugins/agent-chat.d.ts.map +1 -1
- package/dist/server/plugins/agent-chat.js +2 -1
- package/dist/server/plugins/agent-chat.js.map +1 -1
- package/dist/server/plugins/core-routes.d.ts.map +1 -1
- package/dist/server/plugins/core-routes.js +4 -0
- package/dist/server/plugins/core-routes.js.map +1 -1
- package/dist/server/plugins/integrations.js +2 -2
- package/dist/server/plugins/integrations.js.map +1 -1
- package/package.json +13 -11
- package/src/actions/create-pylon-ticket.ts +109 -0
- package/src/actions/create-vault-grant.ts +1 -1
- package/src/actions/create-vault-secret.ts +4 -3
- package/src/actions/get-vault-access-settings.ts +11 -0
- package/src/actions/grant-vault-secrets-to-app.ts +1 -1
- package/src/actions/index.ts +8 -0
- package/src/actions/list-integrations-catalog.ts +1 -1
- package/src/actions/list-vault-grants.ts +1 -1
- package/src/actions/list-workspace-apps.ts +5 -1
- package/src/actions/set-vault-access-settings.ts +16 -0
- package/src/actions/start-workspace-app-creation.ts +8 -0
- package/src/actions/sync-vault-to-app.ts +1 -1
- package/src/actions/update-workspace-app-metadata.ts +32 -0
- package/src/actions/view-screen.ts +4 -1
- package/src/components/app-keys-popover.tsx +23 -7
- package/src/components/create-app-popover.tsx +47 -14
- package/src/components/dispatch-shell.tsx +16 -15
- package/src/components/layout/Layout.tsx +11 -5
- package/src/components/messaging-setup-panel.tsx +54 -39
- package/src/components/workspace-app-card.tsx +102 -0
- package/src/hooks/use-navigation-state.ts +10 -4
- package/src/lib/catch-all-target.spec.ts +218 -0
- package/src/lib/catch-all-target.ts +99 -0
- package/src/lib/workspace-apps.ts +9 -0
- package/src/routes/pages/$appId.tsx +21 -8
- package/src/routes/pages/integrations.tsx +57 -18
- package/src/routes/pages/new-app.tsx +1 -1
- package/src/routes/pages/overview.tsx +11 -3
- package/src/routes/pages/vault.tsx +76 -9
- package/src/server/lib/app-creation-store.spec.ts +61 -2
- package/src/server/lib/app-creation-store.ts +386 -11
- package/src/server/lib/env-config.ts +5 -0
- package/src/server/lib/onboarding-steps.ts +49 -0
- package/src/server/lib/vault-store.spec.ts +69 -0
- package/src/server/lib/vault-store.ts +266 -49
- package/src/server/plugins/agent-chat.ts +2 -1
- package/src/server/plugins/core-routes.ts +5 -0
- package/src/server/plugins/integrations.ts +2 -2
|
@@ -28,6 +28,11 @@ import {
|
|
|
28
28
|
} from "@/components/ui/dialog";
|
|
29
29
|
import { Input } from "@/components/ui/input";
|
|
30
30
|
import { Label } from "@/components/ui/label";
|
|
31
|
+
import {
|
|
32
|
+
Tooltip,
|
|
33
|
+
TooltipContent,
|
|
34
|
+
TooltipTrigger,
|
|
35
|
+
} from "@/components/ui/tooltip";
|
|
31
36
|
|
|
32
37
|
export function meta() {
|
|
33
38
|
return [{ title: "Connections — Dispatch" }];
|
|
@@ -90,10 +95,12 @@ function ConnectDialog({
|
|
|
90
95
|
service,
|
|
91
96
|
open,
|
|
92
97
|
onOpenChange,
|
|
98
|
+
accessMode,
|
|
93
99
|
}: {
|
|
94
100
|
service: Service;
|
|
95
101
|
open: boolean;
|
|
96
102
|
onOpenChange: (next: boolean) => void;
|
|
103
|
+
accessMode: "all-apps" | "manual";
|
|
97
104
|
}) {
|
|
98
105
|
const [value, setValue] = useState("");
|
|
99
106
|
const qc = useQueryClient();
|
|
@@ -128,16 +135,18 @@ function ConnectDialog({
|
|
|
128
135
|
throw new Error("Secret created but id missing");
|
|
129
136
|
}
|
|
130
137
|
|
|
131
|
-
// 2.
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
138
|
+
// 2. Manual mode needs grants; all-apps mode only needs sync.
|
|
139
|
+
if (accessMode === "manual") {
|
|
140
|
+
const targets = service.apps.filter((a) => !a.vaultGranted);
|
|
141
|
+
for (const app of targets) {
|
|
142
|
+
try {
|
|
143
|
+
await createGrant.mutateAsync({
|
|
144
|
+
secretId,
|
|
145
|
+
appId: app.appId,
|
|
146
|
+
});
|
|
147
|
+
} catch (err) {
|
|
148
|
+
console.warn(`grant to ${app.appId} failed`, err);
|
|
149
|
+
}
|
|
141
150
|
}
|
|
142
151
|
}
|
|
143
152
|
for (const app of service.apps) {
|
|
@@ -217,7 +226,13 @@ function ConnectDialog({
|
|
|
217
226
|
);
|
|
218
227
|
}
|
|
219
228
|
|
|
220
|
-
function ConnectorCard({
|
|
229
|
+
function ConnectorCard({
|
|
230
|
+
service,
|
|
231
|
+
accessMode,
|
|
232
|
+
}: {
|
|
233
|
+
service: Service;
|
|
234
|
+
accessMode: "all-apps" | "manual";
|
|
235
|
+
}) {
|
|
221
236
|
const [open, setOpen] = useState(false);
|
|
222
237
|
const isConnected = service.apps.some((a) => a.configured);
|
|
223
238
|
const appCount = service.apps.length;
|
|
@@ -251,10 +266,15 @@ function ConnectorCard({ service }: { service: Service }) {
|
|
|
251
266
|
</Badge>
|
|
252
267
|
)}
|
|
253
268
|
</div>
|
|
254
|
-
<div className="min-w-0">
|
|
255
|
-
<
|
|
256
|
-
|
|
257
|
-
|
|
269
|
+
<div className="w-full min-w-0">
|
|
270
|
+
<Tooltip>
|
|
271
|
+
<TooltipTrigger asChild>
|
|
272
|
+
<div className="text-sm font-semibold text-foreground truncate">
|
|
273
|
+
{service.label}
|
|
274
|
+
</div>
|
|
275
|
+
</TooltipTrigger>
|
|
276
|
+
<TooltipContent>{service.label}</TooltipContent>
|
|
277
|
+
</Tooltip>
|
|
258
278
|
<div className="font-mono text-xs text-muted-foreground/80 truncate">
|
|
259
279
|
{service.key}
|
|
260
280
|
</div>
|
|
@@ -263,7 +283,12 @@ function ConnectorCard({ service }: { service: Service }) {
|
|
|
263
283
|
Used by {appCount} {appCount === 1 ? "app" : "apps"}
|
|
264
284
|
</div>
|
|
265
285
|
</button>
|
|
266
|
-
<ConnectDialog
|
|
286
|
+
<ConnectDialog
|
|
287
|
+
service={service}
|
|
288
|
+
open={open}
|
|
289
|
+
onOpenChange={setOpen}
|
|
290
|
+
accessMode={accessMode}
|
|
291
|
+
/>
|
|
267
292
|
</>
|
|
268
293
|
);
|
|
269
294
|
}
|
|
@@ -297,7 +322,13 @@ export default function ConnectionsRoute() {
|
|
|
297
322
|
"list-integrations-catalog",
|
|
298
323
|
{},
|
|
299
324
|
);
|
|
325
|
+
const { data: accessSettings } = useActionQuery(
|
|
326
|
+
"get-vault-access-settings",
|
|
327
|
+
{},
|
|
328
|
+
);
|
|
300
329
|
const apps = (catalog as CatalogApp[]) || [];
|
|
330
|
+
const accessMode =
|
|
331
|
+
(accessSettings as any)?.mode === "manual" ? "manual" : "all-apps";
|
|
301
332
|
|
|
302
333
|
const services = useMemo<Service[]>(() => {
|
|
303
334
|
const map = new Map<string, Service>();
|
|
@@ -357,7 +388,11 @@ export default function ConnectionsRoute() {
|
|
|
357
388
|
</div>
|
|
358
389
|
<div className="grid gap-3 sm:grid-cols-2 xl:grid-cols-3">
|
|
359
390
|
{available.map((service) => (
|
|
360
|
-
<ConnectorCard
|
|
391
|
+
<ConnectorCard
|
|
392
|
+
key={service.key}
|
|
393
|
+
service={service}
|
|
394
|
+
accessMode={accessMode}
|
|
395
|
+
/>
|
|
361
396
|
))}
|
|
362
397
|
</div>
|
|
363
398
|
</section>
|
|
@@ -373,7 +408,11 @@ export default function ConnectionsRoute() {
|
|
|
373
408
|
</div>
|
|
374
409
|
<div className="grid gap-3 sm:grid-cols-2 xl:grid-cols-3">
|
|
375
410
|
{connected.map((service) => (
|
|
376
|
-
<ConnectorCard
|
|
411
|
+
<ConnectorCard
|
|
412
|
+
key={service.key}
|
|
413
|
+
service={service}
|
|
414
|
+
accessMode={accessMode}
|
|
415
|
+
/>
|
|
377
416
|
))}
|
|
378
417
|
</div>
|
|
379
418
|
</section>
|
|
@@ -9,7 +9,7 @@ export default function NewAppRoute() {
|
|
|
9
9
|
return (
|
|
10
10
|
<DispatchShell
|
|
11
11
|
title="New App"
|
|
12
|
-
description="Create a workspace app from a prompt and
|
|
12
|
+
description="Create a workspace app from a prompt and apply the workspace vault policy."
|
|
13
13
|
>
|
|
14
14
|
<NewWorkspaceAppFlow sourceApp="dispatch" className="px-0 py-0" />
|
|
15
15
|
</DispatchShell>
|
|
@@ -617,7 +617,7 @@ export default function OverviewRoute() {
|
|
|
617
617
|
<div className="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
|
|
618
618
|
<StatCard
|
|
619
619
|
label="Vault secrets"
|
|
620
|
-
help="Credentials stored in the workspace vault.
|
|
620
|
+
help="Credentials stored in the workspace vault."
|
|
621
621
|
value={data?.vault?.secretCount || 0}
|
|
622
622
|
icon={IconKey}
|
|
623
623
|
cta={
|
|
@@ -629,8 +629,16 @@ export default function OverviewRoute() {
|
|
|
629
629
|
}
|
|
630
630
|
/>
|
|
631
631
|
<StatCard
|
|
632
|
-
label=
|
|
633
|
-
|
|
632
|
+
label={
|
|
633
|
+
data?.vault?.accessMode === "manual"
|
|
634
|
+
? "Active grants"
|
|
635
|
+
: "Accessible keys"
|
|
636
|
+
}
|
|
637
|
+
help={
|
|
638
|
+
data?.vault?.accessMode === "manual"
|
|
639
|
+
? "Secrets currently granted to apps. Sync them to push credentials."
|
|
640
|
+
: "Vault keys available to every workspace app."
|
|
641
|
+
}
|
|
634
642
|
value={data?.vault?.activeGrantCount || 0}
|
|
635
643
|
icon={IconShieldCheck}
|
|
636
644
|
/>
|
|
@@ -37,6 +37,7 @@ import {
|
|
|
37
37
|
} from "@/components/ui/alert-dialog";
|
|
38
38
|
import { Input } from "@/components/ui/input";
|
|
39
39
|
import { Label } from "@/components/ui/label";
|
|
40
|
+
import { Switch } from "@/components/ui/switch";
|
|
40
41
|
import {
|
|
41
42
|
Select,
|
|
42
43
|
SelectContent,
|
|
@@ -61,6 +62,8 @@ const PROVIDERS = [
|
|
|
61
62
|
"other",
|
|
62
63
|
];
|
|
63
64
|
|
|
65
|
+
type VaultAccessMode = "all-apps" | "manual";
|
|
66
|
+
|
|
64
67
|
export function meta() {
|
|
65
68
|
return [{ title: "Vault — Dispatch" }];
|
|
66
69
|
}
|
|
@@ -241,7 +244,53 @@ function GrantDialog({
|
|
|
241
244
|
);
|
|
242
245
|
}
|
|
243
246
|
|
|
244
|
-
function
|
|
247
|
+
function VaultAccessSettingsCard({ mode }: { mode: VaultAccessMode }) {
|
|
248
|
+
const update = useActionMutation("set-vault-access-settings", {
|
|
249
|
+
onSuccess: (next: any) =>
|
|
250
|
+
toast.success(
|
|
251
|
+
next?.mode === "manual"
|
|
252
|
+
? "Manual vault access enabled"
|
|
253
|
+
: "All apps can use vault keys",
|
|
254
|
+
),
|
|
255
|
+
onError: (err) => toast.error(String(err)),
|
|
256
|
+
});
|
|
257
|
+
const allApps = mode !== "manual";
|
|
258
|
+
|
|
259
|
+
return (
|
|
260
|
+
<div className="rounded-xl border bg-card px-4 py-3">
|
|
261
|
+
<div className="flex items-center justify-between gap-4">
|
|
262
|
+
<div className="min-w-0">
|
|
263
|
+
<Label className="text-sm font-medium">
|
|
264
|
+
All apps can use vault keys
|
|
265
|
+
</Label>
|
|
266
|
+
<p className="mt-1 text-xs text-muted-foreground">
|
|
267
|
+
{allApps
|
|
268
|
+
? "Every workspace app can receive every saved key."
|
|
269
|
+
: "Only apps with explicit grants can receive saved keys."}
|
|
270
|
+
</p>
|
|
271
|
+
</div>
|
|
272
|
+
<Switch
|
|
273
|
+
checked={allApps}
|
|
274
|
+
disabled={update.isPending}
|
|
275
|
+
onCheckedChange={(checked) =>
|
|
276
|
+
update.mutate({ mode: checked ? "all-apps" : "manual" })
|
|
277
|
+
}
|
|
278
|
+
aria-label="Allow all workspace apps to use vault keys"
|
|
279
|
+
/>
|
|
280
|
+
</div>
|
|
281
|
+
</div>
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function SecretRow({
|
|
286
|
+
secret,
|
|
287
|
+
grants,
|
|
288
|
+
accessMode,
|
|
289
|
+
}: {
|
|
290
|
+
secret: any;
|
|
291
|
+
grants: any[];
|
|
292
|
+
accessMode: VaultAccessMode;
|
|
293
|
+
}) {
|
|
245
294
|
const [expanded, setExpanded] = useState(false);
|
|
246
295
|
const [showValue, setShowValue] = useState(false);
|
|
247
296
|
|
|
@@ -260,6 +309,7 @@ function SecretRow({ secret, grants }: { secret: any; grants: any[] }) {
|
|
|
260
309
|
});
|
|
261
310
|
|
|
262
311
|
const activeGrants = grants.filter((g) => g.status === "active");
|
|
312
|
+
const allApps = accessMode !== "manual";
|
|
263
313
|
|
|
264
314
|
return (
|
|
265
315
|
<div className="rounded-xl border bg-card">
|
|
@@ -290,7 +340,9 @@ function SecretRow({ secret, grants }: { secret: any; grants: any[] }) {
|
|
|
290
340
|
</div>
|
|
291
341
|
<div className="flex items-center gap-2">
|
|
292
342
|
<Badge variant="outline" className="text-xs">
|
|
293
|
-
{
|
|
343
|
+
{allApps
|
|
344
|
+
? "All apps"
|
|
345
|
+
: `${activeGrants.length} grant${activeGrants.length !== 1 ? "s" : ""}`}
|
|
294
346
|
</Badge>
|
|
295
347
|
</div>
|
|
296
348
|
</button>
|
|
@@ -320,11 +372,17 @@ function SecretRow({ secret, grants }: { secret: any; grants: any[] }) {
|
|
|
320
372
|
<div className="space-y-2">
|
|
321
373
|
<div className="flex items-center justify-between">
|
|
322
374
|
<span className="text-xs font-medium text-foreground">
|
|
323
|
-
Grants
|
|
375
|
+
{allApps ? "Access" : "Grants"}
|
|
324
376
|
</span>
|
|
325
|
-
|
|
377
|
+
{!allApps && (
|
|
378
|
+
<GrantDialog secretId={secret.id} secretName={secret.name} />
|
|
379
|
+
)}
|
|
326
380
|
</div>
|
|
327
|
-
{
|
|
381
|
+
{allApps ? (
|
|
382
|
+
<div className="rounded-lg border border-dashed px-3 py-4 text-center text-xs text-muted-foreground">
|
|
383
|
+
Available to every workspace app.
|
|
384
|
+
</div>
|
|
385
|
+
) : activeGrants.length > 0 ? (
|
|
328
386
|
<div className="space-y-1.5">
|
|
329
387
|
{activeGrants.map((grant: any) => (
|
|
330
388
|
<div
|
|
@@ -366,7 +424,7 @@ function SecretRow({ secret, grants }: { secret: any; grants: any[] }) {
|
|
|
366
424
|
</div>
|
|
367
425
|
) : (
|
|
368
426
|
<div className="rounded-lg border border-dashed px-3 py-4 text-center text-xs text-muted-foreground">
|
|
369
|
-
No grants yet.
|
|
427
|
+
No grants yet.
|
|
370
428
|
</div>
|
|
371
429
|
)}
|
|
372
430
|
</div>
|
|
@@ -388,8 +446,8 @@ function SecretRow({ secret, grants }: { secret: any; grants: any[] }) {
|
|
|
388
446
|
<AlertDialogTitle>Delete this secret?</AlertDialogTitle>
|
|
389
447
|
<AlertDialogDescription>
|
|
390
448
|
Removing “{secret.name}” revokes all of its grants. Apps
|
|
391
|
-
that depended on this credential
|
|
392
|
-
|
|
449
|
+
that depended on this credential can lose access on the next
|
|
450
|
+
sync. This cannot be undone.
|
|
393
451
|
</AlertDialogDescription>
|
|
394
452
|
</AlertDialogHeader>
|
|
395
453
|
<AlertDialogFooter>
|
|
@@ -508,6 +566,12 @@ export default function VaultRoute() {
|
|
|
508
566
|
const { data: grants } = useActionQuery("list-vault-grants", {});
|
|
509
567
|
const { data: requests } = useActionQuery("list-vault-requests", {});
|
|
510
568
|
const { data: audit } = useActionQuery("list-vault-audit", { limit: 20 });
|
|
569
|
+
const { data: accessSettings } = useActionQuery(
|
|
570
|
+
"get-vault-access-settings",
|
|
571
|
+
{},
|
|
572
|
+
);
|
|
573
|
+
const accessMode: VaultAccessMode =
|
|
574
|
+
(accessSettings as any)?.mode === "manual" ? "manual" : "all-apps";
|
|
511
575
|
|
|
512
576
|
const grantsBySecret = (grants || []).reduce(
|
|
513
577
|
(acc: Record<string, any[]>, g: any) => {
|
|
@@ -525,7 +589,7 @@ export default function VaultRoute() {
|
|
|
525
589
|
return (
|
|
526
590
|
<DispatchShell
|
|
527
591
|
title="Vault"
|
|
528
|
-
description="Centralized secret management for your workspace. Store credentials once
|
|
592
|
+
description="Centralized secret management for your workspace. Store credentials once and sync them to apps."
|
|
529
593
|
>
|
|
530
594
|
<Tabs defaultValue="secrets">
|
|
531
595
|
<TabsList>
|
|
@@ -547,6 +611,8 @@ export default function VaultRoute() {
|
|
|
547
611
|
</TabsList>
|
|
548
612
|
|
|
549
613
|
<TabsContent value="secrets" className="mt-4 space-y-3">
|
|
614
|
+
<VaultAccessSettingsCard mode={accessMode} />
|
|
615
|
+
|
|
550
616
|
<div className="flex items-center justify-between">
|
|
551
617
|
<div className="flex items-center gap-2 text-sm text-muted-foreground">
|
|
552
618
|
<IconKey size={16} />
|
|
@@ -576,6 +642,7 @@ export default function VaultRoute() {
|
|
|
576
642
|
key={secret.id}
|
|
577
643
|
secret={secret}
|
|
578
644
|
grants={grantsBySecret[secret.id] || []}
|
|
645
|
+
accessMode={accessMode}
|
|
579
646
|
/>
|
|
580
647
|
))}
|
|
581
648
|
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
2
2
|
import { runWithRequestContext } from "@agent-native/core/server";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
generateWorkspaceAppDescription,
|
|
5
|
+
listWorkspaceApps,
|
|
6
|
+
} from "./app-creation-store.js";
|
|
4
7
|
|
|
5
8
|
const originalFetch = globalThis.fetch;
|
|
6
9
|
|
|
@@ -21,7 +24,15 @@ describe("listWorkspaceApps", () => {
|
|
|
21
24
|
name: "Agent-Native Dispatch",
|
|
22
25
|
path: "/dispatch",
|
|
23
26
|
},
|
|
24
|
-
{
|
|
27
|
+
{
|
|
28
|
+
id: "todo",
|
|
29
|
+
name: "Todo",
|
|
30
|
+
description: "Tracks personal tasks and follow-ups",
|
|
31
|
+
path: "/todo",
|
|
32
|
+
audience: "public",
|
|
33
|
+
publicPaths: ["/"],
|
|
34
|
+
protectedPaths: ["/admin"],
|
|
35
|
+
},
|
|
25
36
|
],
|
|
26
37
|
}),
|
|
27
38
|
{ headers: { "content-type": "application/json" } },
|
|
@@ -47,5 +58,53 @@ describe("listWorkspaceApps", () => {
|
|
|
47
58
|
}),
|
|
48
59
|
);
|
|
49
60
|
expect(apps.map((app) => app.id)).toEqual(["dispatch", "todo"]);
|
|
61
|
+
expect(apps.find((app) => app.id === "todo")?.description).toBe(
|
|
62
|
+
"Tracks personal tasks and follow-ups",
|
|
63
|
+
);
|
|
64
|
+
expect(apps.find((app) => app.id === "todo")?.audience).toBe("public");
|
|
65
|
+
expect(apps.find((app) => app.id === "todo")?.publicPaths).toEqual(["/"]);
|
|
66
|
+
expect(apps.find((app) => app.id === "todo")?.protectedPaths).toEqual([
|
|
67
|
+
"/admin",
|
|
68
|
+
]);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("filters workspace apps by audience", async () => {
|
|
72
|
+
vi.stubEnv(
|
|
73
|
+
"AGENT_NATIVE_WORKSPACE_APPS_JSON",
|
|
74
|
+
JSON.stringify([
|
|
75
|
+
{
|
|
76
|
+
id: "dispatch",
|
|
77
|
+
name: "Dispatch",
|
|
78
|
+
path: "/dispatch",
|
|
79
|
+
audience: "internal",
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
id: "portal",
|
|
83
|
+
name: "Portal",
|
|
84
|
+
path: "/portal",
|
|
85
|
+
audience: "public",
|
|
86
|
+
},
|
|
87
|
+
]),
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
const apps = await runWithRequestContext(
|
|
91
|
+
{ userEmail: "dev@example.test" },
|
|
92
|
+
() =>
|
|
93
|
+
listWorkspaceApps({
|
|
94
|
+
includeAgentCards: false,
|
|
95
|
+
audience: "public",
|
|
96
|
+
}),
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
expect(apps.map((app) => app.id)).toEqual(["portal"]);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it("generates a concise seed description from an app prompt", () => {
|
|
103
|
+
expect(
|
|
104
|
+
generateWorkspaceAppDescription(
|
|
105
|
+
"Build me an app that tracks customer onboarding risks and handoffs",
|
|
106
|
+
"customer-onboarding",
|
|
107
|
+
),
|
|
108
|
+
).toBe("Tracks customer onboarding risks and handoffs.");
|
|
50
109
|
});
|
|
51
110
|
});
|