- Add proto schemas in packages/shared-types/events/ (oo.events.v1): envelope.proto, signals.proto, integration.proto - buf.yaml with STANDARD lint + FILE breaking-change rules - .gitea/workflows/buf-check.yaml: lint + breaking check on every PR touching events/ (needs a Gitea Actions runner to execute) - scripts/buf-check.sh: local equivalent of the CI check - NormalizedEvent TS envelope gains eventId, schemaVersion, producer to align with the proto Envelope message - ml/serving/schemas.py: pydantic models mirroring the v1 proto types - nats_consumer.py: validate payloads via pydantic instead of raw .get() A field-rename PR will now fail buf breaking with exit code 100 and show the offending messages. To make a breaking change: keep the old field reserved, add the new one, bump schema_version to v2. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
51 lines
1.0 KiB
Python
51 lines
1.0 KiB
Python
"""
|
|
Pydantic models mirroring oo.events.v1 proto schemas.
|
|
|
|
Field names use camelCase to match the proto3 JSON mapping convention
|
|
and the TypeScript payload shapes published by services/api.
|
|
|
|
Keep in sync with packages/shared-types/events/oo/events/v1/.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from typing import Literal, Optional
|
|
from pydantic import BaseModel
|
|
|
|
|
|
class TaskSyncedPayload(BaseModel):
|
|
userId: str
|
|
source: str
|
|
count: int
|
|
syncedAt: str
|
|
|
|
|
|
class TipServedPayload(BaseModel):
|
|
userId: str
|
|
tipId: str
|
|
policy: str
|
|
servedAt: str
|
|
|
|
|
|
class TipFeedbackPayload(BaseModel):
|
|
userId: str
|
|
tipId: str
|
|
action: Literal['done', 'dismiss', 'snooze', 'helpful', 'not_helpful']
|
|
reward: float
|
|
dwellMs: Optional[int] = None
|
|
createdAt: str
|
|
|
|
|
|
class TipRewardFailedPayload(BaseModel):
|
|
userId: str
|
|
tipId: str
|
|
reward: float
|
|
attempts: int
|
|
error: str
|
|
failedAt: str
|
|
|
|
|
|
class IntegrationTokenExpiredPayload(BaseModel):
|
|
userId: str
|
|
provider: str
|
|
detectedAt: str
|