Skip to content

Migration workflow: add research types to CERN_SCIENTIFIC_COMMUNITY #542

Description

@kpsherva

When migrating public (only public) research records (meaning resource type preprint, article etc - please align on the full list of resource types) we need to include them automatically in CERN_SCIENTIFIC_COMMUNITY (in config) - CERN Research community to ensure the curation rights are given to SIS team.
Implement this as part of global workflow (for all collections, this should be based on resource type)

Activity

  1. moved this from In progress to In review 🔍 in Sprint Q4 2026 ☀️on Jun 26, 2026
  2. removed their assignment
    on Jun 29, 2026
  3. moved this from In review 🔍 to In progress in Sprint Q4 2026 ☀️on Jul 2, 2026
  4. moved this from In progress to In review 🔍 in Sprint Q4 2026 ☀️on Jul 2, 2026
  5. removed their assignment
    on Jul 2, 2026
  6. moved this from In review 🔍 to In progress in Sprint Q4 2026 ☀️on Jul 3, 2026
  7. moved this from In progress to Ready in Sprint Q4 2026 ☀️on Jul 6, 2026
  8. removed their assignment
    on Jul 30, 2026
  9. moved this from Ready to In review 🔍 in Sprint Q4 2026 ☀️on Jul 30, 2026
  10. moved this from In review 🔍 to In progress in Sprint Q4 2026 ☀️on Jul 31, 2026
  11. 8 remaining items

  12. moved this from In progress to In review 🔍 in Sprint Q4 2026 ☀️on Aug 5, 2026
  13. removed their assignment
    on Aug 5, 2026
  14. moved this from In review 🔍 to In progress in Sprint Q4 2026 ☀️on Aug 31, 2026
  15. zzacharo commented on Sep 1, 2026

    @zzacharo
    Contributor

    Context

    Analyze what it would need to override on CDS the permission so that each record submission or inclusion request can be read only from the community that was the receiver of the request even though the record could belong to multiple ones i.e one community cannot see the requests of another one if a record belongs to both.

    Claude plan to be heavily reviewed

    Plan: Restrict Community Request Visibility to Receiver Community

    Problem

    When a record belongs to multiple communities, curators of all those communities
    can read each other's community inclusion/submission requests for that record.

    Root cause trace

    1. RequestPermissionPolicy.can_read includes Topic() for submitted/accepted/etc. requests.
    2. Topic.needs() calls request.type.entity_needs(entity) when resolve_topic_needs = True.
    3. Both CommunityInclusion and CommunitySubmission have resolve_topic_needs = True.
    4. entity_needs() calls entity.get_needs(ctx=needs_context) on the record entity.
    5. The record entity resolver evaluates can_preview from CDSRDMRecordPermissionPolicy:
      can_preview → can_curate → can_manage → RecordCommunitiesAction("curate")
      
    6. RecordCommunitiesAction("curate") emits CommunityRoleNeed(community_id, role) for
      every community the record already belongs to — not just the receiver community.

    The Receiver() generator in can_read already grants the correct target community access.
    The receiver is not the problem. The leak is RecordCommunitiesAction("curate") firing for
    unrelated communities via Topic().

    Note: community_roles in needs_context is only consumed by community entity resolvers
    (subcommunity requests), not by the record entity resolver — so it's irrelevant here.


    What we want

    Who Should see request?
    Record owner ✅ yes
    Explicit collaborators (AccessGrant, SecretLinks) ✅ yes
    Target community curators (the receiver) ✅ yes
    Committee referees (CommitteeRefereeVersionGrant) ✅ yes
    Curators of OTHER communities the record is in ❌ no

    Solution: narrow record_permission used for topic resolution

    Keep resolve_topic_needs = True (we still want explicit collaborators to have access).
    Add a custom permission action can_preview_requests that is identical to can_preview
    but without RecordCommunitiesAction("curate").


    Step 1 — Add can_preview_requests to CDSRDMRecordPermissionPolicy

    File: site/cds_rdm/permissions.py

    Add to imports:

    from invenio_rdm_records.services.generators import (
        AccessGrant,
        RecordOwners,
        RequestReviewers,
        SecretLinks,
        SubmissionReviewer,
    )

    Add to CDSRDMRecordPermissionPolicy:

    # Like can_preview but without RecordCommunitiesAction("curate").
    # Used as the topic-resolution permission for community inclusion/submission
    # requests so that explicit record collaborators can see the request,
    # but curators of unrelated communities cannot.
    can_preview_requests = [
        RecordOwners(),
        AccessGrant("manage"),
        AccessGrant("edit"),
        SecretLinks("edit"),
        AccessGrant("preview"),
        SecretLinks("preview"),
        SubmissionReviewer(),           # current review's receiver community (safe: returns [] for inclusion requests)
        RequestReviewers(),             # assigned request reviewers (gated on REQUESTS_REVIEWERS_ENABLED)
        UserManager,
        SystemProcess(),
        CommitteeRefereeVersionGrant(), # CDS-specific: committee referees
    ]

    Step 2 — CDS request-type subclasses

    File: site/cds_rdm/requests/community_requests.py (new file)

    from invenio_rdm_records.checks import requests as checks_requests
    
    
    class CDSCommunityInclusion(checks_requests.CommunityInclusion):
        """CommunityInclusion with narrowed topic-resolution permission.
    
        Prevents curators of unrelated communities from reading inclusion
        requests for records they happen to share a community with.
        """
        needs_context = {
            "community_roles": ["owner", "manager", "curator"],  # for community topics (unused here)
            "record_permission": "preview_requests",             # replaces "preview"
        }
    
    
    class CDSCommunitySubmission(checks_requests.CommunitySubmission):
        """CommunitySubmission with narrowed topic-resolution permission."""
        needs_context = {
            "community_roles": ["owner", "manager", "curator"],
            "record_permission": "preview_requests",
        }

    Export from site/cds_rdm/requests/__init__.py if needed.


    Step 3 — Wire up in invenio.cfg

    Replace the existing two lines:

    # Before:
    RDM_COMMUNITY_SUBMISSION_REQUEST_CLS = checks_requests.CommunitySubmission
    RDM_COMMUNITY_INCLUSION_REQUEST_CLS  = checks_requests.CommunityInclusion
    
    # After:
    from cds_rdm.requests.community_requests import (
        CDSCommunityInclusion,
        CDSCommunitySubmission,
    )
    RDM_COMMUNITY_SUBMISSION_REQUEST_CLS = CDSCommunitySubmission
    RDM_COMMUNITY_INCLUSION_REQUEST_CLS  = CDSCommunityInclusion

    Files changed

    File Change
    site/cds_rdm/permissions.py Add can_preview_requests to CDSRDMRecordPermissionPolicy
    site/cds_rdm/requests/community_requests.py New file: two subclasses
    invenio.cfg Swap config vars to CDS subclasses

    No changes needed to CDSRequestsPermissionPolicy, can_read, or guest_token.


    Why SubmissionReviewer() is safe in can_preview_requests

    SubmissionReviewer.needs() reads record.parent.review — the active review request on the record:

    • For inclusion requests: the record is published, review is None → returns [].
    • For submission requests: review points to the submission request whose receiver is
      the target community — the same community already covered by Receiver().

    So it adds no unintended access.

  16. moved this from In progress to Ready in Sprint Q4 2026 ☀️on Sep 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions