@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.
- package/README.md +1 -1
- package/dist/access/external-actor-authority.d.ts +47 -0
- package/dist/access/index.d.ts +182 -3
- package/dist/access/service-initiator.d.ts +3 -0
- package/dist/application/api-integration-servers.d.ts +20 -0
- package/dist/application/archived-session-imports.d.ts +6 -0
- package/dist/application/composer-submit.d.ts +24 -0
- package/dist/application/connect-authority.d.ts +13 -0
- package/dist/application/connect-operation.d.ts +31 -0
- package/dist/application/external-continuation.d.ts +15 -0
- package/dist/application/external-identity-lifecycle.d.ts +20 -0
- package/dist/application/external-link-work-admission.d.ts +12 -0
- package/dist/application/external-workspace-members.d.ts +34 -0
- package/dist/application/modal-native-worker-host-transport.d.ts +297 -0
- package/dist/application/new-session-drafts.d.ts +39 -2
- package/dist/application/sandbox-recovery.d.ts +58 -0
- package/dist/application/session-commands.d.ts +26 -13
- package/dist/application/session-mcp-credential-rotation.d.ts +29 -0
- package/dist/application/session-tenancy.d.ts +19 -0
- package/dist/application/user-resource-grants.d.ts +20 -0
- package/dist/billing/limits.d.ts +11 -0
- package/dist/canonical-human-identities.d.ts +7 -2
- package/dist/canonical-human-identities.js +17 -4
- package/dist/canonical-human-identities.js.map +1 -1
- package/dist/{chunk-6WKPWE5S.js → chunk-2MKMRGSY.js} +108 -24
- package/dist/chunk-2MKMRGSY.js.map +1 -0
- package/dist/{chunk-NYPMQ7NO.js → chunk-GVO3N37G.js} +205 -37
- package/dist/chunk-GVO3N37G.js.map +1 -0
- package/dist/{chunk-JJU6I5XD.js → chunk-LCQXNR62.js} +36 -10
- package/dist/chunk-LCQXNR62.js.map +1 -0
- package/dist/chunk-MM6N7CTO.js +387 -0
- package/dist/chunk-MM6N7CTO.js.map +1 -0
- package/dist/chunk-QO5GVFFO.js +235 -0
- package/dist/chunk-QO5GVFFO.js.map +1 -0
- package/dist/codex-model-availability.d.ts +14 -0
- package/dist/default-session-model.d.ts +139 -0
- package/dist/dependencies.d.ts +87 -4
- package/dist/developer-setup-credential-ceiling.d.ts +10 -0
- package/dist/domain/agent-config-resolution.d.ts +49 -0
- package/dist/domain/automations.d.ts +58 -0
- package/dist/domain/capabilities.d.ts +22 -4
- package/dist/domain/company-profile-agent-admin.d.ts +25 -0
- package/dist/domain/connection-account-selection-error.d.ts +8 -0
- package/dist/domain/connector-tool-permissions.d.ts +36 -0
- package/dist/domain/direct-model-provider.d.ts +3 -0
- package/dist/domain/editable-artifacts/agent-application.d.ts +10 -1
- package/dist/domain/editable-artifacts/durable-export.d.ts +22 -1
- package/dist/domain/editable-artifacts/ports.d.ts +10 -0
- package/dist/domain/editable-artifacts/service.d.ts +4 -3
- package/dist/domain/environments.d.ts +5 -9
- package/dist/domain/external-creation-attribution.d.ts +6 -0
- package/dist/domain/file-owner.d.ts +8 -0
- package/dist/domain/github-action-policies.d.ts +36 -0
- package/dist/domain/github-repository-bindings.d.ts +117 -0
- package/dist/domain/github-skill-source.d.ts +5 -0
- package/dist/domain/governed-learning-slack-publication.d.ts +45 -0
- package/dist/domain/insights-timing.d.ts +16 -0
- package/dist/domain/insights-usage.d.ts +27 -0
- package/dist/domain/insights.d.ts +28 -1
- package/dist/domain/knowledge-files.d.ts +20 -0
- package/dist/domain/knowledge-messages.d.ts +39 -0
- package/dist/domain/knowledge-messages.test.d.ts +1 -0
- package/dist/domain/knowledge-preparation.d.ts +10 -0
- package/dist/domain/knowledge-preparation.test.d.ts +1 -0
- package/dist/domain/knowledge-search.d.ts +15 -0
- package/dist/domain/knowledge-search.test.d.ts +1 -0
- package/dist/domain/knowledge.d.ts +9 -0
- package/dist/domain/mcp-account-bindings.d.ts +19 -0
- package/dist/domain/mcp-account-routes.d.ts +21 -0
- package/dist/domain/native-mcp-connection-admission.d.ts +3 -0
- package/dist/domain/organization-integration-catalog.d.ts +15 -0
- package/dist/domain/organization-membership-lifecycle.d.ts +1 -0
- package/dist/domain/personal-connection-delegations.d.ts +87 -4
- package/dist/domain/pr-review.d.ts +249 -0
- package/dist/domain/resources.d.ts +24 -3
- package/dist/domain/scheduled-task-access.d.ts +247 -0
- package/dist/domain/scheduled-tasks.d.ts +103 -6
- package/dist/domain/session-connection-accounts.d.ts +16 -0
- package/dist/domain/session-file-access.d.ts +4 -0
- package/dist/domain/session-native-connection-replacement.d.ts +14 -0
- package/dist/domain/session-start-timing.d.ts +7 -0
- package/dist/domain/session-tool-policy.d.ts +93 -4
- package/dist/domain/sessions.d.ts +275 -28
- package/dist/domain/skill-imports.d.ts +1 -0
- package/dist/domain/skill-search.d.ts +30 -0
- package/dist/domain/skills.d.ts +117 -0
- package/dist/domain/slack-bot.d.ts +46 -1
- package/dist/domain/workspace-members.d.ts +8 -1
- package/dist/editable-artifact-live/application.d.ts +12 -3
- package/dist/editable-artifact-live/ports.d.ts +0 -1
- package/dist/editable-artifact-live/server.d.ts +5 -2
- package/dist/editable-artifact-live/ticket.d.ts +2 -2
- package/dist/editable-artifact-live/types.d.ts +14 -2
- package/dist/editable-artifact-live.js +2 -2
- package/dist/editable-artifacts.js +10 -4
- package/dist/index.d.ts +49 -3
- package/dist/index.js +18826 -6847
- package/dist/index.js.map +1 -1
- package/dist/managed-auth-session-sets.d.ts +131 -0
- package/dist/managed-auth-session-sets.js +51 -0
- package/dist/managed-auth-session-sets.js.map +1 -0
- package/dist/managed-session.d.ts +98 -11
- package/dist/model-catalog.d.ts +117 -0
- package/dist/product-usage-metrics.d.ts +30 -0
- package/dist/rigs/index.d.ts +22 -5
- package/dist/rigs/provider-images.d.ts +1 -1
- package/dist/sandbox/fleet.d.ts +59 -10
- package/dist/sandbox/routing.d.ts +22 -2
- package/dist/sandbox/runtime-settings.d.ts +56 -0
- package/dist/session-authorization.d.ts +38 -1
- package/dist/site-session-origin.d.ts +9 -0
- package/dist/transcription.d.ts +12 -1
- package/dist/turn-surface.d.ts +18 -0
- package/dist/user-presence.d.ts +32 -0
- package/package.json +18 -11
- package/src/access/external-actor-authority.ts +94 -0
- package/src/access/index.ts +1386 -44
- package/src/access/service-initiator.ts +50 -0
- package/src/application/api-integration-servers.ts +215 -0
- package/src/application/archived-session-imports.ts +161 -0
- package/src/application/composer-submit.ts +77 -0
- package/src/application/connect-authority.ts +77 -0
- package/src/application/connect-operation.ts +80 -0
- package/src/application/external-continuation.ts +129 -0
- package/src/application/external-identity-lifecycle.ts +48 -0
- package/src/application/external-link-work-admission.ts +90 -0
- package/src/application/external-workspace-members.ts +232 -0
- package/src/application/modal-native-worker-host-transport.ts +263 -0
- package/src/application/new-session-drafts.ts +222 -29
- package/src/application/sandbox-recovery.ts +78 -0
- package/src/application/session-commands.ts +430 -73
- package/src/application/session-mcp-credential-rotation.ts +217 -0
- package/src/application/session-tenancy.ts +445 -0
- package/src/application/user-resource-grants.ts +154 -0
- package/src/billing/limits.ts +103 -24
- package/src/canonical-human-identities.ts +22 -3
- package/src/codex-model-availability.ts +136 -0
- package/src/default-session-model.ts +656 -0
- package/src/dependencies.ts +97 -5
- package/src/developer-setup-credential-ceiling.ts +60 -0
- package/src/domain/agent-config-resolution.ts +148 -0
- package/src/domain/automations.ts +270 -0
- package/src/domain/capabilities.ts +244 -151
- package/src/domain/company-profile-agent-admin.ts +56 -0
- package/src/domain/connection-account-selection-error.ts +19 -0
- package/src/domain/connector-tool-permissions.ts +371 -0
- package/src/domain/direct-model-provider.ts +62 -0
- package/src/domain/editable-artifacts/agent-application.ts +61 -15
- package/src/domain/editable-artifacts/durable-export.ts +100 -5
- package/src/domain/editable-artifacts/in-memory.ts +6 -0
- package/src/domain/editable-artifacts/ports.ts +11 -0
- package/src/domain/editable-artifacts/service.ts +32 -1
- package/src/domain/editable-artifacts/snapshot-compaction.ts +9 -5
- package/src/domain/editable-artifacts/snapshot-verifier-genesis.ts +10 -8
- package/src/domain/editable-artifacts/snapshot-verifier.ts +10 -3
- package/src/domain/environments.ts +25 -45
- package/src/domain/external-creation-attribution.ts +22 -0
- package/src/domain/file-owner.ts +67 -0
- package/src/domain/github-action-policies.ts +169 -0
- package/src/domain/github-repository-bindings.ts +295 -0
- package/src/domain/github-skill-source.ts +233 -0
- package/src/domain/governed-learning-slack-publication.ts +157 -0
- package/src/domain/insights-timing.ts +95 -0
- package/src/domain/insights-usage.ts +67 -0
- package/src/domain/insights.ts +270 -169
- package/src/domain/knowledge-files.ts +46 -0
- package/src/domain/knowledge-messages.test.ts +91 -0
- package/src/domain/knowledge-messages.ts +106 -0
- package/src/domain/knowledge-preparation.test.ts +276 -0
- package/src/domain/knowledge-preparation.ts +147 -0
- package/src/domain/knowledge-search.test.ts +561 -0
- package/src/domain/knowledge-search.ts +256 -0
- package/src/domain/knowledge.ts +133 -0
- package/src/domain/mcp-account-bindings.ts +171 -0
- package/src/domain/mcp-account-routes.ts +121 -0
- package/src/domain/native-mcp-connection-admission.ts +14 -0
- package/src/domain/organization-integration-catalog.ts +88 -0
- package/src/domain/organization-membership-lifecycle.ts +10 -0
- package/src/domain/personal-connection-delegations.ts +758 -115
- package/src/domain/pr-review.ts +687 -0
- package/src/domain/resources.ts +182 -25
- package/src/domain/scheduled-task-access.ts +1052 -0
- package/src/domain/scheduled-tasks.ts +1952 -215
- package/src/domain/session-connection-accounts.ts +67 -0
- package/src/domain/session-file-access.ts +47 -0
- package/src/domain/session-native-connection-replacement.ts +64 -0
- package/src/domain/session-start-timing.ts +55 -0
- package/src/domain/session-tool-policy.ts +443 -19
- package/src/domain/sessions.ts +3417 -619
- package/src/domain/skill-imports.ts +137 -17
- package/src/domain/skill-search.ts +221 -0
- package/src/domain/skills.ts +104 -0
- package/src/domain/slack-bot.ts +128 -3
- package/src/domain/workspace-members.ts +34 -2
- package/src/editable-artifact-live/application.ts +29 -4
- package/src/editable-artifact-live/ports.ts +0 -1
- package/src/editable-artifact-live/server.ts +167 -13
- package/src/editable-artifact-live/ticket.ts +87 -6
- package/src/editable-artifact-live/types.ts +16 -2
- package/src/editable-artifact-live/wire.ts +0 -10
- package/src/index.ts +69 -4
- package/src/managed-auth-session-sets.ts +371 -0
- package/src/managed-session.ts +520 -2
- package/src/model-catalog.ts +873 -0
- package/src/product-usage-metrics.ts +101 -0
- package/src/rigs/index.ts +179 -63
- package/src/rigs/provider-images.ts +2 -3
- package/src/sandbox/fleet.ts +471 -59
- package/src/sandbox/routing.ts +160 -33
- package/src/sandbox/runtime-settings.ts +281 -0
- package/src/session-authorization.ts +262 -78
- package/src/site-session-origin.ts +22 -0
- package/src/transcription.ts +13 -1
- package/src/turn-surface.ts +45 -0
- package/src/user-presence.ts +134 -0
- package/dist/chunk-6WKPWE5S.js.map +0 -1
- package/dist/chunk-IBOEYG6N.js +0 -34
- package/dist/chunk-IBOEYG6N.js.map +0 -1
- package/dist/chunk-JJU6I5XD.js.map +0 -1
- package/dist/chunk-NYPMQ7NO.js.map +0 -1
- package/dist/domain/durable-learning-slack-publication.d.ts +0 -72
- package/dist/domain/packs.d.ts +0 -55
- package/src/domain/durable-learning-slack-publication.ts +0 -202
- package/src/domain/packs.ts +0 -556
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
// src/managed-auth-session-sets.ts
|
|
2
|
+
import { createHash, createHmac, randomBytes, timingSafeEqual } from "crypto";
|
|
3
|
+
import {
|
|
4
|
+
completeManagedAuthLoginTransaction,
|
|
5
|
+
getManagedAuthSessionSetOperationReceipt,
|
|
6
|
+
getManagedAuthSessionSetSnapshot
|
|
7
|
+
} from "@opengeni/db";
|
|
8
|
+
var MANAGED_AUTH_SESSION_SET_COOKIE = "opengeni.session_set";
|
|
9
|
+
var MANAGED_AUTH_LOGIN_TRANSACTION_COOKIE = "opengeni.login_transaction";
|
|
10
|
+
var MANAGED_AUTH_CSRF_HEADER = "x-opengeni-session-csrf";
|
|
11
|
+
var MANAGED_AUTH_ACTOR_EPOCH_HEADER = "x-opengeni-actor-epoch";
|
|
12
|
+
var MANAGED_AUTH_LOGIN_TRANSACTION_COOKIE_PATH = "/v1/auth/session-set/transactions";
|
|
13
|
+
var ManagedAuthActorChangeError = class extends Error {
|
|
14
|
+
name = "ManagedAuthActorChangeError";
|
|
15
|
+
code = "actor_change_required";
|
|
16
|
+
constructor() {
|
|
17
|
+
super("The selected browser actor changed");
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
var ManagedAuthRequestAdmissionError = class extends Error {
|
|
21
|
+
name = "ManagedAuthRequestAdmissionError";
|
|
22
|
+
code = "origin_rejected";
|
|
23
|
+
};
|
|
24
|
+
var ManagedAuthCompletionOutcomeUnknownError = class extends Error {
|
|
25
|
+
name = "ManagedAuthCompletionOutcomeUnknownError";
|
|
26
|
+
code = "operation_outcome_unknown";
|
|
27
|
+
constructor(options) {
|
|
28
|
+
super("The managed authentication completion outcome is unknown", options);
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
function requireManagedAuthActorFence(input) {
|
|
32
|
+
if (input.expectedActorEpoch !== null && input.expectedActorEpoch !== input.actorEpoch || input.expectedActorEpoch === null && (input.mode === "broker" || input.actorEpoch !== "1" || input.selectedAuthSessionId !== null && input.legacyAmbientSessionId !== input.selectedAuthSessionId)) {
|
|
33
|
+
throw new ManagedAuthActorChangeError();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function managedAuthRandomAuthority() {
|
|
37
|
+
return randomBytes(32).toString("base64url");
|
|
38
|
+
}
|
|
39
|
+
function managedAuthSha256(value) {
|
|
40
|
+
return createHash("sha256").update(value, "utf8").digest("hex");
|
|
41
|
+
}
|
|
42
|
+
function managedAuthCsrfHash(authority) {
|
|
43
|
+
return managedAuthSha256(`opengeni:managed-auth:csrf-authority:v1
|
|
44
|
+
${authority}`);
|
|
45
|
+
}
|
|
46
|
+
function managedAuthCsrfToken(signingSecret, authority, generation) {
|
|
47
|
+
return createHmac("sha256", signingSecret).update(`opengeni:managed-auth:csrf:v1
|
|
48
|
+
${authority}
|
|
49
|
+
${generation}`, "utf8").digest("base64url");
|
|
50
|
+
}
|
|
51
|
+
function managedAuthTransactionSecret(signingSecret, authority, operationId) {
|
|
52
|
+
return createHmac("sha256", signingSecret).update(`opengeni:managed-auth:transaction:v1
|
|
53
|
+
${authority}
|
|
54
|
+
${operationId}`, "utf8").digest("base64url");
|
|
55
|
+
}
|
|
56
|
+
function managedAuthDerivedUuid(namespace, value) {
|
|
57
|
+
const bytes = createHash("sha256").update(`${namespace}
|
|
58
|
+
${value}`, "utf8").digest().subarray(0, 16);
|
|
59
|
+
bytes[6] = bytes[6] & 15 | 80;
|
|
60
|
+
bytes[8] = bytes[8] & 63 | 128;
|
|
61
|
+
const hex = bytes.toString("hex");
|
|
62
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
63
|
+
}
|
|
64
|
+
function canonicalJson(value) {
|
|
65
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
66
|
+
if (Array.isArray(value)) return `[${value.map(canonicalJson).join(",")}]`;
|
|
67
|
+
return `{${Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, child]) => `${JSON.stringify(key)}:${canonicalJson(child)}`).join(",")}}`;
|
|
68
|
+
}
|
|
69
|
+
function managedAuthRequestDigest(value) {
|
|
70
|
+
return managedAuthSha256(canonicalJson(value));
|
|
71
|
+
}
|
|
72
|
+
function managedAuthSecretRequestDigest(signingSecret, value) {
|
|
73
|
+
return createHmac("sha256", signingSecret).update(`opengeni:managed-auth:request:v1
|
|
74
|
+
${canonicalJson(value)}`, "utf8").digest("hex");
|
|
75
|
+
}
|
|
76
|
+
function withManagedAuthCsrfToken(projection, signingSecret, authority) {
|
|
77
|
+
return {
|
|
78
|
+
...projection,
|
|
79
|
+
csrfToken: managedAuthCsrfToken(signingSecret, authority, projection.generation)
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
function equalSecret(left, right) {
|
|
83
|
+
const leftBytes = Buffer.from(left, "utf8");
|
|
84
|
+
const rightBytes = Buffer.from(right, "utf8");
|
|
85
|
+
return leftBytes.length === rightBytes.length && timingSafeEqual(leftBytes, rightBytes);
|
|
86
|
+
}
|
|
87
|
+
function requireManagedAuthMutationAdmission(input) {
|
|
88
|
+
const origin = input.request.headers.get("origin");
|
|
89
|
+
const fetchSite = input.request.headers.get("sec-fetch-site");
|
|
90
|
+
const contentType = input.request.headers.get("content-type")?.split(";", 1)[0]?.trim();
|
|
91
|
+
const csrf = input.request.headers.get(MANAGED_AUTH_CSRF_HEADER);
|
|
92
|
+
const allowed = new Set(input.allowedOrigins.map((candidate) => new URL(candidate).origin));
|
|
93
|
+
const expectedCsrf = managedAuthCsrfToken(
|
|
94
|
+
input.signingSecret,
|
|
95
|
+
input.authority,
|
|
96
|
+
input.expectedGeneration
|
|
97
|
+
);
|
|
98
|
+
if (!origin || !allowed.has(origin) || fetchSite !== "same-origin" || contentType !== "application/json" || !csrf || !equalSecret(csrf, expectedCsrf)) {
|
|
99
|
+
throw new ManagedAuthRequestAdmissionError("Browser session-set mutation admission failed");
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
async function resolveManagedAuthSelectedSession(input) {
|
|
103
|
+
const snapshot = await getManagedAuthSessionSetSnapshot(input.db, {
|
|
104
|
+
authorityHash: managedAuthSha256(input.authority),
|
|
105
|
+
mode: input.mode,
|
|
106
|
+
includeInternal: true,
|
|
107
|
+
allowRecovery: input.allowRecovery ?? false,
|
|
108
|
+
readOnly: true
|
|
109
|
+
});
|
|
110
|
+
if (!snapshot) return null;
|
|
111
|
+
if (snapshot.projection.state === "actor_change_required") {
|
|
112
|
+
throw new ManagedAuthActorChangeError();
|
|
113
|
+
}
|
|
114
|
+
requireManagedAuthActorFence({
|
|
115
|
+
mode: input.mode,
|
|
116
|
+
actorEpoch: snapshot.projection.actorEpoch,
|
|
117
|
+
expectedActorEpoch: input.expectedActorEpoch,
|
|
118
|
+
selectedAuthSessionId: snapshot.selected?.authSessionId ?? null,
|
|
119
|
+
legacyAmbientSessionId: input.legacyAmbientSessionId ?? null
|
|
120
|
+
});
|
|
121
|
+
if (!snapshot.selected) return { session: null, projection: snapshot.projection };
|
|
122
|
+
const resolved = await input.adapter.resolveSelectedSession(snapshot.selected);
|
|
123
|
+
if (!resolved || resolved.session.id !== snapshot.selected.authSessionId || resolved.user.id !== snapshot.selected.authUserId) {
|
|
124
|
+
return { session: null, projection: snapshot.projection };
|
|
125
|
+
}
|
|
126
|
+
return { session: resolved, projection: snapshot.projection };
|
|
127
|
+
}
|
|
128
|
+
async function authenticateAndAdoptManagedAuthSession(input) {
|
|
129
|
+
try {
|
|
130
|
+
const existing = await getManagedAuthSessionSetOperationReceipt(input.db, {
|
|
131
|
+
authorityHash: managedAuthSha256(input.authority),
|
|
132
|
+
operationId: input.operationId,
|
|
133
|
+
requestDigest: input.requestDigest
|
|
134
|
+
});
|
|
135
|
+
if (existing) return existing;
|
|
136
|
+
} catch (error) {
|
|
137
|
+
throw new ManagedAuthCompletionOutcomeUnknownError({ cause: error });
|
|
138
|
+
}
|
|
139
|
+
const created = await input.adapter.authenticate({
|
|
140
|
+
provider: "email_password",
|
|
141
|
+
transactionId: input.transactionId,
|
|
142
|
+
credentials: { email: input.email, password: input.password },
|
|
143
|
+
headers: input.isolatedHeaders
|
|
144
|
+
});
|
|
145
|
+
return await adoptManagedAuthSession({
|
|
146
|
+
...input,
|
|
147
|
+
authorityHash: managedAuthSha256(input.authority),
|
|
148
|
+
transactionSecretHash: managedAuthSha256(input.transactionSecret),
|
|
149
|
+
authSessionId: created.authSessionId
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
async function adoptManagedAuthSession(input) {
|
|
153
|
+
let completed;
|
|
154
|
+
try {
|
|
155
|
+
completed = await completeManagedAuthLoginTransaction(input.db, {
|
|
156
|
+
authorityHash: input.authorityHash,
|
|
157
|
+
csrfHash: input.csrfHash,
|
|
158
|
+
operationId: input.operationId,
|
|
159
|
+
requestDigest: input.requestDigest,
|
|
160
|
+
expectedGeneration: input.expectedGeneration,
|
|
161
|
+
expectedActorEpoch: input.expectedActorEpoch,
|
|
162
|
+
transactionId: input.transactionId,
|
|
163
|
+
transactionSecretHash: input.transactionSecretHash,
|
|
164
|
+
authSessionId: input.authSessionId,
|
|
165
|
+
mode: input.mode
|
|
166
|
+
});
|
|
167
|
+
} catch (error) {
|
|
168
|
+
let receipt;
|
|
169
|
+
try {
|
|
170
|
+
receipt = await getManagedAuthSessionSetOperationReceipt(input.db, {
|
|
171
|
+
authorityHash: input.authorityHash,
|
|
172
|
+
operationId: input.operationId,
|
|
173
|
+
requestDigest: input.requestDigest
|
|
174
|
+
});
|
|
175
|
+
} catch (receiptError) {
|
|
176
|
+
throw new ManagedAuthCompletionOutcomeUnknownError({ cause: receiptError });
|
|
177
|
+
}
|
|
178
|
+
if (receipt) {
|
|
179
|
+
await reconcileCreatedManagedAuthSession(input, input.authSessionId);
|
|
180
|
+
return receipt;
|
|
181
|
+
}
|
|
182
|
+
await input.adapter.revokeSession({ authSessionId: input.authSessionId }).catch(() => void 0);
|
|
183
|
+
throw error;
|
|
184
|
+
}
|
|
185
|
+
try {
|
|
186
|
+
await reconcileCreatedManagedAuthSession(input, input.authSessionId);
|
|
187
|
+
} catch (error) {
|
|
188
|
+
throw new ManagedAuthCompletionOutcomeUnknownError({ cause: error });
|
|
189
|
+
}
|
|
190
|
+
return completed;
|
|
191
|
+
}
|
|
192
|
+
async function reconcileCreatedManagedAuthSession(input, authSessionId) {
|
|
193
|
+
const snapshot = await getManagedAuthSessionSetSnapshot(input.db, {
|
|
194
|
+
authorityHash: managedAuthSha256(input.authority),
|
|
195
|
+
mode: input.mode,
|
|
196
|
+
includeInternal: true,
|
|
197
|
+
readOnly: true
|
|
198
|
+
});
|
|
199
|
+
if (snapshot?.internalSlots.some((slot) => slot.authSessionId === authSessionId)) return;
|
|
200
|
+
await input.adapter.revokeSession({ authSessionId });
|
|
201
|
+
}
|
|
202
|
+
function isolatedManagedAuthHeaders(request) {
|
|
203
|
+
const headers = new Headers(request.headers);
|
|
204
|
+
headers.delete("cookie");
|
|
205
|
+
headers.delete("authorization");
|
|
206
|
+
headers.delete("x-forwarded-user");
|
|
207
|
+
return headers;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export {
|
|
211
|
+
MANAGED_AUTH_SESSION_SET_COOKIE,
|
|
212
|
+
MANAGED_AUTH_LOGIN_TRANSACTION_COOKIE,
|
|
213
|
+
MANAGED_AUTH_CSRF_HEADER,
|
|
214
|
+
MANAGED_AUTH_ACTOR_EPOCH_HEADER,
|
|
215
|
+
MANAGED_AUTH_LOGIN_TRANSACTION_COOKIE_PATH,
|
|
216
|
+
ManagedAuthActorChangeError,
|
|
217
|
+
ManagedAuthRequestAdmissionError,
|
|
218
|
+
ManagedAuthCompletionOutcomeUnknownError,
|
|
219
|
+
requireManagedAuthActorFence,
|
|
220
|
+
managedAuthRandomAuthority,
|
|
221
|
+
managedAuthSha256,
|
|
222
|
+
managedAuthCsrfHash,
|
|
223
|
+
managedAuthCsrfToken,
|
|
224
|
+
managedAuthTransactionSecret,
|
|
225
|
+
managedAuthDerivedUuid,
|
|
226
|
+
managedAuthRequestDigest,
|
|
227
|
+
managedAuthSecretRequestDigest,
|
|
228
|
+
withManagedAuthCsrfToken,
|
|
229
|
+
requireManagedAuthMutationAdmission,
|
|
230
|
+
resolveManagedAuthSelectedSession,
|
|
231
|
+
authenticateAndAdoptManagedAuthSession,
|
|
232
|
+
adoptManagedAuthSession,
|
|
233
|
+
isolatedManagedAuthHeaders
|
|
234
|
+
};
|
|
235
|
+
//# sourceMappingURL=chunk-QO5GVFFO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/managed-auth-session-sets.ts"],"sourcesContent":["import { createHash, createHmac, randomBytes, timingSafeEqual } from \"node:crypto\";\nimport type {\n ManagedAuthSessionSetMode,\n ManagedAuthSessionSetProjection,\n} from \"@opengeni/contracts/managed-auth-session-sets\";\nimport {\n completeManagedAuthLoginTransaction,\n getManagedAuthSessionSetOperationReceipt,\n getManagedAuthSessionSetSnapshot,\n type Database,\n type ManagedAuthDatabaseProjection,\n type ManagedAuthSelectedSession,\n} from \"@opengeni/db\";\n\nexport const MANAGED_AUTH_SESSION_SET_COOKIE = \"opengeni.session_set\" as const;\nexport const MANAGED_AUTH_LOGIN_TRANSACTION_COOKIE = \"opengeni.login_transaction\" as const;\nexport const MANAGED_AUTH_CSRF_HEADER = \"x-opengeni-session-csrf\" as const;\nexport const MANAGED_AUTH_ACTOR_EPOCH_HEADER = \"x-opengeni-actor-epoch\" as const;\nexport const MANAGED_AUTH_LOGIN_TRANSACTION_COOKIE_PATH =\n \"/v1/auth/session-set/transactions\" as const;\n\nexport type ManagedAuthResolvedSession = {\n session: { id: string; userId: string; [key: string]: unknown };\n user: {\n id: string;\n email: string;\n name: string;\n emailVerified: boolean;\n [key: string]: unknown;\n };\n};\n\n/** Provider-neutral boundary; provider credentials and tokens never cross its output. */\nexport interface ManagedAuthSessionAdapter {\n authenticate(input: {\n provider: \"email_password\";\n transactionId: string;\n credentials: { email: string; password: string };\n headers: Headers;\n }): Promise<{ authSessionId: string }>;\n /** Verify an ambient provider cookie without sliding expiry or emitting cookies. */\n resolveAmbientSession(headers: Headers): Promise<ManagedAuthResolvedSession | null>;\n resolveSelectedSession(\n input: ManagedAuthSelectedSession,\n ): Promise<ManagedAuthResolvedSession | null>;\n refreshSelectedSession(\n input: ManagedAuthSelectedSession,\n ): Promise<ManagedAuthResolvedSession | null>;\n revokeSession(input: { authSessionId: string }): Promise<void>;\n /** Dual-mode exact selected-session cookie plus stale provider-cache invalidations. */\n createLegacySelectedSessionCookies(\n input: ManagedAuthSelectedSession | null,\n currentCookieHeader?: string | null,\n ): Promise<string[]>;\n}\n\nexport class ManagedAuthActorChangeError extends Error {\n readonly name = \"ManagedAuthActorChangeError\";\n readonly code = \"actor_change_required\";\n constructor() {\n super(\"The selected browser actor changed\");\n }\n}\n\nexport class ManagedAuthRequestAdmissionError extends Error {\n readonly name = \"ManagedAuthRequestAdmissionError\";\n readonly code = \"origin_rejected\";\n}\n\nexport class ManagedAuthCompletionOutcomeUnknownError extends Error {\n readonly name = \"ManagedAuthCompletionOutcomeUnknownError\";\n readonly code = \"operation_outcome_unknown\";\n constructor(options?: ErrorOptions) {\n super(\"The managed authentication completion outcome is unknown\", options);\n }\n}\n\nexport function requireManagedAuthActorFence(input: {\n mode: ManagedAuthSessionSetMode;\n actorEpoch: string;\n expectedActorEpoch: string | null;\n selectedAuthSessionId: string | null;\n legacyAmbientSessionId?: string | null;\n}): void {\n if (\n (input.expectedActorEpoch !== null && input.expectedActorEpoch !== input.actorEpoch) ||\n (input.expectedActorEpoch === null &&\n (input.mode === \"broker\" ||\n input.actorEpoch !== \"1\" ||\n (input.selectedAuthSessionId !== null &&\n input.legacyAmbientSessionId !== input.selectedAuthSessionId)))\n ) {\n throw new ManagedAuthActorChangeError();\n }\n}\n\nexport function managedAuthRandomAuthority(): string {\n return randomBytes(32).toString(\"base64url\");\n}\n\nexport function managedAuthSha256(value: string): string {\n return createHash(\"sha256\").update(value, \"utf8\").digest(\"hex\");\n}\n\nexport function managedAuthCsrfHash(authority: string): string {\n return managedAuthSha256(`opengeni:managed-auth:csrf-authority:v1\\n${authority}`);\n}\n\nexport function managedAuthCsrfToken(\n signingSecret: string,\n authority: string,\n generation: string,\n): string {\n return createHmac(\"sha256\", signingSecret)\n .update(`opengeni:managed-auth:csrf:v1\\n${authority}\\n${generation}`, \"utf8\")\n .digest(\"base64url\");\n}\n\nexport function managedAuthTransactionSecret(\n signingSecret: string,\n authority: string,\n operationId: string,\n): string {\n return createHmac(\"sha256\", signingSecret)\n .update(`opengeni:managed-auth:transaction:v1\\n${authority}\\n${operationId}`, \"utf8\")\n .digest(\"base64url\");\n}\n\nexport function managedAuthDerivedUuid(namespace: string, value: string): string {\n const bytes = createHash(\"sha256\")\n .update(`${namespace}\\n${value}`, \"utf8\")\n .digest()\n .subarray(0, 16);\n bytes[6] = (bytes[6]! & 0x0f) | 0x50;\n bytes[8] = (bytes[8]! & 0x3f) | 0x80;\n const hex = bytes.toString(\"hex\");\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n}\n\nfunction canonicalJson(value: unknown): string {\n if (value === null || typeof value !== \"object\") return JSON.stringify(value);\n if (Array.isArray(value)) return `[${value.map(canonicalJson).join(\",\")}]`;\n return `{${Object.entries(value as Record<string, unknown>)\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([key, child]) => `${JSON.stringify(key)}:${canonicalJson(child)}`)\n .join(\",\")}}`;\n}\n\nexport function managedAuthRequestDigest(value: unknown): string {\n return managedAuthSha256(canonicalJson(value));\n}\n\nexport function managedAuthSecretRequestDigest(signingSecret: string, value: unknown): string {\n return createHmac(\"sha256\", signingSecret)\n .update(`opengeni:managed-auth:request:v1\\n${canonicalJson(value)}`, \"utf8\")\n .digest(\"hex\");\n}\n\nexport function withManagedAuthCsrfToken(\n projection: ManagedAuthDatabaseProjection,\n signingSecret: string,\n authority: string,\n): ManagedAuthSessionSetProjection {\n return {\n ...projection,\n csrfToken: managedAuthCsrfToken(signingSecret, authority, projection.generation),\n };\n}\n\nfunction equalSecret(left: string, right: string): boolean {\n const leftBytes = Buffer.from(left, \"utf8\");\n const rightBytes = Buffer.from(right, \"utf8\");\n return leftBytes.length === rightBytes.length && timingSafeEqual(leftBytes, rightBytes);\n}\n\nexport function requireManagedAuthMutationAdmission(input: {\n request: Request;\n allowedOrigins: readonly string[];\n authority: string;\n signingSecret: string;\n expectedGeneration: string;\n}): void {\n const origin = input.request.headers.get(\"origin\");\n const fetchSite = input.request.headers.get(\"sec-fetch-site\");\n const contentType = input.request.headers.get(\"content-type\")?.split(\";\", 1)[0]?.trim();\n const csrf = input.request.headers.get(MANAGED_AUTH_CSRF_HEADER);\n const allowed = new Set(input.allowedOrigins.map((candidate) => new URL(candidate).origin));\n const expectedCsrf = managedAuthCsrfToken(\n input.signingSecret,\n input.authority,\n input.expectedGeneration,\n );\n if (\n !origin ||\n !allowed.has(origin) ||\n fetchSite !== \"same-origin\" ||\n contentType !== \"application/json\" ||\n !csrf ||\n !equalSecret(csrf, expectedCsrf)\n ) {\n throw new ManagedAuthRequestAdmissionError(\"Browser session-set mutation admission failed\");\n }\n}\n\nexport async function resolveManagedAuthSelectedSession(input: {\n db: Database;\n adapter: ManagedAuthSessionAdapter;\n authority: string;\n mode: ManagedAuthSessionSetMode;\n expectedActorEpoch: string | null;\n legacyAmbientSessionId?: string | null;\n allowRecovery?: boolean;\n}): Promise<{\n session: ManagedAuthResolvedSession | null;\n projection: ManagedAuthDatabaseProjection;\n} | null> {\n const snapshot = await getManagedAuthSessionSetSnapshot(input.db, {\n authorityHash: managedAuthSha256(input.authority),\n mode: input.mode,\n includeInternal: true,\n allowRecovery: input.allowRecovery ?? false,\n readOnly: true,\n });\n if (!snapshot) return null;\n if (snapshot.projection.state === \"actor_change_required\") {\n throw new ManagedAuthActorChangeError();\n }\n requireManagedAuthActorFence({\n mode: input.mode,\n actorEpoch: snapshot.projection.actorEpoch,\n expectedActorEpoch: input.expectedActorEpoch,\n selectedAuthSessionId: snapshot.selected?.authSessionId ?? null,\n legacyAmbientSessionId: input.legacyAmbientSessionId ?? null,\n });\n if (!snapshot.selected) return { session: null, projection: snapshot.projection };\n const resolved = await input.adapter.resolveSelectedSession(snapshot.selected);\n if (\n !resolved ||\n resolved.session.id !== snapshot.selected.authSessionId ||\n resolved.user.id !== snapshot.selected.authUserId\n ) {\n return { session: null, projection: snapshot.projection };\n }\n return { session: resolved, projection: snapshot.projection };\n}\n\nexport async function authenticateAndAdoptManagedAuthSession(input: {\n db: Database;\n adapter: ManagedAuthSessionAdapter;\n isolatedHeaders: Headers;\n authority: string;\n csrfHash: string;\n operationId: string;\n requestDigest: string;\n expectedGeneration: string;\n expectedActorEpoch: string;\n transactionId: string;\n transactionSecret: string;\n email: string;\n password: string;\n mode: ManagedAuthSessionSetMode;\n}): Promise<{ projection: ManagedAuthDatabaseProjection; returnIntent: string | null }> {\n try {\n const existing = await getManagedAuthSessionSetOperationReceipt(input.db, {\n authorityHash: managedAuthSha256(input.authority),\n operationId: input.operationId,\n requestDigest: input.requestDigest,\n });\n if (existing) return existing;\n } catch (error) {\n // Provider authentication creates a durable session. Do not perform it\n // while exact-replay reconciliation is unavailable.\n throw new ManagedAuthCompletionOutcomeUnknownError({ cause: error });\n }\n const created = await input.adapter.authenticate({\n provider: \"email_password\",\n transactionId: input.transactionId,\n credentials: { email: input.email, password: input.password },\n headers: input.isolatedHeaders,\n });\n return await adoptManagedAuthSession({\n ...input,\n authorityHash: managedAuthSha256(input.authority),\n transactionSecretHash: managedAuthSha256(input.transactionSecret),\n authSessionId: created.authSessionId,\n });\n}\n\nexport async function adoptManagedAuthSession(input: {\n db: Database;\n adapter: ManagedAuthSessionAdapter;\n authority: string;\n authorityHash: string;\n csrfHash: string;\n operationId: string;\n requestDigest: string;\n expectedGeneration: string;\n expectedActorEpoch: string;\n transactionId: string;\n transactionSecretHash: string;\n authSessionId: string;\n mode: ManagedAuthSessionSetMode;\n}): Promise<{ projection: ManagedAuthDatabaseProjection; returnIntent: string | null }> {\n let completed: { projection: ManagedAuthDatabaseProjection; returnIntent: string | null };\n try {\n completed = await completeManagedAuthLoginTransaction(input.db, {\n authorityHash: input.authorityHash,\n csrfHash: input.csrfHash,\n operationId: input.operationId,\n requestDigest: input.requestDigest,\n expectedGeneration: input.expectedGeneration,\n expectedActorEpoch: input.expectedActorEpoch,\n transactionId: input.transactionId,\n transactionSecretHash: input.transactionSecretHash,\n authSessionId: input.authSessionId,\n mode: input.mode,\n });\n } catch (error) {\n let receipt: Awaited<ReturnType<typeof getManagedAuthSessionSetOperationReceipt>>;\n try {\n receipt = await getManagedAuthSessionSetOperationReceipt(input.db, {\n authorityHash: input.authorityHash,\n operationId: input.operationId,\n requestDigest: input.requestDigest,\n });\n } catch (receiptError) {\n throw new ManagedAuthCompletionOutcomeUnknownError({ cause: receiptError });\n }\n if (receipt) {\n await reconcileCreatedManagedAuthSession(input, input.authSessionId);\n return receipt;\n }\n await input.adapter\n .revokeSession({ authSessionId: input.authSessionId })\n .catch(() => undefined);\n throw error;\n }\n try {\n await reconcileCreatedManagedAuthSession(input, input.authSessionId);\n } catch (error) {\n throw new ManagedAuthCompletionOutcomeUnknownError({ cause: error });\n }\n return completed;\n}\n\nasync function reconcileCreatedManagedAuthSession(\n input: {\n db: Database;\n adapter: ManagedAuthSessionAdapter;\n authority: string;\n mode: ManagedAuthSessionSetMode;\n },\n authSessionId: string,\n): Promise<void> {\n const snapshot = await getManagedAuthSessionSetSnapshot(input.db, {\n authorityHash: managedAuthSha256(input.authority),\n mode: input.mode,\n includeInternal: true,\n readOnly: true,\n });\n if (snapshot?.internalSlots.some((slot) => slot.authSessionId === authSessionId)) return;\n await input.adapter.revokeSession({ authSessionId });\n}\n\nexport function isolatedManagedAuthHeaders(request: Request): Headers {\n const headers = new Headers(request.headers);\n headers.delete(\"cookie\");\n headers.delete(\"authorization\");\n headers.delete(\"x-forwarded-user\");\n return headers;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { fetchCodexModels } from "@opengeni/codex";
|
|
2
|
+
import { type Settings } from "@opengeni/config";
|
|
3
|
+
import { buildCodexTokenResolver, getCodexRotationSettings, listCodexAccountStatuses, loadCodexCredentialForRun, type Database } from "@opengeni/db";
|
|
4
|
+
import type { ModelAvailabilityObservation } from "./model-catalog.js";
|
|
5
|
+
type Dependencies = {
|
|
6
|
+
listAccounts: typeof listCodexAccountStatuses;
|
|
7
|
+
getRotation: typeof getCodexRotationSettings;
|
|
8
|
+
loadCredential: typeof loadCodexCredentialForRun;
|
|
9
|
+
fetchModels: typeof fetchCodexModels;
|
|
10
|
+
getToken: (db: Database, settings: Settings, workspaceId: string, credentialId: string) => ReturnType<ReturnType<typeof buildCodexTokenResolver>["getToken"]>;
|
|
11
|
+
};
|
|
12
|
+
/** Live provider support is separate from deployment membership and model permissions. */
|
|
13
|
+
export declare function loadWorkspaceCodexModelAvailability(db: Database, settings: Settings, workspaceId: string, deps?: Dependencies): Promise<Record<string, ModelAvailabilityObservation>>;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { type ConfiguredModel, type Settings } from "@opengeni/config";
|
|
2
|
+
import { type DefaultModelSelection, type ReasoningEffort, type ScheduledTask, type WorkspaceSessionDefaults, type XaiProviderAccountAuthoritySnapshotV1, type ClaudeProviderAccountAuthoritySnapshotV1 } from "@opengeni/contracts";
|
|
3
|
+
import { type Database } from "@opengeni/db";
|
|
4
|
+
import { type WorkspaceModelSelection, type WorkspaceModelSelectionInput } from "./model-catalog.js";
|
|
5
|
+
/** The model's own default effort, matching the web picker's choice. */
|
|
6
|
+
export declare function defaultReasoningEffortForConfiguredModel(model: ConfiguredModel, fallback: ReasoningEffort): ReasoningEffort;
|
|
7
|
+
/** The highest supported effort at or below `preferred`. */
|
|
8
|
+
export declare function clampReasoningEffortForConfiguredModel(model: ConfiguredModel, preferred: ReasoningEffort, fallback: ReasoningEffort): ReasoningEffort;
|
|
9
|
+
export type DefaultSessionModelInput = {
|
|
10
|
+
/** Catalog-resolved settings: `openaiModel` is the deployment default. */
|
|
11
|
+
settings: Settings;
|
|
12
|
+
/** This workspace's selection, in operator catalog order. */
|
|
13
|
+
selections: readonly WorkspaceModelSelection[];
|
|
14
|
+
workspaceDefaults: WorkspaceSessionDefaults | null;
|
|
15
|
+
/**
|
|
16
|
+
* True while the organization holds a positive OpenGeni credit balance from
|
|
17
|
+
* any source, the verified-signup trial grant included (see
|
|
18
|
+
* `organizationHoldsCredits`).
|
|
19
|
+
*/
|
|
20
|
+
creditsAvailable: boolean;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Default model policy for a new chat or scheduled task that names no model.
|
|
24
|
+
*
|
|
25
|
+
* Precedence, first match wins:
|
|
26
|
+
*
|
|
27
|
+
* 1. `workspace`: the saved workspace default (`settings.sessionDefaults`)
|
|
28
|
+
* while it is selectable in this workspace, its saved effort clamped to
|
|
29
|
+
* what the model supports today.
|
|
30
|
+
* 2. `subscription`: the first selectable connected-subscription model
|
|
31
|
+
* (ChatGPT/Codex, then SuperGrok) in operator catalog order. The
|
|
32
|
+
* deployment default wins inside this step when it is itself a selectable
|
|
33
|
+
* subscription model.
|
|
34
|
+
* 3. `credits`: while the organization holds a positive OpenGeni credit
|
|
35
|
+
* balance (a purchase, a grant, or the verified-signup trial grant), the
|
|
36
|
+
* configured credits default (`OPENGENI_CREDITS_DEFAULT_MODEL`, effort
|
|
37
|
+
* clamped to what the model supports), or the first selectable
|
|
38
|
+
* credits-billed model when that one is not selectable. When the
|
|
39
|
+
* deployment default is already a selectable credits-billed model it is
|
|
40
|
+
* never replaced: it keeps the deployment effort, except that it takes the
|
|
41
|
+
* credits default effort when it is the credits default model itself.
|
|
42
|
+
* 4. `deployment`: the deployment default with the deployment reasoning effort
|
|
43
|
+
* when stably admissible; otherwise the first stably admissible catalog
|
|
44
|
+
* model with its own default effort. With no admitted models, retain the
|
|
45
|
+
* deployment hint and let fresh creation refuse it.
|
|
46
|
+
*
|
|
47
|
+
* An explicit model on the request, the scheduled task, or the person's
|
|
48
|
+
* new-chat draft is never passed through this function.
|
|
49
|
+
*/
|
|
50
|
+
export declare function selectDefaultSessionModel(input: DefaultSessionModelInput): DefaultModelSelection;
|
|
51
|
+
/**
|
|
52
|
+
* The default this workspace would use while its organization holds a
|
|
53
|
+
* positive OpenGeni credit balance. Null when the deployment does not bill
|
|
54
|
+
* credits.
|
|
55
|
+
*/
|
|
56
|
+
export declare function creditsDefaultSessionModel(input: {
|
|
57
|
+
settings: Settings;
|
|
58
|
+
selections: readonly WorkspaceModelSelection[];
|
|
59
|
+
workspaceSettings: unknown;
|
|
60
|
+
}): DefaultModelSelection | null;
|
|
61
|
+
/**
|
|
62
|
+
* Resolve the default for an already-loaded workspace selection. The credit
|
|
63
|
+
* ledger is read only when it can change the answer.
|
|
64
|
+
*/
|
|
65
|
+
export declare function resolveDefaultSessionModelForSelections(db: Database, input: {
|
|
66
|
+
settings: Settings;
|
|
67
|
+
accountId: string;
|
|
68
|
+
workspaceSettings: unknown;
|
|
69
|
+
selections: readonly WorkspaceModelSelection[];
|
|
70
|
+
}): Promise<DefaultModelSelection>;
|
|
71
|
+
export type WorkspaceModelSelectionContext = {
|
|
72
|
+
accountId: string;
|
|
73
|
+
workspaceId: string;
|
|
74
|
+
/**
|
|
75
|
+
* The subject whose connected-subscription authority applies: the
|
|
76
|
+
* authenticated caller for direct creates, or a scheduled task's immutable
|
|
77
|
+
* execution owner. Never another member.
|
|
78
|
+
*/
|
|
79
|
+
subjectId: string;
|
|
80
|
+
/**
|
|
81
|
+
* An already-frozen SuperGrok authority (a scheduled task's snapshot).
|
|
82
|
+
* Omitted means the subject's current acceptance authority, exactly as a
|
|
83
|
+
* direct Send resolves it.
|
|
84
|
+
*/
|
|
85
|
+
xaiAuthoritySnapshot?: XaiProviderAccountAuthoritySnapshotV1 | undefined;
|
|
86
|
+
/** Already accepted Claude pool; never replace it with current selection. */
|
|
87
|
+
claudeAuthoritySnapshot?: ClaudeProviderAccountAuthoritySnapshotV1 | undefined;
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Readiness for the subject's current or already accepted Claude pool observes
|
|
91
|
+
* metadata only; quota is handled by the runtime allocator. This is not an
|
|
92
|
+
* authorization: callers must supply their authenticated or frozen subject.
|
|
93
|
+
*/
|
|
94
|
+
export declare function loadWorkspaceClaudeSubscriptionReadiness(db: Database, settings: Settings, context: WorkspaceModelSelectionContext): Promise<{
|
|
95
|
+
workspace: boolean;
|
|
96
|
+
organization: boolean;
|
|
97
|
+
}>;
|
|
98
|
+
/** Load the same inputs the workspace model catalog route evaluates. */
|
|
99
|
+
export declare function loadWorkspaceModelSelectionInput(db: Database, settings: Settings, context: WorkspaceModelSelectionContext, options?: {
|
|
100
|
+
observeAvailability?: boolean;
|
|
101
|
+
}): Promise<WorkspaceModelSelectionInput>;
|
|
102
|
+
/**
|
|
103
|
+
* Caller-scoped stable fresh admission; never re-admit already accepted work.
|
|
104
|
+
* Live discovery is opt-in: its token refresh can mutate connection readiness,
|
|
105
|
+
* so a health hint must not change the billing rail of an explicit create.
|
|
106
|
+
*/
|
|
107
|
+
export declare function resolveCallerWorkspaceModelSelections(db: Database, settings: Settings, context: WorkspaceModelSelectionContext, options?: {
|
|
108
|
+
observeAvailability?: boolean;
|
|
109
|
+
}): Promise<WorkspaceModelSelection[]>;
|
|
110
|
+
/** Transient selectability for existing consumers; not fresh-create admission. */
|
|
111
|
+
export declare function selectableWorkspaceModel(selections: readonly WorkspaceModelSelection[], modelId: string): WorkspaceModelSelection | undefined;
|
|
112
|
+
/** Same stable decision used by client config and direct fresh session creation. */
|
|
113
|
+
export declare function admissibleWorkspaceModel(selections: readonly WorkspaceModelSelection[], modelId: string): WorkspaceModelSelection | undefined;
|
|
114
|
+
/**
|
|
115
|
+
* Server-side default for new work that names no model: API and Slack session
|
|
116
|
+
* creates, new-chat drafts that follow the default, and scheduled-task
|
|
117
|
+
* occurrences. The result is resolved once and then frozen by the accepted
|
|
118
|
+
* session or occurrence like any other model choice.
|
|
119
|
+
*/
|
|
120
|
+
export declare function resolveDefaultSessionModel(db: Database, settings: Settings, context: WorkspaceModelSelectionContext & {
|
|
121
|
+
workspaceSettings?: unknown;
|
|
122
|
+
}): Promise<DefaultModelSelection>;
|
|
123
|
+
/**
|
|
124
|
+
* The default a scheduled occurrence uses when its task names no model and the
|
|
125
|
+
* occurrence creates its own session: resolved under the task's immutable
|
|
126
|
+
* execution owner (or its creator for a workspace/service task) and the task's
|
|
127
|
+
* frozen SuperGrok authority, never another member's. The worker stamps the
|
|
128
|
+
* result onto the accepted execution, so retries and recovery replay it; the
|
|
129
|
+
* API's manual-trigger limit check uses the same resolution so it gates the
|
|
130
|
+
* model that will run.
|
|
131
|
+
*/
|
|
132
|
+
export declare function resolveScheduledTaskDefaultModel(db: Database, settings: Settings, task: Pick<ScheduledTask, "id" | "accountId" | "workspaceId" | "ownerSubjectId" | "createdBy">): Promise<DefaultModelSelection>;
|
|
133
|
+
/**
|
|
134
|
+
* The model a manual trigger's limit pre-check evaluates, matching what the
|
|
135
|
+
* occurrence will run: the task's explicit model, else the target or reusable
|
|
136
|
+
* session's model when that session exists, else the resolved scheduled
|
|
137
|
+
* default. The worker still resolves authoritatively at dispatch.
|
|
138
|
+
*/
|
|
139
|
+
export declare function resolveScheduledTaskPreflightModel(db: Database, settings: Settings, task: Pick<ScheduledTask, "id" | "accountId" | "workspaceId" | "ownerSubjectId" | "createdBy" | "agentConfig" | "runMode" | "targetSessionId" | "reusableSessionId">): Promise<string>;
|
package/dist/dependencies.d.ts
CHANGED
|
@@ -1,16 +1,24 @@
|
|
|
1
1
|
import type { Settings } from "@opengeni/config";
|
|
2
2
|
import type { ConnectionCredentialsPort, Document, DocumentAuthorityKind, GitHubAppApiPort, ScheduledTask, ScheduledTaskTriggerType, SessionAuthorizationPort, TurnInitiator } from "@opengeni/contracts";
|
|
3
|
-
import type { Database } from "@opengeni/db";
|
|
3
|
+
import type { Database, SessionWorkflowWakeDeliveryResult } from "@opengeni/db";
|
|
4
4
|
import type { DocumentServices } from "@opengeni/documents";
|
|
5
5
|
import type { EventBus } from "@opengeni/events";
|
|
6
6
|
import type { Observability } from "@opengeni/observability";
|
|
7
|
+
import type { UserPresenceRecorder } from "./user-presence.js";
|
|
7
8
|
import type { createObjectStorage } from "@opengeni/storage";
|
|
8
9
|
import type { ManagedAuth } from "./managed-auth-type.js";
|
|
10
|
+
import type { ManagedAuthSessionAdapter } from "./managed-auth-session-sets.js";
|
|
9
11
|
import type { ApiSandboxClient, ResumeBoxByIdInput, ResumedSandboxSession } from "./sandbox-types.js";
|
|
10
12
|
import type { TranscriptionSegmenter, TranscriptionService } from "./transcription.js";
|
|
11
13
|
import type { EditableArtifactApplicationPort } from "./editable-artifact-live.js";
|
|
14
|
+
import type { ResolvedCatalogSettings } from "./model-catalog.js";
|
|
12
15
|
import type { EditableArtifactAgentApplication, EditableArtifactDurableExportService, EditableArtifactOfficeImportPort } from "./editable-artifacts.js";
|
|
13
16
|
export type SessionWorkflowClient = {
|
|
17
|
+
triggerAutomationRun?: (input: {
|
|
18
|
+
accountId: string;
|
|
19
|
+
workspaceId: string;
|
|
20
|
+
runId: string;
|
|
21
|
+
}) => Promise<void>;
|
|
14
22
|
signalUserMessage: (input: {
|
|
15
23
|
sessionId: string;
|
|
16
24
|
eventId: string;
|
|
@@ -23,7 +31,9 @@ export type SessionWorkflowClient = {
|
|
|
23
31
|
workflowId: string;
|
|
24
32
|
wakeRevision: number;
|
|
25
33
|
interruptionRequested?: boolean;
|
|
26
|
-
|
|
34
|
+
/** Called after transport acceptance, before the fallible durable ACK. */
|
|
35
|
+
onSignalAccepted?: () => void;
|
|
36
|
+
}) => Promise<SessionWorkflowWakeDeliveryResult | void>;
|
|
27
37
|
/** Trigger one bounded drain of already-committed workflow-wake revisions. */
|
|
28
38
|
requestSessionWorkflowWakeDispatch: () => Promise<void>;
|
|
29
39
|
signalCodexCapacity?: (input: {
|
|
@@ -44,6 +54,12 @@ export type SessionWorkflowClient = {
|
|
|
44
54
|
}) => Promise<void>;
|
|
45
55
|
syncScheduledTask: (input: {
|
|
46
56
|
task: ScheduledTask;
|
|
57
|
+
/**
|
|
58
|
+
* Compensate under the same per-schedule writer lock. Return the error to
|
|
59
|
+
* throw only after this transaction commits; lock/commit failures bypass
|
|
60
|
+
* that receipt. A failing compensation must roll back its own savepoint.
|
|
61
|
+
*/
|
|
62
|
+
onFailure?: (tx: Database, error: unknown) => Promise<Error>;
|
|
47
63
|
}) => Promise<void>;
|
|
48
64
|
deleteScheduledTaskSchedule: (input: {
|
|
49
65
|
temporalScheduleId: string;
|
|
@@ -53,6 +69,8 @@ export type SessionWorkflowClient = {
|
|
|
53
69
|
agentRunUsageIdempotencyKey: string;
|
|
54
70
|
triggerWorkflowId: string;
|
|
55
71
|
initiator: TurnInitiator;
|
|
72
|
+
/** Server-frozen caller ceiling for this run, independent of task ownership. */
|
|
73
|
+
credentialRestriction?: "developer_setup";
|
|
56
74
|
triggerType?: Extract<ScheduledTaskTriggerType, "manual" | "initial" | "provider_event" | "retry" | "repair">;
|
|
57
75
|
}) => Promise<void>;
|
|
58
76
|
startRigVerification: (input: {
|
|
@@ -73,8 +91,48 @@ export type DocumentIndexClient = {
|
|
|
73
91
|
authoritySubjectId: string | null;
|
|
74
92
|
}) => Promise<Document | void>;
|
|
75
93
|
};
|
|
94
|
+
export type ManagedEmailMessage = {
|
|
95
|
+
kind: "email_verification" | "password_reset" | "organization_user_setup" | "sign_in_method_changed";
|
|
96
|
+
from: string;
|
|
97
|
+
to: string;
|
|
98
|
+
subject: string;
|
|
99
|
+
text: string;
|
|
100
|
+
html: string;
|
|
101
|
+
idempotencyKey?: string;
|
|
102
|
+
};
|
|
103
|
+
export type ManagedEmailDeliveryResult = {
|
|
104
|
+
status: "sent";
|
|
105
|
+
providerMessageId: string | null;
|
|
106
|
+
} | {
|
|
107
|
+
status: "failed";
|
|
108
|
+
errorClass: string;
|
|
109
|
+
} | {
|
|
110
|
+
status: "outcome_unknown";
|
|
111
|
+
errorClass: string;
|
|
112
|
+
};
|
|
113
|
+
/** Provider-neutral, injectable boundary for every managed-auth email. */
|
|
114
|
+
export type ManagedEmailTransport = {
|
|
115
|
+
/** Effective provider sender; frozen into any idempotent payload digest. */
|
|
116
|
+
readonly sender: string;
|
|
117
|
+
/**
|
|
118
|
+
* Stable non-secret provider/account/policy namespace plus the provider's
|
|
119
|
+
* guaranteed key-retention window. Both are durably fenced before I/O.
|
|
120
|
+
*/
|
|
121
|
+
readonly idempotency: {
|
|
122
|
+
readonly scope: string;
|
|
123
|
+
readonly retentionSeconds: number;
|
|
124
|
+
};
|
|
125
|
+
send(message: ManagedEmailMessage): Promise<ManagedEmailDeliveryResult>;
|
|
126
|
+
};
|
|
76
127
|
export type AppDependencies = {
|
|
77
128
|
settings: Settings;
|
|
129
|
+
/**
|
|
130
|
+
* Original deployment settings when `settings` is already overlaid with a
|
|
131
|
+
* deployment/workspace catalog snapshot. Model-bearing request adapters set
|
|
132
|
+
* this marker so core admission never feeds a synthetic reviewed provider
|
|
133
|
+
* back through deployment validation.
|
|
134
|
+
*/
|
|
135
|
+
catalogSourceSettings?: Settings;
|
|
78
136
|
db: Database;
|
|
79
137
|
/**
|
|
80
138
|
* Host-composed editable artifact engine. Standalone startup binds the same
|
|
@@ -90,13 +148,22 @@ export type AppDependencies = {
|
|
|
90
148
|
editableArtifactOfficeImports?: EditableArtifactOfficeImportPort;
|
|
91
149
|
bus: EventBus;
|
|
92
150
|
workflowClient: SessionWorkflowClient;
|
|
93
|
-
/**
|
|
151
|
+
/**
|
|
152
|
+
* Injectable structural seam for replayable post-commit fanout and wake work.
|
|
153
|
+
* The historical name is retained for host compatibility; every interactive
|
|
154
|
+
* session command now uses this boundary, not only prompt submission.
|
|
155
|
+
*/
|
|
94
156
|
schedulePromptPostCommit?: (task: () => Promise<void>) => void;
|
|
95
157
|
/** Optional provider override for deterministic API/object-storage tests. */
|
|
96
158
|
objectStorage?: ObjectStorageDependency;
|
|
97
159
|
documentIndexer?: DocumentIndexClient;
|
|
98
160
|
documentServices?: DocumentServices;
|
|
99
161
|
observability?: Observability;
|
|
162
|
+
/**
|
|
163
|
+
* Throttled server-side presence for canonical managed browser sessions
|
|
164
|
+
* (`createUserPresenceRecorder`). Analytics only; never an authorization input.
|
|
165
|
+
*/
|
|
166
|
+
userPresence?: UserPresenceRecorder | null;
|
|
100
167
|
readinessChecks?: Partial<Record<"db" | "nats" | "temporal", () => Promise<void> | void>>;
|
|
101
168
|
githubStateSecret?: string;
|
|
102
169
|
/**
|
|
@@ -105,6 +172,8 @@ export type AppDependencies = {
|
|
|
105
172
|
* App credentials; standalone deployments fall back to @opengeni/github.
|
|
106
173
|
*/
|
|
107
174
|
githubAppApi?: GitHubAppApiPort;
|
|
175
|
+
/** Optional provider seam for the separately registered OpenGeni Lens App. */
|
|
176
|
+
prReviewGithubAppApi?: GitHubAppApiPort;
|
|
108
177
|
/**
|
|
109
178
|
* Optional host-owned connection credential seam. API-side consumers use
|
|
110
179
|
* the MCP leg for Codemode/Code Mode; worker consumers bind the same port
|
|
@@ -118,8 +187,18 @@ export type AppDependencies = {
|
|
|
118
187
|
*/
|
|
119
188
|
sessionAuthorization?: SessionAuthorizationPort | null;
|
|
120
189
|
managedAuth?: ManagedAuth | null;
|
|
190
|
+
/** Provider-neutral browser login-slot adapter; required by dual/broker managed auth. */
|
|
191
|
+
managedAuthSessionAdapter?: ManagedAuthSessionAdapter | null;
|
|
192
|
+
/** Injectable managed-email transport; standalone API defaults to Resend or local capture. */
|
|
193
|
+
managedEmailTransport?: ManagedEmailTransport;
|
|
121
194
|
/** Injectable Codex HTTP transport for deterministic API/provider tests. */
|
|
122
195
|
codexFetch?: typeof fetch;
|
|
196
|
+
/** Injectable transport for customer OpenAI/Azure connection checks. */
|
|
197
|
+
directModelFetch?: typeof fetch;
|
|
198
|
+
/** Injectable GitHub transport for deterministic personal-OAuth tests. */
|
|
199
|
+
githubPersonalFetch?: typeof fetch;
|
|
200
|
+
/** Injectable credential-free GitHub transport for public repository verification tests. */
|
|
201
|
+
githubAnonymousFetch?: typeof fetch;
|
|
123
202
|
/** Injectable xAI OAuth/subscription transport for deterministic API/provider tests. */
|
|
124
203
|
xaiFetch?: typeof fetch;
|
|
125
204
|
/** Injectable Slack Web API transport for deterministic bot-connection tests. */
|
|
@@ -130,6 +209,8 @@ export type AppDependencies = {
|
|
|
130
209
|
fikenFetch?: typeof fetch;
|
|
131
210
|
/** Injectable Integration Definition OAuth/API transport for deterministic tests. */
|
|
132
211
|
apiIntegrationOAuthFetch?: typeof fetch;
|
|
212
|
+
/** Injectable specification/introspection transport, still network-policy checked. */
|
|
213
|
+
apiIntegrationSourceFetch?: typeof fetch;
|
|
133
214
|
atlassianFetch?: typeof fetch;
|
|
134
215
|
/** Injectable MCP OAuth setup deadline for deterministic stalled-provider tests. */
|
|
135
216
|
oauthStartDeadlineMs?: number;
|
|
@@ -151,6 +232,8 @@ export type AppDependencies = {
|
|
|
151
232
|
};
|
|
152
233
|
export type ObjectStorageDependency = ReturnType<typeof createObjectStorage>;
|
|
153
234
|
export type ApiRouteDeps = AppDependencies & {
|
|
235
|
+
resolveCatalogSettings: () => Promise<ResolvedCatalogSettings>;
|
|
236
|
+
managedEmailTransport: ManagedEmailTransport;
|
|
154
237
|
objectStorage: ObjectStorageDependency;
|
|
155
238
|
githubStateSecret: string;
|
|
156
239
|
documentIndexer: DocumentIndexClient;
|
|
@@ -164,7 +247,7 @@ export type ApiRouteDeps = AppDependencies & {
|
|
|
164
247
|
* the canonical admission path without constructing unrelated HTTP, document,
|
|
165
248
|
* or sandbox services. The public API still passes its `ApiRouteDeps` superset.
|
|
166
249
|
*/
|
|
167
|
-
export type AcceptSessionUserMessageDependencies = Pick<AppDependencies, "settings" | "db" | "bus" | "sessionAuthorization" | "schedulePromptPostCommit"> & {
|
|
250
|
+
export type AcceptSessionUserMessageDependencies = Pick<AppDependencies, "settings" | "catalogSourceSettings" | "db" | "bus" | "sessionAuthorization" | "schedulePromptPostCommit" | "observability"> & {
|
|
168
251
|
workflowClient: Pick<SessionWorkflowClient, "wakeSessionWorkflow">;
|
|
169
252
|
objectStorage: ObjectStorageDependency;
|
|
170
253
|
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type AccessGrant, type Permission, type TurnExecutionPolicyV1 } from "@opengeni/contracts";
|
|
2
|
+
import { type AccessGrantAuthorization } from "./access/index.js";
|
|
3
|
+
/** The policy must be server-frozen, never supplied as request metadata. */
|
|
4
|
+
export declare function requireDeveloperSetupDelegatedPermissions(policy: TurnExecutionPolicyV1, permissions: readonly Permission[] | undefined): void;
|
|
5
|
+
/** Only pass server-owned persisted session/turn metadata, never request JSON. */
|
|
6
|
+
export declare function withDeveloperSetupCredentialRestriction(policy: TurnExecutionPolicyV1, source: {
|
|
7
|
+
grant?: AccessGrant;
|
|
8
|
+
authorization?: AccessGrantAuthorization | undefined;
|
|
9
|
+
trustedMetadata?: readonly unknown[];
|
|
10
|
+
}): TurnExecutionPolicyV1;
|