Files
rengine/shared/models/instance_settings.py
T
Yogesh Ojha a700bbed03 feat(scans): concurrent scan limit with a launch-order queue
Launches past the limit stay pending and start in launch order when a slot
frees, so each running scan gets full speed and memory stays bounded.

- run_scan admits a pending scan under an advisory lock: running plus waiting
  scans ahead of it must be under the limit
- finalize, cancel, pause, delete and a limit change start the next scans;
  the reaper re-sends only scans whose turn has come
- automatic limit: live worker-scans stage slots over the widest step,
  so --scale raises it; Settings sets a fixed limit from 1 to 50
- watch probes skip the queue, resume is never held
- queued scans show how many are ahead
2026-09-25 05:38:23 +05:30

122 lines
4.5 KiB
Python

import uuid
from datetime import datetime
from pydantic import BaseModel
from pydantic import Field as PydanticField
from sqlalchemy import Column
from sqlalchemy.types import JSON
from sqlmodel import Field, SQLModel, UniqueConstraint
from shared.definitions.bounty_programs import (
DEFAULT_FEED_INTERVAL,
DEFAULT_SYNC_INTERVAL,
)
from shared.definitions.oast import (
DEFAULT_WAIT_SECONDS,
MAX_SERVER_LENGTH,
OastMode,
)
from shared.definitions.scan_admission import AUTOMATIC, MAX_CONCURRENT_SCANS
from shared.enums.instance import InstanceMode
from shared.utils.datetime import utc_now
SINGLETON_KEY = "instance"
class InstanceSettings(SQLModel, table=True):
__tablename__ = "instance_settings"
__table_args__ = (
UniqueConstraint("singleton_key", name="uq_instance_settings_singleton"),
)
id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
singleton_key: str = Field(default=SINGLETON_KEY, max_length=20)
instance_name: str = Field(default="reNgine", max_length=120)
timezone: str = Field(default="UTC", max_length=64)
mode: str = Field(default=InstanceMode.BUG_BOUNTY.value)
onboarding_completed: bool = Field(default=False)
onboarding_completed_at: datetime | None = Field(default=None)
onboarding_completed_by: uuid.UUID | None = Field(default=None)
onboarding_step: int = Field(default=0)
onboarding_state: dict = Field(
default_factory=dict, sa_column=Column(JSON, nullable=False)
)
scan_history_retention_days: int = Field(default=90)
screenshot_retention_days: int = Field(default=30)
ai_enabled: bool = Field(default=False)
ai_provider: str | None = Field(default=None)
ai_model: str | None = Field(default=None)
ai_api_key_encrypted: str | None = Field(default=None)
ai_features: dict = Field(
default_factory=dict, sa_column=Column(JSON, nullable=False)
)
report_defaults: dict = Field(
default_factory=dict, sa_column=Column(JSON, nullable=False)
)
threat_intel_auto_sync: bool = Field(default=True)
cert_recheck_enabled: bool = Field(default=False)
bounty_sync_interval: str = Field(default=DEFAULT_SYNC_INTERVAL, max_length=16)
bounty_synced_at: datetime | None = Field(default=None)
bounty_events_seen_at: datetime | None = Field(default=None)
bounty_feed_interval: str = Field(default=DEFAULT_FEED_INTERVAL, max_length=16)
bounty_feed_synced_at: datetime | None = Field(default=None)
bounty_settings: dict = Field(
default_factory=dict, sa_column=Column(JSON, nullable=False)
)
mcp_enabled: bool = Field(default=False)
mcp_settings: dict = Field(
default_factory=dict, sa_column=Column(JSON, nullable=False)
)
new_checks_swept_at: datetime | None = Field(default=None)
oast_mode: str = Field(default=OastMode.OFF.value, max_length=16)
oast_server: str | None = Field(default=None, max_length=MAX_SERVER_LENGTH)
oast_public_acknowledged: bool = Field(default=False)
oast_wait_seconds: int = Field(default=DEFAULT_WAIT_SECONDS)
concurrent_scans: int = Field(default=AUTOMATIC)
created_at: datetime = Field(default_factory=utc_now)
updated_at: datetime = Field(default_factory=utc_now)
class InstanceSettingsUpdate(BaseModel):
instance_name: str | None = None
timezone: str | None = None
mode: str | None = None
scan_history_retention_days: int | None = None
screenshot_retention_days: int | None = None
cert_recheck_enabled: bool | None = None
concurrent_scans: int | None = PydanticField(
default=None, ge=AUTOMATIC, le=MAX_CONCURRENT_SCANS
)
ai_enabled: bool | None = None
ai_provider: str | None = None
ai_model: str | None = None
ai_api_key: str | None = None
ai_features: dict | None = None
class InstanceSettingsRead(BaseModel):
id: uuid.UUID
singleton_key: str
instance_name: str
timezone: str
mode: str
onboarding_completed: bool
onboarding_completed_at: datetime | None
onboarding_completed_by: uuid.UUID | None
onboarding_step: int
onboarding_state: dict
scan_history_retention_days: int
screenshot_retention_days: int
cert_recheck_enabled: bool
concurrent_scans: int = AUTOMATIC
concurrent_scans_auto: int | None = None
ai_enabled: bool
ai_provider: str | None
ai_model: str | None
ai_api_key_masked: str | None
ai_configured: bool
ai_features: dict
capabilities: list[str]
created_at: datetime
updated_at: datetime