This repository was archived by the owner on Feb 6, 2026. It is now read-only.
Commit ccfd2ac
committed
feat(luminork): Change set review endpoint
Adds a new `/review` endpoint to the Luminork API that provides a comprehensive, single-call review of all component changes in a change set.
## Motivation
Currently, to review all changes in a change set, clients would need to:
1. List all components
2. Fetch individual component diffs for each one
3. Fetch component metadata for subscription resolution
4. Filter out noise (empty defaults, internal fields, etc.)
This requires **N+1 API calls** and complex client-side logic. For workspaces with 100+ components, this is slow and inefficient.
## Solution
New endpoint: `GET /v1/w/{workspace_id}/change-sets/{change_set_id}/review`
Returns all component diffs with changes in a **single API call**, with:
- ✅ Pre-filtered attribute diffs (removes noise)
- ✅ Simplified, CLI-friendly format
- ✅ Subscription source resolution included
- ✅ Summary statistics
- ✅ Optional resource code diffs
## Implementation Details
### **Uses Pre-Computed MVs from Frigg**
The endpoint leverages existing `ComponentDiff` materialized views:
- Fetches from Frigg's object store (fast!)
- Returns **202 Accepted** if MVs not ready (triggers edda rebuild)
- No expensive on-demand diff calculation
### **Smart Filtering (Same as Web UI)**
Applies the same filtering logic as `app/web/src/newhotness/Review.vue`:
**Excluded diffs:**
- Internal fields: `/si/type`, `/si/color`
- Identical old/new values (can occur on schema upgrades)
- Empty schema defaults: `{}`, `[]`, `null`, `""`, `0`
- Object field placeholders at top-level paths
**Diff status recalculation:**
- If filtering removes all attribute diffs → `Modified` becomes `None`
- Only returns components with meaningful changes
### **Simplified Response Format**
Instead of the complex MV format:
```json
{
"$source": {
"component": "01HZZZ...",
"path": "/domain/region"
},
"$value": "us-east-1"
}
```
Returns CLI-friendly format:
```json
{
"changeType": "added",
"newValue": "us-east-1",
"newSourceType": "subscription",
"newSourceComponentName": "region-1",
"newSourcePath": "/domain/region"
}
```
## Design Decisions
### Why Not Parallel MV Fetching?
Uses sequential fetching with early filtering instead of parallel. This is fine because:
- MVs are pre-computed and cached (fast to fetch)
- We filter by diff_status early (skip unchanged components)
- Simpler error handling
- Follows existing patterns in the codebase
### Why Server-Side Filtering?
- **Consistency**: Web and CLI show the same filtered view
- **Simplicity**: CLI doesn't need to reimplement filtering logic
- **Single source of truth**: Changes to filtering happen in one place
- **Better UX**: Users see clean, curated diffs
### Why Simplified Format?
The raw MV format with `$source` and `$value` is:
- Hard to parse
- Verbose
- Requires understanding SI's internal data model
The simplified format is:
- Self-documenting
- Easy to render in CLI
- Clear separation of value vs source
## Example Responses
```
{
"components": [
{
"componentId": "01KF272RATCMXECD5GHD7291B1",
"componentName": "test",
"schemaName": "AWS Credential",
"diffStatus": "Added",
"attributeDiffs": {
"/si/name": {
"changeType": "added",
"newValue": "test",
"newSourceType": "value"
},
"/secrets/AWS Credential": {
"changeType": "added",
"newValue": "fb24d5e22162989a269899c3e3d27654",
"newSourceType": "value"
}
}
},
{
"componentId": "01KF28M419BZXWWXN4EKQPNFKM",
"componentName": "si-0953",
"schemaName": "Region",
"diffStatus": "Added",
"attributeDiffs": {
"/si/name": {
"changeType": "added",
"newValue": "si-0953",
"newSourceType": "value"
},
"/domain/region": {
"changeType": "added",
"newValue": "us-east-1",
"newSourceType": "value"
},
"/secrets/credential": {
"changeType": "added",
"newValue": "fb24d5e22162989a269899c3e3d27654",
"newSourceType": "subscription",
"newSourceComponentName": "test",
"newSourceComponentId": "01KF272RATCMXECD5GHD7291B1",
"newSourcePath": "/secrets/AWS Credential"
}
}
}
],
"summary": {
"totalComponents": 2,
"added": 2,
"modified": 0,
"removed": 0
}
}
```
```
{
"components": [
{
"componentId": "01KF28M419BZXWWXN4EKQPNFKM",
"componentName": "si-0953",
"schemaName": "Region",
"diffStatus": "Modified",
"attributeDiffs": {
"/domain/region": {
"changeType": "modified",
"newValue": "us-east-2",
"oldValue": "us-east-1",
"newSourceType": "value",
"oldSourceType": "value"
}
}
}
],
"summary": {
"totalComponents": 1,
"added": 0,
"modified": 1,
"removed": 0
}
}
```1 parent d57a38e commit ccfd2ac
17 files changed
Lines changed: 2005 additions & 1 deletion
File tree
- generated-sdks
- python
- system_initiative_api_client
- api
- models
- test
- typescript
- lib/luminork-server/src/service
- v1
- change_sets
Lines changed: 8 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
53 | 53 | | |
54 | 54 | | |
55 | 55 | | |
| 56 | + | |
56 | 57 | | |
57 | 58 | | |
58 | 59 | | |
59 | 60 | | |
60 | 61 | | |
61 | 62 | | |
62 | 63 | | |
| 64 | + | |
63 | 65 | | |
64 | 66 | | |
65 | 67 | | |
| |||
153 | 155 | | |
154 | 156 | | |
155 | 157 | | |
| 158 | + | |
156 | 159 | | |
157 | 160 | | |
158 | 161 | | |
| |||
171 | 174 | | |
172 | 175 | | |
173 | 176 | | |
| 177 | + | |
174 | 178 | | |
175 | 179 | | |
176 | 180 | | |
| |||
235 | 239 | | |
236 | 240 | | |
237 | 241 | | |
| 242 | + | |
238 | 243 | | |
239 | 244 | | |
240 | 245 | | |
241 | 246 | | |
242 | 247 | | |
243 | 248 | | |
244 | 249 | | |
| 250 | + | |
245 | 251 | | |
246 | 252 | | |
247 | 253 | | |
| |||
335 | 341 | | |
336 | 342 | | |
337 | 343 | | |
| 344 | + | |
338 | 345 | | |
339 | 346 | | |
340 | 347 | | |
| |||
353 | 360 | | |
354 | 361 | | |
355 | 362 | | |
| 363 | + | |
356 | 364 | | |
357 | 365 | | |
358 | 366 | | |
| |||
Lines changed: 307 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
16 | 16 | | |
17 | 17 | | |
18 | 18 | | |
19 | | - | |
| 19 | + | |
| 20 | + | |
20 | 21 | | |
| 22 | + | |
21 | 23 | | |
22 | 24 | | |
23 | 25 | | |
| |||
2260 | 2262 | | |
2261 | 2263 | | |
2262 | 2264 | | |
| 2265 | + | |
| 2266 | + | |
| 2267 | + | |
| 2268 | + | |
| 2269 | + | |
| 2270 | + | |
| 2271 | + | |
| 2272 | + | |
| 2273 | + | |
| 2274 | + | |
| 2275 | + | |
| 2276 | + | |
| 2277 | + | |
| 2278 | + | |
| 2279 | + | |
| 2280 | + | |
| 2281 | + | |
| 2282 | + | |
| 2283 | + | |
| 2284 | + | |
| 2285 | + | |
| 2286 | + | |
| 2287 | + | |
| 2288 | + | |
| 2289 | + | |
| 2290 | + | |
| 2291 | + | |
| 2292 | + | |
| 2293 | + | |
| 2294 | + | |
| 2295 | + | |
| 2296 | + | |
| 2297 | + | |
| 2298 | + | |
| 2299 | + | |
| 2300 | + | |
| 2301 | + | |
| 2302 | + | |
| 2303 | + | |
| 2304 | + | |
| 2305 | + | |
| 2306 | + | |
| 2307 | + | |
| 2308 | + | |
| 2309 | + | |
| 2310 | + | |
| 2311 | + | |
| 2312 | + | |
| 2313 | + | |
| 2314 | + | |
| 2315 | + | |
| 2316 | + | |
| 2317 | + | |
| 2318 | + | |
| 2319 | + | |
| 2320 | + | |
| 2321 | + | |
| 2322 | + | |
| 2323 | + | |
| 2324 | + | |
| 2325 | + | |
| 2326 | + | |
| 2327 | + | |
| 2328 | + | |
| 2329 | + | |
| 2330 | + | |
| 2331 | + | |
| 2332 | + | |
| 2333 | + | |
| 2334 | + | |
| 2335 | + | |
| 2336 | + | |
| 2337 | + | |
| 2338 | + | |
| 2339 | + | |
| 2340 | + | |
| 2341 | + | |
| 2342 | + | |
| 2343 | + | |
| 2344 | + | |
| 2345 | + | |
| 2346 | + | |
| 2347 | + | |
| 2348 | + | |
| 2349 | + | |
| 2350 | + | |
| 2351 | + | |
| 2352 | + | |
| 2353 | + | |
| 2354 | + | |
| 2355 | + | |
| 2356 | + | |
| 2357 | + | |
| 2358 | + | |
| 2359 | + | |
| 2360 | + | |
| 2361 | + | |
| 2362 | + | |
| 2363 | + | |
| 2364 | + | |
| 2365 | + | |
| 2366 | + | |
| 2367 | + | |
| 2368 | + | |
| 2369 | + | |
| 2370 | + | |
| 2371 | + | |
| 2372 | + | |
| 2373 | + | |
| 2374 | + | |
| 2375 | + | |
| 2376 | + | |
| 2377 | + | |
| 2378 | + | |
| 2379 | + | |
| 2380 | + | |
| 2381 | + | |
| 2382 | + | |
| 2383 | + | |
| 2384 | + | |
| 2385 | + | |
| 2386 | + | |
| 2387 | + | |
| 2388 | + | |
| 2389 | + | |
| 2390 | + | |
| 2391 | + | |
| 2392 | + | |
| 2393 | + | |
| 2394 | + | |
| 2395 | + | |
| 2396 | + | |
| 2397 | + | |
| 2398 | + | |
| 2399 | + | |
| 2400 | + | |
| 2401 | + | |
| 2402 | + | |
| 2403 | + | |
| 2404 | + | |
| 2405 | + | |
| 2406 | + | |
| 2407 | + | |
| 2408 | + | |
| 2409 | + | |
| 2410 | + | |
| 2411 | + | |
| 2412 | + | |
| 2413 | + | |
| 2414 | + | |
| 2415 | + | |
| 2416 | + | |
| 2417 | + | |
| 2418 | + | |
| 2419 | + | |
| 2420 | + | |
| 2421 | + | |
| 2422 | + | |
| 2423 | + | |
| 2424 | + | |
| 2425 | + | |
| 2426 | + | |
| 2427 | + | |
| 2428 | + | |
| 2429 | + | |
| 2430 | + | |
| 2431 | + | |
| 2432 | + | |
| 2433 | + | |
| 2434 | + | |
| 2435 | + | |
| 2436 | + | |
| 2437 | + | |
| 2438 | + | |
| 2439 | + | |
| 2440 | + | |
| 2441 | + | |
| 2442 | + | |
| 2443 | + | |
| 2444 | + | |
| 2445 | + | |
| 2446 | + | |
| 2447 | + | |
| 2448 | + | |
| 2449 | + | |
| 2450 | + | |
| 2451 | + | |
| 2452 | + | |
| 2453 | + | |
| 2454 | + | |
| 2455 | + | |
| 2456 | + | |
| 2457 | + | |
| 2458 | + | |
| 2459 | + | |
| 2460 | + | |
| 2461 | + | |
| 2462 | + | |
| 2463 | + | |
| 2464 | + | |
| 2465 | + | |
| 2466 | + | |
| 2467 | + | |
| 2468 | + | |
| 2469 | + | |
| 2470 | + | |
| 2471 | + | |
| 2472 | + | |
| 2473 | + | |
| 2474 | + | |
| 2475 | + | |
| 2476 | + | |
| 2477 | + | |
| 2478 | + | |
| 2479 | + | |
| 2480 | + | |
| 2481 | + | |
| 2482 | + | |
| 2483 | + | |
| 2484 | + | |
| 2485 | + | |
| 2486 | + | |
| 2487 | + | |
| 2488 | + | |
| 2489 | + | |
| 2490 | + | |
| 2491 | + | |
| 2492 | + | |
| 2493 | + | |
| 2494 | + | |
| 2495 | + | |
| 2496 | + | |
| 2497 | + | |
| 2498 | + | |
| 2499 | + | |
| 2500 | + | |
| 2501 | + | |
| 2502 | + | |
| 2503 | + | |
| 2504 | + | |
| 2505 | + | |
| 2506 | + | |
| 2507 | + | |
| 2508 | + | |
| 2509 | + | |
| 2510 | + | |
| 2511 | + | |
| 2512 | + | |
| 2513 | + | |
| 2514 | + | |
| 2515 | + | |
| 2516 | + | |
| 2517 | + | |
| 2518 | + | |
| 2519 | + | |
| 2520 | + | |
| 2521 | + | |
| 2522 | + | |
| 2523 | + | |
| 2524 | + | |
| 2525 | + | |
| 2526 | + | |
| 2527 | + | |
| 2528 | + | |
| 2529 | + | |
| 2530 | + | |
| 2531 | + | |
| 2532 | + | |
| 2533 | + | |
| 2534 | + | |
| 2535 | + | |
| 2536 | + | |
| 2537 | + | |
| 2538 | + | |
| 2539 | + | |
| 2540 | + | |
| 2541 | + | |
| 2542 | + | |
| 2543 | + | |
| 2544 | + | |
| 2545 | + | |
| 2546 | + | |
| 2547 | + | |
| 2548 | + | |
| 2549 | + | |
| 2550 | + | |
| 2551 | + | |
| 2552 | + | |
| 2553 | + | |
| 2554 | + | |
| 2555 | + | |
| 2556 | + | |
| 2557 | + | |
| 2558 | + | |
| 2559 | + | |
| 2560 | + | |
| 2561 | + | |
| 2562 | + | |
| 2563 | + | |
| 2564 | + | |
| 2565 | + | |
| 2566 | + | |
| 2567 | + | |
| 2568 | + | |
0 commit comments