One identity for an object across organizations
Many organizations describe the same real-world things, and each numbers them on its own. A company has a number in the commercial register and another id in every database that lists it. My question is how such an object keeps one identity while the records about it change and contradict each other. This page states the model I use for a client’s information platform. Same-as links are a design I am developing, and the rest is in production use.
One id space
Every object has one id, and that id belongs to nothing else. One allocator draws from one sequence and skips every number that an object or an assertion already holds. An entity is created object first: the object row and its assertions are written in one transaction.
An id that is unique only within its table is ambiguous as soon as a second table holds ids of the same kind. The price of one id space is a central allocator that every writer depends on.
Versions belong to the object
An edit creates a version of the object, and the object row stays the same. Every relation, URL, permission check and search document uses the object id to mean the thing itself.
The version boundary is the complete mutation: one editor submit or one import item creates at most one version. A rollback is a new version too, so the history only grows.
Storage sees many row writes for one change, and a history cut at that level is unreadable for the person who made it. I define the version by the mutation a user sees, and the tests assert how many versions it creates.
Relationships are objects
A relationship such as the role of a person in a company is often a data row owned by one of its endpoints. Such a row has no identity and cannot be versioned or retired alone.
I model each relationship family as an object type. A relationship has its own id and its own versions, and its two endpoints are assertions on it. A contract between two companies can end while both continue, and that end is a version of the contract. The cost is more objects and one more join on every traversal.
Register codes are the shared key
An internal id means nothing to a statistics office. Both sides hold the register code. My rule is one datatype per register and per administrative tier. The code stays a string end to end, because a leading zero is part of it.
Two limits apply to what a code proves. Registers reuse codes, so a code that names one place in one edition can name another place in the next. A shared identifier is weak evidence for a merge, because records that share an identifier or a web link often differ in a basic fact. It only generates a candidate for the de-duplication review.
Same-as links
A same-as link asserts that two objects denote one real-world entity, in the strict sense of owl:sameAs. Both objects keep their ids and histories, so withdrawing a link is one change. Only accepted, published links enter the identity closure.
Confidence is a value on one assertion and is not transitive: a score for A and B and a score for B and C yield no score for A and C. Hard vetoes run before acceptance, and no score overrides them. A veto is a contradiction between the two objects, such as a dissolved company and an active one.
What is open
Source records are the first open part. An external record such as a Wikipedia page or a register entry gets a stable identity and is joined to the canonical object by a source-description link. Same-as is excluded there, since a page about a company and the company are different resources.
The second open part is a journal of merges and splits with an unmerge operation. OWL equality guides the semantics without an RDF store or a reasoner, and PostgreSQL is the canonical store.