Skip to content

Integrate Ash UI with unified-ui ecosystem - #3

Merged
pcharbon70 merged 1 commit into
mainfrom
feature/governance-system-v2
Mar 19, 2026
Merged

pcharbon70 merged 1 commit into
mainfrom
feature/governance-system-v2

Conversation

@pcharbon70

Copy link
Copy Markdown
Collaborator

This PR updates Ash UI specs to integrate with the unified-ui ecosystem, positioning Ash UI as an Ash Framework integration layer rather than defining parallel UI concepts.

Summary

  • Rendering now delegates to external packages (live_ui, web_ui, desktop_ui)
  • Updated architecture shows Ash UI → canonical IUR → unified renderers flow
  • RFC-0002 proposes Ash UI as pure Ash integration layer (storage, authorization, data binding)
  • Simplified API for users (mount_ui_screen/3 helper)

Key Changes

Specs Updated

  • specs/contracts/rendering_contract.md - External renderer packages, IUR adapter
  • specs/contracts/control_plane_ownership_matrix.md - Delegated rendering authority
  • specs/contracts/compilation_contract.md - References canonical unified_iur format
  • specs/topology.md - Updated architecture diagrams
  • specs/rendering/README.md - Describes unified ecosystem integration

Guides Updated

  • guides/user/UG-0001-getting-started.md - Simplified API, unified-ui deps
  • guides/developer/DG-0001-architecture-overview.md - External renderer architecture

RFC Added

  • rfcs/RFC-0002-ash-ui-unified-integration.md - Proposes Ash UI as integration layer

Architecture

Ash UI (Ash Framework integration)
  ├── Stores unified-ui definitions as Ash Resources
  ├── Ash authorization (policies)
  ├── Ash actions (CRUD on UI)
  └── Data binding to Ash resources
         ↓
Unified UI Ecosystem
  ├── unified-ui: DSL, widgets, layouts, styling
  ├── unified_iur: Canonical format
  └── live_ui/web_ui/desktop_ui: Renderers

Related

- Update rendering_contract.md to delegate to external renderer packages (live_ui, web_ui, desktop_ui)
- Update topology.md to show Ash UI → canonical IUR → unified renderers flow
- Update control_plane_ownership_matrix.md to reflect delegated rendering authority
- Update compilation_contract.md to reference canonical unified_iur format
- Update guides to show simplified API (mount_ui_screen/3)
- Add RFC-0002 proposing Ash UI as pure Ash Framework integration layer

This positions Ash UI as an Ash-specific integration layer for the unified-ui
ecosystem, focusing on storage, authorization, and data binding while delegating
widgets, layouts, compilation, and rendering to the unified packages.
@pcharbon70
pcharbon70 merged commit 854b5a3 into main Mar 19, 2026
0 of 3 checks passed
ty13r added a commit that referenced this pull request May 18, 2026
…t binding allow-list

Authoring validator (`validate_element_binding_locality!` at
lib/ash_ui/resources/validations/authoring.ex:373) raises ArgumentError
"does not expose collection semantics" for any :list-typed binding on
Elements whose canonical widget_type isn't in @list_widgets ("list",
"table", "info_list", "select", "list_repeat").

`custom:*` opaque widget types are application-extension primitives
outside the canonical catalog (per Storage.canonical_widget_type at
lib/ash_ui/dsl/storage.ex:162). The validator can't know their
collection semantics and shouldn't gate the :list binding allow-list
on them; trust the authoring intent.

Conservative scope:
  - Bypass applies ONLY to "custom:*" string widget_types
  - nil widget_type (`ui_element` block missing entirely) still
    raises through downstream missing-element error paths
  - Canonical list-supporting widgets (`list`, `table`, etc.) remain
    the exclusive allow-list for non-custom Elements; row-template
    primitives like `:artifact_row` continue to belong INSIDE a
    `:list_repeat` parent that owns the list binding (per the
    Phase31RepeatListElement canonical pattern + Codex P2 #2 review)

Triggered by Wave AshUI-3.9 Item 2 dispatch (2026-05-17/18). The
original sizing investigation proposed adding `artifact_row` to
@list_widgets so destination Elements could hold :list bindings
directly; Codex P2 #2 review correctly pointed out that
:list_repeat is the canonical destination wrapper (not :artifact_row)
per the Phase31RepeatListElement test fixture. Per umbrella CLAUDE.md
"substrate gaps become our roadmap, not asks-of-Pascal" — the
`custom:*` bypass DOES belong here since the canonical catalog has
no opinion on opaque application types.

Per Codex P2 #3 review: the bypass is tightened to ONLY match
`"custom:*"` binary strings. Earlier draft included `is_nil(widget_type)`
which would have silently accepted bindings on Elements missing their
`ui_element` declaration entirely; that case should still surface
as a downstream missing-element error.

Test coverage:
  - Existing negative test (`:text` widget rejecting :list) still passes
    (regression check that the allow-list still gates unknown-bad types)
  - New positive test: `"custom:thread_card"` widget compiles with
    `binding_type :list`

The positive test uses a helper `assert_validator_accepts_list_binding`
that checks the SPECIFIC validator error is not raised; downstream
Ash domain-registration exceptions (which fire only AFTER the validator
we're testing passes) are acknowledged as proof the validator accepted.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ty13r added a commit that referenced this pull request May 18, 2026
…t binding allow-list (#113)

Authoring validator (`validate_element_binding_locality!` at
lib/ash_ui/resources/validations/authoring.ex:373) raises ArgumentError
"does not expose collection semantics" for any :list-typed binding on
Elements whose canonical widget_type isn't in @list_widgets ("list",
"table", "info_list", "select", "list_repeat").

`custom:*` opaque widget types are application-extension primitives
outside the canonical catalog (per Storage.canonical_widget_type at
lib/ash_ui/dsl/storage.ex:162). The validator can't know their
collection semantics and shouldn't gate the :list binding allow-list
on them; trust the authoring intent.

Conservative scope:
  - Bypass applies ONLY to "custom:*" string widget_types
  - nil widget_type (`ui_element` block missing entirely) still
    raises through downstream missing-element error paths
  - Canonical list-supporting widgets (`list`, `table`, etc.) remain
    the exclusive allow-list for non-custom Elements; row-template
    primitives like `:artifact_row` continue to belong INSIDE a
    `:list_repeat` parent that owns the list binding (per the
    Phase31RepeatListElement canonical pattern + Codex P2 #2 review)

Triggered by Wave AshUI-3.9 Item 2 dispatch (2026-05-17/18). The
original sizing investigation proposed adding `artifact_row` to
@list_widgets so destination Elements could hold :list bindings
directly; Codex P2 #2 review correctly pointed out that
:list_repeat is the canonical destination wrapper (not :artifact_row)
per the Phase31RepeatListElement test fixture. Per umbrella CLAUDE.md
"substrate gaps become our roadmap, not asks-of-Pascal" — the
`custom:*` bypass DOES belong here since the canonical catalog has
no opinion on opaque application types.

Per Codex P2 #3 review: the bypass is tightened to ONLY match
`"custom:*"` binary strings. Earlier draft included `is_nil(widget_type)`
which would have silently accepted bindings on Elements missing their
`ui_element` declaration entirely; that case should still surface
as a downstream missing-element error.

Test coverage:
  - Existing negative test (`:text` widget rejecting :list) still passes
    (regression check that the allow-list still gates unknown-bad types)
  - New positive test: `"custom:thread_card"` widget compiles with
    `binding_type :list`

The positive test uses a helper `assert_validator_accepts_list_binding`
that checks the SPECIFIC validator error is not raised; downstream
Ash domain-registration exceptions (which fire only AFTER the validator
we're testing passes) are acknowledged as proof the validator accepted.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant