Files
rengine/shared/services/locks.py
T
Yogesh OjhaandClaude Opus 5 dcdba5cfd4 feat(bounty-hub): read Intigriti through its researcher API
A platform with a researcher API is now a provider: one module under
shared/services/bounty_providers implementing programs() and scopes(),
returning rows the sync engine stores. bounty_programs.py became the
platform-agnostic engine, so adding a platform is one module, one
APIProvider value, one PlatformSpec.api_provider and a key tester.

Intigriti is the second connected platform, on a personal access token
the hunter creates. On this instance: 220 programs, 54 of them private,
155 with scope and 65 the platform refuses, which accounts for all 220.

Measured against the live API, against the docs:

- Tier ids are unordered and undocumented. Id 4 is Tier 1, not No Bounty,
  so the first mapping stored the best-paying assets as paying nothing.
  Eligibility reads the label; out of scope is matched on id and label.
- A 403 carrying FORBID001 is a refusal, not the documented rate-limit
  overage, and it covers public programs the account has not joined.
  Retrying it cost 11s a program; AccessDeniedError ends it in one
  request and records scope_access, keeping the failure budget for
  real breakage.
- Membership is proved by the platform letting the token read a private
  program's scope. confidentialityLevel never reports "invite only", so
  joined was always false and its filter was dead.

Bounty Hub follows what the data actually says:

- source becomes sources, a JSONB array. A program is routinely in both
  a platform API and the public feed; the feed adds itself without
  taking an API row back, and facet counts overlap accordingly.
- The row hint read "Bookmarked on HackerOne" while rendering
  Intigriti's follow flag. It now reads PlatformSpec.follow_label.
- Refresh queued the sync and returned, so nothing changed on screen.
  It waits for the sweep, reloads, and says so.
- The dashed connect card per platform is one dismissible Alert.
- Connecting a platform no longer diffs API scope against feed scope,
  which would report every asset removed and re-added.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SiHx8Sm34hS1nanrsPdBaD
2026-09-12 23:35:59 +05:30

41 lines
1.1 KiB
Python

"""Advisory locks for instance-wide work that must not run twice at once."""
from __future__ import annotations
import zlib
from collections.abc import Iterator
from contextlib import contextmanager
from typing import TYPE_CHECKING
from sqlalchemy import text
if TYPE_CHECKING:
from sqlalchemy.orm import Session
# bounty_platform() spans BOUNTY_SYNC .. BOUNTY_SYNC + 0xFFFF
BOUNTY_SYNC = 0x624F0001
BOUNTY_FEED = 0x624F0002
IP_RANGES = 0x624E0001
def bounty_platform(platform: str) -> int:
"""One lock per platform."""
return BOUNTY_SYNC + (zlib.crc32(platform.encode()) & 0xFFFF)
@contextmanager
def sync_lock(session: Session, key: int) -> Iterator[bool]:
"""Session-level advisory lock. Yields False when another session holds it."""
held = bool(
session.execute(
text("SELECT pg_try_advisory_lock(:key)"), {"key": key}
).scalar_one()
)
try:
yield held
finally:
if held:
session.rollback()
session.execute(text("SELECT pg_advisory_unlock(:key)"), {"key": key})
session.commit()