activity-tenant-indexrun.mdlane/output/notes.mdactivities collection's index set differs: one index is
added, none dropped, none altered. Reads return the same documents in the same
order; the planner simply gets a seek where it had a scan.packages/services/src/db/models/activity.ts: added
ActivitySchema.index({ tenantId: 1, createdAt: -1 }) with a comment
cross-referencing the migration. Every read of activity is tenant-scoped
(tenantPlugin injects tenantId), but no index led with tenantId — they led
with leadId / userId / performedBy — and the plugin's own { tenantId: 1 }
fallback never fires because activity.ts declares tenantId explicitly. So the
tenant-wide feed (ActivityService.findRecent —
find({ tenantId }).sort({ createdAt: -1 }).limit(n)) had nothing to seek on.
ESR: the tenantId Equality field first, the createdAt Sort last.packages/services/src/db/migrations/1784500000000-add-activities-tenant-index.ts:
creates the same index on the live activities collection via the raw driver
(connection.collection(...), never the model). Auto-applies on merge via
.github/workflows/db-migrate.yaml. createIndex is idempotent for an identical
key, so a re-run is a no-op.down drops tenantId_1_createdAt_-1 and nothing else — up dropped
nothing, so there is nothing to recreate. The drop tolerates an already-absent
index, so a partial re-run converges. Reverting the schema line alone is also
safe: an index that exists in Mongo but not in the schema is inert.The other activities indexes stay as they are. { leadId, createdAt: -1 },
{ userId, createdAt: -1 } and { performedBy, createdAt: -1 } are also not
tenant-leading, and the single-field { leadId } / { userId } indexes declared
inline on the schema paths are redundant prefixes of their own compounds. Folding
tenantId into those three and retiring the redundant singles is a real
improvement, but it means dropping live indexes — that needs $indexStats evidence
over a representative window (see db-auditor) and is its own chore, not a
free-rider on this one.
The sandbox can't reach MongoDB (TCP 27017 blocked), so the migration was not run
locally. It did run for real on the PR: the Migrate preview database job
(db-migrate.yaml) applied it against the preview DB and passed, which confirms
the collection name (activities) and the up body. Migrate production
database is correctly skipped until merge. Audit database is green — the
missing-tenant-index finding for activities no longer fires. Format / lint /
typecheck ran in Quality Project, green.