Conversation
Adds the spacecat-shared primitives needed to implement Path A/B access
resolution and the delegated-site dropdown in the api-service.
**spacecat-shared-http-utils / AuthInfo**
- `isDelegatedTenantsComplete()`: returns `true` when the
`delegated_tenants_complete` JWT claim is absent or `true`; `false`
when the claim is explicitly `false`. Used by `hasAccess()` to switch
between the JWT-gate fast-deny path (Path A, ≤20 grants) and the
DB-direct path (Path B, truncated list). Defaults to `true` for
backward-compat with old tokens that predate the claim.
**spacecat-shared-data-access / BaseCollection**
- `createInstanceFromRow(row)`: public wrapper around the private
`#toModelRecord` + `#createInstance` pipeline. Lets other collections
convert an embedded PostgREST sub-row (snake_case) into a proper model
instance without duplicating field-mapping logic.
**spacecat-shared-data-access / SiteImsOrgAccessCollection**
- `findBySiteIdAndOrganizationIdAndProductCode(siteId, orgId, product)`:
thin public wrapper around `findByIndexKeys`. Used by `hasAccess()` for
the DB revocation check (Path A) and DB-direct lookup (Path B).
- `allByOrganizationIdWithSites(organizationId)`: PostgREST embedding
query (`sites!fkey(*)`) — returns `{ grant, site }` pairs in a single
round-trip. `site` is a proper Site model instance via
`BaseCollection.createInstanceFromRow`. Replaces the N+1
`allByOrganizationId` + batch `Site.findById` pattern for the
delegated-site dropdown.
- Internal refactor of the existing `#fetchGrantsWithTargetOrg`:
extracted `static #toGrant(row)` (8-field snake→camelCase mapper) and
`async #fetchPaginatedGrants(query, mapRow, errorMessage)` (shared
pagination loop). Both existing embedding methods and the new
`#fetchGrantsWithSite` are now thin wrappers — no behaviour change.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The grant field in allByOrganizationIdWithTargetOrganization, allByOrganizationIdsWithTargetOrganization, and allByOrganizationIdWithSites was a plain camelCase object. It is now a proper SiteImsOrgAccess model instance, so all three methods return consistent types (getters everywhere). Removes the now-unnecessary static #toGrant helper and calls this.createInstanceFromRow(row) directly in both #fetchGrantsWithTargetOrg and #fetchGrantsWithSite. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
This PR will trigger a minor release when merged. |
grant is now a SiteImsOrgAccess model instance, so property access (entry.grant.organizationId) must be replaced with getters (entry.grant.getOrganizationId()). Same for siteId and targetOrganizationId. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The all-collections-methods-coverage smoke test invokes every public method including createInstanceFromRow (starts with 'create', treated as mutating). With no args the call reached fromDbRecord(undefined) and threw a TypeError that didn't match the expected-error patterns, failing all 36 collection smoke tests. Add an isNonEmptyObject guard so the method returns null gracefully instead of throwing — consistent with #createInstance's own null-return contract for empty records. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Member
Author
|
@solaris007 this contains a bunch of helpers for the feature I will implement in api-service side. Due to time constraints, I will need to merge this. Please review, but I will address the reviews retroactively in a separate PR. |
solaris007
pushed a commit
that referenced
this pull request
Mar 19, 2026
## [@adobe/spacecat-shared-data-access-v3.26.0](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-data-access-v3.25.0...@adobe/spacecat-shared-data-access-v3.26.0) (2026-03-19) ### Features * add access control helpers for cross-org delegation (Option 2a) ([#1453](#1453)) ([960623e](960623e)), closes [adobe/spacecat-auth-service#503](https://github.com/adobe/spacecat-auth-service/issues/503) [#1448](#1448)
Member
|
🎉 This PR is included in version @adobe/spacecat-shared-data-access-v3.26.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
solaris007
pushed a commit
that referenced
this pull request
Mar 19, 2026
## [@adobe/spacecat-shared-http-utils-v1.24.0](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-http-utils-v1.23.0...@adobe/spacecat-shared-http-utils-v1.24.0) (2026-03-19) ### Features * add access control helpers for cross-org delegation (Option 2a) ([#1453](#1453)) ([960623e](960623e)), closes [adobe/spacecat-auth-service#503](https://github.com/adobe/spacecat-auth-service/issues/503) [#1448](#1448)
Member
|
🎉 This PR is included in version @adobe/spacecat-shared-http-utils-v1.24.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
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
Follow-on to #1448. Adds the spacecat-shared primitives required to implement the access-check
decision flow (Path A / Path B) and the delegated-site dropdown in the api-service.
AuthInfo.isDelegatedTenantsComplete()—spacecat-shared-http-utilsReturns
truewhen thedelegated_tenants_completeJWT claim is absent ortrue;falsewhenit is explicitly
false.hasAccess()in the api-service uses this to branch between two resolution paths:complete = true(≤ 20 grants, typical agency)delegated_tenantslist, deny with zero DB calls. DB only hit when JWT confirms a match (revocation check).complete = false(> 20 grants, e.g. internal sales)sourceOrganizationIdfromdelegated_tenants[0]and go DB-direct every request.Defaults to
truewhen the claim is absent — backward-compat with tokens minted before the claimwas added (all such tokens had ≤ 20 grants).
BaseCollection.createInstanceFromRow(row)—spacecat-shared-data-accessPublic wrapper around the existing private
#toModelRecord+#createInstancepipeline.Enables other collections to convert an embedded PostgREST sub-row (snake_case columns) into a
proper model instance, reusing the full field-mapping logic without duplication.
SiteImsOrgAccessCollectionadditions —spacecat-shared-data-accessfindBySiteIdAndOrganizationIdAndProductCode(siteId, organizationId, productCode)Thin public wrapper around
findByIndexKeys. Used byhasAccess()for the DB revocation check(Path A) and the DB-direct lookup (Path B).
allByOrganizationIdWithSites(organizationId)Single-round-trip PostgREST embedding query (
sites!site_ims_org_accesses_site_id_fkey(*)).Returns
{ grant: SiteImsOrgAccess, site: Site | null }pairs — both fields are proper modelinstances with getters. Used by the api-service
getSitesForOrganizationendpoint to mergedelegated sites into the org's site list with no N+1.
All embedding methods now return
SiteImsOrgAccessmodel instances forgrantPreviously
grantwas a plain camelCase object. NowallByOrganizationIdWithTargetOrganization,allByOrganizationIdsWithTargetOrganization, andallByOrganizationIdWithSitesall return aproper
SiteImsOrgAccessmodel instance asgrant. Callers useentry.grant.getOrganizationId(),entry.grant.getExpiresAt(), etc. — consistent getters everywhere.The now-unnecessary
static #toGrant(row)helper was removed.How these will be used in the api-service (next PR)
hasAccess()inaccess-control-util.js:getSitesForOrganizationinorganizations.js:Test plan
AuthInfo.isDelegatedTenantsComplete()— 5 unit testsSiteImsOrgAccessCollection— 33 unit tests (all embedding methods use getter assertions)Related
🤖 Generated with Claude Code