Verified catalogue of mobiles and laptops sold in India, collected from real retail listings (FastAPI backend, React frontend, Postgres/pgvector). - REST API under /api/elec (read-only catalogue; admin endpoints need login) - MCP server (FastMCP) at /mcp/ with list_categories, search_products, get_product and price_history tools - Real ratings and reviews read from product pages and search results - Production Dockerfile (requirements-api.txt, no PyTorch) and .env.production.example; remote database only via an explicit ELEC_ALLOW_REMOTE_DB host/name allowlist - docs/API.md: endpoint and MCP reference with live examples Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
74 lines
2.7 KiB
Python
74 lines
2.7 KiB
Python
"""Pydantic response models for the health endpoint. The electronics
|
|
catalogue's own models live in app/electronics/api_models.py."""
|
|
from __future__ import annotations
|
|
|
|
from typing import List, Optional
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
class ApiKeyInfoOut(BaseModel):
|
|
"""One configured machine consumer, named but never quoted.
|
|
|
|
`fingerprint` is a truncated digest of name+secret, not the secret. It exists
|
|
so a caller who was issued a key can confirm THAT key is the one this
|
|
deployment loaded - the question a 401 cannot answer, since an undeployed key
|
|
and a wrong key fail identically.
|
|
"""
|
|
|
|
name: str
|
|
role: str
|
|
fingerprint: str
|
|
|
|
|
|
class AuthConfigOut(BaseModel):
|
|
"""
|
|
The effective auth configuration, reported by /api/health.
|
|
|
|
Unauthenticated on purpose. The failure this exists to diagnose is "nobody
|
|
can sign in", so anything gated behind an admin token is unreachable
|
|
exactly when it is needed. Nothing here is a secret: the admin username is
|
|
already the documented one, allow_any_login=true is a fact an operator
|
|
urgently needs (and an attacker discovers with a single login attempt
|
|
anyway), and the fingerprint is a truncated hash of a salted digest, not a
|
|
password. The API key block follows the same rule: it names which consumers
|
|
are configured and fingerprints their keys, so a caller can tell an
|
|
undeployed key from a rejected one, but it never renders a secret. What it buys is a one-command answer to "is this deployment
|
|
running the config I think it is?" - compare the fingerprint here against
|
|
the one printed by scripts/make_auth_secrets.py --fingerprint.
|
|
"""
|
|
|
|
enabled: bool
|
|
allow_any_login: bool
|
|
admin_username: str
|
|
password_hash_valid: bool
|
|
password_hash_iterations: Optional[int] = None
|
|
password_hash_fingerprint: str
|
|
# "process-env" | "env-file" | "default" - which one actually won.
|
|
admin_username_source: str
|
|
password_hash_source: str
|
|
# Machine consumers. Names and fingerprints only - the secrets themselves are
|
|
# never rendered here, and _parse_api_keys enforces enough entropy that the
|
|
# fingerprints do not give them away. Defaulted so a client of this schema
|
|
# still validates against a deployment predating these fields.
|
|
api_keys_count: int = 0
|
|
api_keys: List[ApiKeyInfoOut] = Field(default_factory=list)
|
|
api_keys_source: str = "default"
|
|
|
|
|
|
class SearchStatusOut(BaseModel):
|
|
"""Which web-search providers discovery can use right now."""
|
|
ddg: bool
|
|
google_cse: bool
|
|
|
|
|
|
class HealthOut(BaseModel):
|
|
status: str
|
|
database: bool
|
|
database_name: str
|
|
ollama: bool
|
|
ollama_model: str
|
|
embeddings_model: str
|
|
search: SearchStatusOut
|
|
auth: AuthConfigOut
|