|
| 1 | +# Integration Visibility — Design Questions |
| 2 | + |
| 3 | +**Status:** Resolved — all decisions made |
| 4 | +**Related:** [Design document](enabled-integrations-design.md) |
| 5 | + |
| 6 | +Each question has options with trade-offs and a recommendation. Go through them one by one to form the design, then update the design document. |
| 7 | + |
| 8 | +--- |
| 9 | + |
| 10 | +## Q1: Allowlist vs. denylist approach? |
| 11 | + |
| 12 | +When a cluster admin wants to hide a broken integration, the system needs a mechanism. This affects the operational model and how much config admins need to maintain. |
| 13 | + |
| 14 | +### Option C: Denylist approach (`disabledIntegrations`) |
| 15 | + |
| 16 | +List what is disabled. Everything not in the list is enabled. |
| 17 | + |
| 18 | +- **Pro:** Backward compatible — existing deployments show everything. |
| 19 | +- **Pro:** Operationally simpler — the common case (everything healthy) is an empty field; admins only add the 1-2 broken integrations. |
| 20 | +- **Pro:** Adding a new integration requires no config change — it's enabled by default. |
| 21 | +- **Con:** The UI must check each integration against the disabled list (trivial). |
| 22 | + |
| 23 | +**Decision:** Option C — denylist approach. With an allowlist, admins must enumerate every integration; with a denylist the normal state is empty and only broken integrations are listed. |
| 24 | + |
| 25 | +_Considered and rejected: Option A — allowlist when populated (requires listing all integrations, higher operational overhead), Option B — explicit allowlist with nothing enabled by default (breaking change for existing deployments)._ |
| 26 | + |
| 27 | +--- |
| 28 | + |
| 29 | +## Q2: Should integrations be simple string identifiers or richer structs? |
| 30 | + |
| 31 | +This determines the shape of the array items in the CRD. |
| 32 | + |
| 33 | +### Option A: Simple `[]string` |
| 34 | + |
| 35 | +```yaml |
| 36 | +disabledIntegrations: |
| 37 | + - "openshift-lightspeed" |
| 38 | +``` |
| 39 | +
|
| 40 | +- **Pro:** Minimal API surface, easy to understand. |
| 41 | +- **Pro:** Follows the pattern used by comma-separated string lists elsewhere in the config (e.g. `domains`, `forbiddenUsernamePrefixes`), but as a proper array. |
| 42 | +- **Con:** No room for per-integration metadata (e.g. a display name or URL) without a future API change. |
| 43 | + |
| 44 | +**Decision:** Option A — simple `[]string` keeps the API minimal. The UI already knows how to render each integration; it only needs the enable/disable signal. |
| 45 | + |
| 46 | +_Considered and rejected: Option B — array of structs (over-engineered for current needs, display metadata belongs in UI), Option C — comma-separated string (less idiomatic for CRDs)._ |
| 47 | + |
| 48 | +--- |
| 49 | + |
| 50 | +## Q3: Where should the field live in the config hierarchy? |
| 51 | + |
| 52 | +The `ToolchainConfig` has a deep nested structure. The field placement affects who "owns" this configuration conceptually. |
| 53 | + |
| 54 | +### Option A: Under `spec.host.registrationService` |
| 55 | + |
| 56 | +```yaml |
| 57 | +spec: |
| 58 | + host: |
| 59 | + registrationService: |
| 60 | + disabledIntegrations: |
| 61 | + - "openshift-lightspeed" |
| 62 | +``` |
| 63 | + |
| 64 | +- **Pro:** The registration service is the component that exposes this data; co-locating it with other registration service config is natural. |
| 65 | +- **Pro:** Follows the pattern of `uiCanaryDeploymentWeight` and `workatoWebHookURL` which are UI-facing config under `registrationService`. |
| 66 | +- **Con:** Conceptually, "which integrations are disabled" could be considered a broader host-level concern, not specific to the registration service. |
| 67 | + |
| 68 | +**Decision:** Option A — co-locate with other UI-facing config under `registrationService`, following existing precedent. |
| 69 | + |
| 70 | +_Considered and rejected: Option B — under `spec.host` directly (only registration service needs it, would bloat HostConfig)._ |
| 71 | + |
| 72 | +--- |
| 73 | + |
| 74 | +## Q4: Should this be a new endpoint or added to the existing `/api/v1/uiconfig`? |
| 75 | + |
| 76 | +The registration service already has `GET /api/v1/uiconfig` that returns UI-facing configuration (canary weight, Workato URL). |
| 77 | + |
| 78 | +### Option A: Extend `/api/v1/uiconfig` |
| 79 | + |
| 80 | +Add the integration visibility field to the existing `UIConfigResponse`. |
| 81 | + |
| 82 | +- **Pro:** No new endpoint to maintain; the UI already calls `/api/v1/uiconfig`. |
| 83 | +- **Pro:** Keeps UI configuration consolidated in one place. |
| 84 | +- **Con:** Makes the uiconfig response grow over time; it's currently JWT-secured, which means unauthenticated callers cannot access it. |
| 85 | + |
| 86 | +**Decision:** Option A — add to existing `UIConfigResponse`. Avoids an extra HTTP round-trip and keeps UI configuration consolidated. |
| 87 | + |
| 88 | +_Considered and rejected: Option B — new dedicated endpoint (extra maintenance burden, extra HTTP call from the UI)._ |
| 89 | + |
| 90 | +--- |
| 91 | + |
| 92 | +## Q5: Should the endpoint be secured (JWT) or unsecured? |
| 93 | + |
| 94 | +Currently `/api/v1/uiconfig` requires JWT authentication. The list of disabled integrations is not sensitive, but access control is a consideration. |
| 95 | + |
| 96 | +### Option A: Keep it secured (current behavior for `/api/v1/uiconfig`) |
| 97 | + |
| 98 | +- **Pro:** No security posture change. |
| 99 | +- **Pro:** Only authenticated users see what integrations are available. |
| 100 | +- **Con:** The UI must have a valid token before it can determine what to render, which may delay the initial page load or require the UI to handle a two-phase render. |
| 101 | + |
| 102 | +**Decision:** Option A — keep the endpoint JWT-secured. No security posture change needed; the UI already has a token when it renders integration entry points. |
| 103 | + |
| 104 | +_Considered and rejected: Option B — unsecured (would also expose workatoWebHookURL and canary weight), Option C — split into new unsecured endpoint (contradicts Q4 decision)._ |
| 105 | + |
| 106 | +--- |
| 107 | + |
| 108 | +## Q6: What should the CRD field be named? |
| 109 | + |
| 110 | +Naming affects clarity, consistency with the codebase, and how the field appears in the CRD YAML. |
| 111 | + |
| 112 | +### Option A: `disabledIntegrations` |
| 113 | + |
| 114 | +```yaml |
| 115 | +disabledIntegrations: |
| 116 | + - "openshift-lightspeed" |
| 117 | +``` |
| 118 | +JSON tag: `disabledIntegrations` |
| 119 | + |
| 120 | +- **Pro:** Directly communicates the denylist semantics — these are the integrations that are turned off. |
| 121 | +- **Pro:** Consistent with the naming pattern of the approach (listing what's disabled). |
| 122 | +- **Con:** Slightly long. |
| 123 | + |
| 124 | +**Decision:** Option A (`disabledIntegrations`) — unambiguous, directly reflects the denylist semantics. |
| 125 | + |
| 126 | +_Considered and rejected: Option B — `integrations` (ambiguous), Option C — `hiddenIntegrations` (UI term out of place in a CRD)._ |
| 127 | + |
| 128 | +--- |
| 129 | + |
| 130 | +## Q7: What should the REST response JSON property be named? |
| 131 | + |
| 132 | +The CRD field is `disabledIntegrations` (a denylist), but the REST response could either mirror the CRD directly or translate the semantics for the UI's convenience. This affects where the "is this integration disabled?" logic lives. |
| 133 | + |
| 134 | +### Option A: Mirror the CRD — expose `disabledIntegrations` in the JSON response |
| 135 | + |
| 136 | +```json |
| 137 | +{ |
| 138 | + "uiCanaryDeploymentWeight": 20, |
| 139 | + "workatoWebHookURL": "https://...", |
| 140 | + "disabledIntegrations": ["openshift-lightspeed"] |
| 141 | +} |
| 142 | +``` |
| 143 | + |
| 144 | +- **Pro:** 1:1 mapping with the CRD — simple, transparent, no translation layer. |
| 145 | +- **Pro:** The UI can trivially check `disabledIntegrations.includes("x")` before rendering each integration. |
| 146 | +- **Pro:** Empty array `[]` unambiguously means "nothing is disabled" (everything enabled). |
| 147 | +- **Con:** The UI works with a negative list, which some may find less intuitive than a positive one. |
| 148 | + |
| 149 | +**Decision:** Option A — mirror the CRD directly. Simple, no master list needed, trivial UI check. |
| 150 | + |
| 151 | +_Considered and rejected: Option B — translate to `enabledIntegrations` (requires backend to maintain a hardcoded master list of all integrations, adds a translation layer that can drift)._ |
0 commit comments