@opengeni/core 2.5.3 → 2.6.4-canary.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/access/index.d.ts +24 -0
- package/dist/billing/limits.d.ts +5 -0
- package/dist/canonical-human-identities.js +2 -2
- package/dist/{chunk-ZVZJTMSV.js → chunk-OF65T3PM.js} +2 -2
- package/dist/{chunk-YGOMUGYS.js → chunk-QO5GVFFO.js} +17 -8
- package/dist/{chunk-YGOMUGYS.js.map → chunk-QO5GVFFO.js.map} +1 -1
- package/dist/dependencies.d.ts +10 -1
- package/dist/domain/company-brain-governed-writes.d.ts +15 -6
- package/dist/domain/company-profile-agent-admin.d.ts +3 -2
- package/dist/domain/environments.d.ts +1 -1
- package/dist/domain/memory-slack-delivery.d.ts +4 -1
- package/dist/domain/personal-connection-delegations.d.ts +1 -0
- package/dist/domain/pr-review.d.ts +1 -1
- package/dist/domain/scheduled-tasks.d.ts +12 -0
- package/dist/domain/sessions.d.ts +37 -11
- package/dist/domain/workspace-members.d.ts +8 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1706 -667
- package/dist/index.js.map +1 -1
- package/dist/managed-auth-session-sets.d.ts +18 -0
- package/dist/managed-auth-session-sets.js +3 -1
- package/dist/model-catalog.d.ts +89 -0
- package/dist/sandbox/fleet.d.ts +6 -4
- package/dist/sandbox/routing.d.ts +7 -2
- package/dist/sandbox/runtime-settings.d.ts +17 -1
- package/package.json +10 -10
- package/src/access/index.ts +140 -5
- package/src/application/user-resource-grants.ts +31 -2
- package/src/billing/limits.ts +57 -24
- package/src/dependencies.ts +15 -1
- package/src/domain/company-brain-governed-writes.ts +29 -13
- package/src/domain/company-profile-agent-admin.ts +3 -2
- package/src/domain/environments.ts +6 -34
- package/src/domain/memory-slack-delivery.ts +30 -0
- package/src/domain/personal-connection-delegations.ts +40 -7
- package/src/domain/remember.ts +5 -6
- package/src/domain/scheduled-tasks.ts +146 -1
- package/src/domain/sessions.ts +912 -358
- package/src/domain/workspace-members.ts +34 -2
- package/src/index.ts +1 -0
- package/src/managed-auth-session-sets.ts +38 -11
- package/src/model-catalog.ts +565 -0
- package/src/sandbox/fleet.ts +20 -17
- package/src/sandbox/routing.ts +18 -4
- package/src/sandbox/runtime-settings.ts +32 -0
- /package/dist/{chunk-ZVZJTMSV.js.map → chunk-OF65T3PM.js.map} +0 -0
package/dist/access/index.d.ts
CHANGED
|
@@ -4,6 +4,16 @@ import { type Database } from "@opengeni/db";
|
|
|
4
4
|
import type { Context } from "hono";
|
|
5
5
|
import type { ManagedAuth } from "../managed-auth-type.js";
|
|
6
6
|
import type { ManagedAuthSessionAdapter } from "../managed-auth-session-sets.js";
|
|
7
|
+
export type AccountScopedApiKeyWorkspaceAuthority = Readonly<{
|
|
8
|
+
accountId: string;
|
|
9
|
+
permissions: Permission[];
|
|
10
|
+
}>;
|
|
11
|
+
/**
|
|
12
|
+
* Return account-scoped API-key workspace authority only for the exact
|
|
13
|
+
* AccessContext object stamped by successful API-key authentication. Subject
|
|
14
|
+
* shape alone is deliberately insufficient.
|
|
15
|
+
*/
|
|
16
|
+
export declare function accountScopedApiKeyWorkspaceAuthority(context: AccessContext): AccountScopedApiKeyWorkspaceAuthority | null;
|
|
7
17
|
/**
|
|
8
18
|
* Opaque, request-local proof that the canonical access resolver authorized the
|
|
9
19
|
* exact account administrator named by the stamp. The random id is audit and
|
|
@@ -44,6 +54,8 @@ export type AccessGrantAuthorization = {
|
|
|
44
54
|
* principal, and for any future path that does not verify a cookie.
|
|
45
55
|
*/
|
|
46
56
|
canonicalManagedHumanSession: boolean;
|
|
57
|
+
/** Exact in-process single-user local bootstrap, never a delegated bearer. */
|
|
58
|
+
canonicalLocalHumanSession: boolean;
|
|
47
59
|
};
|
|
48
60
|
export declare function accessGrantAuthorizationFromContext(context: AccessContext, grant: AccessGrant): AccessGrantAuthorization;
|
|
49
61
|
/**
|
|
@@ -56,6 +68,18 @@ export declare function accessGrantAuthorizationFromContext(context: AccessConte
|
|
|
56
68
|
* access resolver are present in `resolvedAccessGrantAuthorizations`.
|
|
57
69
|
*/
|
|
58
70
|
export declare function requireAccountAdminAuthorizationStamp(authorization: AccessGrantAuthorization): AccountAdminAuthorizationStamp;
|
|
71
|
+
/**
|
|
72
|
+
* Resolve the exact built-in single-user local administrator for an account.
|
|
73
|
+
*
|
|
74
|
+
* This is intentionally narrower than checking `context.mode === "local"` or
|
|
75
|
+
* the `dev` subject name. Only the in-process local bootstrap branch can place
|
|
76
|
+
* the resolved context in `canonicalLocalHumanContexts`, so delegated bearer
|
|
77
|
+
* tokens and caller-constructed contexts cannot borrow this authority.
|
|
78
|
+
*/
|
|
79
|
+
export declare function requireCanonicalLocalAccountAdministrator(c: Context, deps: AccessDeps, accountId: string): Promise<{
|
|
80
|
+
subjectId: string;
|
|
81
|
+
authorization: AccessGrantAuthorization;
|
|
82
|
+
}>;
|
|
59
83
|
export declare function requireAccessGrantAuthorization(c: Context, deps: AccessDeps, workspaceId: string, permission?: Permission): Promise<AccessGrantAuthorization>;
|
|
60
84
|
export declare function requirePermission(grant: AccessGrant, permission: Permission): void;
|
|
61
85
|
/**
|
package/dist/billing/limits.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type Settings } from "@opengeni/config";
|
|
1
2
|
import type { LimitAction, LimitDecision, SessionTurnSource, TurnInitiator, TurnInitiatorContext } from "@opengeni/contracts";
|
|
2
3
|
import type { ApiRouteDeps } from "../dependencies.js";
|
|
3
4
|
export type LimitDependencies = Pick<ApiRouteDeps, "db" | "settings">;
|
|
@@ -8,6 +9,10 @@ export type LimitCheckInput = {
|
|
|
8
9
|
quantity?: number;
|
|
9
10
|
model?: string | null;
|
|
10
11
|
};
|
|
12
|
+
export declare function modelFundingForAdmission(settings: Settings, model: string | null | undefined, codexBilled: boolean): {
|
|
13
|
+
fundedWithoutCredits: boolean;
|
|
14
|
+
countsTowardTokenCap: boolean;
|
|
15
|
+
};
|
|
11
16
|
export declare function requireLimit(deps: LimitDependencies, input: LimitCheckInput): Promise<void>;
|
|
12
17
|
export declare function checkLimit(deps: LimitDependencies, input: LimitCheckInput): Promise<LimitDecision>;
|
|
13
18
|
export declare function recordWorkspaceUsage(deps: LimitDependencies, input: {
|
|
@@ -3,8 +3,8 @@ import {
|
|
|
3
3
|
getManagedAuthRequestActorLeaseStamp,
|
|
4
4
|
getManagedSession,
|
|
5
5
|
markManagedAuthRequestActorTransitionApplied
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-OF65T3PM.js";
|
|
7
|
+
import "./chunk-QO5GVFFO.js";
|
|
8
8
|
|
|
9
9
|
// src/canonical-human-identities.ts
|
|
10
10
|
import { HTTPException } from "hono/http-exception";
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
ManagedAuthActorChangeError,
|
|
5
5
|
managedAuthSha256,
|
|
6
6
|
resolveManagedAuthSelectedSession
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-QO5GVFFO.js";
|
|
8
8
|
|
|
9
9
|
// src/managed-session.ts
|
|
10
10
|
import {
|
|
@@ -366,4 +366,4 @@ export {
|
|
|
366
366
|
getManagedAuthRequestActorAdmissionStamp,
|
|
367
367
|
getManagedAuthRequestActorLeaseStamp
|
|
368
368
|
};
|
|
369
|
-
//# sourceMappingURL=chunk-
|
|
369
|
+
//# sourceMappingURL=chunk-OF65T3PM.js.map
|
|
@@ -142,25 +142,33 @@ async function authenticateAndAdoptManagedAuthSession(input) {
|
|
|
142
142
|
credentials: { email: input.email, password: input.password },
|
|
143
143
|
headers: input.isolatedHeaders
|
|
144
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) {
|
|
145
153
|
let completed;
|
|
146
154
|
try {
|
|
147
155
|
completed = await completeManagedAuthLoginTransaction(input.db, {
|
|
148
|
-
authorityHash:
|
|
156
|
+
authorityHash: input.authorityHash,
|
|
149
157
|
csrfHash: input.csrfHash,
|
|
150
158
|
operationId: input.operationId,
|
|
151
159
|
requestDigest: input.requestDigest,
|
|
152
160
|
expectedGeneration: input.expectedGeneration,
|
|
153
161
|
expectedActorEpoch: input.expectedActorEpoch,
|
|
154
162
|
transactionId: input.transactionId,
|
|
155
|
-
transactionSecretHash:
|
|
156
|
-
authSessionId:
|
|
163
|
+
transactionSecretHash: input.transactionSecretHash,
|
|
164
|
+
authSessionId: input.authSessionId,
|
|
157
165
|
mode: input.mode
|
|
158
166
|
});
|
|
159
167
|
} catch (error) {
|
|
160
168
|
let receipt;
|
|
161
169
|
try {
|
|
162
170
|
receipt = await getManagedAuthSessionSetOperationReceipt(input.db, {
|
|
163
|
-
authorityHash:
|
|
171
|
+
authorityHash: input.authorityHash,
|
|
164
172
|
operationId: input.operationId,
|
|
165
173
|
requestDigest: input.requestDigest
|
|
166
174
|
});
|
|
@@ -168,14 +176,14 @@ async function authenticateAndAdoptManagedAuthSession(input) {
|
|
|
168
176
|
throw new ManagedAuthCompletionOutcomeUnknownError({ cause: receiptError });
|
|
169
177
|
}
|
|
170
178
|
if (receipt) {
|
|
171
|
-
await reconcileCreatedManagedAuthSession(input,
|
|
179
|
+
await reconcileCreatedManagedAuthSession(input, input.authSessionId);
|
|
172
180
|
return receipt;
|
|
173
181
|
}
|
|
174
|
-
await input.adapter.revokeSession(
|
|
182
|
+
await input.adapter.revokeSession({ authSessionId: input.authSessionId }).catch(() => void 0);
|
|
175
183
|
throw error;
|
|
176
184
|
}
|
|
177
185
|
try {
|
|
178
|
-
await reconcileCreatedManagedAuthSession(input,
|
|
186
|
+
await reconcileCreatedManagedAuthSession(input, input.authSessionId);
|
|
179
187
|
} catch (error) {
|
|
180
188
|
throw new ManagedAuthCompletionOutcomeUnknownError({ cause: error });
|
|
181
189
|
}
|
|
@@ -221,6 +229,7 @@ export {
|
|
|
221
229
|
requireManagedAuthMutationAdmission,
|
|
222
230
|
resolveManagedAuthSelectedSession,
|
|
223
231
|
authenticateAndAdoptManagedAuthSession,
|
|
232
|
+
adoptManagedAuthSession,
|
|
224
233
|
isolatedManagedAuthHeaders
|
|
225
234
|
};
|
|
226
|
-
//# sourceMappingURL=chunk-
|
|
235
|
+
//# sourceMappingURL=chunk-QO5GVFFO.js.map
|
|
@@ -1 +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 let completed: { projection: ManagedAuthDatabaseProjection; returnIntent: string | null };\n try {\n completed = await completeManagedAuthLoginTransaction(input.db, {\n authorityHash: managedAuthSha256(input.authority),\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: managedAuthSha256(input.transactionSecret),\n authSessionId: created.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: managedAuthSha256(input.authority),\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, created.authSessionId);\n return receipt;\n }\n await input.adapter.revokeSession(created).catch(() => undefined);\n throw error;\n }\n try {\n await reconcileCreatedManagedAuthSession(input, created.authSessionId);\n } catch (error) {\n throw new ManagedAuthCompletionOutcomeUnknownError({ cause: error });\n }\n return completed;\n}\n\nasync function reconcileCreatedManagedAuthSession(\n input: Pick<\n Parameters<typeof authenticateAndAdoptManagedAuthSession>[0],\n \"db\" | \"adapter\" | \"authority\" | \"mode\"\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":[]}
|
|
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":[]}
|
package/dist/dependencies.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ import type { ManagedAuthSessionAdapter } from "./managed-auth-session-sets.js";
|
|
|
10
10
|
import type { ApiSandboxClient, ResumeBoxByIdInput, ResumedSandboxSession } from "./sandbox-types.js";
|
|
11
11
|
import type { TranscriptionSegmenter, TranscriptionService } from "./transcription.js";
|
|
12
12
|
import type { EditableArtifactApplicationPort } from "./editable-artifact-live.js";
|
|
13
|
+
import type { ResolvedCatalogSettings } from "./model-catalog.js";
|
|
13
14
|
import type { EditableArtifactAgentApplication, EditableArtifactDurableExportService, EditableArtifactOfficeImportPort } from "./editable-artifacts.js";
|
|
14
15
|
export type SessionWorkflowClient = {
|
|
15
16
|
triggerAutomationRun?: (input: {
|
|
@@ -114,6 +115,13 @@ export type ManagedEmailTransport = {
|
|
|
114
115
|
};
|
|
115
116
|
export type AppDependencies = {
|
|
116
117
|
settings: Settings;
|
|
118
|
+
/**
|
|
119
|
+
* Original deployment settings when `settings` is already overlaid with a
|
|
120
|
+
* deployment/workspace catalog snapshot. Model-bearing request adapters set
|
|
121
|
+
* this marker so core admission never feeds a synthetic reviewed provider
|
|
122
|
+
* back through deployment validation.
|
|
123
|
+
*/
|
|
124
|
+
catalogSourceSettings?: Settings;
|
|
117
125
|
db: Database;
|
|
118
126
|
/**
|
|
119
127
|
* Host-composed editable artifact engine. Standalone startup binds the same
|
|
@@ -202,6 +210,7 @@ export type AppDependencies = {
|
|
|
202
210
|
};
|
|
203
211
|
export type ObjectStorageDependency = ReturnType<typeof createObjectStorage>;
|
|
204
212
|
export type ApiRouteDeps = AppDependencies & {
|
|
213
|
+
resolveCatalogSettings: () => Promise<ResolvedCatalogSettings>;
|
|
205
214
|
managedEmailTransport: ManagedEmailTransport;
|
|
206
215
|
objectStorage: ObjectStorageDependency;
|
|
207
216
|
githubStateSecret: string;
|
|
@@ -216,7 +225,7 @@ export type ApiRouteDeps = AppDependencies & {
|
|
|
216
225
|
* the canonical admission path without constructing unrelated HTTP, document,
|
|
217
226
|
* or sandbox services. The public API still passes its `ApiRouteDeps` superset.
|
|
218
227
|
*/
|
|
219
|
-
export type AcceptSessionUserMessageDependencies = Pick<AppDependencies, "settings" | "db" | "bus" | "sessionAuthorization" | "schedulePromptPostCommit"> & {
|
|
228
|
+
export type AcceptSessionUserMessageDependencies = Pick<AppDependencies, "settings" | "catalogSourceSettings" | "db" | "bus" | "sessionAuthorization" | "schedulePromptPostCommit"> & {
|
|
220
229
|
workflowClient: Pick<SessionWorkflowClient, "wakeSessionWorkflow">;
|
|
221
230
|
objectStorage: ObjectStorageDependency;
|
|
222
231
|
};
|
|
@@ -15,9 +15,8 @@ export type CompanyBrainGovernedWriteRouterOptions = {
|
|
|
15
15
|
activate?: typeof activateGovernedLearningDecision;
|
|
16
16
|
/**
|
|
17
17
|
* Destinations the router may activate automatically from a final eligible
|
|
18
|
-
* decision. Defaults to
|
|
19
|
-
*
|
|
20
|
-
* decision receipt is recorded but the inactive draft stays for review.
|
|
18
|
+
* decision. Defaults to Skills and instruction policy. Both still pass
|
|
19
|
+
* through the evaluator and destination-owned activation lifecycle.
|
|
21
20
|
*/
|
|
22
21
|
automaticDestinations?: ReadonlyArray<GovernedLearningActivationDestination>;
|
|
23
22
|
/**
|
|
@@ -33,6 +32,17 @@ export type CompanyBrainGovernedWriteRouterOptions = {
|
|
|
33
32
|
}) => Promise<GovernedLearningSlackPublicationResult>;
|
|
34
33
|
};
|
|
35
34
|
export declare const DEFAULT_AUTOMATIC_LEARNING_DESTINATIONS: ReadonlyArray<GovernedLearningActivationDestination>;
|
|
35
|
+
/**
|
|
36
|
+
* Start a non-authoritative post-activation notification without making the
|
|
37
|
+
* durable activation receipt wait for its settlement. The callback is invoked
|
|
38
|
+
* synchronously so immediate enqueue work begins before the router returns;
|
|
39
|
+
* both synchronous throws and later promise rejections are contained.
|
|
40
|
+
*
|
|
41
|
+
* Exact retries intentionally dispatch again: the publication sink owns an
|
|
42
|
+
* activation-receipt idempotency key, while the activation receipt remains the
|
|
43
|
+
* caller-facing source of truth even if notification delivery stalls forever.
|
|
44
|
+
*/
|
|
45
|
+
export declare function dispatchBestEffortGovernedLearningNotification(notify: () => Promise<unknown>): void;
|
|
36
46
|
/**
|
|
37
47
|
* Transport-neutral facade for explicit governed Company Brain proposals.
|
|
38
48
|
* It intentionally exposes no generic remember call, selector, activation,
|
|
@@ -59,9 +69,8 @@ export declare function derivedGovernedLearningOperationId(operationId: string,
|
|
|
59
69
|
* snapshot. `suggest` records the content-free decision receipt only. Under
|
|
60
70
|
* `automatic`, a final `automaticEligible` receipt is handed to the activation
|
|
61
71
|
* controller, which revalidates current authority and applies the change only
|
|
62
|
-
* through the destination-owned lifecycle.
|
|
63
|
-
* activate automatically
|
|
64
|
-
* activation boundary. Evaluation or activation failure
|
|
72
|
+
* through the destination-owned lifecycle. Eligible Skills and instruction
|
|
73
|
+
* policies may activate automatically. Evaluation or activation failure
|
|
65
74
|
* never rolls back the durable proposal; it is reported as a bounded
|
|
66
75
|
* `learningFailure` and the proposal remains for human review.
|
|
67
76
|
*/
|
|
@@ -9,8 +9,9 @@ export type CompanyProfileAgentAdminRouterOptions = {
|
|
|
9
9
|
/**
|
|
10
10
|
* Explicit organization administration is intentionally separate from derived
|
|
11
11
|
* workspace learning. The database capabilities own exact-attempt admission,
|
|
12
|
-
* current organization-owner authority,
|
|
13
|
-
* tenant isolation, CAS, and immutable
|
|
12
|
+
* current organization-owner authority, the separate organization policy,
|
|
13
|
+
* canonical review when required, tenant isolation, CAS, and immutable
|
|
14
|
+
* receipts.
|
|
14
15
|
*/
|
|
15
16
|
export declare function createCompanyProfileAgentAdminRouter(options: CompanyProfileAgentAdminRouterOptions): {
|
|
16
17
|
propose: (input: {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type Settings } from "@opengeni/config";
|
|
2
|
-
import type
|
|
2
|
+
import { type AccessGrant, type VariableSet } from "@opengeni/contracts";
|
|
3
3
|
import { type Database } from "@opengeni/db";
|
|
4
4
|
export declare const MAX_ENVIRONMENTS_PER_WORKSPACE = 25;
|
|
5
5
|
export declare const MAX_VARIABLES_PER_ENVIRONMENT = 100;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { MemorySlackPublicationDistribution } from "@opengeni/contracts";
|
|
2
|
-
import { type Database, type EnqueueMemorySlackPublicationResult, type MemoryEmbedder, type MemorySlackPublicationActor, type SaveWorkspaceMemoryInput, type SaveWorkspaceMemoryResult } from "@opengeni/db";
|
|
2
|
+
import { type CorrectWorkspaceMemoryInput, type CorrectWorkspaceMemoryResult, type Database, type EnqueueMemorySlackPublicationResult, type MemoryEmbedder, type MemorySlackPublicationActor, type SaveWorkspaceMemoryInput, type SaveWorkspaceMemoryResult } from "@opengeni/db";
|
|
3
3
|
import { type MemorySlackOrigin, type MemorySlackPublicationDecision } from "./memory-slack-publication.js";
|
|
4
4
|
export type MemorySlackPublicationCommitRequest = {
|
|
5
5
|
distribution: MemorySlackPublicationDistribution;
|
|
@@ -14,3 +14,6 @@ export type MemorySlackPublicationCommitResult = {
|
|
|
14
14
|
export declare function saveWorkspaceMemoryWithSlackPublication(db: Database, input: SaveWorkspaceMemoryInput, publication: MemorySlackPublicationCommitRequest | null, embedder?: MemoryEmbedder): Promise<SaveWorkspaceMemoryResult & {
|
|
15
15
|
slackPublication: MemorySlackPublicationCommitResult;
|
|
16
16
|
}>;
|
|
17
|
+
export declare function correctWorkspaceMemoryWithSlackPublication(db: Database, input: CorrectWorkspaceMemoryInput, publication: MemorySlackPublicationCommitRequest | null, embedder?: MemoryEmbedder): Promise<CorrectWorkspaceMemoryResult & {
|
|
18
|
+
slackPublication: MemorySlackPublicationCommitResult;
|
|
19
|
+
}>;
|
|
@@ -47,6 +47,7 @@ export declare function personalConnectionDelegationsFromVisibleConnections(inpu
|
|
|
47
47
|
export declare function personalConnectionDelegationsFromParent(input: {
|
|
48
48
|
servers: McpServerConfig[];
|
|
49
49
|
parentDelegations: McpPersonalConnectionDelegation[];
|
|
50
|
+
personalGitHubResources?: ResourceRef[];
|
|
50
51
|
targetSessionId?: string;
|
|
51
52
|
rejectActivatedConnections?: boolean;
|
|
52
53
|
}): McpPersonalConnectionDelegation[];
|
|
@@ -81,7 +81,7 @@ export declare const prReviewAutomationAdapter: {
|
|
|
81
81
|
optional?: boolean | undefined;
|
|
82
82
|
}[];
|
|
83
83
|
firstPartyMcpTools: ("artifacts_create" | "artifacts_get_source" | "artifacts_list" | "artifacts_publish" | "artifacts_rollback" | "atlassian_get" | "atlassian_search" | "atlassian_sources_list" | "browser_act" | "browser_auth" | "browser_clipboard" | "browser_debug" | "browser_identity" | "browser_lifecycle" | "browser_observe" | "browser_open" | "browser_publish" | "browser_tabs" | "capability_authorization_request" | "capability_catalog_search" | "company_profile_confirm" | "company_profile_propose" | "computer_act" | "computer_clipboard" | "computer_lifecycle" | "computer_observe" | "computer_open" | "computer_targets" | "connected_machine_remove" | "editable_artifact_apply" | "editable_artifact_create" | "editable_artifact_export" | "editable_artifact_export_status" | "editable_artifact_get" | "editable_artifact_import" | "editable_artifact_inspect" | "editable_artifact_list" | "environment_list" | "environment_set_variable" | "fiken_bank_accounts_list" | "fiken_companies_list" | "fiken_contact_create" | "fiken_contacts_list" | "fiken_invoice_draft_create" | "fiken_invoice_get" | "fiken_invoices_list" | "fiken_products_list" | "fiken_purchases_list" | "fiken_sales_list" | "github_connect_link" | "github_repositories_list" | "goal_complete" | "goal_pause" | "goal_progress" | "goal_set" | "goal_update" | "goal_wait" | "instruction_policy_propose" | "interaction_discover" | "interaction_request_human" | "knowledge_correct" | "knowledge_propose" | "memory_correct" | "memory_save" | "memory_search" | "preference_propose" | "preference_registry_get" | "preference_registry_summary" | "reddit_accounts_list" | "reddit_mentions_live" | "reddit_post_reply" | "reddit_posts_sync" | "reddit_search_live" | "reddit_thread_fetch" | "remember" | "remember_confirm" | "rig_get" | "rig_list" | "rig_promote" | "rig_propose_change" | "rig_verify" | "run_on" | "sandbox_attach" | "sandbox_file_publish" | "sandbox_provision" | "sandbox_swap" | "sandboxes_list" | "scheduled_task_runs_list" | "scheduled_tasks_create" | "scheduled_tasks_delete" | "scheduled_tasks_get" | "scheduled_tasks_list" | "scheduled_tasks_pause" | "scheduled_tasks_resume" | "scheduled_tasks_trigger" | "scheduled_tasks_update" | "session_create" | "session_events" | "session_get" | "session_human_input_respond" | "session_pause" | "session_resume" | "session_send_message" | "session_steer" | "session_wait" | "sessions_list" | "set_other_session_title" | "set_session_title" | "slack_bot_channel_history" | "slack_bot_delete_message" | "slack_bot_file_content" | "slack_bot_file_info" | "slack_bot_list_channels" | "slack_bot_list_files" | "slack_bot_list_users" | "slack_bot_post_message" | "slack_bot_search" | "slack_bot_thread_replies" | "social_connections_list" | "social_daily_analysis_context" | "social_mentions_live" | "social_post_reply" | "social_posts_recent" | "social_posts_sync" | "social_search_live" | "social_thread_fetch" | "task_note_archive" | "task_note_promote_instruction_policy" | "task_note_promote_knowledge" | "task_note_promote_preference" | "task_note_replace" | "task_note_save" | "task_notes_list" | "variable_set_get_variable" | "variable_set_list" | "variable_set_set_variable" | "work_claim_release" | "work_claim_upsert" | "x_accounts_list" | "x_mentions_live" | "x_post_reply" | "x_posts_sync" | "x_search_live" | "x_thread_fetch")[];
|
|
84
|
-
firstPartyMcpPermissions: ("account:admin" | "account:read" | "api_keys:manage" | "artifacts:publish" | "artifacts:read" | "billing:manage" | "billing:read" | "codemode:call" | "connections:read" | "connections:write" | "documents:manage" | "documents:search" | "enrollments:manage" | "enrollments:read" | "environments:manage" | "environments:use" | "files:read" | "files:upload" | "files:write" | "github:manage" | "github:use" | "goals:manage" | "mcp_servers:attach" | "members:manage" | "rigs:manage" | "rigs:use" | "scheduled_tasks:manage" | "scheduled_tasks:run" | "secrets:list" | "secrets:read" | "secrets:write" | "sessions:control" | "sessions:create" | "sessions:read" | "stream:acknowledge" | "stream:control" | "stream:view" | "terminal:attach" | "variable-sets:attach" | "variable-sets:list" | "variable-sets:manage" | "variable-sets:read" | "variable-sets:use" | "variable-sets:write" | "workspace:admin" | "workspace:create" | "workspace:read")[];
|
|
84
|
+
firstPartyMcpPermissions: ("account:admin" | "account:read" | "api_keys:manage" | "artifacts:publish" | "artifacts:read" | "billing:manage" | "billing:read" | "capabilities:manage" | "codemode:call" | "connections:read" | "connections:write" | "documents:manage" | "documents:search" | "enrollments:manage" | "enrollments:read" | "environments:manage" | "environments:use" | "files:read" | "files:upload" | "files:write" | "github:manage" | "github:use" | "goals:manage" | "mcp_servers:attach" | "members:manage" | "rigs:manage" | "rigs:use" | "scheduled_tasks:manage" | "scheduled_tasks:run" | "secrets:list" | "secrets:read" | "secrets:write" | "sessions:control" | "sessions:create" | "sessions:read" | "stream:acknowledge" | "stream:control" | "stream:view" | "terminal:attach" | "variable-sets:attach" | "variable-sets:list" | "variable-sets:manage" | "variable-sets:read" | "variable-sets:use" | "variable-sets:write" | "workspace:admin" | "workspace:create" | "workspace:read")[];
|
|
85
85
|
model: string | null;
|
|
86
86
|
reasoningEffort: "high" | "low" | "max" | "medium" | "minimal" | "none" | "xhigh" | null;
|
|
87
87
|
sandboxBackend: "blaxel" | "cloudflare" | "daytona" | "docker" | "e2b" | "local" | "modal" | "none" | "opensandbox" | "runloop" | "selfhosted" | "vercel" | null;
|
|
@@ -48,6 +48,18 @@ export declare function validateScheduledTaskTarget(input: {
|
|
|
48
48
|
agentConfig: ScheduledTaskAgentConfig;
|
|
49
49
|
missingTargetStatus?: 404 | 422;
|
|
50
50
|
}): Promise<Session | null>;
|
|
51
|
+
export declare function validateScheduledTaskMachineTarget(input: {
|
|
52
|
+
settings: Settings;
|
|
53
|
+
db: Database;
|
|
54
|
+
grant: AccessGrant;
|
|
55
|
+
runMode: ScheduledTask["runMode"];
|
|
56
|
+
agentConfig: ScheduledTaskAgentConfig;
|
|
57
|
+
requireOnline?: boolean;
|
|
58
|
+
}): Promise<{
|
|
59
|
+
sandboxId: string;
|
|
60
|
+
enrollmentId: string;
|
|
61
|
+
sandboxOs: Session["sandboxOs"];
|
|
62
|
+
} | null>;
|
|
51
63
|
export declare function scheduledTaskForGrant(task: ScheduledTask, grant: AccessGrant): ScheduledTask;
|
|
52
64
|
export declare function scheduledTaskRunForGrant<T extends {
|
|
53
65
|
sessionId: string | null;
|
|
@@ -66,6 +66,15 @@ export type CreateSessionRequestOutcome = CreateSessionOutcome & {
|
|
|
66
66
|
/** Billing telemetry is recorded after the committed session start. */
|
|
67
67
|
usageRecording: "recorded" | "failed";
|
|
68
68
|
};
|
|
69
|
+
type AgentChildSessionCreatePresentation = {
|
|
70
|
+
/** Model-authored title candidate from the first-party `session_create` tool.
|
|
71
|
+
* This is deliberately separate from the public REST request contract. */
|
|
72
|
+
automaticTitleCandidate?: string | null;
|
|
73
|
+
};
|
|
74
|
+
/** @internal Exported for the keyed-create repair regression. */
|
|
75
|
+
export declare function freezeAgentChildAutomaticTitleInCreatorContext(context: TurnInitiatorContext | undefined, title: string | null | undefined): TurnInitiatorContext | undefined;
|
|
76
|
+
/** @internal Keyed repair must use the committed winner, not the retry payload. */
|
|
77
|
+
export declare function initialAutomaticTitleForSessionStart(session: Pick<Session, "createdByContext">, requestedTitle: string | null | undefined): string | null;
|
|
69
78
|
export declare function createAndStartSessionWithOutcome(input: {
|
|
70
79
|
requestedSessionId?: string;
|
|
71
80
|
db: Database;
|
|
@@ -74,6 +83,16 @@ export declare function createAndStartSessionWithOutcome(input: {
|
|
|
74
83
|
/** Internal database-only composition seam. The exact session shell and this
|
|
75
84
|
* linkage commit together before its first event/turn can be initialized. */
|
|
76
85
|
beforeCreateCommit?: (tx: Database, sessionId: string) => Promise<void>;
|
|
86
|
+
/** The custom workspace model was frozen by an earlier accepted boundary or
|
|
87
|
+
* inherited from an existing session, so retirement must not invalidate it. */
|
|
88
|
+
retainWorkspaceGatewayModel?: boolean;
|
|
89
|
+
/** Provider-neutral successor to retainWorkspaceGatewayModel. */
|
|
90
|
+
retainWorkspaceCustomModel?: boolean;
|
|
91
|
+
/** The selected workspace Gateway product is backed by a mutable custom row,
|
|
92
|
+
* rather than deployment-curated Gateway membership. */
|
|
93
|
+
workspaceGatewayCustomModel?: boolean;
|
|
94
|
+
/** Provider-neutral successor to workspaceGatewayCustomModel. */
|
|
95
|
+
workspaceCustomModel?: boolean;
|
|
77
96
|
accountId: string;
|
|
78
97
|
workspaceId: string;
|
|
79
98
|
visibility?: "user_private" | "workspace_shared";
|
|
@@ -107,6 +126,9 @@ export declare function createAndStartSessionWithOutcome(input: {
|
|
|
107
126
|
rigVersionId?: string | null;
|
|
108
127
|
channelId?: string | null;
|
|
109
128
|
goal?: GoalSpec | null;
|
|
129
|
+
/** Trusted sensitive-safe automatic title for an agent-created child. The
|
|
130
|
+
* atomic initializer commits the row mutation and `session.title_set`. */
|
|
131
|
+
initialAutomaticTitle?: string | null;
|
|
110
132
|
instructions?: string | null;
|
|
111
133
|
policyRole?: string | null;
|
|
112
134
|
firstPartyMcpPermissions?: Permission[] | null;
|
|
@@ -201,7 +223,16 @@ export declare function requireQueuedTurnForApi(db: Database, workspaceId: strin
|
|
|
201
223
|
* `session_send_message` tool so the two surfaces cannot drift. Callers own
|
|
202
224
|
* resource/tool validation and the per-message usage limit before calling.
|
|
203
225
|
*/
|
|
204
|
-
|
|
226
|
+
type PostUserMessageTurnResult = {
|
|
227
|
+
accepted: SessionEvent;
|
|
228
|
+
turn: SessionTurn;
|
|
229
|
+
draft: ComposerDraft | null;
|
|
230
|
+
receipt: SessionCommandReceipt;
|
|
231
|
+
routing: SessionPromptRouting;
|
|
232
|
+
interruptionCount: number;
|
|
233
|
+
replay: boolean;
|
|
234
|
+
};
|
|
235
|
+
type PostUserMessageTurnInput = {
|
|
205
236
|
db: Database;
|
|
206
237
|
bus: EventBus;
|
|
207
238
|
workflowClient: Pick<SessionWorkflowClient, "wakeSessionWorkflow">;
|
|
@@ -229,19 +260,13 @@ export declare function postUserMessageTurn(input: {
|
|
|
229
260
|
commandActor?: SessionCommandActor;
|
|
230
261
|
controlEtag?: string | null;
|
|
231
262
|
expectedDraftRevision?: number | null;
|
|
263
|
+
boundaryRequestHash?: string;
|
|
232
264
|
reasoningEffortFallback?: Settings["openaiReasoningEffort"];
|
|
233
265
|
turnExecutionPolicy: TurnExecutionPolicyV1;
|
|
234
266
|
recordAgentRunUsage?: boolean;
|
|
235
267
|
schedulePostCommit?: (task: () => Promise<void>) => void;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
turn: SessionTurn;
|
|
239
|
-
draft: ComposerDraft | null;
|
|
240
|
-
receipt: SessionCommandReceipt;
|
|
241
|
-
routing: SessionPromptRouting;
|
|
242
|
-
interruptionCount: number;
|
|
243
|
-
replay: boolean;
|
|
244
|
-
}>;
|
|
268
|
+
};
|
|
269
|
+
export declare function postUserMessageTurn(input: PostUserMessageTurnInput): Promise<PostUserMessageTurnResult>;
|
|
245
270
|
/**
|
|
246
271
|
* Full create-session flow shared by `POST /sessions` and the first-party MCP
|
|
247
272
|
* `session_create` tool: payload validation, resource/tool/variableSet
|
|
@@ -257,7 +282,7 @@ export declare function resolveSessionCreateVisibility(input: {
|
|
|
257
282
|
visibilityProvided: boolean;
|
|
258
283
|
parentVisibility: "user_private" | "workspace_shared" | null;
|
|
259
284
|
}): "user_private" | "workspace_shared";
|
|
260
|
-
export declare function createSessionForRequestWithOutcome(
|
|
285
|
+
export declare function createSessionForRequestWithOutcome(unresolvedDeps: ApiRouteDeps, grant: AccessGrant, workspaceId: string, rawPayload: unknown, authorization?: AccessGrantAuthorization, agentChildPresentation?: AgentChildSessionCreatePresentation): Promise<CreateSessionRequestOutcome>;
|
|
261
286
|
/** @internal Fixed public projection; the committed session outcome remains authoritative. */
|
|
262
287
|
export declare function reportSessionUsageRecordingFailure(_error: unknown): void;
|
|
263
288
|
/** Backward-compatible entity-returning request path for REST and core callers. */
|
|
@@ -348,3 +373,4 @@ export declare function updateSessionToolPolicy(deps: {
|
|
|
348
373
|
sessionAuthorization?: SessionAuthorizationPort | null;
|
|
349
374
|
}, grant: AccessGrant, sessionId: string, request: UpdateSessionToolPolicyRequest): Promise<Session>;
|
|
350
375
|
export declare function readSessionLineage(deps: Pick<ApiRouteDeps, "db" | "sessionAuthorization">, grant: AccessGrant, sessionId: string): Promise<import("@opengeni/db").SessionLineage>;
|
|
376
|
+
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { WorkspaceMember } from "@opengeni/contracts";
|
|
1
|
+
import type { Permission, WorkspaceMember } from "@opengeni/contracts";
|
|
2
2
|
/** A member can manage other members (directly or via the admin wildcard). */
|
|
3
3
|
export declare function memberCanAdminister(member: Pick<WorkspaceMember, "permissions">): boolean;
|
|
4
4
|
/** Only `user:` subjects are people; `api_key:` subjects belong to API keys. */
|
|
@@ -21,6 +21,13 @@ export declare function assertWorkspaceMemberRemovable(input: {
|
|
|
21
21
|
subjectId: string;
|
|
22
22
|
callerSubjectId: string;
|
|
23
23
|
}): void;
|
|
24
|
+
/** Keep scoped member edits from orphaning the workspace or changing the caller's own grant. */
|
|
25
|
+
export declare function assertWorkspaceMemberUpdateAllowed(input: {
|
|
26
|
+
members: WorkspaceMember[];
|
|
27
|
+
subjectId: string;
|
|
28
|
+
callerSubjectId: string;
|
|
29
|
+
nextPermissions: Permission[];
|
|
30
|
+
}): void;
|
|
24
31
|
/**
|
|
25
32
|
* Guard the workspace-delete path before any external/DB mutation. Refuses
|
|
26
33
|
* (409) to delete the account's last workspace, and refuses while any session
|
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export * from "./sandbox-types.js";
|
|
|
4
4
|
export * from "./managed-auth-type.js";
|
|
5
5
|
export { getManagedAuthRequestActorAbortSignal, getManagedAuthRequestActorAdmissionStamp, getManagedAuthRequestActorEpoch, getManagedAuthRequestActorLeaseStamp, getManagedSession, ManagedAuthActorLeaseOutcomeUnknownError, markManagedAuthRequestActorTransitionApplied, releaseManagedAuthRequestActorLease, validateManagedAuthRequestActorLease, type ManagedAuthActorAdmissionStamp, type ManagedAuthActorMutationLeaseStamp, } from "./managed-session.js";
|
|
6
6
|
export * from "./transcription.js";
|
|
7
|
+
export * from "./model-catalog.js";
|
|
7
8
|
export * from "./sandbox/fleet.js";
|
|
8
9
|
export * from "./sandbox/routing.js";
|
|
9
10
|
export * from "./sandbox/runtime-settings.js";
|