@praxisui/page-builder 9.0.47 → 9.0.48

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -86,6 +86,11 @@ All omitted `authoringCapabilities` entries remain enabled for backward compatib
86
86
  never written to `WidgetPageDefinition` and does not authorize AI operations; manifests, backend
87
87
  policy, target resolution and validation remain authoritative.
88
88
 
89
+ `childCustomization` is a host grant, not a bulk enable switch. A nested component receives
90
+ `enableCustomization=true` only while the builder is in authoring mode, the host grant is enabled,
91
+ and that widget explicitly declares `definition.inputs.enableCustomization=true`. Widgets with an
92
+ absent or false authored opt-in remain presentation-only.
93
+
89
94
  For example, a host that should expose only canvas and shell-identity authoring can declare:
90
95
 
91
96
  ```ts
@@ -262,6 +267,8 @@ The package exports `PRAXIS_PAGE_BUILDER_AUTHORING_MANIFEST` for governed operat
262
267
 
263
268
  The visual authoring runtime may project editor-only inputs required by canvas affordances. Page changes emitted by that runtime are normalized back to the canonical `WidgetPageDefinition` before persistence: transient authoring inputs are removed, explicitly authored values are preserved, and a projection-only no-op does not create a new revision.
264
269
 
270
+ `saveCurrentPage()` reads the embedded Dynamic Page snapshot only while the editable canvas is active. In presentation mode, composition may hydrate component inputs and derive display layout; those values are runtime projections and must never overwrite the canonical `currentPage` during save. Presentation-mode save therefore emits a clone of the authored page, preserving widgets, links, state, layout and provenance exactly.
271
+
265
272
  `UiCompositionPlan` can carry the complete page-owned envelope required by the runtime: `i18n`, explicit `context`, canonical `layout`, state, presets, responsive variants, governed widget `shell`, component inputs and semantic wiring. The compiler clones these fields into `WidgetPageDefinition`; hosts must not add business copy, tenant context, layout or widget chrome after compilation as an undocumented enrichment step. `context` is page-wide runtime context, while `contextScopes` is an authoring shorthand that expands repeated values into explicit widget inputs and links.
266
273
 
267
274
  Repeated selection projections can be authored once through `UiCompositionPlan.selectionSyncs`. A sync declares structured component-output sources, a base state target, and a field-to-payload mapping. `compileUiCompositionPlan` expands every source/mapping pair into explicit `page.composition.links` with stable ids, canonical `pick-path` transforms, policy, condition, and `selection-sync` intent. The shorthand is never persisted in `WidgetPageDefinition`, so runtime inspection and audit continue to see the complete executable graph.
@@ -321,16 +328,23 @@ Workspace contributors can exercise this path in the reference host at
321
328
  the compact plan, registry-aware preflight, compiled `WidgetPageDefinition`, real
322
329
  Dynamic Page, diagnostics, widget-event trail and sanitized runtime observation
323
330
  without introducing another compiler or registry. Its scenario catalog reuses the
324
- same A2-A4 plan fixtures exercised by focused certification specs—forms/filters,
325
- CRUD lifecycle and parent/related-resource—alongside the certified A5
326
- Table/shell/global-action contracts. An unknown component proves fail-closed
327
- behavior. The browser proof for the related-resource scenario requires a real
331
+ same A1-A5 plan fixtures exercised by focused certification specs—List,
332
+ forms/filters, CRUD lifecycle, parent/related-resource and
333
+ Table/shell/global-action. Seven adversarial scenarios prove fail-closed behavior
334
+ for missing component, missing port, invalid direction, incompatible semantic
335
+ kind, unguarded feedback, incomplete master-detail layout and a stale governed
336
+ template hash. The browser proof for the related-resource scenario requires a real
328
337
  parent selection, the relationship filter and visible child columns/data derived
329
338
  from the remote schema; request success alone is insufficient. The same route's
330
339
  People Operations dashboard is authored as a 9-widget/10-binding plan and proves
331
- filter and governed decision propagation through the compiled graph. The broader
332
- certification matrix remains tracked in issue #430; issue #431 closed the former
333
- global-action source limitation.
340
+ filter and governed decision propagation through the compiled graph. The lab also
341
+ executes deterministic runtime reset, verifies JSON persistence invariants for
342
+ every applicable scenario, and invokes the real Page Builder save output before
343
+ reopening the rich People Operations page. Corrupted executable transforms and
344
+ legacy `page.connections` remain Core/page-ingress adversarials because neither is
345
+ a valid `UiCompositionPlan` input; the lab does not duplicate those boundary
346
+ validators. The governed Config Starter + Quickstart gate remains tracked in
347
+ issue #430; issue #431 closed the former global-action source limitation.
334
348
 
335
349
  For multi-consumer interaction state, author one `event -> state` binding and
336
350
  project `state -> component-port` to each consumer. A direct event delivery is
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": "1.0.0",
3
- "generatedAt": "2026-08-30T21:38:22.309Z",
3
+ "generatedAt": "2026-08-30T23:30:05.791Z",
4
4
  "packageName": "@praxisui/page-builder",
5
- "packageVersion": "9.0.47",
5
+ "packageVersion": "9.0.48",
6
6
  "sourceRegistry": "praxis-component-registry-ingestion",
7
7
  "sourceRegistryVersion": "1.0.0",
8
8
  "componentCount": 1,
@@ -24754,28 +24754,12 @@ class DynamicPageBuilderComponent {
24754
24754
  }
24755
24755
  /**
24756
24756
  * Builds one mode-independent runtime projection for the authored page.
24757
- * Child authoring chrome is materialized by the embedded dynamic page from
24758
- * host capabilities, so JSON/Visual mode changes never replace this object.
24757
+ * The authored child opt-in remains in this stable source. The embedded
24758
+ * dynamic page combines it with host mode/capabilities at the loader boundary,
24759
+ * so JSON/Visual changes never replace this object or broaden permissions.
24759
24760
  */
24760
24761
  toRuntimeBasePage(page) {
24761
- const cloned = this.clonePage(page);
24762
- cloned.widgets = (cloned.widgets || []).map((widget) => {
24763
- const metadata = this.componentMetadata.get(widget.definition?.id);
24764
- if (!metadata?.inputs?.some((input) => input.name === 'enableCustomization')) {
24765
- return widget;
24766
- }
24767
- return {
24768
- ...widget,
24769
- definition: {
24770
- ...widget.definition,
24771
- inputs: {
24772
- ...(widget.definition.inputs || {}),
24773
- enableCustomization: false,
24774
- },
24775
- },
24776
- };
24777
- });
24778
- return cloned;
24762
+ return this.clonePage(page);
24779
24763
  }
24780
24764
  /** Restores authoring-only child inputs from the canonical builder page. */
24781
24765
  toCanonicalPageFromRuntime(page) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@praxisui/page-builder",
3
- "version": "9.0.47",
3
+ "version": "9.0.48",
4
4
  "description": "Page and widget builder utilities for Praxis UI (grid, dynamic widgets, editors).",
5
5
  "peerDependencies": {
6
6
  "@angular/common": "^21.0.0",
@@ -8,9 +8,9 @@
8
8
  "@angular/forms": "^21.0.0",
9
9
  "@angular/cdk": "^21.0.0",
10
10
  "@angular/material": "^21.0.0",
11
- "@praxisui/ai": "^9.0.47",
12
- "@praxisui/core": "^9.0.47",
13
- "@praxisui/settings-panel": "^9.0.47",
11
+ "@praxisui/ai": "^9.0.48",
12
+ "@praxisui/core": "^9.0.48",
13
+ "@praxisui/settings-panel": "^9.0.48",
14
14
  "rxjs": "~7.8.0"
15
15
  },
16
16
  "dependencies": {
@@ -2197,8 +2197,9 @@ declare class DynamicPageBuilderComponent implements OnChanges, OnDestroy {
2197
2197
  private enterPreviewMode;
2198
2198
  /**
2199
2199
  * Builds one mode-independent runtime projection for the authored page.
2200
- * Child authoring chrome is materialized by the embedded dynamic page from
2201
- * host capabilities, so JSON/Visual mode changes never replace this object.
2200
+ * The authored child opt-in remains in this stable source. The embedded
2201
+ * dynamic page combines it with host mode/capabilities at the loader boundary,
2202
+ * so JSON/Visual changes never replace this object or broaden permissions.
2202
2203
  */
2203
2204
  private toRuntimeBasePage;
2204
2205
  /** Restores authoring-only child inputs from the canonical builder page. */