@opengeni/api-router 3.0.0-canary.0 → 3.0.1-canary.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.
Files changed (39) hide show
  1. package/dist/app.js +1 -1
  2. package/dist/{chunk-7IAWEYBH.js → chunk-XZGTKYOA.js} +3626 -2525
  3. package/dist/{chunk-7IAWEYBH.js.map → chunk-XZGTKYOA.js.map} +1 -1
  4. package/dist/index.js +1 -1
  5. package/dist/integrations/fiken.d.ts +3 -1
  6. package/dist/integrations/github-lens-connect.d.ts +2 -2
  7. package/dist/integrations/integration-commit-authority.d.ts +13 -0
  8. package/dist/integrations/oauth-client.d.ts +118 -1
  9. package/dist/integrations/slack-interactions.d.ts +1 -1
  10. package/dist/mcp/first-party-tool-permissions.d.ts +4 -0
  11. package/dist/mcp/scheduled-task-view.d.ts +3 -3
  12. package/dist/routes/api-integrations.d.ts +1 -0
  13. package/dist/routes/organization-integration-policy.d.ts +3 -0
  14. package/package.json +19 -19
  15. package/src/app.ts +7 -2
  16. package/src/integrations/atlassian.ts +135 -65
  17. package/src/integrations/fiken.ts +57 -35
  18. package/src/integrations/github-app-connect.ts +34 -15
  19. package/src/integrations/google-drive.ts +295 -124
  20. package/src/integrations/integration-commit-authority.ts +69 -0
  21. package/src/integrations/oauth-client.ts +220 -65
  22. package/src/integrations/personal-github.ts +55 -31
  23. package/src/integrations/provider-oauth.ts +54 -31
  24. package/src/integrations/social-oauth.ts +83 -56
  25. package/src/mcp/first-party-tool-permissions.ts +1 -0
  26. package/src/mcp/knowledge-entries.ts +23 -6
  27. package/src/routes/api-integrations.ts +116 -4
  28. package/src/routes/billing.ts +52 -0
  29. package/src/routes/capabilities.ts +51 -1
  30. package/src/routes/connect.ts +161 -57
  31. package/src/routes/connections.ts +430 -305
  32. package/src/routes/github.ts +48 -19
  33. package/src/routes/integration-facets.ts +66 -25
  34. package/src/routes/knowledge.ts +48 -1
  35. package/src/routes/organization-integration-policy.ts +113 -0
  36. package/src/routes/plugins.ts +12 -2
  37. package/src/routes/pr-review-github.ts +60 -30
  38. package/src/routes/pr-review.ts +69 -45
  39. package/src/routes/social.ts +24 -13
package/dist/index.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  createOpenGeniSlackBotInteractionClient,
8
8
  startSlackInteractionPump,
9
9
  startTemporalScheduleCleanupPump
10
- } from "./chunk-7IAWEYBH.js";
10
+ } from "./chunk-XZGTKYOA.js";
11
11
 
12
12
  // src/index.ts
13
13
  import { scheduledTaskKnowledgeSource } from "@opengeni/contracts";
@@ -6,7 +6,9 @@ import { type Database } from "@opengeni/db";
6
6
  import { type FetchLike } from "@opengeni/network";
7
7
  import { HTTPException } from "hono/http-exception";
8
8
  /** Shared native/embedded token adapter. Provider verification happens before
9
- * persistence; the caller reauthorizes inside its durable commit transaction. */
9
+ * persistence; the caller reauthorizes inside its durable commit transaction.
10
+ * That caller must acquire the organization policy fence for `fiken` BEFORE
11
+ * owner/tenancy locks and invoke the returned writer with that exact tx. */
10
12
  export declare function prepareFikenTokenInstall(deps: ApiRouteDeps, grant: Pick<AccessGrant, "accountId" | "workspaceId" | "subjectId">, raw: unknown, expectedVersion?: number): Promise<(tx: Database) => Promise<ConnectionMetadata>>;
11
13
  export type FikenOperation = "companies.list" | "contacts.list" | "contact.create" | "products.list" | "invoices.list" | "invoice.get" | "invoice_draft.create" | "bank_accounts.list" | "purchases.list" | "sales.list";
12
14
  export declare class FikenProviderError extends Error {
@@ -65,7 +65,7 @@ export declare function requireGitHubLensConnect(deps: ApiRouteDeps, workspaceId
65
65
  adapterId: string;
66
66
  eventTypes: string[];
67
67
  sessionTemplate: {
68
- bundledSkillIds?: ("builtin:document-parsing" | "builtin:opengeni-documents" | "builtin:opengeni-presentations" | "builtin:opengeni-projects" | "builtin:opengeni-sites" | "builtin:opengeni-skills" | "builtin:opengeni-spreadsheets" | "builtin:opengeni-video-generation" | "builtin:opengeni-visualize")[] | undefined;
68
+ bundledSkillIds?: ("builtin:document-parsing" | "builtin:opengeni-documents" | "builtin:opengeni-help" | "builtin:opengeni-presentations" | "builtin:opengeni-projects" | "builtin:opengeni-sites" | "builtin:opengeni-skills" | "builtin:opengeni-spreadsheets" | "builtin:opengeni-video-generation" | "builtin:opengeni-visualize")[] | undefined;
69
69
  prompt: string;
70
70
  instructions: string | null;
71
71
  resources: ({
@@ -104,7 +104,7 @@ export declare function requireGitHubLensConnect(deps: ApiRouteDeps, workspaceId
104
104
  eager?: boolean | undefined;
105
105
  optional?: boolean | undefined;
106
106
  }[];
107
- firstPartyMcpTools: ("artifacts_archive" | "artifacts_create" | "artifacts_get_source" | "artifacts_list" | "artifacts_prepare_upload" | "artifacts_publish" | "artifacts_restore" | "artifacts_rollback" | "atlassian_get" | "atlassian_search" | "atlassian_sources_list" | "browser_act" | "browser_auth" | "browser_clipboard" | "browser_debug" | "browser_identity" | "browser_lifecycle" | "browser_observe" | "browser_open" | "browser_publish" | "browser_tabs" | "capability_authorization_request" | "capability_catalog_search" | "command_read" | "command_wait" | "company_profile_confirm" | "company_profile_propose" | "computer_act" | "computer_clipboard" | "computer_lifecycle" | "computer_observe" | "computer_open" | "computer_targets" | "connected_machine_remove" | "editable_artifact_apply" | "editable_artifact_create" | "editable_artifact_export" | "editable_artifact_export_status" | "editable_artifact_get" | "editable_artifact_import" | "editable_artifact_inspect" | "editable_artifact_list" | "environment_list" | "environment_set_variable" | "fiken_bank_accounts_list" | "fiken_companies_list" | "fiken_contact_create" | "fiken_contacts_list" | "fiken_invoice_draft_create" | "fiken_invoice_get" | "fiken_invoices_list" | "fiken_products_list" | "fiken_purchases_list" | "fiken_sales_list" | "github_connect_link" | "github_repositories_list" | "goal_complete" | "goal_pause" | "goal_progress" | "goal_resume" | "goal_set" | "goal_update" | "instruction_policy_get" | "instruction_policy_propose" | "instruction_policy_save" | "interaction_discover" | "interaction_request_human" | "knowledge_archive" | "knowledge_browse" | "knowledge_correct" | "knowledge_get" | "knowledge_propose" | "knowledge_retain_file" | "knowledge_retain_message" | "knowledge_save" | "knowledge_search" | "memory_correct" | "memory_save" | "memory_search" | "preference_propose" | "preference_registry_get" | "preference_registry_summary" | "project_create" | "project_delete" | "project_get" | "project_list" | "project_reorder" | "project_update" | "reddit_accounts_list" | "reddit_mentions_live" | "reddit_post_reply" | "reddit_posts_sync" | "reddit_search_live" | "reddit_thread_fetch" | "remember" | "remember_confirm" | "rig_get" | "rig_list" | "rig_promote" | "rig_propose_change" | "rig_verify" | "run_on" | "sandbox_attach" | "sandbox_file_publish" | "sandbox_provision" | "sandbox_swap" | "sandboxes_list" | "scheduled_task_runs_list" | "scheduled_tasks_create" | "scheduled_tasks_delete" | "scheduled_tasks_get" | "scheduled_tasks_list" | "scheduled_tasks_pause" | "scheduled_tasks_resume" | "scheduled_tasks_trigger" | "scheduled_tasks_update" | "session_create" | "session_events" | "session_get" | "session_human_input_respond" | "session_pause" | "session_resume" | "session_send_message" | "session_set_project" | "session_steer" | "session_wait" | "sessions_list" | "set_other_session_title" | "set_session_title" | "slack_bot_channel_history" | "slack_bot_delete_message" | "slack_bot_file_content" | "slack_bot_file_info" | "slack_bot_list_channels" | "slack_bot_list_files" | "slack_bot_list_users" | "slack_bot_post_message" | "slack_bot_search" | "slack_bot_thread_replies" | "social_connections_list" | "social_daily_analysis_context" | "social_mentions_live" | "social_post_reply" | "social_posts_recent" | "social_posts_sync" | "social_search_live" | "social_thread_fetch" | "task_note_archive" | "task_note_promote_instruction_policy" | "task_note_promote_knowledge" | "task_note_promote_preference" | "task_note_replace" | "task_note_save" | "task_notes_list" | "variable_set_get_variable" | "variable_set_list" | "variable_set_set_variable" | "wait_for_input" | "work_claim_release" | "work_claim_upsert" | "x_accounts_list" | "x_mentions_live" | "x_post_reply" | "x_posts_sync" | "x_search_live" | "x_thread_fetch")[];
107
+ firstPartyMcpTools: ("artifacts_archive" | "artifacts_create" | "artifacts_get_source" | "artifacts_list" | "artifacts_prepare_upload" | "artifacts_publish" | "artifacts_restore" | "artifacts_rollback" | "atlassian_get" | "atlassian_search" | "atlassian_sources_list" | "browser_act" | "browser_auth" | "browser_clipboard" | "browser_debug" | "browser_identity" | "browser_lifecycle" | "browser_observe" | "browser_open" | "browser_publish" | "browser_tabs" | "capability_authorization_request" | "capability_catalog_search" | "command_read" | "command_wait" | "company_profile_confirm" | "company_profile_propose" | "computer_act" | "computer_clipboard" | "computer_lifecycle" | "computer_observe" | "computer_open" | "computer_targets" | "connected_machine_remove" | "editable_artifact_apply" | "editable_artifact_create" | "editable_artifact_export" | "editable_artifact_export_status" | "editable_artifact_get" | "editable_artifact_import" | "editable_artifact_inspect" | "editable_artifact_list" | "environment_list" | "environment_set_variable" | "fiken_bank_accounts_list" | "fiken_companies_list" | "fiken_contact_create" | "fiken_contacts_list" | "fiken_invoice_draft_create" | "fiken_invoice_get" | "fiken_invoices_list" | "fiken_products_list" | "fiken_purchases_list" | "fiken_sales_list" | "github_connect_link" | "github_repositories_list" | "goal_complete" | "goal_pause" | "goal_progress" | "goal_resume" | "goal_set" | "goal_update" | "instruction_policy_get" | "instruction_policy_propose" | "instruction_policy_save" | "interaction_discover" | "interaction_request_human" | "knowledge_archive" | "knowledge_browse" | "knowledge_correct" | "knowledge_get" | "knowledge_prepare_save" | "knowledge_propose" | "knowledge_retain_file" | "knowledge_retain_message" | "knowledge_save" | "knowledge_search" | "memory_correct" | "memory_save" | "memory_search" | "preference_propose" | "preference_registry_get" | "preference_registry_summary" | "project_create" | "project_delete" | "project_get" | "project_list" | "project_reorder" | "project_update" | "reddit_accounts_list" | "reddit_mentions_live" | "reddit_post_reply" | "reddit_posts_sync" | "reddit_search_live" | "reddit_thread_fetch" | "remember" | "remember_confirm" | "rig_get" | "rig_list" | "rig_promote" | "rig_propose_change" | "rig_verify" | "run_on" | "sandbox_attach" | "sandbox_file_publish" | "sandbox_provision" | "sandbox_swap" | "sandboxes_list" | "scheduled_task_runs_list" | "scheduled_tasks_create" | "scheduled_tasks_delete" | "scheduled_tasks_get" | "scheduled_tasks_list" | "scheduled_tasks_pause" | "scheduled_tasks_resume" | "scheduled_tasks_trigger" | "scheduled_tasks_update" | "session_create" | "session_events" | "session_get" | "session_human_input_respond" | "session_pause" | "session_resume" | "session_send_message" | "session_set_project" | "session_steer" | "session_wait" | "sessions_list" | "set_other_session_title" | "set_session_title" | "slack_bot_channel_history" | "slack_bot_delete_message" | "slack_bot_file_content" | "slack_bot_file_info" | "slack_bot_list_channels" | "slack_bot_list_files" | "slack_bot_list_users" | "slack_bot_post_message" | "slack_bot_search" | "slack_bot_thread_replies" | "social_connections_list" | "social_daily_analysis_context" | "social_mentions_live" | "social_post_reply" | "social_posts_recent" | "social_posts_sync" | "social_search_live" | "social_thread_fetch" | "task_note_archive" | "task_note_promote_instruction_policy" | "task_note_promote_knowledge" | "task_note_promote_preference" | "task_note_replace" | "task_note_save" | "task_notes_list" | "variable_set_get_variable" | "variable_set_list" | "variable_set_set_variable" | "wait_for_input" | "work_claim_release" | "work_claim_upsert" | "x_accounts_list" | "x_mentions_live" | "x_post_reply" | "x_posts_sync" | "x_search_live" | "x_thread_fetch")[];
108
108
  firstPartyMcpPermissions: ("account:admin" | "account:read" | "api_keys:manage" | "artifacts:publish" | "artifacts:read" | "billing:manage" | "billing:read" | "capabilities:manage" | "codemode:call" | "connections:read" | "connections:write" | "documents:manage" | "documents:search" | "enrollments:manage" | "enrollments:read" | "environments:manage" | "environments:use" | "files:read" | "files:upload" | "files:write" | "github:manage" | "github:use" | "goals:manage" | "mcp_servers:attach" | "members:manage" | "rigs:manage" | "rigs:use" | "scheduled_tasks:manage" | "scheduled_tasks:run" | "secrets:list" | "secrets:read" | "secrets:write" | "sessions:control" | "sessions:create" | "sessions:read" | "stream:acknowledge" | "stream:control" | "stream:view" | "terminal:attach" | "variable-sets:attach" | "variable-sets:list" | "variable-sets:manage" | "variable-sets:read" | "variable-sets:use" | "variable-sets:write" | "workspace:admin" | "workspace:create" | "workspace:read")[];
109
109
  model: string | null;
110
110
  reasoningEffort: "high" | "low" | "max" | "medium" | "minimal" | "none" | "xhigh" | null;
@@ -0,0 +1,13 @@
1
+ import { type AccessGrant, type Permission } from "@opengeni/contracts";
2
+ import { type Settings } from "@opengeni/config";
3
+ import { type AccessGrantAuthorization } from "@opengeni/core";
4
+ import type { Database } from "@opengeni/db";
5
+ export type IntegrationCommitGrant = AccessGrant & {
6
+ authorizeCommit: (tx: Database) => Promise<void>;
7
+ };
8
+ /** Keep server-verified provenance alongside the grant across provider work.
9
+ * Call only inside the policy transaction, before persistence locks. */
10
+ export declare function integrationCommitGrant(authorization: AccessGrantAuthorization, permissions: readonly Permission[], request: {
11
+ settings: Settings;
12
+ authorizationHeader?: string | undefined;
13
+ }): Promise<IntegrationCommitGrant>;
@@ -2,7 +2,7 @@ import { type Settings } from "@opengeni/config";
2
2
  import { OAuthStartResponse, type ConnectionOwnership, type OAuthStartRequest } from "@opengeni/contracts";
3
3
  import { ExternalActorContinuation } from "@opengeni/contracts/external-identities";
4
4
  import type { Observability } from "@opengeni/observability";
5
- import { type Database } from "@opengeni/db";
5
+ import { claimConnectOperation, finishConnectOperation, type Database } from "@opengeni/db";
6
6
  import { type McpAuthorizationServerMetadata } from "@opengeni/network";
7
7
  import { type OAuthProviderProfile } from "./oauth-profiles.js";
8
8
  export declare const oauthStateTtlMs: number;
@@ -16,6 +16,8 @@ type OAuthClientDeps = {
16
16
  oauthCallbackDeadlineMs?: number | undefined;
17
17
  };
18
18
  export type OAuthStartContext = {
19
+ /** Server-selected dedicated adapter identity; never copied from request metadata. */
20
+ integrationKey?: "gmail" | "slack-personal";
19
21
  connectAttemptId?: string;
20
22
  externalContinuation?: ExternalActorContinuation;
21
23
  accountId: string;
@@ -38,6 +40,121 @@ type AuthorizationServerMetadata = McpAuthorizationServerMetadata;
38
40
  export declare const OAUTH_START_DEADLINE_MS = 15000;
39
41
  export declare const OAUTH_CALLBACK_DEADLINE_MS = 30000;
40
42
  export type OAuthStartStage = "connection_lookup" | "mcp_challenge" | "protected_resource_metadata" | "authorization_server_metadata" | "client_registration";
43
+ /** Policy is the outermost lock. Receipt replay still runs normal authorization,
44
+ * but the DB calls authorizeAcquisition only for uncommitted progress. Provider
45
+ * requests must happen after this transaction, never inside either wrapper. */
46
+ export declare function claimOAuthAcquisition(db: Database, scope: Parameters<typeof claimConnectOperation>[1], input: Parameters<typeof claimConnectOperation>[2], integrationKey: string | null, acquiring?: boolean): Promise<{
47
+ status: "claimed";
48
+ attempt: import("@opengeni/contracts/connect").ConnectAttempt;
49
+ } | {
50
+ status: "replayed";
51
+ attempt: import("@opengeni/contracts/connect").ConnectAttempt;
52
+ }>;
53
+ type IntegrationSourceSelection = Record<string, unknown> & {
54
+ id: string;
55
+ syncEnabled: boolean;
56
+ readPolicy: "allow" | "ask" | "block";
57
+ };
58
+ /** Compare server-bound selections, not provider classification. Removing a
59
+ * source, disabling sync, or narrowing its read permission acquires no authority.
60
+ * Generation/timestamp bookkeeping does not turn an unchanged save into setup. */
61
+ export declare function integrationSourceSelectionRequiresAcquisition(previous: readonly IntegrationSourceSelection[], requested: readonly IntegrationSourceSelection[]): boolean;
62
+ export declare function finishOAuthAcquisition(db: Database, scope: Parameters<typeof finishConnectOperation>[1], input: Parameters<typeof finishConnectOperation>[2], integrationKey: string | null): Promise<{
63
+ id: string;
64
+ workspaceId: string;
65
+ providerId: string;
66
+ ownership: "personal" | "workspace";
67
+ revision: number;
68
+ state: "account_selection" | "cancelled" | "complete" | "connected_but_incomplete" | "credential_input" | "expired" | "failed" | "installing" | "preview" | "provider_wait" | "ready" | "requires_user_action" | "resource_selection" | "uncertain";
69
+ credentialsCommitted: boolean;
70
+ integrationInstalled: boolean;
71
+ completionRequirement: "connection" | "integration" | "provider_setup";
72
+ nextAction: {
73
+ type: "authorize";
74
+ url: string;
75
+ } | {
76
+ type: "credentials";
77
+ fields: {
78
+ name: string;
79
+ label: string;
80
+ required: boolean;
81
+ secret: boolean;
82
+ options?: {
83
+ value: string;
84
+ label: string;
85
+ }[] | undefined;
86
+ }[];
87
+ } | {
88
+ type: "wait";
89
+ pollAfterMs: number;
90
+ userCode?: string | undefined;
91
+ verificationUrl?: string | undefined;
92
+ } | {
93
+ type: "select_account";
94
+ accounts: {
95
+ id: string;
96
+ providerId: string;
97
+ version?: number | undefined;
98
+ label: string;
99
+ ownership: "personal" | "workspace";
100
+ status: "auth_needed" | "connected" | "disabled";
101
+ }[];
102
+ } | {
103
+ type: "select_resources";
104
+ resources: {
105
+ id: string;
106
+ label: string;
107
+ kind: string;
108
+ }[];
109
+ cursor?: string | undefined;
110
+ } | {
111
+ type: "preview";
112
+ previewId: string;
113
+ contentHash: string;
114
+ operations: {
115
+ id: string;
116
+ label: string;
117
+ kind: string;
118
+ }[];
119
+ } | {
120
+ type: "none";
121
+ };
122
+ expiresAt: string;
123
+ account?: {
124
+ id: string;
125
+ providerId: string;
126
+ version?: number | undefined;
127
+ label: string;
128
+ ownership: "personal" | "workspace";
129
+ status: "auth_needed" | "connected" | "disabled";
130
+ } | undefined;
131
+ installationTarget?: {
132
+ instanceKey: string;
133
+ displayName: string;
134
+ expectedInstanceVersion?: number | undefined;
135
+ } | undefined;
136
+ source?: {
137
+ kind: "definition";
138
+ definitionId: string;
139
+ } | {
140
+ kind: "openapi";
141
+ url: string;
142
+ baseUrl?: string | undefined;
143
+ } | {
144
+ kind: "graphql";
145
+ endpoint: string;
146
+ name?: string | undefined;
147
+ } | {
148
+ kind: "auto";
149
+ url: string;
150
+ baseUrl?: string | undefined;
151
+ } | undefined;
152
+ error?: {
153
+ code: string;
154
+ message: string;
155
+ retryable: boolean;
156
+ } | undefined;
157
+ }>;
41
158
  export declare function startMcpOAuth(deps: OAuthClientDeps, context: OAuthStartContext): Promise<OAuthStartResponse>;
42
159
  /** Ownership fence for the official Gmail profile, keyed by exact MCP URL. */
43
160
  export declare function assertOfficialGmailPersonalOwnership(mcpUrl: string, ownership: ConnectionOwnership): void;
@@ -19,7 +19,7 @@ export declare const SLACK_SESSION_INSTRUCTIONS: string;
19
19
  * selection at session creation while keeping Slack mutations out of the model
20
20
  * surface; interaction delivery remains owned by the durable delivery pump.
21
21
  */
22
- export declare const SLACK_TASK_FIRST_PARTY_MCP_TOOLS: ("artifacts_archive" | "artifacts_create" | "artifacts_get_source" | "artifacts_list" | "artifacts_prepare_upload" | "artifacts_publish" | "artifacts_restore" | "artifacts_rollback" | "atlassian_get" | "atlassian_search" | "atlassian_sources_list" | "browser_act" | "browser_auth" | "browser_clipboard" | "browser_debug" | "browser_identity" | "browser_lifecycle" | "browser_observe" | "browser_open" | "browser_publish" | "browser_tabs" | "capability_authorization_request" | "capability_catalog_search" | "command_read" | "command_wait" | "company_profile_confirm" | "company_profile_propose" | "computer_act" | "computer_clipboard" | "computer_lifecycle" | "computer_observe" | "computer_open" | "computer_targets" | "connected_machine_remove" | "editable_artifact_apply" | "editable_artifact_create" | "editable_artifact_export" | "editable_artifact_export_status" | "editable_artifact_get" | "editable_artifact_import" | "editable_artifact_inspect" | "editable_artifact_list" | "environment_list" | "environment_set_variable" | "fiken_bank_accounts_list" | "fiken_companies_list" | "fiken_contact_create" | "fiken_contacts_list" | "fiken_invoice_draft_create" | "fiken_invoice_get" | "fiken_invoices_list" | "fiken_products_list" | "fiken_purchases_list" | "fiken_sales_list" | "github_connect_link" | "github_repositories_list" | "goal_complete" | "goal_pause" | "goal_progress" | "goal_resume" | "goal_set" | "goal_update" | "instruction_policy_get" | "instruction_policy_propose" | "instruction_policy_save" | "interaction_discover" | "interaction_request_human" | "knowledge_archive" | "knowledge_browse" | "knowledge_correct" | "knowledge_get" | "knowledge_propose" | "knowledge_retain_file" | "knowledge_retain_message" | "knowledge_save" | "knowledge_search" | "memory_correct" | "memory_save" | "memory_search" | "preference_propose" | "preference_registry_get" | "preference_registry_summary" | "project_create" | "project_delete" | "project_get" | "project_list" | "project_reorder" | "project_update" | "reddit_accounts_list" | "reddit_mentions_live" | "reddit_post_reply" | "reddit_posts_sync" | "reddit_search_live" | "reddit_thread_fetch" | "remember" | "remember_confirm" | "rig_get" | "rig_list" | "rig_promote" | "rig_propose_change" | "rig_verify" | "run_on" | "sandbox_attach" | "sandbox_file_publish" | "sandbox_provision" | "sandbox_swap" | "sandboxes_list" | "scheduled_task_runs_list" | "scheduled_tasks_create" | "scheduled_tasks_delete" | "scheduled_tasks_get" | "scheduled_tasks_list" | "scheduled_tasks_pause" | "scheduled_tasks_resume" | "scheduled_tasks_trigger" | "scheduled_tasks_update" | "session_create" | "session_events" | "session_get" | "session_human_input_respond" | "session_pause" | "session_resume" | "session_send_message" | "session_set_project" | "session_steer" | "session_wait" | "sessions_list" | "set_other_session_title" | "set_session_title" | "slack_bot_channel_history" | "slack_bot_delete_message" | "slack_bot_file_content" | "slack_bot_file_info" | "slack_bot_list_channels" | "slack_bot_list_files" | "slack_bot_list_users" | "slack_bot_post_message" | "slack_bot_search" | "slack_bot_thread_replies" | "social_connections_list" | "social_daily_analysis_context" | "social_mentions_live" | "social_post_reply" | "social_posts_recent" | "social_posts_sync" | "social_search_live" | "social_thread_fetch" | "task_note_archive" | "task_note_promote_instruction_policy" | "task_note_promote_knowledge" | "task_note_promote_preference" | "task_note_replace" | "task_note_save" | "task_notes_list" | "variable_set_get_variable" | "variable_set_list" | "variable_set_set_variable" | "wait_for_input" | "work_claim_release" | "work_claim_upsert" | "x_accounts_list" | "x_mentions_live" | "x_post_reply" | "x_posts_sync" | "x_search_live" | "x_thread_fetch")[];
22
+ export declare const SLACK_TASK_FIRST_PARTY_MCP_TOOLS: ("artifacts_archive" | "artifacts_create" | "artifacts_get_source" | "artifacts_list" | "artifacts_prepare_upload" | "artifacts_publish" | "artifacts_restore" | "artifacts_rollback" | "atlassian_get" | "atlassian_search" | "atlassian_sources_list" | "browser_act" | "browser_auth" | "browser_clipboard" | "browser_debug" | "browser_identity" | "browser_lifecycle" | "browser_observe" | "browser_open" | "browser_publish" | "browser_tabs" | "capability_authorization_request" | "capability_catalog_search" | "command_read" | "command_wait" | "company_profile_confirm" | "company_profile_propose" | "computer_act" | "computer_clipboard" | "computer_lifecycle" | "computer_observe" | "computer_open" | "computer_targets" | "connected_machine_remove" | "editable_artifact_apply" | "editable_artifact_create" | "editable_artifact_export" | "editable_artifact_export_status" | "editable_artifact_get" | "editable_artifact_import" | "editable_artifact_inspect" | "editable_artifact_list" | "environment_list" | "environment_set_variable" | "fiken_bank_accounts_list" | "fiken_companies_list" | "fiken_contact_create" | "fiken_contacts_list" | "fiken_invoice_draft_create" | "fiken_invoice_get" | "fiken_invoices_list" | "fiken_products_list" | "fiken_purchases_list" | "fiken_sales_list" | "github_connect_link" | "github_repositories_list" | "goal_complete" | "goal_pause" | "goal_progress" | "goal_resume" | "goal_set" | "goal_update" | "instruction_policy_get" | "instruction_policy_propose" | "instruction_policy_save" | "interaction_discover" | "interaction_request_human" | "knowledge_archive" | "knowledge_browse" | "knowledge_correct" | "knowledge_get" | "knowledge_prepare_save" | "knowledge_propose" | "knowledge_retain_file" | "knowledge_retain_message" | "knowledge_save" | "knowledge_search" | "memory_correct" | "memory_save" | "memory_search" | "preference_propose" | "preference_registry_get" | "preference_registry_summary" | "project_create" | "project_delete" | "project_get" | "project_list" | "project_reorder" | "project_update" | "reddit_accounts_list" | "reddit_mentions_live" | "reddit_post_reply" | "reddit_posts_sync" | "reddit_search_live" | "reddit_thread_fetch" | "remember" | "remember_confirm" | "rig_get" | "rig_list" | "rig_promote" | "rig_propose_change" | "rig_verify" | "run_on" | "sandbox_attach" | "sandbox_file_publish" | "sandbox_provision" | "sandbox_swap" | "sandboxes_list" | "scheduled_task_runs_list" | "scheduled_tasks_create" | "scheduled_tasks_delete" | "scheduled_tasks_get" | "scheduled_tasks_list" | "scheduled_tasks_pause" | "scheduled_tasks_resume" | "scheduled_tasks_trigger" | "scheduled_tasks_update" | "session_create" | "session_events" | "session_get" | "session_human_input_respond" | "session_pause" | "session_resume" | "session_send_message" | "session_set_project" | "session_steer" | "session_wait" | "sessions_list" | "set_other_session_title" | "set_session_title" | "slack_bot_channel_history" | "slack_bot_delete_message" | "slack_bot_file_content" | "slack_bot_file_info" | "slack_bot_list_channels" | "slack_bot_list_files" | "slack_bot_list_users" | "slack_bot_post_message" | "slack_bot_search" | "slack_bot_thread_replies" | "social_connections_list" | "social_daily_analysis_context" | "social_mentions_live" | "social_post_reply" | "social_posts_recent" | "social_posts_sync" | "social_search_live" | "social_thread_fetch" | "task_note_archive" | "task_note_promote_instruction_policy" | "task_note_promote_knowledge" | "task_note_promote_preference" | "task_note_replace" | "task_note_save" | "task_notes_list" | "variable_set_get_variable" | "variable_set_list" | "variable_set_set_variable" | "wait_for_input" | "work_claim_release" | "work_claim_upsert" | "x_accounts_list" | "x_mentions_live" | "x_post_reply" | "x_posts_sync" | "x_search_live" | "x_thread_fetch")[];
23
23
  export type NormalizedSlackInteraction = {
24
24
  providerEventId: string;
25
25
  providerMessageId: string;
@@ -46,6 +46,10 @@ export declare const FIRST_PARTY_TOOL_AUTHORIZATION: {
46
46
  sessionRequired: true;
47
47
  allOf: "documents:search"[];
48
48
  };
49
+ knowledge_prepare_save: {
50
+ sessionRequired: true;
51
+ allOf: "documents:search"[];
52
+ };
49
53
  knowledge_get: {
50
54
  sessionRequired: true;
51
55
  allOf: "documents:search"[];
@@ -82,8 +82,8 @@ export declare function scheduledTaskMcpSummary(task: ScheduledTask): {
82
82
  runMode: "existing_session" | "new_session_per_run" | "reusable_session";
83
83
  overlapPolicy: "allow_concurrent" | "buffer_one" | "skip";
84
84
  action: {
85
+ readonly sourceId?: never;
85
86
  kind: "agent_turn";
86
- sourceId?: never;
87
87
  sourceGeneration?: never;
88
88
  sourceLifecycleGeneration?: never;
89
89
  destination?: never;
@@ -205,8 +205,8 @@ export declare function boundScheduledTaskDetailMcp(task: ScheduledTask): {
205
205
  runMode: "existing_session" | "new_session_per_run" | "reusable_session";
206
206
  overlapPolicy: "allow_concurrent" | "buffer_one" | "skip";
207
207
  action: {
208
+ readonly sourceId?: never;
208
209
  kind: "agent_turn";
209
- sourceId?: never;
210
210
  sourceGeneration?: never;
211
211
  sourceLifecycleGeneration?: never;
212
212
  destination?: never;
@@ -389,8 +389,8 @@ export declare function boundScheduledTaskMcpPage(input: {
389
389
  runMode: "existing_session" | "new_session_per_run" | "reusable_session";
390
390
  overlapPolicy: "allow_concurrent" | "buffer_one" | "skip";
391
391
  action: {
392
+ readonly sourceId?: never;
392
393
  kind: "agent_turn";
393
- sourceId?: never;
394
394
  sourceGeneration?: never;
395
395
  sourceLifecycleGeneration?: never;
396
396
  destination?: never;
@@ -16,6 +16,7 @@ export declare function registerApiIntegrationRoutes(app: Hono, deps: ApiRouteDe
16
16
  export declare function resolveForRoute(input: {
17
17
  deps: ApiRouteDeps;
18
18
  transport: ReturnType<typeof createPinnedIntegrationTransport>;
19
+ accountId: string;
19
20
  workspaceId: string;
20
21
  subjectId: string;
21
22
  payload: PreviewApiIntegrationRequest | InstallApiIntegrationRequest;
@@ -0,0 +1,3 @@
1
+ import { type ApiRouteDeps } from "@opengeni/core";
2
+ import type { Hono } from "hono";
3
+ export declare function registerOrganizationIntegrationPolicyRoutes(app: Hono, deps: ApiRouteDeps): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengeni/api-router",
3
- "version": "3.0.0-canary.0",
3
+ "version": "3.0.1-canary.0",
4
4
  "description": "OpenGeni HTTP surface: the Hono adapter/router (createApp), routes, MCP HTTP transport, and HTTP access adapters over @opengeni/core. An engine-distribution surface — its runtime closure includes engine-internal packages.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -43,24 +43,24 @@
43
43
  "@hono/zod-validator": "^0.7.6",
44
44
  "@llamaindex/liteparse": "2.14.2",
45
45
  "@modelcontextprotocol/sdk": "^1.29.0",
46
- "@opengeni/agent-proto": "^0.6.0-canary.3",
47
- "@opengeni/artifact-tool": "^0.3.28-canary.0",
48
- "@opengeni/capabilities": "^0.3.3-canary.15",
49
- "@opengeni/codemode": "^0.5.8-canary.0",
50
- "@opengeni/codex": "^0.2.23-canary.0",
51
- "@opengeni/config": "^1.2.1-canary.0",
52
- "@opengeni/contracts": "^4.0.0-canary.0",
53
- "@opengeni/core": "^3.0.0-canary.0",
54
- "@opengeni/db": "^5.0.0-canary.0",
55
- "@opengeni/documents": "^0.8.29-canary.0",
56
- "@opengeni/events": "^0.4.27-canary.0",
57
- "@opengeni/github": "^0.7.12-canary.0",
58
- "@opengeni/network": "^0.3.1-canary.15",
59
- "@opengeni/observability": "^0.8.28-canary.0",
60
- "@opengeni/runtime": "^3.0.0-canary.0",
61
- "@opengeni/storage": "^0.2.129-canary.0",
62
- "@opengeni/tool-gateway": "^0.1.9-canary.0",
63
- "@opengeni/xai-subscription": "^0.1.4-canary.15",
46
+ "@opengeni/agent-proto": "^0.6.0-canary.5",
47
+ "@opengeni/artifact-tool": "^0.3.29-canary.0",
48
+ "@opengeni/capabilities": "^0.3.4-canary.0",
49
+ "@opengeni/codemode": "^0.5.9-canary.0",
50
+ "@opengeni/codex": "^0.2.23-canary.2",
51
+ "@opengeni/config": "^1.2.2-canary.0",
52
+ "@opengeni/contracts": "^4.1.0-canary.0",
53
+ "@opengeni/core": "^3.0.1-canary.0",
54
+ "@opengeni/db": "^5.0.1-canary.0",
55
+ "@opengeni/documents": "^0.8.30-canary.0",
56
+ "@opengeni/events": "^0.4.28-canary.0",
57
+ "@opengeni/github": "^0.7.13-canary.0",
58
+ "@opengeni/network": "^0.3.1-canary.17",
59
+ "@opengeni/observability": "^0.8.29-canary.0",
60
+ "@opengeni/runtime": "^3.0.1-canary.0",
61
+ "@opengeni/storage": "^0.2.130-canary.0",
62
+ "@opengeni/tool-gateway": "^0.1.10-canary.0",
63
+ "@opengeni/xai-subscription": "^0.1.4-canary.17",
64
64
  "@temporalio/client": "^1.17.0",
65
65
  "better-auth": "^1.6.14",
66
66
  "hono": "^4.12.18",
package/src/app.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { registerConnectCallbackReturns } from "./integrations/connect-callback-return";
2
2
  import { registerFeedbackRoutes } from "./routes/feedback";
3
3
  import { codemodeSessionRequest } from "./codemode";
4
- import { SiteSessionPathError } from "@opengeni/contracts";
4
+ import { SiteSessionPathError, OrganizationIntegrationDeniedError } from "@opengeni/contracts";
5
5
  import { registerModelConnectionAccessRoutes } from "./routes/model-connection-access";
6
6
  import {
7
7
  canonicalizeConfiguredModelId,
@@ -149,6 +149,7 @@ import { registerCapabilityRoutes } from "./routes/capabilities";
149
149
  import { registerCatalogAssetRoutes } from "./routes/catalog-assets";
150
150
  import { registerCodexRoutes } from "./routes/codex";
151
151
  import { registerOrganizationModelProviderRoutes } from "./routes/organization-model-providers";
152
+ import { registerOrganizationIntegrationPolicyRoutes } from "./routes/organization-integration-policy";
152
153
  import { registerSuperGrokRoutes } from "./routes/supergrok";
153
154
  import { registerConnectionRoutes } from "./routes/connections";
154
155
  import { registerConnectRoutes } from "./routes/connect";
@@ -1278,6 +1279,7 @@ export function createAppComposition(deps: AppDependencies): {
1278
1279
  registerScheduledTaskRoutes(app, routeDeps);
1279
1280
  registerCodexRoutes(app, routeDeps);
1280
1281
  registerOrganizationModelProviderRoutes(app, routeDeps);
1282
+ registerOrganizationIntegrationPolicyRoutes(app, routeDeps);
1281
1283
  registerModelConnectionAccessRoutes(app, routeDeps);
1282
1284
  registerSuperGrokRoutes(app, routeDeps);
1283
1285
  registerTranscriptionRoutes(app, routeDeps);
@@ -1311,7 +1313,10 @@ export function createAppComposition(deps: AppDependencies): {
1311
1313
  app.onError((rawError, c) => {
1312
1314
  // One central mapping for every Send/Steer/control route: a bounded
1313
1315
  // control-prefix wait that expired is a known, retryable, not-applied 503.
1314
- const error = workspaceControlBusyHttpError(rawError) ?? rawError;
1316
+ const error =
1317
+ rawError instanceof OrganizationIntegrationDeniedError
1318
+ ? new HTTPException(403, { message: rawError.message })
1319
+ : (workspaceControlBusyHttpError(rawError) ?? rawError);
1315
1320
  const compactionLock = codexCompactionV2ProviderLockedError(error);
1316
1321
  const apiError = error instanceof ApiHttpError ? error : null;
1317
1322
  const status = compactionLock ? 422 : httpStatusForError(error);