Keys identify facts and enforce uniqueness; relationships reference those identities with domain-specific update and delete behavior. Surrogate keys provide stable internal identity, while natural candidate keys still need constraints. Hierarchies require explicit choices about traversal, cycles, moves, depth, and consistency rather than a fashionable tree representation.
A key is a fact’s identity contract. “Unique today” is not enough; ask whether it changes, can be recycled, is known at creation, leaks information, or has tenant scope.
SignalDesk uses generated bigint internal IDs and unique tenant-scoped business keys such as (organization_id, email). A UUID can improve distributed generation and opacity, but it does not provide authorization and has index/locality tradeoffs. Preserve all real candidate keys with unique constraints even when the primary key is surrogate.
Relationship patterns:
The join table is a real relation and can carry authorship or ordering.
Knowledge categories can use an adjacency list: parent_id references the same table. It is simple for direct-parent writes and recursive reads, but cycle prevention and subtree operations need care. Materialized paths optimize ancestry/prefix operations but require path maintenance. Closure tables store all ancestor/descendant pairs and make reads fast at higher write/storage cost.
Choose from actual operations: maximum depth, move frequency, subtree queries, tenant scope, and consistency requirements.
Stable document, chunk, conversation, and tool-call identities are required for citations, deduplication, idempotency, and evaluation. A model must not invent or infer authorization from an opaque ID. Hierarchies used for knowledge scopes need cycle and tenant controls before they become retrieval filters.
Insert duplicate tag names within one tenant and across two tenants; only the same-tenant duplicate should fail. Try a cross-tenant ticket/tag assignment; it must fail. For a hierarchy, test root, leaf, move, maximum depth, and attempted cycle.
Model threaded message replies within a ticket using a self-reference that cannot point across tickets or tenants.
Acceptance criterion: valid replies work, cross-ticket and cross-tenant parents fail, and your traversal has deterministic order and a depth guard.