Skip to content

MEMBERS-IDENTITY-001A — Define provider-neutral membership authority and entitlement contract #208

Closed

Description

@daliu

Officer impact: None yet. This child defines and tests an unused membership-authority contract. It does not change signup, dues, discounts, account access, officer screens, or any live member record.

Officer documentation: Update only the membership-authority future-state section in docs/officers/EVENTS_SHOP_MEMBERS.md, including a matching Mermaid diagram and text alternative. Current officer procedures must remain NOT AVAILABLE YET.

Deployment evidence: None at issue creation. Closure must report source, tests, merge, website, runmprc.com, Firebase, provider configuration, production data, migration, and live behavior separately. A green workflow proves no external surface is live.

Problem

The current website has Firebase accounts and role claims, but no provider-neutral contract separating a stable MPRC membership from the account used to sign in. A membership may exist before a website account, and annual access must eventually follow approved membership-term evidence. Google, WhatsApp, Strava, an email match, or a browser role must never become membership authority.

Downstream #82, #83, #109, and #114–#117 need one fail-closed contract, but owner decisions in #110/#113/#114 still block data fields, retention, legacy disposition, pricing, grace, plan eligibility, refunds/disputes, and production adoption.

Atomic outcome

Add one unused CommonJS pure module and focused tests that define a versioned provider-neutral membership-authority snapshot, deterministic technical transitions, and a fixed fail-closed entitlement projection.

The contract may represent:

  • one stable opaque membership ID independent of Firebase UID;
  • an optional explicit UID association with revision and an immediate last-command marker;
  • one versioned current-term reference with explicit start/end boundaries and opaque plan/evidence references;
  • explicit decision_pending states for unresolved owner policy; and
  • a non-identifying entitlement result that is never active when required state is missing, malformed, conflicting, out of order, expired, suspended, or pending.

It does not decide whether an underlying payment, plan, person, household, refund, dispute, or legacy row is valid. A future trusted runtime must establish those facts.

flowchart LR
    M["Stable MPRC membership ID"] --> A{"Explicit UID association?"}
    A -- "No or conflict" --> D["No website entitlement"]
    A -- "Yes" --> T{"Versioned term and evidence references complete?"}
    T -- "No or decision pending" --> D
    T -- "Yes" --> P{"Approved policy inputs and explicit time bounds admit access?"}
    P -- "No" --> D
    P -- "Yes" --> E["Fixed current-member entitlement result"]
    G["Google / WhatsApp / Strava / email"] -. "projection only; never authority" .-> D
Loading

Text alternative: a stable membership record receives website access only after an explicit UID association and a complete, policy-approved term reference. Missing, conflicting, expired, suspended, or undecided state denies entitlement. External identities and channels never grant membership.

Invariants

  • The module is pure, deterministic, unused, CommonJS, and has no Firebase, Firestore, Auth, Stripe, provider, clock, environment, network, logger, random, filesystem, or Functions-index import.
  • Account identity and membership identity remain separate. No same-email, provider, phone, role, or client field creates an association.
  • Membership IDs, command IDs, term IDs, plan references, and evidence references are bounded opaque values. No names, emails, phones, addresses, DOB, emergency contacts, provider IDs/tokens, payment IDs/details, URLs, free text, or roster data are accepted, returned, or logged.
  • A record can remain valid without a UID. Such a record cannot produce website entitlement.
  • UID association is explicit and revision-bound within one snapshot. Exact latest-command retry is read-only/deterministic; a changed latest retry or a correct-revision second/different UID association on the same membership fails closed. Durable UID uniqueness across membership records remains future trusted-runtime work.
  • Term boundaries are explicit and half-open; the module does not choose calendar-year versus anniversary policy. Missing, invalid, reversed, expired, future-only, suspended, or decision_pending terms do not grant entitlement.
  • Plan and evidence references are opaque. The module does not verify payment, choose prices/plans, or interpret refund/dispute policy.
  • Outputs are fixed and non-identifying. Invalid/hostile input exposes one generic boundary and no partial values.
  • No unbounded mutable audit/history array is introduced. Runtime persistence and append-only audit are future work.
  • No schema, Rules, custom claim, role, profile, migration, endpoint, UI route, provider configuration, deployment, or production record changes.
  • Existing AUTH-001B — Require verified email for role-based Firestore access #196 verified-email and DATA-001C2 — Stop profile setup from copying Firebase Auth phone numbers #197 phone-minimization behavior remains unchanged.

Required tests

  • Valid account-independent record with no UID remains valid but ineligible for website access.
  • Explicit association plus a complete currently admitted term yields only the fixed entitled result.
  • Exact latest-command retry is deterministic; a changed latest command, wrong expected revision, unchanged older-command replay, stale/reordered command, and correct-revision second/different UID association on the same membership fail closed. Reuse of an older raw command ID after an intervening command and UID uniqueness across separate membership records require the future durable journal/index.
  • Missing/malformed identifiers, extra keys, accessors/proxies, unsupported versions/enums, invalid times, reversed bounds, boundary instants, future, expired, suspended, and pending decisions deny or return the generic invalid boundary as specified.
  • Provider/email/phone/role/payment/PII fields are rejected.
  • Inputs are not mutated; returned records/results are frozen or otherwise protected from caller mutation.
  • Source scans prove no runtime/index import, external SDK, logger, environment, network, timestamp generation, random value, provider field, or deployment edge.
  • Focused tests, full Functions tests/lint, Firestore Rules, frontend/SPA/build, workflow/artifact safety, and diff checks pass using Node 20 and Java 17 where applicable.

Exact owned paths

  1. New functions/membershipAuthority.js
  2. New functions/membershipAuthority.test.js
  3. Only the named membership-authority section and diagram in SYSTEM_DESIGN.md
  4. Only the matching membership-authority future-state section and diagram in docs/officers/EVENTS_SHOP_MEMBERS.md

Dependencies and coordination

Owner-dependent decisions deliberately deferred

Explicitly out of scope

Do not edit commerce-command/C3A–C3C sections, STRIPE_COMMERCE_DESIGN.md, SECURITY.md, IMPLEMENTATION_PLAN.md, GITHUB_ISSUES.md, GITHUB_ISSUE_SLICES.md, Rules, Auth/profile/signup code, Functions index/endpoints, packages/workflows, or any provider/deployment configuration.

Do not use real members, accounts, payments, providers, or production data.

Claim protocol

Creation is not a claim. Before any file edit, assign the issue, post CLAIMED by <canonical agent> at <UTC>; branch <branch>; exact base <SHA>, re-read live comments, and move status:ready to status:in-progress. Earliest valid claim wins.

Activity

  1. added
    priority:P0Launch blocker or urgent security risk
    type:securitySecurity or privacy boundary
    area:membershipMembership lifecycle and reconciliation
    area:authAuthentication and authorization
    area:firebaseFirebase services and data
    size:SSmall focused issue
    status:readyDependencies complete and ready to claim
    type:testingTest infrastructure and quality gates
    status:in-progressClaimed and actively being implemented
    and removed
    status:readyDependencies complete and ready to claim
    on Jul 14, 2026
  2. self-assigned this
    on Jul 14, 2026
  3. daliu commented on Jul 14, 2026

    @daliu
    ContributorAuthor

    CLAIMED by /root at 2026-07-14T03:22:49Z; branch codex/issue-208-membership-authority; exact base 1730977eca65dc7df59bb7f195bbc44afd7e5895.

    Exact ownership:

    • new functions/membershipAuthority.js
    • new functions/membershipAuthority.test.js
    • only the named membership-authority section/diagram in SYSTEM_DESIGN.md
    • only the matching future-state membership-authority section/diagram in docs/officers/EVENTS_SHOP_MEMBERS.md

    The active PAY-002B2C3C task owns only its commerce-command C3C hunk in SYSTEM_DESIGN.md and will preserve this membership hunk. I will preserve its hunk. All commerce journal/reconciliation files, C3A–C3C text, STRIPE_COMMERCE_DESIGN.md, SECURITY.md, IMPLEMENTATION_PLAN.md, issue trackers, Rules, Auth/profile/signup/runtime/index code, packages/workflows, providers, deployment, migration, and production data are excluded.

  4. added a commit that references this issue on Jul 14, 2026
    f84c4c8
  5. daliu commented on Jul 14, 2026

    @daliu
    ContributorAuthor

    COMPLETE / CLAIM RELEASED.

    • Reviewed source head: aee505cacd0d8f155ed14c9bb0942b02a158aa2d
    • Merged PR: MEMBERS-IDENTITY-001A: define membership authority contract #210
    • Exact main merge: f84c4c8883a2f6e9c400081051e9d8f4eaf64e05
    • Exact-head PR CI: 29303961087 passed all five hosted jobs.
    • Post-merge main CI: 29304025914 passed frontend, Functions, artifact scrubber, Firestore Rules, and the 38-case commerce-journal emulator.
    • Three independent exact-hash reviews approved security/privacy, contract/tests, and officer continuity/coordination.
    • status:in-progress was removed; the four-path claim is released.

    Deployment/live truth:

    • Source changed: yes.
    • Tests passed: yes.
    • Code merged: yes.
    • Website published: no release workflow ran.
    • runmprc.com verified for this source: not applicable; no website behavior changed.
    • Firebase deployed/read back: no.
    • Provider configured or called: no.
    • Production data/migration: none.
    • Live membership behavior: none; the module remains unused with no runtime/index edge.
    • GitHub Actions shows only the post-merge CI run for the merge SHA, and GitHub records no deployment for that SHA.

    Durable command replay, cross-record account-link uniqueness, approved membership/payment policy, schema, Rules, authorization, migration, protected deployment, and live proof remain future work. Do not treat #208 as an available membership system.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:authAuthentication and authorizationarea:firebaseFirebase services and dataarea:membershipMembership lifecycle and reconciliationpriority:P0Launch blocker or urgent security risksize:SSmall focused issuetype:architectureArchitecture and contract designtype:securitySecurity or privacy boundarytype:testingTest infrastructure and quality gates

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions