feat(spaces): materialize uniform ref-valued hasGoverningSpaceRef edge (#130)#132
Merged
Conversation
#130) Consumer authority gates (view-displays, preset/role assignments) all re-derive resource→space(ref)→RoleInstantiation→tier in federated SPARQL. Copy-pasted across queries, that policy produced the cross-ref bleed and dead-maintainer-arm bugs in nanodash#510. Move it into the materializer once. Emit a uniform ref-valued npa:hasGoverningSpaceRef edge in each per-ref state graph: - Reflexive: <spaceIRI> hasGoverningSpaceRef <its own SpaceRef>, via the new self-healing governingSpaceRefReflexiveUpdate pass (no source nanopub, no load filter; a SpaceRef disappearing is itself a rebuild event). This removes the zero-hop special case — consumers no longer need isMaintainedBy? with a bare-IRI zero-length path for "resource is a space". - Maintained: <resourceIRI> hasGoverningSpaceRef <maintaining space's ref>, emitted inside maintainedResourceAdmitUpdate (so it is covered by the existing MaintainedResourceLink reification) pointing at the ref whose admin authorized the declaration. Ref-valued, so no bare-IRI join survives and cross-ref bleed is gone. The maintained arm is orphan-swept on invalidation by maintainedResourceConvenienceEdgeCleanup (issue #125 #5 machinery), extended with a guard (?o spaceIri ?r) that keeps the reflexive self-edge — which is self-healing and has no nanopub to invalidate. Consumers can then collapse the gate to a single mandatory hop keyed on npa:hasRoleType (materialized since #125): see proposed queries in #130 / nanodash#510. Wired into runAllTierLoops + the late-arrival sweep + counters/logging. Tests: new AuthorityResolverGoverningSpaceRefTest (reflexive per-ref emission, ref-valued maintained edge isolated to the authorizing ref, the simplified gate resolving a space and a maintained resource but not a rival ref, and sweep-on-invalidation keeping the reflexive edge) plus string-contract tests in AuthorityResolverTest. Full suite green. Requires a full re-ingest on deploy to backfill the edges onto existing rows. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
🎉 This PR is included in version 1.18.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.
Implements #130.
What
Materializes a uniform ref-valued
npa:hasGoverningSpaceRefedge in each per-ref state graph, so consumer authority gates do one mandatory hop (resource → governing space ref → RoleInstantiation) whether the subject is a space or a maintained resource — instead of re-deriving the hop, the bare-IRI match, and the broken declaration join in every published query.<spaceIRI> npa:hasGoverningSpaceRef <its own SpaceRef>, via a new self-healinggoverningSpaceRefReflexiveUpdatepass (no source nanopub, no load filter; dedup on the edge). Removes the zero-hop special case (isMaintainedBy?zero-length path) that breaks once the hop is ref-valued — a space has no self ref-edge today.<resourceIRI> npa:hasGoverningSpaceRef <maintaining space's ref>, emitted insidemaintainedResourceAdmitUpdatepointing at the ref whose admin authorized the declaration. Ref-valued ⇒ no bare-IRI join ⇒ cross-ref bleed gone.Invalidation
The maintained arm rides the #125 finding-#5 machinery: it's emitted under the existing
MaintainedResourceLinkreification and orphan-swept bymaintainedResourceConvenienceEdgeCleanup, extended with a guard (?o npa:spaceIri ?r) that keeps the reflexive self-edge — which is self-healing and has no nanopub to invalidate.Consumer side
Queries collapse to the simplified gate (keyed on
npa:hasRoleType, materialized since #125):That's the repoint for nanodash#510 (view-displays + preset/role assignments).
Tests
AuthorityResolverGoverningSpaceRefTest(behavioral): reflexive per-ref emission; ref-valued maintained edge isolated to the authorizing ref (no bleed to a rival ref claiming the same IRI); the simplified gate resolving a space and a maintained resource but not a rival ref; maintained governing edge swept on invalidation while the reflexive self-edge is kept.AuthorityResolverTest.Deploy
Requires a full re-ingest to backfill
hasGoverningSpaceRefonto existing rows (rides the same re-ingest as #125 / #131).Rollout order
Materializer (this PR) → re-ingest → consumer supersede per affected query (nanodash#510).
🤖 Generated with Claude Code