@opengeni/api-router 2.3.2-canary.2 → 2.5.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/app.js +1 -1
- package/dist/auth/managed-auth-attempt-context.d.ts +4 -0
- package/dist/auth/managed-auth-session-adapter.d.ts +4 -0
- package/dist/{chunk-IBV7Z6F4.js → chunk-QESX7HDK.js} +3645 -470
- package/dist/chunk-QESX7HDK.js.map +1 -0
- package/dist/fatal-process-boundary.d.ts +25 -0
- package/dist/http/sse.d.ts +2 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.js +168 -6
- package/dist/index.js.map +1 -1
- package/dist/integrations/slack-interactions.d.ts +1 -1
- package/dist/mcp/receipts.d.ts +9 -0
- package/dist/mcp/server.d.ts +33 -0
- package/dist/organization-recovery-notifications.d.ts +41 -0
- package/dist/routes/managed-auth-session-sets.d.ts +19 -0
- package/dist/routes/organization-recovery.d.ts +19 -0
- package/dist/routes/sessions.d.ts +17 -5
- package/dist/routes/workspaces.d.ts +1 -0
- package/dist/work-discovery-observability.d.ts +33 -0
- package/package.json +18 -18
- package/src/app.ts +133 -1
- package/src/auth/managed-auth-attempt-context.ts +24 -0
- package/src/auth/managed-auth-session-adapter.ts +205 -0
- package/src/auth/managed-auth.ts +52 -2
- package/src/fatal-process-boundary.ts +231 -0
- package/src/http/sse.ts +7 -0
- package/src/index.ts +25 -5
- package/src/integrations/slack-interactions.ts +30 -17
- package/src/mcp/receipts.ts +34 -0
- package/src/mcp/server.ts +349 -68
- package/src/organization-recovery-notifications.ts +103 -0
- package/src/routes/canonical-human-identities.ts +29 -14
- package/src/routes/codex.ts +5 -1
- package/src/routes/environments.ts +23 -0
- package/src/routes/interaction-resources.ts +3 -0
- package/src/routes/managed-auth-session-sets.ts +994 -0
- package/src/routes/managed-onboarding.ts +2 -0
- package/src/routes/organization-memberships.ts +2 -0
- package/src/routes/organization-recovery.ts +325 -0
- package/src/routes/sessions.ts +401 -120
- package/src/routes/supergrok.ts +5 -1
- package/src/routes/workspaces.ts +23 -1
- package/src/work-discovery-observability.ts +121 -0
- package/dist/chunk-IBV7Z6F4.js.map +0 -1
|
@@ -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_create" | "artifacts_get_source" | "artifacts_list" | "artifacts_publish" | "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" | "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_set" | "goal_update" | "goal_wait" | "instruction_policy_propose" | "interaction_discover" | "interaction_request_human" | "knowledge_correct" | "knowledge_propose" | "memory_correct" | "memory_save" | "memory_search" | "preference_propose" | "preference_registry_get" | "preference_registry_summary" | "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_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" | "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_create" | "artifacts_get_source" | "artifacts_list" | "artifacts_publish" | "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" | "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_set" | "goal_update" | "goal_wait" | "instruction_policy_propose" | "interaction_discover" | "interaction_request_human" | "knowledge_correct" | "knowledge_propose" | "memory_correct" | "memory_save" | "memory_search" | "preference_propose" | "preference_registry_get" | "preference_registry_summary" | "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_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" | "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;
|
package/dist/mcp/receipts.d.ts
CHANGED
|
@@ -9,6 +9,15 @@ export type McpMutationReceiptInput = Omit<McpMutationReceiptType, "receiptVersi
|
|
|
9
9
|
* accidentally adding an unbounded entity or a copy of request fields.
|
|
10
10
|
*/
|
|
11
11
|
export declare function mcpMutationReceipt(input: McpMutationReceiptInput): McpMutationReceiptType;
|
|
12
|
+
export declare function sessionControlMutationReceipt(input: {
|
|
13
|
+
operation: "session_pause" | "session_resume";
|
|
14
|
+
sessionId: string;
|
|
15
|
+
state: string;
|
|
16
|
+
receiptId: string;
|
|
17
|
+
timestamp: string;
|
|
18
|
+
outcome: "changed" | "unchanged" | "replayed";
|
|
19
|
+
interruptionCount: number;
|
|
20
|
+
}): McpMutationReceiptType;
|
|
12
21
|
export type SessionCreateReceiptResult = {
|
|
13
22
|
session: {
|
|
14
23
|
id: string;
|
package/dist/mcp/server.d.ts
CHANGED
|
@@ -94,6 +94,39 @@ export declare function capSessionDiscoveryPage(page: Awaited<ReturnType<typeof
|
|
|
94
94
|
attentionSince?: string | null | undefined;
|
|
95
95
|
truncated: boolean;
|
|
96
96
|
};
|
|
97
|
+
relatedWork: {
|
|
98
|
+
claims: {
|
|
99
|
+
id: string;
|
|
100
|
+
sessionId: string;
|
|
101
|
+
subject: {
|
|
102
|
+
namespace: string;
|
|
103
|
+
type: "artifact" | "branch" | "ci_run" | "issue" | "other" | "pull_request" | "release" | "repository";
|
|
104
|
+
canonicalKey: string;
|
|
105
|
+
displayLabel: string | null;
|
|
106
|
+
};
|
|
107
|
+
role: "delivering" | "monitoring" | "reviewing" | "working";
|
|
108
|
+
state: "active" | "released" | "stale" | "superseded";
|
|
109
|
+
revision: number;
|
|
110
|
+
provenance: "explicit_agent" | "session_resource" | "system_lifecycle" | "trusted_integration" | "user_api";
|
|
111
|
+
version: {
|
|
112
|
+
kind: "artifact_version" | "branch_head" | "ci_run" | "git_commit" | "other" | "pull_request_head" | "release_version";
|
|
113
|
+
value: string;
|
|
114
|
+
} | null;
|
|
115
|
+
observedAt: string;
|
|
116
|
+
updatedAt: string;
|
|
117
|
+
settledAt: string | null;
|
|
118
|
+
}[];
|
|
119
|
+
claimsTruncated: boolean;
|
|
120
|
+
match: {
|
|
121
|
+
class: "exact_subject" | "fuzzy" | "goal" | "title";
|
|
122
|
+
field: "claim_key" | "claim_label" | "goal" | "subject" | "title";
|
|
123
|
+
scoreBand: "exact" | "related" | "strong";
|
|
124
|
+
claimId: string | null;
|
|
125
|
+
} | null;
|
|
126
|
+
possibleOverlap: boolean;
|
|
127
|
+
advisoryOnly: true;
|
|
128
|
+
noAdditionalAccess: true;
|
|
129
|
+
};
|
|
97
130
|
latestMessage?: {
|
|
98
131
|
type: "agent.message.completed" | "agent.message.delta" | "agent.model.request" | "agent.model.usage" | "agent.reasoning.delta" | "agent.toolCall.created" | "agent.toolCall.output" | "agent.updated" | "artifact.created" | "codex.account.switched" | "codex.capacity.resumed" | "codex.capacity.superseded" | "codex.capacity.waiting" | "codex.credential.selected" | "codex.fleet.decision" | "credential.auth_needed" | "fs.changed" | "git.changed" | "goal.cleared" | "goal.completed" | "goal.continuation" | "goal.held" | "goal.paused" | "goal.progress" | "goal.resumed" | "goal.rewrite.proposed" | "goal.rewrite.rejected" | "goal.set" | "goal.updated" | "machine.link.lost" | "machine.link.restored" | "machine.op.failed" | "machine.op.recovered" | "machine.runner.restarted" | "memory.corrected" | "memory.saved" | "recording.available" | "recording.failed" | "recording.started" | "rig.setup.completed" | "rig.setup.failed" | "rig.setup.skipped" | "rig.setup.started" | "sandbox.box.created" | "sandbox.box.lost" | "sandbox.box.snapshot" | "sandbox.box.terminated" | "sandbox.command.output.delta" | "sandbox.env.drift" | "sandbox.operation.completed" | "sandbox.operation.failed" | "sandbox.operation.started" | "session.command.backgrounded" | "session.command.finished" | "session.context.cleared" | "session.context.compacted" | "session.context.compaction.requested" | "session.context.compaction.skipped" | "session.context.compaction.started" | "session.control.paused" | "session.control.resumed" | "session.control.steer_requested" | "session.created" | "session.event.envelope_omitted" | "session.humanInput.requested" | "session.mcp.approval_policy.updated" | "session.personal_resources.attached" | "session.queue.changed" | "session.queue.history" | "session.queue.prompt.cancelled" | "session.realtime.ended" | "session.realtime.started" | "session.requiresAction" | "session.route.reconciled" | "session.runtime.configured" | "session.status.changed" | "session.title_set" | "session.tool_policy.updated" | "session.variable_sets.updated" | "session.visibility.changed" | "stream.closed" | "stream.opened" | "stream.revoked" | "stream.url.rotated" | "system.update.cancelled" | "system.update.delivered" | "system.update.pending" | "system.update.settled" | "system.update.superseded" | "terminal.pty.exited" | "terminal.pty.output.delta" | "terminal.pty.started" | "tool.auth_needed" | "turn.cancelled" | "turn.capacity_waiting" | "turn.completed" | "turn.event.rejected_late" | "turn.failed" | "turn.queued" | "turn.recovery.requested" | "turn.started" | "turn.startup.phase.completed" | "turn.startup.phase.failed" | "turn.startup.phase.started" | "turn.superseded" | "user.approvalDecision" | "user.humanInputResponse" | "user.message" | "user.pause" | "workspace.inference.paused" | "workspace.inference.resumed" | "workspace.revision.captured" | "workspace.revision.degraded";
|
|
99
132
|
preview: string | null;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Database } from "@opengeni/db";
|
|
2
|
+
import { prepareOrganizationRecoveryNotifications, settleOrganizationRecoveryNotification, type OrganizationRecoveryNotificationClaim, type OrganizationRecoveryNotificationSettlement } from "@opengeni/db";
|
|
3
|
+
export type OrganizationRecoveryNotificationDeliveryResult = {
|
|
4
|
+
status: "sent";
|
|
5
|
+
providerMessageId: string | null;
|
|
6
|
+
} | {
|
|
7
|
+
status: "failed";
|
|
8
|
+
errorClass: string;
|
|
9
|
+
} | {
|
|
10
|
+
status: "outcome_unknown";
|
|
11
|
+
};
|
|
12
|
+
export interface OrganizationRecoveryNotificationTransport {
|
|
13
|
+
readonly provider: string;
|
|
14
|
+
send(claim: OrganizationRecoveryNotificationClaim): Promise<OrganizationRecoveryNotificationDeliveryResult>;
|
|
15
|
+
}
|
|
16
|
+
export type OrganizationRecoveryNotificationLifecycle = {
|
|
17
|
+
prepare: typeof prepareOrganizationRecoveryNotifications;
|
|
18
|
+
settle: typeof settleOrganizationRecoveryNotification;
|
|
19
|
+
};
|
|
20
|
+
export declare function dispatchOrganizationRecoveryNotifications(input: {
|
|
21
|
+
db: Database;
|
|
22
|
+
transport: OrganizationRecoveryNotificationTransport;
|
|
23
|
+
claimOwner: string;
|
|
24
|
+
limit?: number;
|
|
25
|
+
leaseSeconds?: number;
|
|
26
|
+
lifecycle?: OrganizationRecoveryNotificationLifecycle;
|
|
27
|
+
}): Promise<OrganizationRecoveryNotificationSettlement[]>;
|
|
28
|
+
export declare class InMemoryOrganizationRecoveryNotificationTransport implements OrganizationRecoveryNotificationTransport {
|
|
29
|
+
readonly provider = "fake";
|
|
30
|
+
readonly attempts: Array<{
|
|
31
|
+
idempotencyKey: string;
|
|
32
|
+
payloadDigest: string;
|
|
33
|
+
recipientCanonicalIdentityId: string;
|
|
34
|
+
providerMessageId: string;
|
|
35
|
+
}>;
|
|
36
|
+
private readonly deliveries;
|
|
37
|
+
private readonly scripted;
|
|
38
|
+
enqueue(...results: OrganizationRecoveryNotificationDeliveryResult[]): void;
|
|
39
|
+
logicalDeliveryCount(): number;
|
|
40
|
+
send(claim: OrganizationRecoveryNotificationClaim): Promise<OrganizationRecoveryNotificationDeliveryResult>;
|
|
41
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type ApiRouteDeps } from "@opengeni/core";
|
|
2
|
+
import type { Hono } from "hono";
|
|
3
|
+
export declare function registerManagedAuthSessionSetRoutes(app: Hono, deps: ApiRouteDeps): void;
|
|
4
|
+
/**
|
|
5
|
+
* Better Auth 1.6.26 provider lifecycle routes retained while session-set mode
|
|
6
|
+
* owns all selected-session reads, enumeration, revocation, and user mutation.
|
|
7
|
+
* The list is intentionally exact so a dependency upgrade cannot silently add
|
|
8
|
+
* a selected-session capability under the wildcard.
|
|
9
|
+
*/
|
|
10
|
+
export declare function requireManagedAuthProviderRouteAllowed(method: string, pathname: string): void;
|
|
11
|
+
/** Remove provider bearer/session material and enforce browser-auth cache/cookie policy. */
|
|
12
|
+
export declare function scrubManagedAuthProviderResponse(response: Response, options?: {
|
|
13
|
+
replacementCookies?: readonly string[] | undefined;
|
|
14
|
+
}): Promise<Response>;
|
|
15
|
+
export declare function parseSupportedDeepLink(path: string): {
|
|
16
|
+
workspaceId: string | null;
|
|
17
|
+
sessionId: string | null;
|
|
18
|
+
permission: "workspace:read" | "sessions:read";
|
|
19
|
+
} | null;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { getManagedAuthRequestActorAdmissionStamp, getManagedAuthRequestActorLeaseStamp, requireCanonicalHumanRequestIdentity } from "@opengeni/core/canonical-human-identities";
|
|
2
|
+
import type { ApiRouteDeps } from "@opengeni/core";
|
|
3
|
+
import { acceptOrganizationRecoveryCustody, approveOrganizationRecoveryOperation, cancelOrganizationRecoveryOperation, configureOrganizationRecoveryPolicy, disableOrganizationRecoveryPolicy, executeOrganizationRecoveryOperation, getOrganizationRecoveryOverview, startOrganizationRecoveryOperation } from "@opengeni/db";
|
|
4
|
+
import type { Hono } from "hono";
|
|
5
|
+
export type OrganizationRecoveryRouteServices = {
|
|
6
|
+
requireCanonicalHumanRequestIdentity: typeof requireCanonicalHumanRequestIdentity;
|
|
7
|
+
getManagedAuthRequestActorAdmissionStamp: typeof getManagedAuthRequestActorAdmissionStamp;
|
|
8
|
+
getManagedAuthRequestActorLeaseStamp: typeof getManagedAuthRequestActorLeaseStamp;
|
|
9
|
+
getOrganizationRecoveryOverview: typeof getOrganizationRecoveryOverview;
|
|
10
|
+
configureOrganizationRecoveryPolicy: typeof configureOrganizationRecoveryPolicy;
|
|
11
|
+
acceptOrganizationRecoveryCustody: typeof acceptOrganizationRecoveryCustody;
|
|
12
|
+
disableOrganizationRecoveryPolicy: typeof disableOrganizationRecoveryPolicy;
|
|
13
|
+
startOrganizationRecoveryOperation: typeof startOrganizationRecoveryOperation;
|
|
14
|
+
approveOrganizationRecoveryOperation: typeof approveOrganizationRecoveryOperation;
|
|
15
|
+
cancelOrganizationRecoveryOperation: typeof cancelOrganizationRecoveryOperation;
|
|
16
|
+
executeOrganizationRecoveryOperation: typeof executeOrganizationRecoveryOperation;
|
|
17
|
+
};
|
|
18
|
+
export declare function organizationRecoveryHttpError(error: unknown): Error;
|
|
19
|
+
export declare function registerOrganizationRecoveryRoutes(app: Hono, deps: ApiRouteDeps, services?: OrganizationRecoveryRouteServices): void;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ClientSessionEvent, SteerSessionMessageRequest, type SessionGoalRevision, type SessionAuthorizationOperation } from "@opengeni/contracts";
|
|
1
|
+
import { ClientSessionEvent, SteerSessionMessageRequest, type SessionStatus, type WorkClaimSubjectFilter, type SessionGoalRevision, type SessionAuthorizationOperation } from "@opengeni/contracts";
|
|
2
2
|
import { type SessionDiscoveryCursor } from "@opengeni/db";
|
|
3
3
|
import type { Context, Hono } from "hono";
|
|
4
4
|
import type { ApiRouteDeps } from "@opengeni/core";
|
|
@@ -15,14 +15,26 @@ export declare function sessionAuthorizationOperationForHttp(method: string, pat
|
|
|
15
15
|
export declare function sessionTenancyHttpError(error: unknown): Error;
|
|
16
16
|
export type AgentTopologyCursorEnvelope = {
|
|
17
17
|
cursor: SessionDiscoveryCursor;
|
|
18
|
-
parentSessionId: string | null;
|
|
19
|
-
|
|
18
|
+
parentSessionId: string | null | "all";
|
|
19
|
+
rootSessionId: string | null;
|
|
20
|
+
query: string | null;
|
|
21
|
+
statuses: SessionStatus[];
|
|
22
|
+
activeOnly: boolean;
|
|
23
|
+
recentHours: number | null;
|
|
24
|
+
subject: WorkClaimSubjectFilter | null;
|
|
25
|
+
claimLimit: number | null;
|
|
20
26
|
};
|
|
21
27
|
export declare function encodeAgentTopologyCursor(value: AgentTopologyCursorEnvelope): string;
|
|
22
28
|
export declare function agentTopologyQuery(query: Record<string, string>): {
|
|
23
29
|
limit: number;
|
|
24
|
-
parentSessionId: string | null;
|
|
25
|
-
|
|
30
|
+
parentSessionId: string | null | undefined;
|
|
31
|
+
rootSessionId: string | undefined;
|
|
32
|
+
query: string | undefined;
|
|
33
|
+
statuses: SessionStatus[] | undefined;
|
|
34
|
+
activeOnly: boolean;
|
|
35
|
+
recentHours: number | undefined;
|
|
36
|
+
subject: WorkClaimSubjectFilter | undefined;
|
|
37
|
+
claimLimit: number | undefined;
|
|
26
38
|
cursor: SessionDiscoveryCursor | undefined;
|
|
27
39
|
};
|
|
28
40
|
/** Stable, value-free JSON errors for only the create-session boundary. */
|
|
@@ -20,5 +20,6 @@ export declare function workspaceMembersResponse(members: readonly WorkspaceMemb
|
|
|
20
20
|
createdAt: string;
|
|
21
21
|
}[];
|
|
22
22
|
};
|
|
23
|
+
export declare function workspaceUpdateRequestsAccountTransfer(value: unknown): boolean;
|
|
23
24
|
export declare function registerWorkspaceRoutes(app: Hono, deps: ApiRouteDeps): void;
|
|
24
25
|
export {};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { WorkDiscoveryMatchClass } from "@opengeni/contracts";
|
|
2
|
+
import type { Observability } from "@opengeni/observability";
|
|
3
|
+
export type WorkDiscoverySurface = "first_party_mcp" | "agent_topology";
|
|
4
|
+
export type WorkDiscoveryMode = "browse" | "query" | "subject";
|
|
5
|
+
export type WorkDiscoveryOutcome = "ok" | "empty" | "disabled" | "error";
|
|
6
|
+
export type WorkDiscoveryAuthorizationScope = "workspace" | "scoped";
|
|
7
|
+
export type WorkDiscoveryObservation = {
|
|
8
|
+
surface: WorkDiscoverySurface;
|
|
9
|
+
mode: WorkDiscoveryMode;
|
|
10
|
+
outcome: WorkDiscoveryOutcome;
|
|
11
|
+
authorizationScope: WorkDiscoveryAuthorizationScope;
|
|
12
|
+
durationMs: number;
|
|
13
|
+
responseBytes: number;
|
|
14
|
+
resultCount: number;
|
|
15
|
+
overlapCount: number;
|
|
16
|
+
matchCounts: Partial<Record<WorkDiscoveryMatchClass, number>>;
|
|
17
|
+
};
|
|
18
|
+
type WorkDiscoveryObservedRow = {
|
|
19
|
+
relatedWork: {
|
|
20
|
+
match: {
|
|
21
|
+
class: WorkDiscoveryMatchClass;
|
|
22
|
+
} | null;
|
|
23
|
+
possibleOverlap: boolean;
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
export declare function summarizeWorkDiscoveryRows(rows: readonly WorkDiscoveryObservedRow[]): Pick<WorkDiscoveryObservation, "resultCount" | "overlapCount" | "matchCounts">;
|
|
27
|
+
/**
|
|
28
|
+
* Low-cardinality work-discovery telemetry. Identifiers, search text, subject
|
|
29
|
+
* keys, titles, goals, claim labels, versions, and provenance are excluded by
|
|
30
|
+
* construction. An observability failure never changes product behavior.
|
|
31
|
+
*/
|
|
32
|
+
export declare function observeWorkDiscovery(observability: Observability | null | undefined, observation: WorkDiscoveryObservation): void;
|
|
33
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengeni/api-router",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.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,23 +43,23 @@
|
|
|
43
43
|
"@hono/zod-validator": "^0.7.6",
|
|
44
44
|
"@llamaindex/liteparse": "^1.5.3",
|
|
45
45
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
46
|
-
"@opengeni/agent-proto": "^0.5.1
|
|
47
|
-
"@opengeni/artifact-tool": "^0.3.
|
|
48
|
-
"@opengeni/capabilities": "^0.3.1
|
|
49
|
-
"@opengeni/codemode": "^0.4.
|
|
50
|
-
"@opengeni/codex": "^0.2.19
|
|
51
|
-
"@opengeni/config": "^0.
|
|
52
|
-
"@opengeni/contracts": "^2.
|
|
53
|
-
"@opengeni/core": "^2.
|
|
54
|
-
"@opengeni/db": "^3.
|
|
55
|
-
"@opengeni/documents": "^0.8.
|
|
56
|
-
"@opengeni/events": "^0.4.
|
|
57
|
-
"@opengeni/github": "^0.
|
|
58
|
-
"@opengeni/network": "^0.2.3
|
|
59
|
-
"@opengeni/observability": "^0.8.
|
|
60
|
-
"@opengeni/runtime": "^1.4.
|
|
61
|
-
"@opengeni/storage": "^0.2.
|
|
62
|
-
"@opengeni/xai-subscription": "^0.1.2
|
|
46
|
+
"@opengeni/agent-proto": "^0.5.1",
|
|
47
|
+
"@opengeni/artifact-tool": "^0.3.9",
|
|
48
|
+
"@opengeni/capabilities": "^0.3.1",
|
|
49
|
+
"@opengeni/codemode": "^0.4.17",
|
|
50
|
+
"@opengeni/codex": "^0.2.19",
|
|
51
|
+
"@opengeni/config": "^0.22.0",
|
|
52
|
+
"@opengeni/contracts": "^2.7.0",
|
|
53
|
+
"@opengeni/core": "^2.5.3",
|
|
54
|
+
"@opengeni/db": "^3.6.0",
|
|
55
|
+
"@opengeni/documents": "^0.8.6",
|
|
56
|
+
"@opengeni/events": "^0.4.4",
|
|
57
|
+
"@opengeni/github": "^0.6.1",
|
|
58
|
+
"@opengeni/network": "^0.2.3",
|
|
59
|
+
"@opengeni/observability": "^0.8.9",
|
|
60
|
+
"@opengeni/runtime": "^1.4.2",
|
|
61
|
+
"@opengeni/storage": "^0.2.110",
|
|
62
|
+
"@opengeni/xai-subscription": "^0.1.2",
|
|
63
63
|
"@temporalio/client": "^1.17.0",
|
|
64
64
|
"better-auth": "^1.6.14",
|
|
65
65
|
"hono": "^4.12.18",
|
package/src/app.ts
CHANGED
|
@@ -36,7 +36,10 @@ import {
|
|
|
36
36
|
configureChildLifecycleNotices,
|
|
37
37
|
configureWorkspaceControlRequestLockTimeoutMs,
|
|
38
38
|
dbSql,
|
|
39
|
+
getManagedAuthSessionSetSnapshot,
|
|
39
40
|
getWorkspace,
|
|
41
|
+
reapManagedAuthIsolatedSessions,
|
|
42
|
+
reapExpiredManagedAuthSessionSets,
|
|
40
43
|
rlsContextForWorkspace,
|
|
41
44
|
withSessionRlsActorContext,
|
|
42
45
|
} from "@opengeni/db";
|
|
@@ -49,21 +52,32 @@ import { Hono } from "hono";
|
|
|
49
52
|
import { bodyLimit } from "hono/body-limit";
|
|
50
53
|
import { compress } from "hono/compress";
|
|
51
54
|
import { cors } from "hono/cors";
|
|
55
|
+
import { getCookie } from "hono/cookie";
|
|
52
56
|
import { HTTPException } from "hono/http-exception";
|
|
53
57
|
import { ApiHttpError, workspaceControlBusyHttpError } from "./http/api-error";
|
|
54
58
|
import type { ContentfulStatusCode } from "hono/utils/http-status";
|
|
55
59
|
import type { ApiRouteDeps, AppDependencies } from "@opengeni/core";
|
|
56
60
|
import {
|
|
57
61
|
CodexCompactionV2ProviderLockedError,
|
|
62
|
+
ManagedAuthActorLeaseOutcomeUnknownError,
|
|
58
63
|
hasPermission,
|
|
59
64
|
requireAccessGrant,
|
|
60
65
|
requireLiveAgentAttemptAuthorization,
|
|
61
66
|
requirePermission,
|
|
67
|
+
releaseManagedAuthRequestActorLease,
|
|
68
|
+
validateManagedAuthRequestActorLease,
|
|
62
69
|
requireSessionAuthorization,
|
|
63
70
|
SessionAuthorizationDeniedError,
|
|
64
71
|
SessionAuthorizationUnavailableError,
|
|
65
72
|
} from "@opengeni/core";
|
|
66
73
|
import { createManagedAuth } from "./auth/managed-auth";
|
|
74
|
+
import {
|
|
75
|
+
MANAGED_AUTH_SESSION_SET_COOKIE,
|
|
76
|
+
ManagedAuthActorChangeError,
|
|
77
|
+
managedAuthSha256,
|
|
78
|
+
} from "@opengeni/core/managed-auth-session-sets";
|
|
79
|
+
import { createBetterAuthSessionAdapter } from "./auth/managed-auth-session-adapter";
|
|
80
|
+
import { runManagedAuthDiscardedProviderSession } from "./auth/managed-auth-attempt-context";
|
|
67
81
|
import { createManagedEmailTransport } from "./auth/managed-email";
|
|
68
82
|
import { assertManagedEmailTransportMetadata } from "./auth/organization-user-setup";
|
|
69
83
|
import { createApiSandboxClient, makeResumeBoxById } from "./sandbox/access";
|
|
@@ -135,7 +149,13 @@ import { registerEditableArtifactRoutes } from "./routes/editable-artifacts";
|
|
|
135
149
|
import { registerVideoGenerationRoutes } from "./routes/video-generation";
|
|
136
150
|
import { registerCanonicalHumanIdentityRoutes } from "./routes/canonical-human-identities";
|
|
137
151
|
import { registerOrganizationMembershipRoutes } from "./routes/organization-memberships";
|
|
152
|
+
import { registerOrganizationRecoveryRoutes } from "./routes/organization-recovery";
|
|
138
153
|
import { registerManagedOnboardingRoutes } from "./routes/managed-onboarding";
|
|
154
|
+
import {
|
|
155
|
+
registerManagedAuthSessionSetRoutes,
|
|
156
|
+
requireManagedAuthProviderRouteAllowed,
|
|
157
|
+
scrubManagedAuthProviderResponse,
|
|
158
|
+
} from "./routes/managed-auth-session-sets";
|
|
139
159
|
import { registerUserResourceAuthorityRoutes } from "./routes/user-resource-authorities";
|
|
140
160
|
import { registerConnectionAuthorityRoutes } from "./routes/connection-authorities";
|
|
141
161
|
import { projectClientModel } from "./model-catalog";
|
|
@@ -167,6 +187,8 @@ export { workflowIdForSession } from "@opengeni/core";
|
|
|
167
187
|
export { replaySessionEvents, sseSessionStream, sseWorkspaceControlStream } from "./http/sse";
|
|
168
188
|
|
|
169
189
|
export const API_MAX_REQUEST_BODY_BYTES = 32 * 1024 * 1024;
|
|
190
|
+
const managedAuthReaperDatabases = new WeakSet<object>();
|
|
191
|
+
const MANAGED_AUTH_REAPER_INTERVAL_MS = 60_000;
|
|
170
192
|
|
|
171
193
|
/** Effective Hono bodyLimit — API JSON ceiling or voice multipart + multipart overhead. */
|
|
172
194
|
export function apiRequestBodyLimitBytes(settings: {
|
|
@@ -202,6 +224,9 @@ export function createAppComposition(deps: AppDependencies): {
|
|
|
202
224
|
assertManagedEmailTransportMetadata(managedEmailTransport);
|
|
203
225
|
const managedAuth =
|
|
204
226
|
deps.managedAuth ?? createManagedAuth(deps.settings, deps.db, managedEmailTransport);
|
|
227
|
+
const managedAuthSessionAdapter =
|
|
228
|
+
deps.managedAuthSessionAdapter ??
|
|
229
|
+
(managedAuth ? createBetterAuthSessionAdapter(managedAuth, deps.db) : null);
|
|
205
230
|
const objectStorage =
|
|
206
231
|
deps.objectStorage === undefined ? createObjectStorage(deps.settings) : deps.objectStorage;
|
|
207
232
|
let documentServices: DocumentServices | null = deps.documentServices ?? null;
|
|
@@ -284,6 +309,24 @@ export function createAppComposition(deps: AppDependencies): {
|
|
|
284
309
|
const resumeBoxById = deps.resumeBoxById ?? makeResumeBoxById(sandboxClient);
|
|
285
310
|
const observability =
|
|
286
311
|
deps.observability ?? createObservability(deps.settings, { component: "api" });
|
|
312
|
+
if (
|
|
313
|
+
managedAuth &&
|
|
314
|
+
deps.settings.managedAuthSessionSetMode !== "legacy" &&
|
|
315
|
+
!managedAuthReaperDatabases.has(deps.db as object)
|
|
316
|
+
) {
|
|
317
|
+
managedAuthReaperDatabases.add(deps.db as object);
|
|
318
|
+
const timer = setInterval(() => {
|
|
319
|
+
void Promise.all([
|
|
320
|
+
reapManagedAuthIsolatedSessions(deps.db, 100),
|
|
321
|
+
reapExpiredManagedAuthSessionSets(deps.db, 100),
|
|
322
|
+
]).catch((error) => {
|
|
323
|
+
observability.error("Managed isolated-auth orphan reap failed", {
|
|
324
|
+
errorClass: error instanceof Error ? error.name : "UnknownError",
|
|
325
|
+
});
|
|
326
|
+
});
|
|
327
|
+
}, MANAGED_AUTH_REAPER_INTERVAL_MS);
|
|
328
|
+
(timer as ReturnType<typeof setInterval> & { unref?: () => void }).unref?.();
|
|
329
|
+
}
|
|
287
330
|
const transcription =
|
|
288
331
|
deps.transcription === undefined
|
|
289
332
|
? createTranscriptionService({
|
|
@@ -304,6 +347,7 @@ export function createAppComposition(deps: AppDependencies): {
|
|
|
304
347
|
githubStateSecret:
|
|
305
348
|
deps.githubStateSecret ?? deps.settings.githubAppManifestStateSecret ?? crypto.randomUUID(),
|
|
306
349
|
managedAuth,
|
|
350
|
+
managedAuthSessionAdapter,
|
|
307
351
|
managedEmailTransport,
|
|
308
352
|
objectStorage,
|
|
309
353
|
documentIndexer,
|
|
@@ -332,13 +376,17 @@ export function createAppComposition(deps: AppDependencies): {
|
|
|
332
376
|
"Range",
|
|
333
377
|
"X-OpenGeni-Access-Key",
|
|
334
378
|
"X-OpenGeni-Api-Contract",
|
|
379
|
+
"X-OpenGeni-Actor-Epoch",
|
|
335
380
|
"X-OpenGeni-Correlation-Id",
|
|
381
|
+
"X-OpenGeni-Session-Csrf",
|
|
336
382
|
"X-OpenGeni-Subject",
|
|
337
383
|
],
|
|
338
384
|
exposeHeaders: [
|
|
339
385
|
"Accept-Ranges",
|
|
340
386
|
"Content-Range",
|
|
341
387
|
"X-OpenGeni-Api-Contract",
|
|
388
|
+
"X-OpenGeni-Actor-Epoch",
|
|
389
|
+
"X-OpenGeni-Actor-State",
|
|
342
390
|
"X-OpenGeni-Correlation-Id",
|
|
343
391
|
],
|
|
344
392
|
};
|
|
@@ -495,11 +543,93 @@ export function createAppComposition(deps: AppDependencies): {
|
|
|
495
543
|
await next();
|
|
496
544
|
});
|
|
497
545
|
|
|
546
|
+
app.use("/v1/*", async (c, next) => {
|
|
547
|
+
try {
|
|
548
|
+
await next();
|
|
549
|
+
try {
|
|
550
|
+
await validateManagedAuthRequestActorLease(c.req.raw);
|
|
551
|
+
} catch (error) {
|
|
552
|
+
if (error instanceof ManagedAuthActorChangeError) {
|
|
553
|
+
c.header("x-opengeni-actor-state", "changed");
|
|
554
|
+
throw new HTTPException(409, { message: error.code, cause: error });
|
|
555
|
+
}
|
|
556
|
+
if (error instanceof ManagedAuthActorLeaseOutcomeUnknownError) {
|
|
557
|
+
throw new ApiHttpError(503, {
|
|
558
|
+
code: "upstream_unavailable",
|
|
559
|
+
message: error.code,
|
|
560
|
+
retryable: true,
|
|
561
|
+
outcomeUnknown: true,
|
|
562
|
+
details: { managedAuthCode: error.code },
|
|
563
|
+
});
|
|
564
|
+
}
|
|
565
|
+
throw error;
|
|
566
|
+
}
|
|
567
|
+
} finally {
|
|
568
|
+
await releaseManagedAuthRequestActorLease(c.req.raw).catch((error) => {
|
|
569
|
+
observability.error("Managed actor mutation lease release failed", {
|
|
570
|
+
errorClass: error instanceof Error ? error.name : "UnknownError",
|
|
571
|
+
});
|
|
572
|
+
});
|
|
573
|
+
}
|
|
574
|
+
});
|
|
575
|
+
|
|
498
576
|
// These product-owned auth routes must be registered before Better Auth's
|
|
499
577
|
// wildcard handler or the provider returns its own 404 first.
|
|
500
578
|
registerManagedOnboardingRoutes(app, routeDeps);
|
|
579
|
+
registerManagedAuthSessionSetRoutes(app, routeDeps);
|
|
501
580
|
if (managedAuth) {
|
|
502
|
-
app.on(["GET", "POST"], "/v1/auth/*", (c) =>
|
|
581
|
+
app.on(["GET", "POST"], "/v1/auth/*", async (c) => {
|
|
582
|
+
if (deps.settings.managedAuthSessionSetMode === "legacy") {
|
|
583
|
+
return await managedAuth.handler(c.req.raw);
|
|
584
|
+
}
|
|
585
|
+
requireManagedAuthProviderRouteAllowed(c.req.method, new URL(c.req.url).pathname);
|
|
586
|
+
// Provider authentication/recovery is isolated from whichever actor the
|
|
587
|
+
// browser currently renders. Selected-session capabilities are all
|
|
588
|
+
// product-owned above this wildcard and generation/epoch fenced.
|
|
589
|
+
const headers = new Headers(c.req.raw.headers);
|
|
590
|
+
headers.delete("cookie");
|
|
591
|
+
headers.delete("authorization");
|
|
592
|
+
headers.delete("x-forwarded-user");
|
|
593
|
+
const providerRequest = new Request(c.req.raw, { headers });
|
|
594
|
+
const authority = getCookie(c, MANAGED_AUTH_SESSION_SET_COOKIE);
|
|
595
|
+
const discardProviderSession =
|
|
596
|
+
deps.settings.managedAuthSessionSetMode === "broker" || authority !== undefined;
|
|
597
|
+
const providerResponse = discardProviderSession
|
|
598
|
+
? await runManagedAuthDiscardedProviderSession(
|
|
599
|
+
async () => await managedAuth.handler(providerRequest),
|
|
600
|
+
)
|
|
601
|
+
: await managedAuth.handler(providerRequest);
|
|
602
|
+
let replacementCookies: readonly string[] | undefined;
|
|
603
|
+
if (deps.settings.managedAuthSessionSetMode === "broker") {
|
|
604
|
+
replacementCookies = await managedAuthSessionAdapter!.createLegacySelectedSessionCookies(
|
|
605
|
+
null,
|
|
606
|
+
c.req.header("cookie") ?? null,
|
|
607
|
+
);
|
|
608
|
+
} else {
|
|
609
|
+
if (authority !== undefined) {
|
|
610
|
+
const snapshot = await getManagedAuthSessionSetSnapshot(deps.db, {
|
|
611
|
+
authorityHash: managedAuthSha256(authority),
|
|
612
|
+
mode: "dual",
|
|
613
|
+
includeInternal: true,
|
|
614
|
+
readOnly: true,
|
|
615
|
+
});
|
|
616
|
+
if (snapshot) {
|
|
617
|
+
replacementCookies =
|
|
618
|
+
await managedAuthSessionAdapter!.createLegacySelectedSessionCookies(
|
|
619
|
+
snapshot.selected,
|
|
620
|
+
c.req.header("cookie") ?? null,
|
|
621
|
+
);
|
|
622
|
+
} else {
|
|
623
|
+
replacementCookies =
|
|
624
|
+
await managedAuthSessionAdapter!.createLegacySelectedSessionCookies(
|
|
625
|
+
null,
|
|
626
|
+
c.req.header("cookie") ?? null,
|
|
627
|
+
);
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
return await scrubManagedAuthProviderResponse(providerResponse, { replacementCookies });
|
|
632
|
+
});
|
|
503
633
|
}
|
|
504
634
|
|
|
505
635
|
app.get("/healthz", (c) =>
|
|
@@ -585,6 +715,7 @@ export function createAppComposition(deps: AppDependencies): {
|
|
|
585
715
|
: {}),
|
|
586
716
|
},
|
|
587
717
|
productAccessMode: deps.settings.productAccessMode,
|
|
718
|
+
managedAuthSessionSetMode: deps.settings.managedAuthSessionSetMode,
|
|
588
719
|
auth: clientAuthConfig(deps.settings),
|
|
589
720
|
analytics: clientAnalyticsConfig(deps.settings),
|
|
590
721
|
// Channel-A structured services (P4.4) ride exec/readFile/createEditor,
|
|
@@ -765,6 +896,7 @@ export function createAppComposition(deps: AppDependencies): {
|
|
|
765
896
|
registerVideoGenerationRoutes(app, routeDeps);
|
|
766
897
|
registerCanonicalHumanIdentityRoutes(app, routeDeps);
|
|
767
898
|
registerOrganizationMembershipRoutes(app, routeDeps);
|
|
899
|
+
registerOrganizationRecoveryRoutes(app, routeDeps);
|
|
768
900
|
registerUserResourceAuthorityRoutes(app, routeDeps);
|
|
769
901
|
registerConnectionAuthorityRoutes(app, routeDeps);
|
|
770
902
|
registerSlackInteractionRoutes(app, routeDeps);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
|
+
|
|
3
|
+
type ManagedAuthAttemptContext =
|
|
4
|
+
| { kind: "isolated_transaction"; transactionId: string }
|
|
5
|
+
| { kind: "discard_provider_session" };
|
|
6
|
+
|
|
7
|
+
const managedAuthAttemptStorage = new AsyncLocalStorage<ManagedAuthAttemptContext>();
|
|
8
|
+
|
|
9
|
+
export function runManagedAuthAttempt<T>(transactionId: string, action: () => T): T {
|
|
10
|
+
return managedAuthAttemptStorage.run({ kind: "isolated_transaction", transactionId }, action);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function runManagedAuthDiscardedProviderSession<T>(action: () => T): T {
|
|
14
|
+
return managedAuthAttemptStorage.run({ kind: "discard_provider_session" }, action);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function currentManagedAuthAttemptId(): string | null {
|
|
18
|
+
const context = managedAuthAttemptStorage.getStore();
|
|
19
|
+
return context?.kind === "isolated_transaction" ? context.transactionId : null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function shouldDiscardCurrentManagedAuthProviderSession(): boolean {
|
|
23
|
+
return managedAuthAttemptStorage.getStore()?.kind === "discard_provider_session";
|
|
24
|
+
}
|