Appearance
Database Mutations
This page documents every MongoDB write operation performed by the server, grouped by collection and command. It covers all cases where data is inserted, updated or hard-deleted — including entity lifecycle (create, edit, duplicate, delete), property management, account bootstrapping, passkey registration and Stripe billing updates.
The data model separates raw input from computed views: field values are written to the property collection as individual records and never overwritten — when a value changes, the old record is soft-deleted and a new one is inserted. The entity collection stores only the aggregated denormalized document (rebuilt after every mutation) and acts as the primary read target.
Collection: entity
insertOne({})
Called by:
POST /api/[db]/entity— creates a new entityPOST /api/[db]/entity/[_id]/duplicate— once per requested copyPUT /api/[db]— once per seed entity during account bootstrap
Inserts a blank entity document that serves as an ID anchor. Its actual field values are stored as individual records in the property collection and later denormalized back onto the entity via aggregation.
replaceOne({ _id }, newEntity, { upsert: true })
Called by: every mutation, via aggregateEntity() in server/utils/aggregate.js
Recomputes the full denormalized public/private views from raw properties and replaces the stored entity document.
updateMany({ _id: { $in: ids } }, { $set: { queued: now } })
Called by: any deletion or reference change, via addAggregateQueue() in server/utils/aggregate.js
Marks related entities for re-aggregation by the background worker after a change propagates to them.
deleteOne({ _id: entityId })
Called by: aggregateEntity() in server/utils/aggregate.js
Permanently removes the entity document when aggregation detects a _deleted property on it.
Collection: property
insertOne(property)
Called by:
DELETE /api/[db]/entity/[_id]— inserts{ entity: entityId, type: '_deleted', reference: user, datetime: now, created: { at: now, by: user } }POST /api/[db]/entity— one per submitted property + auto_ownerand_createdPOST /api/[db]/entity/[_id]— one per submitted propertyPOST /api/[db]/entity/[_id]/duplicate— one per copied property per duplicatePOST /api/[db]/passkey— inserts{ type: 'entu_passkey', passkey_id, passkey_public_key, passkey_counter }POST /api/stripe— one per billing property updated from the Stripe webhook
Appends a new property record to an entity. Existing values are never overwritten — old ones are soft-deleted instead.
insertMany(properties)
Called by: PUT /api/[db]
Bulk-inserts all property records for each seed entity during account bootstrap.
updateMany({ _id: { $in: oldPIds } }, { $set: { deleted: { at, by } } })
Called by: any setEntity() call that replaces existing values, via markPropertiesDeleted() in server/utils/entity.js:
POST /api/[db]/entity/[_id]POST /api/[db]/entity/[_id]/duplicatePOST /api/[db]/passkeyPOST /api/stripePUT /api/[db]
Soft-deletes the superseded property records when values are replaced, preserving the full history.
updateOne({ _id: propertyId }, { $set: { deleted: { at, by } } })
Called by: DELETE /api/[db]/property/[_id]
Soft-deletes a single specific property value. The record stays in the DB for audit purposes.
updateMany({ reference: entityId }, { $set: { deleted: { at, by } } })
Called by: DELETE /api/[db]/entity/[_id]
Soft-deletes all properties across all entities referencing the deleted entity, preventing stale references.
updateMany({ entity, type: 'entu_passkey', passkey_id }, { $set: { passkey_counter } })
Called by: POST /api/auth/passkey
Increments the WebAuthn signature counter after a successful passkey authentication to detect cloned authenticators.
updateMany({ reference: oldOid }, { $set: { reference: newId } })
Called by: PUT /api/[db]
After bulk import, rewrites all reference values from legacy OIDs to the new MongoDB ObjectIds assigned at import time.
deleteMany({ reference: { $nin: allEntityIds } })
Called by: PUT /api/[db]
Hard-deletes property records whose reference target no longer exists, keeping data consistent after DB creation or import.
