unbridled-41 opened a new issue, #4789:
URL: https://github.com/apache/rocketmq-dashboard/issues/4789

   ### Studio Version
   
   Trunk `rocketmq-studio` @ `4c697f07` (line references are as of that commit).
   
   ### Problem
   
   `InstanceService` holds an already-resolved instance but hands its **numeric 
id as a string** to the vendor provider for resource counts:
   
   - `loadCounts` 
(`server/src/main/java/org/apache/rocketmq/studio/instance/InstanceService.java:180-186`,
 used by the instance list via `fillCountsInParallel`): 
`provider.countTopics(String.valueOf(instance.getId()))`.
   - the delete guard (`InstanceService.java:654-658`): 
`provider.countTopics(String.valueOf(id))` decides whether an instance may be 
deleted.
   
   Every provider resolves that string through 
`InstanceRepository.findByIdentifier` (`InstanceRepository.java:42-57`), which 
tries the unique **name first** and only falls back to the numeric id. Instance 
names are free-form (up to 64 chars, digits allowed — `requireInstanceName` 
only trims and length-checks), so an instance literally named `42` shadows the 
instance whose primary key is `42`:
   
   1. The instance list row for the numeric instance shows the named instance's 
topic/group counts (or a misleading 400 "missing cloud binding" when the named 
instance is Apache and the counted one is cloud).
   2. Worse, the destructive path: `POST` delete of the numeric instance 
evaluates its managed-resource guard against the **named** instance. An 
operator can delete an instance whose topics/groups still exist, orphaning 
them; and the opposite direction blocks a legitimately empty instance.
   
   ### Evidence
   
   1. `findByIdentifier` → `findByName(identifier)` before 
`findById(Long.parseLong(...))` with no rejection of pure-digit names 
(`InstanceRepository.java:46-51`).
   2. `requireInstanceName` (`InstanceService.java:554-562`) imposes no charset 
constraint, and `createApacheInstance` only requires name + endpoint, so a 
numeric name is storable through the public API today.
   3. The codebase's own javadoc on `findByIdentifier` says the name is primary 
and the id a fallback — callers that already hold the resolved instance must 
not round-trip through that ambiguous resolution.
   4. `ApacheInstanceProvider.countTopics` 
(`provider/apache/ApacheInstanceProvider.java:76-81`) maps through 
`findByIdentifier(...).getName()` then counts by that name — so the string is 
resolved by name first, confirming the shadowing.
   
   ### Impact
   
   - Wrong resource counts on the instance list for any deployment where an 
instance name equals another instance's numeric id (self-inflicted but storable 
via the API, and ids are small sequential integers so collisions are realistic).
   - The delete guard can read the wrong instance's counts: deletion of a 
non-empty instance succeeds (orphans its topics/groups), or a clean instance is 
blocked by another instance's counts.
   
   ### Expected behavior
   
   Callers that already hold the resolved `InstanceVO` pass its canonical name 
(`getName()`) to the provider; name-first resolution of the canonical name 
always returns the instance itself, immune to shadowing.
   
   ### Related work
   
   - #2050 (closed): established "instance name is the immutable external 
identifier" — this defect is the callers that bypass it by passing the id 
string.
   - #4716 (closed): legacy null-vendor reading, same package, unrelated to 
identifier resolution.
   - #4006 (open): offline-client 502 — different resolution surface 
(`RocketMQClientProvider`), unaffected by this change.
   
   ## PR
   
   Fix: #… (opened together with this issue).


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to