Skip to content

Switch join eligibility gate to canivote (#406) - #425

Merged
lgelauff merged 6 commits into
mainfrom
agent/lane-eligibility-switch-the-join-gate-to
Sep 21, 2026
Merged

lgelauff merged 6 commits into
mainfrom
agent/lane-eligibility-switch-the-join-gate-to

Conversation

@schiste

@schiste schiste commented Sep 18, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • Switch the join gate from the old AccountEligibility eligible boolean to canivote GET /check with user and policy.
  • Map eligible and not_eligible to the existing join contract; keep indeterminate and all non-200 responses, timeouts, and malformed bodies on the could-not-check path.
  • Replace the raw logger.exception call with logging limited to policy id, response status or exception class, and Retry-After.
  • Add fake-canivote coverage for all verdicts, 400/404/429/500/502, timeout, malformed JSON, request parameters, and username-free logs.

Scope

This PR implements #406 work item 1 only. Policy picker, schema/migration changes, verdict persistence, invitations, shared access checks, and background re-checks are deliberately left for the other work items and lanes.

The requested recommendation to close #257 as superseded by #406 work item 2 was posted separately; the issue was not closed.

Review follow-ups

  • Finding 1: the default remains empty until work item 2 migrates legacy event IDs to canivote policy IDs. This prevents disclosing usernames for legacy identifiers that can only produce a policy-not-found response. An explicitly configured ACCOUNT_ELIGIBILITY_URL still opts into checks.
  • Finding 2: indeterminate now logs only the policy ID, internal participant ID, and unmeasured metric IDs; no username or upstream response prose is logged.
  • Finding 3: the legacy detail allowlist now retains only the event identifier. Upstream reason, message, criteria, failed rules, and rules are not stored or surfaced.

Logging note

I checked v2/logging_setup.py:41-56: its redactions cover credentials, hashes, and sensitive key/value fields, but do not match a user= query parameter in a requests traceback. The eligibility logger avoids attaching the raw exception or URL.

Tests

  • CI-equivalent uvx ruff check . from v2: passed
  • uv run --frozen pytest -q: 837 passed, 1 skipped

Part of #406; context: #409.

canivote has since published an OpenAPI contract and no longer accepts the
`event` alias; its response carries `policy`. `_eligibility_detail` still read
`event`, so the cached detail was always empty against a real response — and the
test hid it by fabricating `event=`.

- `_eligibility_detail` reads `policy`. Criteria are not cached: nothing reads
  them yet (#406 adds the failed-rule view), and they are where prose/username
  could leak.
- `_check_join_eligibility`'s docstring points at canivote's `/openapi.json`
  and states exactly what is cached.
- Tests build a canivote-shaped response and assert the cache holds only the
  policy id, with no prose or username.
- `guide_deployment.md` documents `ACCOUNT_ELIGIBILITY_URL` as the canivote
  base URL (not an endpoint) and when to set it.
@lgelauff

Copy link
Copy Markdown
Owner

Staging verification

Ran against the beta combination on wiki-polis-dev, deployed commit 56a5bb8 (current main + #425/#426/#427 + a fix to this PR). canivote is live at https://canivote.toolforge.org (its contract PR, lgelauff/canivote#10, is merged).

Environment note: ACCOUNT_ELIGIBILITY_URL must be set to canivote's base URL (https://canivote.toolforge.org). With it unset the gate is offline; an invalid policy id yields unavailable, not denied (see #406).

Results

Check Result
canivote contract live (/openapi.json, version header) PASS
event alias removed → 400 bad_request PASS
unknown policy → 404 unknown_policy + known_policies PASS
live Verdict validates against the published OpenAPI schema PASS
Refusal path — eiabot (not eligible) joining a process with policy nlwiki-stemprocedure PASS → 403 eligibility_denied, copy "Your account does not meet the criteria", requirement label rendered
canivote direct for eiabot not_eligible, fails 2/7 (time_since_first_edit, edit_count)
Eligible path — canivote direct for effeietsanders eligible (all rules pass)
Eligible join submitted as effeietsanders Exercised; not independently confirmed (the account is a global admin, so the workspace view is moderator access, not proof of the join — the participants count is the confirmation)

Fix included in this PR

_eligibility_detail read event, which canivote no longer returns, so the cached detail was always empty; the test hid it by fabricating event=. It now reads policy (commit bed70e3), and the tests build a canivote-shaped payload. CI green.

Filed from this work

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.

Eligibility config: replace opaque free-text event ID + criteria label with two dropdowns (predefined criteria + target wiki) (follow-up to #236)

2 participants