@opengeni/api-router 0.30.3 → 2.2.0-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.
- package/dist/api-websocket.d.ts +18 -0
- package/dist/app.js +1 -1
- package/dist/auth/managed-auth.d.ts +6 -0
- package/dist/{chunk-WCXHI3FF.js → chunk-3TP54PPX.js} +26692 -15389
- package/dist/chunk-3TP54PPX.js.map +1 -0
- package/dist/codemode.d.ts +8 -1
- package/dist/company-brain-okf.d.ts +24 -0
- package/dist/connected-machine-computer-access.d.ts +11 -0
- package/dist/connection-authority-owner.d.ts +59 -0
- package/dist/connection-ownership.d.ts +47 -0
- package/dist/controller-data-plane.d.ts +16 -0
- package/dist/editable-artifact-websocket.d.ts +5 -15
- package/dist/editable-artifact-workspace-files.d.ts +1 -1
- package/dist/http/api-error.d.ts +10 -0
- package/dist/http/cors.d.ts +5 -0
- package/dist/http/interaction-control-error.d.ts +13 -0
- package/dist/http/sse.d.ts +2 -3
- package/dist/index.d.ts +5 -2
- package/dist/index.js +326 -82
- package/dist/index.js.map +1 -1
- package/dist/integrations/atlassian.d.ts +17 -0
- package/dist/integrations/fiken.d.ts +7 -2
- package/dist/integrations/google-drive.d.ts +18 -0
- package/dist/integrations/oauth-client.d.ts +22 -3
- package/dist/integrations/oauth-profiles.d.ts +195 -0
- package/dist/integrations/personal-github-repositories.d.ts +45 -0
- package/dist/integrations/personal-github.d.ts +40 -0
- package/dist/integrations/pr-review-provider.d.ts +22 -0
- package/dist/integrations/provider-oauth.d.ts +8 -0
- package/dist/integrations/slack-app-home.d.ts +24 -0
- package/dist/integrations/slack-bot.d.ts +157 -9
- package/dist/integrations/slack-interactions.d.ts +39 -5
- package/dist/integrations/slack-routing.d.ts +120 -0
- package/dist/integrations/social-oauth.d.ts +5 -0
- package/dist/interaction-frame-proxy.d.ts +68 -0
- package/dist/mcp/company-brain-governed-writes.d.ts +26 -0
- package/dist/mcp/company-profile-agent-admin.d.ts +44 -0
- package/dist/mcp/documents.d.ts +1 -0
- package/dist/mcp/remember.d.ts +28 -0
- package/dist/mcp/request-abort.d.ts +19 -0
- package/dist/mcp/scheduled-task-view.d.ts +4 -4
- package/dist/mcp/server.d.ts +15 -2
- package/dist/mcp/session-view.d.ts +4 -0
- package/dist/mcp/session-wait.d.ts +137 -0
- package/dist/routes/automations.d.ts +4 -0
- package/dist/routes/billing.d.ts +5 -0
- package/dist/routes/browser-sessions.d.ts +4 -1
- package/dist/routes/company-brain.d.ts +3 -0
- package/dist/routes/company-profile.d.ts +2 -1
- package/dist/routes/connection-authorities.d.ts +3 -0
- package/dist/routes/personal-github-git-broker.d.ts +29 -0
- package/dist/routes/personal-github.d.ts +3 -0
- package/dist/routes/pr-review.d.ts +3 -0
- package/dist/routes/sessions.d.ts +1 -0
- package/dist/routes/user-resource-authorities.d.ts +3 -0
- package/dist/routes/workspace-capture.d.ts +10 -2
- package/dist/routes/workspace-learning.d.ts +3 -0
- package/dist/routes/workspaces.d.ts +19 -0
- package/dist/sandbox/channel-a.d.ts +11 -1
- package/dist/sandbox/connection-authority.d.ts +3 -0
- package/dist/sandbox/enrollment.d.ts +2 -0
- package/dist/sandbox/machines.d.ts +2 -2
- package/dist/sandbox/metrics-ingestion.d.ts +10 -20
- package/dist/sandbox/viewer.d.ts +24 -1
- package/dist/sandbox-file-artifacts.d.ts +11 -0
- package/dist/scheduled-task-deletion.d.ts +14 -0
- package/dist/slack-reaction-files.d.ts +1 -1
- package/dist/temporal-schedule-cleanup.d.ts +1 -0
- package/package.json +20 -18
- package/src/api-websocket.ts +23 -0
- package/src/app.ts +161 -23
- package/src/auth/managed-auth.ts +25 -3
- package/src/codemode.ts +53 -23
- package/src/codex-realtime.ts +8 -2
- package/src/company-brain-okf.ts +340 -0
- package/src/connected-machine-computer-access.ts +33 -0
- package/src/connection-authority-owner.ts +61 -0
- package/src/connection-ownership.ts +180 -0
- package/src/controller-data-plane.ts +47 -0
- package/src/editable-artifact-native-kernel.ts +26 -15
- package/src/editable-artifact-office-import.ts +28 -3
- package/src/editable-artifact-production.ts +13 -7
- package/src/editable-artifact-websocket.ts +11 -18
- package/src/editable-artifact-workspace-files.ts +31 -6
- package/src/http/api-error.ts +28 -0
- package/src/http/auth.ts +4 -0
- package/src/http/cors.ts +35 -0
- package/src/http/interaction-control-error.ts +164 -0
- package/src/http/sse.ts +112 -66
- package/src/index.ts +46 -6
- package/src/integrations/atlassian.ts +146 -35
- package/src/integrations/fiken.ts +102 -22
- package/src/integrations/google-drive.ts +301 -92
- package/src/integrations/oauth-client.ts +272 -143
- package/src/integrations/oauth-profiles.ts +477 -0
- package/src/integrations/personal-github-repositories.ts +445 -0
- package/src/integrations/personal-github.ts +705 -0
- package/src/integrations/pr-review-provider.ts +246 -0
- package/src/integrations/provider-oauth.ts +121 -5
- package/src/integrations/slack-app-home.ts +300 -0
- package/src/integrations/slack-bot.ts +342 -57
- package/src/integrations/slack-interactions.ts +1898 -259
- package/src/integrations/slack-routing.ts +337 -0
- package/src/integrations/social-oauth.ts +25 -0
- package/src/interaction-frame-proxy.ts +409 -0
- package/src/mcp/company-brain-governed-writes.ts +262 -0
- package/src/mcp/company-profile-agent-admin.ts +205 -0
- package/src/mcp/documents.ts +37 -6
- package/src/mcp/files.ts +16 -1
- package/src/mcp/remember.ts +181 -0
- package/src/mcp/request-abort.ts +44 -0
- package/src/mcp/scheduled-task-view.ts +1 -0
- package/src/mcp/server.ts +719 -369
- package/src/mcp/session-view.ts +54 -0
- package/src/mcp/session-wait.ts +554 -0
- package/src/model-catalog.ts +20 -12
- package/src/routes/api-integrations.ts +4 -0
- package/src/routes/api-keys.ts +1 -0
- package/src/routes/automations.ts +534 -0
- package/src/routes/billing.ts +57 -1
- package/src/routes/browser-sessions.ts +329 -79
- package/src/routes/channels.ts +17 -1
- package/src/routes/codex.ts +50 -0
- package/src/routes/company-brain.ts +367 -0
- package/src/routes/company-profile.ts +1 -1
- package/src/routes/computer-sessions.ts +320 -93
- package/src/routes/connection-authorities.ts +139 -0
- package/src/routes/connections.ts +144 -34
- package/src/routes/documents.ts +353 -4
- package/src/routes/editable-artifacts.ts +11 -3
- package/src/routes/enrollments.ts +116 -26
- package/src/routes/environments.ts +127 -55
- package/src/routes/files.ts +72 -11
- package/src/routes/install.ts +82 -28
- package/src/routes/integration-facets.ts +29 -0
- package/src/routes/interaction-resources.ts +20 -2
- package/src/routes/machines.ts +275 -13
- package/src/routes/organization-memberships.ts +717 -28
- package/src/routes/packs.ts +4 -3
- package/src/routes/personal-github-git-broker.ts +785 -0
- package/src/routes/personal-github.ts +319 -0
- package/src/routes/pr-review.ts +531 -0
- package/src/routes/rigs.ts +104 -39
- package/src/routes/scheduled-tasks.ts +19 -21
- package/src/routes/sessions.ts +775 -38
- package/src/routes/social.ts +14 -2
- package/src/routes/supergrok.ts +23 -4
- package/src/routes/transcription-recordings.ts +8 -2
- package/src/routes/user-resource-authorities.ts +138 -0
- package/src/routes/workspace-artifacts.ts +4 -1
- package/src/routes/workspace-capture.ts +21 -0
- package/src/routes/workspace-learning.ts +228 -0
- package/src/routes/workspaces.ts +59 -6
- package/src/sandbox/auth-callout.ts +38 -12
- package/src/sandbox/channel-a.ts +242 -19
- package/src/sandbox/connection-authority.ts +3 -0
- package/src/sandbox/enrollment.ts +15 -3
- package/src/sandbox/machines.ts +186 -64
- package/src/sandbox/metrics-ingestion.ts +220 -58
- package/src/sandbox/viewer.ts +243 -19
- package/src/sandbox-file-artifacts.ts +329 -0
- package/src/scheduled-task-deletion.ts +127 -0
- package/src/slack-reaction-files.ts +16 -5
- package/src/temporal-schedule-cleanup.ts +13 -0
- package/dist/chunk-WCXHI3FF.js.map +0 -1
|
@@ -25,6 +25,7 @@ export declare function browseAtlassianSources(deps: ApiRouteDeps, input: {
|
|
|
25
25
|
}): Promise<{
|
|
26
26
|
connection: {
|
|
27
27
|
id: string;
|
|
28
|
+
authorityId?: string | undefined;
|
|
28
29
|
accountId: string;
|
|
29
30
|
workspaceId: string;
|
|
30
31
|
subjectId: string | null;
|
|
@@ -167,10 +168,26 @@ export declare function disconnectAtlassian(deps: ApiRouteDeps, input: {
|
|
|
167
168
|
connection: AtlassianConnectionRecord;
|
|
168
169
|
payload: AtlassianDisconnectRequest;
|
|
169
170
|
}): Promise<import("@opengeni/db").ConnectionMetadataWithVerification | null>;
|
|
171
|
+
export declare function preflightAtlassianScheduleAuthorization(deps: ApiRouteDeps, input: {
|
|
172
|
+
task: ScheduledTask;
|
|
173
|
+
subjectId: string;
|
|
174
|
+
}): Promise<void>;
|
|
170
175
|
export declare function revokeAtlassianScheduleAuthorization(deps: ApiRouteDeps, input: {
|
|
171
176
|
task: ScheduledTask;
|
|
172
177
|
subjectId: string;
|
|
173
178
|
}): Promise<void>;
|
|
179
|
+
export declare function cleanupAtlassianScheduleAuthorization(deps: ApiRouteDeps, input: {
|
|
180
|
+
taskId: string;
|
|
181
|
+
accountId: string;
|
|
182
|
+
workspaceId: string;
|
|
183
|
+
connectionId: string;
|
|
184
|
+
connectionVersion: number;
|
|
185
|
+
sourceId: string;
|
|
186
|
+
sourceLifecycleGeneration: number;
|
|
187
|
+
sourceConfigGeneration: number;
|
|
188
|
+
externalSourceId: string;
|
|
189
|
+
subjectId: string;
|
|
190
|
+
}): Promise<void>;
|
|
174
191
|
export declare function isSelectableConfluenceSpaceType(value: unknown): boolean;
|
|
175
192
|
export declare function confluenceNextUrl(cloudId: string, next: string): URL;
|
|
176
193
|
export {};
|
|
@@ -25,6 +25,7 @@ type FikenContext = {
|
|
|
25
25
|
subjectId: string | null;
|
|
26
26
|
sessionId: string | null;
|
|
27
27
|
};
|
|
28
|
+
type FikenProviderAuthorization = () => Promise<boolean | void>;
|
|
28
29
|
/**
|
|
29
30
|
* Validates a pasted Fiken personal API token before it enters encrypted
|
|
30
31
|
* storage, and discovers the companies it can act on. The companies list is
|
|
@@ -57,8 +58,10 @@ export declare class FikenClient {
|
|
|
57
58
|
private readonly metadata;
|
|
58
59
|
private readonly context;
|
|
59
60
|
private readonly fetchImpl;
|
|
61
|
+
private readonly authorizeProviderRequest?;
|
|
60
62
|
private readonly resolveCredential;
|
|
61
|
-
|
|
63
|
+
private expectedConnectionVersion;
|
|
64
|
+
constructor(db: Database, settings: Settings, connection: ConnectionMetadata, metadata: FikenConnectionMetadata, context: FikenContext, fetchImpl?: FetchLike, authorizeProviderRequest?: FikenProviderAuthorization | undefined);
|
|
62
65
|
listCompanies(input?: {
|
|
63
66
|
page?: number;
|
|
64
67
|
pageSize?: number;
|
|
@@ -202,7 +205,8 @@ export declare class FikenClient {
|
|
|
202
205
|
private request;
|
|
203
206
|
private readResponse;
|
|
204
207
|
private markNeedsReauth;
|
|
205
|
-
private
|
|
208
|
+
private currentAuthority;
|
|
209
|
+
private credentialFor;
|
|
206
210
|
private receipt;
|
|
207
211
|
private recordAudit;
|
|
208
212
|
}
|
|
@@ -210,6 +214,7 @@ export declare function createFikenClient(deps: {
|
|
|
210
214
|
db: Database;
|
|
211
215
|
settings: Settings;
|
|
212
216
|
fikenFetch?: typeof fetch;
|
|
217
|
+
authorizeProviderRequest?: FikenProviderAuthorization;
|
|
213
218
|
}, resolved: Awaited<ReturnType<typeof resolveFikenConnectionForTool>>): FikenClient;
|
|
214
219
|
export declare class FikenOAuthCallbackError extends Error {
|
|
215
220
|
readonly reason: string;
|
|
@@ -52,6 +52,7 @@ export declare function browseGoogleDrive(deps: ApiRouteDeps, input: {
|
|
|
52
52
|
}): Promise<{
|
|
53
53
|
connection: {
|
|
54
54
|
id: string;
|
|
55
|
+
authorityId?: string | undefined;
|
|
55
56
|
accountId: string;
|
|
56
57
|
workspaceId: string;
|
|
57
58
|
subjectId: string | null;
|
|
@@ -107,6 +108,7 @@ export declare function browseGoogleDriveFacetSource(deps: ApiRouteDeps, input:
|
|
|
107
108
|
}): Promise<{
|
|
108
109
|
connection: {
|
|
109
110
|
id: string;
|
|
111
|
+
authorityId?: string | undefined;
|
|
110
112
|
accountId: string;
|
|
111
113
|
workspaceId: string;
|
|
112
114
|
subjectId: string | null;
|
|
@@ -174,8 +176,24 @@ export declare function saveGoogleDriveSource(deps: ApiRouteDeps, input: {
|
|
|
174
176
|
canManageWorkspaceDestination: boolean;
|
|
175
177
|
canManagePersonalDestination: boolean;
|
|
176
178
|
}): Promise<import("@opengeni/db").ConnectionMetadataWithVerification>;
|
|
179
|
+
export declare function preflightKnowledgeSourceScheduleAuthorization(deps: ApiRouteDeps, input: {
|
|
180
|
+
task: ScheduledTask;
|
|
181
|
+
subjectId: string;
|
|
182
|
+
}): Promise<void>;
|
|
177
183
|
export declare function revokeKnowledgeSourceScheduleAuthorization(deps: ApiRouteDeps, input: {
|
|
178
184
|
task: ScheduledTask;
|
|
179
185
|
subjectId: string;
|
|
180
186
|
}): Promise<void>;
|
|
187
|
+
export declare function cleanupKnowledgeSourceScheduleAuthorization(deps: ApiRouteDeps, input: {
|
|
188
|
+
taskId: string;
|
|
189
|
+
accountId: string;
|
|
190
|
+
workspaceId: string;
|
|
191
|
+
connectionId: string;
|
|
192
|
+
connectionVersion: number;
|
|
193
|
+
sourceId: string;
|
|
194
|
+
sourceLifecycleGeneration: number;
|
|
195
|
+
sourceConfigGeneration: number;
|
|
196
|
+
externalSourceId: string;
|
|
197
|
+
subjectId: string;
|
|
198
|
+
}): Promise<void>;
|
|
181
199
|
export {};
|
|
@@ -2,10 +2,9 @@ import { type Settings } from "@opengeni/config";
|
|
|
2
2
|
import { OAuthStartResponse, type ConnectionOwnership, type OAuthStartRequest } from "@opengeni/contracts";
|
|
3
3
|
import type { Observability } from "@opengeni/observability";
|
|
4
4
|
import { type Database } from "@opengeni/db";
|
|
5
|
+
import { type OAuthProviderProfile } from "./oauth-profiles.js";
|
|
5
6
|
export declare const oauthStateTtlMs: number;
|
|
6
|
-
export
|
|
7
|
-
export declare const OFFICIAL_GMAIL_MCP_URL = "https://gmailmcp.googleapis.com/mcp/v1";
|
|
8
|
-
export declare const OFFICIAL_GMAIL_MCP_SCOPES: readonly ["https://www.googleapis.com/auth/gmail.readonly", "https://www.googleapis.com/auth/gmail.compose", "https://www.googleapis.com/auth/gmail.modify"];
|
|
7
|
+
export { OFFICIAL_GMAIL_MCP_SCOPES, OFFICIAL_GMAIL_MCP_URL, OFFICIAL_SLACK_MCP_URL, } from "./oauth-profiles.js";
|
|
9
8
|
export { OAUTH_MAX_RESPONSE_BYTES } from "@opengeni/network";
|
|
10
9
|
type OAuthClientDeps = {
|
|
11
10
|
db: Database;
|
|
@@ -18,6 +17,12 @@ export type OAuthStartContext = {
|
|
|
18
17
|
accountId: string;
|
|
19
18
|
workspaceId: string;
|
|
20
19
|
subjectId: string;
|
|
20
|
+
/**
|
|
21
|
+
* False for every principal that cannot own a personal Connection (API keys,
|
|
22
|
+
* the configured key, services, agent attempts). Resolved by the route from
|
|
23
|
+
* the live authenticated principal, never inferred here.
|
|
24
|
+
*/
|
|
25
|
+
personalOwnershipAllowed: boolean;
|
|
21
26
|
requestUrl: string;
|
|
22
27
|
payload: OAuthStartRequest;
|
|
23
28
|
};
|
|
@@ -39,7 +44,16 @@ export declare const OAUTH_START_DEADLINE_MS = 15000;
|
|
|
39
44
|
export declare const OAUTH_CALLBACK_DEADLINE_MS = 30000;
|
|
40
45
|
export type OAuthStartStage = "connection_lookup" | "mcp_challenge" | "protected_resource_metadata" | "authorization_server_metadata" | "client_registration";
|
|
41
46
|
export declare function startMcpOAuth(deps: OAuthClientDeps, context: OAuthStartContext): Promise<OAuthStartResponse>;
|
|
47
|
+
/** Ownership fence for the official Gmail profile, keyed by exact MCP URL. */
|
|
42
48
|
export declare function assertOfficialGmailPersonalOwnership(mcpUrl: string, ownership: ConnectionOwnership): void;
|
|
49
|
+
/**
|
|
50
|
+
* Slack's hosted MCP issues user tokens only. Sharing one human's grant as
|
|
51
|
+
* workspace authority made every shared agent act as a named employee; the
|
|
52
|
+
* OpenGeni workspace bot owns shared Slack access instead (bot-token search
|
|
53
|
+
* covers public channels, files, and users).
|
|
54
|
+
*/
|
|
55
|
+
export declare function assertHostedSlackMcpPersonalOwnership(hostedSlackMcp: boolean, ownership: ConnectionOwnership): void;
|
|
56
|
+
export declare function isHostedSlackMcpTarget(providerDomain: string, mcpUrl: string): boolean;
|
|
43
57
|
export declare function completeMcpOAuthCallback(deps: OAuthClientDeps, input: {
|
|
44
58
|
code?: string | undefined;
|
|
45
59
|
state?: string | undefined;
|
|
@@ -47,8 +61,11 @@ export declare function completeMcpOAuthCallback(deps: OAuthClientDeps, input: {
|
|
|
47
61
|
}): Promise<OAuthCallbackResult>;
|
|
48
62
|
export declare function integrationBaseUrl(publicBaseUrl: string | undefined, requestUrl: string): string;
|
|
49
63
|
export declare function requireIntegrationsStateSecret(settings: Settings): string;
|
|
64
|
+
/** The hosted-Slack profile's origin pins, kept exported for its tests. */
|
|
50
65
|
export declare function assertSlackAuthorizationServer(as: AuthorizationServerMetadata): void;
|
|
66
|
+
/** The official-Gmail profile's origin pins, kept exported for its tests. */
|
|
51
67
|
export declare function assertGoogleAuthorizationServer(as: AuthorizationServerMetadata): void;
|
|
68
|
+
export declare function preferredOAuthSelfRegistration(as: Pick<AuthorizationServerMetadata, "clientIdMetadataDocumentSupported" | "registrationEndpoint">, clientSource: OAuthProviderProfile["clientSource"]): "cimd" | "dcr" | null;
|
|
52
69
|
export declare function buildAuthorizationUrl(input: {
|
|
53
70
|
endpoint: string;
|
|
54
71
|
settings: Settings;
|
|
@@ -59,6 +76,8 @@ export declare function buildAuthorizationUrl(input: {
|
|
|
59
76
|
verifier: string;
|
|
60
77
|
scopes: string[];
|
|
61
78
|
resourceParameterSupported: boolean;
|
|
79
|
+
/** Profile-declared extra authorize parameters, applied last. */
|
|
80
|
+
extraParams?: Readonly<Record<string, string>> | undefined;
|
|
62
81
|
}): string;
|
|
63
82
|
export type OAuthPublicErrorFields = {
|
|
64
83
|
errorClass: "OAuthOperationError";
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { type ConnectionOwnership } from "@opengeni/contracts";
|
|
2
|
+
import type { Settings } from "@opengeni/config";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
/**
|
|
5
|
+
* Provider OAuth quirks as data.
|
|
6
|
+
*
|
|
7
|
+
* Some providers do not support DCR or CIMD and need a pre-registered client
|
|
8
|
+
* with pinned metadata; some issue personal tokens only; some reject RFC 8707's
|
|
9
|
+
* `resource` parameter. Each used to be a hand-written branch set inside
|
|
10
|
+
* `oauth-client.ts`; every quirk is now a field on an `OAuthProviderProfile`.
|
|
11
|
+
* The flow reads exactly one resolved profile and contains no provider-name
|
|
12
|
+
* conditional.
|
|
13
|
+
*
|
|
14
|
+
* Profiles come from two layers:
|
|
15
|
+
*
|
|
16
|
+
* 1. Built-in profiles below, for the providers whose fences are security
|
|
17
|
+
* invariants (hosted Slack MCP and official Gmail are personal-only, their
|
|
18
|
+
* authorization servers are origin-pinned). These live in code as data so
|
|
19
|
+
* the fences never depend on catalog import state.
|
|
20
|
+
* 2. A validated `oauthProfile` object on a global catalog row (curated
|
|
21
|
+
* overlay -> importer -> `capability_catalog_items.metadata`). A catalog
|
|
22
|
+
* profile applies only when no built-in matches, and it can only narrow the
|
|
23
|
+
* default behavior, never loosen a built-in fence.
|
|
24
|
+
*/
|
|
25
|
+
export declare const OFFICIAL_SLACK_MCP_URL: "https://mcp.slack.com/mcp";
|
|
26
|
+
export declare const OFFICIAL_GMAIL_MCP_URL = "https://gmailmcp.googleapis.com/mcp/v1";
|
|
27
|
+
export declare const OFFICIAL_GMAIL_MCP_SCOPES: readonly ["https://www.googleapis.com/auth/gmail.readonly", "https://www.googleapis.com/auth/gmail.compose", "https://www.googleapis.com/auth/gmail.modify"];
|
|
28
|
+
/** The slice of discovered authorization-server metadata the pins constrain. */
|
|
29
|
+
export type PinnableAuthorizationServer = {
|
|
30
|
+
issuer: string;
|
|
31
|
+
authorizationServer: string;
|
|
32
|
+
authorizationEndpoint: string;
|
|
33
|
+
tokenEndpoint: string;
|
|
34
|
+
};
|
|
35
|
+
export type AuthorizationServerPins = {
|
|
36
|
+
/** Origins `issuer` and `authorizationServer` must both belong to. */
|
|
37
|
+
issuerOrigins: readonly string[];
|
|
38
|
+
/** Origins the authorization endpoint must belong to. */
|
|
39
|
+
authorizationEndpointOrigins: readonly string[];
|
|
40
|
+
/** Origins the token endpoint must belong to. */
|
|
41
|
+
tokenEndpointOrigins: readonly string[];
|
|
42
|
+
/** Exact 422 message when a pin fails. */
|
|
43
|
+
message: string;
|
|
44
|
+
/** Skip enforcement in a local test environment (loopback fixtures). */
|
|
45
|
+
skipInLocalTest: boolean;
|
|
46
|
+
};
|
|
47
|
+
export type OAuthProviderProfile = {
|
|
48
|
+
/** Stable identity for guards, logs, and tests. */
|
|
49
|
+
key: string;
|
|
50
|
+
/** Built-in matching; catalog profiles match their own row's exact mcpUrl. */
|
|
51
|
+
match: {
|
|
52
|
+
mcpUrls?: readonly string[];
|
|
53
|
+
providerDomains?: readonly string[];
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Canonical provider identity forced when the profile matches by URL, so a
|
|
57
|
+
* caller cannot relabel a pinned resource under another domain.
|
|
58
|
+
*/
|
|
59
|
+
canonicalProviderDomain?: string;
|
|
60
|
+
/** Reject a caller-supplied manual OAuth client (deployment-managed only). */
|
|
61
|
+
rejectCallerOAuthClient?: {
|
|
62
|
+
message: string;
|
|
63
|
+
};
|
|
64
|
+
/** The payload's explicit providerDomain must canonicalize to this domain. */
|
|
65
|
+
requireProviderDomain?: {
|
|
66
|
+
domain: string;
|
|
67
|
+
message: string;
|
|
68
|
+
};
|
|
69
|
+
/** Outside a local test environment, the start URL must be exactly this. */
|
|
70
|
+
requireExactMcpUrl?: {
|
|
71
|
+
url: string;
|
|
72
|
+
message: string;
|
|
73
|
+
};
|
|
74
|
+
/** Deployment-managed client credentials must be configured (503 otherwise). */
|
|
75
|
+
requireDeploymentClient?: {
|
|
76
|
+
key: DeploymentManagedClientKey;
|
|
77
|
+
message: string;
|
|
78
|
+
};
|
|
79
|
+
/** Ownerships a connection may take; a singleton also sets the default. */
|
|
80
|
+
allowedOwnership: readonly ConnectionOwnership[];
|
|
81
|
+
/** Exact 422 message when an explicit disallowed ownership is requested. */
|
|
82
|
+
ownershipMessage?: string;
|
|
83
|
+
/** Bind reconnect/dedupe to the exact mcpUrl, not just the provider domain. */
|
|
84
|
+
exactMcpBinding: boolean;
|
|
85
|
+
/** How an existing connection is chosen for reconnect coalescing. */
|
|
86
|
+
connectionSelection: "canonical_personal" | "first_active";
|
|
87
|
+
/** Post-discovery authorization-server origin pins. */
|
|
88
|
+
authorizationServer?: AuthorizationServerPins;
|
|
89
|
+
/**
|
|
90
|
+
* Post-discovery identity check: the resolved providerDomain must equal this
|
|
91
|
+
* domain (the reserved-authorization-server guard shares its message).
|
|
92
|
+
*/
|
|
93
|
+
postDiscoveryProviderDomain?: {
|
|
94
|
+
domain: string;
|
|
95
|
+
message: string;
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* Client registration preference. `dcr` or `cimd` forces that advertised
|
|
99
|
+
* self-registration mechanism after operator/deployment clients. Without an
|
|
100
|
+
* explicit preference, DCR wins when both mechanisms are advertised.
|
|
101
|
+
*/
|
|
102
|
+
clientSource?: "deployment_managed" | "cimd" | "dcr";
|
|
103
|
+
/** Send RFC 8707 `resource` on authorize and token requests. */
|
|
104
|
+
sendResourceParameter: boolean;
|
|
105
|
+
/** Extra authorize-URL query parameters (e.g. offline-consent opts). */
|
|
106
|
+
extraAuthorizeParams?: Readonly<Record<string, string>>;
|
|
107
|
+
/** Exact scope override; the caller can never widen past it. */
|
|
108
|
+
requestedScopes?: readonly string[];
|
|
109
|
+
};
|
|
110
|
+
export declare const DEFAULT_OAUTH_PROFILE: OAuthProviderProfile;
|
|
111
|
+
/** Exact built-in profile by its stable key; throws on an unknown key. */
|
|
112
|
+
export declare function builtInOAuthProfileByKey(key: string): OAuthProviderProfile;
|
|
113
|
+
export type DeploymentManagedClientKey = "slack";
|
|
114
|
+
/**
|
|
115
|
+
* Pre-registered deployment clients resolved from dedicated settings, keyed by
|
|
116
|
+
* the authorization-server origins they serve. Consulted before the operator
|
|
117
|
+
* clients JSON so a deployment-managed provider can never be shadowed.
|
|
118
|
+
*/
|
|
119
|
+
export declare const DEPLOYMENT_MANAGED_CLIENTS: readonly {
|
|
120
|
+
key: DeploymentManagedClientKey;
|
|
121
|
+
issuerOrigins: readonly string[];
|
|
122
|
+
resolve: (settings: Settings) => {
|
|
123
|
+
clientId: string;
|
|
124
|
+
clientSecret: string;
|
|
125
|
+
tokenEndpointAuthMethod: "client_secret_post";
|
|
126
|
+
} | null;
|
|
127
|
+
}[];
|
|
128
|
+
export declare function deploymentManagedClientFor(settings: Settings, key: DeploymentManagedClientKey): ReturnType<(typeof DEPLOYMENT_MANAGED_CLIENTS)[number]["resolve"]>;
|
|
129
|
+
/** Built-in profile for a start target, or null when only the default applies. */
|
|
130
|
+
export declare function builtInOAuthProfileFor(input: {
|
|
131
|
+
mcpUrl: string;
|
|
132
|
+
providerDomain?: string | undefined;
|
|
133
|
+
}): OAuthProviderProfile | null;
|
|
134
|
+
/** Ownership an omitted request defaults to under a profile. */
|
|
135
|
+
export declare function defaultOwnershipFor(profile: OAuthProviderProfile): ConnectionOwnership;
|
|
136
|
+
/** Rejects an ownership outside the profile's allowed set with its exact message. */
|
|
137
|
+
export declare function assertOwnershipAllowed(profile: OAuthProviderProfile, ownership: ConnectionOwnership): void;
|
|
138
|
+
/** Enforces a profile's authorization-server origin pins with its exact message. */
|
|
139
|
+
export declare function assertAuthorizationServerPins(as: PinnableAuthorizationServer, pins: Pick<AuthorizationServerPins, "issuerOrigins" | "authorizationEndpointOrigins" | "tokenEndpointOrigins" | "message">): void;
|
|
140
|
+
/**
|
|
141
|
+
* Reserved-authorization-server guard: a discovered identity claimed by one
|
|
142
|
+
* profile is rejected on every other flow with that guard's exact message.
|
|
143
|
+
*/
|
|
144
|
+
export declare function assertAuthorizationServerNotReserved(as: PinnableAuthorizationServer, profile: OAuthProviderProfile): void;
|
|
145
|
+
/**
|
|
146
|
+
* Catalog-row profile: the declarative subset a curated row may carry. It can
|
|
147
|
+
* only narrow the default flow; the fields that grant authority (deployment
|
|
148
|
+
* client settings, reserved-server membership) are built-in-only by
|
|
149
|
+
* construction because the schema cannot express them.
|
|
150
|
+
*/
|
|
151
|
+
/**
|
|
152
|
+
* Authorize-URL parameters owned by the OAuth client itself. A profile's
|
|
153
|
+
* `extraAuthorizeParams` may never name one: overriding `scope` or `resource`
|
|
154
|
+
* would widen the grant past the recorded contract, and the rest carry the
|
|
155
|
+
* PKCE/state security machinery. Enforced in this schema, in the curation
|
|
156
|
+
* parser, and defensively again in `buildAuthorizationUrl`.
|
|
157
|
+
*/
|
|
158
|
+
export declare const RESERVED_AUTHORIZE_PARAMS: ReadonlySet<string>;
|
|
159
|
+
export declare const catalogOAuthProfileSchema: z.ZodObject<{
|
|
160
|
+
clientSource: z.ZodOptional<z.ZodEnum<{
|
|
161
|
+
cimd: "cimd";
|
|
162
|
+
dcr: "dcr";
|
|
163
|
+
deployment_managed: "deployment_managed";
|
|
164
|
+
}>>;
|
|
165
|
+
exactMcpUrl: z.ZodOptional<z.ZodString>;
|
|
166
|
+
pinnedIssuerOrigins: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
167
|
+
pinnedEndpointOrigins: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
168
|
+
sendResourceParameter: z.ZodOptional<z.ZodBoolean>;
|
|
169
|
+
allowedOwnership: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
170
|
+
personal: "personal";
|
|
171
|
+
workspace: "workspace";
|
|
172
|
+
}>>>;
|
|
173
|
+
requestedScopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
174
|
+
extraAuthorizeParams: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
175
|
+
}, z.core.$strict>;
|
|
176
|
+
export type CatalogOAuthProfile = z.infer<typeof catalogOAuthProfileSchema>;
|
|
177
|
+
/**
|
|
178
|
+
* Canonical catalog lookup key for an MCP URL, mirroring the importer's
|
|
179
|
+
* `canonicalMcpUrl` (`scripts/catalog-curation.ts`): no fragment, lowercase
|
|
180
|
+
* host, default ports stripped, trailing slashes collapsed. Without this, a
|
|
181
|
+
* trailing-slash or uppercase-host variant of a profiled URL would miss the
|
|
182
|
+
* row and silently fall back to the default profile.
|
|
183
|
+
*/
|
|
184
|
+
export declare function catalogMcpUrlKey(value: string): string;
|
|
185
|
+
/**
|
|
186
|
+
* Applies a validated catalog profile over the default profile for a row with
|
|
187
|
+
* no built-in. `deployment_managed` from catalog data resolves through the
|
|
188
|
+
* operator clients JSON (issuer-keyed) only; named settings-backed clients
|
|
189
|
+
* remain built-in-only.
|
|
190
|
+
*
|
|
191
|
+
* A present-but-invalid profile fails closed with a 422: the row's operator
|
|
192
|
+
* declared constraints, and silently degrading to the default profile would
|
|
193
|
+
* drop an ownership fence or origin pin on a JSON typo.
|
|
194
|
+
*/
|
|
195
|
+
export declare function oauthProfileFromCatalog(mcpUrl: string, raw: unknown): OAuthProviderProfile;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { type PersonalGitHubRepository as PersonalGitHubRepositoryContract, type PersonalGitHubRepositorySelectionInput } from "@opengeni/contracts/personal-github";
|
|
2
|
+
import type { ApiRouteDeps } from "@opengeni/core";
|
|
3
|
+
import { getConnectionMetadata } from "@opengeni/db";
|
|
4
|
+
import { HTTPException } from "hono/http-exception";
|
|
5
|
+
export type PersonalGitHubRepositoryConnection = NonNullable<Awaited<ReturnType<typeof getConnectionMetadata>>>;
|
|
6
|
+
export type PersonalGitHubRepositoryProviderErrorCode = "connection_changed" | "connection_inactive" | "invalid_provider_response" | "provider_denied" | "provider_rate_limited" | "provider_unavailable" | "repository_archived" | "repository_not_found" | "repository_read_denied" | "repository_write_denied";
|
|
7
|
+
export declare class PersonalGitHubRepositoryProviderError extends Error {
|
|
8
|
+
readonly code: PersonalGitHubRepositoryProviderErrorCode;
|
|
9
|
+
constructor(code: PersonalGitHubRepositoryProviderErrorCode);
|
|
10
|
+
}
|
|
11
|
+
export declare function requirePersonalGitHubRepositoryConnection(deps: ApiRouteDeps, input: {
|
|
12
|
+
accountId: string;
|
|
13
|
+
workspaceId: string;
|
|
14
|
+
subjectId: string;
|
|
15
|
+
connectionId: string;
|
|
16
|
+
}): Promise<PersonalGitHubRepositoryConnection>;
|
|
17
|
+
export declare function listLivePersonalGitHubRepositories(deps: ApiRouteDeps, input: {
|
|
18
|
+
workspaceId: string;
|
|
19
|
+
accountId: string;
|
|
20
|
+
subjectId: string;
|
|
21
|
+
connectionId: string;
|
|
22
|
+
expectedConnectionAuthorityGeneration: number;
|
|
23
|
+
page: number;
|
|
24
|
+
limit: number;
|
|
25
|
+
}): Promise<{
|
|
26
|
+
repositories: PersonalGitHubRepositoryContract[];
|
|
27
|
+
nextPage: number | null;
|
|
28
|
+
}>;
|
|
29
|
+
/** Serial by design: one bounded provider request and one authority check at a time. */
|
|
30
|
+
export declare function verifyLivePersonalGitHubRepositories(deps: ApiRouteDeps, input: {
|
|
31
|
+
workspaceId: string;
|
|
32
|
+
accountId: string;
|
|
33
|
+
subjectId: string;
|
|
34
|
+
connectionId: string;
|
|
35
|
+
expectedConnectionAuthorityGeneration: number;
|
|
36
|
+
repositories: PersonalGitHubRepositorySelectionInput[];
|
|
37
|
+
}): Promise<Array<PersonalGitHubRepositoryContract & {
|
|
38
|
+
selectedAccess: "read" | "write";
|
|
39
|
+
}>>;
|
|
40
|
+
export declare function personalGitHubRepositoryProviderHttpError(error: PersonalGitHubRepositoryProviderError): HTTPException;
|
|
41
|
+
/** Keep provider integer lexemes exact before repository IDs become bigint-backed strings. */
|
|
42
|
+
export declare function parsePersonalGitHubProviderJson(value: string): unknown;
|
|
43
|
+
export declare function personalGitHubRepositoryCanRead(permissions: PersonalGitHubRepositoryContract["permissions"]): boolean;
|
|
44
|
+
export declare function personalGitHubRepositoryCanWrite(permissions: PersonalGitHubRepositoryContract["permissions"]): boolean;
|
|
45
|
+
export declare function parsePersonalGitHubRepository(value: unknown): PersonalGitHubRepositoryContract;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { type Settings } from "@opengeni/config";
|
|
2
|
+
import { type PersonalGitHubDisconnectRequest } from "@opengeni/contracts/personal-github";
|
|
3
|
+
import { type AccessGrantAuthorization, type ApiRouteDeps } from "@opengeni/core";
|
|
4
|
+
export declare function personalGitHubClientMarker(clientId: string): string;
|
|
5
|
+
export declare function requirePersonalGitHubOAuthSettings(settings: Settings): {
|
|
6
|
+
clientId: string;
|
|
7
|
+
clientSecret: string;
|
|
8
|
+
callbackUrl: string;
|
|
9
|
+
oauthEnvironment: string;
|
|
10
|
+
oauthClientMarker: string;
|
|
11
|
+
};
|
|
12
|
+
export declare function listPersonalGitHubConnections(deps: ApiRouteDeps, input: {
|
|
13
|
+
workspaceId: string;
|
|
14
|
+
subjectId: string;
|
|
15
|
+
}): Promise<import("@opengeni/db").ConnectionMetadataWithVerification[]>;
|
|
16
|
+
export declare function disconnectPersonalGitHub(deps: ApiRouteDeps, input: {
|
|
17
|
+
workspaceId: string;
|
|
18
|
+
subjectId: string;
|
|
19
|
+
connectionId: string;
|
|
20
|
+
payload: PersonalGitHubDisconnectRequest;
|
|
21
|
+
}): Promise<import("@opengeni/db").ConnectionMetadataWithVerification | null>;
|
|
22
|
+
export declare function startPersonalGitHubOAuth(deps: ApiRouteDeps, input: {
|
|
23
|
+
access: AccessGrantAuthorization;
|
|
24
|
+
workspaceId: string;
|
|
25
|
+
connectionId?: string;
|
|
26
|
+
returnPath?: string;
|
|
27
|
+
}): Promise<{
|
|
28
|
+
authorizationUrl: string;
|
|
29
|
+
expiresAt: string;
|
|
30
|
+
}>;
|
|
31
|
+
export declare function completePersonalGitHubOAuthCallback(deps: ApiRouteDeps, input: {
|
|
32
|
+
code?: string;
|
|
33
|
+
state?: string;
|
|
34
|
+
error?: string;
|
|
35
|
+
requestUrl: string;
|
|
36
|
+
}): Promise<{
|
|
37
|
+
redirectTo: string;
|
|
38
|
+
}>;
|
|
39
|
+
export declare function personalGitHubReviewUrl(settings: Settings): string | null;
|
|
40
|
+
export declare const PERSONAL_GITHUB_CONNECTION_PRINCIPAL_MESSAGE: string;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { PrReviewProvider } from "@opengeni/contracts";
|
|
2
|
+
import { type FetchLike, type OutboundNetworkSettings } from "@opengeni/network";
|
|
3
|
+
export declare class PrReviewProviderRepositoryError extends Error {
|
|
4
|
+
readonly reason: "denied" | "identity_mismatch" | "unavailable";
|
|
5
|
+
constructor(reason: "denied" | "identity_mismatch" | "unavailable", message: string);
|
|
6
|
+
}
|
|
7
|
+
export type VerifiedPrReviewProviderRepository = {
|
|
8
|
+
repositoryUri: string;
|
|
9
|
+
repositoryFullName: string;
|
|
10
|
+
providerRepositoryId: string;
|
|
11
|
+
projectId: string;
|
|
12
|
+
};
|
|
13
|
+
export declare function verifyPrReviewProviderRepository(input: {
|
|
14
|
+
provider: Exclude<PrReviewProvider, "github">;
|
|
15
|
+
providerBaseUrl: string;
|
|
16
|
+
providerRepositoryId: string;
|
|
17
|
+
projectId?: string;
|
|
18
|
+
token: string;
|
|
19
|
+
username: string | null;
|
|
20
|
+
settings: OutboundNetworkSettings;
|
|
21
|
+
fetchImpl?: FetchLike;
|
|
22
|
+
}): Promise<VerifiedPrReviewProviderRepository>;
|
|
@@ -1,9 +1,16 @@
|
|
|
1
|
+
import { type Settings } from "@opengeni/config";
|
|
1
2
|
import { OAuthStartResponse, type ApiIntegrationOAuthStartRequest } from "@opengeni/contracts";
|
|
2
3
|
import { type ApiRouteDeps } from "@opengeni/core";
|
|
3
4
|
export declare function startApiIntegrationProviderOAuth(deps: ApiRouteDeps, input: {
|
|
4
5
|
accountId: string;
|
|
5
6
|
workspaceId: string;
|
|
6
7
|
subjectId: string;
|
|
8
|
+
/**
|
|
9
|
+
* False for every principal that cannot own a personal Connection (API
|
|
10
|
+
* keys, the configured key, services, agent attempts). Resolved by the
|
|
11
|
+
* route from the live authenticated principal, never inferred here.
|
|
12
|
+
*/
|
|
13
|
+
personalOwnershipAllowed: boolean;
|
|
7
14
|
requestUrl: string;
|
|
8
15
|
payload: ApiIntegrationOAuthStartRequest;
|
|
9
16
|
}): Promise<OAuthStartResponse>;
|
|
@@ -15,3 +22,4 @@ export declare function completeApiIntegrationProviderOAuth(deps: ApiRouteDeps,
|
|
|
15
22
|
}): Promise<{
|
|
16
23
|
redirectTo: string;
|
|
17
24
|
}>;
|
|
25
|
+
export declare function isApiIntegrationProviderOAuthState(value: string | undefined, settings: Settings): boolean;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Session } from "@opengeni/contracts";
|
|
2
|
+
import type { SlackHomeBlock } from "./slack-bot.js";
|
|
3
|
+
export type SlackAppHomeOpenedEvent = {
|
|
4
|
+
eventId: string;
|
|
5
|
+
slackTeamId: string;
|
|
6
|
+
slackUserId: string;
|
|
7
|
+
viewHash: string | null;
|
|
8
|
+
};
|
|
9
|
+
export declare function slackAppHomeOpenedEvent(payload: unknown): SlackAppHomeOpenedEvent | null;
|
|
10
|
+
/** URL-only App Home buttons are acknowledged but never become Slack commands. */
|
|
11
|
+
export declare function isSlackAppHomeLinkAction(payload: unknown): boolean;
|
|
12
|
+
export declare function buildSlackAppHomeBlocks(input: {
|
|
13
|
+
sessions: readonly Session[];
|
|
14
|
+
workspaceUrl: string | null;
|
|
15
|
+
sessionUrl: (sessionId: string) => string | null;
|
|
16
|
+
nowMs?: number;
|
|
17
|
+
}): SlackHomeBlock[];
|
|
18
|
+
export declare function buildSlackAppHomeAccessBlocks(input: {
|
|
19
|
+
title: string;
|
|
20
|
+
message: string;
|
|
21
|
+
actionLabel?: string;
|
|
22
|
+
actionUrl?: string | null;
|
|
23
|
+
}): SlackHomeBlock[];
|
|
24
|
+
export declare function escapeSlackMrkdwn(value: string): string;
|