Skip to content

Analytics/dashboard query path resolves no user token — personal ("my …") dashboard widgets are impossible #510

Description

@yinlianghui

Split out of #491 so the platform-level gap is visible on its own and leadership can decide whether to (re-)escalate it to the upstream runtime repo. This is an upstream limitation, not app metadata.

The gap

The list-view data path (/api/v1/data/..., platform-objects) resolves {current_user_id} in filters — the "My Leads / My Tasks / My Deals" list views all work. The analytics path (dashboard widgets / dataset reports, /api/v1/analytics/...) resolves no user token at all: the literal string reaches the SQL WHERE, matches no owner, and the widget renders 0 for every viewer.

This was proven empirically before #491 and is documented in src/apps/crm.app.ts (My Work group note): a "My Day" dashboard was built and removed after a side-by-side test on one dashboard — {current_user} → 0, {current_user_id} → 0, no owner filter → 10,100,081. That note says "Filed upstream", but no issue link was recorded — hence this tracking issue.

(For contrast, the same analytics path DOES resolve the DATE_MACRO_TOKENS vocabulary — verified during #491 via the generated SQL in analytics responses — so this is specifically about user tokens.)

⚠️ The headline above is not quite the mechanism, per the upstream review of objectstack#12376. Token resolution had already landed in @objectstack/core after 17.1.0; what actually produced the measured 0 was two narrower holes — the direct AnalyticsService.query / generateSql door resolved nothing (so the SQL strategy bound the literal while the ObjectQL strategy resolved via the engine), and the dataset-scope channel handed strategies an unresolved copy of the filter which was ANDed beside the resolved one, producing an unsatisfiable owner = $viewer AND owner = '{current_user_id}'. That second one is why the shape was a hard 0 rather than a partial result. The defect was real; the one-line diagnosis in this card was incomplete.

Impact on this app

To close this issue

Once the Restart-when: predicate above is met, restore the personal widget on the service_dashboard table widget and retitle it back to "My Open Cases by Priority".

⚠️ Use owner_id, not owner. Since #548/#677 the owner column no longer exists and the spelling in the original instruction fails with no such column: owner (measured). Copying that line verbatim will misfire.

⭐ Two behaviour changes arrive with the fix, and both help: an unresolvable placeholder now refuses loudly (FILTER_TOKEN_UNKNOWN / FILTER_TOKEN_UNRESOLVED, HTTP 400) instead of charting a plausible zero — so a broken restore will look like an error rather than an empty widget — and the {current_user} misspelling this card records is now caught with a near-miss suggestion rather than silently rendering 0.

⚠️ Verify the restore by having two different reps see different rows. {current_user_id} is presentation scope, not an access boundary — that is the frozen vocabulary's own declaration (objectstack#3594). Row-level security owns the guarantee that one rep cannot reach another's cases; this token only scopes what a widget shows.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingpriority:p2Medium: important, M3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions