@agent-native/dispatch 0.0.0-beta-20260819184657 → 0.0.0-beta-20260820150521

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.
@@ -1 +1 @@
1
- {"version":3,"file":"app-creation-store.d.ts","sourceRoot":"","sources":["../../../src/server/lib/app-creation-store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"app-creation-store.d.ts","sourceRoot":"","sources":["../../../src/server/lib/app-creation-store.ts"],"names":[],"mappings":"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"}
@@ -7,7 +7,7 @@ import { getDbExec } from "@agent-native/core/db";
7
7
  import { getOrgA2ASecret, getOrgDomain } from "@agent-native/core/org";
8
8
  import { ensureBuilderProject, getBuilderBranchProjectId, getRequestContext, isIntegrationCallerRequest, resolveBuilderCredentialsDetailed, runBuilderAgent, } from "@agent-native/core/server";
9
9
  import { getOrgSetting } from "@agent-native/core/settings";
10
- import { getSetting, putSetting } from "@agent-native/core/settings";
10
+ import { getSetting, mutateSetting, putSetting, } from "@agent-native/core/settings";
11
11
  import { assertValidWorkspaceAppId } from "@agent-native/core/shared";
12
12
  import { resolveAccess } from "@agent-native/core/sharing";
13
13
  // Register the workspace-app shareable resource before any access lookup.
@@ -552,6 +552,9 @@ function parsePendingWorkspaceApps(value) {
552
552
  ...(record.audience === undefined
553
553
  ? {}
554
554
  : { audience: normalizeWorkspaceAppAudience(record.audience) }),
555
+ ...(record.visibility === "private" || record.visibility === "org"
556
+ ? { visibility: record.visibility }
557
+ : {}),
555
558
  createdAt,
556
559
  updatedAt: typeof record.updatedAt === "string" && record.updatedAt.trim()
557
560
  ? record.updatedAt.trim()
@@ -567,6 +570,97 @@ async function listPendingWorkspaceApps() {
567
570
  const raw = await readSettingsRecord();
568
571
  return parsePendingWorkspaceApps(raw.pendingApps);
569
572
  }
573
+ async function assertPendingWorkspaceAppCreationAvailable(appId) {
574
+ const existing = (await listPendingWorkspaceApps())
575
+ .filter((app) => !isPendingWorkspaceAppExpired(app))
576
+ .find((app) => app.id === appId);
577
+ if (!existing)
578
+ return;
579
+ const viewerEmail = currentOwnerEmail().trim().toLowerCase();
580
+ const ownerEmail = (existing.createdBy ?? existing.owner)
581
+ ?.trim()
582
+ .toLowerCase();
583
+ if (ownerEmail && ownerEmail !== viewerEmail) {
584
+ throw new Error(`Workspace app "${appId}" is already being created by another member.`);
585
+ }
586
+ }
587
+ async function assertWorkspaceAppIdRegisteredFree(appId) {
588
+ let existing;
589
+ try {
590
+ const result = await getDbExec().execute({
591
+ sql: "SELECT id FROM workspace_apps WHERE id = ? LIMIT 1",
592
+ args: [appId],
593
+ });
594
+ existing = result.rows;
595
+ }
596
+ catch {
597
+ throw new Error("Could not verify the workspace app registry; refusing to reuse an app id.");
598
+ }
599
+ if (existing.length > 0) {
600
+ throw new Error(`Workspace app "${appId}" is already registered.`);
601
+ }
602
+ }
603
+ async function reservePendingWorkspaceApp(input) {
604
+ await assertWorkspaceAppIdRegisteredFree(input.appId);
605
+ const now = new Date().toISOString();
606
+ const context = pendingWorkspaceAppContext();
607
+ const creatorEmail = currentOwnerEmail();
608
+ await mutateSetting(scopedSettingsKey(), async (current) => {
609
+ const raw = current && typeof current === "object" && !Array.isArray(current)
610
+ ? current
611
+ : {};
612
+ const pendingApps = parsePendingWorkspaceApps(raw.pendingApps);
613
+ const existing = pendingApps
614
+ .filter((app) => !isPendingWorkspaceAppExpired(app))
615
+ .find((app) => app.id === input.appId);
616
+ if (existing) {
617
+ throw new Error(`Workspace app "${input.appId}" is already being created${existing.createdBy || existing.owner
618
+ ? ` by ${existing.createdBy ?? existing.owner}`
619
+ : ""}.`);
620
+ }
621
+ const reservation = {
622
+ id: input.appId,
623
+ name: titleCase(input.appId),
624
+ description: input.description ||
625
+ "Builder is creating this app. The workspace path becomes live after the branch is merged and deployed.",
626
+ path: `/${input.appId}`,
627
+ builderUrl: null,
628
+ branchName: null,
629
+ projectId: input.projectId,
630
+ contextId: context?.id ?? null,
631
+ contextLabel: context?.label ?? null,
632
+ visibility: input.visibility,
633
+ createdBy: creatorEmail,
634
+ owner: creatorEmail,
635
+ createdAt: now,
636
+ updatedAt: now,
637
+ expiresAt: pendingWorkspaceAppExpiresAt(now),
638
+ };
639
+ return {
640
+ ...raw,
641
+ pendingApps: [reservation, ...pendingApps].slice(0, MAX_PENDING_APPS),
642
+ };
643
+ });
644
+ }
645
+ async function releasePendingWorkspaceAppReservation(appId) {
646
+ const contextId = pendingWorkspaceAppContext()?.id ?? null;
647
+ const creatorEmail = currentOwnerEmail().trim().toLowerCase();
648
+ await mutateSetting(scopedSettingsKey(), async (current) => {
649
+ const raw = current && typeof current === "object" && !Array.isArray(current)
650
+ ? current
651
+ : {};
652
+ const pendingApps = parsePendingWorkspaceApps(raw.pendingApps);
653
+ return {
654
+ ...raw,
655
+ pendingApps: pendingApps.filter((app) => {
656
+ if (app.id !== appId || app.contextId !== contextId)
657
+ return true;
658
+ const owner = (app.createdBy ?? app.owner)?.trim().toLowerCase();
659
+ return owner !== creatorEmail;
660
+ }),
661
+ };
662
+ });
663
+ }
570
664
  function parseArchivedAppIds(value) {
571
665
  if (!Array.isArray(value))
572
666
  return [];
@@ -643,6 +737,7 @@ function pendingAppToSummary(app) {
643
737
  protectedPaths: [],
644
738
  status: "pending",
645
739
  statusLabel: "Pending Builder branch",
740
+ visibility: app.visibility,
646
741
  builderUrl: app.builderUrl,
647
742
  branchName: app.branchName,
648
743
  createdAt: app.createdAt,
@@ -776,7 +871,6 @@ async function ensureWorkspaceAppRecords(apps) {
776
871
  return apps;
777
872
  const orgId = currentOrgId();
778
873
  const metadata = await readWorkspaceAppMetadataSettings();
779
- const defaultVisibility = await workspaceAppDefaultVisibility();
780
874
  const db = getDbExec();
781
875
  const records = new Map();
782
876
  try {
@@ -806,13 +900,12 @@ async function ensureWorkspaceAppRecords(apps) {
806
900
  const ownerEmail = cleanOptionalText(override?.createdBy) ??
807
901
  cleanOptionalText(app.createdBy) ??
808
902
  "";
809
- const hasTrustedCreationMetadata = Boolean(ownerEmail);
810
903
  const visibility = override?.visibility === "private"
811
904
  ? "private"
812
905
  : override?.visibility === "org"
813
906
  ? "org"
814
- : hasTrustedCreationMetadata
815
- ? defaultVisibility
907
+ : app.visibility === "private"
908
+ ? "private"
816
909
  : "org";
817
910
  const createdAt = appRecordTimestamp(app.createdAt);
818
911
  await db.execute({
@@ -870,7 +963,18 @@ async function filterWorkspaceAppsByAccess(apps) {
870
963
  const visibleIds = new Set();
871
964
  const candidates = [];
872
965
  for (const app of apps) {
873
- if (app.status === "pending" || app.isDispatch) {
966
+ if (app.status === "pending") {
967
+ const viewerEmail = userEmail.toLowerCase();
968
+ const creatorEmail = app.createdBy?.trim().toLowerCase();
969
+ const ownerEmail = app.owner?.trim().toLowerCase();
970
+ if (app.visibility !== "private" ||
971
+ creatorEmail === viewerEmail ||
972
+ ownerEmail === viewerEmail) {
973
+ visibleIds.add(app.id);
974
+ }
975
+ continue;
976
+ }
977
+ if (app.isDispatch) {
874
978
  visibleIds.add(app.id);
875
979
  continue;
876
980
  }
@@ -910,6 +1014,12 @@ async function recordPendingWorkspaceApp(input) {
910
1014
  const existing = pendingApps
911
1015
  .filter((app) => !isPendingWorkspaceAppExpired(app))
912
1016
  .find(samePendingEntry);
1017
+ const creatorEmail = currentOwnerEmail();
1018
+ const existingOwnerEmail = existing?.createdBy ?? existing?.owner;
1019
+ if (existingOwnerEmail &&
1020
+ existingOwnerEmail.trim().toLowerCase() !== creatorEmail.toLowerCase()) {
1021
+ throw new Error(`Workspace app "${input.appId}" is already being created by another member.`);
1022
+ }
913
1023
  const next = {
914
1024
  id: input.appId,
915
1025
  name: titleCase(input.appId),
@@ -921,8 +1031,9 @@ async function recordPendingWorkspaceApp(input) {
921
1031
  projectId: input.projectId,
922
1032
  contextId: context?.id ?? null,
923
1033
  contextLabel: context?.label ?? null,
924
- createdBy: currentOwnerEmail(),
925
- owner: currentOwnerEmail(),
1034
+ visibility: input.visibility,
1035
+ createdBy: existing?.createdBy ?? existing?.owner ?? creatorEmail,
1036
+ owner: existing?.owner ?? existing?.createdBy ?? creatorEmail,
926
1037
  createdAt: existing?.createdAt || now,
927
1038
  updatedAt: now,
928
1039
  expiresAt: pendingWorkspaceAppExpiresAt(existing?.createdAt || now),
@@ -939,8 +1050,9 @@ async function recordPendingWorkspaceApp(input) {
939
1050
  description: input.description,
940
1051
  generated: true,
941
1052
  sourcePrompt: input.sourcePrompt,
942
- updatedBy: currentOwnerEmail(),
943
- createdBy: currentOwnerEmail(),
1053
+ updatedBy: creatorEmail,
1054
+ createdBy: next.createdBy,
1055
+ visibility: input.visibility,
944
1056
  });
945
1057
  await recordAudit({
946
1058
  action: "workspace-app.pending",
@@ -1420,6 +1532,8 @@ export async function scaffoldWorkspaceAppFromTemplate(input) {
1420
1532
  }
1421
1533
  const appId = (input.appId?.trim() || template).toLowerCase();
1422
1534
  assertValidWorkspaceAppId(appId);
1535
+ await assertPendingWorkspaceAppCreationAvailable(appId);
1536
+ await assertWorkspaceAppIdRegisteredFree(appId);
1423
1537
  const workspaceRoot = findWorkspaceRoot();
1424
1538
  if (!workspaceRoot) {
1425
1539
  throw new Error("No agent-native workspace detected for scaffolding.");
@@ -1428,10 +1542,35 @@ export async function scaffoldWorkspaceAppFromTemplate(input) {
1428
1542
  if (fs.existsSync(appDir)) {
1429
1543
  throw new Error(`apps/${appId} already exists.`);
1430
1544
  }
1431
- const output = await runScaffoldCli({
1432
- cwd: workspaceRoot,
1433
- args: ["add-app", appId, "--template", template],
1434
- });
1545
+ const visibility = await workspaceAppDefaultVisibility();
1546
+ const creatorEmail = currentOwnerEmail();
1547
+ let output;
1548
+ try {
1549
+ output = await runScaffoldCli({
1550
+ cwd: workspaceRoot,
1551
+ args: ["add-app", appId, "--template", template],
1552
+ });
1553
+ }
1554
+ catch (error) {
1555
+ if (fs.existsSync(appDir)) {
1556
+ fs.rmSync(appDir, { recursive: true, force: true });
1557
+ }
1558
+ throw error;
1559
+ }
1560
+ try {
1561
+ await writeWorkspaceAppMetadataOverride({
1562
+ appId,
1563
+ updatedBy: creatorEmail,
1564
+ createdBy: creatorEmail,
1565
+ visibility,
1566
+ });
1567
+ }
1568
+ catch (error) {
1569
+ if (fs.existsSync(appDir)) {
1570
+ fs.rmSync(appDir, { recursive: true, force: true });
1571
+ }
1572
+ throw error;
1573
+ }
1435
1574
  await recordAudit({
1436
1575
  action: "workspace-app.scaffolded",
1437
1576
  targetType: "workspace-app",
@@ -1452,6 +1591,7 @@ export async function scaffoldWorkspaceAppFromTemplate(input) {
1452
1591
  protectedPaths: [],
1453
1592
  status: "ready",
1454
1593
  createdBy: currentOwnerEmail(),
1594
+ visibility,
1455
1595
  },
1456
1596
  ]);
1457
1597
  return { appId, template, output };
@@ -1826,6 +1966,8 @@ export async function startWorkspaceAppCreation(input) {
1826
1966
  };
1827
1967
  }
1828
1968
  }
1969
+ const creationVisibility = await workspaceAppDefaultVisibility();
1970
+ await assertPendingWorkspaceAppCreationAvailable(initial.appId);
1829
1971
  const selectedKeys = input.secretIds?.length
1830
1972
  ? (await listSecretOptions())
1831
1973
  .filter((secret) => input.secretIds?.includes(secret.id))
@@ -1844,6 +1986,15 @@ export async function startWorkspaceAppCreation(input) {
1844
1986
  const appDescription = input.description?.trim() ||
1845
1987
  generateWorkspaceAppDescription(input.prompt, built.appId);
1846
1988
  if (isLocal) {
1989
+ await writeWorkspaceAppMetadataOverride({
1990
+ appId: built.appId,
1991
+ description: appDescription,
1992
+ generated: true,
1993
+ sourcePrompt: input.prompt,
1994
+ updatedBy: currentOwnerEmail(),
1995
+ createdBy: currentOwnerEmail(),
1996
+ visibility: creationVisibility,
1997
+ });
1847
1998
  await requestSelectedVaultKeys({
1848
1999
  appId: built.appId,
1849
2000
  selectedKeys,
@@ -1920,6 +2071,12 @@ export async function startWorkspaceAppCreation(input) {
1920
2071
  }
1921
2072
  }
1922
2073
  const builderUserId = builderCreds.userId || undefined;
2074
+ await reservePendingWorkspaceApp({
2075
+ appId: built.appId,
2076
+ description: appDescription,
2077
+ projectId: builderProjectId,
2078
+ visibility: creationVisibility,
2079
+ });
1923
2080
  let result;
1924
2081
  try {
1925
2082
  result = normalizeBuilderRunResult(await runBuilderAgent({
@@ -1931,6 +2088,12 @@ export async function startWorkspaceAppCreation(input) {
1931
2088
  }));
1932
2089
  }
1933
2090
  catch (err) {
2091
+ try {
2092
+ await releasePendingWorkspaceAppReservation(built.appId);
2093
+ }
2094
+ catch (cleanupError) {
2095
+ console.warn("[dispatch] failed to release pending workspace app reservation", cleanupError);
2096
+ }
1934
2097
  const detail = err instanceof Error && err.message
1935
2098
  ? err.message
1936
2099
  : "Builder could not start the app branch";
@@ -1948,6 +2111,7 @@ export async function startWorkspaceAppCreation(input) {
1948
2111
  projectId: builderProjectId,
1949
2112
  description: appDescription,
1950
2113
  sourcePrompt: input.prompt,
2114
+ visibility: creationVisibility,
1951
2115
  branchName: result.branchName,
1952
2116
  builderUrl: result.url,
1953
2117
  });