Skip to content

record:activity widens on a bad types filter: an unrecognised or empty kind list renders EVERY activity, not none #11305

Closed as not planned

Description

@os-zhuang

record:activity sanitises its own types prop and turns an unrecognised or empty filter into no filter — so an author who names the wrong kind is served every activity on the record, with no diagnostic anywhere at runtime.

Measured

Executed out of the shipped bundle (@objectstack/console 17.1.0, dist/assets/plugins-views-BaBStVok.js) — this is the renderer's own code, not a reimplementation:

function Qa(e){
  if(!Array.isArray(e)) return;                                    // absent  -> undefined
  let t = e.filter(e => typeof e === 'string' && Ja.includes(e));   // Ja = FeedItemType.options
  return t.length > 0 ? t : void 0;                                // EMPTY REMAINDER -> undefined
}
// caller:
let i = Qa(t.types);
if (i) { let e = new Set(i); r = r.filter(t => e.has(t.type)); }    // undefined => no filter at all

Running it over a record's feed:

Qa(undefined)      = undefined      -> unfiltered
Qa([])             = undefined      -> unfiltered
Qa(["crm_task"])   = undefined      -> unfiltered      <- every member unrecognised
Qa(["task"])       = ["task"]       -> filtered

So three distinct authored intents collapse into one rendering:

authored intent rendered
types omitted "show every kind" every kind
types: [] "show no kind" every kind
types: ['crm_task'] "show this kind" (typo/wrong vocabulary) every kind

Why this is worth closing rather than documenting

PageComponentSchema.properties is an open bag (z.record(z.string(), z.unknown())), so nothing rejects the value on the storage path — build says exactly that beside its own author-time warning: "the props bag is not parsed on the storage path either, so nothing rejects this today" (#5068). That is the known half. The half this card is about is what happens after: the renderer does not merely ignore the bad value, it widens on it. A tolerant consumer is where a wrong authored value hides and spreads, and here it hides behind a plausible-looking result — a populated timeline — rather than an empty one an author would investigate.

Measured consequence in a real app: HotCRM's lead page authored types: ['crm_task'] (an object name where a feed kind belongs) and its Activity tab rendered the audit stream — Created Lead … / Updated Lead … — for as long as it shipped. The author-time warning existed and was one of 85; nothing at runtime said anything at all. (objectstack-ai/hotcrm#1209)

Suggested direction

Two independent decisions, both consumer-side tolerance to remove:

  1. Unrecognised members must not widen. Either keep only the recognised members and filter on those (an all-unrecognised list then renders empty — visibly wrong, which is the point), or drop the whole component to an error state. Silently falling back to "everything" is the one behaviour that cannot be noticed.
  2. types: [] should mean what it says. If "no kinds" is not an intent worth honouring, reject it at the schema (.min(1)) rather than reinterpreting it at render time — declared = enforced.

The same question probably applies to filterMode, whose sanitiser (Za) folds any unrecognised value to 'all' — the widest option, again.

Found while fixing objectstack-ai/hotcrm#1209; not worked around there, per 「平台相关的功能应该在平台中实现」.

Activity

  1. claude commented on Aug 23, 2026

    @claude
    Contributor

    Moved to objectstack-ai/objectui#5841 (rebuilt — the transfer API is unavailable in this session). Triage rationale, file-at-destination (maintainer 2026-08-10 ruling): record:activity is a console/UI renderer whose source lives in objectui (packages/console here is its built artifact; the measurement itself was taken from the shipped console bundle). Body rebuilt verbatim with a provenance header; bare issue refs expanded to full names. Closing this copy as moved — all further state lives on the objectui card. Triage seat, session session_01LsWeHbPzR3i6mmonFfGykk.


    Generated by Claude Code

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions