To handle editor navigation and support object links consistency Links to this object (key=backlinks) built-in relation is provided by Middleware. This relation handles a list of objects that have a link to the object the relation is set to.
Every time link from one object to another is created - besides setting Links from this object, new link is saved to the ObjectStore.
ObjectStore provides method SubscribeBacklinksUpdate that generates subscription on every links changes in store.
Special service backlinks.UpdateWatcher was designed to look after changes on links using backlinks subscription. On links change the service triggers StateAppend of target objects, that helps to:
- inject derived details of target object. Backlinks are retrieved from store on this step
- generate necessary events to notify dependent objects about details changes
All objects can have relation InternalFlags set to its details. This relation handles list of flags used mainly by client:
DeleteEmpty- stands for deletion of empty objects. Middleware performs object deletion on ObjectClose in case object has this internal flag.SelectType- stands for showing Type Picker on client-side.SelectTemplate- stands for showing Template Picker on client-side.
Client passes internalFlags value on object creation, and then the content of its value could be modified only by Middleware. However, it only deletes flags, and it deletes them on ALL commands where new state of object is applied EXCEPT these cases:
- ObjectApplyTemplate
- ObjectSetObjectType - deletes only
DeleteEmptyandSelectType - ObjectSetDetails - deletes only
DeleteEmpty - ObjectOpen
- ObjectClose
- BlockTextSetText - if no changes in block were made OR it is title or description block
In all other cases Middleware performs state Non-Emptiness check. And if state is not empty, it wipes internalFlags.
A state that either has no blocks or all blocks have no text inside. This definition is awful, because these kinds of objects would be deleted on closing:
- Object has no blocks filled, but a lot of details pre-filled by user
- Object has a lot of custom blocks that could not handle text
- Redesign
state.IsEmptycheck. Reasons are mentioned above - Think about moving
SelectTypeandSelectTemplateflags controlling logic to clients, because Middleware does not use these flags, but have very complex logic on its maintaining
Blank template is a virtual template for all kinds of objects, that could be chosen as default on client-side. Middleware does not have built-in template object to apply it on state on desired object, but understands literal blank as a value of templateId field of following commands:
- BlockLinkCreateWithObject
- ObjectCreate
- ObjectCreateSet
- ObjectApplyTemplate
If blank is chosen as templateId in one of first three commands, Middleware acts as no template was chosen at all and creates new object regarding remaining parameters of request.
If blank is chosen as templateId in ObjectApplyTemplate, Middleware creates applies new state, leaving only Type and Layout of previous state.
Some Object types and Relations are recognized as System ones, because application business logic depends on their content.
Examples of system types are Note, Task and Bookmark. Non-system - Contact, Goal and Feature.
Examples of system relations are Id, Name and Done. Non-system - FocalRatio, Instagram and HowToReproduce.
System types and relations could not be modified by the users or deleted from spaces. However, sometimes developers need to modify system objects to support some new features.
To handle system object update and save backward compatibility each system object type and relation has its own Revision.
Anytype will update system objects only if Revision of object from marketplace is higher than Revision of object from user's space.
- Update description of system object, that is stored in
pkg/lib/bundle - Increase
revisionfield of system type/relation or put"revision":1if it was empty - Generate go-level variables for new version of types and relations using
pkg/lib/bundle/generator - Make sure that new fields are taken into account in System Object Reviser.
(Only the fields listed in
systemObjectFilterKeysare checked, e.g. Revision, Name, IsHidden, IsReadonly, PluralName) - Build and run Anytype. All system objects with lower
Revisionshould be updated according your changes in all spaces
Bundled relations that are NOT system ones (e.g. AudioGenre) can be renamed in relations.json too,
but users are allowed to rename such relations in their spaces, so the reviser must not overwrite a user's own name.
The reviser therefore applies a bundled rename only if the installed relation still carries a previous bundled name.
- Change the
nameof the relation inpkg/lib/bundle/relations.json - Increase its
revisionfield or put"revision":1if it was empty — without this the rename never reaches existing spaces - Append the OLD name to
previousBundledRelationNamesin the System Object Reviser package - Regenerate go-level variables using
pkg/lib/bundle/generator
Only Revision and Name are revised on non-system relations, and the name is applied only when the local name
still equals one of the previous bundled names; any other local name is treated as the user's rename and kept.
Renamed system types and relations do not need previousBundledRelationNames entries: users cannot rename them,
so the system path applies the bundled name unconditionally (a revision bump is still required).
From the first millisecond of AccountSelect until every space has published its load result,
the middleware emits Event.Account.Recovery.Update (a recovery-scoped, monotonic event log) and
serves the folded Snapshot through AccountRecoveryState, both from one fold in
core/recovery. It covers every app open: a cold recovery on a fresh device, a warm start, and
a new account. The coarse phase (LookingForPeers -> Connecting -> FetchingAccount -> LoadingSpaces -> Done, with a calm WaitingForNetwork overlay and a terminal Failed) is the
headline; peers, the account fetch and per-space load states are the detail underneath.
Producers are advisory seams (peer observer, pull observer, space loader, tech-space head-sync)
that never affect control flow.
- Design: docs/superpowers/specs/2026-09-02-cold-sync-recovery-events-design.md
- Client integration: docs/RecoveryEventsClientIntegration.md