feat(init): list sub-orgs with counts in org picker (ENG-4673)#157
feat(init): list sub-orgs with counts in org picker (ENG-4673)#157
Conversation
- Add GET /v1/organization/accessible-with-sub-orgs API call with ErrEndpointNotSupported sentinel for older self-hosted instances - Use flat GET /v1/organization list as source of truth; enrich with sub-org counts best-effort (failures fall back silently with debug log) - Show two-level picker: root org with sub-org count, then sub-org selector - Extract api.Organization named type; apply same sub-org picker to login flow - Update E2E login test to handle optional sub-org prompt step
Greptile SummaryThis PR enriches the Key changes:
Issues found:
Confidence Score: 4/5
Important Files Changed
|
45478d7 to
396ee58
Compare
- Remove unused Label field from OrgPickerItem (only ID is used by callers) - Add username to debug log for sub-org fetch failures per logging convention
|
docs for the subor support as organization-id Infisical/infisical#5793 |
akhilmhdh
left a comment
There was a problem hiding this comment.
Application testing pending
|
|
||
| // 404 means this Infisical instance doesn't support the endpoint yet (older self-hosted). | ||
| // Check before the generic IsError() so we can return the sentinel instead of an API error. | ||
| if response.StatusCode() == http.StatusNotFound { |
There was a problem hiding this comment.
This could be also when a resource not found as well right? I think Route not found has an explicit message
| PrintErrorMessageAndExit(message) | ||
| // BuildOrgRootLabels returns first-prompt labels: org name with sub-org count when present. | ||
| // orgs is the flat list from GET /v1/organization; subOrgMap is keyed by org ID. | ||
| func BuildOrgRootLabels(orgs []api.Organization, subOrgMap map[string][]api.SubOrganization) []string { |
There was a problem hiding this comment.
Nit: With go static type - we already know it's a map - i don't think we need to say it again as subOrgMap
| stepChan <- step | ||
| } else if strings.Contains(terminalOut, "Which of your Infisical projects would you like to connect this project to?") && step < 1 { | ||
| step += 1; | ||
| } else if strings.Contains(terminalOut, "Which scope within") && step < 1 { |
There was a problem hiding this comment.
What is the meaning of scope?
Summary
GET /v1/organization/accessible-with-sub-orgsto enrich the org picker with sub-org counts (e.g.Acme Corp (3 sub-orgs)). The existing flatGET /v1/organizationlist remains the source of truth — if the new endpoint is unavailable (older self-hosted instances return 404), the picker falls back gracefully with no visible change to the user.pickOrganizationhelper is reused in theloginflow with a context-appropriate label.api.Organizationtype (replaces anonymous struct), debug log on sub-org fetch failure, comment explaining the 404 sentinel check ordering.Test plan
infisical initon an account with no sub-orgs — single prompt, behaviour unchangedinfisical initon an account with sub-orgs — first prompt shows counts, second prompt shows root org + sub-orgsinfisical initagainst an older self-hosted instance (404 on new endpoint) — falls back to flat list, no error showninfisical logininteractive flow shows correct "log into" label instead of "select a project from"test/login_test.go)🤖 Generated with Claude Code