generated from coulomb/repo-seed
Compare commits
3 Commits
093b2b14ae
...
493c241054
| Author | SHA1 | Date | |
|---|---|---|---|
| 493c241054 | |||
| 5e32d5723d | |||
| 70b264a37a |
@@ -1,30 +1,7 @@
|
|||||||
import uuid
|
from hub_core.schemas.agent_message import MessageCreate, MessageRead, MessageReply
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
from pydantic import BaseModel, ConfigDict
|
__all__ = [
|
||||||
|
"MessageCreate",
|
||||||
|
"MessageRead",
|
||||||
class MessageCreate(BaseModel):
|
"MessageReply",
|
||||||
from_agent: str
|
]
|
||||||
to_agent: str
|
|
||||||
subject: str
|
|
||||||
body: str
|
|
||||||
thread_id: uuid.UUID | None = None
|
|
||||||
|
|
||||||
|
|
||||||
class MessageReply(BaseModel):
|
|
||||||
from_agent: str
|
|
||||||
body: str
|
|
||||||
|
|
||||||
|
|
||||||
class MessageRead(BaseModel):
|
|
||||||
model_config = ConfigDict(from_attributes=True)
|
|
||||||
id: uuid.UUID
|
|
||||||
from_agent: str
|
|
||||||
to_agent: str
|
|
||||||
subject: str
|
|
||||||
body: str
|
|
||||||
thread_id: uuid.UUID | None = None
|
|
||||||
read_at: datetime | None = None
|
|
||||||
archived_at: datetime | None = None
|
|
||||||
created_at: datetime
|
|
||||||
|
|||||||
@@ -1,29 +1,7 @@
|
|||||||
from pydantic import BaseModel
|
from hub_core.schemas.doi import DoICriterion, DoIReport, DoISummaryEntry
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
class DoICriterion(BaseModel):
|
"DoICriterion",
|
||||||
id: str
|
"DoIReport",
|
||||||
label: str
|
"DoISummaryEntry",
|
||||||
tier: str
|
]
|
||||||
status: str # pass | fail | warn | skip
|
|
||||||
detail: str = ""
|
|
||||||
|
|
||||||
|
|
||||||
class DoIReport(BaseModel):
|
|
||||||
repo_slug: str
|
|
||||||
tier: str # none | core | standard | full
|
|
||||||
core_pass: bool
|
|
||||||
standard_pass: bool
|
|
||||||
full_pass: bool
|
|
||||||
criteria: list[DoICriterion] = []
|
|
||||||
checked_at: str
|
|
||||||
|
|
||||||
|
|
||||||
class DoISummaryEntry(BaseModel):
|
|
||||||
repo_slug: str
|
|
||||||
domain_slug: str | None
|
|
||||||
tier: str
|
|
||||||
core_pass: bool
|
|
||||||
standard_pass: bool
|
|
||||||
full_pass: bool
|
|
||||||
checked_at: str
|
|
||||||
|
|||||||
@@ -1,24 +1,8 @@
|
|||||||
import uuid
|
import uuid
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
from pydantic import BaseModel, ConfigDict
|
from pydantic import BaseModel, ConfigDict
|
||||||
|
|
||||||
|
from hub_core.schemas.domain import DomainCreate, DomainRead, DomainRename, DomainUpdate
|
||||||
class DomainCreate(BaseModel):
|
|
||||||
slug: str
|
|
||||||
name: str
|
|
||||||
description: str | None = None
|
|
||||||
|
|
||||||
|
|
||||||
class DomainUpdate(BaseModel):
|
|
||||||
name: str | None = None
|
|
||||||
description: str | None = None
|
|
||||||
status: str | None = None
|
|
||||||
|
|
||||||
|
|
||||||
class DomainRename(BaseModel):
|
|
||||||
new_slug: str
|
|
||||||
new_name: str
|
|
||||||
|
|
||||||
|
|
||||||
class RepoStub(BaseModel):
|
class RepoStub(BaseModel):
|
||||||
@@ -31,17 +15,6 @@ class RepoStub(BaseModel):
|
|||||||
status: str
|
status: str
|
||||||
|
|
||||||
|
|
||||||
class DomainRead(BaseModel):
|
|
||||||
model_config = ConfigDict(from_attributes=True)
|
|
||||||
id: uuid.UUID
|
|
||||||
slug: str
|
|
||||||
name: str
|
|
||||||
description: str | None = None
|
|
||||||
status: str
|
|
||||||
created_at: datetime
|
|
||||||
updated_at: datetime
|
|
||||||
|
|
||||||
|
|
||||||
class DomainDetail(DomainRead):
|
class DomainDetail(DomainRead):
|
||||||
"""Domain with entity counts and repo list."""
|
"""Domain with entity counts and repo list."""
|
||||||
topic_count: int = 0
|
topic_count: int = 0
|
||||||
@@ -59,3 +32,14 @@ class DomainSummary(BaseModel):
|
|||||||
active_workstream_count: int = 0
|
active_workstream_count: int = 0
|
||||||
ep_count: int = 0
|
ep_count: int = 0
|
||||||
td_count: int = 0
|
td_count: int = 0
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"DomainCreate",
|
||||||
|
"DomainDetail",
|
||||||
|
"DomainRead",
|
||||||
|
"DomainRename",
|
||||||
|
"DomainSummary",
|
||||||
|
"DomainUpdate",
|
||||||
|
"RepoStub",
|
||||||
|
]
|
||||||
|
|||||||
@@ -1,115 +1,29 @@
|
|||||||
import uuid
|
from hub_core.schemas.tpsc import (
|
||||||
from datetime import datetime
|
AuthType,
|
||||||
from typing import Literal
|
GDPRMaturity,
|
||||||
from pydantic import BaseModel, computed_field
|
GDPR_WARNING_LEVELS,
|
||||||
|
PricingModel,
|
||||||
|
TPSCCatalogCreate,
|
||||||
|
TPSCCatalogRead,
|
||||||
|
TPSCEntryCreate,
|
||||||
|
TPSCEntryRead,
|
||||||
|
TPSCGDPRReport,
|
||||||
|
TPSCGDPRWarning,
|
||||||
|
TPSCIngestRequest,
|
||||||
|
TPSCSnapshotRead,
|
||||||
|
)
|
||||||
|
|
||||||
# GDPR maturity scale (CNIL/IAPP CMMI-aligned, adapted for third-party assessment)
|
__all__ = [
|
||||||
GDPRMaturity = Literal["unknown", "non_compliant", "initial", "developing", "defined", "managed", "certified"]
|
"AuthType",
|
||||||
|
"GDPRMaturity",
|
||||||
# Services at these levels trigger a GDPR warning
|
"GDPR_WARNING_LEVELS",
|
||||||
GDPR_WARNING_LEVELS = {"unknown", "non_compliant", "initial"}
|
"PricingModel",
|
||||||
|
"TPSCCatalogCreate",
|
||||||
PricingModel = Literal["free", "paid", "freemium", "usage_based", "unknown"]
|
"TPSCCatalogRead",
|
||||||
AuthType = Literal["api_key", "oauth", "cli", "none", "unknown"]
|
"TPSCEntryCreate",
|
||||||
|
"TPSCEntryRead",
|
||||||
|
"TPSCGDPRReport",
|
||||||
class TPSCCatalogCreate(BaseModel):
|
"TPSCGDPRWarning",
|
||||||
slug: str
|
"TPSCIngestRequest",
|
||||||
name: str
|
"TPSCSnapshotRead",
|
||||||
provider: str | None = None
|
]
|
||||||
category: str | None = None
|
|
||||||
website_url: str | None = None
|
|
||||||
pricing_model: PricingModel = "unknown"
|
|
||||||
gdpr_maturity: GDPRMaturity = "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[str] | None = None
|
|
||||||
data_retention_notes: str | None = None
|
|
||||||
status: str = "active"
|
|
||||||
|
|
||||||
|
|
||||||
class TPSCCatalogRead(BaseModel):
|
|
||||||
model_config = {"from_attributes": True}
|
|
||||||
|
|
||||||
id: uuid.UUID
|
|
||||||
slug: str
|
|
||||||
name: str
|
|
||||||
provider: str | None
|
|
||||||
category: str | None
|
|
||||||
website_url: str | None
|
|
||||||
pricing_model: str
|
|
||||||
gdpr_maturity: str
|
|
||||||
gdpr_notes: str | None
|
|
||||||
dpa_available: bool
|
|
||||||
tos_url: str | None
|
|
||||||
privacy_policy_url: str | None
|
|
||||||
data_processing_regions: list[str] | None
|
|
||||||
data_retention_notes: str | None
|
|
||||||
status: str
|
|
||||||
created_at: datetime
|
|
||||||
updated_at: datetime
|
|
||||||
|
|
||||||
@computed_field
|
|
||||||
@property
|
|
||||||
def gdpr_warning(self) -> bool:
|
|
||||||
return self.gdpr_maturity in GDPR_WARNING_LEVELS
|
|
||||||
|
|
||||||
|
|
||||||
class TPSCEntryCreate(BaseModel):
|
|
||||||
service_slug: str
|
|
||||||
purpose: str | None = None
|
|
||||||
auth_type: str | None = None
|
|
||||||
endpoint_override: str | None = None
|
|
||||||
notes: str | None = None
|
|
||||||
|
|
||||||
|
|
||||||
class TPSCEntryRead(BaseModel):
|
|
||||||
model_config = {"from_attributes": True}
|
|
||||||
|
|
||||||
id: uuid.UUID
|
|
||||||
snapshot_id: uuid.UUID
|
|
||||||
catalog_id: uuid.UUID | None
|
|
||||||
service_slug: str
|
|
||||||
purpose: str | None
|
|
||||||
auth_type: str | None
|
|
||||||
endpoint_override: str | None
|
|
||||||
notes: str | None
|
|
||||||
# Denormalised from catalog for convenience
|
|
||||||
gdpr_maturity: str | None = None
|
|
||||||
gdpr_warning: bool = False
|
|
||||||
pricing_model: str | None = None
|
|
||||||
|
|
||||||
|
|
||||||
class TPSCIngestRequest(BaseModel):
|
|
||||||
repo_slug: str
|
|
||||||
source_file: str = "tpsc.yaml"
|
|
||||||
entries: list[TPSCEntryCreate]
|
|
||||||
|
|
||||||
|
|
||||||
class TPSCSnapshotRead(BaseModel):
|
|
||||||
model_config = {"from_attributes": True}
|
|
||||||
|
|
||||||
id: uuid.UUID
|
|
||||||
repo_id: uuid.UUID | None
|
|
||||||
snapshot_at: datetime
|
|
||||||
source_file: str | None
|
|
||||||
entry_count: int
|
|
||||||
entries: list[TPSCEntryRead] = []
|
|
||||||
|
|
||||||
|
|
||||||
class TPSCGDPRWarning(BaseModel):
|
|
||||||
repo_slug: str | None
|
|
||||||
service_slug: str
|
|
||||||
gdpr_maturity: str
|
|
||||||
purpose: str | None
|
|
||||||
pricing_model: str | None
|
|
||||||
|
|
||||||
|
|
||||||
class TPSCGDPRReport(BaseModel):
|
|
||||||
generated_at: datetime
|
|
||||||
total_services: int
|
|
||||||
warning_count: int
|
|
||||||
warnings: list[TPSCGDPRWarning]
|
|
||||||
by_maturity: dict[str, int]
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ dependencies = [
|
|||||||
"llm-connect",
|
"llm-connect",
|
||||||
"pyyaml>=6.0.3",
|
"pyyaml>=6.0.3",
|
||||||
"nats-py>=2.7.0",
|
"nats-py>=2.7.0",
|
||||||
|
"hub-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[project.scripts]
|
[project.scripts]
|
||||||
@@ -34,6 +35,7 @@ artifacts = ["custodian_cli.py", "statehub_register.py"]
|
|||||||
|
|
||||||
[tool.uv.sources]
|
[tool.uv.sources]
|
||||||
llm-connect = { path = "/home/worsch/llm-connect", editable = true }
|
llm-connect = { path = "/home/worsch/llm-connect", editable = true }
|
||||||
|
hub-core = { path = "/home/worsch/hub-core", editable = true }
|
||||||
|
|
||||||
[tool.pytest.ini_options]
|
[tool.pytest.ini_options]
|
||||||
asyncio_mode = "auto"
|
asyncio_mode = "auto"
|
||||||
|
|||||||
38
tests/test_hub_core_imports.py
Normal file
38
tests/test_hub_core_imports.py
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
from api.schemas.agent_message import MessageCreate
|
||||||
|
from api.schemas.doi import DoIReport
|
||||||
|
from api.schemas.domain import DomainCreate, DomainRead, DomainRename, DomainUpdate
|
||||||
|
from api.schemas.tpsc import GDPR_WARNING_LEVELS, TPSCCatalogRead, TPSCGDPRReport
|
||||||
|
from hub_core.schemas.agent_message import MessageCreate as CoreMessageCreate
|
||||||
|
from hub_core.schemas.doi import DoIReport as CoreDoIReport
|
||||||
|
from hub_core.schemas.domain import (
|
||||||
|
DomainCreate as CoreDomainCreate,
|
||||||
|
DomainRead as CoreDomainRead,
|
||||||
|
DomainRename as CoreDomainRename,
|
||||||
|
DomainUpdate as CoreDomainUpdate,
|
||||||
|
)
|
||||||
|
from hub_core.schemas.tpsc import (
|
||||||
|
GDPR_WARNING_LEVELS as CORE_GDPR_WARNING_LEVELS,
|
||||||
|
TPSCCatalogRead as CoreTPSCCatalogRead,
|
||||||
|
TPSCGDPRReport as CoreTPSCGDPRReport,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_state_hub_reexports_core_message_schema() -> None:
|
||||||
|
assert MessageCreate is CoreMessageCreate
|
||||||
|
|
||||||
|
|
||||||
|
def test_state_hub_reexports_core_doi_schema() -> None:
|
||||||
|
assert DoIReport is CoreDoIReport
|
||||||
|
|
||||||
|
|
||||||
|
def test_state_hub_reexports_core_domain_base_schemas() -> None:
|
||||||
|
assert DomainCreate is CoreDomainCreate
|
||||||
|
assert DomainRead is CoreDomainRead
|
||||||
|
assert DomainRename is CoreDomainRename
|
||||||
|
assert DomainUpdate is CoreDomainUpdate
|
||||||
|
|
||||||
|
|
||||||
|
def test_state_hub_reexports_core_tpsc_schemas() -> None:
|
||||||
|
assert TPSCCatalogRead is CoreTPSCCatalogRead
|
||||||
|
assert TPSCGDPRReport is CoreTPSCGDPRReport
|
||||||
|
assert GDPR_WARNING_LEVELS is CORE_GDPR_WARNING_LEVELS
|
||||||
23
uv.lock
generated
23
uv.lock
generated
@@ -530,6 +530,27 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/d2/fd/6668e5aec43ab844de6fc74927e155a3b37bf40d7c3790e49fc0406b6578/httpx_sse-0.4.3-py3-none-any.whl", hash = "sha256:0ac1c9fe3c0afad2e0ebb25a934a59f4c7823b60792691f779fad2c5568830fc", size = 8960 },
|
{ url = "https://files.pythonhosted.org/packages/d2/fd/6668e5aec43ab844de6fc74927e155a3b37bf40d7c3790e49fc0406b6578/httpx_sse-0.4.3-py3-none-any.whl", hash = "sha256:0ac1c9fe3c0afad2e0ebb25a934a59f4c7823b60792691f779fad2c5568830fc", size = 8960 },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hub-core"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = { editable = "../hub-core" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "fastapi" },
|
||||||
|
{ name = "fastmcp" },
|
||||||
|
{ name = "httpx" },
|
||||||
|
{ name = "pydantic" },
|
||||||
|
{ name = "sqlalchemy", extra = ["asyncio"] },
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.metadata]
|
||||||
|
requires-dist = [
|
||||||
|
{ name = "fastapi", specifier = ">=0.115.0" },
|
||||||
|
{ name = "fastmcp", specifier = ">=2.0.0" },
|
||||||
|
{ name = "httpx", specifier = ">=0.28.0" },
|
||||||
|
{ name = "pydantic", specifier = ">=2.10.0" },
|
||||||
|
{ name = "sqlalchemy", extras = ["asyncio"], specifier = ">=2.0.0" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "idna"
|
name = "idna"
|
||||||
version = "3.11"
|
version = "3.11"
|
||||||
@@ -1443,6 +1464,7 @@ dependencies = [
|
|||||||
{ name = "fastapi" },
|
{ name = "fastapi" },
|
||||||
{ name = "fastmcp" },
|
{ name = "fastmcp" },
|
||||||
{ name = "httpx" },
|
{ name = "httpx" },
|
||||||
|
{ name = "hub-core" },
|
||||||
{ name = "llm-connect" },
|
{ name = "llm-connect" },
|
||||||
{ name = "nats-py" },
|
{ name = "nats-py" },
|
||||||
{ name = "psycopg2-binary" },
|
{ name = "psycopg2-binary" },
|
||||||
@@ -1468,6 +1490,7 @@ requires-dist = [
|
|||||||
{ name = "fastapi", specifier = ">=0.115.0" },
|
{ name = "fastapi", specifier = ">=0.115.0" },
|
||||||
{ name = "fastmcp", specifier = ">=2.0.0" },
|
{ name = "fastmcp", specifier = ">=2.0.0" },
|
||||||
{ name = "httpx", specifier = ">=0.28.0" },
|
{ name = "httpx", specifier = ">=0.28.0" },
|
||||||
|
{ name = "hub-core", editable = "../hub-core" },
|
||||||
{ name = "llm-connect", editable = "../llm-connect" },
|
{ name = "llm-connect", editable = "../llm-connect" },
|
||||||
{ name = "nats-py", specifier = ">=2.7.0" },
|
{ name = "nats-py", specifier = ">=2.7.0" },
|
||||||
{ name = "psycopg2-binary", specifier = ">=2.9.0" },
|
{ name = "psycopg2-binary", specifier = ">=2.9.0" },
|
||||||
|
|||||||
Reference in New Issue
Block a user