@opengeni/api-router 3.3.0 → 3.4.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/access-grant-rls.d.ts +15 -0
- package/dist/app.js +1 -1
- package/dist/billing-stripe-customer.d.ts +18 -0
- package/dist/billing-subscription-store.d.ts +34 -0
- package/dist/billing-subscriptions.d.ts +64 -0
- package/dist/{chunk-6CECHDZP.js → chunk-6DZ4H5JQ.js} +2684 -1410
- package/dist/{chunk-6CECHDZP.js.map → chunk-6DZ4H5JQ.js.map} +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/integrations/marketplace-plugin.d.ts +43 -43
- package/dist/mcp/scheduled-task-view.d.ts +4 -4
- package/dist/mcp/server.d.ts +11 -1
- package/dist/routes/browser-sessions.d.ts +23 -2
- package/dist/routes/sessions.d.ts +1 -0
- package/package.json +24 -24
- package/src/access-grant-rls.ts +98 -10
- package/src/app.ts +105 -43
- package/src/billing-stripe-customer.ts +40 -0
- package/src/billing-subscription-store.ts +121 -0
- package/src/billing-subscriptions.ts +759 -0
- package/src/index.ts +3 -0
- package/src/mcp/action-catalog.gen.ts +113 -0
- package/src/mcp/action-schema-imports.gen.ts +5 -1
- package/src/mcp/server.ts +28 -0
- package/src/routes/billing.ts +161 -21
- package/src/routes/browser-sessions.ts +359 -9
- package/src/routes/organization-memberships.ts +12 -0
- package/src/routes/sessions.ts +8 -1
package/src/index.ts
CHANGED
|
@@ -343,6 +343,9 @@ export async function startApi(
|
|
|
343
343
|
max: settings.apiDatabasePoolMax,
|
|
344
344
|
...(searchPath ? { searchPath } : {}),
|
|
345
345
|
rlsStrategy: settings.rlsStrategy,
|
|
346
|
+
...(settings.databasePreparedStatements === undefined
|
|
347
|
+
? {}
|
|
348
|
+
: { preparedStatements: settings.databasePreparedStatements }),
|
|
346
349
|
});
|
|
347
350
|
let bus: Awaited<ReturnType<typeof createNatsEventBus>> | undefined;
|
|
348
351
|
let workflowClient: Awaited<ReturnType<typeof createTemporalWorkflowClient>> | undefined;
|
|
@@ -191,6 +191,17 @@ export const ACTION_CATALOG: readonly ActionCatalogEntry[] = [
|
|
|
191
191
|
"WorkspaceMember"
|
|
192
192
|
]
|
|
193
193
|
},
|
|
194
|
+
{
|
|
195
|
+
"id": "adoptBrowserSessionWorkingCopy",
|
|
196
|
+
"method": "POST",
|
|
197
|
+
"path": "/v1/workspaces/:workspaceId/browser-sessions/:browserSessionId/working-copy/adoptions",
|
|
198
|
+
"request": [
|
|
199
|
+
"BrowserWorkingCopyAdoptionRequest"
|
|
200
|
+
],
|
|
201
|
+
"response": [
|
|
202
|
+
"BrowserWorkingCopyAdoptionResponse"
|
|
203
|
+
]
|
|
204
|
+
},
|
|
194
205
|
{
|
|
195
206
|
"id": "advanceConnectAttempt",
|
|
196
207
|
"method": "POST",
|
|
@@ -427,6 +438,17 @@ export const ACTION_CATALOG: readonly ActionCatalogEntry[] = [
|
|
|
427
438
|
"ToolGatewayDeclarationsResponse"
|
|
428
439
|
]
|
|
429
440
|
},
|
|
441
|
+
{
|
|
442
|
+
"id": "cancelBillingSubscription",
|
|
443
|
+
"method": "POST",
|
|
444
|
+
"path": "/v1/billing/subscription/cancel",
|
|
445
|
+
"request": [
|
|
446
|
+
"CancelBillingSubscriptionRequest"
|
|
447
|
+
],
|
|
448
|
+
"response": [
|
|
449
|
+
"BillingSubscriptionChange"
|
|
450
|
+
]
|
|
451
|
+
},
|
|
430
452
|
{
|
|
431
453
|
"id": "cancelConnectAttempt",
|
|
432
454
|
"method": "POST",
|
|
@@ -482,6 +504,17 @@ export const ACTION_CATALOG: readonly ActionCatalogEntry[] = [
|
|
|
482
504
|
"request": [],
|
|
483
505
|
"response": []
|
|
484
506
|
},
|
|
507
|
+
{
|
|
508
|
+
"id": "changeBillingSubscription",
|
|
509
|
+
"method": "POST",
|
|
510
|
+
"path": "/v1/billing/subscription/change",
|
|
511
|
+
"request": [
|
|
512
|
+
"ChangeBillingSubscriptionRequest"
|
|
513
|
+
],
|
|
514
|
+
"response": [
|
|
515
|
+
"BillingSubscriptionChange"
|
|
516
|
+
]
|
|
517
|
+
},
|
|
485
518
|
{
|
|
486
519
|
"id": "changeMachineAudience",
|
|
487
520
|
"method": "PUT",
|
|
@@ -1112,6 +1145,28 @@ export const ACTION_CATALOG: readonly ActionCatalogEntry[] = [
|
|
|
1112
1145
|
"AutomationSource"
|
|
1113
1146
|
]
|
|
1114
1147
|
},
|
|
1148
|
+
{
|
|
1149
|
+
"id": "createSubscriptionCheckout",
|
|
1150
|
+
"method": "POST",
|
|
1151
|
+
"path": "/v1/billing/subscription/checkout",
|
|
1152
|
+
"request": [
|
|
1153
|
+
"CreateSubscriptionCheckoutRequest"
|
|
1154
|
+
],
|
|
1155
|
+
"response": [
|
|
1156
|
+
"CreateSubscriptionCheckoutResponse"
|
|
1157
|
+
]
|
|
1158
|
+
},
|
|
1159
|
+
{
|
|
1160
|
+
"id": "createSubscriptionPortalSession",
|
|
1161
|
+
"method": "POST",
|
|
1162
|
+
"path": "/v1/billing/subscription/portal",
|
|
1163
|
+
"request": [
|
|
1164
|
+
"CreateBillingPortalRequest"
|
|
1165
|
+
],
|
|
1166
|
+
"response": [
|
|
1167
|
+
"CreateBillingPortalResponse"
|
|
1168
|
+
]
|
|
1169
|
+
},
|
|
1115
1170
|
{
|
|
1116
1171
|
"id": "createTranscriptionRecording",
|
|
1117
1172
|
"method": "POST",
|
|
@@ -2543,6 +2598,15 @@ export const ACTION_CATALOG: readonly ActionCatalogEntry[] = [
|
|
|
2543
2598
|
"request": [],
|
|
2544
2599
|
"response": []
|
|
2545
2600
|
},
|
|
2601
|
+
{
|
|
2602
|
+
"id": "getBillingSubscriptionPlans",
|
|
2603
|
+
"method": "GET",
|
|
2604
|
+
"path": "/v1/billing/subscription/plans",
|
|
2605
|
+
"request": [],
|
|
2606
|
+
"response": [
|
|
2607
|
+
"BillingSubscriptionCatalog"
|
|
2608
|
+
]
|
|
2609
|
+
},
|
|
2546
2610
|
{
|
|
2547
2611
|
"id": "getBillingUsage",
|
|
2548
2612
|
"method": "GET",
|
|
@@ -2586,6 +2650,15 @@ export const ACTION_CATALOG: readonly ActionCatalogEntry[] = [
|
|
|
2586
2650
|
"BrowserSession"
|
|
2587
2651
|
]
|
|
2588
2652
|
},
|
|
2653
|
+
{
|
|
2654
|
+
"id": "getBrowserSessionWorkingCopyAdoption",
|
|
2655
|
+
"method": "GET",
|
|
2656
|
+
"path": "/v1/workspaces/:workspaceId/browser-sessions/:browserSessionId/working-copy/adoptions/:operationId",
|
|
2657
|
+
"request": [],
|
|
2658
|
+
"response": [
|
|
2659
|
+
"BrowserWorkingCopyAdoptionResponse"
|
|
2660
|
+
]
|
|
2661
|
+
},
|
|
2589
2662
|
{
|
|
2590
2663
|
"id": "getBrowserTargetState",
|
|
2591
2664
|
"method": "GET",
|
|
@@ -3584,6 +3657,17 @@ export const ACTION_CATALOG: readonly ActionCatalogEntry[] = [
|
|
|
3584
3657
|
"WorkspaceInsightsResponse"
|
|
3585
3658
|
]
|
|
3586
3659
|
},
|
|
3660
|
+
{
|
|
3661
|
+
"id": "getWorkspaceInsightsSiteUsage",
|
|
3662
|
+
"method": "GET",
|
|
3663
|
+
"path": "/v1/workspaces/:workspaceId/insights/sites",
|
|
3664
|
+
"request": [
|
|
3665
|
+
"InsightsSiteUsageQuery"
|
|
3666
|
+
],
|
|
3667
|
+
"response": [
|
|
3668
|
+
"InsightsSiteUsageResponse"
|
|
3669
|
+
]
|
|
3670
|
+
},
|
|
3587
3671
|
{
|
|
3588
3672
|
"id": "getWorkspaceInsightsUsage",
|
|
3589
3673
|
"method": "GET",
|
|
@@ -3850,6 +3934,15 @@ export const ACTION_CATALOG: readonly ActionCatalogEntry[] = [
|
|
|
3850
3934
|
],
|
|
3851
3935
|
"response": []
|
|
3852
3936
|
},
|
|
3937
|
+
{
|
|
3938
|
+
"id": "inspectBrowserSessionWorkingCopy",
|
|
3939
|
+
"method": "POST",
|
|
3940
|
+
"path": "/v1/workspaces/:workspaceId/browser-sessions/:browserSessionId/working-copy/inspection",
|
|
3941
|
+
"request": [],
|
|
3942
|
+
"response": [
|
|
3943
|
+
"BrowserWorkingCopyInspection"
|
|
3944
|
+
]
|
|
3945
|
+
},
|
|
3853
3946
|
{
|
|
3854
3947
|
"id": "inspectMcpAuthentication",
|
|
3855
3948
|
"method": "POST",
|
|
@@ -6565,6 +6658,15 @@ export const ACTION_CATALOG: readonly ActionCatalogEntry[] = [
|
|
|
6565
6658
|
"SessionRetryResponse"
|
|
6566
6659
|
]
|
|
6567
6660
|
},
|
|
6661
|
+
{
|
|
6662
|
+
"id": "revertBrowserSessionWorkingCopyAdoption",
|
|
6663
|
+
"method": "POST",
|
|
6664
|
+
"path": "/v1/workspaces/:workspaceId/browser-sessions/:browserSessionId/working-copy/adoptions/:operationId/revert",
|
|
6665
|
+
"request": [],
|
|
6666
|
+
"response": [
|
|
6667
|
+
"BrowserWorkingCopyAdoptionResponse"
|
|
6668
|
+
]
|
|
6669
|
+
},
|
|
6568
6670
|
{
|
|
6569
6671
|
"id": "reviewAgentInstruction",
|
|
6570
6672
|
"method": "POST",
|
|
@@ -8183,6 +8285,17 @@ export const ACTION_CATALOG: readonly ActionCatalogEntry[] = [
|
|
|
8183
8285
|
"WorkspaceWebhook"
|
|
8184
8286
|
]
|
|
8185
8287
|
},
|
|
8288
|
+
{
|
|
8289
|
+
"id": "upgradeBillingSubscription",
|
|
8290
|
+
"method": "POST",
|
|
8291
|
+
"path": "/v1/billing/subscription/upgrade",
|
|
8292
|
+
"request": [
|
|
8293
|
+
"ChangeBillingSubscriptionRequest"
|
|
8294
|
+
],
|
|
8295
|
+
"response": [
|
|
8296
|
+
"BillingSubscriptionChange"
|
|
8297
|
+
]
|
|
8298
|
+
},
|
|
8186
8299
|
{
|
|
8187
8300
|
"id": "uploadTranscriptionRecordingChunk",
|
|
8188
8301
|
"method": "PUT",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Generated by scripts/public-api/action-catalog.ts. Do not edit.
|
|
2
2
|
// Named imports keep unrelated response and tool validators out of the API graph.
|
|
3
|
-
import { AcceptOrganizationInvitationRequest, AcceptOrganizationRecoveryCustodyRequest, AcknowledgeStreamRequest, ActivateCodexRealtimeConnectionRequest, ActivateCompanyProfileRevisionRequest, ActivatePreferenceRegistryRevisionRequest, ActivateWorkspaceInstructionPolicyRequest, AddDocumentRequest, AddWorkspaceMemberRequest, AgentInstructionReviewRequest, AgentLearningContext, ApiIntegrationOAuthStartRequest, AppendArchivedSessionEventsRequest, ApplySessionGoalRevisionRequest, ApproveSlackUserLinkAccessRequest, ArtifactCatalogKind, AtlassianLifecycleActionRequest, AttachViewerRequest, BeginSessionRealtimeRequest, BrowserActionRequest, BrowserDomReadRequest, BrowserDownloadSaveRequest, BrowserOpenTargetRequest, BrowserSessionAttachmentRequest, BrowserSessionLifecycleRequest, ChangeMachineAudienceRequest, ChangePreferenceRegistryScopeRequest, ClaudeSubscriptionOAuthCompleteRequest, ClaudeSubscriptionOAuthStartRequest, ClaudeSubscriptionSetupTokenRequest, ClearWorkspaceAllowanceRequest, CodexAppsDesignationRequest, CodexRealtimeWebrtcRequest, CodexSourceRequest, CompanyProfileDiffRequest, ComputerActionRequest, ComputerNativeCallRequest, ComputerSessionAttachmentRequest, ComputerSessionLifecycleRequest, ConfigureOrganizationRecoveryPolicyRequest, CorrectPreferenceRegistryRequest, CreateAdditionalOrganizationRequest, CreateApiKeyRequest, CreateAutomationSourceRequest, CreateAutomationTriggerRequest, CreateBillingPortalRequest, CreateBrowserIdentityRequest, CreateBrowserSessionRequest, CreateCapabilityCatalogItemRequest, CreateChannelRequest, CreateCheckoutRequest, CreateComputerSessionRequest, CreateConnectionRequest, CreateDocumentBaseRequest, CreateFeedbackRequest, CreateFileUploadRequest, CreateInteractionInterventionRequest, CreateKnowledgeDropRequest, CreateNetworkRouteRequest, CreateOrganizationApiKeyRequest, CreateOrganizationInvitationRequest, CreateOrganizationProviderCustomModelRequest, CreateOrganizationRequest, CreateOrganizationServiceAccountRequest, CreateOrganizationWebhookRequest, CreateOrganizationWorkspaceRequest, CreatePersonalApiKeyRequest, CreatePrReviewAppRegistrationRequest, CreatePrReviewRepositoryBindingRequest, CreatePreferenceRegistryProposalRequest, CreateRigRequest, CreateScheduledTaskRequest, CreateSessionRequest, CreateSiteAuthConnectionRequest, CreateWorkspaceArtifactRequest, CreateWorkspaceGatewayCustomModelRequest, CreateWorkspaceInstructionPolicyDraftRequest, CreateWorkspaceInstructionPolicyOnboardingProposalRequest, CreateWorkspaceOpenRouterCustomModelRequest, CreateWorkspaceOpperCustomModelRequest, CreateWorkspaceRequest, CreateWorkspaceWebhookRequest, DeactivatePreferenceRegistryRequest, DeleteOrganizationProviderCustomModelRequest, DeleteSessionQueueItemRequest, DeleteWorkspaceGatewayCustomModelRequest, DeleteWorkspaceOpenRouterCustomModelRequest, DeleteWorkspaceOpperCustomModelRequest, DeviceEnrollmentApproveRequest, DisableOrganizationRecoveryPolicyRequest, EditSessionQueueItemRequest, EnableCapabilityRequest, EndSessionRealtimeRequest, EnsureWorkspaceRequest, ExternalAuthInteractiveRequest, ExternalAuthRunRequest, FikenInstallRequest, FikenOAuthStartRequest, FileListRequest, ForkSessionRequest, FsDeleteRequest, FsListBatchRequest, FsListRequest, FsMkdirRequest, FsMoveRequest, FsReadRequest, FsWriteRequest, GatewayRealtimeConnectRequest, GetMyUsageRequest, GetUsageRequest, GitDiffRequest, GitLogRequest, GitReadBatchRequest, GitShowRequest, GitStatusRequest, GrantSessionAdminAccessRequest, GrantWorkspaceCreditsRequest, ImportArchivedSessionRequest, ImportLegacyWorkspaceInstructionPolicyDraftRequest, InboxItem, InboxSettings, InsightsRange, InstallApiIntegrationRequest, InstallLibrarySkillRequest, InstallPluginRequest, InstallSkillRequest, InstallVaultProviderRequest, IssueUserResourceGrantRequest, KnowledgeEntryBatchReviewRequest, KnowledgeEntryListRequest, KnowledgeEntryRestoreRequest, KnowledgeEntryReviewRequest, KnowledgeEntrySaveRequest, KnowledgeReviewBatchListRequest, KnowledgeSavePreparationRequest, MachineAudiencePreviewRequest, McpConnectionDecision, MemberNotificationsSetting, MemorySlackPublicationActionRequest, MintEnrollTokenRequest, ModelConnectionAccessPolicy, MoveDocumentRequest, MoveSessionQueueItemRequest, MutateIntegrationFacetRequest, OAuthStartRequest, OpenGeniSlackBotInstallRequest, OpenMachinePrivacySettingsRequest, OrganizationModelProviderKind, OrganizationRecoveryOperationCommandRequest, OrganizationUsagePeriod, PrepareSlackUserLinkAccessRequest, PreviewApiIntegrationRequest, PreviewPluginRequest, PreviewSkillImportRequest, ProposeRigChangeRequest, PtyCloseRequest, PtyOpenRequest, PtyResizeRequest, PtyWriteRequest, PublishBrowserRevisionRequest, PublishSandboxFileArtifactRequest, PublishWorkspaceArtifactVersionRequest, PutOrganizationCredentialProviderRequest, PutOrganizationWorkspaceMemberRequest, PutWorkspaceCredentialProviderRequest, ReclassifyDocumentAuthorityRequest, RefreshScheduledTaskAccessRequest, RejectPreferenceRegistryProposalRequest, RejectSessionGoalRevisionRequest, RemoveEnrollmentRequest, RenewSessionRealtimeRequest, ReorderChannelsRequest, ReplaceVaultProviderCredentialsRequest, ReportAuthRunRequest, ResolveInteractionInterventionRequest, RetryOrganizationUserSetupDeliveryRequest, RevokeOrganizationInvitationRequest, RevokeOrganizationModelProviderConnectionRequest, RevokeOrganizationWorkspaceMemberRequest, RollbackCompanyProfileRequest, RollbackSessionGoalRevisionRequest, RollbackWorkspaceArtifactRequest, RollbackWorkspaceInstructionPolicyRequest, RotateSessionMcpCredentialsRequest, RunDocumentDefaultCollectionBackfillRequest, SandboxRecoveryRequest, SaveAtlassianSourcesRequest, SaveComposerDraftRequest, SaveNewSessionDraftRequest, SessionCodexAccountPinRequest, SessionControlRequest, SessionHumanInputRequest, SessionInboxMute, SessionMessageSearchRequest, SessionRetryRequest, SessionScopeSubjectId, SessionStatus, SessionVisibility, SetMemberAllowanceRequest, SetSessionModelAccountChoiceRequest, SetSessionUsageLimitRequest, SetWorkspaceAllowanceRequest, SetWorkspaceArtifactStatusRequest, SetWorkspaceDefaultRigRequest, SiteDataCollectionDefinitionRequest, SiteDataImportRequest, SiteDataQueryRequest, SiteDataWriteRequest, SiteLimitProfile, SitePublishWarningFix, SiteSqlExportFormat, SiteSqlImportRequest, SiteSqlMigrationRequest, SiteSqlQueryDefinitionRequest, SiteSqlRunRequest, SiteSqlSettingsRequest, SiteSqlStatementRequest, SiteTakedownRequest, SlackUserLinkAccessMutationRequest, SocialOAuthStartRequest, StartAuthRunRequest, StartOrganizationRecoveryOperationRequest, SteerSessionQueueItemRequest, SubmitComposerDraftRequest, SubscriptionAccountRenameRequest, SubscriptionAccountToggleRequest, SubscriptionConnectPollRequest, SubscriptionRotationSettingsRequest, SupergrokConnectStartRequest, SupersedePreferenceRegistryRequest, SwapActiveSandboxRequest, SyncSessionRealtimeLedgerRequest, TerminalExecRequest, TriggerAutomationManuallyRequest, UninstallApiIntegrationRequest, UninstallPluginRequest, UninstallSkillRequest, UpdateAutomationSourceRequest, UpdateAutomationTriggerRequest, UpdateBrowserIdentityRequest, UpdateChannelRequest, UpdateCompanyProfileAgentPolicyRequest, UpdateCompanyProfileRequest, UpdateConnectionRequest, UpdateConnectorToolPermissionsRequest, UpdateGitHubActionPolicyRequest, UpdateMachineOperationPolicyRequest, UpdateMemorySlackPublicationConfigurationRequest, UpdateModelAccountPreferencesRequest, UpdateNetworkRouteRequest, UpdateOpenGeniSlackBotOrganizationAccess, UpdateOrganizationAgentAdminAccessRequest, UpdateOrganizationApiKeyRequest, UpdateOrganizationIntegrationPolicyRequest, UpdateOrganizationMcpConnectionRequest, UpdateOrganizationMemberRequest, UpdateOrganizationModelAccountSettingsRequest, UpdateOrganizationModelDefaultsRequest, UpdateOrganizationNameRequest, UpdateOrganizationPrivacySettingsRequest, UpdateOrganizationPrivateSessionSettingsRequest, UpdateOrganizationRetentionPolicyRequest, UpdateOrganizationServiceAccountRequest, UpdateOrganizationWebhookRequest, UpdateOrganizationWorkspaceRequest, UpdatePrReviewAppRegistrationRequest, UpdatePrReviewRepositoryBindingRequest, UpdateRigRequest, UpdateScheduledTaskRequest, UpdateSessionAgentRequest, UpdateSessionArchiveRequest, UpdateSessionAttentionRequest, UpdateSessionChannelRequest, UpdateSessionGoalRequest, UpdateSessionMcpApprovalPolicyRequest, UpdateSessionMcpToolPermissionsRequest, UpdateSessionPinRequest, UpdateSessionRequest, UpdateSessionRetentionRequest, UpdateSessionSkillsRequest, UpdateSessionToolPolicyRequest, UpdateSessionVisibilityRequest, UpdateSiteAuthConnectionRequest, UpdateSlackChannelRoutesRequest, UpdateVideoGenerationPolicyRequest, UpdateWorkspaceArtifactVisibilityRequest, UpdateWorkspaceMemberRequest, UpdateWorkspaceModelAccountSettingsRequest, UpdateWorkspaceModelPolicyRequest, UpdateWorkspaceRequest, UpdateWorkspaceSettingsRequest, UpdateWorkspaceWebhookRequest, UpsertIntegrationFacetRequest, UpsertOrganizationModelProviderConnectionRequest, UpsertSitePublicationRequest, VerifyAuthRunRequest, ViewerHeartbeatRequest, WorkClaimSubjectType, WorkspaceInstructionPolicyDiffRequest, WorkspacePauseTimerRequest } from "@opengeni/contracts";
|
|
3
|
+
import { AcceptOrganizationInvitationRequest, AcceptOrganizationRecoveryCustodyRequest, AcknowledgeStreamRequest, ActivateCodexRealtimeConnectionRequest, ActivateCompanyProfileRevisionRequest, ActivatePreferenceRegistryRevisionRequest, ActivateWorkspaceInstructionPolicyRequest, AddDocumentRequest, AddWorkspaceMemberRequest, AgentInstructionReviewRequest, AgentLearningContext, ApiIntegrationOAuthStartRequest, AppendArchivedSessionEventsRequest, ApplySessionGoalRevisionRequest, ApproveSlackUserLinkAccessRequest, ArtifactCatalogKind, AtlassianLifecycleActionRequest, AttachViewerRequest, BeginSessionRealtimeRequest, BrowserActionRequest, BrowserDomReadRequest, BrowserDownloadSaveRequest, BrowserOpenTargetRequest, BrowserSessionAttachmentRequest, BrowserSessionLifecycleRequest, BrowserWorkingCopyAdoptionRequest, CancelBillingSubscriptionRequest, ChangeBillingSubscriptionRequest, ChangeMachineAudienceRequest, ChangePreferenceRegistryScopeRequest, ClaudeSubscriptionOAuthCompleteRequest, ClaudeSubscriptionOAuthStartRequest, ClaudeSubscriptionSetupTokenRequest, ClearWorkspaceAllowanceRequest, CodexAppsDesignationRequest, CodexRealtimeWebrtcRequest, CodexSourceRequest, CompanyProfileDiffRequest, ComputerActionRequest, ComputerNativeCallRequest, ComputerSessionAttachmentRequest, ComputerSessionLifecycleRequest, ConfigureOrganizationRecoveryPolicyRequest, CorrectPreferenceRegistryRequest, CreateAdditionalOrganizationRequest, CreateApiKeyRequest, CreateAutomationSourceRequest, CreateAutomationTriggerRequest, CreateBillingPortalRequest, CreateBrowserIdentityRequest, CreateBrowserSessionRequest, CreateCapabilityCatalogItemRequest, CreateChannelRequest, CreateCheckoutRequest, CreateComputerSessionRequest, CreateConnectionRequest, CreateDocumentBaseRequest, CreateFeedbackRequest, CreateFileUploadRequest, CreateInteractionInterventionRequest, CreateKnowledgeDropRequest, CreateNetworkRouteRequest, CreateOrganizationApiKeyRequest, CreateOrganizationInvitationRequest, CreateOrganizationProviderCustomModelRequest, CreateOrganizationRequest, CreateOrganizationServiceAccountRequest, CreateOrganizationWebhookRequest, CreateOrganizationWorkspaceRequest, CreatePersonalApiKeyRequest, CreatePrReviewAppRegistrationRequest, CreatePrReviewRepositoryBindingRequest, CreatePreferenceRegistryProposalRequest, CreateRigRequest, CreateScheduledTaskRequest, CreateSessionRequest, CreateSiteAuthConnectionRequest, CreateSubscriptionCheckoutRequest, CreateWorkspaceArtifactRequest, CreateWorkspaceGatewayCustomModelRequest, CreateWorkspaceInstructionPolicyDraftRequest, CreateWorkspaceInstructionPolicyOnboardingProposalRequest, CreateWorkspaceOpenRouterCustomModelRequest, CreateWorkspaceOpperCustomModelRequest, CreateWorkspaceRequest, CreateWorkspaceWebhookRequest, DeactivatePreferenceRegistryRequest, DeleteOrganizationProviderCustomModelRequest, DeleteSessionQueueItemRequest, DeleteWorkspaceGatewayCustomModelRequest, DeleteWorkspaceOpenRouterCustomModelRequest, DeleteWorkspaceOpperCustomModelRequest, DeviceEnrollmentApproveRequest, DisableOrganizationRecoveryPolicyRequest, EditSessionQueueItemRequest, EnableCapabilityRequest, EndSessionRealtimeRequest, EnsureWorkspaceRequest, ExternalAuthInteractiveRequest, ExternalAuthRunRequest, FikenInstallRequest, FikenOAuthStartRequest, FileListRequest, ForkSessionRequest, FsDeleteRequest, FsListBatchRequest, FsListRequest, FsMkdirRequest, FsMoveRequest, FsReadRequest, FsWriteRequest, GatewayRealtimeConnectRequest, GetMyUsageRequest, GetUsageRequest, GitDiffRequest, GitLogRequest, GitReadBatchRequest, GitShowRequest, GitStatusRequest, GrantSessionAdminAccessRequest, GrantWorkspaceCreditsRequest, ImportArchivedSessionRequest, ImportLegacyWorkspaceInstructionPolicyDraftRequest, InboxItem, InboxSettings, InsightsRange, InstallApiIntegrationRequest, InstallLibrarySkillRequest, InstallPluginRequest, InstallSkillRequest, InstallVaultProviderRequest, IssueUserResourceGrantRequest, KnowledgeEntryBatchReviewRequest, KnowledgeEntryListRequest, KnowledgeEntryRestoreRequest, KnowledgeEntryReviewRequest, KnowledgeEntrySaveRequest, KnowledgeReviewBatchListRequest, KnowledgeSavePreparationRequest, MachineAudiencePreviewRequest, McpConnectionDecision, MemberNotificationsSetting, MemorySlackPublicationActionRequest, MintEnrollTokenRequest, ModelConnectionAccessPolicy, MoveDocumentRequest, MoveSessionQueueItemRequest, MutateIntegrationFacetRequest, OAuthStartRequest, OpenGeniSlackBotInstallRequest, OpenMachinePrivacySettingsRequest, OrganizationModelProviderKind, OrganizationRecoveryOperationCommandRequest, OrganizationUsagePeriod, PrepareSlackUserLinkAccessRequest, PreviewApiIntegrationRequest, PreviewPluginRequest, PreviewSkillImportRequest, ProposeRigChangeRequest, PtyCloseRequest, PtyOpenRequest, PtyResizeRequest, PtyWriteRequest, PublishBrowserRevisionRequest, PublishSandboxFileArtifactRequest, PublishWorkspaceArtifactVersionRequest, PutOrganizationCredentialProviderRequest, PutOrganizationWorkspaceMemberRequest, PutWorkspaceCredentialProviderRequest, ReclassifyDocumentAuthorityRequest, RefreshScheduledTaskAccessRequest, RejectPreferenceRegistryProposalRequest, RejectSessionGoalRevisionRequest, RemoveEnrollmentRequest, RenewSessionRealtimeRequest, ReorderChannelsRequest, ReplaceVaultProviderCredentialsRequest, ReportAuthRunRequest, ResolveInteractionInterventionRequest, RetryOrganizationUserSetupDeliveryRequest, RevokeOrganizationInvitationRequest, RevokeOrganizationModelProviderConnectionRequest, RevokeOrganizationWorkspaceMemberRequest, RollbackCompanyProfileRequest, RollbackSessionGoalRevisionRequest, RollbackWorkspaceArtifactRequest, RollbackWorkspaceInstructionPolicyRequest, RotateSessionMcpCredentialsRequest, RunDocumentDefaultCollectionBackfillRequest, SandboxRecoveryRequest, SaveAtlassianSourcesRequest, SaveComposerDraftRequest, SaveNewSessionDraftRequest, SessionCodexAccountPinRequest, SessionControlRequest, SessionHumanInputRequest, SessionInboxMute, SessionMessageSearchRequest, SessionRetryRequest, SessionScopeSubjectId, SessionStatus, SessionVisibility, SetMemberAllowanceRequest, SetSessionModelAccountChoiceRequest, SetSessionUsageLimitRequest, SetWorkspaceAllowanceRequest, SetWorkspaceArtifactStatusRequest, SetWorkspaceDefaultRigRequest, SiteDataCollectionDefinitionRequest, SiteDataImportRequest, SiteDataQueryRequest, SiteDataWriteRequest, SiteLimitProfile, SitePublishWarningFix, SiteSqlExportFormat, SiteSqlImportRequest, SiteSqlMigrationRequest, SiteSqlQueryDefinitionRequest, SiteSqlRunRequest, SiteSqlSettingsRequest, SiteSqlStatementRequest, SiteTakedownRequest, SlackUserLinkAccessMutationRequest, SocialOAuthStartRequest, StartAuthRunRequest, StartOrganizationRecoveryOperationRequest, SteerSessionQueueItemRequest, SubmitComposerDraftRequest, SubscriptionAccountRenameRequest, SubscriptionAccountToggleRequest, SubscriptionConnectPollRequest, SubscriptionRotationSettingsRequest, SupergrokConnectStartRequest, SupersedePreferenceRegistryRequest, SwapActiveSandboxRequest, SyncSessionRealtimeLedgerRequest, TerminalExecRequest, TriggerAutomationManuallyRequest, UninstallApiIntegrationRequest, UninstallPluginRequest, UninstallSkillRequest, UpdateAutomationSourceRequest, UpdateAutomationTriggerRequest, UpdateBrowserIdentityRequest, UpdateChannelRequest, UpdateCompanyProfileAgentPolicyRequest, UpdateCompanyProfileRequest, UpdateConnectionRequest, UpdateConnectorToolPermissionsRequest, UpdateGitHubActionPolicyRequest, UpdateMachineOperationPolicyRequest, UpdateMemorySlackPublicationConfigurationRequest, UpdateModelAccountPreferencesRequest, UpdateNetworkRouteRequest, UpdateOpenGeniSlackBotOrganizationAccess, UpdateOrganizationAgentAdminAccessRequest, UpdateOrganizationApiKeyRequest, UpdateOrganizationIntegrationPolicyRequest, UpdateOrganizationMcpConnectionRequest, UpdateOrganizationMemberRequest, UpdateOrganizationModelAccountSettingsRequest, UpdateOrganizationModelDefaultsRequest, UpdateOrganizationNameRequest, UpdateOrganizationPrivacySettingsRequest, UpdateOrganizationPrivateSessionSettingsRequest, UpdateOrganizationRetentionPolicyRequest, UpdateOrganizationServiceAccountRequest, UpdateOrganizationWebhookRequest, UpdateOrganizationWorkspaceRequest, UpdatePrReviewAppRegistrationRequest, UpdatePrReviewRepositoryBindingRequest, UpdateRigRequest, UpdateScheduledTaskRequest, UpdateSessionAgentRequest, UpdateSessionArchiveRequest, UpdateSessionAttentionRequest, UpdateSessionChannelRequest, UpdateSessionGoalRequest, UpdateSessionMcpApprovalPolicyRequest, UpdateSessionMcpToolPermissionsRequest, UpdateSessionPinRequest, UpdateSessionRequest, UpdateSessionRetentionRequest, UpdateSessionSkillsRequest, UpdateSessionToolPolicyRequest, UpdateSessionVisibilityRequest, UpdateSiteAuthConnectionRequest, UpdateSlackChannelRoutesRequest, UpdateVideoGenerationPolicyRequest, UpdateWorkspaceArtifactVisibilityRequest, UpdateWorkspaceMemberRequest, UpdateWorkspaceModelAccountSettingsRequest, UpdateWorkspaceModelPolicyRequest, UpdateWorkspaceRequest, UpdateWorkspaceSettingsRequest, UpdateWorkspaceWebhookRequest, UpsertIntegrationFacetRequest, UpsertOrganizationModelProviderConnectionRequest, UpsertSitePublicationRequest, VerifyAuthRunRequest, ViewerHeartbeatRequest, WorkClaimSubjectType, WorkspaceInstructionPolicyDiffRequest, WorkspacePauseTimerRequest } from "@opengeni/contracts";
|
|
4
4
|
|
|
5
5
|
export const ACTION_REQUEST_SCHEMAS: Readonly<Record<string, unknown>> = {
|
|
6
6
|
AcceptOrganizationInvitationRequest,
|
|
@@ -28,6 +28,9 @@ export const ACTION_REQUEST_SCHEMAS: Readonly<Record<string, unknown>> = {
|
|
|
28
28
|
BrowserOpenTargetRequest,
|
|
29
29
|
BrowserSessionAttachmentRequest,
|
|
30
30
|
BrowserSessionLifecycleRequest,
|
|
31
|
+
BrowserWorkingCopyAdoptionRequest,
|
|
32
|
+
CancelBillingSubscriptionRequest,
|
|
33
|
+
ChangeBillingSubscriptionRequest,
|
|
31
34
|
ChangeMachineAudienceRequest,
|
|
32
35
|
ChangePreferenceRegistryScopeRequest,
|
|
33
36
|
ClaudeSubscriptionOAuthCompleteRequest,
|
|
@@ -77,6 +80,7 @@ export const ACTION_REQUEST_SCHEMAS: Readonly<Record<string, unknown>> = {
|
|
|
77
80
|
CreateScheduledTaskRequest,
|
|
78
81
|
CreateSessionRequest,
|
|
79
82
|
CreateSiteAuthConnectionRequest,
|
|
83
|
+
CreateSubscriptionCheckoutRequest,
|
|
80
84
|
CreateWorkspaceArtifactRequest,
|
|
81
85
|
CreateWorkspaceGatewayCustomModelRequest,
|
|
82
86
|
CreateWorkspaceInstructionPolicyDraftRequest,
|
package/src/mcp/server.ts
CHANGED
|
@@ -976,6 +976,34 @@ export function slackBotFileContentResult(
|
|
|
976
976
|
};
|
|
977
977
|
}
|
|
978
978
|
|
|
979
|
+
/**
|
|
980
|
+
* The first-party server as seen by MCP protocol messages that touch no tool:
|
|
981
|
+
* `initialize`, `ping` and notifications. It advertises exactly what the full
|
|
982
|
+
* server does (the same name, version and tools capability) without the
|
|
983
|
+
* workspace, catalog, Memory and admin reads that registering tools needs.
|
|
984
|
+
* Never route `tools/*` here: it lists no tools.
|
|
985
|
+
*/
|
|
986
|
+
export function buildOpenGeniMcpProtocolServer(grant: AccessGrant): McpServer {
|
|
987
|
+
const sessionId =
|
|
988
|
+
typeof grant.metadata?.["sessionId"] === "string"
|
|
989
|
+
? (grant.metadata["sessionId"] as string)
|
|
990
|
+
: null;
|
|
991
|
+
const server = new PolicyMcpServer(grant, sessionId, new Set());
|
|
992
|
+
server.ensureToolsListHandler();
|
|
993
|
+
return server;
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
/** JSON-RPC methods {@link buildOpenGeniMcpProtocolServer} answers like the full server. */
|
|
997
|
+
export function isOpenGeniMcpProtocolOnlyMessage(message: unknown): boolean {
|
|
998
|
+
if (!message || typeof message !== "object" || Array.isArray(message)) return false;
|
|
999
|
+
const method = (message as { method?: unknown }).method;
|
|
1000
|
+
if (typeof method !== "string") return false;
|
|
1001
|
+
if (method === "initialize" || method === "ping") return true;
|
|
1002
|
+
// Notifications carry no id and get no response. The stateless transport
|
|
1003
|
+
// holds no in-flight request a cancellation could reach.
|
|
1004
|
+
return method.startsWith("notifications/") && !("id" in message);
|
|
1005
|
+
}
|
|
1006
|
+
|
|
979
1007
|
export function buildOpenGeniMcpServer(
|
|
980
1008
|
deps: ApiRouteDeps,
|
|
981
1009
|
grant: AccessGrant,
|
package/src/routes/billing.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
BillingCheckoutStatus,
|
|
3
|
+
BillingSubscriptionCatalog,
|
|
4
|
+
BillingSubscriptionChange,
|
|
5
|
+
CancelBillingSubscriptionRequest,
|
|
6
|
+
ChangeBillingSubscriptionRequest,
|
|
7
|
+
CreateSubscriptionCheckoutRequest,
|
|
8
|
+
CreateSubscriptionCheckoutResponse,
|
|
3
9
|
CreateBillingPortalRequest,
|
|
4
10
|
CreateBillingPortalResponse,
|
|
5
11
|
CreateCheckoutRequest,
|
|
@@ -33,14 +39,19 @@ import {
|
|
|
33
39
|
recordStripeWebhookEvent,
|
|
34
40
|
upsertBillingCustomer,
|
|
35
41
|
} from "@opengeni/db";
|
|
36
|
-
import type { Hono } from "hono";
|
|
42
|
+
import type { Context, Hono } from "hono";
|
|
37
43
|
import { HTTPException } from "hono/http-exception";
|
|
38
44
|
import Stripe from "stripe";
|
|
45
|
+
import { sql } from "drizzle-orm";
|
|
39
46
|
import { requireAccessContext } from "@opengeni/core";
|
|
40
47
|
import type { ApiRouteDeps } from "@opengeni/core";
|
|
41
48
|
import { withAccessGrantSessionRlsContext } from "../access-grant-rls";
|
|
49
|
+
import { subscriptionStore } from "../billing-subscription-store";
|
|
50
|
+
import { StripeSubscriptions, subscriptionWebhookEvent } from "../billing-subscriptions";
|
|
51
|
+
import { serializedStripeCustomer } from "../billing-stripe-customer";
|
|
42
52
|
|
|
43
53
|
export function registerBillingRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
54
|
+
registerSubscriptionRoutes(app, deps);
|
|
44
55
|
app.get("/v1/billing", async (c) => {
|
|
45
56
|
const context = await requireAccessContext(c, deps);
|
|
46
57
|
const accountId = requireSelectedAccount(context, c.req.query("accountId"), "billing:read");
|
|
@@ -342,6 +353,11 @@ export function registerBillingRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
|
342
353
|
return c.json({ received: true, duplicate: true });
|
|
343
354
|
}
|
|
344
355
|
}
|
|
356
|
+
// Retain disabled subscription deliveries, but leave them unprocessed so
|
|
357
|
+
// an operator can replay them after activation. Top-up events remain live.
|
|
358
|
+
if (subscriptionWebhookEvent(event) && !deps.settings.subscriptionPlansEnabled) {
|
|
359
|
+
return c.json({ received: true, ignored: true });
|
|
360
|
+
}
|
|
345
361
|
try {
|
|
346
362
|
await handleStripeWebhookEvent(deps, stripeClient(deps), event);
|
|
347
363
|
await markStripeWebhookProcessed(deps.db, event.id);
|
|
@@ -354,6 +370,120 @@ export function registerBillingRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
|
354
370
|
});
|
|
355
371
|
}
|
|
356
372
|
|
|
373
|
+
function requireSubscriptionsEnabled(deps: ApiRouteDeps): void {
|
|
374
|
+
if (!deps.settings.subscriptionPlansEnabled || deps.settings.billingMode !== "stripe") {
|
|
375
|
+
throw new HTTPException(404, { message: "subscription plans are not enabled" });
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
function subscriptions(deps: ApiRouteDeps, stripe = stripeClient(deps)) {
|
|
380
|
+
return new StripeSubscriptions(
|
|
381
|
+
stripe,
|
|
382
|
+
subscriptionStore(deps.db),
|
|
383
|
+
deps.settings.subscriptionPlansEnabled,
|
|
384
|
+
stripeCustomerProvider(deps),
|
|
385
|
+
);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
function registerSubscriptionRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
389
|
+
app.get("/v1/billing/subscription/plans", async (c) => {
|
|
390
|
+
requireSubscriptionsEnabled(deps);
|
|
391
|
+
const context = await requireAccessContext(c, deps);
|
|
392
|
+
const accountId = requireSelectedAccount(context, c.req.query("accountId"), "billing:read");
|
|
393
|
+
return c.json(BillingSubscriptionCatalog.parse(await subscriptions(deps).catalog(accountId)));
|
|
394
|
+
});
|
|
395
|
+
app.post("/v1/billing/subscription/checkout", async (c) => {
|
|
396
|
+
requireSubscriptionsEnabled(deps);
|
|
397
|
+
const context = await requireAccessContext(c, deps);
|
|
398
|
+
const parsed = CreateSubscriptionCheckoutRequest.safeParse(await c.req.json());
|
|
399
|
+
if (!parsed.success)
|
|
400
|
+
throw new HTTPException(400, {
|
|
401
|
+
message: parsed.error.issues[0]?.message ?? "invalid subscription checkout request",
|
|
402
|
+
});
|
|
403
|
+
const accountId = requireSelectedAccount(context, parsed.data.accountId, "billing:manage");
|
|
404
|
+
const stripe = stripeClient(deps);
|
|
405
|
+
const customerId = await getOrCreateStripeCustomer(deps, stripe, context, accountId);
|
|
406
|
+
return c.json(
|
|
407
|
+
CreateSubscriptionCheckoutResponse.parse(
|
|
408
|
+
await subscriptions(deps, stripe).checkout({
|
|
409
|
+
...parsed.data,
|
|
410
|
+
accountId,
|
|
411
|
+
customerId,
|
|
412
|
+
successUrl: checkoutReturnUrl(
|
|
413
|
+
deps.settings.publicBaseUrl,
|
|
414
|
+
deps.settings.webBaseUrl,
|
|
415
|
+
parsed.data.successUrl,
|
|
416
|
+
"/billing?subscription=success",
|
|
417
|
+
"successUrl",
|
|
418
|
+
),
|
|
419
|
+
cancelUrl: checkoutReturnUrl(
|
|
420
|
+
deps.settings.publicBaseUrl,
|
|
421
|
+
deps.settings.webBaseUrl,
|
|
422
|
+
parsed.data.cancelUrl,
|
|
423
|
+
"/billing?subscription=cancelled",
|
|
424
|
+
"cancelUrl",
|
|
425
|
+
),
|
|
426
|
+
}),
|
|
427
|
+
),
|
|
428
|
+
);
|
|
429
|
+
});
|
|
430
|
+
const changeSubscription = (action: "upgrade" | "change") => async (c: Context) => {
|
|
431
|
+
requireSubscriptionsEnabled(deps);
|
|
432
|
+
const context = await requireAccessContext(c, deps);
|
|
433
|
+
const parsed = ChangeBillingSubscriptionRequest.safeParse(await c.req.json());
|
|
434
|
+
if (!parsed.success)
|
|
435
|
+
throw new HTTPException(400, {
|
|
436
|
+
message: parsed.error.issues[0]?.message ?? "invalid subscription change request",
|
|
437
|
+
});
|
|
438
|
+
const accountId = requireSelectedAccount(context, parsed.data.accountId, "billing:manage");
|
|
439
|
+
return c.json(
|
|
440
|
+
BillingSubscriptionChange.parse(
|
|
441
|
+
await subscriptions(deps)[action]({ ...parsed.data, accountId }),
|
|
442
|
+
),
|
|
443
|
+
);
|
|
444
|
+
};
|
|
445
|
+
app.post("/v1/billing/subscription/upgrade", changeSubscription("upgrade"));
|
|
446
|
+
app.post("/v1/billing/subscription/change", changeSubscription("change"));
|
|
447
|
+
app.post("/v1/billing/subscription/cancel", async (c) => {
|
|
448
|
+
requireSubscriptionsEnabled(deps);
|
|
449
|
+
const context = await requireAccessContext(c, deps);
|
|
450
|
+
const parsed = CancelBillingSubscriptionRequest.safeParse(await c.req.json());
|
|
451
|
+
if (!parsed.success)
|
|
452
|
+
throw new HTTPException(400, {
|
|
453
|
+
message: parsed.error.issues[0]?.message ?? "invalid subscription cancellation request",
|
|
454
|
+
});
|
|
455
|
+
const accountId = requireSelectedAccount(context, parsed.data.accountId, "billing:manage");
|
|
456
|
+
return c.json(
|
|
457
|
+
BillingSubscriptionChange.parse(
|
|
458
|
+
await subscriptions(deps).cancel({ ...parsed.data, accountId }),
|
|
459
|
+
),
|
|
460
|
+
);
|
|
461
|
+
});
|
|
462
|
+
app.post("/v1/billing/subscription/portal", async (c) => {
|
|
463
|
+
requireSubscriptionsEnabled(deps);
|
|
464
|
+
const context = await requireAccessContext(c, deps);
|
|
465
|
+
const parsed = CreateBillingPortalRequest.safeParse(await c.req.json());
|
|
466
|
+
if (!parsed.success)
|
|
467
|
+
throw new HTTPException(400, {
|
|
468
|
+
message: parsed.error.issues[0]?.message ?? "invalid billing portal request",
|
|
469
|
+
});
|
|
470
|
+
const accountId = requireSelectedAccount(context, parsed.data.accountId, "billing:manage");
|
|
471
|
+
const stripe = stripeClient(deps);
|
|
472
|
+
const customerId = await getOrCreateStripeCustomer(deps, stripe, context, accountId);
|
|
473
|
+
const session = await stripe.billingPortal.sessions.create(
|
|
474
|
+
stripeBillingPortalSessionCreateParams({
|
|
475
|
+
customerId,
|
|
476
|
+
publicBaseUrl: deps.settings.publicBaseUrl,
|
|
477
|
+
webBaseUrl: deps.settings.webBaseUrl,
|
|
478
|
+
returnUrl: parsed.data.returnUrl,
|
|
479
|
+
}),
|
|
480
|
+
);
|
|
481
|
+
return c.json(
|
|
482
|
+
CreateBillingPortalResponse.parse({ portalSessionId: session.id, url: session.url }),
|
|
483
|
+
);
|
|
484
|
+
});
|
|
485
|
+
}
|
|
486
|
+
|
|
357
487
|
export function stripeCheckoutSessionCreateParams(input: {
|
|
358
488
|
accountId: string;
|
|
359
489
|
customerId: string;
|
|
@@ -508,6 +638,10 @@ async function handleStripeWebhookEvent(
|
|
|
508
638
|
stripe: Stripe,
|
|
509
639
|
event: Stripe.Event,
|
|
510
640
|
): Promise<void> {
|
|
641
|
+
if (subscriptionWebhookEvent(event)) {
|
|
642
|
+
await subscriptions(deps, stripe).handleEvent(event);
|
|
643
|
+
return;
|
|
644
|
+
}
|
|
511
645
|
switch (event.type) {
|
|
512
646
|
case "checkout.session.completed":
|
|
513
647
|
case "checkout.session.async_payment_succeeded":
|
|
@@ -1059,28 +1193,34 @@ async function getOrCreateStripeCustomer(
|
|
|
1059
1193
|
accountId: string,
|
|
1060
1194
|
): Promise<string> {
|
|
1061
1195
|
const provider = stripeCustomerProvider(deps);
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
return existing.providerCustomerId;
|
|
1065
|
-
}
|
|
1066
|
-
const account = await getManagedAccount(deps.db, accountId);
|
|
1067
|
-
if (!account) {
|
|
1068
|
-
throw new HTTPException(404, { message: "account not found" });
|
|
1069
|
-
}
|
|
1070
|
-
const customer = await stripe.customers.create({
|
|
1071
|
-
name: account.name,
|
|
1072
|
-
...(looksLikeEmail(context.subjectLabel) ? { email: context.subjectLabel } : {}),
|
|
1073
|
-
metadata: {
|
|
1074
|
-
opengeni_account_id: accountId,
|
|
1075
|
-
},
|
|
1076
|
-
});
|
|
1077
|
-
await upsertBillingCustomer(deps.db, {
|
|
1078
|
-
accountId,
|
|
1196
|
+
return await serializedStripeCustomer({
|
|
1197
|
+
stripe,
|
|
1079
1198
|
provider,
|
|
1080
|
-
|
|
1081
|
-
email:
|
|
1199
|
+
accountId,
|
|
1200
|
+
...(looksLikeEmail(context.subjectLabel) ? { email: context.subjectLabel } : {}),
|
|
1201
|
+
locked: (run) =>
|
|
1202
|
+
withRlsContext(deps.db, { accountId, workspaceId: null }, async (tx) => {
|
|
1203
|
+
// Same account lock as credit writers. All top-up/portal/subscription
|
|
1204
|
+
// callers share transactional read/create/persist under this one fence.
|
|
1205
|
+
await tx.execute(sql`select pg_advisory_xact_lock(hashtext(${accountId}))`);
|
|
1206
|
+
return await run({
|
|
1207
|
+
read: async () =>
|
|
1208
|
+
(await getBillingCustomer(tx, accountId, provider))?.providerCustomerId ?? null,
|
|
1209
|
+
account: async () => {
|
|
1210
|
+
const account = await getManagedAccount(tx, accountId);
|
|
1211
|
+
if (!account) throw new HTTPException(404, { message: "account not found" });
|
|
1212
|
+
return account;
|
|
1213
|
+
},
|
|
1214
|
+
save: (customer) =>
|
|
1215
|
+
upsertBillingCustomer(tx, {
|
|
1216
|
+
accountId,
|
|
1217
|
+
provider,
|
|
1218
|
+
providerCustomerId: customer.id,
|
|
1219
|
+
email: customer.email,
|
|
1220
|
+
}),
|
|
1221
|
+
});
|
|
1222
|
+
}),
|
|
1082
1223
|
});
|
|
1083
|
-
return customer.id;
|
|
1084
1224
|
}
|
|
1085
1225
|
|
|
1086
1226
|
export function stripeCustomerProvider(
|