mirror of
https://github.com/yogeshojha/rengine.git
synced 2026-10-21 07:41:28 +02:00
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
41 lines
1.1 KiB
Python
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()
|