Skip to Content
Living documentation — last reviewed 2026-05-28
FeaturesInsightsInsights — QA Plan

Insights — QA Plan

Auth

StepExpected
Non-member calls GET /insights403 — requireMembership throws.
Coach role calls403 — role check.
Member role calls403.
Owner / admin calls200 with insight array (possibly empty).

Empty state

StepExpected
Org with no cancellation requests, no debt, no past-due members, no overdue tasksResponse is { data: [] }.

Rule — finance.cancellation_requests

StepExpected
2 pending cancellation requests, 0 scheduledInsight returned, count = 2, severity warning, meta.pending = 2, meta.scheduled = 0.
0 pending, 5 scheduled (subscriptions with cancel_at_period_end = true)count = 5, severity info.
3 pending + 5 scheduledcount = 8, severity warning.
Deleted subscriptions with cancel_at_period_end = trueExcluded from the count.

Rule — finance.outstanding_debt

StepExpected
One member with debt 1200 centscount = 1, meta.totalDebtInCents = 1200, severity warning.
Five members totaling 100k cents debtcount = 5, meta.totalDebtInCents = 100000.
Subscription with debt = 0Excluded.
Deleted subscription with debt > 0Excluded.

Rule — members.at_risk_billing

StepExpected
0 past-due membersRule returns null; insight not in array.
1 past-due membercount = 1, severity info, sample contains that member.
5 past-due membersseverity warning.
15 past-due membersseverity urgent.
Sample sizeCapped at 3, ordered by name ascending.
Member with NULL nameSample entry has name: null, email always present.

Rule — operations.tasks_overdue

StepExpected
Task with due_date < today, not completedInsight returned.
Task due_date = todayNot overdue (strict less-than).
Completed task with past due dateNot counted.

Ordering

StepExpected
Org has urgent at-risk billing + warning debt + info cancellationsOrder: at-risk → debt → cancellations.
Tied severitiesHigher count comes first.

Agent surface

StepExpected
Prompt: “anything I should look at?”Spotter calls analytics.org_insights, returns the same payload, summarizes in prose.
Prompt as a coachTool returns 403; agent surfaces “Sorry, that’s owner/admin only.” (verify via integration test).

Performance

  • 500-member org with realistic data → response < 150ms p95.
  • Re-running the same query 100 times in a loop → no rule slowdown (indexes cold-hit warm-hit ratio acceptable).

Negative

  • Force one rule to throw (mock the DB) → API returns 500. Document this as a current limitation; rules are not per-rule isolated.
  • Org id that does not exist → returns [] (empty arrays from each rule).