@agent-native/core 0.98.5 → 0.98.6
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/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +12 -0
- package/corpus/core/docs/content/external-agents.mdx +62 -7
- package/corpus/core/docs/content/locales/ar-SA/external-agents.mdx +38 -7
- package/corpus/core/docs/content/locales/de-DE/external-agents.mdx +39 -7
- package/corpus/core/docs/content/locales/es-ES/external-agents.mdx +39 -7
- package/corpus/core/docs/content/locales/fr-FR/external-agents.mdx +39 -7
- package/corpus/core/docs/content/locales/hi-IN/external-agents.mdx +38 -7
- package/corpus/core/docs/content/locales/ja-JP/external-agents.mdx +38 -7
- package/corpus/core/docs/content/locales/ko-KR/external-agents.mdx +38 -7
- package/corpus/core/docs/content/locales/pt-BR/external-agents.mdx +39 -7
- package/corpus/core/docs/content/locales/zh-CN/external-agents.mdx +37 -7
- package/corpus/core/docs/content/locales/zh-TW/external-agents.mdx +37 -7
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/a2a/handlers.ts +95 -21
- package/corpus/core/src/a2a/task-store.ts +65 -3
- package/corpus/core/src/integrations/adapters/slack.ts +123 -13
- package/corpus/core/src/integrations/identity-links-store.ts +210 -0
- package/corpus/core/src/integrations/identity.ts +132 -0
- package/corpus/core/src/integrations/index.ts +6 -0
- package/corpus/core/src/integrations/plugin.ts +58 -1
- package/corpus/core/src/integrations/types.ts +7 -0
- package/corpus/core/src/mcp/build-server.ts +127 -22
- package/corpus/core/src/mcp/external-agent-policy.ts +18 -0
- package/corpus/core/src/mcp/index.ts +1 -0
- package/corpus/core/src/server/agent-chat/plugin-options.ts +12 -1
- package/corpus/core/src/server/agent-chat/script-entries.ts +20 -3
- package/corpus/core/src/server/agent-chat-plugin.ts +3 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +34 -5
- package/corpus/templates/analytics/AGENTS.md +20 -5
- package/corpus/templates/analytics/actions/create-session-replay-agent-link.ts +0 -1
- package/corpus/templates/analytics/actions/get-session-replay-events.ts +0 -1
- package/corpus/templates/analytics/actions/get-session-replay-timeline.ts +40 -0
- package/corpus/templates/analytics/actions/list-error-issues.ts +12 -0
- package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +4 -1
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +48 -17
- package/corpus/templates/analytics/changelog/2026-07-12-connected-external-agents-can-now-look-up-sessions-error-iss.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-12-session-identities-stay-visible-when-demo-mode-is-off.md +6 -0
- package/corpus/templates/analytics/server/lib/analytics-connector-catalog.ts +2 -2
- package/corpus/templates/analytics/server/lib/error-capture.ts +47 -5
- package/corpus/templates/analytics/server/lib/session-replay-agent-context.ts +49 -17
- package/corpus/templates/analytics/server/lib/session-replay.ts +16 -7
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +4 -0
- package/corpus/templates/analytics/server/plugins/db.ts +15 -0
- package/corpus/templates/forms/app/global.css +54 -8
- package/corpus/templates/forms/app/pages/AskPage.tsx +35 -13
- package/corpus/templates/forms/app/pages/FormBuilderPage.tsx +11 -17
- package/corpus/templates/forms/app/pages/ResponsesPage.tsx +8 -5
- package/corpus/templates/forms/changelog/2026-07-12-ask-forms-suggestions-now-sit-beneath-the-composer-for-a-tig.md +6 -0
- package/corpus/templates/forms/changelog/2026-07-12-builder-response-tables-now-fill-the-view-without-a-redundan.md +6 -0
- package/corpus/templates/forms/changelog/2026-07-12-response-tables-now-fill-the-available-pane-with-a-flexible-.md +6 -0
- package/corpus/templates/mail/AGENTS.md +3 -1
- package/corpus/templates/mail/server/lib/mail-integrations.ts +3 -0
- package/dist/a2a/handlers.d.ts.map +1 -1
- package/dist/a2a/handlers.js +84 -15
- package/dist/a2a/handlers.js.map +1 -1
- package/dist/a2a/task-store.d.ts +20 -1
- package/dist/a2a/task-store.d.ts.map +1 -1
- package/dist/a2a/task-store.js +57 -4
- package/dist/a2a/task-store.js.map +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/integrations/adapters/slack.d.ts.map +1 -1
- package/dist/integrations/adapters/slack.js +98 -13
- package/dist/integrations/adapters/slack.js.map +1 -1
- package/dist/integrations/identity-links-store.d.ts +23 -0
- package/dist/integrations/identity-links-store.d.ts.map +1 -0
- package/dist/integrations/identity-links-store.js +158 -0
- package/dist/integrations/identity-links-store.js.map +1 -0
- package/dist/integrations/identity.d.ts +11 -0
- package/dist/integrations/identity.d.ts.map +1 -0
- package/dist/integrations/identity.js +100 -0
- package/dist/integrations/identity.js.map +1 -0
- package/dist/integrations/index.d.ts +2 -0
- package/dist/integrations/index.d.ts.map +1 -1
- package/dist/integrations/index.js +2 -0
- package/dist/integrations/index.js.map +1 -1
- package/dist/integrations/plugin.d.ts.map +1 -1
- package/dist/integrations/plugin.js +43 -1
- package/dist/integrations/plugin.js.map +1 -1
- package/dist/integrations/types.d.ts +6 -0
- package/dist/integrations/types.d.ts.map +1 -1
- package/dist/integrations/types.js.map +1 -1
- package/dist/mcp/build-server.d.ts +9 -2
- package/dist/mcp/build-server.d.ts.map +1 -1
- package/dist/mcp/build-server.js +97 -20
- package/dist/mcp/build-server.js.map +1 -1
- package/dist/mcp/external-agent-policy.d.ts +19 -0
- package/dist/mcp/external-agent-policy.d.ts.map +1 -0
- package/dist/mcp/external-agent-policy.js +2 -0
- package/dist/mcp/external-agent-policy.js.map +1 -0
- package/dist/mcp/index.d.ts +1 -0
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js.map +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/resources/handlers.d.ts +3 -3
- package/dist/server/agent-chat/plugin-options.d.ts +11 -1
- package/dist/server/agent-chat/plugin-options.d.ts.map +1 -1
- package/dist/server/agent-chat/plugin-options.js.map +1 -1
- package/dist/server/agent-chat/script-entries.d.ts.map +1 -1
- package/dist/server/agent-chat/script-entries.js +16 -2
- package/dist/server/agent-chat/script-entries.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +3 -0
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/templates/workspace-core/.agents/skills/external-agents/SKILL.md +34 -5
- package/docs/content/external-agents.mdx +62 -7
- package/docs/content/locales/ar-SA/external-agents.mdx +38 -7
- package/docs/content/locales/de-DE/external-agents.mdx +39 -7
- package/docs/content/locales/es-ES/external-agents.mdx +39 -7
- package/docs/content/locales/fr-FR/external-agents.mdx +39 -7
- package/docs/content/locales/hi-IN/external-agents.mdx +38 -7
- package/docs/content/locales/ja-JP/external-agents.mdx +38 -7
- package/docs/content/locales/ko-KR/external-agents.mdx +38 -7
- package/docs/content/locales/pt-BR/external-agents.mdx +39 -7
- package/docs/content/locales/zh-CN/external-agents.mdx +37 -7
- package/docs/content/locales/zh-TW/external-agents.mdx +37 -7
- package/package.json +1 -1
- package/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +34 -5
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Durable links between a verified provider identity and an Agent Native user.
|
|
3
|
+
* Provider credentials and raw provider payloads never belong in this table.
|
|
4
|
+
*/
|
|
5
|
+
import { randomUUID } from "node:crypto";
|
|
6
|
+
import { getDbExec, intType, isPostgres, isUniqueViolation, retryOnDdlRace, } from "../db/client.js";
|
|
7
|
+
import { ensureIndexExists, ensureTableExists } from "../db/ddl-guard.js";
|
|
8
|
+
const TABLE = "integration_identity_links";
|
|
9
|
+
let _initPromise;
|
|
10
|
+
function createSql() {
|
|
11
|
+
const integer = intType();
|
|
12
|
+
return `CREATE TABLE IF NOT EXISTS ${TABLE} (
|
|
13
|
+
id TEXT PRIMARY KEY,
|
|
14
|
+
platform TEXT NOT NULL,
|
|
15
|
+
tenant_id TEXT NOT NULL,
|
|
16
|
+
external_user_id TEXT NOT NULL,
|
|
17
|
+
user_email TEXT NOT NULL,
|
|
18
|
+
org_id TEXT NOT NULL,
|
|
19
|
+
created_at ${integer} NOT NULL,
|
|
20
|
+
updated_at ${integer} NOT NULL
|
|
21
|
+
)`;
|
|
22
|
+
}
|
|
23
|
+
const INDEXES = [
|
|
24
|
+
[
|
|
25
|
+
"idx_integration_identity_links_external",
|
|
26
|
+
`CREATE UNIQUE INDEX IF NOT EXISTS idx_integration_identity_links_external
|
|
27
|
+
ON ${TABLE}(platform, tenant_id, external_user_id)`,
|
|
28
|
+
],
|
|
29
|
+
[
|
|
30
|
+
"idx_integration_identity_links_account",
|
|
31
|
+
`CREATE INDEX IF NOT EXISTS idx_integration_identity_links_account
|
|
32
|
+
ON ${TABLE}(org_id, user_email)`,
|
|
33
|
+
],
|
|
34
|
+
];
|
|
35
|
+
async function ensureTable() {
|
|
36
|
+
if (!_initPromise) {
|
|
37
|
+
_initPromise = (async () => {
|
|
38
|
+
const client = getDbExec();
|
|
39
|
+
if (isPostgres()) {
|
|
40
|
+
await ensureTableExists(TABLE, createSql());
|
|
41
|
+
for (const [name, sql] of INDEXES) {
|
|
42
|
+
await ensureIndexExists(name, sql);
|
|
43
|
+
}
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
await retryOnDdlRace(() => client.execute(createSql()));
|
|
47
|
+
for (const [, sql] of INDEXES) {
|
|
48
|
+
await retryOnDdlRace(() => client.execute(sql));
|
|
49
|
+
}
|
|
50
|
+
})().catch((error) => {
|
|
51
|
+
_initPromise = undefined;
|
|
52
|
+
throw error;
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
return _initPromise;
|
|
56
|
+
}
|
|
57
|
+
function required(value, name) {
|
|
58
|
+
const normalized = value.trim();
|
|
59
|
+
if (!normalized)
|
|
60
|
+
throw new Error(`${name} is required`);
|
|
61
|
+
if (normalized.length > 512)
|
|
62
|
+
throw new Error(`${name} is too long`);
|
|
63
|
+
return normalized;
|
|
64
|
+
}
|
|
65
|
+
function normalizePlatform(value) {
|
|
66
|
+
return required(value, "platform").toLowerCase();
|
|
67
|
+
}
|
|
68
|
+
function normalizeEmail(value) {
|
|
69
|
+
const normalized = required(value, "userEmail").toLowerCase();
|
|
70
|
+
if (!normalized.includes("@"))
|
|
71
|
+
throw new Error("userEmail must be an email");
|
|
72
|
+
return normalized;
|
|
73
|
+
}
|
|
74
|
+
function rowToLink(row) {
|
|
75
|
+
return {
|
|
76
|
+
id: String(row.id),
|
|
77
|
+
platform: String(row.platform),
|
|
78
|
+
tenantId: String(row.tenant_id),
|
|
79
|
+
externalUserId: String(row.external_user_id),
|
|
80
|
+
userEmail: String(row.user_email),
|
|
81
|
+
orgId: String(row.org_id),
|
|
82
|
+
createdAt: Number(row.created_at ?? 0),
|
|
83
|
+
updatedAt: Number(row.updated_at ?? 0),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
async function selectByExternalIdentity(platform, tenantId, externalUserId) {
|
|
87
|
+
await ensureTable();
|
|
88
|
+
const { rows } = await getDbExec().execute({
|
|
89
|
+
sql: `SELECT * FROM ${TABLE}
|
|
90
|
+
WHERE platform = ? AND tenant_id = ? AND external_user_id = ?
|
|
91
|
+
LIMIT 1`,
|
|
92
|
+
args: [platform, tenantId, externalUserId],
|
|
93
|
+
});
|
|
94
|
+
return rows[0] ? rowToLink(rows[0]) : null;
|
|
95
|
+
}
|
|
96
|
+
function matchesVerifiedLink(row, input) {
|
|
97
|
+
return row.userEmail === input.userEmail && row.orgId === input.orgId;
|
|
98
|
+
}
|
|
99
|
+
/** Persist a verified mapping and fail closed if it changes identity later. */
|
|
100
|
+
export async function upsertVerifiedIntegrationIdentity(input) {
|
|
101
|
+
const platform = normalizePlatform(input.platform);
|
|
102
|
+
const tenantId = required(input.tenantId, "tenantId");
|
|
103
|
+
const externalUserId = required(input.externalUserId, "externalUserId");
|
|
104
|
+
const userEmail = normalizeEmail(input.userEmail);
|
|
105
|
+
const orgId = required(input.orgId, "orgId");
|
|
106
|
+
const existing = await selectByExternalIdentity(platform, tenantId, externalUserId);
|
|
107
|
+
if (existing) {
|
|
108
|
+
if (!matchesVerifiedLink(existing, { userEmail, orgId })) {
|
|
109
|
+
throw new Error("This provider identity is already linked to a different Agent Native account.");
|
|
110
|
+
}
|
|
111
|
+
const updatedAt = Date.now();
|
|
112
|
+
await getDbExec().execute({
|
|
113
|
+
sql: `UPDATE ${TABLE} SET updated_at = ? WHERE id = ?`,
|
|
114
|
+
args: [updatedAt, existing.id],
|
|
115
|
+
});
|
|
116
|
+
return { ...existing, updatedAt };
|
|
117
|
+
}
|
|
118
|
+
const id = randomUUID();
|
|
119
|
+
const now = Date.now();
|
|
120
|
+
try {
|
|
121
|
+
await getDbExec().execute({
|
|
122
|
+
sql: `INSERT INTO ${TABLE} (
|
|
123
|
+
id, platform, tenant_id, external_user_id, user_email, org_id,
|
|
124
|
+
created_at, updated_at
|
|
125
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
126
|
+
args: [
|
|
127
|
+
id,
|
|
128
|
+
platform,
|
|
129
|
+
tenantId,
|
|
130
|
+
externalUserId,
|
|
131
|
+
userEmail,
|
|
132
|
+
orgId,
|
|
133
|
+
now,
|
|
134
|
+
now,
|
|
135
|
+
],
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
if (!isUniqueViolation(error))
|
|
140
|
+
throw error;
|
|
141
|
+
const raced = await selectByExternalIdentity(platform, tenantId, externalUserId);
|
|
142
|
+
if (!raced || !matchesVerifiedLink(raced, { userEmail, orgId })) {
|
|
143
|
+
throw new Error("This provider identity is already linked to a different Agent Native account.");
|
|
144
|
+
}
|
|
145
|
+
return raced;
|
|
146
|
+
}
|
|
147
|
+
return {
|
|
148
|
+
id,
|
|
149
|
+
platform,
|
|
150
|
+
tenantId,
|
|
151
|
+
externalUserId,
|
|
152
|
+
userEmail,
|
|
153
|
+
orgId,
|
|
154
|
+
createdAt: now,
|
|
155
|
+
updatedAt: now,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=identity-links-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity-links-store.js","sourceRoot":"","sources":["../../src/integrations/identity-links-store.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Durable links between a verified provider identity and an Agent Native user.\n * Provider credentials and raw provider payloads never belong in this table.\n */\n\nimport { randomUUID } from \"node:crypto\";\n\nimport {\n getDbExec,\n intType,\n isPostgres,\n isUniqueViolation,\n retryOnDdlRace,\n} from \"../db/client.js\";\nimport { ensureIndexExists, ensureTableExists } from \"../db/ddl-guard.js\";\n\nconst TABLE = \"integration_identity_links\";\nlet _initPromise: Promise<void> | undefined;\n\nexport interface IntegrationIdentityLink {\n id: string;\n platform: string;\n tenantId: string;\n externalUserId: string;\n userEmail: string;\n orgId: string;\n createdAt: number;\n updatedAt: number;\n}\n\nfunction createSql(): string {\n const integer = intType();\n return `CREATE TABLE IF NOT EXISTS ${TABLE} (\n id TEXT PRIMARY KEY,\n platform TEXT NOT NULL,\n tenant_id TEXT NOT NULL,\n external_user_id TEXT NOT NULL,\n user_email TEXT NOT NULL,\n org_id TEXT NOT NULL,\n created_at ${integer} NOT NULL,\n updated_at ${integer} NOT NULL\n )`;\n}\n\nconst INDEXES = [\n [\n \"idx_integration_identity_links_external\",\n `CREATE UNIQUE INDEX IF NOT EXISTS idx_integration_identity_links_external\n ON ${TABLE}(platform, tenant_id, external_user_id)`,\n ],\n [\n \"idx_integration_identity_links_account\",\n `CREATE INDEX IF NOT EXISTS idx_integration_identity_links_account\n ON ${TABLE}(org_id, user_email)`,\n ],\n] as const;\n\nasync function ensureTable(): Promise<void> {\n if (!_initPromise) {\n _initPromise = (async () => {\n const client = getDbExec();\n if (isPostgres()) {\n await ensureTableExists(TABLE, createSql());\n for (const [name, sql] of INDEXES) {\n await ensureIndexExists(name, sql);\n }\n return;\n }\n await retryOnDdlRace(() => client.execute(createSql()));\n for (const [, sql] of INDEXES) {\n await retryOnDdlRace(() => client.execute(sql));\n }\n })().catch((error) => {\n _initPromise = undefined;\n throw error;\n });\n }\n return _initPromise;\n}\n\nfunction required(value: string, name: string): string {\n const normalized = value.trim();\n if (!normalized) throw new Error(`${name} is required`);\n if (normalized.length > 512) throw new Error(`${name} is too long`);\n return normalized;\n}\n\nfunction normalizePlatform(value: string): string {\n return required(value, \"platform\").toLowerCase();\n}\n\nfunction normalizeEmail(value: string): string {\n const normalized = required(value, \"userEmail\").toLowerCase();\n if (!normalized.includes(\"@\")) throw new Error(\"userEmail must be an email\");\n return normalized;\n}\n\nfunction rowToLink(row: Record<string, unknown>): IntegrationIdentityLink {\n return {\n id: String(row.id),\n platform: String(row.platform),\n tenantId: String(row.tenant_id),\n externalUserId: String(row.external_user_id),\n userEmail: String(row.user_email),\n orgId: String(row.org_id),\n createdAt: Number(row.created_at ?? 0),\n updatedAt: Number(row.updated_at ?? 0),\n };\n}\n\nasync function selectByExternalIdentity(\n platform: string,\n tenantId: string,\n externalUserId: string,\n): Promise<IntegrationIdentityLink | null> {\n await ensureTable();\n const { rows } = await getDbExec().execute({\n sql: `SELECT * FROM ${TABLE}\n WHERE platform = ? AND tenant_id = ? AND external_user_id = ?\n LIMIT 1`,\n args: [platform, tenantId, externalUserId],\n });\n return rows[0] ? rowToLink(rows[0] as Record<string, unknown>) : null;\n}\n\nfunction matchesVerifiedLink(\n row: IntegrationIdentityLink,\n input: { userEmail: string; orgId: string },\n): boolean {\n return row.userEmail === input.userEmail && row.orgId === input.orgId;\n}\n\n/** Persist a verified mapping and fail closed if it changes identity later. */\nexport async function upsertVerifiedIntegrationIdentity(input: {\n platform: string;\n tenantId: string;\n externalUserId: string;\n userEmail: string;\n orgId: string;\n}): Promise<IntegrationIdentityLink> {\n const platform = normalizePlatform(input.platform);\n const tenantId = required(input.tenantId, \"tenantId\");\n const externalUserId = required(input.externalUserId, \"externalUserId\");\n const userEmail = normalizeEmail(input.userEmail);\n const orgId = required(input.orgId, \"orgId\");\n const existing = await selectByExternalIdentity(\n platform,\n tenantId,\n externalUserId,\n );\n\n if (existing) {\n if (!matchesVerifiedLink(existing, { userEmail, orgId })) {\n throw new Error(\n \"This provider identity is already linked to a different Agent Native account.\",\n );\n }\n const updatedAt = Date.now();\n await getDbExec().execute({\n sql: `UPDATE ${TABLE} SET updated_at = ? WHERE id = ?`,\n args: [updatedAt, existing.id],\n });\n return { ...existing, updatedAt };\n }\n\n const id = randomUUID();\n const now = Date.now();\n try {\n await getDbExec().execute({\n sql: `INSERT INTO ${TABLE} (\n id, platform, tenant_id, external_user_id, user_email, org_id,\n created_at, updated_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n id,\n platform,\n tenantId,\n externalUserId,\n userEmail,\n orgId,\n now,\n now,\n ],\n });\n } catch (error) {\n if (!isUniqueViolation(error)) throw error;\n const raced = await selectByExternalIdentity(\n platform,\n tenantId,\n externalUserId,\n );\n if (!raced || !matchesVerifiedLink(raced, { userEmail, orgId })) {\n throw new Error(\n \"This provider identity is already linked to a different Agent Native account.\",\n );\n }\n return raced;\n }\n\n return {\n id,\n platform,\n tenantId,\n externalUserId,\n userEmail,\n orgId,\n createdAt: now,\n updatedAt: now,\n };\n}\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { IncomingMessage, IntegrationExecutionContext } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Resolve the default integration principal.
|
|
4
|
+
*
|
|
5
|
+
* Slack DMs become a user principal only after the adapter has verified the
|
|
6
|
+
* sender email and the email is already a member of the managed installation's
|
|
7
|
+
* Agent Native organization. Shared channels deliberately stay service-scoped
|
|
8
|
+
* so a channel message cannot borrow one participant's private permissions.
|
|
9
|
+
*/
|
|
10
|
+
export declare function resolveDefaultIntegrationExecutionContext(incoming: IncomingMessage): Promise<IntegrationExecutionContext>;
|
|
11
|
+
//# sourceMappingURL=identity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/integrations/identity.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,eAAe,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAC;AAuD/E;;;;;;;GAOG;AACH,wBAAsB,yCAAyC,CAC7D,QAAQ,EAAE,eAAe,GACxB,OAAO,CAAC,2BAA2B,CAAC,CA2DtC"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { getDbExec } from "../db/client.js";
|
|
2
|
+
import { upsertVerifiedIntegrationIdentity } from "./identity-links-store.js";
|
|
3
|
+
import { getActiveIntegrationInstallationByKey, getActiveIntegrationInstallationForTenant, } from "./installations-store.js";
|
|
4
|
+
import { slackInstallationKey } from "./slack-oauth.js";
|
|
5
|
+
function serviceOwner(platform) {
|
|
6
|
+
return `integration@${platform}`;
|
|
7
|
+
}
|
|
8
|
+
function normalizedEmail(value) {
|
|
9
|
+
if (typeof value !== "string")
|
|
10
|
+
return null;
|
|
11
|
+
const email = value.trim().toLowerCase();
|
|
12
|
+
if (!email || email.length > 320 || !email.includes("@"))
|
|
13
|
+
return null;
|
|
14
|
+
return email;
|
|
15
|
+
}
|
|
16
|
+
async function resolveSlackInstallation(incoming) {
|
|
17
|
+
const teamId = typeof incoming.platformContext.teamId === "string"
|
|
18
|
+
? incoming.platformContext.teamId
|
|
19
|
+
: incoming.tenantId;
|
|
20
|
+
const enterpriseId = typeof incoming.platformContext.enterpriseId === "string"
|
|
21
|
+
? incoming.platformContext.enterpriseId
|
|
22
|
+
: undefined;
|
|
23
|
+
const apiAppId = typeof incoming.platformContext.apiAppId === "string"
|
|
24
|
+
? incoming.platformContext.apiAppId
|
|
25
|
+
: undefined;
|
|
26
|
+
if (apiAppId && (teamId || enterpriseId)) {
|
|
27
|
+
const byKey = await getActiveIntegrationInstallationByKey("slack", slackInstallationKey({ teamId, enterpriseId, apiAppId }));
|
|
28
|
+
if (byKey)
|
|
29
|
+
return byKey;
|
|
30
|
+
}
|
|
31
|
+
return teamId || enterpriseId
|
|
32
|
+
? getActiveIntegrationInstallationForTenant("slack", teamId ?? enterpriseId)
|
|
33
|
+
: null;
|
|
34
|
+
}
|
|
35
|
+
async function isMemberOfOrg(email, orgId) {
|
|
36
|
+
try {
|
|
37
|
+
const { rows } = await getDbExec().execute({
|
|
38
|
+
sql: `SELECT 1 FROM org_members
|
|
39
|
+
WHERE org_id = ? AND LOWER(email) = ?
|
|
40
|
+
LIMIT 1`,
|
|
41
|
+
args: [orgId, email],
|
|
42
|
+
});
|
|
43
|
+
return rows.length > 0;
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Resolve the default integration principal.
|
|
51
|
+
*
|
|
52
|
+
* Slack DMs become a user principal only after the adapter has verified the
|
|
53
|
+
* sender email and the email is already a member of the managed installation's
|
|
54
|
+
* Agent Native organization. Shared channels deliberately stay service-scoped
|
|
55
|
+
* so a channel message cannot borrow one participant's private permissions.
|
|
56
|
+
*/
|
|
57
|
+
export async function resolveDefaultIntegrationExecutionContext(incoming) {
|
|
58
|
+
const installation = incoming.platform === "slack"
|
|
59
|
+
? await resolveSlackInstallation(incoming)
|
|
60
|
+
: null;
|
|
61
|
+
if (incoming.platform !== "slack" || incoming.conversationType !== "dm") {
|
|
62
|
+
return {
|
|
63
|
+
ownerEmail: serviceOwner(incoming.platform),
|
|
64
|
+
orgId: installation?.orgId ?? null,
|
|
65
|
+
principalType: "service",
|
|
66
|
+
...(installation?.id ? { installationId: installation.id } : {}),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
const email = normalizedEmail(incoming.senderEmail);
|
|
70
|
+
if (!email ||
|
|
71
|
+
incoming.senderVerified !== true ||
|
|
72
|
+
!incoming.senderId ||
|
|
73
|
+
!incoming.tenantId) {
|
|
74
|
+
throw new Error("Slack DM sender identity could not be verified; refusing to run with a service principal.");
|
|
75
|
+
}
|
|
76
|
+
if (incoming.actorTrust?.memberType === "guest" ||
|
|
77
|
+
incoming.actorTrust?.memberType === "external") {
|
|
78
|
+
throw new Error("External or guest Slack members cannot use personal Agent Native permissions.");
|
|
79
|
+
}
|
|
80
|
+
if (!installation?.orgId) {
|
|
81
|
+
throw new Error("Slack workspace is not connected to an Agent Native organization.");
|
|
82
|
+
}
|
|
83
|
+
if (!(await isMemberOfOrg(email, installation.orgId))) {
|
|
84
|
+
throw new Error("Slack DM sender is not a member of the connected Agent Native organization.");
|
|
85
|
+
}
|
|
86
|
+
const link = await upsertVerifiedIntegrationIdentity({
|
|
87
|
+
platform: incoming.platform,
|
|
88
|
+
tenantId: incoming.tenantId,
|
|
89
|
+
externalUserId: incoming.senderId,
|
|
90
|
+
userEmail: email,
|
|
91
|
+
orgId: installation.orgId,
|
|
92
|
+
});
|
|
93
|
+
return {
|
|
94
|
+
ownerEmail: link.userEmail,
|
|
95
|
+
orgId: link.orgId,
|
|
96
|
+
principalType: "user",
|
|
97
|
+
installationId: installation.id,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=identity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity.js","sourceRoot":"","sources":["../../src/integrations/identity.ts"],"names":[],"mappings":"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","sourcesContent":["import { getDbExec } from \"../db/client.js\";\nimport { upsertVerifiedIntegrationIdentity } from \"./identity-links-store.js\";\nimport {\n getActiveIntegrationInstallationByKey,\n getActiveIntegrationInstallationForTenant,\n} from \"./installations-store.js\";\nimport { slackInstallationKey } from \"./slack-oauth.js\";\nimport type { IncomingMessage, IntegrationExecutionContext } from \"./types.js\";\n\nfunction serviceOwner(platform: string): string {\n return `integration@${platform}`;\n}\n\nfunction normalizedEmail(value: unknown): string | null {\n if (typeof value !== \"string\") return null;\n const email = value.trim().toLowerCase();\n if (!email || email.length > 320 || !email.includes(\"@\")) return null;\n return email;\n}\n\nasync function resolveSlackInstallation(incoming: IncomingMessage) {\n const teamId =\n typeof incoming.platformContext.teamId === \"string\"\n ? incoming.platformContext.teamId\n : incoming.tenantId;\n const enterpriseId =\n typeof incoming.platformContext.enterpriseId === \"string\"\n ? incoming.platformContext.enterpriseId\n : undefined;\n const apiAppId =\n typeof incoming.platformContext.apiAppId === \"string\"\n ? incoming.platformContext.apiAppId\n : undefined;\n if (apiAppId && (teamId || enterpriseId)) {\n const byKey = await getActiveIntegrationInstallationByKey(\n \"slack\",\n slackInstallationKey({ teamId, enterpriseId, apiAppId }),\n );\n if (byKey) return byKey;\n }\n return teamId || enterpriseId\n ? getActiveIntegrationInstallationForTenant(\n \"slack\",\n teamId ?? enterpriseId!,\n )\n : null;\n}\n\nasync function isMemberOfOrg(email: string, orgId: string): Promise<boolean> {\n try {\n const { rows } = await getDbExec().execute({\n sql: `SELECT 1 FROM org_members\n WHERE org_id = ? AND LOWER(email) = ?\n LIMIT 1`,\n args: [orgId, email],\n });\n return rows.length > 0;\n } catch {\n return false;\n }\n}\n\n/**\n * Resolve the default integration principal.\n *\n * Slack DMs become a user principal only after the adapter has verified the\n * sender email and the email is already a member of the managed installation's\n * Agent Native organization. Shared channels deliberately stay service-scoped\n * so a channel message cannot borrow one participant's private permissions.\n */\nexport async function resolveDefaultIntegrationExecutionContext(\n incoming: IncomingMessage,\n): Promise<IntegrationExecutionContext> {\n const installation =\n incoming.platform === \"slack\"\n ? await resolveSlackInstallation(incoming)\n : null;\n\n if (incoming.platform !== \"slack\" || incoming.conversationType !== \"dm\") {\n return {\n ownerEmail: serviceOwner(incoming.platform),\n orgId: installation?.orgId ?? null,\n principalType: \"service\",\n ...(installation?.id ? { installationId: installation.id } : {}),\n };\n }\n\n const email = normalizedEmail(incoming.senderEmail);\n if (\n !email ||\n incoming.senderVerified !== true ||\n !incoming.senderId ||\n !incoming.tenantId\n ) {\n throw new Error(\n \"Slack DM sender identity could not be verified; refusing to run with a service principal.\",\n );\n }\n if (\n incoming.actorTrust?.memberType === \"guest\" ||\n incoming.actorTrust?.memberType === \"external\"\n ) {\n throw new Error(\n \"External or guest Slack members cannot use personal Agent Native permissions.\",\n );\n }\n if (!installation?.orgId) {\n throw new Error(\n \"Slack workspace is not connected to an Agent Native organization.\",\n );\n }\n\n if (!(await isMemberOfOrg(email, installation.orgId))) {\n throw new Error(\n \"Slack DM sender is not a member of the connected Agent Native organization.\",\n );\n }\n\n const link = await upsertVerifiedIntegrationIdentity({\n platform: incoming.platform,\n tenantId: incoming.tenantId,\n externalUserId: incoming.senderId,\n userEmail: email,\n orgId: installation.orgId,\n });\n return {\n ownerEmail: link.userEmail,\n orgId: link.orgId,\n principalType: \"user\",\n installationId: installation.id,\n };\n}\n"]}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export type { PlatformAdapter, IncomingMessage, OutgoingMessage, IntegrationStatus, IntegrationsPluginOptions, ImmediateWebhookResponse, PlatformAdapterCapabilities, UnsupportedPlatformCapabilityError, IntegrationExecutionContext, IntegrationActorTrust, IntegrationContextMessage, IntegrationFileReference, IntegrationConversationType, IntegrationTriggerKind, PlatformRunProgress, } from "./types.js";
|
|
2
2
|
export { assertPlatformCapability } from "./types.js";
|
|
3
|
+
export { resolveDefaultIntegrationExecutionContext } from "./identity.js";
|
|
4
|
+
export { upsertVerifiedIntegrationIdentity, type IntegrationIdentityLink, } from "./identity-links-store.js";
|
|
3
5
|
export { BUILT_IN_INTEGRATION_CATALOG, INTEGRATION_CATEGORIES, getIntegrationCatalogEntry, listBuiltInChannelIntegrations, listIntegrationCatalog, type BuiltInChannelId, type AutomationCapabilities, type ChannelCapabilities, type IntegrationAvailability, type IntegrationCatalogEntry, type IntegrationCategory, type IntegrationCredentialRequirement, type IntegrationIconKey, type IntegrationSupportMaturity, } from "./catalog.js";
|
|
4
6
|
export { createIntegrationsPlugin, defaultIntegrationsPlugin, enqueueRemoteCommand, } from "./plugin.js";
|
|
5
7
|
export { getRemoteComputerCapabilities, listRemoteDevicesForOwner, revokeRemoteDeviceForOwner, unregisterRemoteDevice, } from "./remote-devices-store.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/integrations/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/integrations/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export { assertPlatformCapability } from "./types.js";
|
|
2
|
+
export { resolveDefaultIntegrationExecutionContext } from "./identity.js";
|
|
3
|
+
export { upsertVerifiedIntegrationIdentity, } from "./identity-links-store.js";
|
|
2
4
|
export { BUILT_IN_INTEGRATION_CATALOG, INTEGRATION_CATEGORIES, getIntegrationCatalogEntry, listBuiltInChannelIntegrations, listIntegrationCatalog, } from "./catalog.js";
|
|
3
5
|
// Plugin
|
|
4
6
|
export { createIntegrationsPlugin, defaultIntegrationsPlugin, enqueueRemoteCommand, } from "./plugin.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/integrations/index.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAEtD,OAAO,EACL,4BAA4B,EAC5B,sBAAsB,EACtB,0BAA0B,EAC1B,8BAA8B,EAC9B,sBAAsB,GAUvB,MAAM,cAAc,CAAC;AAEtB,SAAS;AACT,OAAO,EACL,wBAAwB,EACxB,yBAAyB,EACzB,oBAAoB,GACrB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,6BAA6B,EAC7B,yBAAyB,EACzB,0BAA0B,EAC1B,sBAAsB,GACvB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,wBAAwB,EACxB,sBAAsB,EACtB,0BAA0B,GAC3B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,kCAAkC,EAClC,yBAAyB,EACzB,iCAAiC,EACjC,wBAAwB,GACzB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,0BAA0B,EAC1B,6BAA6B,EAC7B,sBAAsB,EACtB,2BAA2B,EAC3B,6BAA6B,GAG9B,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,EACL,mCAAmC,EACnC,mCAAmC,EACnC,4BAA4B,EAC5B,8BAA8B,EAC9B,wCAAwC,EACxC,4BAA4B,GAC7B,MAAM,wBAAwB,CAAC;AAkBhC,WAAW;AACX,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EACL,mCAAmC,EACnC,4BAA4B,EAC5B,qBAAqB,GACtB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,0BAA0B;AAC1B,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,yBAAyB,CAAC;AAEjC,SAAS;AACT,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,uBAAuB,EACvB,sBAAsB,GAEvB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,iCAAiC,EACjC,qCAAqC,EACrC,yCAAyC,EACzC,0BAA0B,EAC1B,4BAA4B,EAC5B,6BAA6B,EAC7B,6BAA6B,EAC7B,6BAA6B,GAC9B,MAAM,0BAA0B,CAAC;AASlC,OAAO,EACL,wBAAwB,EACxB,sBAAsB,EACtB,sBAAsB,EACtB,sBAAsB,EACtB,oBAAoB,EACpB,gCAAgC,EAChC,aAAa,GACd,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,sBAAsB,EACtB,uBAAuB,GAExB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,gCAAgC,EAChC,sBAAsB,EACtB,8BAA8B,EAC9B,mBAAmB,EACnB,0BAA0B,EAC1B,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAQ1B,OAAO,EACL,4BAA4B,EAC5B,yBAAyB,EACzB,2BAA2B,EAC3B,oCAAoC,EACpC,6BAA6B,EAC7B,6BAA6B,EAC7B,0BAA0B,EAC1B,4BAA4B,GAC7B,MAAM,yBAAyB,CAAC;AAOjC,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,GAEnB,MAAM,2BAA2B,CAAC","sourcesContent":["// Types\nexport type {\n PlatformAdapter,\n IncomingMessage,\n OutgoingMessage,\n IntegrationStatus,\n IntegrationsPluginOptions,\n ImmediateWebhookResponse,\n PlatformAdapterCapabilities,\n UnsupportedPlatformCapabilityError,\n IntegrationExecutionContext,\n IntegrationActorTrust,\n IntegrationContextMessage,\n IntegrationFileReference,\n IntegrationConversationType,\n IntegrationTriggerKind,\n PlatformRunProgress,\n} from \"./types.js\";\nexport { assertPlatformCapability } from \"./types.js\";\n\nexport {\n BUILT_IN_INTEGRATION_CATALOG,\n INTEGRATION_CATEGORIES,\n getIntegrationCatalogEntry,\n listBuiltInChannelIntegrations,\n listIntegrationCatalog,\n type BuiltInChannelId,\n type AutomationCapabilities,\n type ChannelCapabilities,\n type IntegrationAvailability,\n type IntegrationCatalogEntry,\n type IntegrationCategory,\n type IntegrationCredentialRequirement,\n type IntegrationIconKey,\n type IntegrationSupportMaturity,\n} from \"./catalog.js\";\n\n// Plugin\nexport {\n createIntegrationsPlugin,\n defaultIntegrationsPlugin,\n enqueueRemoteCommand,\n} from \"./plugin.js\";\n\nexport {\n getRemoteComputerCapabilities,\n listRemoteDevicesForOwner,\n revokeRemoteDeviceForOwner,\n unregisterRemoteDevice,\n} from \"./remote-devices-store.js\";\nexport {\n claimNextComputerCommand,\n enqueueComputerCommand,\n listRemoteCommandsForOwner,\n} from \"./remote-commands-store.js\";\nexport {\n assertValidComputerCommandEnvelope,\n computeComputerActionHash,\n computerOperationRequiresApproval,\n ComputerSupervisionError,\n} from \"./computer-supervision.js\";\nexport {\n authorizeComputerOperation,\n createComputerApprovalRequest,\n decideComputerApproval,\n getComputerApprovalForOwner,\n listComputerApprovalsForOwner,\n type ComputerApprovalRecord,\n type ComputerApprovalStatus,\n} from \"./computer-supervision-store.js\";\nexport { insertRemoteLiveViewEvents } from \"./remote-run-events-store.js\";\nexport {\n listRemotePushNotificationsForOwner,\n listRemotePushRegistrationsForOwner,\n queueRemotePushNotifications,\n toPublicRemotePushRegistration,\n unregisterRemotePushRegistrationForOwner,\n upsertRemotePushRegistration,\n} from \"./remote-push-store.js\";\nexport type {\n ComputerApprovalScope,\n ComputerCommandAction,\n ComputerCommandEnvelope,\n ComputerOperationClass,\n PublicRemotePushRegistration,\n PublicRemoteDevice,\n RemoteComputerCapabilities,\n RemoteCommand,\n RemoteDevice,\n RemoteDeviceMetadata,\n RemoteLiveViewEvent,\n RemotePushNotification,\n RemotePushRegistration,\n RemoteRunEvent,\n} from \"./remote-types.js\";\n\n// Adapters\nexport { slackAdapter } from \"./adapters/slack.js\";\nexport { telegramAdapter } from \"./adapters/telegram.js\";\nexport { whatsappAdapter } from \"./adapters/whatsapp.js\";\nexport { discordAdapter } from \"./adapters/discord.js\";\nexport {\n clearMicrosoftTeamsAccessTokenCache,\n getMicrosoftTeamsAccessToken,\n microsoftTeamsAdapter,\n} from \"./adapters/microsoft-teams.js\";\nexport { googleDocsAdapter } from \"./adapters/google-docs.js\";\nexport { emailAdapter } from \"./adapters/email.js\";\n\n// Google Docs integration\nexport {\n startGoogleDocsPoller,\n stopGoogleDocsPoller,\n handlePushNotification,\n} from \"./google-docs-poller.js\";\n\n// Stores\nexport {\n getIntegrationConfig,\n saveIntegrationConfig,\n deleteIntegrationConfig,\n listIntegrationConfigs,\n type IntegrationConfig,\n} from \"./config-store.js\";\n\nexport {\n disconnectIntegrationInstallation,\n getActiveIntegrationInstallationByKey,\n getActiveIntegrationInstallationForTenant,\n getIntegrationInstallation,\n listIntegrationInstallations,\n resolveIntegrationTokenBundle,\n updateIntegrationInstallation,\n upsertIntegrationInstallation,\n} from \"./installations-store.js\";\nexport type {\n InstallationActor,\n IntegrationInstallation,\n IntegrationInstallationHealth,\n IntegrationInstallationStatus,\n IntegrationTokenBundle,\n} from \"./installations-store.js\";\n\nexport {\n assertSlackInstallAccess,\n buildSlackAuthorizeUrl,\n exchangeSlackOAuthCode,\n refreshSlackOAuthToken,\n slackInstallationKey,\n slackOAuthResponseToInstallation,\n testSlackAuth,\n} from \"./slack-oauth.js\";\n\nexport {\n SLACK_AGENT_BOT_EVENTS,\n buildSlackAgentManifest,\n type SlackAgentManifestUrls,\n} from \"./slack-manifest.js\";\n\nexport {\n DEFAULT_INTEGRATION_SCOPE_POLICY,\n deleteIntegrationScope,\n evaluateIntegrationScopePolicy,\n getIntegrationScope,\n integrationScopeSubjectKey,\n listIntegrationScopes,\n saveIntegrationScope,\n} from \"./scope-store.js\";\nexport type {\n IntegrationConversationTrust,\n IntegrationScope,\n IntegrationScopeAccess,\n IntegrationScopePolicy,\n} from \"./scope-store.js\";\n\nexport {\n getIntegrationBudgetSnapshot,\n getIntegrationUsageBudget,\n listIntegrationUsageBudgets,\n listIntegrationBudgetThresholdEvents,\n releaseIntegrationUsageBudget,\n reserveIntegrationUsageBudget,\n saveIntegrationUsageBudget,\n settleIntegrationUsageBudget,\n} from \"./usage-budget-store.js\";\nexport type {\n IntegrationBudgetPeriod,\n IntegrationBudgetSubject,\n IntegrationUsageBudget,\n} from \"./usage-budget-store.js\";\n\nexport {\n getThreadMapping,\n saveThreadMapping,\n deleteThreadMapping,\n listThreadMappings,\n type ThreadMapping,\n} from \"./thread-mapping-store.js\";\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/integrations/index.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAEtD,OAAO,EAAE,yCAAyC,EAAE,MAAM,eAAe,CAAC;AAC1E,OAAO,EACL,iCAAiC,GAElC,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,4BAA4B,EAC5B,sBAAsB,EACtB,0BAA0B,EAC1B,8BAA8B,EAC9B,sBAAsB,GAUvB,MAAM,cAAc,CAAC;AAEtB,SAAS;AACT,OAAO,EACL,wBAAwB,EACxB,yBAAyB,EACzB,oBAAoB,GACrB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,6BAA6B,EAC7B,yBAAyB,EACzB,0BAA0B,EAC1B,sBAAsB,GACvB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,wBAAwB,EACxB,sBAAsB,EACtB,0BAA0B,GAC3B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,kCAAkC,EAClC,yBAAyB,EACzB,iCAAiC,EACjC,wBAAwB,GACzB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,0BAA0B,EAC1B,6BAA6B,EAC7B,sBAAsB,EACtB,2BAA2B,EAC3B,6BAA6B,GAG9B,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,EACL,mCAAmC,EACnC,mCAAmC,EACnC,4BAA4B,EAC5B,8BAA8B,EAC9B,wCAAwC,EACxC,4BAA4B,GAC7B,MAAM,wBAAwB,CAAC;AAkBhC,WAAW;AACX,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EACL,mCAAmC,EACnC,4BAA4B,EAC5B,qBAAqB,GACtB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,0BAA0B;AAC1B,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,yBAAyB,CAAC;AAEjC,SAAS;AACT,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,uBAAuB,EACvB,sBAAsB,GAEvB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,iCAAiC,EACjC,qCAAqC,EACrC,yCAAyC,EACzC,0BAA0B,EAC1B,4BAA4B,EAC5B,6BAA6B,EAC7B,6BAA6B,EAC7B,6BAA6B,GAC9B,MAAM,0BAA0B,CAAC;AASlC,OAAO,EACL,wBAAwB,EACxB,sBAAsB,EACtB,sBAAsB,EACtB,sBAAsB,EACtB,oBAAoB,EACpB,gCAAgC,EAChC,aAAa,GACd,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,sBAAsB,EACtB,uBAAuB,GAExB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,gCAAgC,EAChC,sBAAsB,EACtB,8BAA8B,EAC9B,mBAAmB,EACnB,0BAA0B,EAC1B,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAQ1B,OAAO,EACL,4BAA4B,EAC5B,yBAAyB,EACzB,2BAA2B,EAC3B,oCAAoC,EACpC,6BAA6B,EAC7B,6BAA6B,EAC7B,0BAA0B,EAC1B,4BAA4B,GAC7B,MAAM,yBAAyB,CAAC;AAOjC,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,GAEnB,MAAM,2BAA2B,CAAC","sourcesContent":["// Types\nexport type {\n PlatformAdapter,\n IncomingMessage,\n OutgoingMessage,\n IntegrationStatus,\n IntegrationsPluginOptions,\n ImmediateWebhookResponse,\n PlatformAdapterCapabilities,\n UnsupportedPlatformCapabilityError,\n IntegrationExecutionContext,\n IntegrationActorTrust,\n IntegrationContextMessage,\n IntegrationFileReference,\n IntegrationConversationType,\n IntegrationTriggerKind,\n PlatformRunProgress,\n} from \"./types.js\";\nexport { assertPlatformCapability } from \"./types.js\";\n\nexport { resolveDefaultIntegrationExecutionContext } from \"./identity.js\";\nexport {\n upsertVerifiedIntegrationIdentity,\n type IntegrationIdentityLink,\n} from \"./identity-links-store.js\";\n\nexport {\n BUILT_IN_INTEGRATION_CATALOG,\n INTEGRATION_CATEGORIES,\n getIntegrationCatalogEntry,\n listBuiltInChannelIntegrations,\n listIntegrationCatalog,\n type BuiltInChannelId,\n type AutomationCapabilities,\n type ChannelCapabilities,\n type IntegrationAvailability,\n type IntegrationCatalogEntry,\n type IntegrationCategory,\n type IntegrationCredentialRequirement,\n type IntegrationIconKey,\n type IntegrationSupportMaturity,\n} from \"./catalog.js\";\n\n// Plugin\nexport {\n createIntegrationsPlugin,\n defaultIntegrationsPlugin,\n enqueueRemoteCommand,\n} from \"./plugin.js\";\n\nexport {\n getRemoteComputerCapabilities,\n listRemoteDevicesForOwner,\n revokeRemoteDeviceForOwner,\n unregisterRemoteDevice,\n} from \"./remote-devices-store.js\";\nexport {\n claimNextComputerCommand,\n enqueueComputerCommand,\n listRemoteCommandsForOwner,\n} from \"./remote-commands-store.js\";\nexport {\n assertValidComputerCommandEnvelope,\n computeComputerActionHash,\n computerOperationRequiresApproval,\n ComputerSupervisionError,\n} from \"./computer-supervision.js\";\nexport {\n authorizeComputerOperation,\n createComputerApprovalRequest,\n decideComputerApproval,\n getComputerApprovalForOwner,\n listComputerApprovalsForOwner,\n type ComputerApprovalRecord,\n type ComputerApprovalStatus,\n} from \"./computer-supervision-store.js\";\nexport { insertRemoteLiveViewEvents } from \"./remote-run-events-store.js\";\nexport {\n listRemotePushNotificationsForOwner,\n listRemotePushRegistrationsForOwner,\n queueRemotePushNotifications,\n toPublicRemotePushRegistration,\n unregisterRemotePushRegistrationForOwner,\n upsertRemotePushRegistration,\n} from \"./remote-push-store.js\";\nexport type {\n ComputerApprovalScope,\n ComputerCommandAction,\n ComputerCommandEnvelope,\n ComputerOperationClass,\n PublicRemotePushRegistration,\n PublicRemoteDevice,\n RemoteComputerCapabilities,\n RemoteCommand,\n RemoteDevice,\n RemoteDeviceMetadata,\n RemoteLiveViewEvent,\n RemotePushNotification,\n RemotePushRegistration,\n RemoteRunEvent,\n} from \"./remote-types.js\";\n\n// Adapters\nexport { slackAdapter } from \"./adapters/slack.js\";\nexport { telegramAdapter } from \"./adapters/telegram.js\";\nexport { whatsappAdapter } from \"./adapters/whatsapp.js\";\nexport { discordAdapter } from \"./adapters/discord.js\";\nexport {\n clearMicrosoftTeamsAccessTokenCache,\n getMicrosoftTeamsAccessToken,\n microsoftTeamsAdapter,\n} from \"./adapters/microsoft-teams.js\";\nexport { googleDocsAdapter } from \"./adapters/google-docs.js\";\nexport { emailAdapter } from \"./adapters/email.js\";\n\n// Google Docs integration\nexport {\n startGoogleDocsPoller,\n stopGoogleDocsPoller,\n handlePushNotification,\n} from \"./google-docs-poller.js\";\n\n// Stores\nexport {\n getIntegrationConfig,\n saveIntegrationConfig,\n deleteIntegrationConfig,\n listIntegrationConfigs,\n type IntegrationConfig,\n} from \"./config-store.js\";\n\nexport {\n disconnectIntegrationInstallation,\n getActiveIntegrationInstallationByKey,\n getActiveIntegrationInstallationForTenant,\n getIntegrationInstallation,\n listIntegrationInstallations,\n resolveIntegrationTokenBundle,\n updateIntegrationInstallation,\n upsertIntegrationInstallation,\n} from \"./installations-store.js\";\nexport type {\n InstallationActor,\n IntegrationInstallation,\n IntegrationInstallationHealth,\n IntegrationInstallationStatus,\n IntegrationTokenBundle,\n} from \"./installations-store.js\";\n\nexport {\n assertSlackInstallAccess,\n buildSlackAuthorizeUrl,\n exchangeSlackOAuthCode,\n refreshSlackOAuthToken,\n slackInstallationKey,\n slackOAuthResponseToInstallation,\n testSlackAuth,\n} from \"./slack-oauth.js\";\n\nexport {\n SLACK_AGENT_BOT_EVENTS,\n buildSlackAgentManifest,\n type SlackAgentManifestUrls,\n} from \"./slack-manifest.js\";\n\nexport {\n DEFAULT_INTEGRATION_SCOPE_POLICY,\n deleteIntegrationScope,\n evaluateIntegrationScopePolicy,\n getIntegrationScope,\n integrationScopeSubjectKey,\n listIntegrationScopes,\n saveIntegrationScope,\n} from \"./scope-store.js\";\nexport type {\n IntegrationConversationTrust,\n IntegrationScope,\n IntegrationScopeAccess,\n IntegrationScopePolicy,\n} from \"./scope-store.js\";\n\nexport {\n getIntegrationBudgetSnapshot,\n getIntegrationUsageBudget,\n listIntegrationUsageBudgets,\n listIntegrationBudgetThresholdEvents,\n releaseIntegrationUsageBudget,\n reserveIntegrationUsageBudget,\n saveIntegrationUsageBudget,\n settleIntegrationUsageBudget,\n} from \"./usage-budget-store.js\";\nexport type {\n IntegrationBudgetPeriod,\n IntegrationBudgetSubject,\n IntegrationUsageBudget,\n} from \"./usage-budget-store.js\";\n\nexport {\n getThreadMapping,\n saveThreadMapping,\n deleteThreadMapping,\n listThreadMappings,\n type ThreadMapping,\n} from \"./thread-mapping-store.js\";\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/integrations/plugin.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/integrations/plugin.ts"],"names":[],"mappings":"AAsIA,OAAO,KAAK,EAEV,yBAAyB,EAG1B,MAAM,YAAY,CAAC;AAOpB,KAAK,cAAc,GAAG,CAAC,QAAQ,EAAE,GAAG,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AA4F9D,KAAK,yBAAyB,GAAG;IAC/B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAUF,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,yBAAyB,GAClC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAsFlC;AA+ND;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,CAAC,EAAE,yBAAyB,GAClC,cAAc,CA69DhB;AAED;;GAEG;AACH,eAAO,MAAM,yBAAyB,gBAA6B,CAAC"}
|
|
@@ -26,6 +26,7 @@ import { ComputerSupervisionError } from "./computer-supervision.js";
|
|
|
26
26
|
import { getIntegrationConfig, saveIntegrationConfig } from "./config-store.js";
|
|
27
27
|
import { claimIntegrationControl } from "./controls-store.js";
|
|
28
28
|
import { startGoogleDocsPoller, handlePushNotification, } from "./google-docs-poller.js";
|
|
29
|
+
import { resolveDefaultIntegrationExecutionContext } from "./identity.js";
|
|
29
30
|
import { disconnectIntegrationInstallation, listIntegrationInstallations, resolveIntegrationTokenBundle, updateIntegrationInstallation, upsertIntegrationInstallation, } from "./installations-store.js";
|
|
30
31
|
import { forgetIntegrationMemory, integrationMemoryActions, listIntegrationMemory, rememberForIntegrationScope, } from "./integration-memory.js";
|
|
31
32
|
import { extractBearerToken, signInternalToken, verifyInternalToken, } from "./internal-token.js";
|
|
@@ -1888,11 +1889,39 @@ export function createIntegrationsPlugin(options) {
|
|
|
1888
1889
|
setResponseStatus(event, 404);
|
|
1889
1890
|
return { error: `Integration ${platform} is not enabled` };
|
|
1890
1891
|
}
|
|
1891
|
-
|
|
1892
|
+
let incoming = await withCredentialContext(credentialContext, () => adapter.parseIncomingMessage(event));
|
|
1892
1893
|
if (!incoming) {
|
|
1893
1894
|
setResponseStatus(event, 200);
|
|
1894
1895
|
return "ok";
|
|
1895
1896
|
}
|
|
1897
|
+
if (adapter.hydrateIncomingIdentity) {
|
|
1898
|
+
try {
|
|
1899
|
+
incoming = await withCredentialContext(credentialContext, () => adapter.hydrateIncomingIdentity(incoming));
|
|
1900
|
+
}
|
|
1901
|
+
catch (err) {
|
|
1902
|
+
// Identity hydration is best-effort for platforms that have an
|
|
1903
|
+
// app-specific resolver. Slack's default DM resolver below will
|
|
1904
|
+
// still fail closed when the identity is absent or unverified.
|
|
1905
|
+
console.warn(`[integrations] Could not hydrate ${platform} sender identity:`, err instanceof Error ? err.message : err);
|
|
1906
|
+
}
|
|
1907
|
+
}
|
|
1908
|
+
let defaultExecutionContext = null;
|
|
1909
|
+
if (incoming.platform === "slack" &&
|
|
1910
|
+
incoming.conversationType === "dm") {
|
|
1911
|
+
try {
|
|
1912
|
+
defaultExecutionContext = await withCredentialContext(credentialContext, () => resolveDefaultIntegrationExecutionContext(incoming));
|
|
1913
|
+
}
|
|
1914
|
+
catch (err) {
|
|
1915
|
+
// An app-specific resolver may intentionally support a legacy
|
|
1916
|
+
// Slack setup. When no override exists, the branch below fails
|
|
1917
|
+
// closed instead of falling back to a service principal.
|
|
1918
|
+
if (!options?.resolveExecutionContext && !options?.resolveOwner) {
|
|
1919
|
+
console.error(`[integrations] default Slack DM identity denied message:`, err);
|
|
1920
|
+
setResponseStatus(event, 200);
|
|
1921
|
+
return "ok";
|
|
1922
|
+
}
|
|
1923
|
+
}
|
|
1924
|
+
}
|
|
1896
1925
|
let executionContext = {
|
|
1897
1926
|
ownerEmail: `integration@${platform}`,
|
|
1898
1927
|
orgId: null,
|
|
@@ -1908,6 +1937,9 @@ export function createIntegrationsPlugin(options) {
|
|
|
1908
1937
|
return "ok";
|
|
1909
1938
|
}
|
|
1910
1939
|
}
|
|
1940
|
+
else if (defaultExecutionContext) {
|
|
1941
|
+
executionContext = defaultExecutionContext;
|
|
1942
|
+
}
|
|
1911
1943
|
else if (options?.resolveOwner) {
|
|
1912
1944
|
try {
|
|
1913
1945
|
executionContext.ownerEmail = await withCredentialContext(credentialContext, () => Promise.resolve(options.resolveOwner(incoming)));
|
|
@@ -1916,6 +1948,16 @@ export function createIntegrationsPlugin(options) {
|
|
|
1916
1948
|
console.error(`[integrations] resolveOwner failed, using default:`, err);
|
|
1917
1949
|
}
|
|
1918
1950
|
}
|
|
1951
|
+
else {
|
|
1952
|
+
try {
|
|
1953
|
+
executionContext = await withCredentialContext(credentialContext, () => resolveDefaultIntegrationExecutionContext(incoming));
|
|
1954
|
+
}
|
|
1955
|
+
catch (err) {
|
|
1956
|
+
console.error(`[integrations] default execution identity denied message:`, err);
|
|
1957
|
+
setResponseStatus(event, 200);
|
|
1958
|
+
return "ok";
|
|
1959
|
+
}
|
|
1960
|
+
}
|
|
1919
1961
|
if (executionContext.scopeId) {
|
|
1920
1962
|
incoming.integrationScopeId = executionContext.scopeId;
|
|
1921
1963
|
}
|