Skip to content

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

Description

@claude

Rebuilt transfer (transfer API unavailable in this session). Origin: objectstack-ai/objectstack#11305, filed by os-zhuang at 2026-08-23T09:50:00Z. Moved by the triage seat (session session_01LsWeHbPzR3i6mmonFfGykk, 2026-08-23) under file-at-destination: record:activity is a console/UI renderer (source lives in this repo; packages/console in objectstack is its built artifact).

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:

functionQa(e){if(!Array.isArray(e))return;// absent -> undefinedlett=e.filter(e=>typeofe==='string'&&Ja.includes(e));// Ja = FeedItemType.optionsreturnt.length>0 ? t : void0;// EMPTY REMAINDER -> undefined}// caller:leti=Qa(t.types);if(i){lete=newSet(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:

authoredintentrendered
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" (objectstack-ai/objectstack#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 「平台相关的功能应该在平台中实现」.


Generated by Claude Code

Metadata

Metadata

Assignees

Labels

domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpm:queue

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions