@agent-native/dispatch 0.42.0-nightly-20261104194955 → 0.42.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/dispatch",
3
- "version": "0.42.0-nightly-20261104194955",
3
+ "version": "0.42.0",
4
4
  "description": "Dispatch — workspace control plane for agent-native apps. Vault, integrations, destinations, scheduled jobs, and cross-app delegation, shipped as a single drop-in package.",
5
5
  "homepage": "https://github.com/BuilderIO/agent-native#readme",
6
6
  "bugs": {
@@ -90,7 +90,7 @@
90
90
  "tailwind-merge": "^3.5.0",
91
91
  "vaul": "^1.1.2",
92
92
  "zod": "^4.3.6",
93
- "@agent-native/toolkit": "0.224.0-nightly-20261104194955"
93
+ "@agent-native/toolkit": "0.224.0"
94
94
  },
95
95
  "devDependencies": {
96
96
  "@react-router/dev": "^8.1.0",
@@ -104,10 +104,10 @@
104
104
  "typescript-7": "npm:typescript@^7.0.2",
105
105
  "vite": "8.1.0",
106
106
  "vitest": "^4.1.5",
107
- "@agent-native/core": "0.224.0-nightly-20261104194955"
107
+ "@agent-native/core": "0.224.0"
108
108
  },
109
109
  "peerDependencies": {
110
- "@agent-native/core": "0.224.0-nightly-20261104194955",
110
+ "@agent-native/core": ">=0.224.0-0",
111
111
  "react": ">=19.2.7",
112
112
  "react-dom": ">=19.2.7",
113
113
  "react-router": ">=8"
@@ -62,6 +62,15 @@ describe("Dispatch workspace app share access", () => {
62
62
  ).resolves.toBe(false);
63
63
  });
64
64
 
65
+ it("shares one manager answer across a request org's apps", () => {
66
+ const key = mocks.getRegisteredResource().canManageAccessKey as (resource: {
67
+ orgId?: string | null;
68
+ }) => string | undefined;
69
+
70
+ expect(key({ orgId: "org-a" })).toBe("org-a");
71
+ expect(key({ orgId: null })).toBeUndefined();
72
+ });
73
+
65
74
  it("does not resolve a role for a resource outside the request org", async () => {
66
75
  await expect(
67
76
  canManageAccess()(
package/src/db/index.ts CHANGED
@@ -21,6 +21,7 @@ registerShareableResource({
21
21
  allowPublic: false,
22
22
  requireOrgMemberForUserShares: true,
23
23
  supportsGroupShares: true,
24
+ canManageAccessKey: (resource) => resource.orgId ?? undefined,
24
25
  canManageAccess: async (resource, ctx) => {
25
26
  if (!ctx.userEmail || !ctx.orgId || resource?.orgId !== ctx.orgId) {
26
27
  return false;
@@ -209,6 +209,20 @@ vi.mock("@agent-native/core/sharing", async (importOriginal) => {
209
209
  return {
210
210
  ...actual,
211
211
  resolveAccess: (...args: any[]) => mocks.resolveAccess(...args),
212
+ // core's own tests prove resolveAccessMany agrees with resolveAccess, so
213
+ // this double answers through the same per-app mock the cases configure.
214
+ resolveAccessMany: async (
215
+ resourceType: string,
216
+ resourceIds: string[],
217
+ ...rest: any[]
218
+ ) => {
219
+ const access = new Map<string, unknown>();
220
+ for (const id of resourceIds) {
221
+ const resolved = await mocks.resolveAccess(resourceType, id, ...rest);
222
+ if (resolved) access.set(id, resolved);
223
+ }
224
+ return access;
225
+ },
212
226
  };
213
227
  });
214
228
 
@@ -56,7 +56,7 @@ import {
56
56
  parseAgentProfileMetadata,
57
57
  type ConnectRequiredCard,
58
58
  } from "@agent-native/core/shared";
59
- import { resolveAccess } from "@agent-native/core/sharing";
59
+ import { resolveAccessMany } from "@agent-native/core/sharing";
60
60
 
61
61
  import { getDb } from "../../db/index.js";
62
62
  import { workspaceAppRoute } from "../../shared/workspace-app-route.js";
@@ -96,7 +96,6 @@ const WORKSPACE_APPS_ENV_KEY = "AGENT_NATIVE_WORKSPACE_APPS_JSON";
96
96
  const WORKSPACE_APPS_MANIFEST_FILE = "workspace-apps.json";
97
97
  const WORKSPACE_APPS_GATEWAY_PATH = "/_workspace/apps";
98
98
  const WORKSPACE_APPS_GATEWAY_TIMEOUT_MS = 2_500;
99
- const WORKSPACE_APP_ACCESS_CONCURRENCY = 8;
100
99
  const MAX_PENDING_APPS = 50;
101
100
  const PENDING_WORKSPACE_APP_TTL_MS = 30 * 24 * 60 * 60 * 1_000;
102
101
  const AGENT_CARD_PATH = "/.well-known/agent-card.json";
@@ -1890,33 +1889,17 @@ async function filterWorkspaceAppsByAccess(
1890
1889
  candidates.push(app);
1891
1890
  }
1892
1891
 
1893
- for (
1894
- let start = 0;
1895
- start < candidates.length;
1896
- start += WORKSPACE_APP_ACCESS_CONCURRENCY
1897
- ) {
1898
- const batch = candidates.slice(
1899
- start,
1900
- start + WORKSPACE_APP_ACCESS_CONCURRENCY,
1901
- );
1902
- const decisions = await Promise.all(
1903
- batch.map(async (app) => {
1904
- try {
1905
- const access = await resolveAccess(
1906
- "workspace-app",
1907
- app.id,
1908
- { userEmail, orgId },
1909
- { skipResourceBody: true },
1910
- );
1911
- return { app, allowed: Boolean(access) };
1912
- } catch (error) {
1913
- console.warn("[dispatch] workspace app access lookup failed", error);
1914
- return { app, allowed: false };
1915
- }
1916
- }),
1917
- );
1918
- for (const decision of decisions) {
1919
- if (decision.allowed) visibleIds.add(decision.app.id);
1892
+ if (candidates.length > 0) {
1893
+ try {
1894
+ const access = await resolveAccessMany(
1895
+ "workspace-app",
1896
+ candidates.map((app) => app.id),
1897
+ { userEmail, ...(orgId ? { orgId } : {}) },
1898
+ { skipResourceBody: true },
1899
+ );
1900
+ for (const id of access.keys()) visibleIds.add(id);
1901
+ } catch (error) {
1902
+ console.warn("[dispatch] workspace app access lookup failed", error);
1920
1903
  }
1921
1904
  }
1922
1905