Nanopublication

< Home

ID

https://w3id.org/np/RAvPNGogj0GqBiBYBxqvympNd_RHXoxMHKs19bBymAelo

Formats

.trig | .trig.txt | .jelly | .jelly.txt | .jsonld | .jsonld.txt | .nq | .nq.txt | .xml | .xml.txt

Content

@prefix this: <https://w3id.org/np/RAvPNGogj0GqBiBYBxqvympNd_RHXoxMHKs19bBymAelo> .
@prefix sub: <https://w3id.org/np/RAvPNGogj0GqBiBYBxqvympNd_RHXoxMHKs19bBymAelo/> .
@prefix np: <http://www.nanopub.org/nschema#> .
@prefix grlc: <https://w3id.org/kpxl/grlc/> .
@prefix dct: <http://purl.org/dc/terms/> .
@prefix nt: <https://w3id.org/np/o/ntemplate/> .
@prefix npx: <http://purl.org/nanopub/x/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix orcid: <https://orcid.org/> .
@prefix prov: <http://www.w3.org/ns/prov#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .

sub:Head {
  this: a np:Nanopublication;
    np:hasAssertion sub:assertion;
    np:hasProvenance sub:provenance;
    np:hasPublicationInfo sub:pubinfo .
}

sub:assertion {
  sub:get-view-displays a grlc:grlc-query;
    dct:description "Returns the views to display for a given resource: both standalone view displays and the views contributed by assigned presets (issue #302), unioned and ordered by date so latest-wins override resolution holds across both. Filtered server-side to declarations signed by an admin or maintainer of the owning space, or by the affected user themselves (for an agent's own page). Each referenced view is resolved to its latest version by following the npx:supersedes chain: among the version tree's current heads (nanopubs that are themselves neither superseded nor validly retracted via npx:invalidates), the most recent is chosen, so ?view is the latest non-retracted view definition (no separate latest-version lookup needed by the client). Choosing a current head rather than the max-timestamp node makes resolution robust to backdated supersedes and to retracted versions. Preset-derived rows have an unbound ?display and carry the resolved ?view plus the assignment's activation mode. The view-version resolution is a bound lookup per referenced view. Space-governed versions (gen:governedBy, nanodash docs/views-and-presets-as-maintained-resources.md): a referenced version declaring gen:governedBy resolves to the newest version of its (kind, space) pair signed by a current member+ (admin/maintainer/member) of that space -- with the kind validated as a maintained resource of the space -- taking precedence over the supersedes-based head; without a valid governed candidate the pinned version stands. Federation footprint (2026-08-20): the query now runs on the repo/full endpoint, so the former SERVICE hops to repo/full (preset branch) and to the ResourceView type repo (view lookups, governed candidates) are plain local patterns; only the two lookups of materialized space state (authority gate, governed-signer validation) remain federated, to repo/spaces. The previous 5-SERVICE layout was the main amplifier of a connection-pool deadlock in the query service's loopback federation (an outer query holds a pooled connection while each SERVICE hop -- one per binding under a nested-loop join -- requests another from the same pool): a thread dump during a production wedge showed all 60 route connections held by result streamers of exactly these hops. Validated byte-for-byte identical to the previous version across resources covering standalone displays, preset assignments, governed views, an agent's own page, and rival space refs. Pending accounts (nanopub-query#195, nanodash#625): the self-signed arm additionally accepts npa:PendingAccountState rows -- mirrored by the query service from authoritative introductions of users who are not trust-approved yet -- so such a user's own page shows the view displays they signed themselves. The pending class is distinct from npa:AccountState, so no authority-granting join is widened: the admin/maintainer arm and the governed-version resolution keep requiring approved accounts. Preset-assignment identity (nanodash issue #607): rows contributed by a preset assignment now also carry ?presetKind, the assigned preset's stable kind (dct:isVersionOf, falling back to the version IRI), so the client can keep only the newest assignment per (preset kind, resource) -- the same identity view displays already have via view kind -- and views that a newer preset version no longer carries drop out with the older assignment. Purely additive: every pre-existing column is unchanged. Performance rewrite (2026-09-25; the query took 3.5-7s on a quiet instance and 502'd at the 60s cap under load, now ~0.3-0.5s, rows identical across 40 resources): (1) the authority gate is materialized once as a single row of the allowed key hashes (?authKeys) by a sub-select sharing no variable with the rest of the query, and checked with contains(?authKeys, ?pubkey) after the two branches -- joining the gate's ?pubkey rows directly made rdf4j start the display and preset lookups from the signing keys, i.e. walk every nanopub those keys ever signed; (2) the latest-version resolution, formerly a run-once sub-select over every ResourceView in the repository, is a bound lookup per referenced view, with same-key conditions compared by FILTER on separately bound key variables; (3) the governed winners of all (kind, space) pairs are computed once as a single '|kind>space>winner|' string and looked up per pin, instead of a winner sub-select (with its SERVICE) joined on ?pinKind/?pinSpace inside an OPTIONAL, which rdf4j re-ran per row.";
    dct:license <http://www.apache.org/licenses/LICENSE-2.0>;
    rdfs:label "Get view displays";
    grlc:endpoint <https://w3id.org/np/l/nanopub-query-1.1/repo/full>;
    grlc:sparql """prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix dct:  <http://purl.org/dc/terms/>
prefix np:   <http://www.nanopub.org/nschema#>
prefix npa:  <http://purl.org/nanopub/admin/>
prefix npx:  <http://purl.org/nanopub/x/>
prefix gen:  <https://w3id.org/kpxl/gen/terms/>

select distinct ?display ?view (coalesce(?viewKindOptional, ?view) as ?viewKind) ?presetKind
                ?label ?displayType ?displayMode ?np ?pubkey ?date where {
  values ?_resource_multi_iri {}
  # Governed winners of all (kind, space) pairs, computed once as a single row
  # (see the space-governed resolution below).
  {
    select (concat(\"|\", group_concat(concat(str(?wKind), \">\", str(?wSpace), \">\", str(?wLatest)); separator=\"|\"), \"|\") as ?govWinners) where {
      select ?wKind ?wSpace (iri(strafter(max(concat(str(?cDate), \">\", str(?cver))), \">\")) as ?wLatest) where {
        # Candidate versions. The sub-select wrapper is LOAD-BEARING, not stylistic: on
        # rdf4j 6.0.0, bindings produced by raw statement patterns are silently NOT joined
        # into a subsequent SERVICE clause (empirically: identical bindings via VALUES join
        # fine, via bare patterns yield zero rows, and any projecting sub-select restores
        # the join -- reproduced on two instances, 2026-08-20).
        { select ?wKind ?wSpace ?cver ?cpk ?cDate where {
          graph npa:graph {
            ?cnp dct:created ?cDate ; npa:hasValidSignatureForPublicKeyHash ?cpk ; npx:embeds ?cver ; np:hasAssertion ?ca .
            filter not exists { ?ci npx:invalidates ?cnp ; npa:hasValidSignatureForPublicKeyHash ?cpk . }
          }
          graph ?ca { ?cver dct:isVersionOf ?wKind ; gen:governedBy ?wSpace . }
        } }
        service <https://w3id.org/np/l/nanopub-query-1.1/repo/spaces> {
          graph npa:graph { <http://purl.org/nanopub/admin/thisRepo> npa:hasCurrentSpaceState ?gsg . }
          graph ?gsg {
            ?wKind npa:isMaintainedBy ?wSpace ; npa:hasGoverningSpaceRef ?gref .
            ?gri a gen:RoleInstantiation ; npa:forSpace ?wSpace ; npa:forSpaceRef ?gref ; npa:hasRoleType ?gtier ; npa:forAgent ?gag .
            filter(?gtier = gen:AdminRole || ?gtier = gen:MaintainerRole || ?gtier = gen:MemberRole)
            ?gacct a npa:AccountState ; npa:agent ?gag ; npa:pubkey ?cpk .
          }
        }
      } group by ?wKind ?wSpace
    }
  }
  # Authority gate, materialized ONCE as a single row (?authKeys: the space-separated
  # key hashes allowed to declare displays here) by a sub-select sharing no variable with
  # the rest of the query. Joining the gate's ?pubkey rows directly made rdf4j start the
  # display/preset lookups from the signing keys -- i.e. walk every nanopub those keys
  # ever signed (13k+ for knowledgepixels/nanodash) -- instead of from the few displays of
  # this resource. The keys are checked with contains() after the two branches instead.
  {
    select ?authKeys where {
      service <https://w3id.org/np/l/nanopub-query-1.1/repo/spaces> {
        select (group_concat(distinct ?pubkey; separator=\" \") as ?authKeys) where {
          values ?_resource_multi_iri {}
          graph npa:graph { npa:thisRepo npa:hasCurrentSpaceState ?stateG . }
          {
            # Authority gate (issue #130 / nanodash#510): a single mandatory hop through the
            # governing space ref, which covers both a maintained resource and a space itself
            # (the reflexive self-edge), keyed on the role tier materialized on the
            # RoleInstantiation since #125. Replaces the old bare-IRI isMaintainedBy? hop and the
            # dead RoleDeclaration maintainer join. Non-ref variant: any ref claiming the IRI, so
            # authority merges across refs (the ref variant pins a single ?passedRef instead).
            graph ?stateG {
              ?_resource_multi_iri npa:hasGoverningSpaceRef ?spaceRef .
              ?ri a gen:RoleInstantiation ; npa:forSpaceRef ?spaceRef ; npa:hasRoleType ?roleType ; npa:forAgent ?authAgent .
              filter(?roleType = gen:AdminRole || ?roleType = gen:MaintainerRole)
              ?authAcct a npa:AccountState ; npa:agent ?authAgent ; npa:pubkey ?pubkey .
            }
          } union {
            graph ?stateG { ?selfAcct a npa:AccountState ; npa:agent ?_resource_multi_iri ; npa:pubkey ?pubkey . }
          } union {
            # Own page of an agent who is introduced but not trust-approved yet
            # (nanopub-query#195, nanodash#625): npa:PendingAccountState rows are mirrored
            # from authoritative introductions and carry a distinct class so that no
            # authority join can resolve through them; this arm is display-only and scoped
            # to the page's own agent, exactly like the AccountState self-arm above.
            graph ?stateG { ?pendAcct a npa:PendingAccountState ; npa:agent ?_resource_multi_iri ; npa:pubkey ?pubkey . }
          }
        }
      }
    }
  }
  {
    # branch (a): standalone view displays — LOCAL pattern on the endpoint repo
    graph npa:graph {
      ?np npx:hasNanopubType gen:ViewDisplay .
      ?np npa:hasValidSignatureForPublicKeyHash ?pubkey .
      filter not exists { ?npx npx:invalidates ?np ; npa:hasValidSignatureForPublicKeyHash ?pubkey . }
      ?np dct:created ?date .
      ?np npx:embeds ?display .
      ?np np:hasAssertion ?a .
      optional { ?np rdfs:label ?label }
    }
    graph ?a {
      ?display gen:isDisplayOfView ?refView .
      ?display gen:isDisplayFor   ?_resource_multi_iri .
      optional { values ?displayType { gen:PartLevelViewDisplay gen:TopLevelViewDisplay } ?display a ?displayType . }
      optional { values ?displayMode { gen:ActivatedViewDisplay gen:DeactivatedViewDisplay } ?display a ?displayMode . }
    }
  }
  union
  {
    # branch (b): preset-supplied views — LOCAL since the endpoint moved to
    # repo/full (the connection-pinning SERVICE hop this replaced was the main
    # amplifier of the federation deadlock, eclipse-rdf4j/rdf4j federation +
    # nanopub-query loopback route). Kept wrapped in a sub-SELECT so its
    # bindings cannot collapse branch (a). ?display stays unbound.
    select ?refView ?label ?displayType ?displayMode ?np ?pubkey ?date ?_resource_multi_iri ?presetKind {
      {  # was: service repo/full — now local on the repo/full endpoint
        graph npa:graph {
          ?np npx:hasNanopubType gen:PresetAssignment .
          ?np npa:hasValidSignatureForPublicKeyHash ?pubkey .
          filter not exists { ?npx npx:invalidates ?np ; npa:hasValidSignatureForPublicKeyHash ?pubkey . }
          ?np dct:created ?date .
          ?np npx:embeds ?assignment .
          ?np np:hasAssertion ?a .
          optional { ?np rdfs:label ?label }
        }
        graph ?a {
          ?assignment gen:isAssignmentFor      ?_resource_multi_iri .
          ?assignment gen:isAssignmentOfPreset ?presetRef .
          optional { values ?displayMode { gen:ActivatedPresetAssignment gen:DeactivatedPresetAssignment } ?assignment a ?displayMode . }
        }
        graph npa:graph { ?presetNp npx:embeds ?presetRef ; np:hasAssertion ?pa . }
        graph ?pa {
          ?presetRef a gen:Preset .
          optional { ?presetRef dct:isVersionOf ?presetKindOptional . }
          { ?presetRef gen:hasTopLevelView ?refView . bind(gen:TopLevelViewDisplay as ?displayType) }
          union { ?presetRef gen:hasView ?refView . bind(gen:PartLevelViewDisplay as ?displayType) }
        }
        # A preset assignment is identified by the preset's stable KIND and the resource
        # (nanodash issue #607), so the client keeps only the newest assignment per kind
        # and an older version's views drop out when a newer version is assigned. A
        # version declaring no kind keys on itself.
        bind(coalesce(?presetKindOptional, ?presetRef) as ?presetKind)
      }
    }
  }
  filter(contains(?authKeys, ?pubkey))
  # Resolve each referenced view to its latest version: the current head of its
  # supersedes version tree (a nanopub itself neither superseded nor validly
  # retracted via npx:invalidates), most recent among heads on a fork. Bound point
  # lookups per ?refView: the former run-once sub-select resolved EVERY ResourceView
  # in the repository (linear in the repo-wide view count) before joining. Same-key
  # conditions compare separately bound key variables by FILTER, never through a
  # shared join variable, which would let rdf4j start from the signing key.
  optional {
    graph npa:graph { ?rnp npx:embeds ?refView ; np:hasAssertion ?ra . }
    graph ?ra { ?refView a gen:ResourceView . }
    optional { graph ?ra { ?refView dct:isVersionOf ?pinKind ; gen:governedBy ?pinSpace . } }
    optional {
      ?vnp npx:embeds ?refView .
      ?latestNp (npx:supersedes|^npx:supersedes)* ?vnp ; dct:created ?ldate ; npx:embeds ?latestView ; np:hasAssertion ?va ; npa:hasValidSignatureForPublicKeyHash ?invPk .
      filter not exists { ?supNp npx:supersedes ?latestNp . }
      filter not exists { ?invNp npx:invalidates ?latestNp ; npa:hasValidSignatureForPublicKeyHash ?invK . filter(str(?invK) = str(?invPk)) }
      filter not exists {
        ?other (npx:supersedes|^npx:supersedes)* ?vnp ; dct:created ?odate ; npa:hasValidSignatureForPublicKeyHash ?invPk2 .
        filter not exists { ?supNp2 npx:supersedes ?other . }
        filter not exists { ?invNp2 npx:invalidates ?other ; npa:hasValidSignatureForPublicKeyHash ?invK2 . filter(str(?invK2) = str(?invPk2)) }
        filter(?odate > ?ldate)
      }
      graph ?va { ?latestView a gen:ResourceView . optional { ?latestView dct:isVersionOf ?viewKindOptional . } }
    }
  }
  # Space-governed resolution (gen:governedBy; nanodash docs/views-and-presets-as-
  # maintained-resources.md): a pinned version declaring a governing space resolves to
  # the newest member+-signed version of its (kind, space) pair instead of the
  # supersedes head; no valid candidate -> the pin stands. The winners of ALL governed
  # (kind, space) pairs are computed once, as a single \"|kind>space>winner|...\" string
  # (?govWinners, top of the query), and looked up per pin by string: the former winner
  # sub-select joined on ?pinKind/?pinSpace inside an OPTIONAL was re-run -- SERVICE
  # included -- once per row. '>' and '|' cannot occur in IRIs.
  # The winner lookup is inlined into coalesce(): on rdf4j, a variable whose BIND
  # expression failed (iri(\"\") when there is no winner) tests as unbound with bound(),
  # yet coalesce() over it still yields nothing instead of falling through.
  bind(if(bound(?pinSpace),
          coalesce(iri(strbefore(strafter(?govWinners, concat(\"|\", str(?pinKind), \">\", str(?pinSpace), \">\")), \"|\")), ?refView),
          coalesce(?latestView, ?refView)) as ?view)
}
order by desc(?date)""" .
}

sub:provenance {
  sub:assertion prov:wasAttributedTo orcid:0000-0002-1267-0234 .
}

sub:pubinfo {
  orcid:0000-0002-1267-0234 foaf:name "Tobias Kuhn" .
  
  this: dct:created "2026-09-25T08:25:01Z"^^xsd:dateTime;
    dct:creator orcid:0000-0002-1267-0234;
    dct:license <https://creativecommons.org/licenses/by/4.0/>;
    npx:embeds sub:get-view-displays;
    npx:supersedes <https://w3id.org/np/RAwkiytrR_PaBVqUjfUtoTEBAVwNWq7QxHJbAshQ1dD9g>;
    rdfs:label "Get view displays";
    nt:wasCreatedFromProvenanceTemplate <https://w3id.org/np/RA7lSq6MuK_TIC6JMSHvLtee3lpLoZDOqLJCLXevnrPoU>;
    nt:wasCreatedFromPubinfoTemplate <https://w3id.org/np/RA0J4vUn_dekg-U1kK3AOEt02p9mT2WO03uGxLDec1jLw>,
      <https://w3id.org/np/RAoTD7udB2KtUuOuAe74tJi1t3VzK0DyWS7rYVAq1GRvw>, <https://w3id.org/np/RAukAcWHRDlkqxk7H2XNSegc1WnHI569INvNr-xdptDGI>;
    nt:wasCreatedFromTemplate <https://w3id.org/np/RAEFAt-QcFK0ZhqfvlsmS10BnzGJA0xwOICZXkO-ai87k> .
  
  sub:sig npx:hasAlgorithm "RSA";
    npx:hasPublicKey "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwUtewGCpT5vIfXYE1bmf/Uqu1ojqnWdYxv+ySO80ul8Gu7m8KoyPAwuvaPj0lvPtHrg000qMmkxzKhYknEjq8v7EerxZNYp5B3/3+5ZpuWOYAs78UnQVjbHSmDdmryr4D4VvvNIiUmd0yxci47dTFUj4DvfHnGd6hVe5+goqdcwIDAQAB";
    npx:hasSignature "RbshpCZL8fXw6sjDdOrN38WkKsucvVFRWC/0Hy7b+1/rmwRAIY9FXc9wB1kdX2tvjakhH1s+n1qEzr6j3tFUubkZQM+wO5ByIPIaE0mqCV7MeUG9t0z9RLYvehk34WysVXW5wmRILP8X0W2BWRlHpWt+nLy1N6FrROQWNKCAZ30=";
    npx:hasSignatureTarget this:;
    npx:signedBy orcid:0000-0002-1267-0234 .
}