Skip to content

scientific(membership): reject zero-share active affiliations #613

Description

@seonghobae

Scientific/domain finding

MembershipWeight on #605 currently accepts finite [0,1], including +0.0 and -0.0. That is inconsistent with the canonical active-membership meaning and with TEPP's existing persistence boundary: MembershipAssignmentRecord::validate already rejects membership_weight <= 0.0, and migration 0006_typed_membership_assignment has CHECK (membership_weight > 0).

A zero-share edge therefore has no affiliation mass but can still enter MembershipNetwork, contribute an active group/role edge, alter classify_membership_design, and affect nested-ICC applicability. This is structural contamination, not an estimator tolerance question.

Required RED

On #605 or its verified successor:

  • MembershipWeight::new(+0.0) and MembershipWeight::new(-0.0) must return InvalidMembershipWeight;
  • transparent serde must reject zero as well;
  • the minimum positive binary64 subnormal (f64::from_bits(1)) remains valid so the repair does not invent an epsilon threshold;
  • 1.0 remains valid and existing finite >1, negative, NaN, and infinity refusals remain intact.

Repair boundary

Change the owner VO domain from [0,1] to (0,1]. Do not clamp, renormalize, use a tolerance, or reinterpret zero as missing data. #612 exact dyadic share-budget arithmetic remains separate and may still represent arithmetic zero internally; persisted/public MembershipWeight must remain strictly positive.

Persistence follow-up

Zero is already refused by both the Rust persistence record validator and PostgreSQL 0006. A separate persistence-owner gap remains for the upper bound: MembershipAssignmentRecord::validate and the database currently accept weights above one even though membership_core rejects them. Repair that through the active persistence lineage without rewriting historical migration 0006 or colliding with #287's reserved 0008_analysis_run_persistence migration.

Acceptance

  • public RED before production repair;
  • minimal (0,1] owner fix with unit/serde edge coverage;
  • exact-head Rust/rustdoc/test/coverage/security/CodeQL/Semgrep evidence and qualifying independent review before feat(membership): add owner-issued single-membership admission #605 lands;
  • keep this issue open through protected-main landing; source repair on a mutable Draft is not completion.

Activity

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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions