SoushAI analysis. Drafted by Soushi's AI assistant, reviewed and posted by @Soushi888.
What happens
ResourceSpecification.scope is mutable and decides one thing: whether the spec is linked from the resource_specifications anchor that get_all_resource_specifications reads. create_resource_specification honours that at creation. update_resource_specification accepts a new scope, writes it into the updated entry, and never touches the anchor.
Both directions are wrong, in opposite ways:
Project → Public: the author widens the scope and the spec stays absent from global discovery. It is public in the entry and invisible in the list.
Public → Project: the author narrows the scope and the spec stays listed globally. The narrowing has no effect on the only thing scope controls.
// dnas/nondominium/zomes/coordinator/zome_resource/src/resource_specification.rs
let updated_spec = ResourceSpecification { /* … */ scope: input.updated_specification.scope, /* … */ };
let updated_spec_hash = update_entry(input.previous_action_hash, &updated_spec)?;
create_link(input.original_action_hash, updated_spec_hash.clone(), LinkTypes::ResourceSpecificationUpdates, ())?;
// no AllResourceSpecifications create_link / delete_link anywhere in this function
What this does not affect
Not a capture-resistance hole. Nondominium and Public regimes are pinned to Public scope by check_scope_coherence, enforced on create and update in zome_resource integrity (PR #132, f57ef43), so a spec on an uncapturable NDO cannot be narrowed out of discovery by this path. The bug bites the regimes where scope is genuinely the author's choice.
Second-order: the anchor read is stale anyway
While fixing this, get_all_resource_specifications deserves a look. It resolves each anchor link to the original action hash and calls get() on it, which returns the original record, not the head of the update chain. So the global list renders pre-update content for every spec that has ever been edited, independently of scope. get_specifications_for_ndo has the same shape. get_latest_resource_specification exists and walks ResourceSpecificationUpdates; the list paths do not use it.
Fix
In update_resource_specification, compare original_spec.scope against the incoming scope and reconcile:
- narrowing to
Project: delete_link the AllResourceSpecifications link
- widening from
Project: create_link it
Then decide whether the two list functions should resolve the latest record rather than the original. That is the larger of the two and can be split.
Accepts on
A Sweettest that creates a Project-scoped spec on a Commons NDO, confirms it is absent from get_all_resource_specifications, updates it to Public, and confirms it appears; plus the reverse. Both halves must be red before the fix.
Provenance
Found reviewing #132 (R4). Not introduced by that PR: scope is new there, so the field and the defect arrive together, but the reconciliation was never written rather than removed.
What happens
ResourceSpecification.scopeis mutable and decides one thing: whether the spec is linked from theresource_specificationsanchor thatget_all_resource_specificationsreads.create_resource_specificationhonours that at creation.update_resource_specificationaccepts a newscope, writes it into the updated entry, and never touches the anchor.Both directions are wrong, in opposite ways:
Project→Public: the author widens the scope and the spec stays absent from global discovery. It is public in the entry and invisible in the list.Public→Project: the author narrows the scope and the spec stays listed globally. The narrowing has no effect on the only thing scope controls.What this does not affect
Not a capture-resistance hole.
NondominiumandPublicregimes are pinned toPublicscope bycheck_scope_coherence, enforced on create and update inzome_resourceintegrity (PR #132,f57ef43), so a spec on an uncapturable NDO cannot be narrowed out of discovery by this path. The bug bites the regimes where scope is genuinely the author's choice.Second-order: the anchor read is stale anyway
While fixing this,
get_all_resource_specificationsdeserves a look. It resolves each anchor link to the original action hash and callsget()on it, which returns the original record, not the head of the update chain. So the global list renders pre-update content for every spec that has ever been edited, independently of scope.get_specifications_for_ndohas the same shape.get_latest_resource_specificationexists and walksResourceSpecificationUpdates; the list paths do not use it.Fix
In
update_resource_specification, compareoriginal_spec.scopeagainst the incoming scope and reconcile:Project:delete_linktheAllResourceSpecificationslinkProject:create_linkitThen decide whether the two list functions should resolve the latest record rather than the original. That is the larger of the two and can be split.
Accepts on
A Sweettest that creates a
Project-scoped spec on aCommonsNDO, confirms it is absent fromget_all_resource_specifications, updates it toPublic, and confirms it appears; plus the reverse. Both halves must be red before the fix.Provenance
Found reviewing #132 (R4). Not introduced by that PR:
scopeis new there, so the field and the defect arrive together, but the reconciliation was never written rather than removed.