@camunda/ccma-shared-types 1.1.0 → 2.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 (70) hide show
  1. package/dist/_tests/approvals/policy.spec.d.ts +1 -0
  2. package/dist/approvals/policy.d.ts +109 -0
  3. package/dist/approvals/policy.js +123 -0
  4. package/dist/approvals/policy.js.map +7 -0
  5. package/dist/config/camundi-permission-rules.js +17 -5
  6. package/dist/config/camundi-permission-rules.js.map +2 -2
  7. package/dist/constants/misc.const.d.ts +21 -0
  8. package/dist/constants/misc.const.js +5 -1
  9. package/dist/constants/misc.const.js.map +2 -2
  10. package/dist/constants/v2-list.const.d.ts +12 -0
  11. package/dist/constants/v2-list.const.js +9 -0
  12. package/dist/constants/v2-list.const.js.map +7 -0
  13. package/dist/constants/version-gates.const.d.ts +9 -2
  14. package/dist/constants/version-gates.const.js +1 -1
  15. package/dist/constants/version-gates.const.js.map +2 -2
  16. package/dist/dtos/ApprovalJob.dto.d.ts +83 -0
  17. package/dist/dtos/ApprovalJob.dto.js +14 -0
  18. package/dist/dtos/ApprovalJob.dto.js.map +7 -0
  19. package/dist/dtos/ClusterCreationDefaults.dto.d.ts +96 -0
  20. package/dist/dtos/ClusterCreationDefaults.dto.js +93 -0
  21. package/dist/dtos/ClusterCreationDefaults.dto.js.map +7 -0
  22. package/dist/dtos/CommonCluster.dto.d.ts +1 -0
  23. package/dist/dtos/ControlV2.dto.d.ts +103 -1
  24. package/dist/dtos/FeatureFlags.dto.d.ts +4 -2
  25. package/dist/dtos/Generations.dto.d.ts +10 -0
  26. package/dist/dtos/Generations.dto.js +36 -2
  27. package/dist/dtos/Generations.dto.js.map +2 -2
  28. package/dist/dtos/Hdp.dto.d.ts +29 -0
  29. package/dist/dtos/Organization.dto.d.ts +29 -0
  30. package/dist/dtos/Organization.dto.js.map +2 -2
  31. package/dist/enums/AuditEntity.enum.d.ts +2 -0
  32. package/dist/enums/AuditEntity.enum.js +2 -0
  33. package/dist/enums/AuditEntity.enum.js.map +2 -2
  34. package/dist/enums/AuditService.enum.d.ts +2 -1
  35. package/dist/enums/AuditService.enum.js +1 -0
  36. package/dist/enums/AuditService.enum.js.map +2 -2
  37. package/dist/enums/SystemAuditEntity.enum.d.ts +6 -2
  38. package/dist/enums/SystemAuditEntity.enum.js +4 -0
  39. package/dist/enums/SystemAuditEntity.enum.js.map +2 -2
  40. package/dist/index.d.ts +14 -7
  41. package/dist/index.js +53 -1
  42. package/dist/index.js.map +2 -2
  43. package/dist/permissions/combo.js +3 -0
  44. package/dist/permissions/combo.js.map +2 -2
  45. package/dist/permissions/combo.optionalTelemetry.spec.d.ts +1 -0
  46. package/dist/permissions/console.permissions.d.ts +2 -0
  47. package/dist/permissions/console.permissions.js +13 -1
  48. package/dist/permissions/console.permissions.js.map +2 -2
  49. package/dist/search/cluster-search-fields.js +9 -1
  50. package/dist/search/cluster-search-fields.js.map +2 -2
  51. package/dist/search/compiler.d.ts +25 -0
  52. package/dist/search/compiler.js +12 -3
  53. package/dist/search/compiler.js.map +2 -2
  54. package/dist/search/index.d.ts +1 -1
  55. package/dist/search/index.js +4 -0
  56. package/dist/search/index.js.map +2 -2
  57. package/dist/types/ClusterBulkOperation.type.d.ts +28 -0
  58. package/dist/types/ClusterPlanTypeAvailabilityClass.type.d.ts +11 -0
  59. package/dist/types/ClusterPlanTypeAvailabilityClass.type.js +4 -0
  60. package/dist/types/ClusterPlanTypeAvailabilityClass.type.js.map +2 -2
  61. package/dist/types/Roles.d.ts +1 -1
  62. package/dist/types/Roles.js.map +2 -2
  63. package/dist/utils/camundiPermissionAugmenter.utils.d.ts +14 -0
  64. package/dist/utils/camundiPermissionAugmenter.utils.js +4 -0
  65. package/dist/utils/camundiPermissionAugmenter.utils.js.map +2 -2
  66. package/dist/utils/camundiPermissionAugmenter.utils.spec.d.ts +1 -0
  67. package/dist/utils/versionCheck.utils.d.ts +39 -0
  68. package/dist/utils/versionCheck.utils.js +45 -4
  69. package/dist/utils/versionCheck.utils.js.map +2 -2
  70. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/search/compiler.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 {\n LuceneQueryError,\n type QueryNode,\n type RangeNode,\n type SearchTermOperator,\n type TermNode,\n} from './ast.js'\n\n// ============================================================================\n// AST \u2192 parameterized SQL compiler.\n//\n// Entity-agnostic: the backend supplies a per-field {@link FieldBinding} map (the\n// SQL columns / computed resolvers stay backend-side), and this turns a parsed\n// query into a single parameterized SQL string for `qb.andWhere(sql, params)`.\n// Field names are whitelisted against the bindings; every value is a bound\n// parameter; wildcards are escaped \u2014 so a query can never inject SQL.\n// ============================================================================\n\n/** SQL binding for one searchable field (values live backend-side, not in the FE). */\nexport type FieldBinding =\n | {\n kind: 'string'\n /** SQL column expression, e.g. `c.name` or `planType.name`. */\n column: string\n /** Cast the column to text before matching (uuid columns). */\n cast?: boolean\n /** `substring` \u2192 ILIKE %v%; `exact` \u2192 case-insensitive equality. */\n match: 'substring' | 'exact'\n }\n | { kind: 'boolean'; column: string }\n /** Presence/absence of a nullable column (e.g. active-modification FK). */\n | { kind: 'nullable'; column: string }\n | { kind: 'date'; column: string }\n | {\n kind: 'computed'\n /** Column the resolved id set is matched against (e.g. `c.uuid`). */\n idColumn: string\n /** Resolve an equality value to matching ids (in-memory / config). */\n resolve: (value: string) => string[]\n }\n\nexport interface CompileContext {\n /** Field name \u2192 SQL binding. Keys are the whitelisted, canonical field names. */\n bindings: Record<string, FieldBinding>\n /** Fields a bare term ORs over (must be `string` bindings); always substring. */\n defaultFields: readonly string[]\n /** Unique-per-call-site parameter prefix (avoids clashing with other params). */\n paramPrefix: string\n}\n\nexport interface CompiledQuery {\n sql: string\n params: Record<string, unknown>\n}\n\nclass Compiler {\n private readonly params: Record<string, unknown> = {}\n private counter = 0\n /** Lowercased field name \u2192 { canonical, binding }, for case-insensitive lookup. */\n private readonly lookup: Map<\n string,\n { canonical: string; binding: FieldBinding }\n >\n\n constructor(private readonly ctx: CompileContext) {\n this.lookup = new Map(\n Object.entries(ctx.bindings).map(([field, binding]) => [\n field.toLowerCase(),\n { canonical: field, binding },\n ]),\n )\n }\n\n compile(node: QueryNode): CompiledQuery {\n return { sql: this.node(node), params: this.params }\n }\n\n private node(node: QueryNode): string {\n switch (node.kind) {\n case 'and':\n return `(${this.node(node.left)} AND ${this.node(node.right)})`\n case 'or':\n return `(${this.node(node.left)} OR ${this.node(node.right)})`\n case 'not':\n return `(NOT ${this.node(node.child)})`\n case 'term':\n return this.term(node)\n case 'range':\n return this.range(node)\n }\n }\n\n private term(node: TermNode): string {\n if (node.field === undefined) {\n return this.bareTerm(node.value)\n }\n const { canonical, binding } = this.resolveField(node.field)\n switch (binding.kind) {\n case 'string':\n this.requireMatchOperator(canonical, node.operator)\n return this.stringMatch(binding, node.value)\n case 'boolean':\n this.requireMatchOperator(canonical, node.operator)\n return `${binding.column} = ${this.bind(this.parseBoolean(canonical, node.value))}`\n case 'nullable':\n this.requireMatchOperator(canonical, node.operator)\n return this.parseBoolean(canonical, node.value)\n ? `${binding.column} IS NOT NULL`\n : `${binding.column} IS NULL`\n case 'computed':\n this.requireMatchOperator(canonical, node.operator)\n return this.computedMatch(binding, node.value)\n case 'date':\n return this.dateTerm(binding, canonical, node.operator, node.value)\n }\n }\n\n private range(node: RangeNode): string {\n const { canonical, binding } = this.resolveField(node.field)\n if (binding.kind !== 'date') {\n throw new LuceneQueryError(\n `Field \"${canonical}\" does not support ranges.`,\n 'bad-operator',\n )\n }\n const lowerOp = node.lowerInclusive ? '>=' : '>'\n const upperOp = node.upperInclusive ? '<=' : '<'\n const lower = this.bind(this.parseDate(canonical, node.lower))\n const upper = this.bind(this.parseDate(canonical, node.upper))\n return `(${binding.column} ${lowerOp} ${lower} AND ${binding.column} ${upperOp} ${upper})`\n }\n\n // --- field kinds ----------------------------------------------------------\n\n private bareTerm(value: string): string {\n const clauses = this.ctx.defaultFields.map((field) => {\n const entry = this.lookup.get(field.toLowerCase())\n if (!entry || entry.binding.kind !== 'string') {\n // A server-side registry/binding bug, not a bad query \u2014 throw a plain\n // Error so the routers surface it as a 5xx, never a 400.\n throw new Error(\n `Search misconfigured: default field \"${field}\" must be a string binding.`,\n )\n }\n const { column, cast } = entry.binding\n const target = cast ? `CAST(${column} AS TEXT)` : column\n return `${target} ILIKE ${this.bind(likeArgument(value, 'substring'))}`\n })\n return clauses.length === 1 ? clauses[0] : `(${clauses.join(' OR ')})`\n }\n\n private stringMatch(\n binding: Extract<FieldBinding, { kind: 'string' }>,\n value: string,\n ): string {\n const target = binding.cast\n ? `CAST(${binding.column} AS TEXT)`\n : binding.column\n return `${target} ILIKE ${this.bind(likeArgument(value, binding.match))}`\n }\n\n private computedMatch(\n binding: Extract<FieldBinding, { kind: 'computed' }>,\n value: string,\n ): string {\n const ids = binding.resolve(value)\n if (ids.length === 0) {\n // No entity matches this value \u2014 a guaranteed-false predicate (a\n // surrounding NOT correctly flips it to all-rows).\n return '1 = 0'\n }\n return `${binding.idColumn} IN (${this.bind(ids, true)})`\n }\n\n private dateTerm(\n binding: Extract<FieldBinding, { kind: 'date' }>,\n canonical: string,\n operator: SearchTermOperator,\n value: string,\n ): string {\n if (operator === ':') {\n // Equality on a date means \"that calendar day\" (UTC): [day, nextDay).\n const start = this.parseDate(canonical, value)\n const startDay = new Date(\n Date.UTC(\n start.getUTCFullYear(),\n start.getUTCMonth(),\n start.getUTCDate(),\n ),\n )\n const nextDay = new Date(startDay.getTime() + 24 * 60 * 60 * 1000)\n return `(${binding.column} >= ${this.bind(startDay.toISOString())} AND ${binding.column} < ${this.bind(nextDay.toISOString())})`\n }\n const bound = this.parseDate(canonical, value).toISOString()\n return `${binding.column} ${operator} ${this.bind(bound)}`\n }\n\n // --- validation helpers ---------------------------------------------------\n\n private resolveField(field: string): {\n canonical: string\n binding: FieldBinding\n } {\n const entry = this.lookup.get(field.toLowerCase())\n if (!entry) {\n const suggestion = closestField(\n field,\n [...this.lookup.values()].map((value) => value.canonical),\n )\n throw new LuceneQueryError(\n `Unknown field \"${field}\".${suggestion ? ` Did you mean \"${suggestion}\"?` : ''}`,\n 'unknown-field',\n suggestion,\n )\n }\n return entry\n }\n\n private requireMatchOperator(\n field: string,\n operator: SearchTermOperator,\n ): void {\n if (operator !== ':') {\n throw new LuceneQueryError(\n `Field \"${field}\" supports only \"field:value\", not \"${operator}\".`,\n 'bad-operator',\n )\n }\n }\n\n private parseBoolean(field: string, value: string): boolean {\n const normalized = value.trim().toLowerCase()\n if (normalized === 'true') {\n return true\n }\n if (normalized === 'false') {\n return false\n }\n throw new LuceneQueryError(\n `Field \"${field}\" expects true or false, got \"${value}\".`,\n 'bad-value',\n )\n }\n\n private parseDate(field: string, value: string): Date {\n const parsed = new Date(value)\n if (Number.isNaN(parsed.getTime())) {\n throw new LuceneQueryError(\n `Field \"${field}\" expects a date (e.g. 2024-01-31), got \"${value}\".`,\n 'bad-value',\n )\n }\n return parsed\n }\n\n private bind(value: unknown, isList = false): string {\n const name = `${this.ctx.paramPrefix}_${this.counter++}`\n this.params[name] = value\n return isList ? `:...${name}` : `:${name}`\n }\n}\n\n/** Compile a parsed query into a single parameterized SQL fragment. */\nexport const compileQuery = (\n node: QueryNode,\n ctx: CompileContext,\n): CompiledQuery => new Compiler(ctx).compile(node)\n\n/**\n * Turn a user value into an ILIKE argument: SQL wildcards (`%`, `_`, `\\`) are\n * escaped to literals, then the user's `*`/`?` become `%`/`_`; a plain\n * substring value is wrapped in `%\u2026%`.\n */\nexport const likeArgument = (\n value: string,\n match: 'substring' | 'exact',\n): string => {\n const escaped = value.replace(/([\\\\%_])/g, '\\\\$1')\n if (/[*?]/.test(value)) {\n return escaped.replace(/\\*/g, '%').replace(/\\?/g, '_')\n }\n return match === 'substring' ? `%${escaped}%` : escaped\n}\n\n/** Closest field name within edit distance 3, for \"did you mean\u2026\" hints. */\nconst closestField = (\n input: string,\n candidates: readonly string[],\n): string | undefined => {\n const needle = input.toLowerCase()\n let best: string | undefined\n let bestDistance = Number.POSITIVE_INFINITY\n for (const candidate of candidates) {\n const distance = editDistance(needle, candidate.toLowerCase())\n if (distance < bestDistance) {\n bestDistance = distance\n best = candidate\n }\n }\n return bestDistance <= 3 ? best : undefined\n}\n\n/** Standard Levenshtein distance. */\nconst editDistance = (left: string, right: string): number => {\n const rows = left.length + 1\n const cols = right.length + 1\n const dist = Array.from({ length: rows }, () =>\n new Array<number>(cols).fill(0),\n )\n for (let row = 0; row < rows; row += 1) {\n dist[row][0] = row\n }\n for (let col = 0; col < cols; col += 1) {\n dist[0][col] = col\n }\n for (let row = 1; row < rows; row += 1) {\n for (let col = 1; col < cols; col += 1) {\n const cost = left[row - 1] === right[col - 1] ? 0 : 1\n dist[row][col] = Math.min(\n dist[row - 1][col] + 1,\n dist[row][col - 1] + 1,\n dist[row - 1][col - 1] + cost,\n )\n }\n }\n return dist[rows - 1][cols - 1]\n}\n"],
5
- "mappings": "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",
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 {\n LuceneQueryError,\n type QueryNode,\n type RangeNode,\n type SearchTermOperator,\n type TermNode,\n} from './ast.js'\n\n// ============================================================================\n// AST \u2192 parameterized SQL compiler.\n//\n// Entity-agnostic: the backend supplies a per-field {@link FieldBinding} map (the\n// SQL columns / computed resolvers stay backend-side), and this turns a parsed\n// query into a single parameterized SQL string for `qb.andWhere(sql, params)`.\n// Field names are whitelisted against the bindings; every value is a bound\n// parameter; wildcards are escaped \u2014 so a query can never inject SQL.\n// ============================================================================\n\n/** SQL binding for one searchable field (values live backend-side, not in the FE). */\nexport type FieldBinding =\n | {\n kind: 'string'\n /** SQL column expression, e.g. `c.name` or `planType.name`. */\n column: string\n /** Cast the column to text before matching (uuid columns). */\n cast?: boolean\n /** `substring` \u2192 ILIKE %v%; `exact` \u2192 case-insensitive equality. */\n match: 'substring' | 'exact'\n }\n | { kind: 'boolean'; column: string }\n /** Presence/absence of a nullable column (e.g. active-modification FK). */\n | { kind: 'nullable'; column: string }\n | { kind: 'date'; column: string }\n | {\n kind: 'computed'\n /** Column the resolved id set is matched against (e.g. `c.uuid`). */\n idColumn: string\n /** Resolve an equality value to matching ids (in-memory / config). */\n resolve: (value: string) => string[]\n }\n\nexport interface CompileContext {\n /** Field name \u2192 SQL binding. Keys are the whitelisted, canonical field names. */\n bindings: Record<string, FieldBinding>\n /** Fields a bare term ORs over (must be `string` bindings); always substring. */\n defaultFields: readonly string[]\n /** Unique-per-call-site parameter prefix (avoids clashing with other params). */\n paramPrefix: string\n}\n\nexport interface CompiledQuery {\n sql: string\n params: Record<string, unknown>\n}\n\nclass Compiler {\n private readonly params: Record<string, unknown> = {}\n private counter = 0\n /** Lowercased field name \u2192 { canonical, binding }, for case-insensitive lookup. */\n private readonly lookup: Map<\n string,\n { canonical: string; binding: FieldBinding }\n >\n\n constructor(private readonly ctx: CompileContext) {\n this.lookup = new Map(\n Object.entries(ctx.bindings).map(([field, binding]) => [\n field.toLowerCase(),\n { canonical: field, binding },\n ]),\n )\n }\n\n compile(node: QueryNode): CompiledQuery {\n return { sql: this.node(node), params: this.params }\n }\n\n private node(node: QueryNode): string {\n switch (node.kind) {\n case 'and':\n return `(${this.node(node.left)} AND ${this.node(node.right)})`\n case 'or':\n return `(${this.node(node.left)} OR ${this.node(node.right)})`\n case 'not':\n return `(NOT ${this.node(node.child)})`\n case 'term':\n return this.term(node)\n case 'range':\n return this.range(node)\n }\n }\n\n private term(node: TermNode): string {\n if (node.field === undefined) {\n return this.bareTerm(node.value)\n }\n const { canonical, binding } = this.resolveField(node.field)\n switch (binding.kind) {\n case 'string':\n this.requireMatchOperator(canonical, node.operator)\n return this.stringMatch(binding, node.value)\n case 'boolean':\n this.requireMatchOperator(canonical, node.operator)\n return `${binding.column} = ${this.bind(this.parseBoolean(canonical, node.value))}`\n case 'nullable':\n this.requireMatchOperator(canonical, node.operator)\n return this.parseBoolean(canonical, node.value)\n ? `${binding.column} IS NOT NULL`\n : `${binding.column} IS NULL`\n case 'computed':\n this.requireMatchOperator(canonical, node.operator)\n return this.computedMatch(binding, node.value)\n case 'date':\n return this.dateTerm(binding, canonical, node.operator, node.value)\n }\n }\n\n private range(node: RangeNode): string {\n const { canonical, binding } = this.resolveField(node.field)\n if (binding.kind !== 'date') {\n throw new LuceneQueryError(\n `Field \"${canonical}\" does not support ranges.`,\n 'bad-operator',\n )\n }\n const lowerOp = node.lowerInclusive ? '>=' : '>'\n const upperOp = node.upperInclusive ? '<=' : '<'\n const lower = this.bind(this.parseDate(canonical, node.lower))\n const upper = this.bind(this.parseDate(canonical, node.upper))\n return `(${binding.column} ${lowerOp} ${lower} AND ${binding.column} ${upperOp} ${upper})`\n }\n\n // --- field kinds ----------------------------------------------------------\n\n private bareTerm(value: string): string {\n const clauses = this.ctx.defaultFields.map((field) => {\n const entry = this.lookup.get(field.toLowerCase())\n if (!entry || entry.binding.kind !== 'string') {\n // A server-side registry/binding bug, not a bad query \u2014 throw a plain\n // Error so the routers surface it as a 5xx, never a 400.\n throw new Error(\n `Search misconfigured: default field \"${field}\" must be a string binding.`,\n )\n }\n const { column, cast } = entry.binding\n const target = cast ? `CAST(${column} AS TEXT)` : column\n return `${target} ILIKE ${this.bind(likeArgument(value, 'substring'))}`\n })\n return clauses.length === 1 ? clauses[0] : `(${clauses.join(' OR ')})`\n }\n\n private stringMatch(\n binding: Extract<FieldBinding, { kind: 'string' }>,\n value: string,\n ): string {\n const target = binding.cast\n ? `CAST(${binding.column} AS TEXT)`\n : binding.column\n return `${target} ILIKE ${this.bind(likeArgument(value, binding.match))}`\n }\n\n private computedMatch(\n binding: Extract<FieldBinding, { kind: 'computed' }>,\n value: string,\n ): string {\n const ids = binding.resolve(value)\n if (ids.length === 0) {\n // No entity matches this value \u2014 a guaranteed-false predicate (a\n // surrounding NOT correctly flips it to all-rows).\n return '1 = 0'\n }\n // One parameter, not one for each id. `status:healthy` resolves to the\n // whole healthy fleet, thus the set follows the size of the fleet.\n return idSetPredicate(binding.idColumn, this.bindName(joinIdSet(ids)))\n }\n\n private dateTerm(\n binding: Extract<FieldBinding, { kind: 'date' }>,\n canonical: string,\n operator: SearchTermOperator,\n value: string,\n ): string {\n if (operator === ':') {\n // Equality on a date means \"that calendar day\" (UTC): [day, nextDay).\n const start = this.parseDate(canonical, value)\n const startDay = new Date(\n Date.UTC(\n start.getUTCFullYear(),\n start.getUTCMonth(),\n start.getUTCDate(),\n ),\n )\n const nextDay = new Date(startDay.getTime() + 24 * 60 * 60 * 1000)\n return `(${binding.column} >= ${this.bind(startDay.toISOString())} AND ${binding.column} < ${this.bind(nextDay.toISOString())})`\n }\n const bound = this.parseDate(canonical, value).toISOString()\n return `${binding.column} ${operator} ${this.bind(bound)}`\n }\n\n // --- validation helpers ---------------------------------------------------\n\n private resolveField(field: string): {\n canonical: string\n binding: FieldBinding\n } {\n const entry = this.lookup.get(field.toLowerCase())\n if (!entry) {\n const suggestion = closestField(\n field,\n [...this.lookup.values()].map((value) => value.canonical),\n )\n throw new LuceneQueryError(\n `Unknown field \"${field}\".${suggestion ? ` Did you mean \"${suggestion}\"?` : ''}`,\n 'unknown-field',\n suggestion,\n )\n }\n return entry\n }\n\n private requireMatchOperator(\n field: string,\n operator: SearchTermOperator,\n ): void {\n if (operator !== ':') {\n throw new LuceneQueryError(\n `Field \"${field}\" supports only \"field:value\", not \"${operator}\".`,\n 'bad-operator',\n )\n }\n }\n\n private parseBoolean(field: string, value: string): boolean {\n const normalized = value.trim().toLowerCase()\n if (normalized === 'true') {\n return true\n }\n if (normalized === 'false') {\n return false\n }\n throw new LuceneQueryError(\n `Field \"${field}\" expects true or false, got \"${value}\".`,\n 'bad-value',\n )\n }\n\n private parseDate(field: string, value: string): Date {\n const parsed = new Date(value)\n if (Number.isNaN(parsed.getTime())) {\n throw new LuceneQueryError(\n `Field \"${field}\" expects a date (e.g. 2024-01-31), got \"${value}\".`,\n 'bad-value',\n )\n }\n return parsed\n }\n\n /** Register a value and give back its parameter name, with no marker. */\n private bindName(value: unknown): string {\n const name = `${this.ctx.paramPrefix}_${this.counter++}`\n this.params[name] = value\n return name\n }\n\n private bind(value: unknown): string {\n return `:${this.bindName(value)}`\n }\n}\n\n/** Compile a parsed query into a single parameterized SQL fragment. */\nexport const compileQuery = (\n node: QueryNode,\n ctx: CompileContext,\n): CompiledQuery => new Compiler(ctx).compile(node)\n\nconst ID_SET_SEPARATOR = ','\n\n/**\n * Match `column` against an id set that arrives as ONE parameter.\n *\n * `IN (:...ids)` expands to one bind parameter, and one literal in the\n * statement, for each id. A dimension that does not live in SQL resolves to an\n * id set, and such a set follows the size of the fleet: the prod cluster fleet\n * is more than 1000. Both the statement text and the parameter count would\n * grow with it, and Postgres would plan the statement again at every size.\n *\n * Postgres splits the string here, thus the statement text is constant.\n * `= ANY(...)` can still use an index on the column.\n */\nexport const idSetPredicate = (column: string, parameter: string): string =>\n `${column} = ANY(string_to_array(:${parameter}, '${ID_SET_SEPARATOR}'))`\n\n/**\n * The id set as one separated string, for {@link idSetPredicate}.\n *\n * The value is a bind parameter, thus it cannot change the statement. But an\n * id that holds the separator would become two ids, thus such an id is\n * dropped. The id columns are text columns, so this stays a guard and not an\n * assumption.\n *\n * An empty string gives an empty array in Postgres. Thus the match finds\n * nothing, which is correct for an empty set.\n */\nexport const joinIdSet = (ids: readonly string[]): string =>\n ids.filter((id) => !id.includes(ID_SET_SEPARATOR)).join(ID_SET_SEPARATOR)\n\n/**\n * Turn a user value into an ILIKE argument: SQL wildcards (`%`, `_`, `\\`) are\n * escaped to literals, then the user's `*`/`?` become `%`/`_`; a plain\n * substring value is wrapped in `%\u2026%`.\n */\nexport const likeArgument = (\n value: string,\n match: 'substring' | 'exact',\n): string => {\n const escaped = value.replace(/([\\\\%_])/g, '\\\\$1')\n if (/[*?]/.test(value)) {\n return escaped.replace(/\\*/g, '%').replace(/\\?/g, '_')\n }\n return match === 'substring' ? `%${escaped}%` : escaped\n}\n\n/** Closest field name within edit distance 3, for \"did you mean\u2026\" hints. */\nconst closestField = (\n input: string,\n candidates: readonly string[],\n): string | undefined => {\n const needle = input.toLowerCase()\n let best: string | undefined\n let bestDistance = Number.POSITIVE_INFINITY\n for (const candidate of candidates) {\n const distance = editDistance(needle, candidate.toLowerCase())\n if (distance < bestDistance) {\n bestDistance = distance\n best = candidate\n }\n }\n return bestDistance <= 3 ? best : undefined\n}\n\n/** Standard Levenshtein distance. */\nconst editDistance = (left: string, right: string): number => {\n const rows = left.length + 1\n const cols = right.length + 1\n const dist = Array.from({ length: rows }, () =>\n new Array<number>(cols).fill(0),\n )\n for (let row = 0; row < rows; row += 1) {\n dist[row][0] = row\n }\n for (let col = 0; col < cols; col += 1) {\n dist[0][col] = col\n }\n for (let row = 1; row < rows; row += 1) {\n for (let col = 1; col < cols; col += 1) {\n const cost = left[row - 1] === right[col - 1] ? 0 : 1\n dist[row][col] = Math.min(\n dist[row - 1][col] + 1,\n dist[row][col - 1] + 1,\n dist[row - 1][col - 1] + cost,\n )\n }\n }\n return dist[rows - 1][cols - 1]\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,6 +1,6 @@
1
1
  export { type AndNode, isLuceneQueryError, LuceneQueryError, type NotNode, type OrNode, type QueryNode, type RangeNode, type SearchTermOperator, type TermNode, } from './ast.js';
2
2
  export { CLUSTER_DEFAULT_SEARCH_FIELDS, CLUSTER_SEARCH_FIELDS, } from './cluster-search-fields.js';
3
- export { type CompileContext, type CompiledQuery, compileQuery, type FieldBinding, likeArgument, } from './compiler.js';
3
+ export { type CompileContext, type CompiledQuery, compileQuery, type FieldBinding, idSetPredicate, joinIdSet, likeArgument, } from './compiler.js';
4
4
  export { findSearchField, type SearchFieldCapability, type SearchFieldSpec, type SearchFieldType, } from './fields.js';
5
5
  export { ORG_DEFAULT_SEARCH_FIELDS, ORGANIZATION_SEARCH_FIELDS, } from './organization-search-fields.js';
6
6
  export { parseLuceneQuery } from './parser.js';
@@ -8,6 +8,8 @@ import {
8
8
  } from "./cluster-search-fields.js";
9
9
  import {
10
10
  compileQuery,
11
+ idSetPredicate,
12
+ joinIdSet,
11
13
  likeArgument
12
14
  } from "./compiler.js";
13
15
  import {
@@ -26,7 +28,9 @@ export {
26
28
  ORG_DEFAULT_SEARCH_FIELDS,
27
29
  compileQuery,
28
30
  findSearchField,
31
+ idSetPredicate,
29
32
  isLuceneQueryError,
33
+ joinIdSet,
30
34
  likeArgument,
31
35
  parseLuceneQuery
32
36
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/search/index.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\nexport {\n type AndNode,\n isLuceneQueryError,\n LuceneQueryError,\n type NotNode,\n type OrNode,\n type QueryNode,\n type RangeNode,\n type SearchTermOperator,\n type TermNode,\n} from './ast.js'\nexport {\n CLUSTER_DEFAULT_SEARCH_FIELDS,\n CLUSTER_SEARCH_FIELDS,\n} from './cluster-search-fields.js'\nexport {\n type CompileContext,\n type CompiledQuery,\n compileQuery,\n type FieldBinding,\n likeArgument,\n} from './compiler.js'\nexport {\n findSearchField,\n type SearchFieldCapability,\n type SearchFieldSpec,\n type SearchFieldType,\n} from './fields.js'\nexport {\n ORG_DEFAULT_SEARCH_FIELDS,\n ORGANIZATION_SEARCH_FIELDS,\n} from './organization-search-fields.js'\nexport { parseLuceneQuery } from './parser.js'\n"],
5
- "mappings": "AAMA;AAAA,EAEE;AAAA,EACA;AAAA,OAOK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP;AAAA,EAGE;AAAA,EAEA;AAAA,OACK;AACP;AAAA,EACE;AAAA,OAIK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP,SAAS,wBAAwB;",
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\nexport {\n type AndNode,\n isLuceneQueryError,\n LuceneQueryError,\n type NotNode,\n type OrNode,\n type QueryNode,\n type RangeNode,\n type SearchTermOperator,\n type TermNode,\n} from './ast.js'\nexport {\n CLUSTER_DEFAULT_SEARCH_FIELDS,\n CLUSTER_SEARCH_FIELDS,\n} from './cluster-search-fields.js'\nexport {\n type CompileContext,\n type CompiledQuery,\n compileQuery,\n type FieldBinding,\n idSetPredicate,\n joinIdSet,\n likeArgument,\n} from './compiler.js'\nexport {\n findSearchField,\n type SearchFieldCapability,\n type SearchFieldSpec,\n type SearchFieldType,\n} from './fields.js'\nexport {\n ORG_DEFAULT_SEARCH_FIELDS,\n ORGANIZATION_SEARCH_FIELDS,\n} from './organization-search-fields.js'\nexport { parseLuceneQuery } from './parser.js'\n"],
5
+ "mappings": "AAMA;AAAA,EAEE;AAAA,EACA;AAAA,OAOK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP;AAAA,EAGE;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,OAIK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP,SAAS,wBAAwB;",
6
6
  "names": []
7
7
  }
@@ -38,8 +38,36 @@ export interface ClusterBulkOperationGenerationUpdateParameter {
38
38
  * the 8h sleep cron then suspends the cluster again. Second, a cluster that
39
39
  * already has the target generation gets a forced spec write instead of a
40
40
  * skip.
41
+ *
42
+ * Needs the permission `canUpgradeGenerationYolo`, on the creation of the
43
+ * operation and on each acknowledgement and the execution.
41
44
  */
42
45
  yoloAllClusters?: boolean;
46
+ /**
47
+ * Retries a refused generation write with the
48
+ * `cloud.camunda.io/force-generation-update` annotation of the operator.
49
+ *
50
+ * The admission webhook refuses a new generation while the cluster did not
51
+ * finish the previous generation update. The annotation waives that one
52
+ * check. Console sends the plain write first, thus only a cluster that the
53
+ * webhook refuses gets the bypass, and the result of the operation names
54
+ * the clusters that needed it.
55
+ *
56
+ * The flag also writes the spec of a cluster that the cluster table calls
57
+ * done already. The CR can hold a different generation from the table,
58
+ * because
59
+ * an earlier write failed, and the webhook reads the CR. Without the flag
60
+ * such a cluster is left out, and no operation can move it.
61
+ *
62
+ * Thus the flag changes two things: what console does when the operator
63
+ * refuses a write, and whether a cluster that the cluster table calls done
64
+ * is left out. `yoloAllClusters` also keeps such a cluster in, but only
65
+ * this flag can get its write past the operator.
66
+ *
67
+ * Needs the permission `canUpgradeGenerationYolo`, on the creation of the
68
+ * operation and on each acknowledgement and the execution.
69
+ */
70
+ yoloForceUpdate?: boolean;
43
71
  }
44
72
  export interface ClusterBulkOperationPlanTypeUpdateParameter {
45
73
  toPlanTypeUuid: string;
@@ -4,4 +4,15 @@ export declare enum ClusterPlanTypeAvailabilityClass {
4
4
  STANDARD = "Standard",
5
5
  ADVANCED = "Advanced"
6
6
  }
7
+ /**
8
+ * True while the plan type sets no availability class, thus the per-cluster
9
+ * non-spot override decides where the cluster runs.
10
+ *
11
+ * `undefined` and `UNSET` are the same answer. The column of the plan type is
12
+ * `NOT NULL DEFAULT 'unset'`, so the entity gives `UNSET`, but
13
+ * `ClusterPlanTypeDto` types the field optional and a reader of the DTO can
14
+ * get `undefined`. One predicate keeps the spec and the Control gate in step:
15
+ * two predicates let Control offer a switch that the spec then ignores.
16
+ */
17
+ export declare function hasNoAvailabilityClass(availabilityClass: ClusterPlanTypeAvailabilityClass | string | undefined): boolean;
7
18
  export declare function sortByAvailabilityClasses(a: ClusterPlanTypeAvailabilityClass, b: ClusterPlanTypeAvailabilityClass): number;
@@ -5,6 +5,9 @@ var ClusterPlanTypeAvailabilityClass = /* @__PURE__ */ ((ClusterPlanTypeAvailabi
5
5
  ClusterPlanTypeAvailabilityClass2["ADVANCED"] = "Advanced";
6
6
  return ClusterPlanTypeAvailabilityClass2;
7
7
  })(ClusterPlanTypeAvailabilityClass || {});
8
+ function hasNoAvailabilityClass(availabilityClass) {
9
+ return availabilityClass === void 0 || availabilityClass === "unset" /* UNSET */;
10
+ }
8
11
  function sortByAvailabilityClasses(a, b) {
9
12
  const availabilityClasses = [
10
13
  "Basic" /* BASIC */,
@@ -16,6 +19,7 @@ function sortByAvailabilityClasses(a, b) {
16
19
  }
17
20
  export {
18
21
  ClusterPlanTypeAvailabilityClass,
22
+ hasNoAvailabilityClass,
19
23
  sortByAvailabilityClasses
20
24
  };
21
25
  //# sourceMappingURL=ClusterPlanTypeAvailabilityClass.type.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/types/ClusterPlanTypeAvailabilityClass.type.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\n// eslint-disable-next-line no-shadow\nexport enum ClusterPlanTypeAvailabilityClass {\n UNSET = 'unset', // used for old plans that don't have an availability class\n BASIC = 'Basic',\n STANDARD = 'Standard',\n ADVANCED = 'Advanced',\n}\n\nexport function sortByAvailabilityClasses(\n a: ClusterPlanTypeAvailabilityClass,\n b: ClusterPlanTypeAvailabilityClass,\n): number {\n const availabilityClasses = [\n ClusterPlanTypeAvailabilityClass.BASIC,\n ClusterPlanTypeAvailabilityClass.STANDARD,\n ClusterPlanTypeAvailabilityClass.ADVANCED,\n ClusterPlanTypeAvailabilityClass.UNSET,\n ]\n\n return availabilityClasses.indexOf(a) - availabilityClasses.indexOf(b)\n}\n"],
5
- "mappings": "AAOO,IAAK,mCAAL,kBAAKA,sCAAL;AACL,EAAAA,kCAAA,WAAQ;AACR,EAAAA,kCAAA,WAAQ;AACR,EAAAA,kCAAA,cAAW;AACX,EAAAA,kCAAA,cAAW;AAJD,SAAAA;AAAA,GAAA;AAOL,SAAS,0BACd,GACA,GACQ;AACR,QAAM,sBAAsB;AAAA,IAC1B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,SAAO,oBAAoB,QAAQ,CAAC,IAAI,oBAAoB,QAAQ,CAAC;AACvE;",
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\n// eslint-disable-next-line no-shadow\nexport enum ClusterPlanTypeAvailabilityClass {\n UNSET = 'unset', // used for old plans that don't have an availability class\n BASIC = 'Basic',\n STANDARD = 'Standard',\n ADVANCED = 'Advanced',\n}\n\n/**\n * True while the plan type sets no availability class, thus the per-cluster\n * non-spot override decides where the cluster runs.\n *\n * `undefined` and `UNSET` are the same answer. The column of the plan type is\n * `NOT NULL DEFAULT 'unset'`, so the entity gives `UNSET`, but\n * `ClusterPlanTypeDto` types the field optional and a reader of the DTO can\n * get `undefined`. One predicate keeps the spec and the Control gate in step:\n * two predicates let Control offer a switch that the spec then ignores.\n */\nexport function hasNoAvailabilityClass(\n availabilityClass: ClusterPlanTypeAvailabilityClass | string | undefined,\n): boolean {\n return (\n availabilityClass === undefined ||\n availabilityClass === ClusterPlanTypeAvailabilityClass.UNSET\n )\n}\n\nexport function sortByAvailabilityClasses(\n a: ClusterPlanTypeAvailabilityClass,\n b: ClusterPlanTypeAvailabilityClass,\n): number {\n const availabilityClasses = [\n ClusterPlanTypeAvailabilityClass.BASIC,\n ClusterPlanTypeAvailabilityClass.STANDARD,\n ClusterPlanTypeAvailabilityClass.ADVANCED,\n ClusterPlanTypeAvailabilityClass.UNSET,\n ]\n\n return availabilityClasses.indexOf(a) - availabilityClasses.indexOf(b)\n}\n"],
5
+ "mappings": "AAOO,IAAK,mCAAL,kBAAKA,sCAAL;AACL,EAAAA,kCAAA,WAAQ;AACR,EAAAA,kCAAA,WAAQ;AACR,EAAAA,kCAAA,cAAW;AACX,EAAAA,kCAAA,cAAW;AAJD,SAAAA;AAAA,GAAA;AAiBL,SAAS,uBACd,mBACS;AACT,SACE,sBAAsB,UACtB,sBAAsB;AAE1B;AAEO,SAAS,0BACd,GACA,GACQ;AACR,QAAM,sBAAsB;AAAA,IAC1B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,SAAO,oBAAoB,QAAQ,CAAC,IAAI,oBAAoB,QAAQ,CAAC;AACvE;",
6
6
  "names": ["ClusterPlanTypeAvailabilityClass"]
7
7
  }
@@ -1,5 +1,5 @@
1
1
  export type AccountRoles = 'accounts:read' | 'accounts:onboard' | 'accounts:orgCreator' | 'accounts:enterpriseAdmin' | 'accounts:enterpriseOffboarding' | 'accounts:admin' | 'accounts:god' | 'accounts:editSalesPlans' | 'support:agent' | 'supersupport:agent' | 'accounts:trialExtender' | 'accounts:limitExtender' | 'accounts:connections:create' | 'accounts:connections:update' | 'accounts:connections:delete' | 'accounts:clusterUpdates' | 'accounts:notifications:global' | 'accounts:addSafeRoles' | 'accounts:consultingManager' | 'accounts:earlyAccessEditor' | 'accounts:pdfWatermarkReader' | 'accounts:pdfWatermarkWriter';
2
- export type ConsoleRoles = 'console:admin' | 'betatester:true' | 'console:admin:readonly' | 'console:god' | 'consoleTeam' | 'console:operationsEngineer' | 'console:C8ReleaseManager' | 'console:C8UpdateEnforcer' | 'console:clusterPlanManager';
2
+ export type ConsoleRoles = 'console:admin' | 'betatester:true' | 'console:admin:readonly' | 'console:god' | 'consoleTeam' | 'console:operationsEngineer' | 'console:C8ReleaseManager' | 'console:C8UpdateEnforcer' | 'console:clusterPlanManager' | 'console:optionalTelemetryManager';
3
3
  export type ModelerRoles = 'modeler:admin';
4
4
  export type Roles = AccountRoles | ConsoleRoles | ModelerRoles;
5
5
  export declare const SAFE_ROLES: Roles[];
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/types/Roles.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\nexport type AccountRoles =\n | 'accounts:read'\n | 'accounts:onboard'\n | 'accounts:orgCreator'\n | 'accounts:enterpriseAdmin'\n | 'accounts:enterpriseOffboarding'\n | 'accounts:admin'\n | 'accounts:god'\n | 'accounts:editSalesPlans'\n | 'support:agent'\n | 'supersupport:agent'\n | 'accounts:trialExtender'\n | 'accounts:limitExtender'\n | 'accounts:connections:create'\n | 'accounts:connections:update'\n | 'accounts:connections:delete'\n | 'accounts:clusterUpdates'\n | 'accounts:notifications:global'\n | 'accounts:addSafeRoles'\n | 'accounts:consultingManager'\n | 'accounts:earlyAccessEditor'\n | 'accounts:pdfWatermarkReader'\n | 'accounts:pdfWatermarkWriter'\nexport type ConsoleRoles =\n | 'console:admin'\n | 'betatester:true'\n | 'console:admin:readonly'\n | 'console:god'\n | 'consoleTeam'\n | 'console:operationsEngineer'\n | 'console:C8ReleaseManager'\n | 'console:C8UpdateEnforcer'\n | 'console:clusterPlanManager'\nexport type ModelerRoles = 'modeler:admin'\nexport type Roles = AccountRoles | ConsoleRoles | ModelerRoles\nexport const SAFE_ROLES: Roles[] = [\n 'accounts:read',\n 'console:admin:readonly',\n 'accounts:trialExtender',\n]\n"],
5
- "mappings": "AAyCO,MAAM,aAAsB;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AACF;",
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\nexport type AccountRoles =\n | 'accounts:read'\n | 'accounts:onboard'\n | 'accounts:orgCreator'\n | 'accounts:enterpriseAdmin'\n | 'accounts:enterpriseOffboarding'\n | 'accounts:admin'\n | 'accounts:god'\n | 'accounts:editSalesPlans'\n | 'support:agent'\n | 'supersupport:agent'\n | 'accounts:trialExtender'\n | 'accounts:limitExtender'\n | 'accounts:connections:create'\n | 'accounts:connections:update'\n | 'accounts:connections:delete'\n | 'accounts:clusterUpdates'\n | 'accounts:notifications:global'\n | 'accounts:addSafeRoles'\n | 'accounts:consultingManager'\n | 'accounts:earlyAccessEditor'\n | 'accounts:pdfWatermarkReader'\n | 'accounts:pdfWatermarkWriter'\nexport type ConsoleRoles =\n | 'console:admin'\n | 'betatester:true'\n | 'console:admin:readonly'\n | 'console:god'\n | 'consoleTeam'\n | 'console:operationsEngineer'\n | 'console:C8ReleaseManager'\n | 'console:C8UpdateEnforcer'\n | 'console:clusterPlanManager'\n | 'console:optionalTelemetryManager'\nexport type ModelerRoles = 'modeler:admin'\nexport type Roles = AccountRoles | ConsoleRoles | ModelerRoles\nexport const SAFE_ROLES: Roles[] = [\n 'accounts:read',\n 'console:admin:readonly',\n 'accounts:trialExtender',\n]\n"],
5
+ "mappings": "AA0CO,MAAM,aAAsB;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AACF;",
6
6
  "names": []
7
7
  }
@@ -1,5 +1,19 @@
1
1
  import { type CamundiPermissionRules, type HibobEmployee } from '../config/camundi-permission-rules.types.js';
2
2
  import type { Roles } from '../types/Roles.js';
3
+ /**
4
+ * Where the HiBob employee list is cached, in the Redis of the fleet.
5
+ *
6
+ * accounts-backend writes the entry. Every other service only reads it, and
7
+ * each one must address it with these two names: a service that reads another
8
+ * key finds nothing, adds no permission of a role, and says nothing about it.
9
+ *
10
+ * They live here, and not in a server package, because both server layers read
11
+ * them. `shared-backend-server` serves the Express services and
12
+ * `shared-backend-fastify` serves the Fastify services, and two copies of one
13
+ * string is how the two engines come apart.
14
+ */
15
+ export declare const HIBOB_CACHE_NAMESPACE = "hibobUsersCache";
16
+ export declare const HIBOB_CACHE_KEY = "allUsers";
3
17
  /**
4
18
  * Determines which permission rules apply to a given employee based on their
5
19
  * department, division, and subdivision.
@@ -5,6 +5,8 @@ import {
5
5
  SUB_DIVISION
6
6
  } from "../config/camundi-permission-rules.types.js";
7
7
  import { expandRolesToPermissions } from "../permissions/roleExpansion.utils.js";
8
+ const HIBOB_CACHE_NAMESPACE = "hibobUsersCache";
9
+ const HIBOB_CACHE_KEY = "allUsers";
8
10
  function getApplicableRolesForEmployee(employee, rules = CAMUNDI_PERMISSION_RULES) {
9
11
  const applicableRoles = /* @__PURE__ */ new Set();
10
12
  const department = employee[DEPARTMENT]?.value || "";
@@ -63,6 +65,8 @@ function isManager(userEmail, employees) {
63
65
  );
64
66
  }
65
67
  export {
68
+ HIBOB_CACHE_KEY,
69
+ HIBOB_CACHE_NAMESPACE,
66
70
  augmentCamundiPermissions,
67
71
  getApplicableRolesForEmployee,
68
72
  isManager
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/utils/camundiPermissionAugmenter.utils.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 { default as CAMUNDI_PERMISSION_RULES } from '../config/camundi-permission-rules.js'\nimport {\n type CamundiPermissionRules,\n DEPARTMENT,\n DIVISION,\n type HibobEmployee,\n SUB_DIVISION,\n} from '../config/camundi-permission-rules.types.js'\nimport { expandRolesToPermissions } from '../permissions/roleExpansion.utils.js'\nimport type { Roles } from '../types/Roles.js'\n\n/**\n * Determines which permission rules apply to a given employee based on their\n * department, division, and subdivision.\n *\n * @param employee - HiBob employee data\n * @param rules - Permission rules configuration\n * @returns Array of roles that should be granted to the employee\n */\nexport function getApplicableRolesForEmployee(\n employee: HibobEmployee,\n rules: CamundiPermissionRules = CAMUNDI_PERMISSION_RULES,\n): Roles[] {\n const applicableRoles = new Set<Roles>()\n\n // Extract employee organizational data - use only direct field paths\n const department = employee[DEPARTMENT]?.value || ''\n const division = employee[DIVISION]?.value || ''\n const subdivision = employee[SUB_DIVISION]?.value || ''\n\n // Check department rules\n if (department && rules.departmentRules[department]) {\n for (const role of rules.departmentRules[department]) {\n applicableRoles.add(role)\n }\n }\n\n // Check division rules\n if (division && rules.divisionRules[division]) {\n for (const role of rules.divisionRules[division]) {\n applicableRoles.add(role)\n }\n }\n\n // Check subdivision rules\n if (subdivision && rules.subdivisionRules[subdivision]) {\n for (const role of rules.subdivisionRules[subdivision]) {\n applicableRoles.add(role)\n }\n }\n\n return Array.from(applicableRoles)\n}\n\n/**\n * Augments user permissions based on their Camunda employee status and organizational position.\n *\n * @param userEmail - Email of the user\n * @param currentPermissions - Current permissions from JWT\n * @param employees - List of all HiBob employees\n * @returns Augmented permissions array (original + new permissions from rules)\n */\nexport function augmentCamundiPermissions(\n userEmail: string,\n currentPermissions: string[],\n employees: HibobEmployee[],\n): {\n augmentedPermissions: string[]\n hibobEmployee?: HibobEmployee\n applicableRoles?: Roles[]\n} {\n // Early return if not a Camundi email\n if (!userEmail.toLowerCase().endsWith('@camunda.com')) {\n return { augmentedPermissions: currentPermissions }\n }\n\n // Find the employee in HiBob data\n const employee = employees.find((emp) => {\n const empEmail = emp.email || emp['/root/email']?.value\n return empEmail?.toLowerCase() === userEmail.toLowerCase()\n })\n\n if (!employee) {\n // Employee not found in HiBob - return original permissions\n return { augmentedPermissions: currentPermissions }\n }\n\n // Get applicable roles based on organizational structure\n const applicableRoles = getApplicableRolesForEmployee(employee)\n\n if (applicableRoles.length === 0) {\n // No rules apply to this employee\n return {\n augmentedPermissions: currentPermissions,\n hibobEmployee: employee,\n applicableRoles,\n }\n }\n\n // Expand roles to permissions\n const newPermissions = expandRolesToPermissions(applicableRoles)\n\n // Merge with existing permissions (deduplication via Set)\n const mergedPermissions = new Set([...currentPermissions, ...newPermissions])\n\n return {\n augmentedPermissions: Array.from(mergedPermissions),\n hibobEmployee: employee,\n applicableRoles,\n }\n}\n\nexport function isManager(\n userEmail: string,\n employees: HibobEmployee[],\n): boolean {\n // Early return if not a Camundi email\n if (!userEmail.toLowerCase().endsWith('@camunda.com')) {\n return false\n }\n return employees.some(\n (emp) =>\n emp['/work/reportsTo']?.value?.email?.toLowerCase() ===\n userEmail.toLowerCase(),\n )\n}\n"],
5
- "mappings": "AAMA,SAAS,WAAW,gCAAgC;AACpD;AAAA,EAEE;AAAA,EACA;AAAA,EAEA;AAAA,OACK;AACP,SAAS,gCAAgC;AAWlC,SAAS,8BACd,UACA,QAAgC,0BACvB;AACT,QAAM,kBAAkB,oBAAI,IAAW;AAGvC,QAAM,aAAa,SAAS,UAAU,GAAG,SAAS;AAClD,QAAM,WAAW,SAAS,QAAQ,GAAG,SAAS;AAC9C,QAAM,cAAc,SAAS,YAAY,GAAG,SAAS;AAGrD,MAAI,cAAc,MAAM,gBAAgB,UAAU,GAAG;AACnD,eAAW,QAAQ,MAAM,gBAAgB,UAAU,GAAG;AACpD,sBAAgB,IAAI,IAAI;AAAA,IAC1B;AAAA,EACF;AAGA,MAAI,YAAY,MAAM,cAAc,QAAQ,GAAG;AAC7C,eAAW,QAAQ,MAAM,cAAc,QAAQ,GAAG;AAChD,sBAAgB,IAAI,IAAI;AAAA,IAC1B;AAAA,EACF;AAGA,MAAI,eAAe,MAAM,iBAAiB,WAAW,GAAG;AACtD,eAAW,QAAQ,MAAM,iBAAiB,WAAW,GAAG;AACtD,sBAAgB,IAAI,IAAI;AAAA,IAC1B;AAAA,EACF;AAEA,SAAO,MAAM,KAAK,eAAe;AACnC;AAUO,SAAS,0BACd,WACA,oBACA,WAKA;AAEA,MAAI,CAAC,UAAU,YAAY,EAAE,SAAS,cAAc,GAAG;AACrD,WAAO,EAAE,sBAAsB,mBAAmB;AAAA,EACpD;AAGA,QAAM,WAAW,UAAU,KAAK,CAAC,QAAQ;AACvC,UAAM,WAAW,IAAI,SAAS,IAAI,aAAa,GAAG;AAClD,WAAO,UAAU,YAAY,MAAM,UAAU,YAAY;AAAA,EAC3D,CAAC;AAED,MAAI,CAAC,UAAU;AAEb,WAAO,EAAE,sBAAsB,mBAAmB;AAAA,EACpD;AAGA,QAAM,kBAAkB,8BAA8B,QAAQ;AAE9D,MAAI,gBAAgB,WAAW,GAAG;AAEhC,WAAO;AAAA,MACL,sBAAsB;AAAA,MACtB,eAAe;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAGA,QAAM,iBAAiB,yBAAyB,eAAe;AAG/D,QAAM,oBAAoB,oBAAI,IAAI,CAAC,GAAG,oBAAoB,GAAG,cAAc,CAAC;AAE5E,SAAO;AAAA,IACL,sBAAsB,MAAM,KAAK,iBAAiB;AAAA,IAClD,eAAe;AAAA,IACf;AAAA,EACF;AACF;AAEO,SAAS,UACd,WACA,WACS;AAET,MAAI,CAAC,UAAU,YAAY,EAAE,SAAS,cAAc,GAAG;AACrD,WAAO;AAAA,EACT;AACA,SAAO,UAAU;AAAA,IACf,CAAC,QACC,IAAI,iBAAiB,GAAG,OAAO,OAAO,YAAY,MAClD,UAAU,YAAY;AAAA,EAC1B;AACF;",
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 { default as CAMUNDI_PERMISSION_RULES } from '../config/camundi-permission-rules.js'\nimport {\n type CamundiPermissionRules,\n DEPARTMENT,\n DIVISION,\n type HibobEmployee,\n SUB_DIVISION,\n} from '../config/camundi-permission-rules.types.js'\nimport { expandRolesToPermissions } from '../permissions/roleExpansion.utils.js'\nimport type { Roles } from '../types/Roles.js'\n\n/**\n * Where the HiBob employee list is cached, in the Redis of the fleet.\n *\n * accounts-backend writes the entry. Every other service only reads it, and\n * each one must address it with these two names: a service that reads another\n * key finds nothing, adds no permission of a role, and says nothing about it.\n *\n * They live here, and not in a server package, because both server layers read\n * them. `shared-backend-server` serves the Express services and\n * `shared-backend-fastify` serves the Fastify services, and two copies of one\n * string is how the two engines come apart.\n */\nexport const HIBOB_CACHE_NAMESPACE = 'hibobUsersCache'\nexport const HIBOB_CACHE_KEY = 'allUsers'\n\n/**\n * Determines which permission rules apply to a given employee based on their\n * department, division, and subdivision.\n *\n * @param employee - HiBob employee data\n * @param rules - Permission rules configuration\n * @returns Array of roles that should be granted to the employee\n */\nexport function getApplicableRolesForEmployee(\n employee: HibobEmployee,\n rules: CamundiPermissionRules = CAMUNDI_PERMISSION_RULES,\n): Roles[] {\n const applicableRoles = new Set<Roles>()\n\n // Extract employee organizational data - use only direct field paths\n const department = employee[DEPARTMENT]?.value || ''\n const division = employee[DIVISION]?.value || ''\n const subdivision = employee[SUB_DIVISION]?.value || ''\n\n // Check department rules\n if (department && rules.departmentRules[department]) {\n for (const role of rules.departmentRules[department]) {\n applicableRoles.add(role)\n }\n }\n\n // Check division rules\n if (division && rules.divisionRules[division]) {\n for (const role of rules.divisionRules[division]) {\n applicableRoles.add(role)\n }\n }\n\n // Check subdivision rules\n if (subdivision && rules.subdivisionRules[subdivision]) {\n for (const role of rules.subdivisionRules[subdivision]) {\n applicableRoles.add(role)\n }\n }\n\n return Array.from(applicableRoles)\n}\n\n/**\n * Augments user permissions based on their Camunda employee status and organizational position.\n *\n * @param userEmail - Email of the user\n * @param currentPermissions - Current permissions from JWT\n * @param employees - List of all HiBob employees\n * @returns Augmented permissions array (original + new permissions from rules)\n */\nexport function augmentCamundiPermissions(\n userEmail: string,\n currentPermissions: string[],\n employees: HibobEmployee[],\n): {\n augmentedPermissions: string[]\n hibobEmployee?: HibobEmployee\n applicableRoles?: Roles[]\n} {\n // Early return if not a Camundi email\n if (!userEmail.toLowerCase().endsWith('@camunda.com')) {\n return { augmentedPermissions: currentPermissions }\n }\n\n // Find the employee in HiBob data\n const employee = employees.find((emp) => {\n const empEmail = emp.email || emp['/root/email']?.value\n return empEmail?.toLowerCase() === userEmail.toLowerCase()\n })\n\n if (!employee) {\n // Employee not found in HiBob - return original permissions\n return { augmentedPermissions: currentPermissions }\n }\n\n // Get applicable roles based on organizational structure\n const applicableRoles = getApplicableRolesForEmployee(employee)\n\n if (applicableRoles.length === 0) {\n // No rules apply to this employee\n return {\n augmentedPermissions: currentPermissions,\n hibobEmployee: employee,\n applicableRoles,\n }\n }\n\n // Expand roles to permissions\n const newPermissions = expandRolesToPermissions(applicableRoles)\n\n // Merge with existing permissions (deduplication via Set)\n const mergedPermissions = new Set([...currentPermissions, ...newPermissions])\n\n return {\n augmentedPermissions: Array.from(mergedPermissions),\n hibobEmployee: employee,\n applicableRoles,\n }\n}\n\nexport function isManager(\n userEmail: string,\n employees: HibobEmployee[],\n): boolean {\n // Early return if not a Camundi email\n if (!userEmail.toLowerCase().endsWith('@camunda.com')) {\n return false\n }\n return employees.some(\n (emp) =>\n emp['/work/reportsTo']?.value?.email?.toLowerCase() ===\n userEmail.toLowerCase(),\n )\n}\n"],
5
+ "mappings": "AAMA,SAAS,WAAW,gCAAgC;AACpD;AAAA,EAEE;AAAA,EACA;AAAA,EAEA;AAAA,OACK;AACP,SAAS,gCAAgC;AAelC,MAAM,wBAAwB;AAC9B,MAAM,kBAAkB;AAUxB,SAAS,8BACd,UACA,QAAgC,0BACvB;AACT,QAAM,kBAAkB,oBAAI,IAAW;AAGvC,QAAM,aAAa,SAAS,UAAU,GAAG,SAAS;AAClD,QAAM,WAAW,SAAS,QAAQ,GAAG,SAAS;AAC9C,QAAM,cAAc,SAAS,YAAY,GAAG,SAAS;AAGrD,MAAI,cAAc,MAAM,gBAAgB,UAAU,GAAG;AACnD,eAAW,QAAQ,MAAM,gBAAgB,UAAU,GAAG;AACpD,sBAAgB,IAAI,IAAI;AAAA,IAC1B;AAAA,EACF;AAGA,MAAI,YAAY,MAAM,cAAc,QAAQ,GAAG;AAC7C,eAAW,QAAQ,MAAM,cAAc,QAAQ,GAAG;AAChD,sBAAgB,IAAI,IAAI;AAAA,IAC1B;AAAA,EACF;AAGA,MAAI,eAAe,MAAM,iBAAiB,WAAW,GAAG;AACtD,eAAW,QAAQ,MAAM,iBAAiB,WAAW,GAAG;AACtD,sBAAgB,IAAI,IAAI;AAAA,IAC1B;AAAA,EACF;AAEA,SAAO,MAAM,KAAK,eAAe;AACnC;AAUO,SAAS,0BACd,WACA,oBACA,WAKA;AAEA,MAAI,CAAC,UAAU,YAAY,EAAE,SAAS,cAAc,GAAG;AACrD,WAAO,EAAE,sBAAsB,mBAAmB;AAAA,EACpD;AAGA,QAAM,WAAW,UAAU,KAAK,CAAC,QAAQ;AACvC,UAAM,WAAW,IAAI,SAAS,IAAI,aAAa,GAAG;AAClD,WAAO,UAAU,YAAY,MAAM,UAAU,YAAY;AAAA,EAC3D,CAAC;AAED,MAAI,CAAC,UAAU;AAEb,WAAO,EAAE,sBAAsB,mBAAmB;AAAA,EACpD;AAGA,QAAM,kBAAkB,8BAA8B,QAAQ;AAE9D,MAAI,gBAAgB,WAAW,GAAG;AAEhC,WAAO;AAAA,MACL,sBAAsB;AAAA,MACtB,eAAe;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAGA,QAAM,iBAAiB,yBAAyB,eAAe;AAG/D,QAAM,oBAAoB,oBAAI,IAAI,CAAC,GAAG,oBAAoB,GAAG,cAAc,CAAC;AAE5E,SAAO;AAAA,IACL,sBAAsB,MAAM,KAAK,iBAAiB;AAAA,IAClD,eAAe;AAAA,IACf;AAAA,EACF;AACF;AAEO,SAAS,UACd,WACA,WACS;AAET,MAAI,CAAC,UAAU,YAAY,EAAE,SAAS,cAAc,GAAG;AACrD,WAAO;AAAA,EACT;AACA,SAAO,UAAU;AAAA,IACf,CAAC,QACC,IAAI,iBAAiB,GAAG,OAAO,OAAO,YAAY,MAClD,UAAU,YAAY;AAAA,EAC1B;AACF;",
6
6
  "names": []
7
7
  }
@@ -16,6 +16,45 @@
16
16
  * the version a gate compares on the same rule.
17
17
  */
18
18
  export declare const stripSecfixPostfix: (version: string) => string;
19
+ /**
20
+ * Makes an image tag comparable with the rules of the operator. Two problems
21
+ * need this, and both cost a support ticket (INC-8048):
22
+ *
23
+ * 1. semver sorts a prerelease UNDER its release, thus `8.8.19-hotfix1` fails
24
+ * a `>= 8.8.19` gate. The operator reads that build as 8.8.19, because the
25
+ * build holds the content of 8.8.19 plus a hotfix. Thus every suffix that
26
+ * is not an alpha comes off.
27
+ * 2. semver compares an alpha identifier as text. `padAlphaIdentifier`
28
+ * corrects that.
29
+ *
30
+ * A `SNAPSHOT` tag comes back unchanged. `checkVersion` expands it, and only
31
+ * when the caller asks for it with `trueForSnapshot`.
32
+ *
33
+ * Use this function for a tag, not for a floor. A floor is a boundary that we
34
+ * write, thus it reads `padAlphaIdentifier` alone.
35
+ */
36
+ export declare const normalizeGenerationVersion: (version: string) => string;
37
+ /**
38
+ * Is this value an image that a generation can use? The value must have the
39
+ * form `repository:tag`, and the tag must obey the grammar of the operator
40
+ * (camunda/camunda-operator#6016).
41
+ *
42
+ * The tag is the text after the LAST colon, not the second colon-delimited
43
+ * segment. A registry host can carry a port
44
+ * (`registry.example.com:5000/zeebe:8.10.0`), and `secfixGenerationArtifacts.ts`
45
+ * already rewrites images of that shape.
46
+ *
47
+ * The grammar permits a suffix after the version, and this function does not
48
+ * limit the text of that suffix. Two reasons:
49
+ * - A security patch tags an alpha `8.10.0-alpha5-secfix`. Such images are in
50
+ * production today, and the retag job makes more of them.
51
+ * - The operator removes a suffix that it does not know, thus an unknown
52
+ * suffix is safe. `normalizeGenerationVersion` does the same.
53
+ *
54
+ * Use this function at creation only. Generations from before the grammar
55
+ * hold tags such as `3.9.0-preview-1`, and a read of those must still work.
56
+ */
57
+ export declare const isValidGenerationImage: (image: string | undefined) => boolean;
19
58
  export declare enum VersionCheckOperator {
20
59
  LessThan = 0,
21
60
  LessThanOrEqual = 1,
@@ -15,14 +15,52 @@ const stripSecfixPostfix = (version) => {
15
15
  const postfixStart = version.toLowerCase().indexOf("-secfix");
16
16
  return postfixStart === -1 ? version : version.slice(0, postfixStart);
17
17
  };
18
+ const ALPHA_PRERELEASE = /^alpha(\d+(?:\.\d+)*)(?=$|-)/i;
19
+ const padAlphaIdentifier = (version) => {
20
+ const parsed = semver.parse(version);
21
+ if (!parsed || parsed.prerelease.length === 0) {
22
+ return version;
23
+ }
24
+ const alpha = ALPHA_PRERELEASE.exec(parsed.prerelease.join("."));
25
+ if (!alpha) {
26
+ return version;
27
+ }
28
+ const release = `${parsed.major}.${parsed.minor}.${parsed.patch}`;
29
+ return `${release}-alpha.${alpha[1]}`;
30
+ };
31
+ const normalizeGenerationVersion = (version) => {
32
+ if (version.includes("SNAPSHOT")) {
33
+ return version;
34
+ }
35
+ const parsed = semver.parse(version);
36
+ if (!parsed || parsed.prerelease.length === 0) {
37
+ return version;
38
+ }
39
+ if (!ALPHA_PRERELEASE.test(parsed.prerelease.join("."))) {
40
+ return `${parsed.major}.${parsed.minor}.${parsed.patch}`;
41
+ }
42
+ return padAlphaIdentifier(version);
43
+ };
44
+ const SNAPSHOT_TAG = /^(?:\d+(?:\.\d+)?-)?SNAPSHOT$/;
45
+ const isValidGenerationImage = (image) => {
46
+ if (!image) {
47
+ return false;
48
+ }
49
+ const lastColon = image.lastIndexOf(":");
50
+ if (lastColon <= 0) {
51
+ return false;
52
+ }
53
+ const tag = image.slice(lastColon + 1);
54
+ return SNAPSHOT_TAG.test(tag) || semver.valid(tag) !== null;
55
+ };
18
56
  const extractVersion = (possiblyVersionOrDockerPath) => {
19
57
  const raw = possiblyVersionOrDockerPath ?? "";
20
58
  if (semver.valid(raw)) {
21
- return stripSecfixPostfix(raw);
59
+ return normalizeGenerationVersion(raw);
22
60
  }
23
- const versionSplit = raw.split(":");
24
- if (versionSplit.length > 1) {
25
- return stripSecfixPostfix(versionSplit[1]);
61
+ const lastColon = raw.lastIndexOf(":");
62
+ if (lastColon !== -1) {
63
+ return normalizeGenerationVersion(raw.slice(lastColon + 1));
26
64
  }
27
65
  return raw;
28
66
  };
@@ -51,6 +89,7 @@ const checkVersion = (params) => {
51
89
  versionToCompareTo = `${parts[0]}.${parts[1]}.${parts[2]}`;
52
90
  }
53
91
  }
92
+ versionToCompareTo = padAlphaIdentifier(versionToCompareTo);
54
93
  if (!semver.valid(versionToCompareTo)) {
55
94
  throw new Error("Invalid version to compare to");
56
95
  }
@@ -189,6 +228,8 @@ export {
189
228
  isAppIntegrationsVersionSupported,
190
229
  isGenerationResumable,
191
230
  isSecretsFilterModeConfigurable,
231
+ isValidGenerationImage,
232
+ normalizeGenerationVersion,
192
233
  stripSecfixPostfix
193
234
  };
194
235
  //# sourceMappingURL=versionCheck.utils.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/utils/versionCheck.utils.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 * as semver from 'semver'\nimport {\n APP_INTEGRATIONS_89_STREAM_CONNECTOR_BRIDGE_MIN_VERSION,\n APP_INTEGRATIONS_89_STREAM_MINOR,\n APP_INTEGRATIONS_89_STREAM_ZEEBE_MIN_VERSION,\n APP_INTEGRATIONS_MIN_VERSION,\n RESUME_ALPHA_MIN_VERSION,\n SECRETS_FILTER_MODE_8_6_MIN_VERSION,\n SECRETS_FILTER_MODE_8_7_MIN_VERSION,\n SECRETS_FILTER_MODE_8_8_MIN_VERSION,\n SECRETS_FILTER_MODE_8_9_MIN_VERSION,\n SECRETS_FILTER_MODE_8_10_MIN_VERSION,\n} from '../constants/version-gates.const.js'\n\n/**\n * stripSecfixPostfix removes the `-secfix` postfix of a version.\n *\n * A security patch tags the images of a generation with the postfix\n * (`8.8.19-secfix`). Semver reads the postfix as a prerelease, which sorts\n * under the release it patches. A `>= 8.8.19` gate thus refuses a patched\n * build of 8.8.19 itself. The postfix holds no version information, so it\n * comes off before every comparison.\n *\n * Only the postfix comes off, not the whole prerelease. A patched alpha\n * (`8.10.0-alpha5-secfix`) stays an alpha, which the 8.10 floors and\n * `isGenerationResumable` both depend on.\n *\n * A surface that shows a version reads this helper too, because the postfix is\n * an internal build detail. One helper keeps the version a customer sees and\n * the version a gate compares on the same rule.\n */\nexport const stripSecfixPostfix = (version: string): string => {\n // A search for the marker, and not a regular expression. `-secfix.*$` over\n // the input of an exported function is a polynomial backtracking pattern,\n // which code scanning rejects (CodeQL js/polynomial-redos).\n const postfixStart = version.toLowerCase().indexOf('-secfix')\n return postfixStart === -1 ? version : version.slice(0, postfixStart)\n}\n\n/**\n * Takes the version out of a generation version field. The field holds either a\n * bare version (`8.10.0-alpha4`) or a docker path\n * (`camunda/zeebe:8.10.0-alpha4`). A value that is neither comes back\n * unchanged, so the caller can still expand a `SNAPSHOT` tag.\n *\n * The postfix comes off after the tag, never before it. A repository path can\n * hold a `-` of its own, and a strip over the whole string would cut the path.\n */\nconst extractVersion = (possiblyVersionOrDockerPath?: string): string => {\n const raw = possiblyVersionOrDockerPath ?? ''\n if (semver.valid(raw)) {\n return stripSecfixPostfix(raw)\n }\n const versionSplit = raw.split(':')\n if (versionSplit.length > 1) {\n return stripSecfixPostfix(versionSplit[1])\n }\n // bare version string not valid semver (e.g. '8.10-SNAPSHOT') \u2014 use as-is so SNAPSHOT expansion can handle it\n return raw\n}\n\n// eslint-disable-next-line no-shadow\nexport enum VersionCheckOperator {\n LessThan,\n LessThanOrEqual,\n GreaterThan,\n GreaterThanOrEqual,\n SameMajor,\n SameMinor,\n}\n\nexport const checkVersion = (params: {\n possiblyVersionOrDockerPath?: string\n trueForSnapshot: boolean | 'compare'\n operator: VersionCheckOperator\n versionToCompareTo: string\n trueOnInvalidVersion?: boolean\n}) => {\n // quick exit: if the versionToCompareTo is\n // - `SNAPSHOT` there is not a lot we can compare here to, so we return false directly\n // - ends with `-SNAPSHOT` we ignore the `-SNAPSHOT` part for the comparison, guess a good matching semver compliant version and try to move on with the generated one in the code\n if (params.versionToCompareTo === 'SNAPSHOT') {\n return false\n }\n let versionToCompareTo = params.versionToCompareTo\n if (versionToCompareTo.endsWith('-SNAPSHOT')) {\n versionToCompareTo = versionToCompareTo.replace('-SNAPSHOT', '')\n const parts = versionToCompareTo.split('.')\n if (parts.length === 1) {\n versionToCompareTo = `${parts[0]}.0.0`\n } else if (parts.length === 2) {\n versionToCompareTo = `${parts[0]}.${parts[1]}.0`\n } else if (parts.length === 3) {\n versionToCompareTo = `${parts[0]}.${parts[1]}.${parts[2]}`\n }\n }\n if (!semver.valid(versionToCompareTo)) {\n throw new Error('Invalid version to compare to')\n }\n let version: string = extractVersion(params.possiblyVersionOrDockerPath)\n if (params.trueForSnapshot && version.includes('SNAPSHOT')) {\n if (version === 'SNAPSHOT') {\n // bare SNAPSHOT: `true` short-circuits here; `'compare'` falls through to invalid-version handling\n if (params.trueForSnapshot !== 'compare') {\n return true\n }\n } else {\n version = version.replace('-SNAPSHOT', '')\n if (version.split('.').length === 1) {\n version = `${version}.99.99`\n }\n if (version.split('.').length === 2) {\n version = `${version}.99`\n }\n if (version.split('.').length === 3) {\n version = `${version.split('.')[0]}.${version.split('.')[1]}.99`\n }\n }\n }\n\n let parsedVersionToCompareTo: string = ''\n if (semver.valid(versionToCompareTo ?? '')) {\n parsedVersionToCompareTo = versionToCompareTo ?? ''\n } else {\n const versionSplit = versionToCompareTo?.split(':') ?? []\n if (versionSplit.length > 1) {\n parsedVersionToCompareTo = versionSplit[1]\n }\n }\n if (params.trueForSnapshot && parsedVersionToCompareTo === 'SNAPSHOT') {\n return true\n }\n\n if (!semver.valid(version)) {\n return !!params.trueOnInvalidVersion\n }\n\n switch (params.operator) {\n case VersionCheckOperator.LessThan:\n return semver.lt(version, parsedVersionToCompareTo)\n case VersionCheckOperator.LessThanOrEqual:\n return semver.lte(version, parsedVersionToCompareTo)\n case VersionCheckOperator.GreaterThan:\n return semver.gt(version, parsedVersionToCompareTo)\n case VersionCheckOperator.GreaterThanOrEqual:\n return semver.gte(version, parsedVersionToCompareTo)\n case VersionCheckOperator.SameMajor:\n return semver.major(version) === semver.major(parsedVersionToCompareTo)\n case VersionCheckOperator.SameMinor:\n return (\n semver.major(version) === semver.major(parsedVersionToCompareTo) &&\n semver.minor(version) === semver.minor(parsedVersionToCompareTo)\n )\n default:\n return false\n }\n}\n\n/**\n * Can a suspended cluster on this generation resume? An alpha generation under\n * `RESUME_ALPHA_MIN_VERSION` answers false. Every other generation answers\n * true.\n *\n * The floor applies to alphas only, because they have no upgrade chain.\n * `RESUME_ALPHA_MIN_VERSION` gives the full reason. A release generation under\n * the floor, 8.9 for example, keeps its resume action.\n *\n * An alpha carries a prerelease tag that starts with `alpha`. The test reads\n * that tag, not the presence of a prerelease. A security patch tags a release\n * generation `8.9.0-secfix`, which semver also reads as a prerelease. That\n * generation is a release and keeps its upgrade chain, so it stays resumable.\n *\n * The c4 resume actions and the console-backend wake-up guards share this\n * function. The frontend keeps the action and disables it, the backend refuses\n * the request, and both must agree on the cohort. Two copies of one floor is\n * #9703.\n *\n * The answer is true for a version this function cannot read as an alpha:\n * - A `SNAPSHOT` tag is built from main, so it is never one of the old alphas.\n * - An empty or invalid version tells us nothing. A guess of false locks a\n * customer out of a cluster that is good, so the safe answer is true.\n */\nexport const isGenerationResumable = (zeebeVersion?: string): boolean => {\n const version = extractVersion(zeebeVersion)\n const isAlpha = (semver.prerelease(version) ?? []).some(\n (part) =>\n typeof part === 'string' && part.toLowerCase().startsWith('alpha'),\n )\n if (!semver.valid(version) || !isAlpha) {\n return true\n }\n return checkVersion({\n possiblyVersionOrDockerPath: zeebeVersion,\n trueForSnapshot: true,\n operator: VersionCheckOperator.GreaterThanOrEqual,\n versionToCompareTo: RESUME_ALPHA_MIN_VERSION,\n })\n}\n\n/**\n * Version gate for the App Integrations exporter toggle (#8536). Shared by the\n * c4 settings tile and the console-backend update guard so both stay in\n * lockstep \u2014 the fix landed as patches on the 8.9 stream (zeebe >=8.9.14 AND\n * connectorBridge >=8.9.7), everything from 8.10.0-alpha4 on already carries\n * both fixes. A plain zeebe >=8.9.14 check would wrongly match\n * 8.10.0-alpha1/2/3, which predate the fix.\n */\nexport const isAppIntegrationsVersionSupported = (versions: {\n zeebe?: string\n connectorBridge?: string\n}): boolean => {\n if (!versions.zeebe) {\n return false\n }\n const isIn89Stream = checkVersion({\n possiblyVersionOrDockerPath: versions.zeebe,\n trueForSnapshot: 'compare',\n operator: VersionCheckOperator.SameMinor,\n versionToCompareTo: APP_INTEGRATIONS_89_STREAM_MINOR,\n })\n if (!isIn89Stream) {\n return checkVersion({\n possiblyVersionOrDockerPath: versions.zeebe,\n trueForSnapshot: true,\n operator: VersionCheckOperator.GreaterThanOrEqual,\n versionToCompareTo: APP_INTEGRATIONS_MIN_VERSION,\n })\n }\n return (\n checkVersion({\n possiblyVersionOrDockerPath: versions.zeebe,\n trueForSnapshot: true,\n operator: VersionCheckOperator.GreaterThanOrEqual,\n versionToCompareTo: APP_INTEGRATIONS_89_STREAM_ZEEBE_MIN_VERSION,\n }) &&\n checkVersion({\n possiblyVersionOrDockerPath: versions.connectorBridge,\n trueForSnapshot: true,\n operator: VersionCheckOperator.GreaterThanOrEqual,\n versionToCompareTo:\n APP_INTEGRATIONS_89_STREAM_CONNECTOR_BRIDGE_MIN_VERSION,\n })\n )\n}\n\n/**\n * Version gate for the secrets filter mode setting on Connectors\n * (`CAMUNDA_CONNECTOR_SECRETRESOLVER_SECRETFILTER_MODE`). Each 8.x line got the\n * fix on a different patch, so a single floor across all lines is wrong: it\n * would open the setting on an early patch of a newer line, or close it on a\n * late patch of an older line. This picks the zeebe minor line first, then\n * applies that line's own floor.\n *\n * On the 8.6 to 8.9 lines, each floor is the patch where the shipped default\n * became STRICT. Below its floor a line either has no setting at all, or has it\n * with the DISABLED default, so the toggle stays hidden and never shows a mode\n * the cluster does not use.\n *\n * Above the 8.9 line, one floor covers everything: 8.10.0-alpha6 and all later\n * versions, 8.11 included. That floor has a second reason, which\n * SECRETS_FILTER_MODE_8_10_MIN_VERSION gives: on 8.10.0-alpha5 a mode other\n * than STRICT crashes the Connectors runtime at startup.\n *\n * Shared by the c4 settings tile and the console-backend update guard so\n * both stay in lockstep.\n */\nexport const isSecretsFilterModeConfigurable = (\n zeebeVersion: string | undefined,\n): boolean => {\n if (!zeebeVersion) {\n return false\n }\n const lineFloors = [\n SECRETS_FILTER_MODE_8_6_MIN_VERSION,\n SECRETS_FILTER_MODE_8_7_MIN_VERSION,\n SECRETS_FILTER_MODE_8_8_MIN_VERSION,\n SECRETS_FILTER_MODE_8_9_MIN_VERSION,\n ]\n for (const floor of lineFloors) {\n const isOnThisLine = checkVersion({\n possiblyVersionOrDockerPath: zeebeVersion,\n trueForSnapshot: 'compare',\n operator: VersionCheckOperator.SameMinor,\n versionToCompareTo: floor,\n })\n if (isOnThisLine) {\n return checkVersion({\n possiblyVersionOrDockerPath: zeebeVersion,\n trueForSnapshot: true,\n operator: VersionCheckOperator.GreaterThanOrEqual,\n versionToCompareTo: floor,\n })\n }\n }\n // Not on the 8.6-8.9 lines: either older than 8.6, which never had the\n // setting, or 8.10 and above, which all share the 8.10 floor.\n return checkVersion({\n possiblyVersionOrDockerPath: zeebeVersion,\n trueForSnapshot: true,\n operator: VersionCheckOperator.GreaterThanOrEqual,\n versionToCompareTo: SECRETS_FILTER_MODE_8_10_MIN_VERSION,\n })\n}\n"],
5
- "mappings": "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",
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 * as semver from 'semver'\nimport {\n APP_INTEGRATIONS_89_STREAM_CONNECTOR_BRIDGE_MIN_VERSION,\n APP_INTEGRATIONS_89_STREAM_MINOR,\n APP_INTEGRATIONS_89_STREAM_ZEEBE_MIN_VERSION,\n APP_INTEGRATIONS_MIN_VERSION,\n RESUME_ALPHA_MIN_VERSION,\n SECRETS_FILTER_MODE_8_6_MIN_VERSION,\n SECRETS_FILTER_MODE_8_7_MIN_VERSION,\n SECRETS_FILTER_MODE_8_8_MIN_VERSION,\n SECRETS_FILTER_MODE_8_9_MIN_VERSION,\n SECRETS_FILTER_MODE_8_10_MIN_VERSION,\n} from '../constants/version-gates.const.js'\n\n/**\n * stripSecfixPostfix removes the `-secfix` postfix of a version.\n *\n * A security patch tags the images of a generation with the postfix\n * (`8.8.19-secfix`). Semver reads the postfix as a prerelease, which sorts\n * under the release it patches. A `>= 8.8.19` gate thus refuses a patched\n * build of 8.8.19 itself. The postfix holds no version information, so it\n * comes off before every comparison.\n *\n * Only the postfix comes off, not the whole prerelease. A patched alpha\n * (`8.10.0-alpha5-secfix`) stays an alpha, which the 8.10 floors and\n * `isGenerationResumable` both depend on.\n *\n * A surface that shows a version reads this helper too, because the postfix is\n * an internal build detail. One helper keeps the version a customer sees and\n * the version a gate compares on the same rule.\n */\nexport const stripSecfixPostfix = (version: string): string => {\n // A search for the marker, and not a regular expression. `-secfix.*$` over\n // the input of an exported function is a polynomial backtracking pattern,\n // which code scanning rejects (CodeQL js/polynomial-redos).\n const postfixStart = version.toLowerCase().indexOf('-secfix')\n return postfixStart === -1 ? version : version.slice(0, postfixStart)\n}\n\n/**\n * The grammar of an image tag, as camunda/camunda-operator#6016 defines it.\n * `SNAPSHOT` keeps its own shape, thus the pattern does not cover it.\n *\n * A tag holds a version, and after the version it can hold one suffix:\n * - An alpha suffix (`-alpha5`, `-alpha1.1`) names a prerelease cohort.\n * - Every other suffix (`-rc1`, `-secfix`, `-hotfix1`) is a build detail of\n * the release. The build has the content of the release, thus the suffix\n * holds no version information.\n */\n// The lookahead needs a hyphen or the end of the tag after the alpha number.\n// Without it, an optional digit group lets the pattern match the `alpha`\n// prefix of a tag such as `alphatest1`. That tag is not an alpha, but the\n// pattern still matches it and drops the text after `alpha`.\n//\n// The digit group itself is not optional. The grammar names a cohort\n// `alphaN`, never bare `alpha`, so a bare `-alpha` suffix must fall to the\n// release, the same as every other suffix that is not a numbered cohort.\nconst ALPHA_PRERELEASE = /^alpha(\\d+(?:\\.\\d+)*)(?=$|-)/i\n\n/**\n * Gives an alpha identifier a dot before its number, thus semver compares the\n * number as a number. Without the dot semver compares `alpha10` and `alpha6`\n * as text, and `alpha10` sorts under `alpha6`.\n *\n * Text after the alpha number comes off, because the operator does not\n * support it. A patched alpha (`8.10.0-alpha5-secfix`) stays alpha5, which the\n * 8.10 floors and `isGenerationResumable` both depend on.\n *\n * A version that has no alpha comes back unchanged. A floor reads this\n * function alone, thus a floor keeps a prerelease that is not an alpha. The\n * sentinel `8.10.0-0` of `LINE_8_10_MIN_VERSION` needs that: it must sort\n * under every 8.10 prerelease, and a strip would make it the 8.10.0 release.\n */\nconst padAlphaIdentifier = (version: string): string => {\n const parsed = semver.parse(version)\n if (!parsed || parsed.prerelease.length === 0) {\n return version\n }\n // The whole prerelease, not its first identifier. semver splits\n // `alpha1.1` at the dot, and the fix number is the part after it.\n const alpha = ALPHA_PRERELEASE.exec(parsed.prerelease.join('.'))\n if (!alpha) {\n return version\n }\n // The digit group is mandatory in `ALPHA_PRERELEASE`, thus `alpha[1]`\n // always holds a value here.\n const release = `${parsed.major}.${parsed.minor}.${parsed.patch}`\n return `${release}-alpha.${alpha[1]}`\n}\n\n/**\n * Makes an image tag comparable with the rules of the operator. Two problems\n * need this, and both cost a support ticket (INC-8048):\n *\n * 1. semver sorts a prerelease UNDER its release, thus `8.8.19-hotfix1` fails\n * a `>= 8.8.19` gate. The operator reads that build as 8.8.19, because the\n * build holds the content of 8.8.19 plus a hotfix. Thus every suffix that\n * is not an alpha comes off.\n * 2. semver compares an alpha identifier as text. `padAlphaIdentifier`\n * corrects that.\n *\n * A `SNAPSHOT` tag comes back unchanged. `checkVersion` expands it, and only\n * when the caller asks for it with `trueForSnapshot`.\n *\n * Use this function for a tag, not for a floor. A floor is a boundary that we\n * write, thus it reads `padAlphaIdentifier` alone.\n */\nexport const normalizeGenerationVersion = (version: string): string => {\n if (version.includes('SNAPSHOT')) {\n return version\n }\n const parsed = semver.parse(version)\n if (!parsed || parsed.prerelease.length === 0) {\n return version\n }\n if (!ALPHA_PRERELEASE.test(parsed.prerelease.join('.'))) {\n return `${parsed.major}.${parsed.minor}.${parsed.patch}`\n }\n return padAlphaIdentifier(version)\n}\n\n/**\n * The SNAPSHOT tags of the grammar. A SNAPSHOT build comes from the head of a\n * branch, thus it has no patch number, and sometimes no minor number.\n */\nconst SNAPSHOT_TAG = /^(?:\\d+(?:\\.\\d+)?-)?SNAPSHOT$/\n\n/**\n * Is this value an image that a generation can use? The value must have the\n * form `repository:tag`, and the tag must obey the grammar of the operator\n * (camunda/camunda-operator#6016).\n *\n * The tag is the text after the LAST colon, not the second colon-delimited\n * segment. A registry host can carry a port\n * (`registry.example.com:5000/zeebe:8.10.0`), and `secfixGenerationArtifacts.ts`\n * already rewrites images of that shape.\n *\n * The grammar permits a suffix after the version, and this function does not\n * limit the text of that suffix. Two reasons:\n * - A security patch tags an alpha `8.10.0-alpha5-secfix`. Such images are in\n * production today, and the retag job makes more of them.\n * - The operator removes a suffix that it does not know, thus an unknown\n * suffix is safe. `normalizeGenerationVersion` does the same.\n *\n * Use this function at creation only. Generations from before the grammar\n * hold tags such as `3.9.0-preview-1`, and a read of those must still work.\n */\nexport const isValidGenerationImage = (image: string | undefined): boolean => {\n if (!image) {\n return false\n }\n const lastColon = image.lastIndexOf(':')\n // A colon at the start leaves an empty repository, thus `lastColon <= 0`\n // rejects both no colon (`-1`) and an empty repository (`0`).\n if (lastColon <= 0) {\n return false\n }\n const tag = image.slice(lastColon + 1)\n return SNAPSHOT_TAG.test(tag) || semver.valid(tag) !== null\n}\n\n/**\n * Takes the version out of a generation version field. The field holds either a\n * bare version (`8.10.0-alpha4`) or a docker path\n * (`camunda/zeebe:8.10.0-alpha4`, or `registry.example.com:5000/zeebe:8.10.0-alpha4`\n * for a registry with a port). A value that is neither comes back unchanged,\n * so the caller can still expand a `SNAPSHOT` tag.\n *\n * The version is the text after the LAST colon, not the second colon-delimited\n * segment \u2014 a registry port is also a colon-delimited segment, and comes\n * before the version, not after it.\n */\nconst extractVersion = (possiblyVersionOrDockerPath?: string): string => {\n const raw = possiblyVersionOrDockerPath ?? ''\n if (semver.valid(raw)) {\n return normalizeGenerationVersion(raw)\n }\n const lastColon = raw.lastIndexOf(':')\n if (lastColon !== -1) {\n return normalizeGenerationVersion(raw.slice(lastColon + 1))\n }\n // bare version string not valid semver (e.g. '8.10-SNAPSHOT') \u2014 use as-is so SNAPSHOT expansion can handle it\n return raw\n}\n\n// eslint-disable-next-line no-shadow\nexport enum VersionCheckOperator {\n LessThan,\n LessThanOrEqual,\n GreaterThan,\n GreaterThanOrEqual,\n SameMajor,\n SameMinor,\n}\n\nexport const checkVersion = (params: {\n possiblyVersionOrDockerPath?: string\n trueForSnapshot: boolean | 'compare'\n operator: VersionCheckOperator\n versionToCompareTo: string\n trueOnInvalidVersion?: boolean\n}) => {\n // quick exit: if the versionToCompareTo is\n // - `SNAPSHOT` there is not a lot we can compare here to, so we return false directly\n // - ends with `-SNAPSHOT` we ignore the `-SNAPSHOT` part for the comparison, guess a good matching semver compliant version and try to move on with the generated one in the code\n if (params.versionToCompareTo === 'SNAPSHOT') {\n return false\n }\n let versionToCompareTo = params.versionToCompareTo\n if (versionToCompareTo.endsWith('-SNAPSHOT')) {\n versionToCompareTo = versionToCompareTo.replace('-SNAPSHOT', '')\n const parts = versionToCompareTo.split('.')\n if (parts.length === 1) {\n versionToCompareTo = `${parts[0]}.0.0`\n } else if (parts.length === 2) {\n versionToCompareTo = `${parts[0]}.${parts[1]}.0`\n } else if (parts.length === 3) {\n versionToCompareTo = `${parts[0]}.${parts[1]}.${parts[2]}`\n }\n }\n versionToCompareTo = padAlphaIdentifier(versionToCompareTo)\n if (!semver.valid(versionToCompareTo)) {\n throw new Error('Invalid version to compare to')\n }\n let version: string = extractVersion(params.possiblyVersionOrDockerPath)\n if (params.trueForSnapshot && version.includes('SNAPSHOT')) {\n if (version === 'SNAPSHOT') {\n // bare SNAPSHOT: `true` short-circuits here; `'compare'` falls through to invalid-version handling\n if (params.trueForSnapshot !== 'compare') {\n return true\n }\n } else {\n version = version.replace('-SNAPSHOT', '')\n if (version.split('.').length === 1) {\n version = `${version}.99.99`\n }\n if (version.split('.').length === 2) {\n version = `${version}.99`\n }\n if (version.split('.').length === 3) {\n version = `${version.split('.')[0]}.${version.split('.')[1]}.99`\n }\n }\n }\n\n let parsedVersionToCompareTo: string = ''\n if (semver.valid(versionToCompareTo ?? '')) {\n parsedVersionToCompareTo = versionToCompareTo ?? ''\n } else {\n const versionSplit = versionToCompareTo?.split(':') ?? []\n if (versionSplit.length > 1) {\n parsedVersionToCompareTo = versionSplit[1]\n }\n }\n if (params.trueForSnapshot && parsedVersionToCompareTo === 'SNAPSHOT') {\n return true\n }\n\n if (!semver.valid(version)) {\n return !!params.trueOnInvalidVersion\n }\n\n switch (params.operator) {\n case VersionCheckOperator.LessThan:\n return semver.lt(version, parsedVersionToCompareTo)\n case VersionCheckOperator.LessThanOrEqual:\n return semver.lte(version, parsedVersionToCompareTo)\n case VersionCheckOperator.GreaterThan:\n return semver.gt(version, parsedVersionToCompareTo)\n case VersionCheckOperator.GreaterThanOrEqual:\n return semver.gte(version, parsedVersionToCompareTo)\n case VersionCheckOperator.SameMajor:\n return semver.major(version) === semver.major(parsedVersionToCompareTo)\n case VersionCheckOperator.SameMinor:\n return (\n semver.major(version) === semver.major(parsedVersionToCompareTo) &&\n semver.minor(version) === semver.minor(parsedVersionToCompareTo)\n )\n default:\n return false\n }\n}\n\n/**\n * Can a suspended cluster on this generation resume? An alpha generation under\n * `RESUME_ALPHA_MIN_VERSION` answers false. Every other generation answers\n * true.\n *\n * The floor applies to alphas only, because they have no upgrade chain.\n * `RESUME_ALPHA_MIN_VERSION` gives the full reason. A release generation under\n * the floor, 8.9 for example, keeps its resume action.\n *\n * An alpha carries a prerelease tag that starts with `alpha`. The test reads\n * that tag, not the presence of a prerelease. A security patch tags a release\n * generation `8.9.0-secfix`, which semver also reads as a prerelease. That\n * generation is a release and keeps its upgrade chain, so it stays resumable.\n *\n * The c4 resume actions and the console-backend wake-up guards share this\n * function. The frontend keeps the action and disables it, the backend refuses\n * the request, and both must agree on the cohort. Two copies of one floor is\n * #9703.\n *\n * The answer is true for a version this function cannot read as an alpha:\n * - A `SNAPSHOT` tag is built from main, so it is never one of the old alphas.\n * - An empty or invalid version tells us nothing. A guess of false locks a\n * customer out of a cluster that is good, so the safe answer is true.\n */\nexport const isGenerationResumable = (zeebeVersion?: string): boolean => {\n const version = extractVersion(zeebeVersion)\n const isAlpha = (semver.prerelease(version) ?? []).some(\n (part) =>\n typeof part === 'string' && part.toLowerCase().startsWith('alpha'),\n )\n if (!semver.valid(version) || !isAlpha) {\n return true\n }\n return checkVersion({\n possiblyVersionOrDockerPath: zeebeVersion,\n trueForSnapshot: true,\n operator: VersionCheckOperator.GreaterThanOrEqual,\n versionToCompareTo: RESUME_ALPHA_MIN_VERSION,\n })\n}\n\n/**\n * Version gate for the App Integrations exporter toggle (#8536). Shared by the\n * c4 settings tile and the console-backend update guard so both stay in\n * lockstep \u2014 the fix landed as patches on the 8.9 stream (zeebe >=8.9.14 AND\n * connectorBridge >=8.9.7), everything from 8.10.0-alpha4 on already carries\n * both fixes. A plain zeebe >=8.9.14 check would wrongly match\n * 8.10.0-alpha1/2/3, which predate the fix.\n */\nexport const isAppIntegrationsVersionSupported = (versions: {\n zeebe?: string\n connectorBridge?: string\n}): boolean => {\n if (!versions.zeebe) {\n return false\n }\n const isIn89Stream = checkVersion({\n possiblyVersionOrDockerPath: versions.zeebe,\n trueForSnapshot: 'compare',\n operator: VersionCheckOperator.SameMinor,\n versionToCompareTo: APP_INTEGRATIONS_89_STREAM_MINOR,\n })\n if (!isIn89Stream) {\n return checkVersion({\n possiblyVersionOrDockerPath: versions.zeebe,\n trueForSnapshot: true,\n operator: VersionCheckOperator.GreaterThanOrEqual,\n versionToCompareTo: APP_INTEGRATIONS_MIN_VERSION,\n })\n }\n return (\n checkVersion({\n possiblyVersionOrDockerPath: versions.zeebe,\n trueForSnapshot: true,\n operator: VersionCheckOperator.GreaterThanOrEqual,\n versionToCompareTo: APP_INTEGRATIONS_89_STREAM_ZEEBE_MIN_VERSION,\n }) &&\n checkVersion({\n possiblyVersionOrDockerPath: versions.connectorBridge,\n trueForSnapshot: true,\n operator: VersionCheckOperator.GreaterThanOrEqual,\n versionToCompareTo:\n APP_INTEGRATIONS_89_STREAM_CONNECTOR_BRIDGE_MIN_VERSION,\n })\n )\n}\n\n/**\n * Version gate for the secrets filter mode setting on Connectors\n * (`CAMUNDA_CONNECTOR_SECRETRESOLVER_SECRETFILTER_MODE`). Each 8.x line got the\n * fix on a different patch, so a single floor across all lines is wrong: it\n * would open the setting on an early patch of a newer line, or close it on a\n * late patch of an older line. This picks the zeebe minor line first, then\n * applies that line's own floor.\n *\n * On the 8.6 to 8.9 lines, each floor is the patch where the shipped default\n * became STRICT. Below its floor a line either has no setting at all, or has it\n * with the DISABLED default, so the toggle stays hidden and never shows a mode\n * the cluster does not use.\n *\n * Above the 8.9 line, one floor covers everything: 8.10.0-alpha6 and all later\n * versions, 8.11 included. That floor has a second reason, which\n * SECRETS_FILTER_MODE_8_10_MIN_VERSION gives: on 8.10.0-alpha5 a mode other\n * than STRICT crashes the Connectors runtime at startup.\n *\n * Shared by the c4 settings tile and the console-backend update guard so\n * both stay in lockstep.\n */\nexport const isSecretsFilterModeConfigurable = (\n zeebeVersion: string | undefined,\n): boolean => {\n if (!zeebeVersion) {\n return false\n }\n const lineFloors = [\n SECRETS_FILTER_MODE_8_6_MIN_VERSION,\n SECRETS_FILTER_MODE_8_7_MIN_VERSION,\n SECRETS_FILTER_MODE_8_8_MIN_VERSION,\n SECRETS_FILTER_MODE_8_9_MIN_VERSION,\n ]\n for (const floor of lineFloors) {\n const isOnThisLine = checkVersion({\n possiblyVersionOrDockerPath: zeebeVersion,\n trueForSnapshot: 'compare',\n operator: VersionCheckOperator.SameMinor,\n versionToCompareTo: floor,\n })\n if (isOnThisLine) {\n return checkVersion({\n possiblyVersionOrDockerPath: zeebeVersion,\n trueForSnapshot: true,\n operator: VersionCheckOperator.GreaterThanOrEqual,\n versionToCompareTo: floor,\n })\n }\n }\n // Not on the 8.6-8.9 lines: either older than 8.6, which never had the\n // setting, or 8.10 and above, which all share the 8.10 floor.\n return checkVersion({\n possiblyVersionOrDockerPath: zeebeVersion,\n trueForSnapshot: true,\n operator: VersionCheckOperator.GreaterThanOrEqual,\n versionToCompareTo: SECRETS_FILTER_MODE_8_10_MIN_VERSION,\n })\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["VersionCheckOperator"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camunda/ccma-shared-types",
3
- "version": "1.1.0",
3
+ "version": "2.0.0",
4
4
  "description": "Shared TypeScript types for Camunda Cloud Management Apps",
5
5
  "bugs": {
6
6
  "url": "https://github.com/camunda/camunda-cloud-management-apps/issues"