Skip to content

test(membership-tiers): pin is_owner semantics for verdict_source gate (#4378)#4389

Merged
bokelley merged 1 commit into
mainfrom
bokelley/verdict-source-owner-scope-tests
May 11, 2026
Merged

test(membership-tiers): pin is_owner semantics for verdict_source gate (#4378)#4389
bokelley merged 1 commit into
mainfrom
bokelley/verdict-source-owner-scope-tests

Conversation

@bokelley
Copy link
Copy Markdown
Contributor

Summary

Partial completion of #4378. Adds 6 explicit unit tests pinning the `is_owner` field semantics in `resolveOwnerMembership` — the load-bearing gate for `verdict_source` exposure on the public compliance API.

The matrix

Caller is_owner Reasoning
Anonymous (no userId) false Never an owner
User not in any owning org false Membership query returns null
Orphan profile (org deleted) false Treated same as non-owner (no side-channel)
Owner on free Explorer tier true Broader than `is_api_access_tier` — free-tier owners still see the UX cue on their own dashboard
Owner on API-access tier, active sub true Standard owner case
Owner with canceled sub true Ownership ≠ entitlement (badges don't issue, but dashboard cue still works)

Why this anchors a real invariant

PR #4263's review caught that gating `verdict_source` on `is_api_access_tier` was too narrow — free-tier owners would see `null` on their own agent. These tests pin the correction so a future refactor can't silently regress to the narrower predicate.

What's deferred

The original #4378 also called for a route-level integration test (`request(app).get(...).expect(...)` against the compliance endpoint). That needs DB-fixture scaffolding (agent_compliance_status row inserts, auth simulation) not currently in place for this endpoint. Filed as the follow-up — leaving #4378 open.

Test plan

```bash
npx vitest run tests/unit/membership-tiers.test.ts

27 passing (6 new)

```

🤖 Generated with Claude Code

#4378)

Adds 6 explicit unit tests to `tests/unit/membership-tiers.test.ts`
covering the `is_owner` field that gates `verdict_source` exposure on
the public `/api/registry/agents/:url/compliance` response. The matrix:

- Anonymous (no userId) → is_owner: false
- User not a member of any owning org → is_owner: false
- Resolved org deleted (orphan profile) → is_owner: false
- Owner on free Explorer tier → is_owner: true (broader than
  is_api_access_tier, which is false for Explorer — pins that free-
  tier owners still get verdict_source on their own dashboard)
- Owner on API-access tier with active sub → is_owner: true
- Owner with canceled sub → is_owner: true (ownership ≠ entitlement;
  the dashboard cue still works, badges don't until reactivation)

Pre-PR #4263 review feedback flagged that gating verdict_source on
is_api_access_tier (the previous design) was too narrow — free-tier
owners would see null on their own agent. These tests anchor the
correction (is_owner is the right gate) so a future refactor can't
silently regress.

Full route-level integration test (anonymous → null, cross-org →
null, owner → populated through `request(app).get(...)`) deferred —
requires DB-fixture scaffolding not currently in place for this
endpoint. Follow-up will set up the harness and write those.

Partial completion of #4378. Leaves the issue open for the
integration-test follow-up.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@bokelley bokelley merged commit 67db405 into main May 11, 2026
13 checks passed
@bokelley bokelley deleted the bokelley/verdict-source-owner-scope-tests branch May 11, 2026 11:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant