@opengeni/core 0.28.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (224) hide show
  1. package/README.md +1 -1
  2. package/dist/access/external-actor-authority.d.ts +47 -0
  3. package/dist/access/index.d.ts +182 -3
  4. package/dist/access/service-initiator.d.ts +3 -0
  5. package/dist/application/api-integration-servers.d.ts +20 -0
  6. package/dist/application/archived-session-imports.d.ts +6 -0
  7. package/dist/application/composer-submit.d.ts +24 -0
  8. package/dist/application/connect-authority.d.ts +13 -0
  9. package/dist/application/connect-operation.d.ts +31 -0
  10. package/dist/application/external-continuation.d.ts +15 -0
  11. package/dist/application/external-identity-lifecycle.d.ts +20 -0
  12. package/dist/application/external-link-work-admission.d.ts +12 -0
  13. package/dist/application/external-workspace-members.d.ts +34 -0
  14. package/dist/application/modal-native-worker-host-transport.d.ts +297 -0
  15. package/dist/application/new-session-drafts.d.ts +39 -2
  16. package/dist/application/sandbox-recovery.d.ts +58 -0
  17. package/dist/application/session-commands.d.ts +26 -13
  18. package/dist/application/session-mcp-credential-rotation.d.ts +29 -0
  19. package/dist/application/session-tenancy.d.ts +19 -0
  20. package/dist/application/user-resource-grants.d.ts +20 -0
  21. package/dist/billing/limits.d.ts +11 -0
  22. package/dist/canonical-human-identities.d.ts +7 -2
  23. package/dist/canonical-human-identities.js +17 -4
  24. package/dist/canonical-human-identities.js.map +1 -1
  25. package/dist/{chunk-6WKPWE5S.js → chunk-2MKMRGSY.js} +108 -24
  26. package/dist/chunk-2MKMRGSY.js.map +1 -0
  27. package/dist/{chunk-NYPMQ7NO.js → chunk-GVO3N37G.js} +205 -37
  28. package/dist/chunk-GVO3N37G.js.map +1 -0
  29. package/dist/{chunk-JJU6I5XD.js → chunk-LCQXNR62.js} +36 -10
  30. package/dist/chunk-LCQXNR62.js.map +1 -0
  31. package/dist/chunk-MM6N7CTO.js +387 -0
  32. package/dist/chunk-MM6N7CTO.js.map +1 -0
  33. package/dist/chunk-QO5GVFFO.js +235 -0
  34. package/dist/chunk-QO5GVFFO.js.map +1 -0
  35. package/dist/codex-model-availability.d.ts +14 -0
  36. package/dist/default-session-model.d.ts +139 -0
  37. package/dist/dependencies.d.ts +87 -4
  38. package/dist/developer-setup-credential-ceiling.d.ts +10 -0
  39. package/dist/domain/agent-config-resolution.d.ts +49 -0
  40. package/dist/domain/automations.d.ts +58 -0
  41. package/dist/domain/capabilities.d.ts +22 -4
  42. package/dist/domain/company-profile-agent-admin.d.ts +25 -0
  43. package/dist/domain/connection-account-selection-error.d.ts +8 -0
  44. package/dist/domain/connector-tool-permissions.d.ts +36 -0
  45. package/dist/domain/direct-model-provider.d.ts +3 -0
  46. package/dist/domain/editable-artifacts/agent-application.d.ts +10 -1
  47. package/dist/domain/editable-artifacts/durable-export.d.ts +22 -1
  48. package/dist/domain/editable-artifacts/ports.d.ts +10 -0
  49. package/dist/domain/editable-artifacts/service.d.ts +4 -3
  50. package/dist/domain/environments.d.ts +5 -9
  51. package/dist/domain/external-creation-attribution.d.ts +6 -0
  52. package/dist/domain/file-owner.d.ts +8 -0
  53. package/dist/domain/github-action-policies.d.ts +36 -0
  54. package/dist/domain/github-repository-bindings.d.ts +117 -0
  55. package/dist/domain/github-skill-source.d.ts +5 -0
  56. package/dist/domain/governed-learning-slack-publication.d.ts +45 -0
  57. package/dist/domain/insights-timing.d.ts +16 -0
  58. package/dist/domain/insights-usage.d.ts +27 -0
  59. package/dist/domain/insights.d.ts +28 -1
  60. package/dist/domain/knowledge-files.d.ts +20 -0
  61. package/dist/domain/knowledge-messages.d.ts +39 -0
  62. package/dist/domain/knowledge-messages.test.d.ts +1 -0
  63. package/dist/domain/knowledge-preparation.d.ts +10 -0
  64. package/dist/domain/knowledge-preparation.test.d.ts +1 -0
  65. package/dist/domain/knowledge-search.d.ts +15 -0
  66. package/dist/domain/knowledge-search.test.d.ts +1 -0
  67. package/dist/domain/knowledge.d.ts +9 -0
  68. package/dist/domain/mcp-account-bindings.d.ts +19 -0
  69. package/dist/domain/mcp-account-routes.d.ts +21 -0
  70. package/dist/domain/native-mcp-connection-admission.d.ts +3 -0
  71. package/dist/domain/organization-integration-catalog.d.ts +15 -0
  72. package/dist/domain/organization-membership-lifecycle.d.ts +1 -0
  73. package/dist/domain/personal-connection-delegations.d.ts +87 -4
  74. package/dist/domain/pr-review.d.ts +249 -0
  75. package/dist/domain/resources.d.ts +24 -3
  76. package/dist/domain/scheduled-task-access.d.ts +247 -0
  77. package/dist/domain/scheduled-tasks.d.ts +103 -6
  78. package/dist/domain/session-connection-accounts.d.ts +16 -0
  79. package/dist/domain/session-file-access.d.ts +4 -0
  80. package/dist/domain/session-native-connection-replacement.d.ts +14 -0
  81. package/dist/domain/session-start-timing.d.ts +7 -0
  82. package/dist/domain/session-tool-policy.d.ts +93 -4
  83. package/dist/domain/sessions.d.ts +275 -28
  84. package/dist/domain/skill-imports.d.ts +1 -0
  85. package/dist/domain/skill-search.d.ts +30 -0
  86. package/dist/domain/skills.d.ts +117 -0
  87. package/dist/domain/slack-bot.d.ts +46 -1
  88. package/dist/domain/workspace-members.d.ts +8 -1
  89. package/dist/editable-artifact-live/application.d.ts +12 -3
  90. package/dist/editable-artifact-live/ports.d.ts +0 -1
  91. package/dist/editable-artifact-live/server.d.ts +5 -2
  92. package/dist/editable-artifact-live/ticket.d.ts +2 -2
  93. package/dist/editable-artifact-live/types.d.ts +14 -2
  94. package/dist/editable-artifact-live.js +2 -2
  95. package/dist/editable-artifacts.js +10 -4
  96. package/dist/index.d.ts +49 -3
  97. package/dist/index.js +18826 -6847
  98. package/dist/index.js.map +1 -1
  99. package/dist/managed-auth-session-sets.d.ts +131 -0
  100. package/dist/managed-auth-session-sets.js +51 -0
  101. package/dist/managed-auth-session-sets.js.map +1 -0
  102. package/dist/managed-session.d.ts +98 -11
  103. package/dist/model-catalog.d.ts +117 -0
  104. package/dist/product-usage-metrics.d.ts +30 -0
  105. package/dist/rigs/index.d.ts +22 -5
  106. package/dist/rigs/provider-images.d.ts +1 -1
  107. package/dist/sandbox/fleet.d.ts +59 -10
  108. package/dist/sandbox/routing.d.ts +22 -2
  109. package/dist/sandbox/runtime-settings.d.ts +56 -0
  110. package/dist/session-authorization.d.ts +38 -1
  111. package/dist/site-session-origin.d.ts +9 -0
  112. package/dist/transcription.d.ts +12 -1
  113. package/dist/turn-surface.d.ts +18 -0
  114. package/dist/user-presence.d.ts +32 -0
  115. package/package.json +18 -11
  116. package/src/access/external-actor-authority.ts +94 -0
  117. package/src/access/index.ts +1386 -44
  118. package/src/access/service-initiator.ts +50 -0
  119. package/src/application/api-integration-servers.ts +215 -0
  120. package/src/application/archived-session-imports.ts +161 -0
  121. package/src/application/composer-submit.ts +77 -0
  122. package/src/application/connect-authority.ts +77 -0
  123. package/src/application/connect-operation.ts +80 -0
  124. package/src/application/external-continuation.ts +129 -0
  125. package/src/application/external-identity-lifecycle.ts +48 -0
  126. package/src/application/external-link-work-admission.ts +90 -0
  127. package/src/application/external-workspace-members.ts +232 -0
  128. package/src/application/modal-native-worker-host-transport.ts +263 -0
  129. package/src/application/new-session-drafts.ts +222 -29
  130. package/src/application/sandbox-recovery.ts +78 -0
  131. package/src/application/session-commands.ts +430 -73
  132. package/src/application/session-mcp-credential-rotation.ts +217 -0
  133. package/src/application/session-tenancy.ts +445 -0
  134. package/src/application/user-resource-grants.ts +154 -0
  135. package/src/billing/limits.ts +103 -24
  136. package/src/canonical-human-identities.ts +22 -3
  137. package/src/codex-model-availability.ts +136 -0
  138. package/src/default-session-model.ts +656 -0
  139. package/src/dependencies.ts +97 -5
  140. package/src/developer-setup-credential-ceiling.ts +60 -0
  141. package/src/domain/agent-config-resolution.ts +148 -0
  142. package/src/domain/automations.ts +270 -0
  143. package/src/domain/capabilities.ts +244 -151
  144. package/src/domain/company-profile-agent-admin.ts +56 -0
  145. package/src/domain/connection-account-selection-error.ts +19 -0
  146. package/src/domain/connector-tool-permissions.ts +371 -0
  147. package/src/domain/direct-model-provider.ts +62 -0
  148. package/src/domain/editable-artifacts/agent-application.ts +61 -15
  149. package/src/domain/editable-artifacts/durable-export.ts +100 -5
  150. package/src/domain/editable-artifacts/in-memory.ts +6 -0
  151. package/src/domain/editable-artifacts/ports.ts +11 -0
  152. package/src/domain/editable-artifacts/service.ts +32 -1
  153. package/src/domain/editable-artifacts/snapshot-compaction.ts +9 -5
  154. package/src/domain/editable-artifacts/snapshot-verifier-genesis.ts +10 -8
  155. package/src/domain/editable-artifacts/snapshot-verifier.ts +10 -3
  156. package/src/domain/environments.ts +25 -45
  157. package/src/domain/external-creation-attribution.ts +22 -0
  158. package/src/domain/file-owner.ts +67 -0
  159. package/src/domain/github-action-policies.ts +169 -0
  160. package/src/domain/github-repository-bindings.ts +295 -0
  161. package/src/domain/github-skill-source.ts +233 -0
  162. package/src/domain/governed-learning-slack-publication.ts +157 -0
  163. package/src/domain/insights-timing.ts +95 -0
  164. package/src/domain/insights-usage.ts +67 -0
  165. package/src/domain/insights.ts +270 -169
  166. package/src/domain/knowledge-files.ts +46 -0
  167. package/src/domain/knowledge-messages.test.ts +91 -0
  168. package/src/domain/knowledge-messages.ts +106 -0
  169. package/src/domain/knowledge-preparation.test.ts +276 -0
  170. package/src/domain/knowledge-preparation.ts +147 -0
  171. package/src/domain/knowledge-search.test.ts +561 -0
  172. package/src/domain/knowledge-search.ts +256 -0
  173. package/src/domain/knowledge.ts +133 -0
  174. package/src/domain/mcp-account-bindings.ts +171 -0
  175. package/src/domain/mcp-account-routes.ts +121 -0
  176. package/src/domain/native-mcp-connection-admission.ts +14 -0
  177. package/src/domain/organization-integration-catalog.ts +88 -0
  178. package/src/domain/organization-membership-lifecycle.ts +10 -0
  179. package/src/domain/personal-connection-delegations.ts +758 -115
  180. package/src/domain/pr-review.ts +687 -0
  181. package/src/domain/resources.ts +182 -25
  182. package/src/domain/scheduled-task-access.ts +1052 -0
  183. package/src/domain/scheduled-tasks.ts +1952 -215
  184. package/src/domain/session-connection-accounts.ts +67 -0
  185. package/src/domain/session-file-access.ts +47 -0
  186. package/src/domain/session-native-connection-replacement.ts +64 -0
  187. package/src/domain/session-start-timing.ts +55 -0
  188. package/src/domain/session-tool-policy.ts +443 -19
  189. package/src/domain/sessions.ts +3417 -619
  190. package/src/domain/skill-imports.ts +137 -17
  191. package/src/domain/skill-search.ts +221 -0
  192. package/src/domain/skills.ts +104 -0
  193. package/src/domain/slack-bot.ts +128 -3
  194. package/src/domain/workspace-members.ts +34 -2
  195. package/src/editable-artifact-live/application.ts +29 -4
  196. package/src/editable-artifact-live/ports.ts +0 -1
  197. package/src/editable-artifact-live/server.ts +167 -13
  198. package/src/editable-artifact-live/ticket.ts +87 -6
  199. package/src/editable-artifact-live/types.ts +16 -2
  200. package/src/editable-artifact-live/wire.ts +0 -10
  201. package/src/index.ts +69 -4
  202. package/src/managed-auth-session-sets.ts +371 -0
  203. package/src/managed-session.ts +520 -2
  204. package/src/model-catalog.ts +873 -0
  205. package/src/product-usage-metrics.ts +101 -0
  206. package/src/rigs/index.ts +179 -63
  207. package/src/rigs/provider-images.ts +2 -3
  208. package/src/sandbox/fleet.ts +471 -59
  209. package/src/sandbox/routing.ts +160 -33
  210. package/src/sandbox/runtime-settings.ts +281 -0
  211. package/src/session-authorization.ts +262 -78
  212. package/src/site-session-origin.ts +22 -0
  213. package/src/transcription.ts +13 -1
  214. package/src/turn-surface.ts +45 -0
  215. package/src/user-presence.ts +134 -0
  216. package/dist/chunk-6WKPWE5S.js.map +0 -1
  217. package/dist/chunk-IBOEYG6N.js +0 -34
  218. package/dist/chunk-IBOEYG6N.js.map +0 -1
  219. package/dist/chunk-JJU6I5XD.js.map +0 -1
  220. package/dist/chunk-NYPMQ7NO.js.map +0 -1
  221. package/dist/domain/durable-learning-slack-publication.d.ts +0 -72
  222. package/dist/domain/packs.d.ts +0 -55
  223. package/src/domain/durable-learning-slack-publication.ts +0 -202
  224. package/src/domain/packs.ts +0 -556
@@ -1,12 +1,30 @@
1
1
  import { type Settings } from "@opengeni/config";
2
- import { type Database } from "@opengeni/db";
2
+ import { type Database, type SandboxRetainedProcess } from "@opengeni/db";
3
3
  import { type EventBus } from "@opengeni/events";
4
- import { type EstablishedSandboxSession, type RoutingSandboxOperationObserver, type SelfhostedRelayConfig } from "@opengeni/runtime/sandbox";
4
+ import { type EstablishedSandboxSession, type ResolvedActiveBackend, type RoutingRetainedProcess, type RoutingRetainedProcessTerminalProof, type RoutingSandboxOperationObserver, type RoutingSandboxCaptureWaitObserver, type SelfhostedRelayConfig } from "@opengeni/runtime/sandbox";
5
+ type DirectRetainedProcessRoute = {
6
+ providerSessionId: number;
7
+ providerBackend: string;
8
+ providerInstanceId: string;
9
+ leaseEpoch: number;
10
+ routeKind: "home" | "active";
11
+ routeTargetId: string | null;
12
+ routeEpoch: number;
13
+ };
14
+ /** API-direct requests always use active-route authority. The default active
15
+ * pointer is represented by a null target id; it is not a home-route write. */
16
+ export declare function directRetainedProcessMatchesBackend(durable: DirectRetainedProcessRoute, process: RoutingRetainedProcess, backend: ResolvedActiveBackend): boolean;
17
+ export declare function retainedProcessBackgroundSettlement(process: Pick<SandboxRetainedProcess, "state" | "exitCode" | "settlementReason">, fallback: RoutingRetainedProcessTerminalProof): {
18
+ outcome: "exited" | "lost";
19
+ exitCode: number | null;
20
+ reason: string;
21
+ };
5
22
  export type ChannelARoutingServices = {
6
23
  db: Database;
7
24
  settings: Settings;
8
25
  bus?: EventBus;
9
26
  onSandboxOperation?: RoutingSandboxOperationObserver;
27
+ onSandboxCaptureWait?: RoutingSandboxCaptureWaitObserver;
10
28
  waitSignal?: AbortSignal;
11
29
  };
12
30
  /** Map the deployment relay URL to the leaf's `SelfhostedRelayConfig` shape. The
@@ -37,6 +55,7 @@ export declare function wrapChannelABoxWithRouting(services: ChannelARoutingServ
37
55
  accountId: string;
38
56
  workspaceId: string;
39
57
  sessionId: string;
58
+ resourceSubjectId: string;
40
59
  homeLease?: {
41
60
  sandboxGroupId: string;
42
61
  leaseEpoch: number;
@@ -55,3 +74,4 @@ export declare function wrapChannelABoxWithRouting(services: ChannelARoutingServ
55
74
  holderId: string;
56
75
  };
57
76
  }, established: EstablishedSandboxSession): EstablishedSandboxSession;
77
+ export {};
@@ -0,0 +1,56 @@
1
+ import { type Settings } from "@opengeni/config";
2
+ import { type RigVersion, type Session, type SandboxBackend, type SandboxOs } from "@opengeni/contracts";
3
+ import { type Database } from "@opengeni/db";
4
+ import { resolveModalCheckpointProviderBinding } from "@opengeni/runtime/sandbox";
5
+ export type ManagedSessionGroupBackend = Exclude<SandboxBackend, "none" | "selfhosted">;
6
+ /**
7
+ * Resolve the provider backend behind a session's synthetic managed group.
8
+ *
9
+ * A machine-home session keeps `selfhosted` as its durable policy while a
10
+ * non-null active pointer selects the enrolled machine. Clearing that pointer
11
+ * is an explicit switch to the deployment's managed group, so API readiness,
12
+ * viewer attachment, Channel-A, and worker turns must all select the same
13
+ * provider. Deployments configured with `none` or `selfhosted` have no managed
14
+ * fallback to expose.
15
+ */
16
+ export declare function managedSessionGroupBackend(deploymentBackend: SandboxBackend, sessionBackend: SandboxBackend): ManagedSessionGroupBackend | null;
17
+ /** Display name and kind for the session's own managed box. The kind is the
18
+ * real provider. Callers must not collapse local, Docker, or other providers
19
+ * into Modal. */
20
+ export declare function sessionGroupMachinePresentation(backend: ManagedSessionGroupBackend): {
21
+ name: string;
22
+ kind: ManagedSessionGroupBackend;
23
+ };
24
+ /** A machine-home row carries the machine's host OS; its managed group uses the
25
+ * platform's canonical managed-sandbox OS instead. Ordinary sessions preserve
26
+ * their explicitly selected OS. */
27
+ export declare function managedSessionGroupOs(sessionBackend: SandboxBackend, sessionOs: SandboxOs): SandboxOs;
28
+ /**
29
+ * Apply a workspace's selected sandbox image. The deployment keeps authority:
30
+ * only an image that is on its allowlist right now is used, so removing an
31
+ * entry returns every workspace that chose it to the deployment image. The
32
+ * lease treats the image as shared state, so a change rotates a live box
33
+ * through the normal capture-and-restore path instead of reusing it.
34
+ */
35
+ export declare function settingsWithWorkspaceSandboxImage(settings: Settings, workspaceSettings: unknown, backend: SandboxBackend): Settings;
36
+ export declare function settingsWithRigImage(settings: Settings, rigImage: string | null): Settings;
37
+ export declare function rigProviderImageSourceImage(settings: Settings, backend: SandboxBackend): string | null;
38
+ export type RigProviderImageSelectionReason = "selected" | "missing" | "provider_unsupported" | "not_ready" | "not_cold_boot_validated" | "content_mismatch" | "provider_binding_unavailable" | "provider_binding_mismatch";
39
+ export declare function resolveRigProviderImageSelection(settings: Settings, version: RigVersion | null, backend: SandboxBackend, currentProviderBindingKeyHash: string | null): {
40
+ settings: Settings;
41
+ reason: RigProviderImageSelectionReason;
42
+ contentHash: string | null;
43
+ imageId: string | null;
44
+ };
45
+ export declare function resolveRigProviderImageForRun(settings: Settings, version: RigVersion | null, backend: SandboxBackend, resolveBinding?: typeof resolveModalCheckpointProviderBinding): Promise<ReturnType<typeof resolveRigProviderImageSelection>>;
46
+ export declare function settingsWithRigProviderImage(settings: Settings, version: RigVersion | null, backend: SandboxBackend, resolveBinding?: typeof resolveModalCheckpointProviderBinding): Promise<Settings>;
47
+ export type SessionSandboxRuntime = {
48
+ /** Exact logical image/rig settings used to fence the durable group lease. */
49
+ settings: Settings;
50
+ image: string | null;
51
+ rigVersion: RigVersion | null;
52
+ };
53
+ export declare function resolveSessionSandboxRuntime(db: Database, settings: Settings, session: Pick<Session, "workspaceId" | "sandboxBackend" | "rigId" | "rigVersionId">): Promise<SessionSandboxRuntime>;
54
+ /** Resolve provider-native cold-create optimization only for the single CAS
55
+ * winner. Ordinary API calls never perform provider identity I/O. */
56
+ export declare function providerSettingsForSessionSandboxRuntime(runtime: SessionSandboxRuntime, backend: SandboxBackend): Promise<Settings>;
@@ -1,7 +1,17 @@
1
- import { SessionAuthorizationActor, SessionAuthorizationListScope, type AccessGrant, type SessionAuthorizationOperation, type SessionAuthorizationSurface, type SessionAuthorizationTarget } from "@opengeni/contracts";
1
+ import { SessionAuthorizationActor, SessionAuthorizationListScope, type AccessGrant, type SessionAgentAccess, type SessionAgentAccessViewer, type SessionAuthorizationOperation, type SessionAuthorizationSurface, type SessionAuthorizationTarget, type SessionScopeSubjectId } from "@opengeni/contracts";
2
2
  import { type Database, type SessionRlsActorContext } from "@opengeni/db";
3
3
  import type { AppDependencies } from "./dependencies.js";
4
4
  export type SessionAuthorizationDependencies = Pick<AppDependencies, "db" | "sessionAuthorization">;
5
+ /** Scope read reuse to one request; it never outlives `fn`. */
6
+ export declare function withSessionAuthorizationReadReuse<T>(fn: (reuse: {
7
+ handOffToToolDispatch(): void;
8
+ }) => Promise<T>): Promise<T>;
9
+ /**
10
+ * Invoke a tool handler so that authorization checks it starts before its
11
+ * first await reuse the route's reads. Later checks, and every other dispatch
12
+ * in the same request, read fresh.
13
+ */
14
+ export declare function dispatchWithSessionAuthorizationReadReuse<T>(handler: () => T): T;
5
15
  /** Maximum time an omitted host hint leaves a live session stream unchecked. */
6
16
  export declare const SESSION_AUTHORIZATION_DEFAULT_REAUTHORIZE_MS = 15000;
7
17
  export declare class SessionAuthorizationDeniedError extends Error {
@@ -19,6 +29,33 @@ export type ResolvedSessionAuthorization = {
19
29
  relatedSessionAccess: "target" | "root";
20
30
  reauthorizeAfterMs: number | null;
21
31
  };
32
+ /** The frozen agent-access facts of one session, as the pairwise rule sees them. */
33
+ export type SessionAgentAccessFacts = {
34
+ agentAccess: SessionAgentAccess;
35
+ scopeSubjectId: SessionScopeSubjectId | null;
36
+ };
37
+ /**
38
+ * The agent-to-agent reach rule (migration 0427) for one caller/target pair
39
+ * that live in DIFFERENT root trees. A caller always keeps its own tree, so
40
+ * this is never consulted for same-root access. Only the caller's task scope
41
+ * restricts outgoing reach. The target's visibility and ownership remain
42
+ * independently enforced; its agent scope does not block incoming access.
43
+ */
44
+ export declare function agentAccessPermitsCrossTreeAccess(caller: SessionAgentAccessFacts, target: SessionAgentAccessFacts): boolean;
45
+ /**
46
+ * The in-database list scope for one calling attempt. A `session` caller is
47
+ * pinned to its own root tree when the host does not narrow it. Every caller
48
+ * carries the viewer so `sessionAuthorizationScopeFilter` intersects the host
49
+ * scope with the same pairwise rule in SQL, including for session callers.
50
+ */
51
+ export declare function agentAccessListScopeForViewer(viewer: SessionAgentAccessViewer, hostScope?: SessionAuthorizationListScope | null): SessionAuthorizationListScope;
52
+ /**
53
+ * Whether a grant acts with live agent-attempt authority: an explicit
54
+ * `agent_attempt` principal kind, or (for legacy tokens without one) any
55
+ * worker-signed exact attempt claim. Shared by the session seam and by the
56
+ * narrowing fences that let a human widen a session an agent may only narrow.
57
+ */
58
+ export declare function grantHasAgentAttemptAuthority(grant: AccessGrant): boolean;
22
59
  export declare function sessionRlsActorForAuthorization(authorization: ResolvedSessionAuthorization): SessionRlsActorContext;
23
60
  export declare function withResolvedSessionAuthorization<T>(authorization: ResolvedSessionAuthorization, fn: () => Promise<T>): Promise<T>;
24
61
  /**
@@ -0,0 +1,9 @@
1
+ export type SiteSessionOrigin = {
2
+ siteId: string;
3
+ title: string;
4
+ };
5
+ /** Request-local provenance, set only after the API validates a published Site version. */
6
+ export declare function withSiteSessionOrigin<T>(origin: SiteSessionOrigin, run: () => T): T;
7
+ export declare function sessionCreationMetadata(metadata: Record<string, unknown>): Record<string, unknown>;
8
+ /** The validated Site origin of the current request, if any. Provenance only. */
9
+ export declare function currentSiteSessionOrigin(): SiteSessionOrigin | undefined;
@@ -28,6 +28,9 @@ export type TranscriptionRequest = {
28
28
  providerDeadlineAt?: Date | undefined;
29
29
  /** Exact provider selected before a resumable segment is first sent upstream. */
30
30
  providerId?: string | undefined;
31
+ preferredProvider?: string | null | undefined;
32
+ fallbackEnabled?: boolean | undefined;
33
+ excludedProviders?: readonly string[] | undefined;
31
34
  };
32
35
  export type TranscriptionResult = TranscribeAudioResponse & {
33
36
  /** Server-private provider id for operational metrics only. Never returned to clients. */
@@ -39,23 +42,31 @@ export declare class TranscriptionServiceError extends Error {
39
42
  readonly code: VoiceInputErrorCode;
40
43
  readonly status: number;
41
44
  readonly retryable: boolean;
45
+ /** Explicit rejection before any transcription result; safe to try another provider. */
46
+ readonly fallbackSafe: boolean;
42
47
  constructor(input: {
43
48
  code: VoiceInputErrorCode;
44
49
  message: string;
45
50
  status?: number;
46
51
  retryable?: boolean;
52
+ fallbackSafe?: boolean;
47
53
  });
48
54
  }
49
55
  export declare function statusForVoiceInputError(code: VoiceInputErrorCode): number;
50
56
  /** Optional workspace scope for readiness checks during provider selection. */
51
57
  export type TranscriptionAvailabilityContext = {
58
+ afterProvider?: string | undefined;
59
+ preferredProvider?: string | null | undefined;
60
+ fallbackEnabled?: boolean | undefined;
61
+ excludedProviders?: readonly string[] | undefined;
52
62
  workspaceId?: string | undefined;
53
63
  subjectId?: string | undefined;
54
64
  };
55
65
  /**
56
66
  * Extensible transcription provider port. Implementations own credentials and
57
67
  * upstream request shape. Selection happens before audio is sent; providers must
58
- * not fall back to another vendor after an upstream request may have started.
68
+ * only fall back after an explicit rejection and before any successful or
69
+ * uncertain provider attempt. Recording persistence owns that eligibility.
59
70
  */
60
71
  export type TranscriptionProvider = {
61
72
  readonly id: string;
@@ -0,0 +1,18 @@
1
+ import type { AccessGrant, SessionTurnSurface } from "@opengeni/contracts";
2
+ import type { AccessGrantAuthorization } from "./access/index.js";
3
+ /**
4
+ * Resolve the content-free product surface a request entered through.
5
+ *
6
+ * The result is an analytics label frozen on the accepted turn. It never
7
+ * authorizes anything, so it reads trusted provenance only where it already
8
+ * exists: an explicit entry-point choice (Slack, automations, maintenance), the
9
+ * API-validated Site scope, and the access path the grant was resolved from.
10
+ * A grant whose path this function cannot place yields null rather than a
11
+ * guess.
12
+ */
13
+ export declare function resolveTurnSurface(input: {
14
+ grant: AccessGrant;
15
+ authorization?: AccessGrantAuthorization | null | undefined;
16
+ /** An entry point that knows its surface (for example Slack) passes it here. */
17
+ requested?: SessionTurnSurface | null | undefined;
18
+ }): SessionTurnSurface | null;
@@ -0,0 +1,32 @@
1
+ import { type Database } from "@opengeni/db";
2
+ import type { Observability } from "@opengeni/observability";
3
+ /**
4
+ * Throttled, batched server-side presence for managed humans.
5
+ *
6
+ * `touch` is called on the request path, so it only does an in-memory map
7
+ * check: each person is queued at most once per throttle window per process,
8
+ * and queued people are written in one batched database call after a short
9
+ * delay, never awaited by the request. API keys, services and embedded-host
10
+ * subjects are never passed here; anything outside the opaque `user:` shape is
11
+ * ignored. The database turns a new UTC day into the `user.active` lifecycle
12
+ * fact, and control workers read windowed counts for `opengeni_active_users`.
13
+ */
14
+ export type UserPresenceRecorder = {
15
+ /** Note authenticated activity for one managed human. Never throws. */
16
+ touch(subjectId: string): void;
17
+ /** Write everything queued now. Resolves even when the write fails. */
18
+ flush(): Promise<void>;
19
+ /** Flush and stop scheduling further writes. */
20
+ close(): Promise<void>;
21
+ };
22
+ export declare const USER_PRESENCE_THROTTLE_MS = 60000;
23
+ export declare const USER_PRESENCE_FLUSH_DELAY_MS = 5000;
24
+ export declare function createUserPresenceRecorder(options: {
25
+ db: Database;
26
+ observability?: Pick<Observability, "incrementCounter" | "warn"> | undefined;
27
+ throttleMs?: number;
28
+ flushDelayMs?: number;
29
+ maxTracked?: number;
30
+ now?: () => number;
31
+ record?: (db: Database, subjectIds: readonly string[]) => Promise<number>;
32
+ }): UserPresenceRecorder;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengeni/core",
3
- "version": "0.28.0",
3
+ "version": "1.0.0",
4
4
  "description": "OpenGeni framework-agnostic core: the domain, access, and billing layers (neutral access, off-HTTP V2 surface). Behavior-preserving extraction from apps/api — keeps Hono's HTTPException for error throwing (typed-errors cleanup deferred).",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -33,6 +33,10 @@
33
33
  "./canonical-human-identities": {
34
34
  "types": "./dist/canonical-human-identities.d.ts",
35
35
  "import": "./dist/canonical-human-identities.js"
36
+ },
37
+ "./managed-auth-session-sets": {
38
+ "types": "./dist/managed-auth-session-sets.d.ts",
39
+ "import": "./dist/managed-auth-session-sets.js"
36
40
  }
37
41
  },
38
42
  "publishConfig": {
@@ -46,16 +50,19 @@
46
50
  },
47
51
  "dependencies": {
48
52
  "@modelcontextprotocol/sdk": "^1.29.0",
49
- "@opengeni/codex": "^0.2.16",
50
- "@opengeni/config": "^0.16.1",
51
- "@opengeni/contracts": "^0.50.0",
52
- "@opengeni/db": "^0.36.0",
53
- "@opengeni/documents": "^0.5.38",
54
- "@opengeni/events": "^0.3.109",
55
- "@opengeni/observability": "^0.7.5",
56
- "@opengeni/runtime": "^0.23.0",
57
- "@opengeni/storage": "^0.2.93",
58
- "hono": "^4.12.18"
53
+ "@opengeni/capabilities": "1.0.0",
54
+ "@opengeni/codex": "1.0.0",
55
+ "@opengeni/config": "1.0.0",
56
+ "@opengeni/contracts": "1.0.0",
57
+ "@opengeni/db": "1.0.0",
58
+ "@opengeni/documents": "1.0.0",
59
+ "@opengeni/events": "1.0.0",
60
+ "@opengeni/network": "1.0.0",
61
+ "@opengeni/observability": "1.0.0",
62
+ "@opengeni/runtime": "1.0.0",
63
+ "@opengeni/storage": "1.0.0",
64
+ "hono": "^4.12.18",
65
+ "zod": "^4.2.1"
59
66
  },
60
67
  "engines": {
61
68
  "node": ">=18"
@@ -0,0 +1,94 @@
1
+ import type { Permission } from "@opengeni/contracts";
2
+
3
+ export type ExternalAuthoritySnapshot = Readonly<{
4
+ accountId: string;
5
+ externalIdentityId: string;
6
+ identityStatus: "active" | "disabled" | "revoked";
7
+ identityRevision: number;
8
+ membershipStatus: "active" | "provisioning" | "suspended" | "revoked";
9
+ workspaceId: string;
10
+ permissions: readonly Permission[];
11
+ }>;
12
+
13
+ export type ExternalLinkAuthoritySnapshot = Readonly<{
14
+ id: string;
15
+ accountId: string;
16
+ externalIdentityId: string;
17
+ revision: number;
18
+ nativeSubjectId: string;
19
+ status: "pending" | "active" | "revoked" | "expired";
20
+ expiresAt: number | null;
21
+ permissions: readonly Permission[];
22
+ nativeAuthority: Readonly<{
23
+ subjectId: string;
24
+ accountId: string;
25
+ workspaceId: string;
26
+ active: boolean;
27
+ permissions: readonly Permission[];
28
+ }>;
29
+ }>;
30
+
31
+ /** Pure permission calculation over already authenticated, live snapshots.
32
+ * This does not authenticate assertions or establish provenance. Callers must
33
+ * read snapshots under their authorization fence, never from request JSON.
34
+ * Linked mode uses the native lane alone: external workspace permissions must
35
+ * not be unioned into that lane, nor must old external resources change owner.
36
+ */
37
+ export function externalActorPermissions(input: {
38
+ accountId: string;
39
+ workspaceId: string;
40
+ keyActive: boolean;
41
+ keyAccountId: string;
42
+ keyPermissions: readonly Permission[];
43
+ external: ExternalAuthoritySnapshot;
44
+ linked?: {
45
+ expectedId: string;
46
+ expectedRevision: number;
47
+ authority: ExternalLinkAuthoritySnapshot;
48
+ };
49
+ now: number;
50
+ }): Permission[] {
51
+ const external = input.external;
52
+ if (
53
+ !input.keyActive ||
54
+ input.keyAccountId !== input.accountId ||
55
+ external.accountId !== input.accountId ||
56
+ external.identityStatus !== "active" ||
57
+ external.membershipStatus !== "active" ||
58
+ !Number.isSafeInteger(external.identityRevision) ||
59
+ external.identityRevision < 1 ||
60
+ !Number.isFinite(input.now)
61
+ )
62
+ return [];
63
+ let ceiling: readonly Permission[];
64
+ if (input.linked) {
65
+ const { authority: link, expectedId, expectedRevision } = input.linked;
66
+ const native = link.nativeAuthority;
67
+ if (
68
+ !expectedId ||
69
+ link.id !== expectedId ||
70
+ link.accountId !== input.accountId ||
71
+ link.externalIdentityId !== external.externalIdentityId ||
72
+ link.status !== "active" ||
73
+ !Number.isSafeInteger(expectedRevision) ||
74
+ expectedRevision < 1 ||
75
+ link.revision !== expectedRevision ||
76
+ (link.expiresAt !== null &&
77
+ (!Number.isFinite(link.expiresAt) || link.expiresAt <= input.now)) ||
78
+ !native.active ||
79
+ link.nativeSubjectId.length > 1024 ||
80
+ !/^user:[^\r\n]+$(?![\s\S])/.test(link.nativeSubjectId) ||
81
+ native.subjectId !== link.nativeSubjectId ||
82
+ native.accountId !== input.accountId ||
83
+ native.workspaceId !== input.workspaceId
84
+ )
85
+ return [];
86
+ const delegation = new Set(link.permissions);
87
+ ceiling = native.permissions.filter((permission) => delegation.has(permission));
88
+ } else {
89
+ if (external.workspaceId !== input.workspaceId) return [];
90
+ ceiling = external.permissions;
91
+ }
92
+ const allowed = new Set(ceiling);
93
+ return [...new Set(input.keyPermissions)].filter((permission) => allowed.has(permission));
94
+ }