Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 22 additions & 16 deletions hindsight-api-slim/hindsight_api/api/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
AuditLogStatsResponse,
)
from hindsight_api.engine.llm_trace import LLMRequestListResponse, LLMRequestStatsResponse
from hindsight_api.extensions import AuthenticationError
from hindsight_api.extensions import AuthenticationError, PrecheckOperation


def _parse_metadata(metadata: Any) -> dict[str, Any]:
Expand Down Expand Up @@ -3364,7 +3364,7 @@ def get_request_context(authorization: str | None = Header(default=None)) -> Req
api_key = authorization.strip()
return RequestContext(api_key=api_key)

def precheck_for(operation: str):
def precheck_for(operation: PrecheckOperation):
"""
Build a FastAPI dependency that runs ``OperationValidator.precheck``.

Expand Down Expand Up @@ -3615,7 +3615,7 @@ async def api_list(
async def _require_dry_run_enabled() -> None:
"""Feature-flag gate for dry-run extraction.

Declared as a dependency BEFORE ``precheck_for("dry_run_extract")`` so a
Declared as a dependency BEFORE ``precheck_for(PrecheckOperation.DRY_RUN_EXTRACT)`` so a
disabled route returns 404 regardless of tenant/billing state — FastAPI
resolves path-operation dependencies in signature order, so this runs
first and preserves the original "disabled → 404" contract.
Expand Down Expand Up @@ -3645,7 +3645,7 @@ async def api_dry_run_extract(
body: DryRunExtractRequest,
request_context: RequestContext = Depends(get_request_context),
_enabled: None = Depends(_require_dry_run_enabled),
_precheck: None = Depends(precheck_for("dry_run_extract")),
_precheck: None = Depends(precheck_for(PrecheckOperation.DRY_RUN_EXTRACT)),
):
try:
override_fields = (
Expand Down Expand Up @@ -3813,7 +3813,7 @@ async def api_recall(
request: RecallRequest,
http_request: Request,
request_context: RequestContext = Depends(get_request_context),
_precheck: None = Depends(precheck_for("recall")),
_precheck: None = Depends(precheck_for(PrecheckOperation.RECALL)),
):
"""Run a recall and return results with trace."""
import time
Expand Down Expand Up @@ -4015,7 +4015,7 @@ async def api_reflect(
request: ReflectRequest,
http_request: Request,
request_context: RequestContext = Depends(get_request_context),
_precheck: None = Depends(precheck_for("reflect")),
_precheck: None = Depends(precheck_for(PrecheckOperation.REFLECT)),
):
metrics = get_metrics_collector()

Expand Down Expand Up @@ -4562,7 +4562,7 @@ async def api_create_mental_model(
bank_id: str,
body: CreateMentalModelRequest,
request_context: RequestContext = Depends(get_request_context),
_precheck: None = Depends(precheck_for("mental_model_create")),
_precheck: None = Depends(precheck_for(PrecheckOperation.MENTAL_MODEL_CREATE)),
):
"""Create a mental model (async - returns operation_id)."""
try:
Expand Down Expand Up @@ -4611,7 +4611,7 @@ async def api_refresh_mental_model(
bank_id: str,
mental_model_id: str,
request_context: RequestContext = Depends(get_request_context),
_precheck: None = Depends(precheck_for("mental_model_refresh")),
_precheck: None = Depends(precheck_for(PrecheckOperation.MENTAL_MODEL_REFRESH)),
):
"""Refresh a mental model by re-running its source query (async)."""
try:
Expand Down Expand Up @@ -6197,9 +6197,11 @@ async def api_get_bank_config(bank_id: str, request_context: RequestContext = De
# Authenticate and set schema context for multi-tenant DB queries
await app.state.memory._authenticate_tenant(request_context)
if app.state.memory._operation_validator:
from hindsight_api.extensions import BankReadContext
from hindsight_api.extensions import BankReadContext, BankReadOperation

ctx = BankReadContext(bank_id=bank_id, operation="get_bank_config", request_context=request_context)
ctx = BankReadContext(
bank_id=bank_id, operation=BankReadOperation.GET_BANK_CONFIG, request_context=request_context
)
await app.state.memory._validate_operation(
app.state.memory._operation_validator.validate_bank_read(ctx)
)
Expand Down Expand Up @@ -6245,9 +6247,11 @@ async def api_update_bank_config(
# Authenticate and set schema context for multi-tenant DB queries
await app.state.memory._authenticate_tenant(request_context)
if app.state.memory._operation_validator:
from hindsight_api.extensions import BankWriteContext
from hindsight_api.extensions import BankWriteContext, BankWriteOperation

ctx = BankWriteContext(bank_id=bank_id, operation="update_bank_config", request_context=request_context)
ctx = BankWriteContext(
bank_id=bank_id, operation=BankWriteOperation.UPDATE_BANK_CONFIG, request_context=request_context
)
await app.state.memory._validate_operation(
app.state.memory._operation_validator.validate_bank_write(ctx)
)
Expand Down Expand Up @@ -6304,9 +6308,11 @@ async def api_reset_bank_config(bank_id: str, request_context: RequestContext =
# Authenticate and set schema context for multi-tenant DB queries
await app.state.memory._authenticate_tenant(request_context)
if app.state.memory._operation_validator:
from hindsight_api.extensions import BankWriteContext
from hindsight_api.extensions import BankWriteContext, BankWriteOperation

ctx = BankWriteContext(bank_id=bank_id, operation="reset_bank_config", request_context=request_context)
ctx = BankWriteContext(
bank_id=bank_id, operation=BankWriteOperation.RESET_BANK_CONFIG, request_context=request_context
)
await app.state.memory._validate_operation(
app.state.memory._operation_validator.validate_bank_write(ctx)
)
Expand Down Expand Up @@ -6677,7 +6683,7 @@ async def api_retain(
bank_id: str,
request: RetainRequest,
request_context: RequestContext = Depends(get_request_context),
_precheck: None = Depends(precheck_for("retain")),
_precheck: None = Depends(precheck_for(PrecheckOperation.RETAIN)),
):
"""Retain memories with optional async processing."""
metrics = get_metrics_collector()
Expand Down Expand Up @@ -6860,7 +6866,7 @@ async def api_file_retain(
files: list[UploadFile] = File(..., description="Files to upload and convert"),
request: str = Form(..., description="JSON string with FileRetainRequest model"),
request_context: RequestContext = Depends(get_request_context),
_precheck: None = Depends(precheck_for("files_retain")),
_precheck: None = Depends(precheck_for(PrecheckOperation.FILES_RETAIN)),
):
"""Upload and convert files to memories."""
from hindsight_api.config import get_config
Expand Down
Loading