generated from coulomb/repo-seed
STATE-WP-0062 T2: /services catalog API over the two-dimension model
Add a local /services router (source of truth for the catalog itself):
- GET /services/catalog with hosting_type / development_type / maturity_level /
status filters (eager-loads all four extensions)
- GET /services/{slug}
- POST /services/catalog upsert-by-slug, applying the dimension extensions;
first_party.repo_slug resolves to a managed_repos FK.
Extensions are read/written via session.get (not the relationship attribute) to
avoid async lazy-load. /tpsc/* is left intact for dependency snapshots. 7 tests.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
116
api/schemas/service.py
Normal file
116
api/schemas/service.py
Normal file
@@ -0,0 +1,116 @@
|
||||
"""Schemas for the two-dimension service catalog (STATE-WP-0062)."""
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
|
||||
from pydantic import BaseModel, ConfigDict
|
||||
|
||||
|
||||
# ── Extension read models ────────────────────────────────────────────────────
|
||||
|
||||
class ServiceThirdPartyRead(BaseModel):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
pricing_model: str
|
||||
upstream_packages: list | None = None
|
||||
upstream_contacts: list | None = None
|
||||
source_url: str | None = None
|
||||
support_url: str | None = None
|
||||
license: str | None = None
|
||||
|
||||
|
||||
class ServiceFirstPartyRead(BaseModel):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
repo_id: uuid.UUID | None = None
|
||||
owning_domain: str | None = None
|
||||
|
||||
|
||||
class ServiceCloudRead(BaseModel):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
gdpr_maturity: str
|
||||
gdpr_notes: str | None = None
|
||||
dpa_available: bool
|
||||
tos_url: str | None = None
|
||||
privacy_policy_url: str | None = None
|
||||
data_processing_regions: list | None = None
|
||||
data_retention_notes: str | None = None
|
||||
|
||||
|
||||
class ServiceSelfHostedRead(BaseModel):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
helix_instance: str | None = None
|
||||
host_node: str | None = None
|
||||
deployment_ref: str | None = None
|
||||
runbook_ref: str | None = None
|
||||
upstream_oss_project: str | None = None
|
||||
|
||||
|
||||
class ServiceCatalogRead(BaseModel):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
id: uuid.UUID
|
||||
slug: str
|
||||
name: str
|
||||
owner_or_provider: str | None = None
|
||||
category: str | None = None
|
||||
description: str | None = None
|
||||
website_url: str | None = None
|
||||
status: str
|
||||
hosting_type: str
|
||||
development_type: str
|
||||
maturity_level: int | None = None
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
third_party: ServiceThirdPartyRead | None = None
|
||||
first_party: ServiceFirstPartyRead | None = None
|
||||
cloud: ServiceCloudRead | None = None
|
||||
self_hosted: ServiceSelfHostedRead | None = None
|
||||
|
||||
|
||||
# ── Write (upsert) models ────────────────────────────────────────────────────
|
||||
|
||||
class ServiceThirdPartyIn(BaseModel):
|
||||
pricing_model: str = "unknown"
|
||||
upstream_packages: list | None = None
|
||||
upstream_contacts: list | None = None
|
||||
source_url: str | None = None
|
||||
support_url: str | None = None
|
||||
license: str | None = None
|
||||
|
||||
|
||||
class ServiceFirstPartyIn(BaseModel):
|
||||
repo_id: uuid.UUID | None = None
|
||||
repo_slug: str | None = None
|
||||
owning_domain: str | None = None
|
||||
|
||||
|
||||
class ServiceCloudIn(BaseModel):
|
||||
gdpr_maturity: str = "unknown"
|
||||
gdpr_notes: str | None = None
|
||||
dpa_available: bool = False
|
||||
tos_url: str | None = None
|
||||
privacy_policy_url: str | None = None
|
||||
data_processing_regions: list | None = None
|
||||
data_retention_notes: str | None = None
|
||||
|
||||
|
||||
class ServiceSelfHostedIn(BaseModel):
|
||||
helix_instance: str | None = None
|
||||
host_node: str | None = None
|
||||
deployment_ref: str | None = None
|
||||
runbook_ref: str | None = None
|
||||
upstream_oss_project: str | None = None
|
||||
|
||||
|
||||
class ServiceUpsert(BaseModel):
|
||||
slug: str
|
||||
name: str
|
||||
owner_or_provider: str | None = None
|
||||
category: str | None = None
|
||||
description: str | None = None
|
||||
website_url: str | None = None
|
||||
status: str = "active"
|
||||
hosting_type: str # self_hosted | cloud_hosted
|
||||
development_type: str # first_party | third_party
|
||||
maturity_level: int | None = None
|
||||
third_party: ServiceThirdPartyIn | None = None
|
||||
first_party: ServiceFirstPartyIn | None = None
|
||||
cloud: ServiceCloudIn | None = None
|
||||
self_hosted: ServiceSelfHostedIn | None = None
|
||||
Reference in New Issue
Block a user