012 turned three descriptive columns into identifiers other systems
keep: in agent.json on a shop counter, in a saved URL, in a scheduled
report. All three were already treated as stable and none of it was
enforced.
- clients.slug is an MQTT topic segment the broker ACL is written
against. Rename one and that tenant's whole estate is silently refused
by the broker, with no way to tell the agents.
- sites.slug is what a shop PC calls itself - agent.json holds
"site_id": "chennai", never the uuid. A rename orphans the PC from the
shop it is standing in.
- site_cameras.camera_id lands in visits.camera_id, which is text and
not a foreign key. A rename orphans every visit already attributed to
the old name: the footfall is still there and no longer joins to a
camera. This was half-enforced in handleUpdateCamera and nowhere else,
which is the shape of a rule that holds until somebody adds a second
write path.
- visitors.number is assigned once from the tenant's counter and read
back as V-42.
A trigger, not a CHECK: a CHECK cannot see the old row and the rule is
about the transition. The DISPLAY name is deliberately not frozen -
"TeNext Chennai", "Front door" - it is what a person reads, nothing keys
on it, and a system that cannot fix a typo in a shop's name has confused
the two.
Also records why the uuid stays where a slug would do. The length was
never the problem; needing it was, and that is fixed. Replacing it would
touch eight foreign keys on a live database to shorten a field clients
are already told not to use, and a sequential id would make any future
tenancy hole walkable by counting. It is NOT because ids must be minted
offline - sites, visitors and visits are all created server-side with a
database in hand, and claiming otherwise would defend the status quo
rather than explain it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HViLj9gYNRtSr7YVZmW5sn