@agent-native/dispatch 0.40.43-nightly-20261029063606 → 0.40.43
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/CHANGELOG.md +6 -9
- package/dist/actions/provider-api-register.d.ts +7 -7
- package/dist/server/lib/community-install-verification.d.ts.map +1 -1
- package/dist/server/lib/community-install-verification.js +36 -4
- package/dist/server/lib/community-install-verification.js.map +1 -1
- package/package.json +4 -4
- package/src/server/lib/community-install-verification.spec.ts +22 -2
- package/src/server/lib/community-install-verification.ts +40 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
# @agent-native/dispatch
|
|
2
2
|
|
|
3
|
-
## 0.40.43
|
|
3
|
+
## 0.40.43
|
|
4
4
|
|
|
5
5
|
### Patch Changes
|
|
6
6
|
|
|
7
|
+
- Release all public npm packages with a patch version bump.
|
|
8
|
+
- 25daf38: Expose bounded stage codes when Builder branch readback cannot be verified.
|
|
7
9
|
- Updated dependencies [86af196]
|
|
8
|
-
|
|
9
|
-
|
|
10
|
+
- Updated dependencies [c96a41d]
|
|
11
|
+
- Updated dependencies
|
|
12
|
+
- @agent-native/toolkit@0.222.1
|
|
10
13
|
|
|
11
14
|
## 0.40.42
|
|
12
15
|
|
|
@@ -1432,10 +1435,4 @@
|
|
|
1432
1435
|
|
|
1433
1436
|
- 5f4031b: Restore ownerless legacy app visibility while preserving explicit private defaults for new apps.
|
|
1434
1437
|
|
|
1435
|
-
## 0.31.0
|
|
1436
|
-
|
|
1437
|
-
### Minor Changes
|
|
1438
|
-
|
|
1439
|
-
- 8690e40: Make automation details inspectable in Dispatch, including the prompt, trigger configuration, capabilities, and past runs.
|
|
1440
|
-
|
|
1441
1438
|
For the full list of releases, see the [changelog archive](./changelog/archive/CHANGELOG.md).
|
|
@@ -48,9 +48,9 @@ declare const _default: import("node_modules/@agent-native/core/dist").ActionDef
|
|
|
48
48
|
scope?: "org" | "user" | undefined;
|
|
49
49
|
}, {
|
|
50
50
|
id?: undefined;
|
|
51
|
+
provider?: undefined;
|
|
51
52
|
deleted?: undefined;
|
|
52
53
|
message?: undefined;
|
|
53
|
-
found?: undefined;
|
|
54
54
|
providers: {
|
|
55
55
|
id: string;
|
|
56
56
|
label: string;
|
|
@@ -61,7 +61,7 @@ declare const _default: import("node_modules/@agent-native/core/dist").ActionDef
|
|
|
61
61
|
updatedAt: number;
|
|
62
62
|
}[];
|
|
63
63
|
count: number;
|
|
64
|
-
|
|
64
|
+
found?: undefined;
|
|
65
65
|
registered?: undefined;
|
|
66
66
|
label?: undefined;
|
|
67
67
|
} | {
|
|
@@ -75,31 +75,31 @@ declare const _default: import("node_modules/@agent-native/core/dist").ActionDef
|
|
|
75
75
|
registered?: undefined;
|
|
76
76
|
label?: undefined;
|
|
77
77
|
} | {
|
|
78
|
+
provider?: undefined;
|
|
78
79
|
count?: undefined;
|
|
79
80
|
deleted?: undefined;
|
|
80
81
|
message?: undefined;
|
|
81
82
|
providers?: undefined;
|
|
82
|
-
provider?: undefined;
|
|
83
83
|
found: boolean;
|
|
84
84
|
id: string;
|
|
85
85
|
registered?: undefined;
|
|
86
86
|
label?: undefined;
|
|
87
87
|
} | {
|
|
88
|
+
provider?: undefined;
|
|
88
89
|
count?: undefined;
|
|
89
90
|
message?: undefined;
|
|
90
|
-
found?: undefined;
|
|
91
91
|
providers?: undefined;
|
|
92
|
-
|
|
92
|
+
found?: undefined;
|
|
93
93
|
deleted: boolean;
|
|
94
94
|
id: string;
|
|
95
95
|
registered?: undefined;
|
|
96
96
|
label?: undefined;
|
|
97
97
|
} | {
|
|
98
|
+
provider?: undefined;
|
|
98
99
|
count?: undefined;
|
|
99
100
|
deleted?: undefined;
|
|
100
|
-
found?: undefined;
|
|
101
101
|
providers?: undefined;
|
|
102
|
-
|
|
102
|
+
found?: undefined;
|
|
103
103
|
registered: boolean;
|
|
104
104
|
id: string;
|
|
105
105
|
label: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"community-install-verification.d.ts","sourceRoot":"","sources":["../../../src/server/lib/community-install-verification.ts"],"names":[],"mappings":"AAyBA,eAAO,MAAM,kCAAkC,itBAgB9C,CAAC;
|
|
1
|
+
{"version":3,"file":"community-install-verification.d.ts","sourceRoot":"","sources":["../../../src/server/lib/community-install-verification.ts"],"names":[],"mappings":"AAyBA,eAAO,MAAM,kCAAkC,itBAgB9C,CAAC;AAkMF,wBAAsB,yBAAyB,CAAC,KAAK,EAAE;IACrD,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB,wFA8FA"}
|
|
@@ -11,6 +11,35 @@ export const communityInstallVerificationErrors = defineActionErrors("community_
|
|
|
11
11
|
function verificationFail(message, code, options) {
|
|
12
12
|
return communityInstallVerificationErrors.fail(message, code, options);
|
|
13
13
|
}
|
|
14
|
+
const READBACK_STAGES = new Set([
|
|
15
|
+
"status_request",
|
|
16
|
+
"status_shape",
|
|
17
|
+
"status_binding",
|
|
18
|
+
"status_currentness",
|
|
19
|
+
"post_read_status_request",
|
|
20
|
+
"post_read_status_shape",
|
|
21
|
+
"post_read_status_binding",
|
|
22
|
+
"post_read_status_currentness",
|
|
23
|
+
"download_url_request",
|
|
24
|
+
"download_url_shape",
|
|
25
|
+
"download_url_binding",
|
|
26
|
+
"bundle_download",
|
|
27
|
+
"bundle_read",
|
|
28
|
+
"bundle_digest",
|
|
29
|
+
"bundle_parse",
|
|
30
|
+
"target_subtree_missing",
|
|
31
|
+
"post_read_currentness",
|
|
32
|
+
"app_integrity",
|
|
33
|
+
"snapshot_ref",
|
|
34
|
+
]);
|
|
35
|
+
function readbackStage(error) {
|
|
36
|
+
const stage = error && typeof error === "object"
|
|
37
|
+
? error.readbackStage
|
|
38
|
+
: undefined;
|
|
39
|
+
return typeof stage === "string" && READBACK_STAGES.has(stage)
|
|
40
|
+
? stage
|
|
41
|
+
: "unknown";
|
|
42
|
+
}
|
|
14
43
|
function requireHumanOrgOwner() {
|
|
15
44
|
const context = getRequestContext();
|
|
16
45
|
const orgId = currentOrgId();
|
|
@@ -87,13 +116,16 @@ function failBranchReadback(error) {
|
|
|
87
116
|
verificationFail("Builder project read access is missing or does not include this project.", "community_verification_readback_forbidden", { statusCode: error.code === "forbidden" ? 403 : 409 });
|
|
88
117
|
}
|
|
89
118
|
if (error.code === "unverified" || error.code === "integrity_failed") {
|
|
90
|
-
verificationFail("Builder could not provide a complete, identity-bound branch snapshot.", "community_verification_readback_unverified", { statusCode: 422 });
|
|
119
|
+
verificationFail("Builder could not provide a complete, identity-bound branch snapshot.", "community_verification_readback_unverified", { statusCode: 422, details: { readbackStage: readbackStage(error) } });
|
|
91
120
|
}
|
|
92
121
|
if (error.code === "invalid_request") {
|
|
93
122
|
verificationFail("Builder rejected the requested branch reference.", "community_verification_branch_invalid", { statusCode: 400 });
|
|
94
123
|
}
|
|
95
124
|
}
|
|
96
|
-
verificationFail("Builder branch readback is unavailable. Try again later.", "community_verification_readback_unavailable", {
|
|
125
|
+
verificationFail("Builder branch readback is unavailable. Try again later.", "community_verification_readback_unavailable", {
|
|
126
|
+
statusCode: 503,
|
|
127
|
+
details: { readbackStage: readbackStage(error) },
|
|
128
|
+
});
|
|
97
129
|
}
|
|
98
130
|
export async function verifyCuratedCommunityApp(input) {
|
|
99
131
|
const { orgId, ownerEmail } = requireHumanOrgOwner();
|
|
@@ -142,10 +174,10 @@ export async function verifyCuratedCommunityApp(input) {
|
|
|
142
174
|
case "file_too_large":
|
|
143
175
|
case "total_too_large":
|
|
144
176
|
case "blob_mismatch":
|
|
145
|
-
verificationFail("Builder branch files do not match the reviewed community template.", "community_verification_integrity_failed", { statusCode: 422 });
|
|
177
|
+
verificationFail("Builder branch files do not match the reviewed community template.", "community_verification_integrity_failed", { statusCode: 422, details: { readbackStage: "app_integrity" } });
|
|
146
178
|
case "ref_mismatch":
|
|
147
179
|
case "invalid_snapshot":
|
|
148
|
-
verificationFail("Builder could not provide a complete, identity-bound branch snapshot.", "community_verification_readback_unverified", { statusCode: 422 });
|
|
180
|
+
verificationFail("Builder could not provide a complete, identity-bound branch snapshot.", "community_verification_readback_unverified", { statusCode: 422, details: { readbackStage: "snapshot_ref" } });
|
|
149
181
|
case "invalid_source":
|
|
150
182
|
verificationFail("The reviewed community catalog entry is invalid.", "community_verification_catalog_invalid", { statusCode: 500 });
|
|
151
183
|
case "invalid_target":
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"community-install-verification.js","sourceRoot":"","sources":["../../../src/server/lib/community-install-verification.ts"],"names":[],"mappings":"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","sourcesContent":["import { defineActionErrors } from \"@agent-native/core/action\";\nimport {\n BuilderBranchFilesError,\n getRequestContext,\n readBuilderBranchFiles,\n readOrgMemberRole,\n} from \"@agent-native/core/server\";\nimport {\n getWorkspaceAppIdValidationError,\n normalizeWorkspaceAppId,\n} from \"@agent-native/core/shared\";\nimport {\n BUILTIN_AGENT_CATALOG_IDS,\n HIDDEN_FIRST_PARTY_AGENT_IDS,\n} from \"@agent-native/core/shared/first-party-agents\";\n\nimport { getAppCreationSettings } from \"./app-creation-store.js\";\nimport { CURATED_COMMUNITY_APP_SOURCES } from \"./community-apps.js\";\nimport {\n CommunityInstallIntegrityError,\n verifyCommunityBranchFiles,\n} from \"./community-install-integrity.js\";\nimport { CURATED_WORKSPACE_TEMPLATES } from \"./curated-workspace-templates.js\";\nimport { currentOrgId, currentOwnerEmail } from \"./dispatch-store.js\";\n\nexport const communityInstallVerificationErrors = defineActionErrors(\n \"community_verification_identity_required\",\n \"community_verification_role_unavailable\",\n \"community_verification_owner_required\",\n \"community_verification_source_unknown\",\n \"community_verification_app_id_invalid\",\n \"community_verification_app_id_shadows_first_party\",\n \"community_verification_branch_invalid\",\n \"community_verification_project_required\",\n \"community_verification_project_unavailable\",\n \"community_verification_readback_unavailable\",\n \"community_verification_readback_forbidden\",\n \"community_verification_readback_unverified\",\n \"community_verification_integrity_failed\",\n \"community_verification_catalog_invalid\",\n \"community_verification_internal_error\",\n);\n\nfunction verificationFail(\n message: string,\n code: Parameters<typeof communityInstallVerificationErrors.fail>[1],\n options: { statusCode: number },\n): never {\n return communityInstallVerificationErrors.fail(message, code, options);\n}\n\nfunction requireHumanOrgOwner(): { orgId: string; ownerEmail: string } {\n const context = getRequestContext();\n const orgId = currentOrgId();\n const contextEmail = context?.userEmail?.trim().toLowerCase();\n if (\n !context ||\n !context.authUserId?.trim() ||\n !contextEmail ||\n !orgId ||\n context.orgId !== orgId ||\n context.isSyntheticTraffic === true ||\n context.isIntegrationCaller === true ||\n context.integration !== undefined ||\n context.verifiedServiceIdentity !== undefined ||\n context.a2aIdentityAssurance !== undefined ||\n context.agentRunAnonymous === true ||\n context.authCapability !== undefined ||\n typeof context.identityAuthenticatedAtMs !== \"number\" ||\n !Number.isFinite(context.identityAuthenticatedAtMs) ||\n context.orgScope === \"personal\" ||\n /^integration@|@integration\\.local$/i.test(contextEmail)\n ) {\n verificationFail(\n \"Sign in directly to an organization as an owner or admin to verify a Builder community branch.\",\n \"community_verification_identity_required\",\n { statusCode: 403 },\n );\n }\n\n let ownerEmail: string;\n try {\n ownerEmail = currentOwnerEmail().trim().toLowerCase();\n } catch {\n verificationFail(\n \"An authenticated organization owner or admin is required.\",\n \"community_verification_identity_required\",\n { statusCode: 403 },\n );\n }\n if (!ownerEmail || ownerEmail !== contextEmail) {\n verificationFail(\n \"An authenticated organization owner or admin is required.\",\n \"community_verification_identity_required\",\n { statusCode: 403 },\n );\n }\n\n return { orgId, ownerEmail };\n}\n\nasync function requireOrganizationOwnerOrAdmin(\n orgId: string,\n ownerEmail: string,\n): Promise<void> {\n let role: string | null;\n try {\n role = await readOrgMemberRole(orgId, ownerEmail);\n } catch {\n verificationFail(\n \"Organization membership could not be verified. Try again shortly.\",\n \"community_verification_role_unavailable\",\n { statusCode: 503 },\n );\n }\n if (role !== \"owner\" && role !== \"admin\") {\n verificationFail(\n \"Only organization owners and admins can verify Builder community branches.\",\n \"community_verification_owner_required\",\n { statusCode: 403 },\n );\n }\n}\n\nfunction requireAppId(appIdInput: string): string {\n const appId = normalizeWorkspaceAppId(appIdInput);\n if (!appId || appId.length > 64 || getWorkspaceAppIdValidationError(appId)) {\n verificationFail(\n \"Choose a valid, non-reserved workspace app id.\",\n \"community_verification_app_id_invalid\",\n { statusCode: 400 },\n );\n }\n if (\n CURATED_WORKSPACE_TEMPLATES.some((template) => template.id === appId) ||\n BUILTIN_AGENT_CATALOG_IDS.includes(appId) ||\n HIDDEN_FIRST_PARTY_AGENT_IDS.has(appId)\n ) {\n verificationFail(\n \"Community apps cannot use a first-party template app id.\",\n \"community_verification_app_id_shadows_first_party\",\n { statusCode: 409 },\n );\n }\n return appId;\n}\n\nfunction requireBranchName(branchNameInput: string): string {\n const branchName = branchNameInput.trim();\n if (\n branchName !== branchNameInput ||\n branchName.length > 256 ||\n !branchName ||\n branchName\n .split(\"/\")\n .some(\n (part) =>\n !/^[A-Za-z0-9_.-]+$/.test(part) || part === \".\" || part === \"..\",\n )\n ) {\n verificationFail(\n \"Choose a valid Builder branch name.\",\n \"community_verification_branch_invalid\",\n { statusCode: 400 },\n );\n }\n return branchName;\n}\n\nfunction failBranchReadback(error: unknown): never {\n if (error instanceof BuilderBranchFilesError) {\n if (error.code === \"forbidden\" || error.code === \"not_connected\") {\n verificationFail(\n \"Builder project read access is missing or does not include this project.\",\n \"community_verification_readback_forbidden\",\n { statusCode: error.code === \"forbidden\" ? 403 : 409 },\n );\n }\n if (error.code === \"unverified\" || error.code === \"integrity_failed\") {\n verificationFail(\n \"Builder could not provide a complete, identity-bound branch snapshot.\",\n \"community_verification_readback_unverified\",\n { statusCode: 422 },\n );\n }\n if (error.code === \"invalid_request\") {\n verificationFail(\n \"Builder rejected the requested branch reference.\",\n \"community_verification_branch_invalid\",\n { statusCode: 400 },\n );\n }\n }\n verificationFail(\n \"Builder branch readback is unavailable. Try again later.\",\n \"community_verification_readback_unavailable\",\n { statusCode: 503 },\n );\n}\n\nexport async function verifyCuratedCommunityApp(input: {\n sourceId: string;\n appId: string;\n branchName: string;\n}) {\n const { orgId, ownerEmail } = requireHumanOrgOwner();\n await requireOrganizationOwnerOrAdmin(orgId, ownerEmail);\n\n const source = CURATED_COMMUNITY_APP_SOURCES.find(\n (candidate) => candidate.id === input.sourceId.trim(),\n );\n if (!source) {\n verificationFail(\n \"That community app is not in Dispatch's reviewed install catalog.\",\n \"community_verification_source_unknown\",\n { statusCode: 404 },\n );\n }\n\n const appId = requireAppId(input.appId);\n const branchName = requireBranchName(input.branchName);\n\n let settings: Awaited<ReturnType<typeof getAppCreationSettings>>;\n try {\n settings = await getAppCreationSettings();\n } catch {\n verificationFail(\n \"The organization Builder project setting could not be read. Try again later.\",\n \"community_verification_project_unavailable\",\n { statusCode: 503 },\n );\n }\n const projectId = settings.savedBuilderProjectId?.trim();\n if (!projectId || settings.builderProjectId !== projectId) {\n verificationFail(\n \"Configure a Builder project for this organization before verifying a branch.\",\n \"community_verification_project_required\",\n { statusCode: 409 },\n );\n }\n\n let snapshot: Awaited<ReturnType<typeof readBuilderBranchFiles>>;\n try {\n snapshot = await readBuilderBranchFiles({\n projectId,\n branchName,\n appPath: `apps/${appId}`,\n });\n } catch (error) {\n failBranchReadback(error);\n }\n\n try {\n return verifyCommunityBranchFiles(source, appId, snapshot, {\n projectId,\n branchName,\n });\n } catch (error) {\n if (!(error instanceof CommunityInstallIntegrityError)) {\n verificationFail(\n \"Community branch verification could not be completed.\",\n \"community_verification_internal_error\",\n { statusCode: 500 },\n );\n }\n\n switch (error.code) {\n case \"file_set_mismatch\":\n case \"file_mode_unsupported\":\n case \"file_too_large\":\n case \"total_too_large\":\n case \"blob_mismatch\":\n verificationFail(\n \"Builder branch files do not match the reviewed community template.\",\n \"community_verification_integrity_failed\",\n { statusCode: 422 },\n );\n case \"ref_mismatch\":\n case \"invalid_snapshot\":\n verificationFail(\n \"Builder could not provide a complete, identity-bound branch snapshot.\",\n \"community_verification_readback_unverified\",\n { statusCode: 422 },\n );\n case \"invalid_source\":\n verificationFail(\n \"The reviewed community catalog entry is invalid.\",\n \"community_verification_catalog_invalid\",\n { statusCode: 500 },\n );\n case \"invalid_target\":\n verificationFail(\n \"Community branch verification could not be completed.\",\n \"community_verification_internal_error\",\n { statusCode: 500 },\n );\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"community-install-verification.js","sourceRoot":"","sources":["../../../src/server/lib/community-install-verification.ts"],"names":[],"mappings":"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","sourcesContent":["import { defineActionErrors } from \"@agent-native/core/action\";\nimport {\n BuilderBranchFilesError,\n getRequestContext,\n readBuilderBranchFiles,\n readOrgMemberRole,\n} from \"@agent-native/core/server\";\nimport {\n getWorkspaceAppIdValidationError,\n normalizeWorkspaceAppId,\n} from \"@agent-native/core/shared\";\nimport {\n BUILTIN_AGENT_CATALOG_IDS,\n HIDDEN_FIRST_PARTY_AGENT_IDS,\n} from \"@agent-native/core/shared/first-party-agents\";\n\nimport { getAppCreationSettings } from \"./app-creation-store.js\";\nimport { CURATED_COMMUNITY_APP_SOURCES } from \"./community-apps.js\";\nimport {\n CommunityInstallIntegrityError,\n verifyCommunityBranchFiles,\n} from \"./community-install-integrity.js\";\nimport { CURATED_WORKSPACE_TEMPLATES } from \"./curated-workspace-templates.js\";\nimport { currentOrgId, currentOwnerEmail } from \"./dispatch-store.js\";\n\nexport const communityInstallVerificationErrors = defineActionErrors(\n \"community_verification_identity_required\",\n \"community_verification_role_unavailable\",\n \"community_verification_owner_required\",\n \"community_verification_source_unknown\",\n \"community_verification_app_id_invalid\",\n \"community_verification_app_id_shadows_first_party\",\n \"community_verification_branch_invalid\",\n \"community_verification_project_required\",\n \"community_verification_project_unavailable\",\n \"community_verification_readback_unavailable\",\n \"community_verification_readback_forbidden\",\n \"community_verification_readback_unverified\",\n \"community_verification_integrity_failed\",\n \"community_verification_catalog_invalid\",\n \"community_verification_internal_error\",\n);\n\nfunction verificationFail(\n message: string,\n code: Parameters<typeof communityInstallVerificationErrors.fail>[1],\n options: { statusCode: number; details?: Record<string, unknown> },\n): never {\n return communityInstallVerificationErrors.fail(message, code, options);\n}\n\nconst READBACK_STAGES = new Set([\n \"status_request\",\n \"status_shape\",\n \"status_binding\",\n \"status_currentness\",\n \"post_read_status_request\",\n \"post_read_status_shape\",\n \"post_read_status_binding\",\n \"post_read_status_currentness\",\n \"download_url_request\",\n \"download_url_shape\",\n \"download_url_binding\",\n \"bundle_download\",\n \"bundle_read\",\n \"bundle_digest\",\n \"bundle_parse\",\n \"target_subtree_missing\",\n \"post_read_currentness\",\n \"app_integrity\",\n \"snapshot_ref\",\n]);\n\nfunction readbackStage(error: unknown): string {\n const stage =\n error && typeof error === \"object\"\n ? (error as { readbackStage?: unknown }).readbackStage\n : undefined;\n return typeof stage === \"string\" && READBACK_STAGES.has(stage)\n ? stage\n : \"unknown\";\n}\n\nfunction requireHumanOrgOwner(): { orgId: string; ownerEmail: string } {\n const context = getRequestContext();\n const orgId = currentOrgId();\n const contextEmail = context?.userEmail?.trim().toLowerCase();\n if (\n !context ||\n !context.authUserId?.trim() ||\n !contextEmail ||\n !orgId ||\n context.orgId !== orgId ||\n context.isSyntheticTraffic === true ||\n context.isIntegrationCaller === true ||\n context.integration !== undefined ||\n context.verifiedServiceIdentity !== undefined ||\n context.a2aIdentityAssurance !== undefined ||\n context.agentRunAnonymous === true ||\n context.authCapability !== undefined ||\n typeof context.identityAuthenticatedAtMs !== \"number\" ||\n !Number.isFinite(context.identityAuthenticatedAtMs) ||\n context.orgScope === \"personal\" ||\n /^integration@|@integration\\.local$/i.test(contextEmail)\n ) {\n verificationFail(\n \"Sign in directly to an organization as an owner or admin to verify a Builder community branch.\",\n \"community_verification_identity_required\",\n { statusCode: 403 },\n );\n }\n\n let ownerEmail: string;\n try {\n ownerEmail = currentOwnerEmail().trim().toLowerCase();\n } catch {\n verificationFail(\n \"An authenticated organization owner or admin is required.\",\n \"community_verification_identity_required\",\n { statusCode: 403 },\n );\n }\n if (!ownerEmail || ownerEmail !== contextEmail) {\n verificationFail(\n \"An authenticated organization owner or admin is required.\",\n \"community_verification_identity_required\",\n { statusCode: 403 },\n );\n }\n\n return { orgId, ownerEmail };\n}\n\nasync function requireOrganizationOwnerOrAdmin(\n orgId: string,\n ownerEmail: string,\n): Promise<void> {\n let role: string | null;\n try {\n role = await readOrgMemberRole(orgId, ownerEmail);\n } catch {\n verificationFail(\n \"Organization membership could not be verified. Try again shortly.\",\n \"community_verification_role_unavailable\",\n { statusCode: 503 },\n );\n }\n if (role !== \"owner\" && role !== \"admin\") {\n verificationFail(\n \"Only organization owners and admins can verify Builder community branches.\",\n \"community_verification_owner_required\",\n { statusCode: 403 },\n );\n }\n}\n\nfunction requireAppId(appIdInput: string): string {\n const appId = normalizeWorkspaceAppId(appIdInput);\n if (!appId || appId.length > 64 || getWorkspaceAppIdValidationError(appId)) {\n verificationFail(\n \"Choose a valid, non-reserved workspace app id.\",\n \"community_verification_app_id_invalid\",\n { statusCode: 400 },\n );\n }\n if (\n CURATED_WORKSPACE_TEMPLATES.some((template) => template.id === appId) ||\n BUILTIN_AGENT_CATALOG_IDS.includes(appId) ||\n HIDDEN_FIRST_PARTY_AGENT_IDS.has(appId)\n ) {\n verificationFail(\n \"Community apps cannot use a first-party template app id.\",\n \"community_verification_app_id_shadows_first_party\",\n { statusCode: 409 },\n );\n }\n return appId;\n}\n\nfunction requireBranchName(branchNameInput: string): string {\n const branchName = branchNameInput.trim();\n if (\n branchName !== branchNameInput ||\n branchName.length > 256 ||\n !branchName ||\n branchName\n .split(\"/\")\n .some(\n (part) =>\n !/^[A-Za-z0-9_.-]+$/.test(part) || part === \".\" || part === \"..\",\n )\n ) {\n verificationFail(\n \"Choose a valid Builder branch name.\",\n \"community_verification_branch_invalid\",\n { statusCode: 400 },\n );\n }\n return branchName;\n}\n\nfunction failBranchReadback(error: unknown): never {\n if (error instanceof BuilderBranchFilesError) {\n if (error.code === \"forbidden\" || error.code === \"not_connected\") {\n verificationFail(\n \"Builder project read access is missing or does not include this project.\",\n \"community_verification_readback_forbidden\",\n { statusCode: error.code === \"forbidden\" ? 403 : 409 },\n );\n }\n if (error.code === \"unverified\" || error.code === \"integrity_failed\") {\n verificationFail(\n \"Builder could not provide a complete, identity-bound branch snapshot.\",\n \"community_verification_readback_unverified\",\n { statusCode: 422, details: { readbackStage: readbackStage(error) } },\n );\n }\n if (error.code === \"invalid_request\") {\n verificationFail(\n \"Builder rejected the requested branch reference.\",\n \"community_verification_branch_invalid\",\n { statusCode: 400 },\n );\n }\n }\n verificationFail(\n \"Builder branch readback is unavailable. Try again later.\",\n \"community_verification_readback_unavailable\",\n {\n statusCode: 503,\n details: { readbackStage: readbackStage(error) },\n },\n );\n}\n\nexport async function verifyCuratedCommunityApp(input: {\n sourceId: string;\n appId: string;\n branchName: string;\n}) {\n const { orgId, ownerEmail } = requireHumanOrgOwner();\n await requireOrganizationOwnerOrAdmin(orgId, ownerEmail);\n\n const source = CURATED_COMMUNITY_APP_SOURCES.find(\n (candidate) => candidate.id === input.sourceId.trim(),\n );\n if (!source) {\n verificationFail(\n \"That community app is not in Dispatch's reviewed install catalog.\",\n \"community_verification_source_unknown\",\n { statusCode: 404 },\n );\n }\n\n const appId = requireAppId(input.appId);\n const branchName = requireBranchName(input.branchName);\n\n let settings: Awaited<ReturnType<typeof getAppCreationSettings>>;\n try {\n settings = await getAppCreationSettings();\n } catch {\n verificationFail(\n \"The organization Builder project setting could not be read. Try again later.\",\n \"community_verification_project_unavailable\",\n { statusCode: 503 },\n );\n }\n const projectId = settings.savedBuilderProjectId?.trim();\n if (!projectId || settings.builderProjectId !== projectId) {\n verificationFail(\n \"Configure a Builder project for this organization before verifying a branch.\",\n \"community_verification_project_required\",\n { statusCode: 409 },\n );\n }\n\n let snapshot: Awaited<ReturnType<typeof readBuilderBranchFiles>>;\n try {\n snapshot = await readBuilderBranchFiles({\n projectId,\n branchName,\n appPath: `apps/${appId}`,\n });\n } catch (error) {\n failBranchReadback(error);\n }\n\n try {\n return verifyCommunityBranchFiles(source, appId, snapshot, {\n projectId,\n branchName,\n });\n } catch (error) {\n if (!(error instanceof CommunityInstallIntegrityError)) {\n verificationFail(\n \"Community branch verification could not be completed.\",\n \"community_verification_internal_error\",\n { statusCode: 500 },\n );\n }\n\n switch (error.code) {\n case \"file_set_mismatch\":\n case \"file_mode_unsupported\":\n case \"file_too_large\":\n case \"total_too_large\":\n case \"blob_mismatch\":\n verificationFail(\n \"Builder branch files do not match the reviewed community template.\",\n \"community_verification_integrity_failed\",\n { statusCode: 422, details: { readbackStage: \"app_integrity\" } },\n );\n case \"ref_mismatch\":\n case \"invalid_snapshot\":\n verificationFail(\n \"Builder could not provide a complete, identity-bound branch snapshot.\",\n \"community_verification_readback_unverified\",\n { statusCode: 422, details: { readbackStage: \"snapshot_ref\" } },\n );\n case \"invalid_source\":\n verificationFail(\n \"The reviewed community catalog entry is invalid.\",\n \"community_verification_catalog_invalid\",\n { statusCode: 500 },\n );\n case \"invalid_target\":\n verificationFail(\n \"Community branch verification could not be completed.\",\n \"community_verification_internal_error\",\n { statusCode: 500 },\n );\n }\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/dispatch",
|
|
3
|
-
"version": "0.40.43
|
|
3
|
+
"version": "0.40.43",
|
|
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.222.1
|
|
93
|
+
"@agent-native/toolkit": "0.222.1"
|
|
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.222.1
|
|
107
|
+
"@agent-native/core": "0.222.1"
|
|
108
108
|
},
|
|
109
109
|
"peerDependencies": {
|
|
110
|
-
"@agent-native/core": "0.222.
|
|
110
|
+
"@agent-native/core": ">=0.222.0-0",
|
|
111
111
|
"react": ">=19.2.7",
|
|
112
112
|
"react-dom": ">=19.2.7",
|
|
113
113
|
"react-router": ">=8"
|
|
@@ -4,7 +4,10 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
4
4
|
|
|
5
5
|
const mocks = vi.hoisted(() => {
|
|
6
6
|
class MockBuilderBranchFilesError extends Error {
|
|
7
|
-
constructor(
|
|
7
|
+
constructor(
|
|
8
|
+
readonly code: string,
|
|
9
|
+
readonly readbackStage?: string,
|
|
10
|
+
) {
|
|
8
11
|
super(code);
|
|
9
12
|
}
|
|
10
13
|
}
|
|
@@ -292,12 +295,29 @@ describe("verifyCuratedCommunityApp", () => {
|
|
|
292
295
|
|
|
293
296
|
it("maps Builder read failures to typed errors without returning a receipt", async () => {
|
|
294
297
|
mocks.readBuilderBranchFiles.mockRejectedValue(
|
|
295
|
-
new BuilderBranchFilesError("unverified"),
|
|
298
|
+
new BuilderBranchFilesError("unverified", "status_currentness"),
|
|
296
299
|
);
|
|
297
300
|
|
|
298
301
|
await expect(verifyCuratedCommunityApp(input)).rejects.toMatchObject({
|
|
299
302
|
errorCode: "community_verification_readback_unverified",
|
|
300
303
|
statusCode: 422,
|
|
304
|
+
details: { readbackStage: "status_currentness" },
|
|
301
305
|
});
|
|
302
306
|
});
|
|
307
|
+
|
|
308
|
+
it("keeps older and unrecognized Core diagnostics explicitly unknown", async () => {
|
|
309
|
+
for (const error of [
|
|
310
|
+
new BuilderBranchFilesError("unverified"),
|
|
311
|
+
new BuilderBranchFilesError(
|
|
312
|
+
"unverified",
|
|
313
|
+
"https://provider.invalid/private",
|
|
314
|
+
),
|
|
315
|
+
]) {
|
|
316
|
+
mocks.readBuilderBranchFiles.mockRejectedValueOnce(error);
|
|
317
|
+
await expect(verifyCuratedCommunityApp(input)).rejects.toMatchObject({
|
|
318
|
+
errorCode: "community_verification_readback_unverified",
|
|
319
|
+
details: { readbackStage: "unknown" },
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
});
|
|
303
323
|
});
|
|
@@ -44,11 +44,43 @@ export const communityInstallVerificationErrors = defineActionErrors(
|
|
|
44
44
|
function verificationFail(
|
|
45
45
|
message: string,
|
|
46
46
|
code: Parameters<typeof communityInstallVerificationErrors.fail>[1],
|
|
47
|
-
options: { statusCode: number },
|
|
47
|
+
options: { statusCode: number; details?: Record<string, unknown> },
|
|
48
48
|
): never {
|
|
49
49
|
return communityInstallVerificationErrors.fail(message, code, options);
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
const READBACK_STAGES = new Set([
|
|
53
|
+
"status_request",
|
|
54
|
+
"status_shape",
|
|
55
|
+
"status_binding",
|
|
56
|
+
"status_currentness",
|
|
57
|
+
"post_read_status_request",
|
|
58
|
+
"post_read_status_shape",
|
|
59
|
+
"post_read_status_binding",
|
|
60
|
+
"post_read_status_currentness",
|
|
61
|
+
"download_url_request",
|
|
62
|
+
"download_url_shape",
|
|
63
|
+
"download_url_binding",
|
|
64
|
+
"bundle_download",
|
|
65
|
+
"bundle_read",
|
|
66
|
+
"bundle_digest",
|
|
67
|
+
"bundle_parse",
|
|
68
|
+
"target_subtree_missing",
|
|
69
|
+
"post_read_currentness",
|
|
70
|
+
"app_integrity",
|
|
71
|
+
"snapshot_ref",
|
|
72
|
+
]);
|
|
73
|
+
|
|
74
|
+
function readbackStage(error: unknown): string {
|
|
75
|
+
const stage =
|
|
76
|
+
error && typeof error === "object"
|
|
77
|
+
? (error as { readbackStage?: unknown }).readbackStage
|
|
78
|
+
: undefined;
|
|
79
|
+
return typeof stage === "string" && READBACK_STAGES.has(stage)
|
|
80
|
+
? stage
|
|
81
|
+
: "unknown";
|
|
82
|
+
}
|
|
83
|
+
|
|
52
84
|
function requireHumanOrgOwner(): { orgId: string; ownerEmail: string } {
|
|
53
85
|
const context = getRequestContext();
|
|
54
86
|
const orgId = currentOrgId();
|
|
@@ -180,7 +212,7 @@ function failBranchReadback(error: unknown): never {
|
|
|
180
212
|
verificationFail(
|
|
181
213
|
"Builder could not provide a complete, identity-bound branch snapshot.",
|
|
182
214
|
"community_verification_readback_unverified",
|
|
183
|
-
{ statusCode: 422 },
|
|
215
|
+
{ statusCode: 422, details: { readbackStage: readbackStage(error) } },
|
|
184
216
|
);
|
|
185
217
|
}
|
|
186
218
|
if (error.code === "invalid_request") {
|
|
@@ -194,7 +226,10 @@ function failBranchReadback(error: unknown): never {
|
|
|
194
226
|
verificationFail(
|
|
195
227
|
"Builder branch readback is unavailable. Try again later.",
|
|
196
228
|
"community_verification_readback_unavailable",
|
|
197
|
-
{
|
|
229
|
+
{
|
|
230
|
+
statusCode: 503,
|
|
231
|
+
details: { readbackStage: readbackStage(error) },
|
|
232
|
+
},
|
|
198
233
|
);
|
|
199
234
|
}
|
|
200
235
|
|
|
@@ -273,14 +308,14 @@ export async function verifyCuratedCommunityApp(input: {
|
|
|
273
308
|
verificationFail(
|
|
274
309
|
"Builder branch files do not match the reviewed community template.",
|
|
275
310
|
"community_verification_integrity_failed",
|
|
276
|
-
{ statusCode: 422 },
|
|
311
|
+
{ statusCode: 422, details: { readbackStage: "app_integrity" } },
|
|
277
312
|
);
|
|
278
313
|
case "ref_mismatch":
|
|
279
314
|
case "invalid_snapshot":
|
|
280
315
|
verificationFail(
|
|
281
316
|
"Builder could not provide a complete, identity-bound branch snapshot.",
|
|
282
317
|
"community_verification_readback_unverified",
|
|
283
|
-
{ statusCode: 422 },
|
|
318
|
+
{ statusCode: 422, details: { readbackStage: "snapshot_ref" } },
|
|
284
319
|
);
|
|
285
320
|
case "invalid_source":
|
|
286
321
|
verificationFail(
|