Repository navigation
[pending DataSpaceBackend#224] Add API coverage for external contributors privacy mask - #197
Draft
saqibmanan wants to merge 1 commit into
Draft
saqibmanan wants to merge 1 commit into
saqibmanan wants to merge 1 commit into
Conversation
Covers the new externalContributors GraphQL field on TypeUseCase and TypeCollaborative (DataSpaceBackend PR #224, open on dev). Querying the field today fails with GraphQL's "Cannot query field" error, which is the proof that the feature is not live yet. Gated with pending_pr so it skips in CI until the source PR merges.
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.
Pending: covers open CivicDataLab/DataSpaceBackend#224 (head
98581547). Skipped in CI until it merges. Safe to merge before it.Source PR
CivicDataLab/DataSpaceBackend#224 — "Create external user for collaborative, publications, use-cases"
dev, open, created 2026-10-06 (>72h old, no coverage yet)headRefOid:985815476a819bae1b066a32896769130ed8a849What actually changed (from the diff, not the title)
ExternalContributormodel (name, email, image, designation, bio, has_approved,timestamps), wired as an M2M onto
Publication,UseCaseandCollaborative.TypeExternalContributorenforces a privacy mask: every field exceptid/hasApproved/createdAt/updatedAtresolves to a safe default whenhas_approvedisFalse—name()→"Anonymous",email()/image()/designation()/bio()→None.externalContributorslist field added toTypeCollaborative,TypeUseCaseandTypePublication, with no permission class — exposed through the same public,unauthenticated queries as the existing
contributorsfield.Collaborative.organizationis removed, replaced by a plaindesignation: strfield, and
is_individual_collaborativeis hardcoded to always returnTrue(previously
self.organization is None). This is a real behaviour change (everyexisting collaborative that had an org now reads as "individual") but is secondary to
the ExternalContributor feature — see "Caveats" below, not covered by new tests here.
Confirmed directly against the PR diff in
DataSpaceBackend(api/types/type_external_contributor.py,api/types/type_collaborative.py,api/types/type_usecase.py,api/types/type_publication.py),not from the PR title/description.
Category chosen:
api+smokeThis is a pure GraphQL schema/resolver change with no UI surface, so
apiis the rightcategory.
smokeis required in addition toapi/pending_prso CI'spull_requestmarker filter (
-m "smoke", fromrun-smoke.yml) actually selects it — anapi-only/regression-only test here would be silently deselected on every event(this repo has no
regression-gated job that ever runs; see SKILL.md §5).regressionwas deliberately not used for the same reason.
Test added
tests/api/smoke/test_api_025_external_contributors.py— two unauthenticated GraphQLtests (
test_usecases_external_contributors_field_does_not_exist_yet,test_collaboratives_external_contributors_field_does_not_exist_yet), reusing theexisting
anon_graphql_clientfixture fromtests/api/conftest.py(no new fixtures orPage Objects needed — there is no UI layer to this test). Each sends
{ useCases(pagination:{limit:1}) { id title externalContributors { id hasApproved name email designation bio } } }(and thecollaborativesequivalent) and asserts theresponse is GraphQL's
"Cannot query field 'externalContributors'"error withdata: null— not just "any error".Both tests carry
pytest.mark.pending_pr("DataSpaceBackend#224")(new file, so set viapytestmark), plusapiandsmoke.Red proof (today's dev schema doesn't have the field)
Captured directly with curl against
https://dev.api.civicdataspace.in/api/graphql:And the actual pytest run against dev, with the
pending_prmarker temporarily removed(
API_BASE_URL=https://dev.api.civicdataspace.in):These "PASSED" because the assertion is "today's schema rejects this field" — that
rejection is the red proof that DataSpaceBackend#224 hasn't landed on dev yet. To check
the assertion is not vacuous, I inverted it locally (asserted
data is not None,i.e. the post-merge expectation) and reran the same test against dev — it failed as
expected:
(That inversion was local-only, reverted before committing — never part of the shipped file.)
Collection + skip-gating proof
Collected (both files, both events' marker filters):
Skip-gating round-trip, with the
pending_prmarker present (as shipped), against dev:Exact reason string matches
_pending_pr_state()inconftest.py(
f"pending_pr {ref}: not merged yet").UNVERIFIED — green behaviour not executed anywhere
UNVERIFIED: PR not deployed anywhere — once DataSpaceBackend#224 is on dev, re-run this
file; the query should then succeed and (a) an unapproved contributor's name must read
"Anonymous" with email/designation/bio/image all null, (b) an approved one must show its
real values. DataSpaceBackend cannot be served in this sandbox (no Postgres, Redis or
Keycloak available), so the privacy-mask logic itself (the actual point of
TypeExternalContributor) has not been exercised against running code — only theschema-absence red proof above has. This test deliberately does not assert the green
behaviour; it only proves today's gap. A human (or a future CI run once #224 merges)
should rewrite/extend it to cover (a) and (b) once real
ExternalContributorrecordswith both
hasApprovedstates exist on dev.Caveats / out of scope
Collaborative.organization→designation+is_individual_collaborativealwaysTrue: this PR also removes theorganizationfield fromTypeCollaborativeandhardcodes
is_individual_collaborativetoTrueregardless of whether thecollaborative actually has an organization. That's a real behaviour change (existing
org-backed collaboratives now read as "individual") but is secondary to the
ExternalContributor feature and is not covered by new tests here — flagging it as
a gap rather than guessing at the intended semantics.
readonly— per SKILL.md §9, a pending test is never markedreadonlysince the prod-deploy gate runs
readonlytests and this would fail every prod deployuntil #224 actually ships to prod. No follow-up needed unless/until a
readonlyvariant is wanted after the feature is live everywhere.
GraphQL check with no UI surface.
test_api_025_*— confirmed free onorigin/CI(
git ls-tree origin/CI --name-only tests/api/smoke/had 001–024 and 027, nothing at025/026).
Housekeeping
test-sync/DataSpaceBackend-pr224, based onorigin/CI(confirmed via recentmerged test PRs that
CI, notmain/dev, is where this repo's test work lands andwhere its workflows run).
existing
test-sync/DataSpaceBackend-pr224branch, no PR mentioningDataSpaceBackend#224.