Skip to content

/forms/:name publishes current_user but not features, so a features.* predicate still resolves differently there than inside an app #6262

Description

@yinlianghui

Found while implementing objectui#6110 (PR #6261). Recording only — not graded, no domain:*, unassigned.

Measured on objectuiorigin/main @ cbc883960 plus PR #6261's branch.

What #6110 changed, and the half it deliberately left

#6110 found that the authed internal form route /forms/:name had noExpressionProvider above it at all — the console mounts one only in AppContent (the /apps/:appName/* subtree) and in app-shell's RecordFormPage. Its fix mounts the provider in InternalFormRoute with the session principal:

<ExpressionProvideruser={expressionUser}>

ExpressionProvider publishes four scope roots — user (as current_user + the ADR-0068 user / ctx.user / os.user aliases), app, data and features. #6110 supplies only user, so on /forms/:namefeatures is {}.

Why that is a real asymmetry rather than a default

AppContent fills features from /api/v1/auth/config (getAuthConfig()), and the flags are already load-bearing for predicate evaluation elsewhere — ExpressionProvider's own docstring names sys_organization's create button being hidden when multiOrgEnabled === false. So an authored predicate naming features.multiOrgEnabled:

  • inside /apps/:appName/* — resolves against the real flags;
  • on /forms/:name — names an unbound key, which faults, and visibleWhen fails OPEN, so the gated field/section is shown to everyone.

That is the same shape as #6110's own defect, one scope root over: one authored text, two verdicts depending on which route opened the form.

app is likewise {} there, though that one is arguably correct by construction — /forms/:name names no app, which is exactly why InternalFormRoute renders HomeLayout rather than ConsoleLayout (see that file's comment and objectui#4109).

Why it was not fixed in #6110

Out of that card's scope by its own words (it names current_user), and it is not a one-line addition: features requires an /auth/config fetch on a route that currently makes none, plus a decision about what a predicate should see before that fetch resolves. ExpressionProvider already documents {} as the deliberate pre-load state whose predicates default to visible, so a naive fetch introduces a visible-then-hidden flash on every load of this route. PR #6261 records the gap in FormPage.tsx's own comment rather than papering over it.

Not yet measured

Whether any shipped form-view metadata actually authors a features.* predicate. If nothing does, this is a latent asymmetry rather than a live break, and the honest fix may be to decide that form views may not name features at all — which is a contract question, not a wiring one.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatneeds-user-decision

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions