A spine, and no engine
There is a cadence table and a pure resolver. Nothing sends anything.
Sequences — multi-step automated outreach with enrolment rules, send windows and reply detection — are a standard part of what the general-CRM category advertises, and for a lot of teams they are the reason to buy one. We do not have that. What we have is the layer underneath it, and the distinction is the whole point of this section.
What exists: a cadence table in the database, scoped to a school and protected by row-level security. A pure resolver that takes a cadence definition and returns its steps in order, with a rule that refuses a definition containing duplicate step identifiers rather than resolving it into something ambiguous. A sequence step type registered in the notification rail’s own vocabulary. Isolation tests over both, proving the tenant wall at the database rather than in the application.
What does not exist: any endpoint that runs a cadence. Any screen that builds one. Any caller, anywhere in the application, of the resolver — we searched the whole application for it and found none, and the same search demonstrably reaches that package for other purposes, so the zero is an absence rather than a broken search. There is no scheduler, no enrolment, no send. Nothing sends anything.
So on the honest board earlier in this page, every row is at least a registered handler with no screen. The cadence spine sits one rung below that: it has no handler at all. Which is why it is not counted in that table, and why the comparison row for sequences is conceded outright rather than hedged into a partial win.
The correction, because it is the most useful thing on this page
The first draft of this section said something different and stronger: that the whole idea was absent from the codebase, verified two ways. That was true when it was measured. Two commits landed while this page was being written, and it stopped being true — and nothing about the sentence would have looked wrong to a reader.
That is the specific way a technical claim goes bad, and it is worth naming because it is not lying. It is a true statement with the scope quietly stripped off: at tip is a property of a measurement, not of a claim, and the tip moves. So the fix is not to write more carefully. The fix is to measure again before shipping the sentence, which is what happened here, and to publish the correction rather than silently swapping the paragraph. If you find something on this page that does not match the code, that is the response you should expect.