feat(organizations): cross-product sites listing via sites:list:cross_product scope (SITES-46454)#2607
Draft
ravverma wants to merge 3 commits into
Draft
feat(organizations): cross-product sites listing via sites:list:cross_product scope (SITES-46454)#2607ravverma wants to merge 3 commits into
ravverma wants to merge 3 commits into
Conversation
…_product scope (SITES-46454)
Phase 1 of multi-product login support. GET /organizations/{id}/sites
now consults authInfo.hasScope('sites:list:cross_product'). When the
scope is present (minted by spacecat-auth-service at login time for
allow-listed IMS client_ids; surfaced as a first-class AuthInfo scope
by spacecat-shared-http-utils JwtHandler), the own-sites filter is
widened from a single x-product to a union across every product the
org is entitled to, deduped by site id.
The entitlement, tier-visibility (CUSTOMER_VISIBLE_TIERS), and
enrollment gates are preserved per-product — we drop only the
single-product restriction. Sites the org has no entitlement to under
any product never appear; PRE_ONBOARD-tier sites stay hidden from
non-admins.
The delegated-sites flow is unchanged — it stays product-pinned to
x-product (which therefore remains required by the route signature).
SiteDto.toJSON is unchanged.
New getEntitledProductCodes(context, organization) helper in
src/support/utils.js next to filterSitesForProductCode. Pure read,
iterates EntitlementModel.PRODUCT_CODES via TierClient.
Design ADR: adobe/mysticat-architecture#139
Jira: SITES-46454
Tests:
- only sites enrolled under entitled products are returned
- union across multiple entitled products, deduped by site id
- empty list when org has no entitlements
- PRE_ONBOARD tier hidden from non-admin (tier-visibility gate preserved)
- single-product behaviour unchanged when scope is absent
- getEntitledProductCodes helper covers zero / single / multiple
entitled-product cases
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
3 tasks
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
|
This PR will trigger a minor release when merged. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Phase 1 of multi-product login support (SITES-46453).
GET /organizations/{organizationId}/sitesnow consultsauthInfo.hasScope('sites:list:cross_product'). When the scope is present (minted byspacecat-auth-serviceat login for allow-listed IMSclient_ids; surfaced as a first-classAuthInfoscope byspacecat-shared-http-utilsJwtHandler), the own-sites filter is widened from a singlex-productto a union across every product the org is entitled to, deduped by site id.The entitlement, tier-visibility (
CUSTOMER_VISIBLE_TIERS), and enrollment gates are preserved per-product — only the single-product restriction is dropped. Sites the org has no entitlement to under any product never appear; PRE_ONBOARD-tier sites stay hidden from non-admins.The delegated-sites flow is unchanged — it stays product-pinned to
x-product(which therefore remains required by the route signature).SiteDto.toJSONis unchanged.Companion PRs (must release first):
spacecat-shared— JWT handler fan-out (PR)spacecat-auth-service— login-time scope minting (PR)Design ADR: adobe/mysticat-architecture#139
Jira: SITES-46454 (parent: SITES-46453)
What changed
src/controllers/organizations.js→getSitesForOrganization: branch on the scope, call new helper, union with dedupe.src/support/utils.js: newgetEntitledProductCodes(context, organization)helper next tofilterSitesForProductCode. Pure read; iteratesEntitlementModel.PRODUCT_CODESviaTierClient.Containment
Only this controller consults
sites:list:cross_product. The literal string appears in exactly two places in this repo (controller + test) plus the auth-service mint site and thejwt.jsnamespace constants. Enforced by code review on the allow-list; any new caller of the scope requires an ADR update.Test plan
npx mocha test/controllers/organizations.test.js test/support/utils.test.js— 203 passingspacecat-shared-http-utilsrelease (will bump the dep version in a follow-up commit before merge).🤖 Generated with Claude Code