Modelled on HubSpot's custom properties: the definition lives in a table, the values live in each record's existing JSON attributes. Adding a field is an INSERT, so it can happen mid-conversation through MCP and the next record can use it immediately. The cost of that is that the database enforces nothing about the values, so data_type is enforced in application code and every write path has to come through it — otherwise the type on a definition is decoration. Values are coerced rather than merely checked, because callers are agents and HTTP clients and "42" is a number expressed loosely; what is rejected is genuinely ambiguous, like "quite large" for a number. A value whose property has no definition is rejected rather than stored. A typo sitting in the database looks exactly like data, and a registry whose set of fields is not actually the set of fields is worse than none. Workspaces with nothing defined keep the old free-form behaviour, so this does not break attributes already in use. name and data_type are not updatable: renaming orphans every value stored under the old key, and retyping leaves values that no longer satisfy the type. Deleting a definition leaves existing values alone rather than rewriting every record, so undoing a mistaken delete is just recreating the property. Two ways in, sharing one validator: a logged-in person, and an integration key for MaskanX. An agent gets no shortcut around the rules a person is held to. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
27 lines
672 B
Python
27 lines
672 B
Python
from fastapi import APIRouter
|
|
|
|
from app.api import (
|
|
activities,
|
|
auth,
|
|
campaigns,
|
|
catalog,
|
|
contacts,
|
|
dashboard,
|
|
integrations,
|
|
properties,
|
|
leads,
|
|
)
|
|
|
|
api_router = APIRouter(prefix="/api/v1")
|
|
api_router.include_router(auth.router)
|
|
api_router.include_router(dashboard.router)
|
|
api_router.include_router(contacts.router)
|
|
api_router.include_router(leads.router)
|
|
api_router.include_router(activities.router)
|
|
api_router.include_router(catalog.router)
|
|
api_router.include_router(campaigns.router)
|
|
api_router.include_router(properties.router)
|
|
api_router.include_router(properties.integration_router)
|
|
api_router.include_router(integrations.router)
|
|
|