Skip to content

lint: filter-token-unknown never walks flows — an unresolvable {TOKEN()} in a flow node's config.filter is silent, while the identical string in a view filter exits 1 #16096

Description

@os-steve

Measured on the pinned @objectstack/lint@17.3.0 artifact as installed by objectstack-ai/hotcrm, ⛔ not on the platform source tree. Filed unassigned by the hotcrm step-3 rule survey (hotcrm#1613); the local assertion covering the flow surface stays in place there.

The gap

validateFilterTokens walks a fixed root list:

[ { key: "objects", kind: "object" },
  { key: "views",   kind: "view" },
  { key: "reports", kind: "report" },
  { key: "datasets",kind: "dataset" },
  { key: "pages",   kind: "page" },
  { key: "apps",    kind: "app" } ]

flows is not in it. A flow node's config.filter is a filter in every sense that matters — it is handed to the data engine and it decides which rows a sweep touches — but no root reaches it, so classifyFilterToken is never called on those strings.

The rule's own message says what the cost is: "It is sent to the data engine as a literal string, matches no record, and the surface renders empty." On a scheduled sweep there is no surface to render empty. The sweep simply acts on nothing, nightly, at exit 0.

Measurement, with a working control

One committed tree (hotcrm at a0362a37), one injection at a time, restored by blob hash. Clean-tree baseline: 0 error(s), 17 warning(s), 12 suggestion(s), exit 0. The same token string in both rows.

where '{TOMORROW()}' was injected pnpm lint
controlsrc/views/account.view.ts, a list view's filter[].value filter-token-unknown error, exit 1
src/flows/opportunity-stagnation.flow.ts, the query_stalled node's config.filter nothing fires — 17 warnings, exit 0, byte-identical to baseline

Same command, same run design, same string. The control fires, so the second row is a reading about the walk's roots.

{TOMORROW()} is genuinely unresolvable on this pin: it is not a context token and not a date macro, and the view-side finding names it as such.

Why this one is sharper than it looks on hotcrm

That repo already carries test/flow-filter-today-token.test.ts, which exists because {TODAY()} in a flow filter changed meaning under it at the rc.5 to rc.6 bump (hotcrm#1107). The answer there was that the flow template engine resolves TODAY() before ObjectQL sees it — so flow filters have their own token vocabulary, resolved by a different layer than the one classifyFilterToken knows. That is a good reason for the flow surface to need its own treatment; it is not a reason for it to have none.

A token the flow template pre-pass does not consume reaches ObjectQL verbatim, and one neither layer knows fails the run rather than querying. Both of those are run-time outcomes with no author-time signal.

Suggested direction, not a prescription

Adding { key: "flows", kind: "flow" } to the root list is the obvious shape, but ⚠️ it is very likely wrong as-is: it would immediately red every legitimate {TODAY() - 45} in every sweep, because those are resolved by the automation template evaluator and not by the filter-token vocabulary. Whatever lands needs the flow token grammar as its reference set, not the ObjectQL one — which is why this is filed as a finding for the owner to scope rather than as a one-line fix.

Related, and why this is not a duplicate

Refs: hotcrm#1613 · hotcrm#1582 (F1) · hotcrm#1583 (F2) · hotcrm#1584 (F3) — filter-token-unknown is claimed by three of the six family cards, and the flow-surface half is unreachable for all of them.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions