@agent-native/core 0.212.1 → 0.214.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/dist/a2a/anthropic-managed-agents.js +1 -0
- package/dist/a2a/caller-auth.js +7 -2
- package/dist/a2a/client.d.ts +1 -0
- package/dist/a2a/client.js +27 -0
- package/dist/a2a/handlers.js +15 -3
- package/dist/a2a/organization-identity.d.ts +4 -1
- package/dist/a2a/organization-identity.js +3 -1
- package/dist/a2a/server.d.ts +6 -5
- package/dist/a2a/server.js +79 -6
- package/dist/a2a-claims.d.ts +1 -0
- package/dist/a2a-claims.js +1 -0
- package/dist/agent/actions/manage-provider-key-policy.js +4 -2
- package/dist/agent/app-model-defaults.js +2 -10
- package/dist/agent/loop-settings.js +2 -10
- package/dist/appearance/actions/get-theme-family.d.ts +8 -0
- package/dist/appearance/actions/get-theme-family.js +38 -0
- package/dist/appearance/actions/set-theme-family.d.ts +7 -0
- package/dist/appearance/actions/set-theme-family.js +33 -0
- package/dist/appearance/theme-family.d.ts +13 -0
- package/dist/appearance/theme-family.js +38 -0
- package/dist/audit/actions/export-audit-events.js +1 -0
- package/dist/audit/attribution.d.ts +5 -4
- package/dist/audit/attribution.js +2 -1
- package/dist/audit/index.d.ts +1 -1
- package/dist/audit/ocsf.js +1 -0
- package/dist/audit/read-scope.js +2 -12
- package/dist/audit/record.js +1 -0
- package/dist/audit/store.js +12 -3
- package/dist/audit/types.d.ts +4 -0
- package/dist/automation/index.d.ts +1 -1
- package/dist/automations/service.js +3 -10
- package/dist/client/org/hooks.d.ts +3 -0
- package/dist/client/org/hooks.js +12 -0
- package/dist/client/theme-family.d.ts +35 -0
- package/dist/client/theme-family.js +223 -0
- package/dist/client/theme.d.ts +1 -1
- package/dist/client/theme.js +5 -2
- package/dist/client/ui/index.d.ts +1 -0
- package/dist/client/ui/index.js +1 -0
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/routes.d.ts +2 -2
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/connections/catalog.d.ts +1 -1
- package/dist/connections/catalog.js +7 -1
- package/dist/credentials/index.js +18 -2
- package/dist/data-widgets/index.d.ts +339 -4
- package/dist/data-widgets/index.js +150 -7
- package/dist/db/schema-snapshot.generated.js +5 -2
- package/dist/feature-flags/a2a-action-route.js +1 -0
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/file-upload/storage-settings.js +2 -9
- package/dist/framework-tools.js +2 -0
- package/dist/jobs/actions/manage-recurring-job.d.ts +1 -1
- package/dist/jobs/tools.js +2 -12
- package/dist/mcp/actions/service-token-access.js +15 -11
- package/dist/mcp/credential-issuance.js +9 -2
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +1 -1
- package/dist/org/actions.d.ts +1 -1
- package/dist/org/actions.js +3 -7
- package/dist/org/app-roles.js +10 -1
- package/dist/org/context.d.ts +1 -0
- package/dist/org/context.js +122 -24
- package/dist/org/federation.d.ts +1 -1
- package/dist/org/federation.js +2 -2
- package/dist/org/handlers.d.ts +4 -0
- package/dist/org/handlers.js +140 -44
- package/dist/org/index.d.ts +2 -1
- package/dist/org/membership.d.ts +6 -4
- package/dist/org/membership.js +7 -5
- package/dist/org/migrations.js +6 -0
- package/dist/org/plugin.d.ts +1 -0
- package/dist/org/plugin.js +9 -1
- package/dist/org/private-icon-handlers.js +4 -10
- package/dist/org/types.d.ts +2 -0
- package/dist/org/workspace-app-access.js +62 -14
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +11 -11
- package/dist/provider-api/actions/provider-api.d.ts +11 -11
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/secrets/routes.d.ts +6 -6
- package/dist/server/action-discovery.js +8 -0
- package/dist/server/action-routes.d.ts +1 -0
- package/dist/server/action-routes.js +13 -1
- package/dist/server/agent-chat/context-tools.js +43 -1
- package/dist/server/agent-chat/prompt-resources.js +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/agent-engine-default-model-route.d.ts +1 -1
- package/dist/server/agent-engine-ollama-models-route.d.ts +1 -1
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.js +1 -0
- package/dist/server/org-admin.js +3 -2
- package/dist/server/personal-provider-key-holders.d.ts +1 -1
- package/dist/server/personal-provider-key-holders.js +7 -2
- package/dist/server/personal-provider-key-policy.d.ts +2 -0
- package/dist/server/personal-provider-key-policy.js +21 -5
- package/dist/server/request-context.d.ts +2 -0
- package/dist/server/request-context.js +7 -0
- package/dist/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +16 -13
- package/dist/triggers/actions/manage-automation.d.ts +4 -4
- package/dist/triggers/routes.js +2 -9
- package/dist/usage/alerts-store.js +2 -9
- package/dist/usage/metrics-store.js +2 -9
- package/dist/workspace-connections/actions/list-workspace-user-groups.d.ts +1 -1
- package/dist/workspace-connections/groups.js +2 -11
- package/package.json +3 -3
- package/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +16 -13
|
@@ -16,7 +16,7 @@ export const SCHEMA_SNAPSHOT = {
|
|
|
16
16
|
'CREATE TABLE "a2a_approvals" (\n "id" text NOT NULL,\n "task_id" text NOT NULL,\n "owner_email" text NOT NULL,\n "org_id" text,\n "tool_name" text NOT NULL,\n "tool_input" text NOT NULL,\n "approval_key" text NOT NULL,\n "call_id" text NOT NULL,\n "status" text DEFAULT \'pending\'::text NOT NULL,\n "result" text,\n "expires_at" bigint NOT NULL,\n "created_at" bigint NOT NULL,\n "updated_at" bigint NOT NULL\n);',
|
|
17
17
|
'CREATE TABLE "a2a_tasks" (\n "id" text NOT NULL,\n "context_id" text,\n "status_state" text DEFAULT \'submitted\'::text NOT NULL,\n "status_message" text,\n "status_timestamp" text NOT NULL,\n "history" text DEFAULT \'[]\'::text NOT NULL,\n "artifacts" text DEFAULT \'[]\'::text NOT NULL,\n "metadata" text,\n "owner_email" text,\n "owner_scope" text DEFAULT \'\'::text NOT NULL,\n "idempotency_key" text,\n "created_at" bigint NOT NULL,\n "updated_at" bigint NOT NULL\n);',
|
|
18
18
|
'CREATE TABLE "account" (\n "id" text NOT NULL,\n "account_id" text NOT NULL,\n "provider_id" text NOT NULL,\n "user_id" text NOT NULL,\n "access_token" text,\n "refresh_token" text,\n "id_token" text,\n "access_token_expires_at" timestamp with time zone,\n "refresh_token_expires_at" timestamp with time zone,\n "scope" text,\n "password" text,\n "created_at" timestamp with time zone NOT NULL,\n "updated_at" timestamp with time zone NOT NULL\n);',
|
|
19
|
-
'CREATE TABLE "agent_audit_log" (\n "id" text NOT NULL,\n "created_at" bigint NOT NULL,\n "action" text NOT NULL,\n "caller" text NOT NULL,\n "actor_kind" text NOT NULL,\n "actor_email" text,\n "org_id" text,\n "thread_id" text,\n "turn_id" text,\n "target_type" text,\n "target_id" text,\n "status" text DEFAULT \'success\'::text NOT NULL,\n "summary" text,\n "input" text,\n "error_code" text,\n "owner_email" text,\n "visibility" text DEFAULT \'private\'::text NOT NULL,\n "run_id" text,\n "task_id" text,\n "parent_task_id" text,\n "source_kind" text,\n "source_platform" text,\n "source_id" text,\n "source_url" text,\n "network_protocol" text,\n "network_id" text,\n "network_peer" text,\n "app" text,\n "reported_client_name" text,\n "reported_client_version" text,\n "oauth_client_id" text,\n "approval" text\n);',
|
|
19
|
+
'CREATE TABLE "agent_audit_log" (\n "id" text NOT NULL,\n "created_at" bigint NOT NULL,\n "action" text NOT NULL,\n "caller" text NOT NULL,\n "actor_kind" text NOT NULL,\n "actor_email" text,\n "org_id" text,\n "thread_id" text,\n "turn_id" text,\n "target_type" text,\n "target_id" text,\n "status" text DEFAULT \'success\'::text NOT NULL,\n "summary" text,\n "input" text,\n "error_code" text,\n "owner_email" text,\n "visibility" text DEFAULT \'private\'::text NOT NULL,\n "run_id" text,\n "task_id" text,\n "parent_task_id" text,\n "source_kind" text,\n "source_platform" text,\n "source_id" text,\n "source_url" text,\n "network_protocol" text,\n "network_id" text,\n "network_peer" text,\n "app" text,\n "reported_client_name" text,\n "reported_client_version" text,\n "oauth_client_id" text,\n "approval" text,\n "identity_assurance" text\n);',
|
|
20
20
|
'CREATE TABLE "agent_chat_submission_inbox" (\n "thread_id" text NOT NULL,\n "message_id" text NOT NULL,\n "state" text NOT NULL,\n "actor_email" text NOT NULL,\n "actor_auth_user_id" text,\n "actor_identity_authenticated_at_ms" bigint,\n "actor_name" text,\n "actor_org_id" text,\n "actor_org_scope" text,\n "actor_anonymous" boolean DEFAULT false NOT NULL,\n "payload_hash" text NOT NULL,\n "payload_json" text NOT NULL,\n "interrupt_active_run" boolean DEFAULT false NOT NULL,\n "submitted_run_id" text,\n "queue_order" bigint DEFAULT nextval(\'agent_chat_submission_inbox_queue_order_seq\'::regclass) NOT NULL,\n "move_to_top_at" bigint,\n "retry_after" bigint,\n "created_at" bigint NOT NULL,\n "updated_at" bigint NOT NULL,\n "interrupt_run_id" text\n);',
|
|
21
21
|
'CREATE TABLE "agent_checkpoints" (\n "id" text NOT NULL,\n "thread_id" text NOT NULL,\n "run_id" text,\n "commit_sha" text NOT NULL,\n "message" text DEFAULT \'\'::text NOT NULL,\n "created_at" bigint NOT NULL\n);',
|
|
22
22
|
'CREATE TABLE "agent_eval_datasets" (\n "id" text NOT NULL,\n "name" text NOT NULL,\n "description" text DEFAULT \'\'::text NOT NULL,\n "entries" text DEFAULT \'[]\'::text NOT NULL,\n "created_at" bigint NOT NULL,\n "updated_at" bigint NOT NULL,\n "user_id" text,\n "idempotency_key" text\n);',
|
|
@@ -121,7 +121,7 @@ export const SCHEMA_SNAPSHOT = {
|
|
|
121
121
|
'CREATE TABLE "org_members" (\n "id" text NOT NULL,\n "org_id" text NOT NULL,\n "email" text NOT NULL,\n "role" text NOT NULL,\n "joined_at" bigint NOT NULL,\n "federation_removal_pending_at" bigint\n);',
|
|
122
122
|
'CREATE TABLE "org_scim_memberships" (\n "id" text NOT NULL,\n "org_id" text NOT NULL,\n "user_id" text NOT NULL,\n "created_membership" boolean DEFAULT false NOT NULL,\n "created_at" bigint NOT NULL,\n "member_id" text\n);',
|
|
123
123
|
'CREATE TABLE "organization" (\n "id" text NOT NULL,\n "name" text NOT NULL,\n "slug" text NOT NULL,\n "logo" text,\n "metadata" text,\n "created_at" timestamp with time zone NOT NULL,\n "updated_at" timestamp with time zone NOT NULL\n);',
|
|
124
|
-
'CREATE TABLE "organizations" (\n "id" text NOT NULL,\n "name" text NOT NULL,\n "created_by" text NOT NULL,\n "created_at" bigint NOT NULL,\n "allowed_domain" text,\n "a2a_secret" text,\n "workspace_url" text,\n "required_auth_provider" text,\n "identity_authority" text,\n "identity_id" text,\n "federation_roster_initialized_at" bigint,\n "icon_json" text,\n "icon_revision" bigint DEFAULT 0 NOT NULL\n);',
|
|
124
|
+
'CREATE TABLE "organizations" (\n "id" text NOT NULL,\n "name" text NOT NULL,\n "created_by" text NOT NULL,\n "created_at" bigint NOT NULL,\n "allowed_domain" text,\n "a2a_secret" text,\n "workspace_url" text,\n "required_auth_provider" text,\n "identity_authority" text,\n "identity_id" text,\n "federation_roster_initialized_at" bigint,\n "icon_json" text,\n "icon_revision" bigint DEFAULT 0 NOT NULL,\n "a2a_member_delegation_enabled" boolean DEFAULT false NOT NULL\n);',
|
|
125
125
|
'CREATE TABLE "private_icon_assets" (\n "id" text NOT NULL,\n "owner_email" text NOT NULL,\n "org_id" text,\n "mime_type" text NOT NULL,\n "filename" text,\n "alt" text,\n "size" bigint NOT NULL,\n "sha256" text NOT NULL,\n "blob_handle_json" text NOT NULL,\n "created_at" bigint NOT NULL,\n "updated_at" bigint NOT NULL\n);',
|
|
126
126
|
'CREATE TABLE "progress_runs" (\n "id" text NOT NULL,\n "owner" text NOT NULL,\n "title" text NOT NULL,\n "step" text,\n "percent" bigint,\n "status" text DEFAULT \'running\'::text NOT NULL,\n "metadata" text,\n "started_at" bigint NOT NULL,\n "updated_at" bigint NOT NULL,\n "completed_at" bigint\n);',
|
|
127
127
|
'CREATE TABLE "provider_api_cooldowns" (\n "quota_key" text NOT NULL,\n "provider_id" text NOT NULL,\n "scope_key" text NOT NULL,\n "cooldown_until" bigint NOT NULL,\n "status" bigint,\n "reason" text,\n "updated_at" bigint NOT NULL\n);',
|
|
@@ -866,6 +866,7 @@ export const SCHEMA_SNAPSHOT = {
|
|
|
866
866
|
["application_state", "baseline", null],
|
|
867
867
|
["application_state", "indexes", null],
|
|
868
868
|
["application_state", "widen-bigint", null],
|
|
869
|
+
["audit", "a2a-identity-assurance", "5ebfefc25224eaa5"],
|
|
869
870
|
["audit", "baseline", null],
|
|
870
871
|
["audit", "mcp-client-attribution", "bc0ea72722e10241"],
|
|
871
872
|
["auth_sessions", "baseline", null],
|
|
@@ -1038,6 +1039,7 @@ export const SCHEMA_SNAPSHOT = {
|
|
|
1038
1039
|
["org", "org-scim-membership-member-id", "cd1c4fb7479507d3"],
|
|
1039
1040
|
["org", "org-scim-membership-ownership", "09ca1c03026cda83"],
|
|
1040
1041
|
["org", "org-tables-timestamps-bigint", "a71b72b885bd5585"],
|
|
1042
|
+
["org", "organization-a2a-member-delegation", "3d01bcd4e7c259b0"],
|
|
1041
1043
|
["org", "organization-federation-removal-pending", "47fe40eb2ea33753"],
|
|
1042
1044
|
["org", "organization-federation-roster-initialized", "3307d4d99818c2f0"],
|
|
1043
1045
|
["org", "organization-identity-federation", "e24bac924c2d4c7a"],
|
|
@@ -1182,5 +1184,6 @@ export const SCHEMA_SNAPSHOT = {
|
|
|
1182
1184
|
["_org_migrations", 1032, "agent-audit-log-base-table"],
|
|
1183
1185
|
["_org_migrations", 1033, "organization-visual-identity"],
|
|
1184
1186
|
["_org_migrations", 1034, "private-icon-assets"],
|
|
1187
|
+
["_org_migrations", 1035, "organization-a2a-member-delegation"],
|
|
1185
1188
|
],
|
|
1186
1189
|
};
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
* keep uploading to the old bucket.
|
|
9
9
|
*/
|
|
10
10
|
import { fail } from "../action.js";
|
|
11
|
-
import { getDbExec } from "../db/client.js";
|
|
12
11
|
import { deleteAppSecret, readAppSecrets, writeAppSecret, } from "../secrets/storage.js";
|
|
12
|
+
import { readOrgMemberRole } from "../server/personal-provider-key-policy.js";
|
|
13
13
|
import { getActiveFileUploadProviderForRequest, listFileUploadProviders, } from "./registry.js";
|
|
14
14
|
import { getPrivateStorageReadinessForUser, } from "./storage-readiness.js";
|
|
15
15
|
export const FILE_STORAGE_SECRET_KEYS = {
|
|
@@ -46,14 +46,7 @@ export async function resolveFileStorageAccess(ctx) {
|
|
|
46
46
|
// matching `canMutateWorkspaceScope` in the secrets routes.
|
|
47
47
|
if (!orgId)
|
|
48
48
|
return { scopeId: `solo:${email}`, canManage: true };
|
|
49
|
-
const
|
|
50
|
-
sql: `SELECT role FROM org_members
|
|
51
|
-
WHERE org_id = ? AND LOWER(email) = LOWER(?)
|
|
52
|
-
AND federation_removal_pending_at IS NULL
|
|
53
|
-
LIMIT 1`,
|
|
54
|
-
args: [orgId, email],
|
|
55
|
-
});
|
|
56
|
-
const role = rows[0]?.role;
|
|
49
|
+
const role = await readOrgMemberRole(orgId, email);
|
|
57
50
|
return { scopeId: orgId, canManage: role === "owner" || role === "admin" };
|
|
58
51
|
}
|
|
59
52
|
export function inferFileStorageProvider(endpoint) {
|
package/dist/framework-tools.js
CHANGED
|
@@ -165,6 +165,8 @@ export const CORE_ACTION_GROUPS = {
|
|
|
165
165
|
"change-password": "userProfile",
|
|
166
166
|
"request-privacy-right": "userProfile",
|
|
167
167
|
"change-appearance": "userProfile",
|
|
168
|
+
"get-theme-family": "userProfile",
|
|
169
|
+
"set-theme-family": "userProfile",
|
|
168
170
|
"list-audit-events": "audit",
|
|
169
171
|
"get-audit-event": "audit",
|
|
170
172
|
"export-audit-events": "audit",
|
|
@@ -13,10 +13,10 @@ declare const _default: import("../../action.js").ActionDefinition<{
|
|
|
13
13
|
enabled?: undefined;
|
|
14
14
|
nextRun?: undefined;
|
|
15
15
|
} | {
|
|
16
|
+
deleted?: undefined;
|
|
16
17
|
resourceId: string;
|
|
17
18
|
name: string;
|
|
18
19
|
enabled: boolean;
|
|
19
20
|
nextRun: string;
|
|
20
|
-
deleted?: undefined;
|
|
21
21
|
}>;
|
|
22
22
|
export default _default;
|
package/dist/jobs/tools.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { resolveAutomationAccess } from "../automations/access.js";
|
|
2
2
|
import { DEFAULT_AUTOMATION_SCHEDULE } from "../automations/service.js";
|
|
3
|
-
import { getDbExec } from "../db/client.js";
|
|
4
3
|
import { resolveUserSchedulingTimezone } from "../localization/user-timezone.js";
|
|
5
4
|
import { organizationIdFromResourceOwner, resourcePutIfAbsent, resourceGetByPath, resourceList, resourceDelete, SHARED_OWNER, sharedResourceOwner, } from "../resources/store.js";
|
|
5
|
+
import { readOrgMemberRole } from "../server/personal-provider-key-policy.js";
|
|
6
6
|
import { getRequestUserEmail, getRequestOrgId, getIntegrationRequestContext, } from "../server/request-context.js";
|
|
7
7
|
import { isReasoningEffort, REASONING_EFFORTS, } from "../shared/reasoning-effort.js";
|
|
8
8
|
import { RESUME_AUTOMATION_PATCH } from "./automation-outcome.js";
|
|
@@ -27,17 +27,7 @@ async function isCurrentUserOrgAdmin(orgId) {
|
|
|
27
27
|
if (!email)
|
|
28
28
|
return false;
|
|
29
29
|
try {
|
|
30
|
-
const
|
|
31
|
-
const { rows } = await client.execute({
|
|
32
|
-
sql: `SELECT role FROM org_members
|
|
33
|
-
WHERE org_id = ? AND LOWER(email) = ?
|
|
34
|
-
AND federation_removal_pending_at IS NULL
|
|
35
|
-
LIMIT 1`,
|
|
36
|
-
args: [orgId, email.toLowerCase()],
|
|
37
|
-
});
|
|
38
|
-
if (rows.length === 0)
|
|
39
|
-
return false;
|
|
40
|
-
const role = String(rows[0].role ?? "").toLowerCase();
|
|
30
|
+
const role = await readOrgMemberRole(orgId, email);
|
|
41
31
|
return role === "owner" || role === "admin";
|
|
42
32
|
}
|
|
43
33
|
catch {
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
import { getDbExec } from "../../db/client.js";
|
|
15
15
|
import { isMissingOrganizationTableError } from "../../org/membership.js";
|
|
16
16
|
import { CREDENTIAL_MEMBERSHIP_UNAVAILABLE_MESSAGE } from "../../server/credential-membership-unavailable.js";
|
|
17
|
+
import { readOrgMemberRole } from "../../server/personal-provider-key-policy.js";
|
|
18
|
+
import { getRequestContext } from "../../server/request-context.js";
|
|
17
19
|
export const SERVICE_TOKEN_MANAGE_FORBIDDEN_MESSAGE = "Only org owners or admins can create or revoke service tokens.";
|
|
18
20
|
export class ServiceTokenError extends Error {
|
|
19
21
|
statusCode;
|
|
@@ -24,17 +26,7 @@ export class ServiceTokenError extends Error {
|
|
|
24
26
|
}
|
|
25
27
|
}
|
|
26
28
|
async function readOrgRole(orgId, email) {
|
|
27
|
-
|
|
28
|
-
sql: `SELECT role FROM org_members
|
|
29
|
-
WHERE org_id = ? AND LOWER(email) = ?
|
|
30
|
-
AND federation_removal_pending_at IS NULL
|
|
31
|
-
LIMIT 1`,
|
|
32
|
-
args: [orgId, email.toLowerCase()],
|
|
33
|
-
});
|
|
34
|
-
const role = rows[0]?.role;
|
|
35
|
-
return role === "owner" || role === "admin" || role === "member"
|
|
36
|
-
? role
|
|
37
|
-
: null;
|
|
29
|
+
return readOrgMemberRole(orgId, email);
|
|
38
30
|
}
|
|
39
31
|
export async function getOrgRoleForEmail(orgId, email) {
|
|
40
32
|
try {
|
|
@@ -76,6 +68,18 @@ export async function requireServiceTokenCaller(params) {
|
|
|
76
68
|
throw new ServiceTokenError("Sign in to manage org service tokens.", 401);
|
|
77
69
|
}
|
|
78
70
|
let orgId = params.orgId?.trim() || "";
|
|
71
|
+
const requestContext = getRequestContext();
|
|
72
|
+
if (requestContext?.a2aIdentityAssurance === "org-member") {
|
|
73
|
+
const delegatedEmail = requestContext.userEmail?.trim().toLowerCase();
|
|
74
|
+
const delegatedOrgId = requestContext.orgId?.trim();
|
|
75
|
+
if (!delegatedEmail ||
|
|
76
|
+
delegatedEmail !== email.toLowerCase() ||
|
|
77
|
+
!delegatedOrgId ||
|
|
78
|
+
(orgId && orgId !== delegatedOrgId)) {
|
|
79
|
+
throw new ServiceTokenError("You are not a member of this organization.", 403);
|
|
80
|
+
}
|
|
81
|
+
orgId = delegatedOrgId;
|
|
82
|
+
}
|
|
79
83
|
if (!orgId) {
|
|
80
84
|
const memberOrgs = await lookupMembership(() => readOrgIds(email), []);
|
|
81
85
|
if (memberOrgs.length === 0) {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { getDbExec } from "../db/client.js";
|
|
2
2
|
import { identityCredentialLockKey, readEmailRetiredAt, } from "../identity/retired-emails.js";
|
|
3
|
+
import { effectiveOrgMemberRole } from "../server/personal-provider-key-policy.js";
|
|
4
|
+
import { getRequestContext } from "../server/request-context.js";
|
|
3
5
|
import { checkCredentialOrgMembership } from "./credential-membership.js";
|
|
4
6
|
export class McpCredentialIssuanceError extends Error {
|
|
5
7
|
reason;
|
|
@@ -19,6 +21,11 @@ export async function withMcpCredentialIssuance(input, run) {
|
|
|
19
21
|
const email = input.email.trim().toLowerCase();
|
|
20
22
|
const human = input.kind !== "service";
|
|
21
23
|
const requiresMembership = orgId !== null && human;
|
|
24
|
+
if (getRequestContext()?.a2aIdentityAssurance === "org-member") {
|
|
25
|
+
if (!orgId || !effectiveOrgMemberRole("member", orgId, email)) {
|
|
26
|
+
throw new McpCredentialIssuanceError("not-member");
|
|
27
|
+
}
|
|
28
|
+
}
|
|
22
29
|
if (requiresMembership) {
|
|
23
30
|
// Federation validation may update membership on another connection.
|
|
24
31
|
// Finish it before acquiring the local offboarding lock.
|
|
@@ -60,9 +67,9 @@ export async function withMcpCredentialIssuance(input, run) {
|
|
|
60
67
|
FOR UPDATE`,
|
|
61
68
|
args: [orgId, email],
|
|
62
69
|
});
|
|
70
|
+
const role = effectiveOrgMemberRole(rows[0]?.role, orgId, email);
|
|
63
71
|
if (rows.length === 0 ||
|
|
64
|
-
(input.roles &&
|
|
65
|
-
!input.roles.includes(String(rows[0].role)))) {
|
|
72
|
+
(input.roles && !input.roles.includes(role))) {
|
|
66
73
|
throw new McpCredentialIssuanceError("not-member");
|
|
67
74
|
}
|
|
68
75
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export declare function createNotificationsHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<"" | import("./types.js").Notification[] | {
|
|
2
2
|
count: number;
|
|
3
|
+
updated?: undefined;
|
|
3
4
|
error?: undefined;
|
|
4
5
|
ok?: undefined;
|
|
5
|
-
updated?: undefined;
|
|
6
6
|
} | {
|
|
7
7
|
count?: undefined;
|
|
8
8
|
updated: number;
|
|
@@ -10,12 +10,12 @@ export declare function createNotificationsHandler(): import("h3").EventHandlerW
|
|
|
10
10
|
ok?: undefined;
|
|
11
11
|
} | {
|
|
12
12
|
count?: undefined;
|
|
13
|
+
updated?: undefined;
|
|
13
14
|
error: string;
|
|
14
15
|
ok?: undefined;
|
|
15
|
-
updated?: undefined;
|
|
16
16
|
} | {
|
|
17
17
|
count?: undefined;
|
|
18
|
+
updated?: undefined;
|
|
18
19
|
ok: boolean;
|
|
19
20
|
error?: undefined;
|
|
20
|
-
updated?: undefined;
|
|
21
21
|
}>>;
|
package/dist/org/actions.d.ts
CHANGED
package/dist/org/actions.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { fail } from "../action.js";
|
|
2
|
-
import {
|
|
2
|
+
import { readOrgMemberRole } from "../server/personal-provider-key-policy.js";
|
|
3
3
|
export async function requireOrgMember(ctx, admin = false) {
|
|
4
4
|
const email = ctx?.userEmail?.trim();
|
|
5
5
|
const orgId = ctx?.orgId?.trim();
|
|
@@ -8,11 +8,7 @@ export async function requireOrgMember(ctx, admin = false) {
|
|
|
8
8
|
errorCode: "unauthorized",
|
|
9
9
|
statusCode: 401,
|
|
10
10
|
});
|
|
11
|
-
const
|
|
12
|
-
sql: `SELECT role FROM org_members WHERE org_id = ? AND LOWER(email) = LOWER(?) AND federation_removal_pending_at IS NULL LIMIT 1`,
|
|
13
|
-
args: [orgId, email],
|
|
14
|
-
});
|
|
15
|
-
const role = rows[0]?.role;
|
|
11
|
+
const role = await readOrgMemberRole(orgId, email);
|
|
16
12
|
if (!role)
|
|
17
13
|
fail("You are not a member of the active organization.", {
|
|
18
14
|
errorCode: "forbidden",
|
|
@@ -23,5 +19,5 @@ export async function requireOrgMember(ctx, admin = false) {
|
|
|
23
19
|
errorCode: "forbidden",
|
|
24
20
|
statusCode: 403,
|
|
25
21
|
});
|
|
26
|
-
return { email, orgId, role
|
|
22
|
+
return { email, orgId, role };
|
|
27
23
|
}
|
package/dist/org/app-roles.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getDbExec } from "../db/client.js";
|
|
2
|
-
import {
|
|
2
|
+
import { effectiveOrgMemberRole } from "../server/personal-provider-key-policy.js";
|
|
3
|
+
import { getRequestContext, getRequestOrgId, getRequestUserEmail, } from "../server/request-context.js";
|
|
3
4
|
import { ForbiddenError } from "../sharing/access.js";
|
|
4
5
|
import { isMissingOrganizationTableError } from "./membership.js";
|
|
5
6
|
const registry = new Map();
|
|
@@ -137,6 +138,9 @@ export async function resolveAppRole(descriptor, caller) {
|
|
|
137
138
|
return { status: "no-identity" };
|
|
138
139
|
if (!orgId)
|
|
139
140
|
return { status: "no-org" };
|
|
141
|
+
if (!effectiveOrgMemberRole("member", orgId, email)) {
|
|
142
|
+
return { status: "not-a-member", orgId };
|
|
143
|
+
}
|
|
140
144
|
let rows;
|
|
141
145
|
try {
|
|
142
146
|
rows = (await getDbExec().execute({
|
|
@@ -187,6 +191,11 @@ export async function resolveAppRole(descriptor, caller) {
|
|
|
187
191
|
return { status: "not-a-member", orgId };
|
|
188
192
|
orgRole = membership.role;
|
|
189
193
|
}
|
|
194
|
+
const isDelegatedOrgMember = getRequestContext()?.a2aIdentityAssurance === "org-member";
|
|
195
|
+
orgRole = effectiveOrgMemberRole(orgRole, orgId, email) ?? undefined;
|
|
196
|
+
if (isDelegatedOrgMember && !orgRole) {
|
|
197
|
+
return { status: "not-a-member", orgId };
|
|
198
|
+
}
|
|
190
199
|
const raw = row.roles ?? row.appRoles ?? row.approles;
|
|
191
200
|
const roles = Array.isArray(raw) ? raw.map(String) : [];
|
|
192
201
|
const validRoles = [
|
package/dist/org/context.d.ts
CHANGED
|
@@ -85,5 +85,6 @@ export declare function resolveA2AOrganizationCredentialsByDomain(domain: string
|
|
|
85
85
|
orgId: string;
|
|
86
86
|
orgDomain: string;
|
|
87
87
|
secret: string;
|
|
88
|
+
a2aMemberDelegationEnabled: boolean;
|
|
88
89
|
} | null>;
|
|
89
90
|
export declare function isSoleOrgDomain(domain: string): Promise<boolean>;
|
package/dist/org/context.js
CHANGED
|
@@ -7,6 +7,7 @@ import { getDbExec, isTransientDatabaseError } from "../db/client.js";
|
|
|
7
7
|
import { isAnonymousWaitlistSessionEmail } from "../server/anonymous-identity.js";
|
|
8
8
|
import { crossSiteCookieAttrs, getSession } from "../server/auth.js";
|
|
9
9
|
import { shouldWriteFirstRunOnboardingEligibility } from "../server/first-run-onboarding-build-mode.js";
|
|
10
|
+
import { effectiveOrgMemberRole, readOrgMemberRole, } from "../server/personal-provider-key-policy.js";
|
|
10
11
|
import { getVerifiedServiceIdentityFromEvent, getRequestContext, hasExplicitPersonalOrgScope, } from "../server/request-context.js";
|
|
11
12
|
import { getSetting } from "../settings/store.js";
|
|
12
13
|
import { getUserSetting } from "../settings/user-settings.js";
|
|
@@ -46,6 +47,32 @@ function normalizeOrgRole(value) {
|
|
|
46
47
|
? value
|
|
47
48
|
: null;
|
|
48
49
|
}
|
|
50
|
+
function delegatedOrgMemberScope(email) {
|
|
51
|
+
const requestContext = getRequestContext();
|
|
52
|
+
if (requestContext?.a2aIdentityAssurance !== "org-member")
|
|
53
|
+
return undefined;
|
|
54
|
+
const requestEmail = requestContext.userEmail?.trim().toLowerCase();
|
|
55
|
+
const requestOrgId = requestContext.orgId?.trim();
|
|
56
|
+
if (!requestEmail ||
|
|
57
|
+
!requestOrgId ||
|
|
58
|
+
(email && email.trim().toLowerCase() !== requestEmail)) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
return requestOrgId;
|
|
62
|
+
}
|
|
63
|
+
function scopeMembershipsForDelegatedIdentity(email, memberships) {
|
|
64
|
+
const scopedOrgId = delegatedOrgMemberScope(email);
|
|
65
|
+
if (scopedOrgId === undefined || memberships === null)
|
|
66
|
+
return memberships;
|
|
67
|
+
if (!scopedOrgId)
|
|
68
|
+
return [];
|
|
69
|
+
return memberships.flatMap((membership) => {
|
|
70
|
+
if (membership.orgId !== scopedOrgId)
|
|
71
|
+
return [];
|
|
72
|
+
const role = effectiveOrgMemberRole(membership.role, scopedOrgId, email);
|
|
73
|
+
return role ? [{ ...membership, role }] : [];
|
|
74
|
+
});
|
|
75
|
+
}
|
|
49
76
|
function emailDomainOf(email) {
|
|
50
77
|
return email.split("@")[1]?.toLowerCase() || null;
|
|
51
78
|
}
|
|
@@ -94,10 +121,13 @@ async function refreshFederatedMemberships(event, email, memberships, selectedOr
|
|
|
94
121
|
if (!result.active) {
|
|
95
122
|
return memberships.filter((item) => item.orgId !== selected.orgId);
|
|
96
123
|
}
|
|
97
|
-
|
|
124
|
+
const role = effectiveOrgMemberRole(result.role, selected.orgId, email);
|
|
125
|
+
if (!role)
|
|
126
|
+
return memberships.filter((item) => item.orgId !== selected.orgId);
|
|
127
|
+
if (role === selected.role) {
|
|
98
128
|
return memberships;
|
|
99
129
|
}
|
|
100
|
-
return memberships.map((item) => item.orgId === selected.orgId ? { ...item, role
|
|
130
|
+
return memberships.map((item) => item.orgId === selected.orgId ? { ...item, role } : item);
|
|
101
131
|
}
|
|
102
132
|
const MEMBERSHIPS_CACHE_KEY = "__anOrgMembershipsCache";
|
|
103
133
|
const ACTIVE_ORG_SETTING_CACHE_KEY = "__anActiveOrgSettingCache";
|
|
@@ -143,12 +173,19 @@ export function markActiveOrgSelectionChanged(event) {
|
|
|
143
173
|
});
|
|
144
174
|
}
|
|
145
175
|
function loadMembershipsForEvent(event, email) {
|
|
176
|
+
const scopedOrgId = delegatedOrgMemberScope(email);
|
|
177
|
+
if (scopedOrgId === null)
|
|
178
|
+
return Promise.resolve([]);
|
|
146
179
|
const ctx = event.context;
|
|
147
180
|
const cache = (ctx[MEMBERSHIPS_CACHE_KEY] ??
|
|
148
181
|
(ctx[MEMBERSHIPS_CACHE_KEY] = new Map()));
|
|
149
182
|
let promise = cache.get(email);
|
|
150
183
|
if (!promise) {
|
|
151
|
-
promise = loadMemberships(email)
|
|
184
|
+
promise = loadMemberships(email)
|
|
185
|
+
.then((memberships) => scopedOrgId === undefined
|
|
186
|
+
? memberships
|
|
187
|
+
: scopeMembershipsForDelegatedIdentity(email, memberships))
|
|
188
|
+
.catch((err) => {
|
|
152
189
|
cache.delete(email);
|
|
153
190
|
throw err;
|
|
154
191
|
});
|
|
@@ -166,17 +203,25 @@ async function resolveOrgContextUncached(event) {
|
|
|
166
203
|
const email = session?.email;
|
|
167
204
|
if (!email)
|
|
168
205
|
return EMPTY_CONTEXT;
|
|
206
|
+
const requestContext = getRequestContext();
|
|
207
|
+
const isDelegatedOrgMember = requestContext?.a2aIdentityAssurance === "org-member";
|
|
208
|
+
const delegatedOrgId = delegatedOrgMemberScope(email);
|
|
209
|
+
if (isDelegatedOrgMember && !delegatedOrgId) {
|
|
210
|
+
return { email, orgId: null, orgName: null, role: null };
|
|
211
|
+
}
|
|
169
212
|
if (isAnonymousWaitlistSessionEmail(email)) {
|
|
170
213
|
return { email, orgId: null, orgName: null, role: null };
|
|
171
214
|
}
|
|
172
|
-
if (hasExplicitPersonalOrgScope(event)) {
|
|
215
|
+
if (!isDelegatedOrgMember && hasExplicitPersonalOrgScope(event)) {
|
|
173
216
|
return { email, orgId: null, orgName: null, role: null };
|
|
174
217
|
}
|
|
175
|
-
const sessionOrgId =
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
const
|
|
218
|
+
const sessionOrgId = delegatedOrgId ??
|
|
219
|
+
(typeof session.orgId === "string" && session.orgId.trim()
|
|
220
|
+
? session.orgId.trim()
|
|
221
|
+
: null);
|
|
222
|
+
const sessionOrgRole = isDelegatedOrgMember
|
|
223
|
+
? "member"
|
|
224
|
+
: normalizeOrgRole(session.orgRole);
|
|
180
225
|
const verifiedServiceIdentity = getVerifiedServiceIdentityFromEvent(event);
|
|
181
226
|
const serviceRole = implicitServiceOrgRole({
|
|
182
227
|
email,
|
|
@@ -209,7 +254,9 @@ async function resolveOrgContextUncached(event) {
|
|
|
209
254
|
}
|
|
210
255
|
}
|
|
211
256
|
const exec = getDbExec();
|
|
212
|
-
const activeOrgSettingPromise =
|
|
257
|
+
const activeOrgSettingPromise = isDelegatedOrgMember
|
|
258
|
+
? Promise.resolve(null)
|
|
259
|
+
: loadActiveOrgSettingForEvent(event, email);
|
|
213
260
|
activeOrgSettingPromise.catch(() => { });
|
|
214
261
|
let memberships;
|
|
215
262
|
try {
|
|
@@ -219,6 +266,10 @@ async function resolveOrgContextUncached(event) {
|
|
|
219
266
|
// A transient membership read must not downgrade an authenticated request
|
|
220
267
|
// to a private/solo scope when the session already carries its org.
|
|
221
268
|
if (sessionOrgId && isTransientDatabaseError(err)) {
|
|
269
|
+
if (isDelegatedOrgMember) {
|
|
270
|
+
markOrgScopeResolutionUnavailable(event);
|
|
271
|
+
return { email, orgId: null, orgName: null, role: null };
|
|
272
|
+
}
|
|
222
273
|
return {
|
|
223
274
|
email,
|
|
224
275
|
orgId: sessionOrgId,
|
|
@@ -231,6 +282,9 @@ async function resolveOrgContextUncached(event) {
|
|
|
231
282
|
if (memberships === null) {
|
|
232
283
|
// A null membership read is unavailable scope, not proof of a solo user.
|
|
233
284
|
markOrgScopeResolutionUnavailable(event);
|
|
285
|
+
if (isDelegatedOrgMember) {
|
|
286
|
+
return { email, orgId: null, orgName: null, role: null };
|
|
287
|
+
}
|
|
234
288
|
if (sessionOrgId) {
|
|
235
289
|
return {
|
|
236
290
|
email,
|
|
@@ -242,16 +296,18 @@ async function resolveOrgContextUncached(event) {
|
|
|
242
296
|
return { email, orgId: null, orgName: null, role: null };
|
|
243
297
|
}
|
|
244
298
|
const activeOrgSetting = await activeOrgSettingPromise;
|
|
245
|
-
const explicitPersonal = activeOrgSetting?.orgId === null;
|
|
246
|
-
const selectedMembership =
|
|
247
|
-
?
|
|
248
|
-
:
|
|
249
|
-
?
|
|
250
|
-
:
|
|
251
|
-
|
|
252
|
-
? memberships.find((membership) => membership.orgId === sessionOrgId)
|
|
299
|
+
const explicitPersonal = !isDelegatedOrgMember && activeOrgSetting?.orgId === null;
|
|
300
|
+
const selectedMembership = isDelegatedOrgMember
|
|
301
|
+
? memberships.find((membership) => membership.orgId === delegatedOrgId)
|
|
302
|
+
: explicitPersonal
|
|
303
|
+
? undefined
|
|
304
|
+
: ((activeOrgSetting?.orgId
|
|
305
|
+
? memberships.find((membership) => membership.orgId === activeOrgSetting.orgId)
|
|
253
306
|
: undefined) ??
|
|
254
|
-
|
|
307
|
+
(sessionOrgId
|
|
308
|
+
? memberships.find((membership) => membership.orgId === sessionOrgId)
|
|
309
|
+
: undefined) ??
|
|
310
|
+
memberships[0]);
|
|
255
311
|
const selectedOrgId = selectedMembership?.orgId ?? null;
|
|
256
312
|
const selectedWasFederated = Boolean(selectedMembership?.identityAuthority || selectedMembership?.identityId);
|
|
257
313
|
const refreshedMemberships = await refreshFederatedMemberships(event, email, memberships, selectedOrgId);
|
|
@@ -268,7 +324,8 @@ async function resolveOrgContextUncached(event) {
|
|
|
268
324
|
markFederationMembershipValidated(event, email, selectedOrgId);
|
|
269
325
|
}
|
|
270
326
|
const emailDomain = emailDomainOf(email);
|
|
271
|
-
const shouldTryDomainAutoJoin = !
|
|
327
|
+
const shouldTryDomainAutoJoin = !isDelegatedOrgMember &&
|
|
328
|
+
!explicitPersonal &&
|
|
272
329
|
session.emailVerified === true &&
|
|
273
330
|
emailDomain !== null &&
|
|
274
331
|
!isFreeEmailProvider(emailDomain) &&
|
|
@@ -358,7 +415,9 @@ async function resolveOrgContextUncached(event) {
|
|
|
358
415
|
}
|
|
359
416
|
return { email, orgId: null, orgName: null, role: null };
|
|
360
417
|
}
|
|
361
|
-
if (
|
|
418
|
+
if (!isDelegatedOrgMember &&
|
|
419
|
+
memberships.length === 0 &&
|
|
420
|
+
autoCreateDefaultOrgEnabled()) {
|
|
362
421
|
const created = await tryCreateDefaultOrg(exec, email, session, event);
|
|
363
422
|
if (created)
|
|
364
423
|
return created;
|
|
@@ -381,7 +440,8 @@ async function loadMemberships(email) {
|
|
|
381
440
|
return cachedMemberships(email, () => loadMembershipsUncached(email));
|
|
382
441
|
}
|
|
383
442
|
export async function listOrgMemberships(email) {
|
|
384
|
-
|
|
443
|
+
const memberships = await loadMemberships(email);
|
|
444
|
+
return scopeMembershipsForDelegatedIdentity(email, memberships);
|
|
385
445
|
}
|
|
386
446
|
export async function listOrgMembershipsForEvent(event, email, selectedOrgId) {
|
|
387
447
|
const memberships = await loadMembershipsForEvent(event, email);
|
|
@@ -423,6 +483,15 @@ async function loadMembershipsUncached(email) {
|
|
|
423
483
|
}) ?? null);
|
|
424
484
|
}
|
|
425
485
|
export async function resolveOrgScopeForEmail(email) {
|
|
486
|
+
const delegatedOrgId = delegatedOrgMemberScope(email);
|
|
487
|
+
if (delegatedOrgId !== undefined) {
|
|
488
|
+
if (!delegatedOrgId)
|
|
489
|
+
return { status: "unknown" };
|
|
490
|
+
const role = await readOrgMemberRole(delegatedOrgId, email);
|
|
491
|
+
return role
|
|
492
|
+
? { status: "organization", orgId: delegatedOrgId }
|
|
493
|
+
: { status: "unknown" };
|
|
494
|
+
}
|
|
426
495
|
if (getRequestContext()?.orgScope === "personal") {
|
|
427
496
|
return { status: "personal" };
|
|
428
497
|
}
|
|
@@ -457,6 +526,13 @@ export async function resolveActiveOrgIdForStorageCredential(email) {
|
|
|
457
526
|
const normalizedEmail = email.trim().toLowerCase();
|
|
458
527
|
if (!normalizedEmail)
|
|
459
528
|
return null;
|
|
529
|
+
const delegatedOrgId = delegatedOrgMemberScope(normalizedEmail);
|
|
530
|
+
if (delegatedOrgId !== undefined) {
|
|
531
|
+
if (!delegatedOrgId)
|
|
532
|
+
return null;
|
|
533
|
+
const role = await readOrgMemberRole(delegatedOrgId, normalizedEmail);
|
|
534
|
+
return role ? delegatedOrgId : null;
|
|
535
|
+
}
|
|
460
536
|
const { rows } = await getDbExec().execute({
|
|
461
537
|
sql: `SELECT m.org_id AS "orgId"
|
|
462
538
|
FROM org_members m
|
|
@@ -476,6 +552,22 @@ export async function resolveActiveOrgIdForStorageCredential(email) {
|
|
|
476
552
|
return rows.some((row) => row.orgId === activeOrgId) ? activeOrgId : null;
|
|
477
553
|
}
|
|
478
554
|
export async function resolveOrgIdForEmailViaEvent(event, email) {
|
|
555
|
+
const delegatedOrgId = delegatedOrgMemberScope(email);
|
|
556
|
+
if (delegatedOrgId !== undefined) {
|
|
557
|
+
if (!delegatedOrgId)
|
|
558
|
+
return null;
|
|
559
|
+
const memberships = await loadMembershipsForEvent(event, email);
|
|
560
|
+
if (!memberships || !memberships.some((m) => m.orgId === delegatedOrgId)) {
|
|
561
|
+
return null;
|
|
562
|
+
}
|
|
563
|
+
const refreshed = await refreshFederatedMemberships(event, email, memberships, delegatedOrgId);
|
|
564
|
+
if (refreshed !== memberships) {
|
|
565
|
+
updateMembershipsForEvent(event, email, refreshed);
|
|
566
|
+
}
|
|
567
|
+
return refreshed.some((m) => m.orgId === delegatedOrgId)
|
|
568
|
+
? delegatedOrgId
|
|
569
|
+
: null;
|
|
570
|
+
}
|
|
479
571
|
if (getRequestContext()?.orgScope === "personal")
|
|
480
572
|
return null;
|
|
481
573
|
const settingPromise = loadActiveOrgSettingForEvent(event, email);
|
|
@@ -842,7 +934,8 @@ export async function resolveA2AOrganizationCredentialsByDomain(domain) {
|
|
|
842
934
|
if (!normalizedDomain)
|
|
843
935
|
return null;
|
|
844
936
|
const { rows } = await getDbExec().execute({
|
|
845
|
-
sql: `SELECT id, allowed_domain, a2a_secret
|
|
937
|
+
sql: `SELECT id, allowed_domain, a2a_secret,
|
|
938
|
+
a2a_member_delegation_enabled
|
|
846
939
|
FROM organizations WHERE LOWER(allowed_domain) = ? LIMIT 2`,
|
|
847
940
|
args: [normalizedDomain],
|
|
848
941
|
});
|
|
@@ -858,7 +951,12 @@ export async function resolveA2AOrganizationCredentialsByDomain(domain) {
|
|
|
858
951
|
const secret = String(row.a2a_secret ?? "").trim();
|
|
859
952
|
if (!orgId || orgDomain !== normalizedDomain || !secret)
|
|
860
953
|
return null;
|
|
861
|
-
return {
|
|
954
|
+
return {
|
|
955
|
+
orgId,
|
|
956
|
+
orgDomain,
|
|
957
|
+
secret,
|
|
958
|
+
a2aMemberDelegationEnabled: row.a2a_member_delegation_enabled === true,
|
|
959
|
+
};
|
|
862
960
|
}
|
|
863
961
|
export async function isSoleOrgDomain(domain) {
|
|
864
962
|
try {
|
package/dist/org/federation.d.ts
CHANGED
|
@@ -52,7 +52,7 @@ export declare function validateFederatedOrganizationMembership(event: H3Event |
|
|
|
52
52
|
export declare function validateFederatedOrganizationMembershipForCurrentRequest(input: {
|
|
53
53
|
orgId: string;
|
|
54
54
|
email: string;
|
|
55
|
-
}): Promise<FederatedMembershipValidation>;
|
|
55
|
+
}, event?: H3Event): Promise<FederatedMembershipValidation>;
|
|
56
56
|
export declare function syncOrganizationToIdentityHub(event: H3Event, input: FederatedOrganizationSyncInput): Promise<boolean>;
|
|
57
57
|
export declare function provisionFederatedOrganization(identity: FederatedOrganizationIdentity, options?: {
|
|
58
58
|
/** The signing-in caller's request; see `setActiveOrgId`. */
|
package/dist/org/federation.js
CHANGED
|
@@ -408,8 +408,8 @@ export async function validateFederatedOrganizationMembership(event, input) {
|
|
|
408
408
|
}
|
|
409
409
|
return { active: true, role: body.memberRole };
|
|
410
410
|
}
|
|
411
|
-
export async function validateFederatedOrganizationMembershipForCurrentRequest(input) {
|
|
412
|
-
return validateFederatedOrganizationMembership(requestEventFromContext(), input);
|
|
411
|
+
export async function validateFederatedOrganizationMembershipForCurrentRequest(input, event) {
|
|
412
|
+
return validateFederatedOrganizationMembership(event ?? requestEventFromContext(), input);
|
|
413
413
|
}
|
|
414
414
|
export async function syncOrganizationToIdentityHub(event, input) {
|
|
415
415
|
const rollout = await federationRolloutState(input.email, input.id);
|