Skip to content

user-state-persistence.md's storage-model section documents a user_app_state object keyed by kind — the shipped adapter uses sys_user_preference keyed by key #5950

Description

@os-warren

Found while clearing content/docs/guide/user-state-persistence.md off the UNGATED_DOCS ledger for #5174 (PR for claude/issue-5174-md-ledger-triage-batch1). Filed unassigned. The ts block on that page is fixed there — it is a snippet-compile defect, which is that card. The prose and the yaml block are not, and no gate reads them.

What

createObjectStackUserStateAdapter's real options (packages/data-objectstack/dist/index.d.ts, interface ObjectStackUserStateAdapterOptions):

dataSource: DataSource<any>;
userId: string;/** Storage key. Should be a dotted, namespaced string … Examples: * `ui.favorites`, `ui.recent`, `ui.grid.account.state`. */
key: string;/** Override the storage object name. Defaults to `"sys_user_preference"`. */
resource?: string;
onError?: (where: 'load'|'save',error: unknown)=>void;

And packages/data-objectstack/src/userState.ts:6-10 states the choice outright — the parallel table was considered and rejected:

Using the existing sys_user_preference table (rather than a parallel user_app_state table) keeps things consistent with the platform's …

The guide documents the rejected design. Still on the page after the snippet fix:

  • :93 — "The official adapter stores one row per (user_id, kind) pair holding the full list as a JSON blob."
  • :95-109 — a ```yaml block declaring an object with a kind field and `unique: [user_id, kind]`.
  • :116find('user_app_state', { filter: { user_id, kind }, limit: 1 }).
  • :188, :205 — "One JSON blob per (user, kind)", "kind: 'favorites'".

packages/data-objectstack/src/userState.test.ts pins the real calls against 'sys_user_preference' at :41, :143, :165, :216, :240, :266, :293.

Not the whole page is wrong

kind is a real word elsewhere on the page: useUserStateAdapter(kind) (:178) is a genuine @object-ui/app-shell API taking a slot kind. The drift is specifically the storage model — the object name, the field name, and the uniqueness constraint. Whoever takes this should re-read the adapter rather than sed kindkey.

What was already fixed, so this issue is not the whole thing

The page's one typescript block used kind: 'favorites' / kind: 'recent' as adapter options. That is a compile error against the real ObjectStackUserStateAdapterOptions (TS2353: 'kind' does not exist in type …) and it is corrected to key: 'ui.favorites' / key: 'ui.recent' in the #5174 batch, along with the missing useEffect import and the untyped dataSource parameter. The page now compiles and left the ledger. The prose did not move, so the page is internally inconsistent until this is done — an improvement over being uniformly wrong, but worth closing out.

Why not folded into #5174

Different defect class. #5174 is snippet coverage: check-doc-snippet-types.mjs reads ts / tsx fences only, and a ```yaml block plus surrounding prose is invisible to it and to check-doc-component-types. Fixing it needs a reading of the adapter's storage contract, not a snippet triage — and it would have made the batch diff unreviewable.

Reachability

Documentation only, but of the load-bearing kind: a reader following this page would model their backend object on user_app_state with a kind column and find the shipped adapter writing to sys_user_preference with a key.

Related: #5174 (the ledger batch that surfaced it), #5160.

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentationdomain: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