@meshmakers/octo-services 3.4.1450 → 3.4.1490

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.
@@ -1,14 +1,14 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { inject, Injector, Injectable, InjectionToken, NgModule, makeEnvironmentProviders } from '@angular/core';
3
3
  import { onError } from '@apollo/client/link/error';
4
- import { MessageService, DataSourceBase, PagedResultDto, provideMmSharedServices } from '@meshmakers/shared-services';
4
+ import { MessageService, MM_CALLER_HANDLED_STATUSES, DataSourceBase, PagedResultDto, provideMmSharedServices } from '@meshmakers/shared-services';
5
5
  import { ApolloLink, InMemoryCache } from '@apollo/client/core';
6
6
  import { CombinedGraphQLErrors } from '@apollo/client';
7
7
  import * as i1 from 'apollo-angular';
8
8
  import { gql } from 'apollo-angular';
9
9
  import { map, catchError, finalize } from 'rxjs/operators';
10
10
  import { of, firstValueFrom, map as map$1, Subject, throwError, from, filter } from 'rxjs';
11
- import { HttpClient, HttpParams, HttpErrorResponse, HttpHeaders } from '@angular/common/http';
11
+ import { HttpClient, HttpParams, HttpErrorResponse, HttpContext, HttpHeaders } from '@angular/common/http';
12
12
  import { Upload } from 'tus-js-client';
13
13
  import { AuthorizeService } from '@meshmakers/shared-auth';
14
14
 
@@ -21,6 +21,12 @@ class OctoServiceOptions {
21
21
  }
22
22
  }
23
23
 
24
+ /**
25
+ * Operation context flag: errors of an operation with `context: { [OCTO_SILENT_ERRORS]: true }`
26
+ * are logged to the console only, never shown as a toast. For best-effort background reads whose
27
+ * caller handles the failure itself (e.g. the Settings counts, AB#5523).
28
+ */
29
+ const OCTO_SILENT_ERRORS = 'octoSilentErrors';
24
30
  class OctoErrorLink extends ApolloLink {
25
31
  errorLink;
26
32
  injector = inject(Injector);
@@ -28,8 +34,12 @@ class OctoErrorLink extends ApolloLink {
28
34
  super();
29
35
  // There is currently no other way to inject a service into an Apollo Link,
30
36
  // because Apollo deprecated without replacement
31
- this.errorLink = onError(({ error }) => {
37
+ this.errorLink = onError(({ error, operation }) => {
32
38
  if (error) {
39
+ if (OctoErrorLink.isSilent(operation)) {
40
+ console.warn(`GraphQL error in ${operation?.operationName ?? 'operation'} (not shown)`, error);
41
+ return;
42
+ }
33
43
  if (error instanceof CombinedGraphQLErrors) {
34
44
  this.showError(error);
35
45
  }
@@ -43,6 +53,15 @@ class OctoErrorLink extends ApolloLink {
43
53
  // lets the original error propagate to the caller's own error handling.
44
54
  });
45
55
  }
56
+ /** True when the operation opted out of error toasts ({@link OCTO_SILENT_ERRORS}). */
57
+ static isSilent(operation) {
58
+ try {
59
+ return operation?.getContext?.()?.[OCTO_SILENT_ERRORS] === true;
60
+ }
61
+ catch {
62
+ return false;
63
+ }
64
+ }
46
65
  showErrorLike(error) {
47
66
  // Network connectivity errors (HTTP status 0) are already handled by MmHttpErrorInterceptor
48
67
  // which either shows the connection error overlay (via ON_CONNECTION_LOST) or a toast.
@@ -200,6 +219,258 @@ class LevelMetaData {
200
219
  }
201
220
  }
202
221
 
222
+ /**
223
+ * SECRET value type (AB#5528) — frontend contract types and helpers (AB#5542).
224
+ *
225
+ * Contract: `octo-construction-kit-engine/docs/secret-frontend-handover.md` §2 (asset repository
226
+ * GraphQL) and §4/§8 (identity providers REST). Field names are binding.
227
+ *
228
+ * The generated `globalTypes.ts` carries the SECRET round-2 schema (`OctoSecretStateDto { isSet
229
+ * keyMissing setAt }`, `secretIsSet` / `secretKeyMissing` / `secretSetAt`, `clearSecretAttributes`,
230
+ * `Query.secrets`). The shapes below accept the generated DTOs structurally; `keyMissing` / `setAt`
231
+ * stay optional so documents (or older backends) without them still map, and `setAt` accepts the
232
+ * ISO string Apollo actually delivers as well as a `Date`.
233
+ *
234
+ * Rules (decisions 2026-10-06):
235
+ * - A secret is never read. Typed fields select `{ isSet keyMissing setAt }`, generic attribute
236
+ * lists select `secretIsSet secretKeyMissing secretSetAt` (`value` is always null for secrets).
237
+ * - Input: a non-empty string sets / rotates; omitted, `null` or `""` keeps the stored value.
238
+ * Clearing is explicit: the camelCase name goes into `clearSecretAttributes` (only optional
239
+ * secrets; a new value and a clear for the same field in one request are rejected).
240
+ * - Placeholders (`<…>`, `TODO_SET_*`) have no meaning — they are ordinary values.
241
+ * - `keyMissing` (value stored, key id unknown in this environment) reads as `isSet: false` for
242
+ * consumers; the UI shows "Key missing — re-enter".
243
+ */
244
+ /** The CK value type name of a secret attribute as reported by the CK model API (`AttributeValueTypesDto.Secret = 17`). */
245
+ const SECRET_VALUE_TYPE = 'SECRET';
246
+ /** Whether a CK value type is the SECRET value type (case-insensitive). */
247
+ function isSecretValueType(valueType) {
248
+ return !!valueType && valueType.toUpperCase() === SECRET_VALUE_TYPE;
249
+ }
250
+ function toDate(value) {
251
+ if (!value)
252
+ return null;
253
+ const d = value instanceof Date ? value : new Date(value);
254
+ return Number.isNaN(d.getTime()) ? null : d;
255
+ }
256
+ /** Normalises a typed `OctoSecretState` (null/undefined = not set). */
257
+ function toSecretState(state) {
258
+ return {
259
+ isSet: state?.isSet === true,
260
+ keyMissing: state?.keyMissing === true,
261
+ setAt: toDate(state?.setAt),
262
+ };
263
+ }
264
+ /**
265
+ * The secret state of a generic attribute, or `null` when the attribute is not a secret
266
+ * (`secretIsSet` is null for every non-secret attribute).
267
+ */
268
+ function secretStateFromAttribute(attribute) {
269
+ if (!attribute || (attribute.secretIsSet !== true && attribute.secretIsSet !== false))
270
+ return null;
271
+ return {
272
+ isSet: attribute.secretIsSet,
273
+ keyMissing: attribute.secretKeyMissing === true,
274
+ setAt: toDate(attribute.secretSetAt),
275
+ };
276
+ }
277
+ /**
278
+ * Whether a value is a secret state object (`{ isSet }` marker or a {@link SecretState}) rather than
279
+ * a plain value — e.g. a SECRET record member read through the generic API. Only objects whose keys
280
+ * are a subset of `isSet` / `keyMissing` / `setAt` with a boolean `isSet` qualify.
281
+ */
282
+ function isSecretStateObject(value) {
283
+ if (!value || typeof value !== 'object' || Array.isArray(value) || value instanceof Date)
284
+ return false;
285
+ const record = value;
286
+ return typeof record['isSet'] === 'boolean'
287
+ && Object.keys(record).every((k) => k === 'isSet' || k === 'keyMissing' || k === 'setAt' || k === '__typename');
288
+ }
289
+ /** Display status: key missing wins (it implies `isSet: false`), then set / not set. */
290
+ function secretStatusOf(state) {
291
+ if (state?.keyMissing)
292
+ return 'keyMissing';
293
+ return state?.isSet ? 'set' : 'notSet';
294
+ }
295
+ /**
296
+ * Whether a secret counts as present for "required" checks: set, or stored but unreadable (the
297
+ * server treats a key-missing secret as present, handover §2).
298
+ */
299
+ function isSecretPresent(state) {
300
+ return state?.isSet === true || state?.keyMissing === true;
301
+ }
302
+ /**
303
+ * The wire value of a typed secret input: the string when the user typed one, else `undefined`
304
+ * (= omit = keep). Never trims — whitespace can be part of a secret.
305
+ */
306
+ function secretInputValue(typed) {
307
+ return typeof typed === 'string' && typed.length > 0 ? typed : undefined;
308
+ }
309
+ const DEFAULT_SECRET_STATUS_LABELS = {
310
+ set: 'Set',
311
+ setAt: 'Set · set at {setAt}',
312
+ notSet: 'Not set',
313
+ keyMissing: 'Key missing — re-enter',
314
+ };
315
+ /**
316
+ * Human-readable status: "Set · set at …" / "Set" (legacy, no timestamp) / "Not set" /
317
+ * "Key missing — re-enter".
318
+ */
319
+ function formatSecretStatus(state, formatDate = (d) => d.toLocaleString(), labels = DEFAULT_SECRET_STATUS_LABELS) {
320
+ switch (secretStatusOf(state)) {
321
+ case 'keyMissing':
322
+ return labels.keyMissing;
323
+ case 'set':
324
+ return state?.setAt ? labels.setAt.replace('{setAt}', formatDate(state.setAt)) : labels.set;
325
+ default:
326
+ return labels.notSet;
327
+ }
328
+ }
329
+
330
+ /**
331
+ * Secret-safe attribute selection for generic runtime GraphQL documents (AB#5542).
332
+ *
333
+ * The generic `attributes` field of `RtEntity` / `RtAssociation` returns EVERY attribute of the
334
+ * entity — passwords, client secrets, API keys included — when its `attributeNames` argument is
335
+ * omitted (or bound to a variable the caller leaves `undefined`). Until the SECRET value type
336
+ * (AB#5528) lets the server mask those values, every generic document must pass an explicit,
337
+ * non-nullable list, and callers that derive the list from CK metadata must leave out
338
+ * credential-like attributes. These helpers are that rule in one place:
339
+ *
340
+ * - {@link isCredentialLikeAttributeName}: the name heuristic (suffix based, camelCase or PascalCase).
341
+ * - {@link isSecretAttributeCandidate}: THE rule — explicit decision, `secret` CK metadata, else the
342
+ * name heuristic for textual value types only.
343
+ * - {@link toAttributeNameFilter}: name-only list for read-only callers without type information.
344
+ * - {@link toUniqueCamelCaseNames}: camelCase + de-duplication for type-aware callers.
345
+ * The server compares camelCase names only, and one list also filters the sub-attributes of records.
346
+ *
347
+ * SECRET value type (AB#5528): an attribute whose value type is `SECRET` is ALWAYS a secret — no
348
+ * explicit decision or metadata can opt it out. The server never projects its value (`value` is
349
+ * null, `secretIsSet` / `{ isSet }` report the state, see `secret-state.ts`). The metadata marker
350
+ * and the name heuristic remain only as the FALLBACK for non-SECRET attributes (models that have
351
+ * not switched their credentials to SECRET yet, handover note §1 phase 2 before phase 3).
352
+ */
353
+ /**
354
+ * Credential-like name suffixes (lower case). Matched against the END of the attribute name so
355
+ * that `password`, `adminPassword`, `privateKeyPassphrase`, `clientSecret`, `botToken`,
356
+ * `refreshToken`, `apiKey`, `secretKey`, `connectionString` match, while `maxTokens`,
357
+ * `tokensPerDay`, `tokenEndpoint` or `receivesClusterSecrets` do not.
358
+ */
359
+ const CREDENTIAL_ATTRIBUTE_NAME_SUFFIXES = [
360
+ 'password',
361
+ 'passphrase',
362
+ 'secret',
363
+ 'secretkey',
364
+ 'token',
365
+ 'apikey',
366
+ 'privatekey',
367
+ 'connectionstring',
368
+ 'credential',
369
+ 'credentials',
370
+ 'encryptedvalue',
371
+ ];
372
+ /** CK value types that can carry a credential (anything textual). */
373
+ const TEXTUAL_VALUE_TYPES = new Set(['STRING', 'STRING_ARRAY']);
374
+ /** Lower-cases the first character, like the server's `ToCamelCase` used by the `attributeNames` filter. */
375
+ function toCamelCaseAttributeName(name) {
376
+ return name.length === 0 ? name : name.charAt(0).toLowerCase() + name.slice(1);
377
+ }
378
+ /** Whether an attribute name looks like a credential (password, secret, token, API key, …). */
379
+ function isCredentialLikeAttributeName(name) {
380
+ if (!name)
381
+ return false;
382
+ const normalised = name.replace(/[^a-zA-Z0-9]/g, '').toLowerCase();
383
+ return CREDENTIAL_ATTRIBUTE_NAME_SUFFIXES.some((suffix) => normalised.endsWith(suffix));
384
+ }
385
+ /** Whether a CK value type can hold a credential (textual). `undefined` (unknown) counts as textual. */
386
+ function isTextualValueType(valueType) {
387
+ return !valueType || TEXTUAL_VALUE_TYPES.has(valueType.toUpperCase());
388
+ }
389
+ /**
390
+ * THE credential rule of the frontend (AB#5542; entity forms, runtime browser, meshboard, Data
391
+ * Explorer all use it). An attribute is a secret candidate when
392
+ * 0. its value type is `SECRET` (always; cannot be opted out), else
393
+ * 1. the caller decided explicitly (`secret: true|false`, e.g. form `Secret: false` opts out), else
394
+ * 2. its CK metadata says `secret: true|false`, else
395
+ * 3. it is TEXTUAL (`STRING`, `STRING_ARRAY`, unknown) and its name is credential-like
396
+ * ({@link isCredentialLikeAttributeName}). Non-textual attributes (`isSecret: BOOLEAN`,
397
+ * `maxTokens: INT`, a `credentials` RECORD) are never secrets by name.
398
+ */
399
+ function isSecretAttributeCandidate(attribute) {
400
+ if (isSecretValueType(attribute.attributeValueType))
401
+ return true;
402
+ if (attribute.secret === true || attribute.secret === false)
403
+ return attribute.secret;
404
+ const marker = (attribute.metaData ?? []).find((m) => !!m && m.key?.toLowerCase() === 'secret');
405
+ if (marker) {
406
+ const value = (marker.value ?? '').trim().toLowerCase();
407
+ if (value === 'true')
408
+ return true;
409
+ if (value === 'false')
410
+ return false;
411
+ }
412
+ if (!isTextualValueType(attribute.attributeValueType))
413
+ return false;
414
+ return isCredentialLikeAttributeName(attribute.attributeName);
415
+ }
416
+ /** camelCase, de-duplicated, without empty entries — no secret filtering (callers decided already). */
417
+ function toUniqueCamelCaseNames(names) {
418
+ const result = [];
419
+ const seen = new Set();
420
+ for (const name of names) {
421
+ if (!name)
422
+ continue;
423
+ const camel = toCamelCaseAttributeName(name);
424
+ if (seen.has(camel))
425
+ continue;
426
+ seen.add(camel);
427
+ result.push(camel);
428
+ }
429
+ return result;
430
+ }
431
+ /**
432
+ * Builds the value of an `attributeNames` argument from names WITHOUT type information (widget
433
+ * configuration, user-picked fields): camelCase, de-duplicated, without empty and credential-like
434
+ * names. Because the type is unknown, the name rule is applied conservatively — use it only for
435
+ * READ-ONLY displays. Anything that is written back must derive its list type-aware
436
+ * ({@link isSecretAttributeCandidate}, octo-ui `SecretSafeAttributeNamesService`), otherwise a
437
+ * dropped non-secret attribute (`isSecret: BOOLEAN`) would be saved back empty.
438
+ * Always returns an array, so a `[String!]!` variable can never fall back to "all attributes".
439
+ */
440
+ function toAttributeNameFilter(names) {
441
+ return toUniqueCamelCaseNames([...names].filter((name) => !isCredentialLikeAttributeName(name)));
442
+ }
443
+ /**
444
+ * Whether a query column (`attributePath` such as `password`, `endpoint.apiKey`,
445
+ * `parent->clientSecret`) is a secret candidate: its last path segment by the shared rule.
446
+ * Column pickers hide these so users cannot add credential columns to runtime queries
447
+ * (AB#5542 — query rows would project the value).
448
+ */
449
+ function isSecretQueryColumn(attributePath, attributeValueType) {
450
+ if (!attributePath)
451
+ return false;
452
+ const lastSegment = attributePath.split(/->|\.|\//).pop() ?? attributePath;
453
+ return isSecretAttributeCandidate({ attributeName: lastSegment, attributeValueType });
454
+ }
455
+
456
+ /**
457
+ * Bot services REST DTOs of the SECRET value type administration (AB#5528 / AB#5544, frontend
458
+ * handover §9). Mirror `Meshmakers.Octo.Communication.Contracts.DataTransferObjects`
459
+ * (`SecretEnvironmentStatusDto`, `SecretSweepRunDto`, `SecretSweepDumpDto`,
460
+ * `SecretFormCountsReportDto`); enums travel as names, JSON is camelCase, timestamps are ISO-8601
461
+ * strings. No DTO ever carries a secret value.
462
+ */
463
+ /** `SecretEnvironmentStatusDto.warnings` codes (handover §9/§14). */
464
+ const SECRET_STATUS_WARNING_NO_KEY_RING = 'NoKeyRing';
465
+ const SECRET_STATUS_WARNING_NO_LEGACY_V1_KEY = 'NoLegacyV1Key';
466
+ /** An existing encrypted dump's key id is not in the key ring: that dump cannot be restored (handover §14). */
467
+ const SECRET_STATUS_WARNING_DUMP_KEY_MISSING = 'DumpKeyMissing';
468
+ /** The pseudo key id of a legacy enc:v1 value (handover §10); shown as "legacy key (enc:v1)". */
469
+ const SECRET_LEGACY_V1_KEY_ID = 'enc:v1';
470
+ /** Error codes of the dump restore (`statusDescription` of the 409 body, handover §14). */
471
+ const SECRET_DUMP_RESTORE_ERROR_DUMP_DELETED = 'DumpDeleted';
472
+ const SECRET_DUMP_RESTORE_ERROR_DUMP_KEY_MISSING = 'DumpKeyMissing';
473
+
203
474
  var HealthStatus;
204
475
  (function (HealthStatus) {
205
476
  /*
@@ -358,6 +629,14 @@ var AssociationModOptionsDto;
358
629
  AssociationModOptionsDto["CreateDto"] = "CREATE";
359
630
  AssociationModOptionsDto["DeleteDto"] = "DELETE";
360
631
  })(AssociationModOptionsDto || (AssociationModOptionsDto = {}));
632
+ /** Who owns an attribute value, and therefore what installing the blueprint again does to it (AB#5187). SEED_OWNED: the blueprint owns the value - re-applying the blueprint OVERWRITES whatever the tenant has, and the value is carried in an exported runtime model. TENANT_OWNED: the tenant owns the value - re-applying the blueprint KEEPS the tenant's value and only seeds it on a fresh tenant, and the value IS still carried in an exported runtime model. RUNTIME_STATE: a service, operator, pipeline or job writes the value - re-applying the blueprint KEEPS it, and it is NOT carried in an exported runtime model. SECRET: a credential such as an API key, client secret, token or password - re-applying the blueprint KEEPS it, and it is NOT carried in an exported runtime model. */
633
+ var AttributeOwnershipDto;
634
+ (function (AttributeOwnershipDto) {
635
+ AttributeOwnershipDto["RuntimeStateDto"] = "RUNTIME_STATE";
636
+ AttributeOwnershipDto["SecretDto"] = "SECRET";
637
+ AttributeOwnershipDto["SeedOwnedDto"] = "SEED_OWNED";
638
+ AttributeOwnershipDto["TenantOwnedDto"] = "TENANT_OWNED";
639
+ })(AttributeOwnershipDto || (AttributeOwnershipDto = {}));
361
640
  /** Enum of valid attribute types */
362
641
  var AttributeValueTypeDto;
363
642
  (function (AttributeValueTypeDto) {
@@ -377,6 +656,7 @@ var AttributeValueTypeDto;
377
656
  AttributeValueTypeDto["IntArrayDto"] = "INT_ARRAY";
378
657
  AttributeValueTypeDto["RecordDto"] = "RECORD";
379
658
  AttributeValueTypeDto["RecordArrayDto"] = "RECORD_ARRAY";
659
+ AttributeValueTypeDto["SecretDto"] = "SECRET";
380
660
  AttributeValueTypeDto["StringDto"] = "STRING";
381
661
  AttributeValueTypeDto["StringArrayDto"] = "STRING_ARRAY";
382
662
  AttributeValueTypeDto["TimeSpanDto"] = "TIME_SPAN";
@@ -982,6 +1262,30 @@ var SearchFilterTypesDto;
982
1262
  SearchFilterTypesDto["AttributeFilterDto"] = "ATTRIBUTE_FILTER";
983
1263
  SearchFilterTypesDto["TextSearchDto"] = "TEXT_SEARCH";
984
1264
  })(SearchFilterTypesDto || (SearchFilterTypesDto = {}));
1265
+ /** Storage form of a secret value. Never the value. */
1266
+ var SecretStorageFormDto;
1267
+ (function (SecretStorageFormDto) {
1268
+ /** Stored value cannot be parsed (reads as not set, warning logged). */
1269
+ SecretStorageFormDto["CorruptDto"] = "CORRUPT";
1270
+ /** Legacy enc:v1 (instance key). */
1271
+ SecretStorageFormDto["EncV1Dto"] = "ENC_V1";
1272
+ /** Protected, key id known. */
1273
+ SecretStorageFormDto["EncV2Dto"] = "ENC_V2";
1274
+ /** Protected, key id not in this environment's key ring. */
1275
+ SecretStorageFormDto["KeyMissingDto"] = "KEY_MISSING";
1276
+ /** Null or missing. */
1277
+ SecretStorageFormDto["NotSetDto"] = "NOT_SET";
1278
+ /** Legacy clear text still stored (before the Encrypt sweep). */
1279
+ SecretStorageFormDto["PlaintextDto"] = "PLAINTEXT";
1280
+ })(SecretStorageFormDto || (SecretStorageFormDto = {}));
1281
+ /** How a RevealSecret@1 node refers to a secret. */
1282
+ var SecretUsageMatchDto;
1283
+ (function (SecretUsageMatchDto) {
1284
+ /** The node resolves the entity at run time (rtIdPath) on the same CK type and attribute. */
1285
+ SecretUsageMatchDto["ByTypeDto"] = "BY_TYPE";
1286
+ /** The node names the CK type, rtId and attribute of the secret. */
1287
+ SecretUsageMatchDto["ExactDto"] = "EXACT";
1288
+ })(SecretUsageMatchDto || (SecretUsageMatchDto = {}));
985
1289
  /** Civil-boundary policy for a series query that spans multiple reference time zones (AB#4190). */
986
1290
  var SeriesComparisonPolicyDto;
987
1291
  (function (SeriesComparisonPolicyDto) {
@@ -1490,6 +1794,14 @@ var SystemStreamDataCkComputedColumnStateDto;
1490
1794
  /** A backfill has been scheduled for this computed column but has not started yet. Consumers still see the previous archive state. */
1491
1795
  SystemStreamDataCkComputedColumnStateDto["PendingDto"] = "PENDING";
1492
1796
  })(SystemStreamDataCkComputedColumnStateDto || (SystemStreamDataCkComputedColumnStateDto = {}));
1797
+ /** Runtime entities of construction kit enum 'System.StreamData/CkConflictKeyOrder' */
1798
+ var SystemStreamDataCkConflictKeyOrderDto;
1799
+ (function (SystemStreamDataCkConflictKeyOrderDto) {
1800
+ /** The greater value is the better one. Use for timestamps, sequence numbers and versions, where later or higher supersedes earlier. */
1801
+ SystemStreamDataCkConflictKeyOrderDto["HigherWinsDto"] = "HIGHER_WINS";
1802
+ /** The smaller value is the better one. Use for rank-like codes numbered best-first, where a lower code must never be displaced by a higher one. */
1803
+ SystemStreamDataCkConflictKeyOrderDto["LowerWinsDto"] = "LOWER_WINS";
1804
+ })(SystemStreamDataCkConflictKeyOrderDto || (SystemStreamDataCkConflictKeyOrderDto = {}));
1493
1805
  /** Runtime entities of construction kit enum 'System.StreamData/CkRecomputeChangeKind' */
1494
1806
  var SystemStreamDataCkRecomputeChangeKindDto;
1495
1807
  (function (SystemStreamDataCkRecomputeChangeKindDto) {
@@ -1752,6 +2064,7 @@ const result = {
1752
2064
  "SystemUIBranding",
1753
2065
  "SystemUIDashboard",
1754
2066
  "SystemUIDashboardWidget",
2067
+ "SystemUIEntityForm",
1755
2068
  "SystemUIMappingCoverageConfiguration",
1756
2069
  "SystemUIProcessDiagram",
1757
2070
  "SystemUISymbolDefinition",
@@ -2116,6 +2429,7 @@ const result = {
2116
2429
  "SystemUIBranding",
2117
2430
  "SystemUIDashboard",
2118
2431
  "SystemUIDashboardWidget",
2432
+ "SystemUIEntityForm",
2119
2433
  "SystemUIMappingCoverageConfiguration",
2120
2434
  "SystemUIProcessDiagram",
2121
2435
  "SystemUISymbolDefinition",
@@ -2585,6 +2899,7 @@ const result = {
2585
2899
  "SystemUIBranding",
2586
2900
  "SystemUIDashboard",
2587
2901
  "SystemUIDashboardWidget",
2902
+ "SystemUIEntityForm",
2588
2903
  "SystemUIMappingCoverageConfiguration",
2589
2904
  "SystemUIProcessDiagram",
2590
2905
  "SystemUISymbolDefinition",
@@ -2758,6 +3073,7 @@ const result = {
2758
3073
  "SystemUIBranding",
2759
3074
  "SystemUIDashboard",
2760
3075
  "SystemUIDashboardWidget",
3076
+ "SystemUIEntityForm",
2761
3077
  "SystemUIMappingCoverageConfiguration",
2762
3078
  "SystemUIProcessDiagram",
2763
3079
  "SystemUISymbolDefinition",
@@ -2930,6 +3246,7 @@ const result = {
2930
3246
  "SystemUIBranding",
2931
3247
  "SystemUIDashboard",
2932
3248
  "SystemUIDashboardWidget",
3249
+ "SystemUIEntityForm",
2933
3250
  "SystemUIMappingCoverageConfiguration",
2934
3251
  "SystemUIProcessDiagram",
2935
3252
  "SystemUISymbolDefinition",
@@ -3102,6 +3419,7 @@ const result = {
3102
3419
  "SystemUIBranding",
3103
3420
  "SystemUIDashboard",
3104
3421
  "SystemUIDashboardWidget",
3422
+ "SystemUIEntityForm",
3105
3423
  "SystemUIMappingCoverageConfiguration",
3106
3424
  "SystemUIProcessDiagram",
3107
3425
  "SystemUISymbolDefinition",
@@ -3274,6 +3592,7 @@ const result = {
3274
3592
  "SystemUIBranding",
3275
3593
  "SystemUIDashboard",
3276
3594
  "SystemUIDashboardWidget",
3595
+ "SystemUIEntityForm",
3277
3596
  "SystemUIMappingCoverageConfiguration",
3278
3597
  "SystemUIProcessDiagram",
3279
3598
  "SystemUISymbolDefinition",
@@ -3446,6 +3765,7 @@ const result = {
3446
3765
  "SystemUIBranding",
3447
3766
  "SystemUIDashboard",
3448
3767
  "SystemUIDashboardWidget",
3768
+ "SystemUIEntityForm",
3449
3769
  "SystemUIMappingCoverageConfiguration",
3450
3770
  "SystemUIProcessDiagram",
3451
3771
  "SystemUISymbolDefinition",
@@ -3618,6 +3938,7 @@ const result = {
3618
3938
  "SystemUIBranding",
3619
3939
  "SystemUIDashboard",
3620
3940
  "SystemUIDashboardWidget",
3941
+ "SystemUIEntityForm",
3621
3942
  "SystemUIMappingCoverageConfiguration",
3622
3943
  "SystemUIProcessDiagram",
3623
3944
  "SystemUISymbolDefinition",
@@ -3739,6 +4060,7 @@ const result = {
3739
4060
  "SystemUIBranding",
3740
4061
  "SystemUIDashboard",
3741
4062
  "SystemUIDashboardWidget",
4063
+ "SystemUIEntityForm",
3742
4064
  "SystemUIMappingCoverageConfiguration",
3743
4065
  "SystemUIProcessDiagram",
3744
4066
  "SystemUISymbolDefinition",
@@ -4039,8 +4361,12 @@ class AttributeSelectorService {
4039
4361
  if (!type) {
4040
4362
  return { items: [], totalCount: 0 };
4041
4363
  }
4042
- const items = (type.availableQueryColumns?.items || [])
4043
- .filter((item) => item !== null)
4364
+ const all = (type.availableQueryColumns?.items || [])
4365
+ .filter((item) => item !== null);
4366
+ // Credential columns are never offered (SECRET-safe, AB#5542): a runtime query row would
4367
+ // project their value in clear text.
4368
+ const items = all
4369
+ .filter(item => !isSecretQueryColumn(item.attributePath, item.attributeValueType))
4044
4370
  .map(item => ({
4045
4371
  attributePath: item.attributePath,
4046
4372
  attributeValueType: item.attributeValueType,
@@ -4048,7 +4374,7 @@ class AttributeSelectorService {
4048
4374
  }));
4049
4375
  return {
4050
4376
  items,
4051
- totalCount: type.availableQueryColumns?.totalCount || 0
4377
+ totalCount: Math.max(0, (type.availableQueryColumns?.totalCount || 0) - (all.length - items.length))
4052
4378
  };
4053
4379
  }));
4054
4380
  }
@@ -5009,6 +5335,169 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
5009
5335
  }]
5010
5336
  }] });
5011
5337
 
5338
+ /**
5339
+ * Bot services REST client of the SECRET value type administration (AB#5528 / AB#5544, frontend
5340
+ * handover §9): environment encryption status, tenant secret sweeps and their pre-sweep dumps.
5341
+ * Like {@link BotService}, every call takes the tenant explicitly and addresses
5342
+ * `{botServices}{tenantId}/v1/...`. Methods return `null` when the bot service URL is not
5343
+ * configured; HTTP errors (403 missing role, 400 `ConfirmationRequired`) are rethrown as
5344
+ * `HttpErrorResponse` for the caller.
5345
+ *
5346
+ * Roles (handover §6, §14): status — any user with tenant access; sweep runs — `AdminPanelManagement`;
5347
+ * starting a sweep, deleting a dump and restoring a dump — `SecretManagement`.
5348
+ *
5349
+ * Tenant (handover §13, §14): the `{tenantId}/v1/secrets/...` routes (status, sweep runs, dump
5350
+ * delete, dump restore) accept only the token's OWN tenant — always pass the current tenant, never a child tenant
5351
+ * (child-tenant links only navigate into that tenant). A restore appears as a run with
5352
+ * `trigger: Restore`, mode `Encrypt` and `dump: null`.
5353
+ */
5354
+ class BotSecretsService {
5355
+ httpClient = inject(HttpClient);
5356
+ configurationService = inject(CONFIGURATION_SERVICE);
5357
+ baseUrl(tenantId) {
5358
+ const botServicesUrl = this.configurationService.config?.botServices;
5359
+ return botServicesUrl ? `${botServicesUrl}${tenantId}/v1/` : null;
5360
+ }
5361
+ /** `GET {tenantId}/v1/secrets/status` — environment-level, identical in every tenant. */
5362
+ async getSecretEnvironmentStatus(tenantId) {
5363
+ const baseUrl = this.baseUrl(tenantId);
5364
+ if (!baseUrl)
5365
+ return null;
5366
+ return firstValueFrom(this.httpClient.get(`${baseUrl}secrets/status`));
5367
+ }
5368
+ /**
5369
+ * `POST {tenantId}/v1/jobs/secret-sweep?mode=&confirm=` — Encrypt and CleanupUnreadable need
5370
+ * `confirm = true` (the server answers `400 ConfirmationRequired` otherwise and takes a
5371
+ * pre-sweep dump first). Role `SecretManagement`.
5372
+ */
5373
+ async startSecretSweep(tenantId, mode, confirm = false) {
5374
+ const baseUrl = this.baseUrl(tenantId);
5375
+ if (!baseUrl)
5376
+ return null;
5377
+ let params = new HttpParams().set('mode', mode);
5378
+ if (confirm) {
5379
+ params = params.set('confirm', true);
5380
+ }
5381
+ return firstValueFrom(this.httpClient.post(`${baseUrl}jobs/secret-sweep`, null, { params }));
5382
+ }
5383
+ /**
5384
+ * `GET {tenantId}/v1/jobs/secret-sweep/report` — the last sweep report of the tenant (counts,
5385
+ * unreadable / cleared references, never values); `null` when there is none (`404`) or the bot
5386
+ * service URL is not configured. Role `AdminPanelManagement`.
5387
+ */
5388
+ async getSecretSweepReport(tenantId) {
5389
+ const baseUrl = this.baseUrl(tenantId);
5390
+ if (!baseUrl)
5391
+ return null;
5392
+ try {
5393
+ return await firstValueFrom(this.httpClient.get(`${baseUrl}jobs/secret-sweep/report`));
5394
+ }
5395
+ catch (error) {
5396
+ if (error instanceof HttpErrorResponse && error.status === 404)
5397
+ return null;
5398
+ throw error;
5399
+ }
5400
+ }
5401
+ /**
5402
+ * `GET {tenantId}/v1/secrets/sweep-runs?limit=` — newest first. Role `AdminPanelManagement`.
5403
+ * A `403` is rethrown WITHOUT the global "Access denied" toast (`MM_CALLER_HANDLED_STATUSES`): the
5404
+ * caller explains it in place.
5405
+ */
5406
+ async getSecretSweepRuns(tenantId, limit = 20) {
5407
+ const baseUrl = this.baseUrl(tenantId);
5408
+ if (!baseUrl)
5409
+ return null;
5410
+ const params = new HttpParams().set('limit', limit);
5411
+ const context = new HttpContext().set(MM_CALLER_HANDLED_STATUSES, [403]);
5412
+ return (await firstValueFrom(this.httpClient.get(`${baseUrl}secrets/sweep-runs`, { params, context }))) ?? [];
5413
+ }
5414
+ /**
5415
+ * `DELETE {tenantId}/v1/secrets/sweep-runs/{runId}/dump` — deletes a pre-sweep dump before it
5416
+ * expires. `404` (unknown run / no dump) and `409` (already deleted) map to a result instead of an
5417
+ * error; other errors (e.g. `403` without `SecretManagement`) are rethrown.
5418
+ */
5419
+ async deleteSecretSweepDump(tenantId, runId) {
5420
+ const baseUrl = this.baseUrl(tenantId);
5421
+ if (!baseUrl)
5422
+ return null;
5423
+ try {
5424
+ await firstValueFrom(this.httpClient.delete(`${baseUrl}secrets/sweep-runs/${encodeURIComponent(runId)}/dump`));
5425
+ return 'Deleted';
5426
+ }
5427
+ catch (error) {
5428
+ if (error instanceof HttpErrorResponse && error.status === 404)
5429
+ return 'NotFound';
5430
+ if (error instanceof HttpErrorResponse && error.status === 409)
5431
+ return 'AlreadyDeleted';
5432
+ throw error;
5433
+ }
5434
+ }
5435
+ /**
5436
+ * `POST {tenantId}/v1/secrets/sweep-runs/{runId}/restore-dump?confirm=` (handover §14, AB#5559) —
5437
+ * restores the run's pre-sweep dump into the tenant (replaces the tenant database, then a Verify
5438
+ * runs). Role `SecretManagement`, own tenant only; `confirm = true` only after the user confirmed.
5439
+ * 🔴 A dump taken before the first Encrypt holds plaintext secrets: restoring it brings them back.
5440
+ *
5441
+ * Every documented answer (200 / 400 / 403 / 404 / 409) is mapped to a
5442
+ * {@link SecretSweepDumpRestoreResult} and kept away from the global error toast
5443
+ * (`MM_CALLER_HANDLED_STATUSES`); other errors (network, 5xx) are rethrown.
5444
+ */
5445
+ async restoreSecretSweepDump(tenantId, runId, confirm = false) {
5446
+ const baseUrl = this.baseUrl(tenantId);
5447
+ if (!baseUrl)
5448
+ return null;
5449
+ let params = new HttpParams();
5450
+ if (confirm) {
5451
+ params = params.set('confirm', true);
5452
+ }
5453
+ const context = new HttpContext().set(MM_CALLER_HANDLED_STATUSES, [400, 403, 404, 409]);
5454
+ try {
5455
+ const response = await firstValueFrom(this.httpClient.post(`${baseUrl}secrets/sweep-runs/${encodeURIComponent(runId)}/restore-dump`, null, { params, context }));
5456
+ return { status: 'Started', jobId: response?.jobId ?? '' };
5457
+ }
5458
+ catch (error) {
5459
+ if (!(error instanceof HttpErrorResponse))
5460
+ throw error;
5461
+ const message = errorMessageOf(error);
5462
+ switch (error.status) {
5463
+ case 400:
5464
+ return { status: 'ConfirmationRequired', message };
5465
+ case 403:
5466
+ return { status: 'Forbidden', message };
5467
+ case 404:
5468
+ return { status: 'NotFound', message };
5469
+ case 409:
5470
+ return { status: errorCodeOf(error) === SECRET_DUMP_RESTORE_ERROR_DUMP_KEY_MISSING ? 'DumpKeyMissing' : 'DumpDeleted', message };
5471
+ default:
5472
+ throw error;
5473
+ }
5474
+ }
5475
+ }
5476
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: BotSecretsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
5477
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: BotSecretsService, providedIn: 'root' });
5478
+ }
5479
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: BotSecretsService, decorators: [{
5480
+ type: Injectable,
5481
+ args: [{ providedIn: 'root' }]
5482
+ }] });
5483
+ /** The code of a bot error body (`statusDescription`, handover §12; `code` / `errorCode` tolerated). */
5484
+ function errorCodeOf(error) {
5485
+ const body = error.error;
5486
+ const code = body && typeof body === 'object' ? (body.code ?? body.errorCode ?? body.statusDescription) : null;
5487
+ if (typeof code === 'string')
5488
+ return code;
5489
+ // A body that arrives as text (no JSON content type) still names the code.
5490
+ if (typeof error.error === 'string' && error.error.includes(SECRET_DUMP_RESTORE_ERROR_DUMP_KEY_MISSING)) {
5491
+ return SECRET_DUMP_RESTORE_ERROR_DUMP_KEY_MISSING;
5492
+ }
5493
+ return null;
5494
+ }
5495
+ /** The value-free message of a bot error body, if any. */
5496
+ function errorMessageOf(error) {
5497
+ const body = error.error;
5498
+ return body && typeof body === 'object' && typeof body.message === 'string' && body.message ? body.message : null;
5499
+ }
5500
+
5012
5501
  class HealthService {
5013
5502
  httpClient = inject(HttpClient);
5014
5503
  configurationService = inject(CONFIGURATION_SERVICE);
@@ -5098,6 +5587,105 @@ class IdentityService {
5098
5587
  }
5099
5588
  return null;
5100
5589
  }
5590
+ /**
5591
+ * Reads one page of the slim user directory of the current tenant
5592
+ * (`GET {tenant}/v1/users/directory?skip=&take=&search=`, AB#5859): id and display name only.
5593
+ *
5594
+ * Unlike {@link getUsers} (`users/getPaged`, which requires the `UserManagement` role once the
5595
+ * identity service enforces tenant roles), the directory is available to any signed-in user of
5596
+ * the own tenant — the token's tenant must equal the route tenant. It is meant for pickers
5597
+ * (group members, assignees, ...) that need nothing but a user id and a name.
5598
+ *
5599
+ * Availability: introduced on the identity branch `feat/gerald/identity-rest-role-authz`, not yet
5600
+ * released. Identity versions without the endpoint answer **404**; the error is propagated as
5601
+ * `HttpErrorResponse`. Use {@link getUserDirectoryWithFallback} to transparently fall back to
5602
+ * `users/getPaged` on such versions.
5603
+ *
5604
+ * @param skip Number of entries to skip (negative values are treated as 0).
5605
+ * @param take Page size; clamped to 1..500 (the server limit). Non-finite values use 100.
5606
+ * @param search Optional case-insensitive substring of the display name; omitted when empty.
5607
+ * The server never matches user names or e-mail addresses.
5608
+ * @returns The page (sorted by display name, then id), or `null` when no identity URL is configured.
5609
+ */
5610
+ async getUserDirectory(skip, take, search) {
5611
+ const baseUrl = await this.getApiBaseUrl();
5612
+ if (!baseUrl) {
5613
+ return null;
5614
+ }
5615
+ return this.fetchUserDirectory(baseUrl, skip, take, search);
5616
+ }
5617
+ /**
5618
+ * Like {@link getUserDirectory}, but falls back to `users/getPaged` when the identity service does
5619
+ * not know the directory endpoint yet (404). The missing capability is remembered per tenant for
5620
+ * the lifetime of this (root) service, so the 404 is hit at most once per tenant and session.
5621
+ *
5622
+ * The fallback maps {@link UserDto} to {@link UserDirectoryEntryDto} with the server's display
5623
+ * name rule ("First Last", else the user name) and applies `search` to the returned page only —
5624
+ * it is a best-effort bridge for old identity versions, and it still needs `UserManagement`
5625
+ * wherever `getPaged` requires it. Errors other than the 404 (401, 403, 5xx, ...) are propagated.
5626
+ */
5627
+ async getUserDirectoryWithFallback(skip, take, search) {
5628
+ const baseUrl = await this.getApiBaseUrl();
5629
+ if (!baseUrl) {
5630
+ return null;
5631
+ }
5632
+ if (!this.tenantsWithoutUserDirectory.has(baseUrl)) {
5633
+ try {
5634
+ return await this.fetchUserDirectory(baseUrl, skip, take, search);
5635
+ }
5636
+ catch (error) {
5637
+ if (!(error instanceof HttpErrorResponse) || error.status !== 404) {
5638
+ throw error;
5639
+ }
5640
+ this.tenantsWithoutUserDirectory.add(baseUrl);
5641
+ }
5642
+ }
5643
+ const page = await this.getUsers(Math.max(0, Math.trunc(skip) || 0), IdentityService.clampDirectoryTake(take));
5644
+ if (!page) {
5645
+ return null;
5646
+ }
5647
+ const term = search?.trim().toLowerCase() ?? '';
5648
+ const list = (page.list ?? [])
5649
+ .map(user => IdentityService.toUserDirectoryEntry(user))
5650
+ .filter(entry => !term || entry.displayName.toLowerCase().includes(term));
5651
+ return {
5652
+ skip: page.skip,
5653
+ take: page.take,
5654
+ totalCount: term ? list.length : page.totalCount,
5655
+ list
5656
+ };
5657
+ }
5658
+ /** Base URLs (= tenants) whose identity service answered 404 for `users/directory`. */
5659
+ tenantsWithoutUserDirectory = new Set();
5660
+ static maxUserDirectoryPageSize = 500;
5661
+ static clampDirectoryTake(take) {
5662
+ if (!Number.isFinite(take)) {
5663
+ return 100;
5664
+ }
5665
+ return Math.min(IdentityService.maxUserDirectoryPageSize, Math.max(1, Math.trunc(take)));
5666
+ }
5667
+ static toUserDirectoryEntry(user) {
5668
+ const fullName = [user.firstName, user.lastName]
5669
+ .filter(n => !!n && n.trim().length > 0)
5670
+ .map(n => n.trim())
5671
+ .join(' ');
5672
+ return { userId: user.userId, displayName: fullName.length > 0 ? fullName : (user.name ?? '') };
5673
+ }
5674
+ async fetchUserDirectory(baseUrl, skip, take, search) {
5675
+ let params = new HttpParams()
5676
+ .set('skip', Math.max(0, Math.trunc(skip) || 0).toString())
5677
+ .set('take', IdentityService.clampDirectoryTake(take).toString());
5678
+ const term = search?.trim();
5679
+ if (term) {
5680
+ // HttpParams URL-encodes the value.
5681
+ params = params.set('search', term);
5682
+ }
5683
+ const response = await firstValueFrom(this.httpClient.get(baseUrl + 'users/directory', {
5684
+ params,
5685
+ observe: 'response'
5686
+ }));
5687
+ return response.body;
5688
+ }
5101
5689
  async getUserDetails(userName) {
5102
5690
  const baseUrl = await this.getApiBaseUrl();
5103
5691
  if (baseUrl) {
@@ -5890,7 +6478,12 @@ class JobManagementService {
5890
6478
  link.click();
5891
6479
  }
5892
6480
  }
5893
- async waitForJob(jobId, title, operation) {
6481
+ /**
6482
+ * Polls a job until it ends and shows its error on failure.
6483
+ * @param formatErrorDetails optional formatter for the failure text, e.g. to append an explanation
6484
+ * of known message codes (the Studio explains the SECRET compiler messages of a CK import, AB#5544).
6485
+ */
6486
+ async waitForJob(jobId, title, operation, formatErrorDetails) {
5894
6487
  let cancelled = false;
5895
6488
  const progressSubject = new Subject();
5896
6489
  const progressDialog = this.progressWindowService.showIndeterminateProgress(title, progressSubject.asObservable(), {
@@ -5916,7 +6509,7 @@ class JobManagementService {
5916
6509
  }
5917
6510
  else {
5918
6511
  const errorDetails = jobDto.errorMessage || jobDto.reason || 'Unknown error';
5919
- this.messageService.showErrorWithDetails(errorDetails, operation);
6512
+ this.messageService.showErrorWithDetails(formatErrorDetails ? formatErrorDetails(errorDetails) : errorDetails, operation);
5920
6513
  }
5921
6514
  break;
5922
6515
  }
@@ -6024,8 +6617,16 @@ class CommunicationService {
6024
6617
  * supplied UTC timestamp are returned, keeping subsequent refreshes light.
6025
6618
  */
6026
6619
  async getAdapterMetrics(tenantId, adapterRtId, adapterCkTypeId, since) {
6620
+ return (await this.getAdapterMetricsResult(tenantId, adapterRtId, adapterCkTypeId, since)).samples;
6621
+ }
6622
+ /**
6623
+ * Like {@link getAdapterMetrics}, but reports a 404 (adapter not connected / unknown to the
6624
+ * controller) as `notFound: true` instead of hiding it, so pollers can back off (AB#5546).
6625
+ * Other errors are rethrown.
6626
+ */
6627
+ async getAdapterMetricsResult(tenantId, adapterRtId, adapterCkTypeId, since) {
6027
6628
  if (!this.communicationServicesUrl) {
6028
- return [];
6629
+ return { samples: [], notFound: false };
6029
6630
  }
6030
6631
  const rtEntityId = encodeURIComponent(`${adapterCkTypeId}@${adapterRtId}`);
6031
6632
  const uri = `${this.communicationServicesUrl}${tenantId}/v1/adapter/${rtEntityId}/metrics`;
@@ -6035,12 +6636,12 @@ class CommunicationService {
6035
6636
  }
6036
6637
  return firstValueFrom(this.httpClient
6037
6638
  .get(uri, { params, headers: this.noCacheHeaders })
6038
- .pipe(catchError((err) => {
6639
+ .pipe(map((samples) => ({ samples: samples ?? [], notFound: false })), catchError((err) => {
6039
6640
  // 404 = adapter not connected yet / unknown to the controller;
6040
6641
  // surface as "no samples" so the UI can render an empty state
6041
6642
  // instead of a toast.
6042
6643
  if (err.status === 404) {
6043
- return of([]);
6644
+ return of({ samples: [], notFound: true });
6044
6645
  }
6045
6646
  return throwError(() => err);
6046
6647
  })));
@@ -6256,6 +6857,26 @@ class CommunicationService {
6256
6857
  const uri = `${this.communicationServicesUrl}${tenantId}/v1/adapter/${adapterRtId}/serviceAccount/rotateSecret`;
6257
6858
  return await firstValueFrom(this.httpClient.post(uri, null));
6258
6859
  }
6860
+ /**
6861
+ * Rotates the client secret of a `ServiceAccountConfiguration` (`POST
6862
+ * /serviceAccount/{configurationRtId}/rotateSecret`, OctoMesh AB#5111) — the
6863
+ * configuration-bound variant of {@link rotateAdapterServiceAccountSecret} with the same core
6864
+ * logic and result: an adapter-owned configuration is rotated through its adapter server-side,
6865
+ * a standalone (declared) one directly. Roles are never touched.
6866
+ *
6867
+ * Same contract as the adapter-bound call: the result carries **no secret**, the old secret is
6868
+ * invalid once this resolves, and the pipelines / data flows using the account keep presenting
6869
+ * it until they are redeployed (`requiresPipelineRedeploy`, `message`). Throws when the
6870
+ * communication services URL is missing or the controller refuses (the error text says that
6871
+ * the previous secret remains in effect).
6872
+ */
6873
+ async rotateServiceAccountConfigurationSecret(tenantId, configurationRtId) {
6874
+ if (!this.communicationServicesUrl) {
6875
+ throw new Error('Communication services URL is not configured');
6876
+ }
6877
+ const uri = `${this.communicationServicesUrl}${tenantId}/v1/serviceAccount/${configurationRtId}/rotateSecret`;
6878
+ return await firstValueFrom(this.httpClient.post(uri, null));
6879
+ }
6259
6880
  /**
6260
6881
  * Enables or disables debug capture for a pipeline via the dedicated debug
6261
6882
  * endpoint (`PATCH /pipeline/{id}/debug`). This is the ONLY way debug capture
@@ -6690,7 +7311,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
6690
7311
  }] });
6691
7312
 
6692
7313
  const GetEntitiesByCkTypeDocumentDto = gql `
6693
- query getEntitiesByCkType($ckTypeId: String!, $rtId: OctoObjectId, $after: String, $first: Int, $searchFilter: SearchFilter, $fieldFilters: [FieldFilter], $sort: [Sort]) {
7314
+ query getEntitiesByCkType($ckTypeId: String!, $attributeNames: [String!]!, $rtId: OctoObjectId, $after: String, $first: Int, $searchFilter: SearchFilter, $fieldFilters: [FieldFilter], $sort: [Sort]) {
6694
7315
  runtime {
6695
7316
  runtimeEntities(
6696
7317
  ckId: $ckTypeId
@@ -6710,7 +7331,7 @@ const GetEntitiesByCkTypeDocumentDto = gql `
6710
7331
  rtDisplayDescription
6711
7332
  rtCreationDateTime
6712
7333
  rtChangedDateTime
6713
- attributes(resolveEnumValuesToNames: true) {
7334
+ attributes(attributeNames: $attributeNames, resolveEnumValuesToNames: true) {
6714
7335
  items {
6715
7336
  attributeName
6716
7337
  value
@@ -6750,6 +7371,8 @@ class RuntimeEntitySelectDataSource {
6750
7371
  const result = await firstValueFrom(this.getEntitiesByCkTypeGQL.fetch({
6751
7372
  variables: {
6752
7373
  ckTypeId: this.ckTypeId,
7374
+ // Only rt* fields are displayed — no attributes (SECRET-safe, AB#5542).
7375
+ attributeNames: [],
6753
7376
  first: take ?? 10,
6754
7377
  fieldFilters: [
6755
7378
  // Search by the engine-computed display name (AB#4813); rtId matching required exact
@@ -6811,6 +7434,7 @@ class RuntimeEntityDialogDataSource {
6811
7434
  return from(this.getEntitiesByCkTypeGQL.fetch({
6812
7435
  variables: {
6813
7436
  ckTypeId: this.ckTypeId,
7437
+ attributeNames: [],
6814
7438
  first: options.take,
6815
7439
  after: options.skip > 0 ? btoa(`arrayconnection:${options.skip - 1}`) : undefined,
6816
7440
  fieldFilters: fieldFilters.length > 0 ? fieldFilters : undefined
@@ -7147,5 +7771,5 @@ function provideOctoServices(octoServiceOptions) {
7147
7771
  * Generated bundle index. Do not edit.
7148
7772
  */
7149
7773
 
7150
- export { AggregationInputTypesDto, AggregationTypeDto, AggregationTypesDto, AiService, ArchiveStorageHealthDto, AssetRepoGraphQlDataSource, AssetRepoService, AssociationModOptionsDto, AttributeSelectorService, AttributeValueTypeDto, BasicEnergyCarrierTypeDto, BasicEnergyDataQualityDto, BasicEnergyFacilityTypeDto, BasicEnergyProductionTypeDto, BasicEnergyStateDto, BasicLegalEntityTypeDto, BasicSalutationDto, BasicTypeOfTelephoneBasicDto, BasicTypeOfTelephoneEnhancedDto, BasicUnitOfMeasureDto, BlueprintConflictResolutionDto, BlueprintUpdateModeDto, BotService, BucketAlignmentDto, BucketAlignmentInputDto, CONFIGURATION_SERVICE, CkExtensionUpdateOperationsDto, CkModelCatalogService, CkModelService, CkRollupFunctionDto, CkTypeAttributeService, CkTypeMetaData, CkTypeSelectorService, CommunicationService, DeepGraphDirectionDto, DeleteStrategiesDto, DeploymentState, EnergyCommunityBillingCycleDto, EnergyCommunityBillingDocumentStateDto, EnergyCommunityBillingTypeDto, EnergyCommunityTaxProcedureCreditNoteDto, EnvironmentCarbonScopeDto, EnvironmentComplianceCategoryDto, EnvironmentComplianceStatusDto, EnvironmentEnergySourceDto, EnvironmentGoalStateDto, FieldFilterOperatorsDto, FormulaResultTypeDto, GetCkModelByIdDocumentDto, GetCkModelByIdDtoGQL, GetCkRecordAttributesDocumentDto, GetCkRecordAttributesDtoGQL, GetCkTypeAttributesDocumentDto, GetCkTypeAttributesDtoGQL, GetCkTypeAvailableQueryColumnsDocumentDto, GetCkTypeAvailableQueryColumnsDtoGQL, GetCkTypesDocumentDto, GetCkTypesDtoGQL, GetDerivedCkTypesDocumentDto, GetDerivedCkTypesDtoGQL, GetEntitiesByCkTypeDocumentDto, GetEntitiesByCkTypeDtoGQL, GraphDirectionDto, GraphQL, GraphQLCloneIgnoredProperties, GraphQLCommonIgnoredProperties, GraphQlDataSource, HealthService, HealthStatus, IDENTITY_PROVIDER_TYPE_LABELS, IdentityProviderType, IdentityService, ImportStrategyDto, IndustryBasicAlarmPriorityDto, IndustryBasicAlarmSourceTypeDto, IndustryBasicAlarmStateDto, IndustryBasicAlarmTypeDto, IndustryBasicIecDataTypeDto, IndustryBasicMachineCapabilitiesDto, IndustryBasicMachineStateDto, IndustryEnergyDemandResponseMarketDto, IndustryEnergyDemandResponseStatusDto, IndustryEnergyTariffTypeDto, IndustryMaintenanceAggregationTypeDto, IndustryMaintenanceCostCategoryDto, IndustryMaintenanceEnergyBalanceGroupDto, IndustryMaintenanceEnergyBalanceProductDto, IndustryMaintenanceEnergyBalanceUnitDto, IndustryMaintenanceOrderPriorityDto, IndustryMaintenanceOrderStateDto, IndustryMaintenanceOrderTypeDto, IndustryMaintenanceServiceTypeDto, IndustryManufacturingFeedbackSyncStateDto, IndustryManufacturingProductionOrderItemStateDto, IndustryManufacturingProductionOrderStateDto, JobManagementService, LevelMetaData, LoggerSeverity, ModelStateDto, MultiplicitiesDto, NavigationFilterModeDto, OctoErrorLink, OctoGraphQLServiceBase, OctoSdkDemoCustomerStatusDto, OctoSdkDemoNetworkOperatorDto, OctoSdkDemoOperatingStatusDto, OctoServiceOptions, OctoServicesModule, PagedGraphResultDto, ProgressValue, ProgressWindowService, QueryModeDto, ReportingService, RtAssociationMetaData, RuntimeEntityDialogDataSource, RuntimeEntitySelectDataSource, SearchFilterTypesDto, SeriesComparisonPolicyDto, SeriesResolutionSignalDto, SortOrdersDto, SystemAggregationTypesDto, SystemAiApprovalModeDto, SystemAiApprovalReasonDto, SystemAiApprovalStatusDto, SystemAiAuthModeDto, SystemAiConflictModeDto, SystemAiCredentialKindDto, SystemAiJobKindDto, SystemAiJobStatusDto, SystemAiKnowledgeKindDto, SystemAiLeaseStatusDto, SystemAiModelTierDto, SystemAiRiskLevelDto, SystemAiSessionEventKindDto, SystemAiSessionStatusDto, SystemAiSubscriptionScopeDto, SystemAiTicketScopeDto, SystemAiTicketStatusDto, SystemAiWorkspaceModeDto, SystemCommunicationCommunicationStateDto, SystemCommunicationConfigurationStateDto, SystemCommunicationDeploymentStateDto, SystemCommunicationEnvironmentDto, SystemCommunicationHelmChannelDto, SystemCommunicationLifecycleModeDto, SystemCommunicationLifecycleStateDto, SystemCommunicationPipelineExecutionStatusDto, SystemCommunicationPipelineTriggerTypeDto, SystemCommunicationSignalRegistrationActionDto, SystemCommunicationSignalRegistrationStateDto, SystemEnvironmentModesDto, SystemFieldFilterOperatorDto, SystemIdentityDataPolicyEnforcementModeDto, SystemIdentityDataPolicyScopeDto, SystemIdentityIdentifierKindDto, SystemIdentityIdentifierSourceDto, SystemIdentityTokenExpirationDto, SystemIdentityTokenTypeDto, SystemIdentityTokenUsageDto, SystemIdentityTrustLevelDto, SystemMaintenanceLevelsDto, SystemNavigationFilterModesDto, SystemNotificationEventLevelsDto, SystemNotificationEventSourcesDto, SystemNotificationEventStatesDto, SystemNotificationNotificationTypesDto, SystemNotificationRenderingTypesDto, SystemQueryTypesDto, SystemSortOrdersDto, SystemStreamDataBucketAlignmentDto, SystemStreamDataCkArchiveStatusDto, SystemStreamDataCkComputedColumnResultTypeDto, SystemStreamDataCkComputedColumnStateDto, SystemStreamDataCkRecomputeChangeKindDto, SystemStreamDataCkRecomputeChangeSourceDto, SystemStreamDataCkRecomputeJobStateDto, SystemStreamDataCkRecomputeTriggerDto, SystemStreamDataCkRollupFunctionDto, TENANT_ID_PROVIDER, TusUploadService, UpdateTypeDto, buildTusEndpoint, octoDataIdFromObject, result as possibleTypes, provideOctoServices };
7774
+ export { AggregationInputTypesDto, AggregationTypeDto, AggregationTypesDto, AiService, ArchiveStorageHealthDto, AssetRepoGraphQlDataSource, AssetRepoService, AssociationModOptionsDto, AttributeOwnershipDto, AttributeSelectorService, AttributeValueTypeDto, BasicEnergyCarrierTypeDto, BasicEnergyDataQualityDto, BasicEnergyFacilityTypeDto, BasicEnergyProductionTypeDto, BasicEnergyStateDto, BasicLegalEntityTypeDto, BasicSalutationDto, BasicTypeOfTelephoneBasicDto, BasicTypeOfTelephoneEnhancedDto, BasicUnitOfMeasureDto, BlueprintConflictResolutionDto, BlueprintUpdateModeDto, BotSecretsService, BotService, BucketAlignmentDto, BucketAlignmentInputDto, CONFIGURATION_SERVICE, CREDENTIAL_ATTRIBUTE_NAME_SUFFIXES, CkExtensionUpdateOperationsDto, CkModelCatalogService, CkModelService, CkRollupFunctionDto, CkTypeAttributeService, CkTypeMetaData, CkTypeSelectorService, CommunicationService, DEFAULT_SECRET_STATUS_LABELS, DeepGraphDirectionDto, DeleteStrategiesDto, DeploymentState, EnergyCommunityBillingCycleDto, EnergyCommunityBillingDocumentStateDto, EnergyCommunityBillingTypeDto, EnergyCommunityTaxProcedureCreditNoteDto, EnvironmentCarbonScopeDto, EnvironmentComplianceCategoryDto, EnvironmentComplianceStatusDto, EnvironmentEnergySourceDto, EnvironmentGoalStateDto, FieldFilterOperatorsDto, FormulaResultTypeDto, GetCkModelByIdDocumentDto, GetCkModelByIdDtoGQL, GetCkRecordAttributesDocumentDto, GetCkRecordAttributesDtoGQL, GetCkTypeAttributesDocumentDto, GetCkTypeAttributesDtoGQL, GetCkTypeAvailableQueryColumnsDocumentDto, GetCkTypeAvailableQueryColumnsDtoGQL, GetCkTypesDocumentDto, GetCkTypesDtoGQL, GetDerivedCkTypesDocumentDto, GetDerivedCkTypesDtoGQL, GetEntitiesByCkTypeDocumentDto, GetEntitiesByCkTypeDtoGQL, GraphDirectionDto, GraphQL, GraphQLCloneIgnoredProperties, GraphQLCommonIgnoredProperties, GraphQlDataSource, HealthService, HealthStatus, IDENTITY_PROVIDER_TYPE_LABELS, IdentityProviderType, IdentityService, ImportStrategyDto, IndustryBasicAlarmPriorityDto, IndustryBasicAlarmSourceTypeDto, IndustryBasicAlarmStateDto, IndustryBasicAlarmTypeDto, IndustryBasicIecDataTypeDto, IndustryBasicMachineCapabilitiesDto, IndustryBasicMachineStateDto, IndustryEnergyDemandResponseMarketDto, IndustryEnergyDemandResponseStatusDto, IndustryEnergyTariffTypeDto, IndustryMaintenanceAggregationTypeDto, IndustryMaintenanceCostCategoryDto, IndustryMaintenanceEnergyBalanceGroupDto, IndustryMaintenanceEnergyBalanceProductDto, IndustryMaintenanceEnergyBalanceUnitDto, IndustryMaintenanceOrderPriorityDto, IndustryMaintenanceOrderStateDto, IndustryMaintenanceOrderTypeDto, IndustryMaintenanceServiceTypeDto, IndustryManufacturingFeedbackSyncStateDto, IndustryManufacturingProductionOrderItemStateDto, IndustryManufacturingProductionOrderStateDto, JobManagementService, LevelMetaData, LoggerSeverity, ModelStateDto, MultiplicitiesDto, NavigationFilterModeDto, OCTO_SILENT_ERRORS, OctoErrorLink, OctoGraphQLServiceBase, OctoSdkDemoCustomerStatusDto, OctoSdkDemoNetworkOperatorDto, OctoSdkDemoOperatingStatusDto, OctoServiceOptions, OctoServicesModule, PagedGraphResultDto, ProgressValue, ProgressWindowService, QueryModeDto, ReportingService, RtAssociationMetaData, RuntimeEntityDialogDataSource, RuntimeEntitySelectDataSource, SECRET_DUMP_RESTORE_ERROR_DUMP_DELETED, SECRET_DUMP_RESTORE_ERROR_DUMP_KEY_MISSING, SECRET_LEGACY_V1_KEY_ID, SECRET_STATUS_WARNING_DUMP_KEY_MISSING, SECRET_STATUS_WARNING_NO_KEY_RING, SECRET_STATUS_WARNING_NO_LEGACY_V1_KEY, SECRET_VALUE_TYPE, SearchFilterTypesDto, SecretStorageFormDto, SecretUsageMatchDto, SeriesComparisonPolicyDto, SeriesResolutionSignalDto, SortOrdersDto, SystemAggregationTypesDto, SystemAiApprovalModeDto, SystemAiApprovalReasonDto, SystemAiApprovalStatusDto, SystemAiAuthModeDto, SystemAiConflictModeDto, SystemAiCredentialKindDto, SystemAiJobKindDto, SystemAiJobStatusDto, SystemAiKnowledgeKindDto, SystemAiLeaseStatusDto, SystemAiModelTierDto, SystemAiRiskLevelDto, SystemAiSessionEventKindDto, SystemAiSessionStatusDto, SystemAiSubscriptionScopeDto, SystemAiTicketScopeDto, SystemAiTicketStatusDto, SystemAiWorkspaceModeDto, SystemCommunicationCommunicationStateDto, SystemCommunicationConfigurationStateDto, SystemCommunicationDeploymentStateDto, SystemCommunicationEnvironmentDto, SystemCommunicationHelmChannelDto, SystemCommunicationLifecycleModeDto, SystemCommunicationLifecycleStateDto, SystemCommunicationPipelineExecutionStatusDto, SystemCommunicationPipelineTriggerTypeDto, SystemCommunicationSignalRegistrationActionDto, SystemCommunicationSignalRegistrationStateDto, SystemEnvironmentModesDto, SystemFieldFilterOperatorDto, SystemIdentityDataPolicyEnforcementModeDto, SystemIdentityDataPolicyScopeDto, SystemIdentityIdentifierKindDto, SystemIdentityIdentifierSourceDto, SystemIdentityTokenExpirationDto, SystemIdentityTokenTypeDto, SystemIdentityTokenUsageDto, SystemIdentityTrustLevelDto, SystemMaintenanceLevelsDto, SystemNavigationFilterModesDto, SystemNotificationEventLevelsDto, SystemNotificationEventSourcesDto, SystemNotificationEventStatesDto, SystemNotificationNotificationTypesDto, SystemNotificationRenderingTypesDto, SystemQueryTypesDto, SystemSortOrdersDto, SystemStreamDataBucketAlignmentDto, SystemStreamDataCkArchiveStatusDto, SystemStreamDataCkComputedColumnResultTypeDto, SystemStreamDataCkComputedColumnStateDto, SystemStreamDataCkConflictKeyOrderDto, SystemStreamDataCkRecomputeChangeKindDto, SystemStreamDataCkRecomputeChangeSourceDto, SystemStreamDataCkRecomputeJobStateDto, SystemStreamDataCkRecomputeTriggerDto, SystemStreamDataCkRollupFunctionDto, TENANT_ID_PROVIDER, TusUploadService, UpdateTypeDto, buildTusEndpoint, formatSecretStatus, isCredentialLikeAttributeName, isSecretAttributeCandidate, isSecretPresent, isSecretQueryColumn, isSecretStateObject, isSecretValueType, isTextualValueType, octoDataIdFromObject, result as possibleTypes, provideOctoServices, secretInputValue, secretStateFromAttribute, secretStatusOf, toAttributeNameFilter, toCamelCaseAttributeName, toSecretState, toUniqueCamelCaseNames };
7151
7775
  //# sourceMappingURL=meshmakers-octo-services.mjs.map