@iblai/data-layer 1.39.0 → 1.40.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/index.d.ts +462 -251
- package/dist/index.esm.js +295 -9
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +305 -8
- package/dist/index.js.map +1 -1
- package/dist/package.json +1 -1
- package/dist/src/features/credentials/__tests__/api-slice.test.d.ts +1 -0
- package/dist/src/features/credentials/api-slice.d.ts +386 -245
- package/dist/src/features/virtual-machine/__tests__/api-slice.test.d.ts +1 -0
- package/dist/src/features/virtual-machine/__tests__/utils.test.d.ts +1 -0
- package/dist/src/features/virtual-machine/api-slice.d.ts +5 -3
- package/dist/src/features/virtual-machine/constants.d.ts +20 -1
- package/dist/src/features/virtual-machine/types.d.ts +1 -1
- package/dist/src/features/virtual-machine/utils.d.ts +49 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -42242,7 +42242,10 @@ const CREDENTIALS_CUSTOM_ENDPOINTS = {
|
|
|
42242
42242
|
|
|
42243
42243
|
const credentialsCustomApiSlice = react.createApi({
|
|
42244
42244
|
reducerPath: CREDENTIALS_CUSTOM_REDUCER_PATH,
|
|
42245
|
-
|
|
42245
|
+
// The Secrets page hides a kind's rows on a 403 of its list and shows the
|
|
42246
|
+
// retry notice on any other failure, which needs the status: RTK Query
|
|
42247
|
+
// keeps only `{}` of a thrown `{ status, data }`.
|
|
42248
|
+
baseQuery: withReturnedErrors(iblFetchBaseQuery),
|
|
42246
42249
|
tagTypes: [
|
|
42247
42250
|
'IntegrationCredentialsSchema',
|
|
42248
42251
|
'CredentialsSchema',
|
|
@@ -42262,6 +42265,23 @@ const credentialsCustomApiSlice = react.createApi({
|
|
|
42262
42265
|
}),
|
|
42263
42266
|
}),
|
|
42264
42267
|
invalidatesTags: ['MaskedIntegrationCredentials'],
|
|
42268
|
+
// The Secrets screens read the admin list and the VM secrets, and the
|
|
42269
|
+
// backend deletes the secrets that read this credential with it. The
|
|
42270
|
+
// slices are imported lazily: api-slice.ts imports this file.
|
|
42271
|
+
async onQueryStarted(_args, { queryFulfilled, dispatch }) {
|
|
42272
|
+
try {
|
|
42273
|
+
await queryFulfilled;
|
|
42274
|
+
const [{ credentialsApiSlice }, { virtualMachineApiSlice }] = await Promise.all([
|
|
42275
|
+
Promise.resolve().then(function () { return apiSlice$1; }),
|
|
42276
|
+
Promise.resolve().then(function () { return apiSlice; }),
|
|
42277
|
+
]);
|
|
42278
|
+
dispatch(credentialsApiSlice.util.invalidateTags(['IntegrationCredentials']));
|
|
42279
|
+
dispatch(virtualMachineApiSlice.util.invalidateTags(['VirtualMachineSecrets']));
|
|
42280
|
+
}
|
|
42281
|
+
catch (_a) {
|
|
42282
|
+
// Only a successful delete invalidates.
|
|
42283
|
+
}
|
|
42284
|
+
},
|
|
42265
42285
|
}),
|
|
42266
42286
|
deleteCredential: builder.mutation({
|
|
42267
42287
|
query: ({ org, name, platform_key, model_name }) => ({
|
|
@@ -42331,7 +42351,7 @@ const { useDeleteIntegrationCredentialMutation, useDeleteCredentialMutation, use
|
|
|
42331
42351
|
const credentialsApiSlice = react.createApi({
|
|
42332
42352
|
reducerPath: 'credentialsApiSlice',
|
|
42333
42353
|
baseQuery: iblFakeBaseQuery,
|
|
42334
|
-
tagTypes: ['Credentials', 'ProviderConfig', 'ExternalMapping'],
|
|
42354
|
+
tagTypes: ['Credentials', 'ProviderConfig', 'ExternalMapping', 'IntegrationCredentials'],
|
|
42335
42355
|
endpoints: (builder) => ({
|
|
42336
42356
|
getCredentials: builder.query({
|
|
42337
42357
|
...buildEndpointFromService(exports.SERVICES.DM, async (args) => {
|
|
@@ -42431,11 +42451,15 @@ const credentialsApiSlice = react.createApi({
|
|
|
42431
42451
|
createCallCredentials: builder.mutation({
|
|
42432
42452
|
...buildEndpointFromAxdService(AiMentorService.aiMentorOrgsUsersMentorsCreateCallCredentialsCreate),
|
|
42433
42453
|
}),
|
|
42454
|
+
// The admin list (ids + service_info), which the Secrets screens join
|
|
42455
|
+
// with the VM secrets that read a credential.
|
|
42434
42456
|
getIntegrationCredentials: builder.query({
|
|
42435
42457
|
...buildEndpointFromDmService(AiAccountService.aiAccountOrgsIntegrationCredentialRetrieve),
|
|
42458
|
+
providesTags: ['IntegrationCredentials'],
|
|
42436
42459
|
}),
|
|
42437
42460
|
createIntegrationCredential: builder.mutation({
|
|
42438
42461
|
...buildEndpointFromDmService(AiAccountService.aiAccountOrgsIntegrationCredentialCreate),
|
|
42462
|
+
invalidatesTags: ['IntegrationCredentials'],
|
|
42439
42463
|
async onQueryStarted(_args, { queryFulfilled, dispatch }) {
|
|
42440
42464
|
try {
|
|
42441
42465
|
await queryFulfilled;
|
|
@@ -42448,9 +42472,42 @@ const credentialsApiSlice = react.createApi({
|
|
|
42448
42472
|
}),
|
|
42449
42473
|
createLLMCredential: builder.mutation({
|
|
42450
42474
|
...buildEndpointFromDmService(AiAccountService.aiAccountOrgsCredentialCreate),
|
|
42475
|
+
async onQueryStarted(_args, { queryFulfilled, dispatch }) {
|
|
42476
|
+
try {
|
|
42477
|
+
await queryFulfilled;
|
|
42478
|
+
dispatch(credentialsCustomApiSlice.util.invalidateTags(['MaskedLLMCredentials']));
|
|
42479
|
+
}
|
|
42480
|
+
catch (_a) {
|
|
42481
|
+
// Swallow — invalidation should only happen on success.
|
|
42482
|
+
}
|
|
42483
|
+
},
|
|
42484
|
+
}),
|
|
42485
|
+
// PATCH `/credential/` replaces the whole value for every provider but
|
|
42486
|
+
// Azure OpenAI, whose per-model values the backend merges.
|
|
42487
|
+
updateLLMCredential: builder.mutation({
|
|
42488
|
+
...buildEndpointFromDmService(AiAccountService.aiAccountOrgsCredentialPartialUpdate),
|
|
42489
|
+
async onQueryStarted(_args, { queryFulfilled, dispatch }) {
|
|
42490
|
+
try {
|
|
42491
|
+
await queryFulfilled;
|
|
42492
|
+
dispatch(credentialsCustomApiSlice.util.invalidateTags(['MaskedLLMCredentials']));
|
|
42493
|
+
}
|
|
42494
|
+
catch (_a) {
|
|
42495
|
+
// Swallow — invalidation should only happen on success.
|
|
42496
|
+
}
|
|
42497
|
+
},
|
|
42451
42498
|
}),
|
|
42452
42499
|
updateIntegrationCredential: builder.mutation({
|
|
42453
42500
|
...buildEndpointFromDmService(AiAccountService.aiAccountOrgsIntegrationCredentialPartialUpdate),
|
|
42501
|
+
invalidatesTags: ['IntegrationCredentials'],
|
|
42502
|
+
async onQueryStarted(_args, { queryFulfilled, dispatch }) {
|
|
42503
|
+
try {
|
|
42504
|
+
await queryFulfilled;
|
|
42505
|
+
dispatch(credentialsCustomApiSlice.util.invalidateTags(['MaskedIntegrationCredentials']));
|
|
42506
|
+
}
|
|
42507
|
+
catch (_a) {
|
|
42508
|
+
// Swallow — invalidation should only happen on success.
|
|
42509
|
+
}
|
|
42510
|
+
},
|
|
42454
42511
|
}),
|
|
42455
42512
|
getConnectedServiceAuthUrl: builder.query({
|
|
42456
42513
|
queryFn: async (queryParams, api, extraOptions) => {
|
|
@@ -42561,7 +42618,45 @@ const credentialsApiSlice = react.createApi({
|
|
|
42561
42618
|
}),
|
|
42562
42619
|
}),
|
|
42563
42620
|
});
|
|
42564
|
-
const { useGetCredentialsQuery, useLazyGetCredentialsQuery, useGetUserCredentialsQuery, useLazyGetUserCredentialsQuery, useCreateCallCredentialsMutation, useGetIntegrationCredentialsQuery, useLazyGetIntegrationCredentialsQuery, useCreateIntegrationCredentialMutation, useUpdateIntegrationCredentialMutation, useGetLLMCredentialsQuery, useLazyGetLLMCredentialsQuery, useCreateLLMCredentialMutation, useGetConnectedServiceAuthUrlQuery, useLazyGetConnectedServiceAuthUrlQuery, useConnectedServicesCallbackQuery, useLazyConnectedServicesCallbackQuery, useGetUsersAsAssertionsQuery, useLazyGetUsersAsAssertionsQuery, useCreateCredentialAssertionMutation, useGetCredentialsListQuery, useLazyGetCredentialsListQuery, useCreateCredentialMutation, useUpdateCredentialMutation, useDeleteCourseCredentialMutation, useGetProviderConfigQuery, useLazyGetProviderConfigQuery, useCreateProviderConfigMutation, useDeleteProviderConfigMutation, useGetExternalMappingQuery, useLazyGetExternalMappingQuery, useCreateExternalMappingMutation, useDeleteExternalMappingMutation, } = credentialsApiSlice;
|
|
42621
|
+
const { useGetCredentialsQuery, useLazyGetCredentialsQuery, useGetUserCredentialsQuery, useLazyGetUserCredentialsQuery, useCreateCallCredentialsMutation, useGetIntegrationCredentialsQuery, useLazyGetIntegrationCredentialsQuery, useCreateIntegrationCredentialMutation, useUpdateIntegrationCredentialMutation, useGetLLMCredentialsQuery, useLazyGetLLMCredentialsQuery, useCreateLLMCredentialMutation, useUpdateLLMCredentialMutation, useGetConnectedServiceAuthUrlQuery, useLazyGetConnectedServiceAuthUrlQuery, useConnectedServicesCallbackQuery, useLazyConnectedServicesCallbackQuery, useGetUsersAsAssertionsQuery, useLazyGetUsersAsAssertionsQuery, useCreateCredentialAssertionMutation, useGetCredentialsListQuery, useLazyGetCredentialsListQuery, useCreateCredentialMutation, useUpdateCredentialMutation, useDeleteCourseCredentialMutation, useGetProviderConfigQuery, useLazyGetProviderConfigQuery, useCreateProviderConfigMutation, useDeleteProviderConfigMutation, useGetExternalMappingQuery, useLazyGetExternalMappingQuery, useCreateExternalMappingMutation, useDeleteExternalMappingMutation, } = credentialsApiSlice;
|
|
42622
|
+
|
|
42623
|
+
var apiSlice$1 = /*#__PURE__*/Object.freeze({
|
|
42624
|
+
__proto__: null,
|
|
42625
|
+
credentialsApiSlice: credentialsApiSlice,
|
|
42626
|
+
useConnectedServicesCallbackQuery: useConnectedServicesCallbackQuery,
|
|
42627
|
+
useCreateCallCredentialsMutation: useCreateCallCredentialsMutation,
|
|
42628
|
+
useCreateCredentialAssertionMutation: useCreateCredentialAssertionMutation,
|
|
42629
|
+
useCreateCredentialMutation: useCreateCredentialMutation,
|
|
42630
|
+
useCreateExternalMappingMutation: useCreateExternalMappingMutation,
|
|
42631
|
+
useCreateIntegrationCredentialMutation: useCreateIntegrationCredentialMutation,
|
|
42632
|
+
useCreateLLMCredentialMutation: useCreateLLMCredentialMutation,
|
|
42633
|
+
useCreateProviderConfigMutation: useCreateProviderConfigMutation,
|
|
42634
|
+
useDeleteCourseCredentialMutation: useDeleteCourseCredentialMutation,
|
|
42635
|
+
useDeleteExternalMappingMutation: useDeleteExternalMappingMutation,
|
|
42636
|
+
useDeleteProviderConfigMutation: useDeleteProviderConfigMutation,
|
|
42637
|
+
useGetConnectedServiceAuthUrlQuery: useGetConnectedServiceAuthUrlQuery,
|
|
42638
|
+
useGetCredentialsListQuery: useGetCredentialsListQuery,
|
|
42639
|
+
useGetCredentialsQuery: useGetCredentialsQuery,
|
|
42640
|
+
useGetExternalMappingQuery: useGetExternalMappingQuery,
|
|
42641
|
+
useGetIntegrationCredentialsQuery: useGetIntegrationCredentialsQuery,
|
|
42642
|
+
useGetLLMCredentialsQuery: useGetLLMCredentialsQuery,
|
|
42643
|
+
useGetProviderConfigQuery: useGetProviderConfigQuery,
|
|
42644
|
+
useGetUserCredentialsQuery: useGetUserCredentialsQuery,
|
|
42645
|
+
useGetUsersAsAssertionsQuery: useGetUsersAsAssertionsQuery,
|
|
42646
|
+
useLazyConnectedServicesCallbackQuery: useLazyConnectedServicesCallbackQuery,
|
|
42647
|
+
useLazyGetConnectedServiceAuthUrlQuery: useLazyGetConnectedServiceAuthUrlQuery,
|
|
42648
|
+
useLazyGetCredentialsListQuery: useLazyGetCredentialsListQuery,
|
|
42649
|
+
useLazyGetCredentialsQuery: useLazyGetCredentialsQuery,
|
|
42650
|
+
useLazyGetExternalMappingQuery: useLazyGetExternalMappingQuery,
|
|
42651
|
+
useLazyGetIntegrationCredentialsQuery: useLazyGetIntegrationCredentialsQuery,
|
|
42652
|
+
useLazyGetLLMCredentialsQuery: useLazyGetLLMCredentialsQuery,
|
|
42653
|
+
useLazyGetProviderConfigQuery: useLazyGetProviderConfigQuery,
|
|
42654
|
+
useLazyGetUserCredentialsQuery: useLazyGetUserCredentialsQuery,
|
|
42655
|
+
useLazyGetUsersAsAssertionsQuery: useLazyGetUsersAsAssertionsQuery,
|
|
42656
|
+
useUpdateCredentialMutation: useUpdateCredentialMutation,
|
|
42657
|
+
useUpdateIntegrationCredentialMutation: useUpdateIntegrationCredentialMutation,
|
|
42658
|
+
useUpdateLLMCredentialMutation: useUpdateLLMCredentialMutation
|
|
42659
|
+
});
|
|
42565
42660
|
|
|
42566
42661
|
const chatPrivacyApiSlice = react.createApi({
|
|
42567
42662
|
reducerPath: 'chatPrivacyApiSlice',
|
|
@@ -49992,11 +50087,51 @@ const VIRTUAL_MACHINE_REJECTED_HOST_SUFFIXES = [
|
|
|
49992
50087
|
];
|
|
49993
50088
|
/** `env_var` of a VM secret: a POSIX-style environment variable name. */
|
|
49994
50089
|
const VIRTUAL_MACHINE_ENV_VAR_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
50090
|
+
/** The backend caps `env_var` at 128 characters. */
|
|
50091
|
+
const VIRTUAL_MACHINE_ENV_VAR_MAX_LENGTH = 128;
|
|
50092
|
+
/**
|
|
50093
|
+
* Variable names the UI refuses for a secret. The backend only checks the
|
|
50094
|
+
* POSIX shape, but the sandbox sets `env_var` in the VM's environment, so a
|
|
50095
|
+
* secret named PATH or LD_PRELOAD would break every command run there.
|
|
50096
|
+
*/
|
|
50097
|
+
const VIRTUAL_MACHINE_RESERVED_ENV_VARS = [
|
|
50098
|
+
'PATH',
|
|
50099
|
+
'HOME',
|
|
50100
|
+
'USER',
|
|
50101
|
+
'LOGNAME',
|
|
50102
|
+
'SHELL',
|
|
50103
|
+
'PWD',
|
|
50104
|
+
'OLDPWD',
|
|
50105
|
+
'TMPDIR',
|
|
50106
|
+
'TERM',
|
|
50107
|
+
'LANG',
|
|
50108
|
+
'LANGUAGE',
|
|
50109
|
+
'LC_ALL',
|
|
50110
|
+
'LD_PRELOAD',
|
|
50111
|
+
'LD_LIBRARY_PATH',
|
|
50112
|
+
'PYTHONPATH',
|
|
50113
|
+
'PYTHONHOME',
|
|
50114
|
+
'NODE_OPTIONS',
|
|
50115
|
+
'HTTP_PROXY',
|
|
50116
|
+
'HTTPS_PROXY',
|
|
50117
|
+
'NO_PROXY',
|
|
50118
|
+
];
|
|
50119
|
+
/** Prefixes the sandbox and ibl.ai keep for their own variables. */
|
|
50120
|
+
const VIRTUAL_MACHINE_RESERVED_ENV_VAR_PREFIXES = ['MSB_', 'IBLAI_'];
|
|
50121
|
+
/**
|
|
50122
|
+
* The port a bare hostname gets in an allowlist. Secrets are only ever
|
|
50123
|
+
* swapped into HTTPS requests, so `api.acme.com` means `api.acme.com:443`.
|
|
50124
|
+
*/
|
|
50125
|
+
const VIRTUAL_MACHINE_DEFAULT_HOST_PORT = 443;
|
|
49995
50126
|
/** A network policy holds between 1 and 100 hosts. */
|
|
49996
50127
|
const VIRTUAL_MACHINE_MAX_POLICY_HOSTS = 100;
|
|
49997
50128
|
/** An agent may bind at most 20 VM secrets. */
|
|
49998
50129
|
const VIRTUAL_MACHINE_MAX_SECRETS_PER_MENTOR = 20;
|
|
49999
|
-
/**
|
|
50130
|
+
/**
|
|
50131
|
+
* The backend's floor for a pasted secret value (its output scrubber blanks
|
|
50132
|
+
* every occurrence of a bound value, so a very short one would blank too
|
|
50133
|
+
* much). The UI no longer checks it; a refusal is shown under the Key field.
|
|
50134
|
+
*/
|
|
50000
50135
|
const VIRTUAL_MACHINE_SECRET_VALUE_MIN_LENGTH = 8;
|
|
50001
50136
|
/**
|
|
50002
50137
|
* Default VM runtime billing: charged to the chatting user's credits, prorated
|
|
@@ -50016,12 +50151,14 @@ const VIRTUAL_MACHINE_DEFAULT_BILLING = {
|
|
|
50016
50151
|
* Hand-written: these endpoints are newer than the pinned `@iblai/iblai-api`
|
|
50017
50152
|
* release. Records are keyed in the body (PATCH) or the query string (DELETE),
|
|
50018
50153
|
* never in the URL. A 403 on either list means the caller lacks the matching
|
|
50019
|
-
* `Ibl.Mentor/VirtualMachine…/list` permission — hosts hide the pages then
|
|
50154
|
+
* `Ibl.Mentor/VirtualMachine…/list` permission — hosts hide the pages then,
|
|
50155
|
+
* which needs the status: the base query returns failures rather than throwing
|
|
50156
|
+
* them, since RTK Query keeps only `{}` of a thrown `{ status, data }`.
|
|
50020
50157
|
*/
|
|
50021
50158
|
const virtualMachineApiSlice = react.createApi({
|
|
50022
50159
|
reducerPath: VIRTUAL_MACHINE_REDUCER_PATH,
|
|
50023
50160
|
tagTypes: [VIRTUAL_MACHINE_QUERY_KEYS.NETWORK_POLICIES, VIRTUAL_MACHINE_QUERY_KEYS.SECRETS],
|
|
50024
|
-
baseQuery: iblFetchBaseQuery,
|
|
50161
|
+
baseQuery: withReturnedErrors(iblFetchBaseQuery),
|
|
50025
50162
|
endpoints: (builder) => ({
|
|
50026
50163
|
// ── Network policies ────────────────────────────────────────────────
|
|
50027
50164
|
listVirtualMachineNetworkPolicies: builder.query({
|
|
@@ -50102,6 +50239,21 @@ const virtualMachineApiSlice = react.createApi({
|
|
|
50102
50239
|
});
|
|
50103
50240
|
const { useListVirtualMachineNetworkPoliciesQuery, useLazyListVirtualMachineNetworkPoliciesQuery, useCreateVirtualMachineNetworkPolicyMutation, useUpdateVirtualMachineNetworkPolicyMutation, useDeleteVirtualMachineNetworkPolicyMutation, useListVirtualMachineSecretsQuery, useLazyListVirtualMachineSecretsQuery, useCreateVirtualMachineSecretMutation, useUpdateVirtualMachineSecretMutation, useDeleteVirtualMachineSecretMutation, } = virtualMachineApiSlice;
|
|
50104
50241
|
|
|
50242
|
+
var apiSlice = /*#__PURE__*/Object.freeze({
|
|
50243
|
+
__proto__: null,
|
|
50244
|
+
useCreateVirtualMachineNetworkPolicyMutation: useCreateVirtualMachineNetworkPolicyMutation,
|
|
50245
|
+
useCreateVirtualMachineSecretMutation: useCreateVirtualMachineSecretMutation,
|
|
50246
|
+
useDeleteVirtualMachineNetworkPolicyMutation: useDeleteVirtualMachineNetworkPolicyMutation,
|
|
50247
|
+
useDeleteVirtualMachineSecretMutation: useDeleteVirtualMachineSecretMutation,
|
|
50248
|
+
useLazyListVirtualMachineNetworkPoliciesQuery: useLazyListVirtualMachineNetworkPoliciesQuery,
|
|
50249
|
+
useLazyListVirtualMachineSecretsQuery: useLazyListVirtualMachineSecretsQuery,
|
|
50250
|
+
useListVirtualMachineNetworkPoliciesQuery: useListVirtualMachineNetworkPoliciesQuery,
|
|
50251
|
+
useListVirtualMachineSecretsQuery: useListVirtualMachineSecretsQuery,
|
|
50252
|
+
useUpdateVirtualMachineNetworkPolicyMutation: useUpdateVirtualMachineNetworkPolicyMutation,
|
|
50253
|
+
useUpdateVirtualMachineSecretMutation: useUpdateVirtualMachineSecretMutation,
|
|
50254
|
+
virtualMachineApiSlice: virtualMachineApiSlice
|
|
50255
|
+
});
|
|
50256
|
+
|
|
50105
50257
|
/**
|
|
50106
50258
|
* Normalise a `host:port` entry the way the backend stores it: trimmed and
|
|
50107
50259
|
* lowercased.
|
|
@@ -50109,13 +50261,78 @@ const { useListVirtualMachineNetworkPoliciesQuery, useLazyListVirtualMachineNetw
|
|
|
50109
50261
|
function normalizeHostPort(value) {
|
|
50110
50262
|
return value.trim().toLowerCase();
|
|
50111
50263
|
}
|
|
50264
|
+
const SCHEME_PORTS = { 'https:': 443, 'http:': 80 };
|
|
50265
|
+
// A loop rather than `/x+$/`, which takes quadratic time on a long run of x
|
|
50266
|
+
// that does not reach the end (CodeQL js/polynomial-redos).
|
|
50267
|
+
function trimChar(value, char, { start = false } = {}) {
|
|
50268
|
+
let from = 0;
|
|
50269
|
+
let to = value.length;
|
|
50270
|
+
if (start)
|
|
50271
|
+
while (from < to && value[from] === char)
|
|
50272
|
+
from += 1;
|
|
50273
|
+
while (to > from && value[to - 1] === char)
|
|
50274
|
+
to -= 1;
|
|
50275
|
+
return value.slice(from, to);
|
|
50276
|
+
}
|
|
50277
|
+
/**
|
|
50278
|
+
* Turn what a person typed or pasted into the `host:port` the backend stores.
|
|
50279
|
+
* People paste the address from a service's instructions, so a whole URL
|
|
50280
|
+
* (`https://api.acme.com/v1/keys`) is reduced to its host, with the scheme's
|
|
50281
|
+
* port unless the URL names one; `api.acme.com/v1` loses its path; a trailing
|
|
50282
|
+
* dot goes. Anything unparseable comes back trimmed and lowercased so
|
|
50283
|
+
* `validateHostPort` can explain it.
|
|
50284
|
+
*/
|
|
50285
|
+
function normalizeHostInput(value, options = {}) {
|
|
50286
|
+
let entry = normalizeHostPort(value);
|
|
50287
|
+
if (entry.length === 0)
|
|
50288
|
+
return entry;
|
|
50289
|
+
let port = null;
|
|
50290
|
+
if (entry.includes('://')) {
|
|
50291
|
+
try {
|
|
50292
|
+
const url = new URL(entry);
|
|
50293
|
+
if (!url.hostname)
|
|
50294
|
+
return entry;
|
|
50295
|
+
port = url.port || (SCHEME_PORTS[url.protocol] ? String(SCHEME_PORTS[url.protocol]) : null);
|
|
50296
|
+
entry = url.hostname;
|
|
50297
|
+
}
|
|
50298
|
+
catch (_a) {
|
|
50299
|
+
return entry;
|
|
50300
|
+
}
|
|
50301
|
+
}
|
|
50302
|
+
else {
|
|
50303
|
+
const pathStart = entry.search(/[/?#]/);
|
|
50304
|
+
if (pathStart !== -1)
|
|
50305
|
+
entry = entry.slice(0, pathStart);
|
|
50306
|
+
}
|
|
50307
|
+
if (port === null) {
|
|
50308
|
+
const separator = entry.lastIndexOf(':');
|
|
50309
|
+
if (separator !== -1) {
|
|
50310
|
+
port = entry.slice(separator + 1);
|
|
50311
|
+
entry = entry.slice(0, separator);
|
|
50312
|
+
}
|
|
50313
|
+
}
|
|
50314
|
+
entry = trimChar(entry, '.');
|
|
50315
|
+
if (entry.length === 0)
|
|
50316
|
+
return entry;
|
|
50317
|
+
if (port)
|
|
50318
|
+
return `${entry}:${port}`;
|
|
50319
|
+
return options.defaultPort !== undefined ? `${entry}:${options.defaultPort}` : entry;
|
|
50320
|
+
}
|
|
50112
50321
|
/** Split a pasted or typed string into candidate `host:port` entries. */
|
|
50113
|
-
function splitHostPortInput(value) {
|
|
50322
|
+
function splitHostPortInput(value, options = {}) {
|
|
50114
50323
|
return value
|
|
50115
50324
|
.split(/[\s,;]+/)
|
|
50116
|
-
.map(
|
|
50325
|
+
.map((entry) => normalizeHostInput(entry, options))
|
|
50117
50326
|
.filter((entry) => entry.length > 0);
|
|
50118
50327
|
}
|
|
50328
|
+
/**
|
|
50329
|
+
* The `host:port` a person reads: the standard HTTPS port is implied, so
|
|
50330
|
+
* `api.acme.com:443` shows as `api.acme.com`; any other port stays visible.
|
|
50331
|
+
* The stored and compared form is never changed by this.
|
|
50332
|
+
*/
|
|
50333
|
+
function formatHostPort(entry) {
|
|
50334
|
+
return entry.endsWith(':443') ? entry.slice(0, -4) : entry;
|
|
50335
|
+
}
|
|
50119
50336
|
const IPV4_PATTERN = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
|
|
50120
50337
|
/** Whether the host part is an IPv4 literal (the `host:port` grammar admits no IPv6). */
|
|
50121
50338
|
function isIpAddressHost(host) {
|
|
@@ -50271,6 +50488,75 @@ function findUncoveredSecretHosts(secrets, allowedHosts) {
|
|
|
50271
50488
|
}
|
|
50272
50489
|
return uncovered;
|
|
50273
50490
|
}
|
|
50491
|
+
/** Whether a variable name is one the VM itself relies on (see the reserved list). */
|
|
50492
|
+
function isReservedEnvVar(name) {
|
|
50493
|
+
const upper = name.toUpperCase();
|
|
50494
|
+
if (VIRTUAL_MACHINE_RESERVED_ENV_VARS.includes(upper))
|
|
50495
|
+
return true;
|
|
50496
|
+
return VIRTUAL_MACHINE_RESERVED_ENV_VAR_PREFIXES.some((prefix) => upper.startsWith(prefix));
|
|
50497
|
+
}
|
|
50498
|
+
const ENV_VAR_WORDS = ['KEY', 'TOKEN', 'SECRET', 'PASSWORD'];
|
|
50499
|
+
const ENV_VAR_FALLBACK = 'SECRET';
|
|
50500
|
+
/** Leaves room for a `_NN` suffix under the backend's 128-character cap. */
|
|
50501
|
+
const ENV_VAR_DERIVED_MAX_LENGTH = VIRTUAL_MACHINE_ENV_VAR_MAX_LENGTH - 8;
|
|
50502
|
+
/**
|
|
50503
|
+
* The variable name a secret gets from its display name, so a person never
|
|
50504
|
+
* has to invent one: "Acme API key" → `ACME_API_KEY`, "Clé Stripe" →
|
|
50505
|
+
* `CLE_STRIPE_KEY`. Accents are folded, every other run of characters becomes
|
|
50506
|
+
* an underscore, a leading digit gets `KEY_` in front, a name without
|
|
50507
|
+
* KEY/TOKEN/SECRET/PASSWORD gets `_KEY` (which also keeps "Path" from
|
|
50508
|
+
* becoming the VM's PATH), nothing derivable falls back to `SECRET`, and a
|
|
50509
|
+
* clash with `taken` gets `_2`, `_3`, …
|
|
50510
|
+
*/
|
|
50511
|
+
function deriveSecretEnvVar(name, options = {}) {
|
|
50512
|
+
var _a;
|
|
50513
|
+
let base = trimChar(name
|
|
50514
|
+
.normalize('NFKD')
|
|
50515
|
+
.replace(/[\u0300-\u036f]/g, '')
|
|
50516
|
+
.toUpperCase()
|
|
50517
|
+
.replace(/[^A-Z0-9]+/g, '_'), '_', { start: true }).replace(/_{2,}/g, '_');
|
|
50518
|
+
if (base.length === 0)
|
|
50519
|
+
base = ENV_VAR_FALLBACK;
|
|
50520
|
+
if (/^[0-9]/.test(base))
|
|
50521
|
+
base = `KEY_${base}`;
|
|
50522
|
+
if (!ENV_VAR_WORDS.some((word) => base.split('_').includes(word)))
|
|
50523
|
+
base = `${base}_KEY`;
|
|
50524
|
+
if (isReservedEnvVar(base))
|
|
50525
|
+
base = `KEY_${base}`;
|
|
50526
|
+
base = trimChar(base.slice(0, ENV_VAR_DERIVED_MAX_LENGTH), '_');
|
|
50527
|
+
const taken = new Set(((_a = options.taken) !== null && _a !== void 0 ? _a : []).map((entry) => entry.toUpperCase()));
|
|
50528
|
+
if (!taken.has(base))
|
|
50529
|
+
return base;
|
|
50530
|
+
for (let suffix = 2;; suffix += 1) {
|
|
50531
|
+
const candidate = `${base}_${suffix}`;
|
|
50532
|
+
if (!taken.has(candidate))
|
|
50533
|
+
return candidate;
|
|
50534
|
+
}
|
|
50535
|
+
}
|
|
50536
|
+
function validateSecretEnvVar(value, options = {}) {
|
|
50537
|
+
var _a;
|
|
50538
|
+
const entry = value.trim();
|
|
50539
|
+
if (entry.length === 0)
|
|
50540
|
+
return 'required';
|
|
50541
|
+
if (!VIRTUAL_MACHINE_ENV_VAR_PATTERN.test(entry))
|
|
50542
|
+
return 'format';
|
|
50543
|
+
if (entry.length > VIRTUAL_MACHINE_ENV_VAR_MAX_LENGTH)
|
|
50544
|
+
return 'too_long';
|
|
50545
|
+
if (isReservedEnvVar(entry))
|
|
50546
|
+
return 'reserved';
|
|
50547
|
+
const upper = entry.toUpperCase();
|
|
50548
|
+
if (((_a = options.taken) !== null && _a !== void 0 ? _a : []).some((taken) => taken.toUpperCase() === upper))
|
|
50549
|
+
return 'taken';
|
|
50550
|
+
return null;
|
|
50551
|
+
}
|
|
50552
|
+
/**
|
|
50553
|
+
* The backend refuses a duplicate variable with a plain-string 400
|
|
50554
|
+
* (`"ACME_KEY already exists for this organization."`), not a field error,
|
|
50555
|
+
* so the form has to recognise it to put the message under the right field.
|
|
50556
|
+
*/
|
|
50557
|
+
function isSecretEnvVarTakenMessage(message) {
|
|
50558
|
+
return /already exists/i.test(message !== null && message !== void 0 ? message : '');
|
|
50559
|
+
}
|
|
50274
50560
|
|
|
50275
50561
|
const mentorReducer = {
|
|
50276
50562
|
[mentorApiSlice.reducerPath]: mentorApiSlice.reducer,
|
|
@@ -50637,8 +50923,10 @@ exports.USER_PROGRESS_DATA_POINTS = USER_PROGRESS_DATA_POINTS;
|
|
|
50637
50923
|
exports.USER_PROGRESS_SUMMARY_TYPE = USER_PROGRESS_SUMMARY_TYPE;
|
|
50638
50924
|
exports.VERCEL_SPA = VERCEL_SPA;
|
|
50639
50925
|
exports.VIRTUAL_MACHINE_DEFAULT_BILLING = VIRTUAL_MACHINE_DEFAULT_BILLING;
|
|
50926
|
+
exports.VIRTUAL_MACHINE_DEFAULT_HOST_PORT = VIRTUAL_MACHINE_DEFAULT_HOST_PORT;
|
|
50640
50927
|
exports.VIRTUAL_MACHINE_EGRESS_PROFILES = VIRTUAL_MACHINE_EGRESS_PROFILES;
|
|
50641
50928
|
exports.VIRTUAL_MACHINE_ENDPOINTS = VIRTUAL_MACHINE_ENDPOINTS;
|
|
50929
|
+
exports.VIRTUAL_MACHINE_ENV_VAR_MAX_LENGTH = VIRTUAL_MACHINE_ENV_VAR_MAX_LENGTH;
|
|
50642
50930
|
exports.VIRTUAL_MACHINE_ENV_VAR_PATTERN = VIRTUAL_MACHINE_ENV_VAR_PATTERN;
|
|
50643
50931
|
exports.VIRTUAL_MACHINE_HOST_PORT_PATTERN = VIRTUAL_MACHINE_HOST_PORT_PATTERN;
|
|
50644
50932
|
exports.VIRTUAL_MACHINE_MAX_POLICY_HOSTS = VIRTUAL_MACHINE_MAX_POLICY_HOSTS;
|
|
@@ -50648,6 +50936,8 @@ exports.VIRTUAL_MACHINE_QUERY_KEYS = VIRTUAL_MACHINE_QUERY_KEYS;
|
|
|
50648
50936
|
exports.VIRTUAL_MACHINE_REDUCER_PATH = VIRTUAL_MACHINE_REDUCER_PATH;
|
|
50649
50937
|
exports.VIRTUAL_MACHINE_REJECTED_HOSTS = VIRTUAL_MACHINE_REJECTED_HOSTS;
|
|
50650
50938
|
exports.VIRTUAL_MACHINE_REJECTED_HOST_SUFFIXES = VIRTUAL_MACHINE_REJECTED_HOST_SUFFIXES;
|
|
50939
|
+
exports.VIRTUAL_MACHINE_RESERVED_ENV_VARS = VIRTUAL_MACHINE_RESERVED_ENV_VARS;
|
|
50940
|
+
exports.VIRTUAL_MACHINE_RESERVED_ENV_VAR_PREFIXES = VIRTUAL_MACHINE_RESERVED_ENV_VAR_PREFIXES;
|
|
50651
50941
|
exports.VIRTUAL_MACHINE_SECRET_VALUE_MIN_LENGTH = VIRTUAL_MACHINE_SECRET_VALUE_MIN_LENGTH;
|
|
50652
50942
|
exports.WATCHED_GROUPS_ENDPOINTS = WATCHED_GROUPS_ENDPOINTS;
|
|
50653
50943
|
exports.WATCHED_GROUPS_QUERY_KEYS = WATCHED_GROUPS_QUERY_KEYS;
|
|
@@ -50697,6 +50987,7 @@ exports.credentialsCustomApiSlice = credentialsCustomApiSlice;
|
|
|
50697
50987
|
exports.customAiSearchApiSlice = customAiSearchApiSlice;
|
|
50698
50988
|
exports.customDomainApiSlice = customDomainApiSlice;
|
|
50699
50989
|
exports.datasetsApiSlice = datasetsApiSlice;
|
|
50990
|
+
exports.deriveSecretEnvVar = deriveSecretEnvVar;
|
|
50700
50991
|
exports.disclaimersApiSlice = disclaimersApiSlice;
|
|
50701
50992
|
exports.edxProctoringApiSlice = edxProctoringApiSlice;
|
|
50702
50993
|
exports.edxSsoApiSlice = edxSsoApiSlice;
|
|
@@ -50715,6 +51006,7 @@ exports.filterSlashSkills = filterSlashSkills;
|
|
|
50715
51006
|
exports.findResumeBlock = findResumeBlock;
|
|
50716
51007
|
exports.findUncoveredSecretHosts = findUncoveredSecretHosts;
|
|
50717
51008
|
exports.flattenOutline = flattenOutline;
|
|
51009
|
+
exports.formatHostPort = formatHostPort;
|
|
50718
51010
|
exports.getNextRecentMessagesPageParam = getNextRecentMessagesPageParam;
|
|
50719
51011
|
exports.getSections = getSections;
|
|
50720
51012
|
exports.getSpendCapExceededError = getSpendCapExceededError;
|
|
@@ -50731,6 +51023,8 @@ exports.isPoliciesResponse = isPoliciesResponse;
|
|
|
50731
51023
|
exports.isPrivacyBlockedError = isPrivacyBlockedError;
|
|
50732
51024
|
exports.isRejectedHostname = isRejectedHostname;
|
|
50733
51025
|
exports.isRejectedIpAddress = isRejectedIpAddress;
|
|
51026
|
+
exports.isReservedEnvVar = isReservedEnvVar;
|
|
51027
|
+
exports.isSecretEnvVarTakenMessage = isSecretEnvVarTakenMessage;
|
|
50734
51028
|
exports.isSpendCapExceededErrorBody = isSpendCapExceededErrorBody;
|
|
50735
51029
|
exports.isUserLlmUsageEmpty = isUserLlmUsageEmpty;
|
|
50736
51030
|
exports.isValidHostPort = isValidHostPort;
|
|
@@ -50748,6 +51042,7 @@ exports.mentorReducer = mentorReducer;
|
|
|
50748
51042
|
exports.moderationLogsApiReducer = moderationLogsApiReducer;
|
|
50749
51043
|
exports.moderationLogsApiSlice = moderationLogsApiSlice;
|
|
50750
51044
|
exports.monetizationApiSlice = monetizationApiSlice;
|
|
51045
|
+
exports.normalizeHostInput = normalizeHostInput;
|
|
50751
51046
|
exports.normalizeHostPort = normalizeHostPort;
|
|
50752
51047
|
exports.normalizeLearnerCompletionError = normalizeLearnerCompletionError;
|
|
50753
51048
|
exports.normalizeOutline = normalizeOutline;
|
|
@@ -51595,6 +51890,7 @@ exports.useUpdateGlobalMemoryMutation = useUpdateGlobalMemoryMutation;
|
|
|
51595
51890
|
exports.useUpdateGraderCriterionMutation = useUpdateGraderCriterionMutation;
|
|
51596
51891
|
exports.useUpdateHostingDomainMutation = useUpdateHostingDomainMutation;
|
|
51597
51892
|
exports.useUpdateIntegrationCredentialMutation = useUpdateIntegrationCredentialMutation;
|
|
51893
|
+
exports.useUpdateLLMCredentialMutation = useUpdateLLMCredentialMutation;
|
|
51598
51894
|
exports.useUpdateLtiKeyMutation = useUpdateLtiKeyMutation;
|
|
51599
51895
|
exports.useUpdateLtiMentorMutation = useUpdateLtiMentorMutation;
|
|
51600
51896
|
exports.useUpdateLtiToolMutation = useUpdateLtiToolMutation;
|
|
@@ -51681,6 +51977,7 @@ exports.userInvitationsApiSlice = userInvitationsApiSlice;
|
|
|
51681
51977
|
exports.userLlmUsageApiSlice = userLlmUsageApiSlice;
|
|
51682
51978
|
exports.validateHostPort = validateHostPort;
|
|
51683
51979
|
exports.validateLearnerCompletionArgs = validateLearnerCompletionArgs;
|
|
51980
|
+
exports.validateSecretEnvVar = validateSecretEnvVar;
|
|
51684
51981
|
exports.validateUserLlmUsageParams = validateUserLlmUsageParams;
|
|
51685
51982
|
exports.virtualMachineApiSlice = virtualMachineApiSlice;
|
|
51686
51983
|
exports.watchedGroupsApiSlice = watchedGroupsApiSlice;
|