@camunda/ccma-shared-types 5.0.0 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/dist/_tests/approvals/dns-subdomain.spec.d.ts +1 -0
  2. package/dist/_tests/approvals/expected-value.spec.d.ts +1 -0
  3. package/dist/_tests/charts/chart-query.spec.d.ts +1 -0
  4. package/dist/_tests/dashboards/definition.spec.d.ts +1 -0
  5. package/dist/_tests/utils/elasticsearchPlanPath.utils.spec.d.ts +1 -0
  6. package/dist/approvals/dns-subdomain.d.ts +12 -0
  7. package/dist/approvals/dns-subdomain.js +16 -0
  8. package/dist/approvals/dns-subdomain.js.map +7 -0
  9. package/dist/approvals/expected-value.d.ts +33 -0
  10. package/dist/approvals/expected-value.js +26 -0
  11. package/dist/approvals/expected-value.js.map +7 -0
  12. package/dist/approvals/use-cases.const.d.ts +80 -0
  13. package/dist/approvals/use-cases.const.js +42 -2
  14. package/dist/approvals/use-cases.const.js.map +2 -2
  15. package/dist/charts/chart-metrics.d.ts +35 -0
  16. package/dist/charts/chart-metrics.js +188 -0
  17. package/dist/charts/chart-metrics.js.map +7 -0
  18. package/dist/charts/chart-query.d.ts +55 -0
  19. package/dist/charts/chart-query.js +376 -0
  20. package/dist/charts/chart-query.js.map +7 -0
  21. package/dist/charts/chart-spec.d.ts +103 -0
  22. package/dist/charts/chart-spec.js +79 -0
  23. package/dist/charts/chart-spec.js.map +7 -0
  24. package/dist/charts/index.d.ts +3 -0
  25. package/dist/charts/index.js +59 -0
  26. package/dist/charts/index.js.map +7 -0
  27. package/dist/dashboards/definition.d.ts +86 -0
  28. package/dist/dashboards/definition.js +137 -0
  29. package/dist/dashboards/definition.js.map +7 -0
  30. package/dist/dtos/Annotation.dto.d.ts +1 -1
  31. package/dist/dtos/Annotation.dto.js +10 -2
  32. package/dist/dtos/Annotation.dto.js.map +2 -2
  33. package/dist/dtos/ControlV2.dto.d.ts +17 -0
  34. package/dist/dtos/Dashboard.dto.d.ts +336 -0
  35. package/dist/dtos/Dashboard.dto.js +70 -0
  36. package/dist/dtos/Dashboard.dto.js.map +7 -0
  37. package/dist/dtos/FeatureFlags.dto.d.ts +88 -54
  38. package/dist/dtos/Hdp.dto.d.ts +5 -88
  39. package/dist/dtos/Organization.dto.d.ts +10 -0
  40. package/dist/dtos/Organization.dto.js.map +1 -1
  41. package/dist/enums/SystemAuditEntity.enum.d.ts +4 -2
  42. package/dist/enums/SystemAuditEntity.enum.js +2 -0
  43. package/dist/enums/SystemAuditEntity.enum.js.map +2 -2
  44. package/dist/index.d.ts +12 -3
  45. package/dist/index.js +150 -1
  46. package/dist/index.js.map +2 -2
  47. package/dist/permissions/accounts.permissions.d.ts +12 -0
  48. package/dist/permissions/accounts.permissions.js +11 -0
  49. package/dist/permissions/accounts.permissions.js.map +2 -2
  50. package/dist/permissions/combo.js +5 -0
  51. package/dist/permissions/combo.js.map +2 -2
  52. package/dist/search/compiler.d.ts +20 -0
  53. package/dist/search/compiler.js +48 -11
  54. package/dist/search/compiler.js.map +2 -2
  55. package/dist/search/index.d.ts +1 -1
  56. package/dist/search/index.js.map +2 -2
  57. package/dist/search/parser.d.ts +3 -0
  58. package/dist/search/parser.js +3 -1
  59. package/dist/search/parser.js.map +2 -2
  60. package/dist/types/ClusterPlanFields.type.js +74 -74
  61. package/dist/types/ClusterPlanFields.type.js.map +2 -2
  62. package/dist/utils/elasticsearchPlanPath.utils.d.ts +18 -0
  63. package/dist/utils/elasticsearchPlanPath.utils.js +23 -0
  64. package/dist/utils/elasticsearchPlanPath.utils.js.map +7 -0
  65. package/dist/utils/qa-user.utils.d.ts +14 -0
  66. package/dist/utils/qa-user.utils.js +14 -0
  67. package/dist/utils/qa-user.utils.js.map +7 -0
  68. package/dist/utils/qa-user.utils.spec.d.ts +1 -0
  69. package/package.json +1 -1
@@ -0,0 +1,336 @@
1
+ import type { ChartGrain, ChartSpec, ChartUnit, ChartWindowUnit } from '../charts/chart-spec.js';
2
+ import type { SearchFieldCapability, SearchFieldType } from '../search/fields.js';
3
+ import type { AnnotationEntityKind, AnnotationKind } from './Annotation.dto.js';
4
+ /**
5
+ * The wire types of the dashboards of Camunda Control.
6
+ *
7
+ * A dashboard stores QUESTIONS and never answers. A tile holds the filters of
8
+ * the page that it came from, and the dashboard runs them again each time a
9
+ * reader opens it. So a stored dashboard stays small, and it never holds a
10
+ * copy of fleet data that can go stale or leak.
11
+ *
12
+ * control-backend and control-frontend both read this file, so it holds no
13
+ * logic with I/O and no dependency.
14
+ */
15
+ /** DASHBOARD_TILES_MAX is the most tiles that one dashboard can hold. */
16
+ export declare const DASHBOARD_TILES_MAX = 20;
17
+ /** DASHBOARD_GRID_COLUMNS is the width of the tile grid, in columns. */
18
+ export declare const DASHBOARD_GRID_COLUMNS = 12;
19
+ /** DASHBOARD_TILE_ROWS_MAX is the tallest tile, in grid rows. */
20
+ export declare const DASHBOARD_TILE_ROWS_MAX = 24;
21
+ /**
22
+ * DASHBOARD_GRID_ROWS_MAX is the lowest row that a tile can start on. It is
23
+ * the height of 20 tiles of the tallest size, one under the other, so a
24
+ * compact grid never reaches it.
25
+ */
26
+ export declare const DASHBOARD_GRID_ROWS_MAX: number;
27
+ /** DASHBOARD_TITLE_MAX is the longest title of a dashboard or of a tile. */
28
+ export declare const DASHBOARD_TITLE_MAX = 120;
29
+ /**
30
+ * DASHBOARD_DEFINITION_BYTES_MAX is the largest definition that the backend
31
+ * stores, as JSON text. Twenty tiles of filters need a few kilobytes, so a
32
+ * larger body is a client that tries to store data and not filters.
33
+ */
34
+ export declare const DASHBOARD_DEFINITION_BYTES_MAX = 32768;
35
+ /** DASHBOARD_PAGE_SIZE_MAX is the most dashboards that one list page holds. */
36
+ export declare const DASHBOARD_PAGE_SIZE_MAX = 200;
37
+ /** DASHBOARD_PAGE_SIZE_DEFAULT is the list page size when a caller sends none. */
38
+ export declare const DASHBOARD_PAGE_SIZE_DEFAULT = 200;
39
+ /**
40
+ * DASHBOARD_DEFINITION_VERSION is the `schemaVersion` that this code writes.
41
+ *
42
+ * Raise it when the shape of the definition changes, add the old shape to
43
+ * `StoredDashboardDefinition`, and teach `upgradeDashboardDefinition` to read
44
+ * it. A row is never rewritten in place: it moves to the new version on its
45
+ * next save.
46
+ */
47
+ export declare const DASHBOARD_DEFINITION_VERSION = 3;
48
+ /**
49
+ * Every kind of tile.
50
+ *
51
+ * `fleet-query` and `annotations` run saved filters. `cluster-detail` and
52
+ * `org-detail` show one card of the page of one cluster or one organization.
53
+ * `heading`, `note` and `link` hold text that a person wrote, and fetch
54
+ * nothing. `chart` runs a chart query on HDP.
55
+ */
56
+ export declare const DASHBOARD_TILE_KINDS: readonly ["fleet-query", "annotations", "cluster-detail", "org-detail", "heading", "note", "link", "chart"];
57
+ export type DashboardTileKind = (typeof DASHBOARD_TILE_KINDS)[number];
58
+ /** Where a tile sits on the grid, in columns and rows from the top left. */
59
+ export interface DashboardTileLayout {
60
+ x: number;
61
+ y: number;
62
+ w: number;
63
+ h: number;
64
+ }
65
+ /**
66
+ * The search params of a Fleet query page, as that page writes them.
67
+ *
68
+ * The backend stores them as they are and checks only their shape: flat
69
+ * values, no objects. The keys belong to the Fleet query page, so the
70
+ * frontend validates them on read with the same function that validates the
71
+ * URL. A tile with a key that this function drops does not run, because the
72
+ * query would be wider than the one that was saved.
73
+ */
74
+ export type DashboardFleetQuery = Record<string, string | number | boolean | string[]>;
75
+ /** The filters of the Notes & tags page. */
76
+ export interface DashboardAnnotationsQuery {
77
+ kind?: AnnotationKind;
78
+ entityKind?: AnnotationEntityKind;
79
+ tag?: string;
80
+ q?: string;
81
+ }
82
+ /**
83
+ * The cards of the Overview tab of a cluster that a dashboard can show.
84
+ *
85
+ * The id names the card and never its content. The tile reads the cluster
86
+ * again each time it is in view, so it shows the current state.
87
+ */
88
+ export declare const DASHBOARD_CLUSTER_CARDS: readonly ["identity", "component-status", "datacenter", "generation", "plan", "backup-encryption", "settings-flags", "external-idp", "data-filters", "auto-pause", "change-history", "disk-usage"];
89
+ export type DashboardClusterCard = (typeof DASHBOARD_CLUSTER_CARDS)[number];
90
+ /** The cards of the Overview tab of an organization. */
91
+ export declare const DASHBOARD_ORG_CARDS: readonly ["summary", "details", "sales-plan", "queued-operations", "clusters", "managed-llm", "recent-activity"];
92
+ export type DashboardOrgCard = (typeof DASHBOARD_ORG_CARDS)[number];
93
+ /** DASHBOARD_ENTITY_ID_MAX is the longest cluster id or organization id. */
94
+ export declare const DASHBOARD_ENTITY_ID_MAX = 64;
95
+ /**
96
+ * DASHBOARD_NOTE_MAX is the longest text of a note tile.
97
+ *
98
+ * Twenty full notes of ASCII text fit in `DASHBOARD_DEFINITION_BYTES_MAX`.
99
+ * Text with characters of more than one UTF-8 byte can pass that limit first,
100
+ * so the frontend measures the whole definition with
101
+ * `dashboardDefinitionBytes` before it saves.
102
+ */
103
+ export declare const DASHBOARD_NOTE_MAX = 1000;
104
+ /** DASHBOARD_LINK_URL_MAX is the longest address of a link tile. */
105
+ export declare const DASHBOARD_LINK_URL_MAX = 1000;
106
+ /**
107
+ * How a chart tile draws its result. `stat` is one number with a sparkline.
108
+ * Each render is a chart of `@camunda/design-system`, which has no area chart.
109
+ */
110
+ export declare const DASHBOARD_CHART_RENDERS: readonly ["line", "bar", "stacked-bar", "stat"];
111
+ export type DashboardChartRender = (typeof DASHBOARD_CHART_RENDERS)[number];
112
+ /**
113
+ * A chart query and how to draw it. The tile stores the structured spec and
114
+ * not the text, so a later change of the grammar cannot break a stored tile.
115
+ */
116
+ export interface DashboardChartQuery extends ChartSpec {
117
+ render: DashboardChartRender;
118
+ }
119
+ /** One card of one cluster. */
120
+ export interface DashboardClusterDetailQuery {
121
+ clusterId: string;
122
+ card: DashboardClusterCard;
123
+ }
124
+ /** One card of one organization. */
125
+ export interface DashboardOrgDetailQuery {
126
+ orgId: string;
127
+ card: DashboardOrgCard;
128
+ }
129
+ interface DashboardTileBaseV1 {
130
+ /** Unique in its dashboard. The client makes it. */
131
+ id: string;
132
+ title: string;
133
+ layout: DashboardTileLayout;
134
+ }
135
+ export interface DashboardFleetQueryTileV1 extends DashboardTileBaseV1 {
136
+ kind: 'fleet-query';
137
+ query: DashboardFleetQuery;
138
+ }
139
+ export interface DashboardAnnotationsTileV1 extends DashboardTileBaseV1 {
140
+ kind: 'annotations';
141
+ query: DashboardAnnotationsQuery;
142
+ }
143
+ export type DashboardTileV1 = DashboardFleetQueryTileV1 | DashboardAnnotationsTileV1;
144
+ export interface DashboardDefinitionV1 {
145
+ schemaVersion: 1;
146
+ tiles: DashboardTileV1[];
147
+ }
148
+ export interface DashboardClusterDetailTileV2 extends DashboardTileBaseV1 {
149
+ kind: 'cluster-detail';
150
+ query: DashboardClusterDetailQuery;
151
+ }
152
+ export interface DashboardOrgDetailTileV2 extends DashboardTileBaseV1 {
153
+ kind: 'org-detail';
154
+ query: DashboardOrgDetailQuery;
155
+ }
156
+ /** A section title. The `title` of the tile is the text. */
157
+ export interface DashboardHeadingTileV2 extends DashboardTileBaseV1 {
158
+ kind: 'heading';
159
+ }
160
+ /** Plain text. Line breaks stay, and nothing in it is markup. */
161
+ export interface DashboardNoteTileV2 extends DashboardTileBaseV1 {
162
+ kind: 'note';
163
+ body: string;
164
+ }
165
+ /**
166
+ * A link to a page of Control (a path that starts with `/`) or to an
167
+ * `https://` address. `isSafeDashboardLink` holds the rule.
168
+ */
169
+ export interface DashboardLinkTileV2 extends DashboardTileBaseV1 {
170
+ kind: 'link';
171
+ url: string;
172
+ }
173
+ /**
174
+ * Version 2 adds kinds of tiles and changes no tile of version 1. A version 1
175
+ * row is a version 2 row with a lower number, so an upgrade only sets the
176
+ * number.
177
+ *
178
+ * The number moved because the kinds are new. A pod with version 1 code
179
+ * answers `unsupportedVersion` for a row with a new kind, and not a 500 from
180
+ * its serializer. A row with no new kind stays version 1, so that pod still
181
+ * reads it (`toStoredDashboardDefinition`).
182
+ */
183
+ export type DashboardTileV2 = DashboardTileV1 | DashboardClusterDetailTileV2 | DashboardOrgDetailTileV2 | DashboardHeadingTileV2 | DashboardNoteTileV2 | DashboardLinkTileV2;
184
+ export interface DashboardDefinitionV2 {
185
+ schemaVersion: 2;
186
+ tiles: DashboardTileV2[];
187
+ }
188
+ /** A chart of a metric of HDP. accounts-backend runs the query. */
189
+ export interface DashboardChartTileV3 extends DashboardTileBaseV1 {
190
+ kind: 'chart';
191
+ query: DashboardChartQuery;
192
+ }
193
+ /**
194
+ * Version 3 adds the `chart` kind and changes no tile of version 2, for the
195
+ * same reason that version 2 moved the number. A row with no chart tile stays
196
+ * at version 1 or 2 (`toStoredDashboardDefinition`).
197
+ */
198
+ export type DashboardTileV3 = DashboardTileV2 | DashboardChartTileV3;
199
+ export interface DashboardDefinitionV3 {
200
+ schemaVersion: 3;
201
+ tiles: DashboardTileV3[];
202
+ }
203
+ /**
204
+ * Every shape that a row can hold. A row keeps its old shape until somebody
205
+ * saves the dashboard again.
206
+ */
207
+ export type StoredDashboardDefinition = DashboardDefinitionV1 | DashboardDefinitionV2 | DashboardDefinitionV3;
208
+ /** The current shape. Every DTO carries this one. */
209
+ export type DashboardDefinition = DashboardDefinitionV3;
210
+ export type DashboardTile = DashboardTileV3;
211
+ export type DashboardFleetQueryTile = DashboardFleetQueryTileV1;
212
+ export type DashboardAnnotationsTile = DashboardAnnotationsTileV1;
213
+ export type DashboardClusterDetailTile = DashboardClusterDetailTileV2;
214
+ export type DashboardOrgDetailTile = DashboardOrgDetailTileV2;
215
+ export type DashboardHeadingTile = DashboardHeadingTileV2;
216
+ export type DashboardNoteTile = DashboardNoteTileV2;
217
+ export type DashboardLinkTile = DashboardLinkTileV2;
218
+ export type DashboardChartTile = DashboardChartTileV3;
219
+ /**
220
+ * `Omit` on a union merges its members into one shape. This one omits from
221
+ * each member, so the kinds stay apart.
222
+ */
223
+ type OmitEach<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never;
224
+ /** A tile as a client adds it to a dashboard. The backend places it. */
225
+ export type DashboardNewTile = OmitEach<DashboardTile, 'layout'>;
226
+ /** Who created or archived a dashboard. The same shape as `ApprovalActor`. */
227
+ export interface DashboardActor {
228
+ userId: string;
229
+ email: string;
230
+ }
231
+ /**
232
+ * One dashboard in a list, without its tiles.
233
+ *
234
+ * The sidebar reads a list of these, so it never parses a definition.
235
+ */
236
+ export interface DashboardSummaryDto {
237
+ id: string;
238
+ title: string;
239
+ tileCount: number;
240
+ createdBy: DashboardActor;
241
+ createdAt: string;
242
+ updatedAt: string;
243
+ /** Set when the dashboard is archived. An archived dashboard is read-only. */
244
+ archivedAt?: string;
245
+ archivedBy?: DashboardActor;
246
+ /** True when the CALLER pinned it. A pin is personal. */
247
+ pinned: boolean;
248
+ }
249
+ export interface DashboardDto extends DashboardSummaryDto {
250
+ definition: DashboardDefinition;
251
+ /**
252
+ * The version that the optimistic lock of a save compares. Send back the
253
+ * value of the read that the edit started from.
254
+ */
255
+ version: number;
256
+ }
257
+ export interface DashboardListDto {
258
+ dashboards: DashboardSummaryDto[];
259
+ page: {
260
+ limit: number;
261
+ offset: number;
262
+ hasMore: boolean;
263
+ };
264
+ }
265
+ /** One Lucene field that a search or a chart filter can use. */
266
+ export interface DashboardCatalogueSearchField {
267
+ field: string;
268
+ label: string;
269
+ description: string;
270
+ type: SearchFieldType;
271
+ capabilities: SearchFieldCapability[];
272
+ enumValues?: string[];
273
+ example: string;
274
+ }
275
+ /** One metric of the chart tiles, without its SQL. */
276
+ export interface DashboardCatalogueChartMetric {
277
+ id: string;
278
+ label: string;
279
+ description: string;
280
+ unit: ChartUnit;
281
+ dimensions: {
282
+ id: string;
283
+ label: string;
284
+ description: string;
285
+ }[];
286
+ filters: DashboardCatalogueSearchField[];
287
+ grains: ChartGrain[];
288
+ maxWindowDays: number;
289
+ }
290
+ /**
291
+ * What a client must know to write a dashboard definition: the kinds of tiles,
292
+ * the cards, the chart metrics and the limits. The answer of
293
+ * `GET /api/dashboards/catalogue`.
294
+ */
295
+ export interface DashboardCatalogue {
296
+ definitionVersion: number;
297
+ limits: {
298
+ tiles: number;
299
+ gridColumns: number;
300
+ tileRowsMax: number;
301
+ titleMax: number;
302
+ noteMax: number;
303
+ linkUrlMax: number;
304
+ definitionBytesMax: number;
305
+ };
306
+ tileKinds: {
307
+ kind: DashboardTileKind;
308
+ description: string;
309
+ }[];
310
+ clusterCards: DashboardClusterCard[];
311
+ orgCards: DashboardOrgCard[];
312
+ fleetSearchFields: {
313
+ cluster: DashboardCatalogueSearchField[];
314
+ org: DashboardCatalogueSearchField[];
315
+ };
316
+ charts: {
317
+ /** False where the flag `control.dashboardCharts` is off. */
318
+ enabled: boolean;
319
+ grammar: string;
320
+ queryMaxLength: number;
321
+ renders: DashboardChartRender[];
322
+ grains: ChartGrain[];
323
+ windowUnits: ChartWindowUnit[];
324
+ defaults: {
325
+ grain: ChartGrain;
326
+ window: {
327
+ amount: number;
328
+ unit: ChartWindowUnit;
329
+ };
330
+ top: number;
331
+ };
332
+ topMax: number;
333
+ metrics: DashboardCatalogueChartMetric[];
334
+ };
335
+ }
336
+ export {};
@@ -0,0 +1,70 @@
1
+ const DASHBOARD_TILES_MAX = 20;
2
+ const DASHBOARD_GRID_COLUMNS = 12;
3
+ const DASHBOARD_TILE_ROWS_MAX = 24;
4
+ const DASHBOARD_GRID_ROWS_MAX = DASHBOARD_TILES_MAX * DASHBOARD_TILE_ROWS_MAX;
5
+ const DASHBOARD_TITLE_MAX = 120;
6
+ const DASHBOARD_DEFINITION_BYTES_MAX = 32768;
7
+ const DASHBOARD_PAGE_SIZE_MAX = 200;
8
+ const DASHBOARD_PAGE_SIZE_DEFAULT = 200;
9
+ const DASHBOARD_DEFINITION_VERSION = 3;
10
+ const DASHBOARD_TILE_KINDS = [
11
+ "fleet-query",
12
+ "annotations",
13
+ "cluster-detail",
14
+ "org-detail",
15
+ "heading",
16
+ "note",
17
+ "link",
18
+ "chart"
19
+ ];
20
+ const DASHBOARD_CLUSTER_CARDS = [
21
+ "identity",
22
+ "component-status",
23
+ "datacenter",
24
+ "generation",
25
+ "plan",
26
+ "backup-encryption",
27
+ "settings-flags",
28
+ "external-idp",
29
+ "data-filters",
30
+ "auto-pause",
31
+ "change-history",
32
+ "disk-usage"
33
+ ];
34
+ const DASHBOARD_ORG_CARDS = [
35
+ "summary",
36
+ "details",
37
+ "sales-plan",
38
+ "queued-operations",
39
+ "clusters",
40
+ "managed-llm",
41
+ "recent-activity"
42
+ ];
43
+ const DASHBOARD_ENTITY_ID_MAX = 64;
44
+ const DASHBOARD_NOTE_MAX = 1e3;
45
+ const DASHBOARD_LINK_URL_MAX = 1e3;
46
+ const DASHBOARD_CHART_RENDERS = [
47
+ "line",
48
+ "bar",
49
+ "stacked-bar",
50
+ "stat"
51
+ ];
52
+ export {
53
+ DASHBOARD_CHART_RENDERS,
54
+ DASHBOARD_CLUSTER_CARDS,
55
+ DASHBOARD_DEFINITION_BYTES_MAX,
56
+ DASHBOARD_DEFINITION_VERSION,
57
+ DASHBOARD_ENTITY_ID_MAX,
58
+ DASHBOARD_GRID_COLUMNS,
59
+ DASHBOARD_GRID_ROWS_MAX,
60
+ DASHBOARD_LINK_URL_MAX,
61
+ DASHBOARD_NOTE_MAX,
62
+ DASHBOARD_ORG_CARDS,
63
+ DASHBOARD_PAGE_SIZE_DEFAULT,
64
+ DASHBOARD_PAGE_SIZE_MAX,
65
+ DASHBOARD_TILES_MAX,
66
+ DASHBOARD_TILE_KINDS,
67
+ DASHBOARD_TILE_ROWS_MAX,
68
+ DASHBOARD_TITLE_MAX
69
+ };
70
+ //# sourceMappingURL=Dashboard.dto.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/dtos/Dashboard.dto.ts"],
4
+ "sourcesContent": ["/*\n * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH\n * under one or more contributor license agreements. Licensed under a commercial license.\n * You may not use this file except in compliance with the commercial license.\n */\n\nimport type {\n ChartGrain,\n ChartSpec,\n ChartUnit,\n ChartWindowUnit,\n} from '../charts/chart-spec.js'\nimport type {\n SearchFieldCapability,\n SearchFieldType,\n} from '../search/fields.js'\nimport type { AnnotationEntityKind, AnnotationKind } from './Annotation.dto.js'\n\n/**\n * The wire types of the dashboards of Camunda Control.\n *\n * A dashboard stores QUESTIONS and never answers. A tile holds the filters of\n * the page that it came from, and the dashboard runs them again each time a\n * reader opens it. So a stored dashboard stays small, and it never holds a\n * copy of fleet data that can go stale or leak.\n *\n * control-backend and control-frontend both read this file, so it holds no\n * logic with I/O and no dependency.\n */\n\n/** DASHBOARD_TILES_MAX is the most tiles that one dashboard can hold. */\nexport const DASHBOARD_TILES_MAX = 20\n\n/** DASHBOARD_GRID_COLUMNS is the width of the tile grid, in columns. */\nexport const DASHBOARD_GRID_COLUMNS = 12\n\n/** DASHBOARD_TILE_ROWS_MAX is the tallest tile, in grid rows. */\nexport const DASHBOARD_TILE_ROWS_MAX = 24\n\n/**\n * DASHBOARD_GRID_ROWS_MAX is the lowest row that a tile can start on. It is\n * the height of 20 tiles of the tallest size, one under the other, so a\n * compact grid never reaches it.\n */\nexport const DASHBOARD_GRID_ROWS_MAX =\n DASHBOARD_TILES_MAX * DASHBOARD_TILE_ROWS_MAX\n\n/** DASHBOARD_TITLE_MAX is the longest title of a dashboard or of a tile. */\nexport const DASHBOARD_TITLE_MAX = 120\n\n/**\n * DASHBOARD_DEFINITION_BYTES_MAX is the largest definition that the backend\n * stores, as JSON text. Twenty tiles of filters need a few kilobytes, so a\n * larger body is a client that tries to store data and not filters.\n */\nexport const DASHBOARD_DEFINITION_BYTES_MAX = 32_768\n\n/** DASHBOARD_PAGE_SIZE_MAX is the most dashboards that one list page holds. */\nexport const DASHBOARD_PAGE_SIZE_MAX = 200\n\n/** DASHBOARD_PAGE_SIZE_DEFAULT is the list page size when a caller sends none. */\nexport const DASHBOARD_PAGE_SIZE_DEFAULT = 200\n\n/**\n * DASHBOARD_DEFINITION_VERSION is the `schemaVersion` that this code writes.\n *\n * Raise it when the shape of the definition changes, add the old shape to\n * `StoredDashboardDefinition`, and teach `upgradeDashboardDefinition` to read\n * it. A row is never rewritten in place: it moves to the new version on its\n * next save.\n */\nexport const DASHBOARD_DEFINITION_VERSION = 3\n\n/**\n * Every kind of tile.\n *\n * `fleet-query` and `annotations` run saved filters. `cluster-detail` and\n * `org-detail` show one card of the page of one cluster or one organization.\n * `heading`, `note` and `link` hold text that a person wrote, and fetch\n * nothing. `chart` runs a chart query on HDP.\n */\nexport const DASHBOARD_TILE_KINDS = [\n 'fleet-query',\n 'annotations',\n 'cluster-detail',\n 'org-detail',\n 'heading',\n 'note',\n 'link',\n 'chart',\n] as const\n\nexport type DashboardTileKind = (typeof DASHBOARD_TILE_KINDS)[number]\n\n/** Where a tile sits on the grid, in columns and rows from the top left. */\nexport interface DashboardTileLayout {\n x: number\n y: number\n w: number\n h: number\n}\n\n/**\n * The search params of a Fleet query page, as that page writes them.\n *\n * The backend stores them as they are and checks only their shape: flat\n * values, no objects. The keys belong to the Fleet query page, so the\n * frontend validates them on read with the same function that validates the\n * URL. A tile with a key that this function drops does not run, because the\n * query would be wider than the one that was saved.\n */\nexport type DashboardFleetQuery = Record<\n string,\n string | number | boolean | string[]\n>\n\n/** The filters of the Notes & tags page. */\nexport interface DashboardAnnotationsQuery {\n kind?: AnnotationKind\n entityKind?: AnnotationEntityKind\n tag?: string\n q?: string\n}\n\n/**\n * The cards of the Overview tab of a cluster that a dashboard can show.\n *\n * The id names the card and never its content. The tile reads the cluster\n * again each time it is in view, so it shows the current state.\n */\nexport const DASHBOARD_CLUSTER_CARDS = [\n 'identity',\n 'component-status',\n 'datacenter',\n 'generation',\n 'plan',\n 'backup-encryption',\n 'settings-flags',\n 'external-idp',\n 'data-filters',\n 'auto-pause',\n 'change-history',\n 'disk-usage',\n] as const\n\nexport type DashboardClusterCard = (typeof DASHBOARD_CLUSTER_CARDS)[number]\n\n/** The cards of the Overview tab of an organization. */\nexport const DASHBOARD_ORG_CARDS = [\n 'summary',\n 'details',\n 'sales-plan',\n 'queued-operations',\n 'clusters',\n 'managed-llm',\n 'recent-activity',\n] as const\n\nexport type DashboardOrgCard = (typeof DASHBOARD_ORG_CARDS)[number]\n\n/** DASHBOARD_ENTITY_ID_MAX is the longest cluster id or organization id. */\nexport const DASHBOARD_ENTITY_ID_MAX = 64\n\n/**\n * DASHBOARD_NOTE_MAX is the longest text of a note tile.\n *\n * Twenty full notes of ASCII text fit in `DASHBOARD_DEFINITION_BYTES_MAX`.\n * Text with characters of more than one UTF-8 byte can pass that limit first,\n * so the frontend measures the whole definition with\n * `dashboardDefinitionBytes` before it saves.\n */\nexport const DASHBOARD_NOTE_MAX = 1000\n\n/** DASHBOARD_LINK_URL_MAX is the longest address of a link tile. */\nexport const DASHBOARD_LINK_URL_MAX = 1000\n\n/**\n * How a chart tile draws its result. `stat` is one number with a sparkline.\n * Each render is a chart of `@camunda/design-system`, which has no area chart.\n */\nexport const DASHBOARD_CHART_RENDERS = [\n 'line',\n 'bar',\n 'stacked-bar',\n 'stat',\n] as const\n\nexport type DashboardChartRender = (typeof DASHBOARD_CHART_RENDERS)[number]\n\n/**\n * A chart query and how to draw it. The tile stores the structured spec and\n * not the text, so a later change of the grammar cannot break a stored tile.\n */\nexport interface DashboardChartQuery extends ChartSpec {\n render: DashboardChartRender\n}\n\n/** One card of one cluster. */\nexport interface DashboardClusterDetailQuery {\n clusterId: string\n card: DashboardClusterCard\n}\n\n/** One card of one organization. */\nexport interface DashboardOrgDetailQuery {\n orgId: string\n card: DashboardOrgCard\n}\n\ninterface DashboardTileBaseV1 {\n /** Unique in its dashboard. The client makes it. */\n id: string\n title: string\n layout: DashboardTileLayout\n}\n\nexport interface DashboardFleetQueryTileV1 extends DashboardTileBaseV1 {\n kind: 'fleet-query'\n query: DashboardFleetQuery\n}\n\nexport interface DashboardAnnotationsTileV1 extends DashboardTileBaseV1 {\n kind: 'annotations'\n query: DashboardAnnotationsQuery\n}\n\nexport type DashboardTileV1 =\n | DashboardFleetQueryTileV1\n | DashboardAnnotationsTileV1\n\nexport interface DashboardDefinitionV1 {\n schemaVersion: 1\n tiles: DashboardTileV1[]\n}\n\nexport interface DashboardClusterDetailTileV2 extends DashboardTileBaseV1 {\n kind: 'cluster-detail'\n query: DashboardClusterDetailQuery\n}\n\nexport interface DashboardOrgDetailTileV2 extends DashboardTileBaseV1 {\n kind: 'org-detail'\n query: DashboardOrgDetailQuery\n}\n\n/** A section title. The `title` of the tile is the text. */\nexport interface DashboardHeadingTileV2 extends DashboardTileBaseV1 {\n kind: 'heading'\n}\n\n/** Plain text. Line breaks stay, and nothing in it is markup. */\nexport interface DashboardNoteTileV2 extends DashboardTileBaseV1 {\n kind: 'note'\n body: string\n}\n\n/**\n * A link to a page of Control (a path that starts with `/`) or to an\n * `https://` address. `isSafeDashboardLink` holds the rule.\n */\nexport interface DashboardLinkTileV2 extends DashboardTileBaseV1 {\n kind: 'link'\n url: string\n}\n\n/**\n * Version 2 adds kinds of tiles and changes no tile of version 1. A version 1\n * row is a version 2 row with a lower number, so an upgrade only sets the\n * number.\n *\n * The number moved because the kinds are new. A pod with version 1 code\n * answers `unsupportedVersion` for a row with a new kind, and not a 500 from\n * its serializer. A row with no new kind stays version 1, so that pod still\n * reads it (`toStoredDashboardDefinition`).\n */\nexport type DashboardTileV2 =\n | DashboardTileV1\n | DashboardClusterDetailTileV2\n | DashboardOrgDetailTileV2\n | DashboardHeadingTileV2\n | DashboardNoteTileV2\n | DashboardLinkTileV2\n\nexport interface DashboardDefinitionV2 {\n schemaVersion: 2\n tiles: DashboardTileV2[]\n}\n\n/** A chart of a metric of HDP. accounts-backend runs the query. */\nexport interface DashboardChartTileV3 extends DashboardTileBaseV1 {\n kind: 'chart'\n query: DashboardChartQuery\n}\n\n/**\n * Version 3 adds the `chart` kind and changes no tile of version 2, for the\n * same reason that version 2 moved the number. A row with no chart tile stays\n * at version 1 or 2 (`toStoredDashboardDefinition`).\n */\nexport type DashboardTileV3 = DashboardTileV2 | DashboardChartTileV3\n\nexport interface DashboardDefinitionV3 {\n schemaVersion: 3\n tiles: DashboardTileV3[]\n}\n\n/**\n * Every shape that a row can hold. A row keeps its old shape until somebody\n * saves the dashboard again.\n */\nexport type StoredDashboardDefinition =\n | DashboardDefinitionV1\n | DashboardDefinitionV2\n | DashboardDefinitionV3\n\n/** The current shape. Every DTO carries this one. */\nexport type DashboardDefinition = DashboardDefinitionV3\nexport type DashboardTile = DashboardTileV3\nexport type DashboardFleetQueryTile = DashboardFleetQueryTileV1\nexport type DashboardAnnotationsTile = DashboardAnnotationsTileV1\nexport type DashboardClusterDetailTile = DashboardClusterDetailTileV2\nexport type DashboardOrgDetailTile = DashboardOrgDetailTileV2\nexport type DashboardHeadingTile = DashboardHeadingTileV2\nexport type DashboardNoteTile = DashboardNoteTileV2\nexport type DashboardLinkTile = DashboardLinkTileV2\nexport type DashboardChartTile = DashboardChartTileV3\n\n/**\n * `Omit` on a union merges its members into one shape. This one omits from\n * each member, so the kinds stay apart.\n */\ntype OmitEach<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never\n\n/** A tile as a client adds it to a dashboard. The backend places it. */\nexport type DashboardNewTile = OmitEach<DashboardTile, 'layout'>\n\n/** Who created or archived a dashboard. The same shape as `ApprovalActor`. */\nexport interface DashboardActor {\n userId: string\n email: string\n}\n\n/**\n * One dashboard in a list, without its tiles.\n *\n * The sidebar reads a list of these, so it never parses a definition.\n */\nexport interface DashboardSummaryDto {\n id: string\n title: string\n tileCount: number\n createdBy: DashboardActor\n createdAt: string\n updatedAt: string\n /** Set when the dashboard is archived. An archived dashboard is read-only. */\n archivedAt?: string\n archivedBy?: DashboardActor\n /** True when the CALLER pinned it. A pin is personal. */\n pinned: boolean\n}\n\nexport interface DashboardDto extends DashboardSummaryDto {\n definition: DashboardDefinition\n /**\n * The version that the optimistic lock of a save compares. Send back the\n * value of the read that the edit started from.\n */\n version: number\n}\n\nexport interface DashboardListDto {\n dashboards: DashboardSummaryDto[]\n page: { limit: number; offset: number; hasMore: boolean }\n}\n\n/** One Lucene field that a search or a chart filter can use. */\nexport interface DashboardCatalogueSearchField {\n field: string\n label: string\n description: string\n type: SearchFieldType\n capabilities: SearchFieldCapability[]\n enumValues?: string[]\n example: string\n}\n\n/** One metric of the chart tiles, without its SQL. */\nexport interface DashboardCatalogueChartMetric {\n id: string\n label: string\n description: string\n unit: ChartUnit\n dimensions: { id: string; label: string; description: string }[]\n filters: DashboardCatalogueSearchField[]\n grains: ChartGrain[]\n maxWindowDays: number\n}\n\n/**\n * What a client must know to write a dashboard definition: the kinds of tiles,\n * the cards, the chart metrics and the limits. The answer of\n * `GET /api/dashboards/catalogue`.\n */\nexport interface DashboardCatalogue {\n definitionVersion: number\n limits: {\n tiles: number\n gridColumns: number\n tileRowsMax: number\n titleMax: number\n noteMax: number\n linkUrlMax: number\n definitionBytesMax: number\n }\n tileKinds: { kind: DashboardTileKind; description: string }[]\n clusterCards: DashboardClusterCard[]\n orgCards: DashboardOrgCard[]\n fleetSearchFields: {\n cluster: DashboardCatalogueSearchField[]\n org: DashboardCatalogueSearchField[]\n }\n charts: {\n /** False where the flag `control.dashboardCharts` is off. */\n enabled: boolean\n grammar: string\n queryMaxLength: number\n renders: DashboardChartRender[]\n grains: ChartGrain[]\n windowUnits: ChartWindowUnit[]\n defaults: {\n grain: ChartGrain\n window: { amount: number; unit: ChartWindowUnit }\n top: number\n }\n topMax: number\n metrics: DashboardCatalogueChartMetric[]\n }\n}\n"],
5
+ "mappings": "AA+BO,MAAM,sBAAsB;AAG5B,MAAM,yBAAyB;AAG/B,MAAM,0BAA0B;AAOhC,MAAM,0BACX,sBAAsB;AAGjB,MAAM,sBAAsB;AAO5B,MAAM,iCAAiC;AAGvC,MAAM,0BAA0B;AAGhC,MAAM,8BAA8B;AAUpC,MAAM,+BAA+B;AAUrC,MAAM,uBAAuB;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAwCO,MAAM,0BAA0B;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAKO,MAAM,sBAAsB;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAKO,MAAM,0BAA0B;AAUhC,MAAM,qBAAqB;AAG3B,MAAM,yBAAyB;AAM/B,MAAM,0BAA0B;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;",
6
+ "names": []
7
+ }
@@ -1,59 +1,93 @@
1
1
  /**
2
- * This type gives the shape of the feature flags of the management apps. It is
3
- * also the body of `GET external/feature-flags` on accounts-backend.
2
+ * The flags of one caller, as `GET /api/feature-flags/evaluate` of
3
+ * control-backend and `GET external/feature-flags` of accounts-backend send
4
+ * them. Nested by the segments of the key: `console.byoidp` is
5
+ * `{ console: { byoidp: true } }`.
4
6
  *
5
- * The shape is here, but the evaluation is not. `features({stage, orgId,
6
- * email})` in `@camunda-cloud/featureflags` stays the only place that decides
7
- * if a flag is on. That package is private, thus a published package
8
- * (`@camunda/ccma-api`, `@camunda/ccma-saas-frontend`) cannot name the type
9
- * from there. `@camunda-cloud/featureflags` re-exports `Features` from here.
10
- * Thus the type has one definition, and every existing import path still works.
7
+ * The keys are not typed. The flag table of each stage holds them, and a key
8
+ * that the table does not hold is not in the answer. A reader takes one flag
9
+ * by its key and reads a missing one as off: `isFeatureOn` of
10
+ * `@camunda-cloud/featureflags`, or `useC4FeatureFlag('console.byoidp')` in
11
+ * c4.
12
+ */
13
+ export interface FeatureFlagAnswer {
14
+ [segment: string]: boolean | FeatureFlagAnswer;
15
+ }
16
+ /**
17
+ * One feature flag, as a row of the table of control-backend.
11
18
  *
12
- * A c4 host reads one flag with `useC4FeatureFlag('console.appIntegrations')`
13
- * — a dot path into this object.
19
+ * Each stage holds its own database, thus a row is the value of THAT stage. A
20
+ * flag is on for a caller when `enabled` is true, when the org of the caller
21
+ * is in `orgIds`, or when the domain of the email of the caller is in
22
+ * `emailDomains`. `evaluateFlags` of `@camunda-cloud/featureflags` holds that
23
+ * rule.
14
24
  */
15
- export interface Features {
16
- console: {
17
- admin: {
18
- overrideOrgRole: boolean;
19
- };
20
- clusterSuspendButton: boolean;
21
- clusterSleepWarning: boolean;
22
- backupRestore: boolean;
23
- failover: boolean;
24
- privateLink87: boolean;
25
- byoidp: boolean;
26
- optimizeUnsetOnDisable: boolean;
27
- appIntegrations: boolean;
28
- orgClusterDefaults: boolean;
29
- releaseTrainSanityFix: boolean;
30
- hubHelpCenterLinks: boolean;
31
- legacyModelerApiNaming: boolean;
32
- backupScheduleApi: boolean;
33
- clusterCreationBlocked: boolean;
34
- deferSpecChangeWhileAsleep: boolean;
35
- clusterDuplication: boolean;
36
- hubUpgradeBanner: boolean;
37
- };
38
- control: {
39
- frontendTelemetry: boolean;
40
- approvals: boolean;
41
- annotations: boolean;
42
- clusterHostingCostBreakdown: boolean;
43
- /** Per-cluster disk usage chart (Elasticsearch and Zeebe) on the cluster page. */
44
- elasticsearchUsageChart: boolean;
45
- fleetHostingCost: boolean;
46
- };
47
- accounts: {
48
- moveClusterOrg: boolean;
49
- orgLimitAuditLog: boolean;
50
- orgReservationAuditLog: boolean;
51
- deleteLiteLLMKeyOnTrialExpiry: boolean;
52
- };
53
- shared: {
54
- cyberpunkBrutalism: boolean;
55
- tenantsValueMetric: boolean;
56
- hdpValueMetricsFor2025: boolean;
57
- permissionsRework: boolean;
58
- };
25
+ export interface FeatureFlagDto {
26
+ id: string;
27
+ /** The dot path, for example `console.byoidp`. It cannot change. */
28
+ key: string;
29
+ /** Why the flag exists. */
30
+ description: string;
31
+ /** The value for everybody. */
32
+ enabled: boolean;
33
+ /** Organizations that get the flag when `enabled` is false. */
34
+ orgIds: string[];
35
+ /** Lower-case email domains, with no `@`. */
36
+ emailDomains: string[];
37
+ /**
38
+ * The team that owns the flag, for example `team-console`. Absent on an
39
+ * older row that nobody gave an owner.
40
+ */
41
+ owner?: string;
42
+ /**
43
+ * The day after which the flag is late, as `YYYY-MM-DD`. The page warns
44
+ * from that day on. Absent for a flag that has no end, such as a permission.
45
+ */
46
+ expiresAt?: string;
47
+ createdAt: string;
48
+ /**
49
+ * The email of the person who made the row, or the name of the seed
50
+ * migration. `UNKNOWN_ACTOR_EMAIL` for a token with no email.
51
+ */
52
+ createdBy: string;
53
+ updatedAt: string;
54
+ /** The email of the person who changed the row last, as `createdBy`. */
55
+ updatedBy: string;
59
56
  }
57
+ /**
58
+ * The answer of `GET /api/feature-flags`: every row of the stage, and the two
59
+ * versions that show whether the other services read the rows yet.
60
+ */
61
+ export interface FeatureFlagListDto {
62
+ flags: FeatureFlagDto[];
63
+ /** The version of the table. Every write raises it. */
64
+ tableVersion: number;
65
+ /**
66
+ * The version that the Redis key holds, which console-backend and
67
+ * accounts-backend read. Absent on a stage with no Redis, and when
68
+ * control-backend cannot read the key. While it is lower than
69
+ * `tableVersion`, those services still answer from the rows before.
70
+ */
71
+ publishedVersion?: number;
72
+ }
73
+ /** What a create sends. The key cannot change after this. */
74
+ export interface CreateFeatureFlagDto {
75
+ key: string;
76
+ description: string;
77
+ enabled: boolean;
78
+ orgIds: string[];
79
+ emailDomains: string[];
80
+ /** Required for a new flag: a flag with no owner is a flag nobody removes. */
81
+ owner: string;
82
+ /** `YYYY-MM-DD`. Give it for a flag that gates a rollout. */
83
+ expiresAt?: string;
84
+ }
85
+ type EditableFeatureFlagFields = Omit<CreateFeatureFlagDto, 'key'>;
86
+ /**
87
+ * What an edit sends: at least one field. A field that is absent stays as it
88
+ * is. The route answers 400 to an empty body.
89
+ */
90
+ export type UpdateFeatureFlagDto = {
91
+ [Field in keyof EditableFeatureFlagFields]: Pick<EditableFeatureFlagFields, Field> & Partial<EditableFeatureFlagFields>;
92
+ }[keyof EditableFeatureFlagFields];
93
+ export {};