Skip to Content

← All archived runs

Run: activity-tenant-index

run.md

Run: activity-tenant-index

  • lane: chore
  • branch: claude/activity-tenant-index-migration-glxfnu
  • pr: #758

lane/output/notes.md

Chore: activity-tenant-index

  • invariant: behaviour unchanged for every persona — no query, service, route or UI is touched. Only the activities 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.
  • change: 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.findRecentfind({ tenantId }).sort({ createdAt: -1 }).limit(n)) had nothing to seek on. ESR: the tenantId Equality field first, the createdAt Sort last.
  • change: 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.
  • rollback: 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.

Not done here (deliberately)

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.

Verification

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.