Skip to content

AUTH-001B — Require verified email for role-based Firestore access #196

Closed

Description

@daliu

Officer impact: After deployment, an officer or member whose account email is not verified cannot use role-only access to private member content or admin records. They can still sign in, view/update their own permitted profile fields, and use the documented verification recovery path.

Officer documentation: Update docs/officers/ACCESS_CONTINUITY.md, docs/officers/EVENTS_SHOP_MEMBERS.md, and the matching system-map text/diagram if the access flow changes. Mark the rule as source-only until Firebase Rules deployment and staged/live proof are complete.

Deployment evidence: None at issue creation. Closure of the source slice requires deterministic Rules emulator tests, merged source, exact hosted CI, and separate evidence that Firebase Rules were or were not deployed. It must not claim website, provider, mailbox, or live-member verification.

Problem

Current Firestore Rules treat a custom role value of member or admin as sufficient for role-based access. They do not also require Firebase Auth's authoritative email_verified token claim. A stale, forged-in-test, or otherwise unverified role-bearing token can therefore satisfy private member/admin Rules even though AUTH-001 requires both facts.

Atomic outcome

Require request.auth.token.email_verified == true for every role-based Firestore authorization decision while preserving identity-only self-service access needed to verify and recover an account.

flowchart LR
    A["Signed-in Firebase identity"] --> B{"Own safe profile action?"}
    B -->|"Yes"| C["Use UID-based self-service rule"]
    B -->|"No; role access"| D{"Verified email and allowed role?"}
    D -->|"Yes"| E["Allow the specific member/admin operation"]
    D -->|"No"| F["Deny"]
Loading

Text alternative: Safe self-service profile actions remain tied to the signed-in UID. Every private member or admin action requires both a verified-email token and the allowed role.

Invariants

  • A member or admin role string alone never authorizes a private read or browser-admin operation.
  • Only the authoritative token boolean email_verified == true counts; profile fields and request data do not override it.
  • Missing, false, string, number, or other malformed verification values deny role-based access.
  • An unverified signed-in person retains only existing UID-bound self-service reads/updates and cannot gain another user's access.
  • Anonymous and public event/product reads remain unchanged.
  • This change does not grant a role after verification and does not treat verification as membership.

Scope

  • firestore.rules
  • Existing Firestore Rules tests under tests/firestore-rules/ needed to prove the role/verification matrix
  • Minimum authoritative engineering/officer status documentation

Acceptance criteria

  • Shared Rules helpers require exact boolean verified-email state for member/admin role access.
  • An unverified or missing-claim admin is denied every browser-admin surface currently guarded by isAdmin().
  • An unverified or missing-claim member/admin is denied members-only documents and events.
  • Verified member/admin behavior remains allowed only where the existing role permits it.
  • Unverified users can still perform the existing UID-bound safe profile recovery/edit operations, without cross-user access.
  • Profile emailVerified data, forged request fields, or malformed token values cannot satisfy the rule.
  • Existing public/anonymous behavior is unchanged.
  • Focused and full Rules emulator suites pass with explicit verified state in every privileged test context.
  • Source, tests, merge, Firebase deployment, and live behavior are reported as separate states.

Dependencies and coordination

Explicitly out of scope

  • Cloud Functions authorization changes, role grants, profile verification-mirror reconciliation, token revocation, MFA/recent-auth, account linking, provider configuration, email templates, Firebase deployment, or production-data inspection.
  • Removing UID-bound self-service access required for account setup/recovery.
  • Granting membership or admin rights because an email becomes verified.

Claim protocol

Creation is not a claim. Before editing, assign the issue, post CLAIMED by <canonical agent> at <UTC>; branch <branch>, and re-read live comments. Keep the change to this Rules authorization outcome.

Activity

  1. self-assigned this
    on Jul 14, 2026
  2. added
    priority:P0Launch blocker or urgent security risk
    type:securitySecurity or privacy boundary
    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
    on Jul 14, 2026
  3. daliu commented on Jul 14, 2026

    @daliu
    ContributorAuthor

    CLAIMED by /root at 2026-07-14T00:39:54Z; branch codex/issue-196-verified-role-rules; exact base e76b1ee.

    This is AUTH-001B, not a multi-mode AUTH-MAIL action-handler slice. Active source ownership is limited to firestore.rules and the minimum tests/firestore-rules role-matrix files required by the failing proof. Minimum AUTH-001/security/officer status hunks will be named after the failing-test audit. It excludes #194 action/Identity/App files, Functions, profile-mirror reconciliation, token revocation, packages, workflows, providers, deployment, and production data.

    Invariant: UID-bound safe self-service remains available; every member/admin role-based Firestore decision additionally requires exact boolean token email_verified == true. Verification never grants membership.

  4. added
    status:in-progressClaimed and actively being implemented
    and removed
    status:readyDependencies complete and ready to claim
    on Jul 14, 2026
  5. daliu commented on Jul 14, 2026

    @daliu
    ContributorAuthor

    SCOPE AMENDMENT after failing-test audit — 2026-07-14T00:44:07Z

    Exact implementation/test paths are now: firestore.rules; tests/firestore-rules/setup.js; tests/firestore-rules/members-only.test.js; tests/firestore-rules/members.test.js; tests/firestore-rules/events.test.js; tests/firestore-rules/shop-and-locked.test.js. The red proof was 30 expected-denial failures against the old role-only Rules; the focused fixed proof is 4 suites / 348 tests.

    Minimum status/continuity paths reserved for #196: SECURITY.md, IMPLEMENTATION_PLAN.md, GITHUB_ISSUES.md, GITHUB_ISSUE_SLICES.md, OPERATIONS_RUNBOOK.md, docs/officers/ACCESS_CONTINUITY.md, and docs/officers/SYSTEM_MAPS.md.

    Coordination: #197 owns functions/memberProfile.js plus its two tests and only the SYSTEM_DESIGN/account-profile and docs/officers/EVENTS_SHOP_MEMBERS phone-copy sections. #196 will not edit those #197 paths. All #194 action/Identity/App paths remain excluded.

  6. daliu commented on Jul 14, 2026

    @daliu
    ContributorAuthor

    EXTRACTION FINISHED — 2026-07-14T00:50:45Z

    PR #198 is ready for review at exact head 2da7bfa824fdc2be635f27ec577150940cf6a303.

    The exact staged diff b681c561bbf55017f14d9caad8a3cdb411c34606ee84637c51c6cd9db891b6a5 was independently approved by security, test, and officer-documentation reviewers. Local evidence includes the red proof (30 new denials failed before the Rules fix), full Rules 348/348, frontend 198/198, Functions 990/990 non-emulator tests, SPA 11/11, release/workflow/artifact 42/42, lint, build, and diff checks.

    Hosted PR checks are running. No Firebase deployment was attempted; #196 remains source/test-only and is not live. The claim stays active until controlled merge, post-merge evidence, and explicit release.

  7. daliu commented on Jul 14, 2026

    @daliu
    ContributorAuthor

    COMPLETE / CLAIM RELEASED — 2026-07-14T00:55:02Z

    PR #198 merged as exact main commit a8801770e97cf21d81f3307f5893734115140d8f.

    Evidence:

    • Exact-head PR CI run 29297012945 passed frontend lint/Jest/SPA/build, Functions lint/tests, Firestore Rules, commerce-journal, and artifact safety. The Netlify PR preview also passed.
    • Exact post-merge CI run 29297116454 passed every blocking job on a8801770e97cf21d81f3307f5893734115140d8f.
    • The full Rules emulator proof is 4 suites / 348 tests. Before the fix, all 30 new unsafe-case denials failed; after the fix, all passed.
    • Three independent exact-diff reviews approved security, tests, and officer continuity with no findings.

    Deployment state:

    • Source changed, tests passed, and code merged.
    • No protected release was run. Firebase Rules were not deployed, so this boundary is not live.
    • No website production publication, outside-provider change, production account test, role change, or production-data action occurred.

    The #196 claim on its 13 paths is released. Remaining AUTH-001 work still includes Functions/Admin SDK authorization, verification-mirror reconciliation, token refresh/revocation behavior, protected Firebase deployment, and live readback. Verification continues to grant no role or membership by itself.

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 datapriority:P0Launch blocker or urgent security risksize:SSmall focused issuetype:securitySecurity or privacy boundarytype:testingTest infrastructure and quality gates

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions