Files
maskanx_crm_frontend/app/api/router.py
T
AFFAANhandClaude Opus 5 9d6aa64ad6 feat(properties): add custom fields without a migration
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>
2026-08-04 11:07:50 +05:30

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)