@praxisui/crud 9.0.61 → 9.0.63

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
@@ -221,8 +221,24 @@ const editAction: CrudAction = {
221
221
  For canonical `create`, `view`, `edit`, and `delete` operations, prefer inferred
222
222
  contracts. The runtime resolves the stable form id, request schema, submit URL,
223
223
  and HTTP method from the resource path, capabilities, surfaces, and HATEOAS
224
- links. Use an explicit form contract only when the operation deliberately
225
- overrides that baseline:
224
+ links. An inferred create/edit action may still author `form.submitLabel` as a
225
+ presentation-only affordance. The discovered surface remains authoritative for
226
+ schema, HTTP operation and endpoint; the CRUD passes the label through the
227
+ Dynamic Form `actions` input and suppresses generic cancel/reset duplicates in
228
+ the standard overlay footer:
229
+
230
+ ```ts
231
+ const createAction: CrudAction = {
232
+ id: 'create',
233
+ action: 'create',
234
+ label: 'Add skill',
235
+ openMode: 'drawer',
236
+ form: { submitLabel: 'Create skill' },
237
+ };
238
+ ```
239
+
240
+ Use an explicit form contract only when the operation deliberately overrides
241
+ the discovered functional baseline:
226
242
 
227
243
  ```ts
228
244
  const explicitEditAction: CrudAction = {
@@ -247,6 +263,10 @@ maximizing or restoring. The default edge is right/top; a configured left edge
247
263
  is preserved by the same lifecycle. `defaults.modal.edgeGap` controls the
248
264
  viewport inset while maximized. Provide `CRUD_DRAWER_ADAPTER` only when a
249
265
  host must replace that standard shell with a real corporate drawer implementation.
266
+ Detached modal and drawer trees retain the injector of the `PraxisCrudComponent`
267
+ that initiated the action. This preserves the same scoped `GenericCrudService`
268
+ for the hosted Dynamic Form, including host-provided test or tenant adapters,
269
+ instead of silently creating an unrelated service instance inside the overlay.
250
270
  Upstream surface materializers should publish the semantic `openMode` and leave
251
271
  geometry absent unless the host intentionally overrides it with a valid
252
272
  `DialogPosition` object. Values such as `position: "end"` are not drawer
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": "1.0.0",
3
- "generatedAt": "2026-09-05T03:48:57.914Z",
3
+ "generatedAt": "2026-09-05T19:46:18.619Z",
4
4
  "packageName": "@praxisui/crud",
5
- "packageVersion": "9.0.61",
5
+ "packageVersion": "9.0.63",
6
6
  "sourceRegistry": "praxis-component-registry-ingestion",
7
7
  "sourceRegistryVersion": "1.0.0",
8
8
  "componentCount": 2,
@@ -89,7 +89,7 @@
89
89
  "name": "metadata.actions[].form",
90
90
  "type": "CrudActionFormContract",
91
91
  "required": false,
92
- "description": "Contrato canônico explícito para modal/drawer quando o host precisa informar schemaUrl, submitUrl e submitMethod sem depender do fallback genérico por resource.path."
92
+ "description": "Contrato da ação para modal/drawer. submitLabel personaliza apenas a apresentação; schemaUrl, submitUrl e submitMethod continuam sujeitos à resolução canônica por resource.path e discovery."
93
93
  },
94
94
  {
95
95
  "name": "enableCustomization",
@@ -4668,6 +4668,12 @@
4668
4668
  "valueKind": "string",
4669
4669
  "description": "FormId canonico para modal/drawer; se ausente, o host precisa resolve-lo por override por acao antes da abertura."
4670
4670
  },
4671
+ {
4672
+ "path": "actions[].form.submitLabel",
4673
+ "category": "actions",
4674
+ "valueKind": "string",
4675
+ "description": "Rótulo de apresentação do submit; não altera schema, método nem endpoint descobertos."
4676
+ },
4671
4677
  {
4672
4678
  "path": "actions[].params",
4673
4679
  "category": "actions",
@@ -5200,6 +5206,24 @@
5200
5206
  ]
5201
5207
  }
5202
5208
  },
5209
+ {
5210
+ "id": "action.submitLabel.set",
5211
+ "intentExamples": [
5212
+ "submit label",
5213
+ "save button label",
5214
+ "rótulo do botão salvar"
5215
+ ],
5216
+ "patchTemplate": {
5217
+ "actions": [
5218
+ {
5219
+ "id": "{{target}}",
5220
+ "form": {
5221
+ "submitLabel": "{{value}}"
5222
+ }
5223
+ }
5224
+ ]
5225
+ }
5226
+ },
5203
5227
  {
5204
5228
  "id": "action.params.add",
5205
5229
  "intentExamples": [
@@ -5517,7 +5541,7 @@
5517
5541
  {
5518
5542
  "kind": "formBinding",
5519
5543
  "resolver": "crud-action-form-contract-by-action-id",
5520
- "description": "CRUD-owned form binding fields: formId, schemaUrl, submitUrl, submitMethod, params and initialValue. Shared FormConfig remains owned by Dynamic Form and is forwarded through CrudMetadata.form when present."
5544
+ "description": "CRUD-owned form binding fields: formId, presentation-only submitLabel, schemaUrl, submitUrl, submitMethod, params and initialValue. Shared FormConfig remains owned by Dynamic Form and is forwarded through CrudMetadata.form when present."
5521
5545
  },
5522
5546
  {
5523
5547
  "kind": "permissions",
@@ -5907,6 +5931,9 @@
5907
5931
  "form": {
5908
5932
  "type": "object",
5909
5933
  "properties": {
5934
+ "submitLabel": {
5935
+ "type": "string"
5936
+ },
5910
5937
  "schemaUrl": {
5911
5938
  "type": "string"
5912
5939
  },
@@ -6013,6 +6040,9 @@
6013
6040
  "form": {
6014
6041
  "type": "object",
6015
6042
  "properties": {
6043
+ "submitLabel": {
6044
+ "type": "string"
6045
+ },
6016
6046
  "schemaUrl": {
6017
6047
  "type": "string"
6018
6048
  },
@@ -6143,6 +6173,9 @@
6143
6173
  "form": {
6144
6174
  "type": "object",
6145
6175
  "properties": {
6176
+ "submitLabel": {
6177
+ "type": "string"
6178
+ },
6146
6179
  "schemaUrl": {
6147
6180
  "type": "string"
6148
6181
  },
@@ -6249,6 +6282,9 @@
6249
6282
  "form": {
6250
6283
  "type": "object",
6251
6284
  "properties": {
6285
+ "submitLabel": {
6286
+ "type": "string"
6287
+ },
6252
6288
  "schemaUrl": {
6253
6289
  "type": "string"
6254
6290
  },
@@ -6381,6 +6417,9 @@
6381
6417
  "form": {
6382
6418
  "type": "object",
6383
6419
  "properties": {
6420
+ "submitLabel": {
6421
+ "type": "string"
6422
+ },
6384
6423
  "schemaUrl": {
6385
6424
  "type": "string"
6386
6425
  },
@@ -6487,6 +6526,9 @@
6487
6526
  "form": {
6488
6527
  "type": "object",
6489
6528
  "properties": {
6529
+ "submitLabel": {
6530
+ "type": "string"
6531
+ },
6490
6532
  "schemaUrl": {
6491
6533
  "type": "string"
6492
6534
  },
@@ -7748,9 +7790,9 @@
7748
7790
  {
7749
7791
  "chunkIndex": 11,
7750
7792
  "chunkKind": "capabilities",
7751
- "content": "Component Capability:\n - Path: actions[].appearance\n Category: actions\n Kind: enum\n Description: Aparencia do botao (ToolbarAction).\n\nComponent Capability:\n - Path: actions[].position\n Category: actions\n Kind: enum\n Description: Posicao da acao (ToolbarAction).\n\nComponent Capability:\n - Path: actions[].order\n Category: actions\n Kind: number\n Description: Ordem de exibicao (ToolbarAction).\n\nComponent Capability:\n - Path: actions[].shortcut\n Category: actions\n Kind: string\n Description: Atalho de teclado (ToolbarAction).\n\nComponent Capability:\n - Path: actions[].children\n Category: actions\n Kind: array\n Description: Sub-acoes (menu).\n\nComponent Capability:\n - Path: actions[].openMode\n Category: actions\n Kind: enum\n Description: Modo de abertura da acao.\n\nComponent Capability:\n - Path: actions[].route\n Category: actions\n Kind: string\n Description: Rota para openMode=route.\n\nComponent Capability:\n - Path: actions[].formId\n Category: actions\n Kind: string\n Description: FormId canonico para modal/drawer; se ausente, o host precisa resolve-lo por override por acao antes da abertura.\n\nComponent Capability:\n - Path: actions[].params\n Category: actions\n Kind: array\n Description: Mapeamento de parametros.\n\nComponent Capability:\n - Path: actions[].params[].from\n Category: actions\n Kind: string\n Description: Origem do parametro.\n\nComponent Capability:\n - Path: actions[].params[].to\n Category: actions\n Kind: enum\n Description: Destino do parametro.\n\nComponent Capability:\n - Path: actions[].params[].name\n Category: actions\n Kind: string\n Description: Nome do parametro no destino.\n\nComponent Capability:\n - Path: actions[].form.initialValue\n Category: actions\n Kind: object\n Description: Seed fixo do formulario injetado em inputs.initialValue antes da abertura.\n\nComponent Capability:\n - Path: actions[].form.layoutPolicy\n Category: actions\n Kind: object\n Description: Politica schema-driven opt-in encaminhada ao Dynamic Form para materializar detalhe ou command form sem FormConfig.sections local; deve acompanhar schemaUrl compativel, especialmente schemaType=request para comandos.\n\nComponent Capability:\n - Path: actions[].back\n Category: navigation\n Kind: object\n Description: BackConfig por acao.\n\nComponent Capability:\n - Path: actions[].back.strategy\n Category: navigation\n Kind: enum\n Description: Estrategia de retorno da acao (auto, close, navigate).\n\nComponent Capability:\n - Path: actions[].back.returnTo\n Category: navigation\n Kind: string\n Description: Rota ou destino usado quando a estrategia de retorno for navigate.\n\nComponent Capability:\n - Path: actions[].back.confirmOnDirty\n Category: navigation\n Kind: boolean\n Description: Solicita confirmacao antes de sair com alteracoes nao salvas.\n\nComponent Capability:\n - Path: i18n\n Category: i18n\n Kind: object\n Description: Mensagens i18n do CRUD.\n\nComponent Capability:\n - Path: i18n.crudDialog\n Category: i18n\n Kind: object\n Description: Mapa de textos do dialog.\n\nCapability Note:\n - CrudMetadata agrega TableConfig e FormConfig; use os catalogos de tabela e formulario para detalhes.\n\nCapability Note:\n - actions[] herda campos de RowAction e ToolbarAction; combine com openMode/route/formId quando aplicavel.",
7793
+ "content": "Component Capability:\n - Path: actions[].appearance\n Category: actions\n Kind: enum\n Description: Aparencia do botao (ToolbarAction).\n\nComponent Capability:\n - Path: actions[].position\n Category: actions\n Kind: enum\n Description: Posicao da acao (ToolbarAction).\n\nComponent Capability:\n - Path: actions[].order\n Category: actions\n Kind: number\n Description: Ordem de exibicao (ToolbarAction).\n\nComponent Capability:\n - Path: actions[].shortcut\n Category: actions\n Kind: string\n Description: Atalho de teclado (ToolbarAction).\n\nComponent Capability:\n - Path: actions[].children\n Category: actions\n Kind: array\n Description: Sub-acoes (menu).\n\nComponent Capability:\n - Path: actions[].openMode\n Category: actions\n Kind: enum\n Description: Modo de abertura da acao.\n\nComponent Capability:\n - Path: actions[].route\n Category: actions\n Kind: string\n Description: Rota para openMode=route.\n\nComponent Capability:\n - Path: actions[].formId\n Category: actions\n Kind: string\n Description: FormId canonico para modal/drawer; se ausente, o host precisa resolve-lo por override por acao antes da abertura.\n\nComponent Capability:\n - Path: actions[].form.submitLabel\n Category: actions\n Kind: string\n Description: Rótulo de apresentação do submit; não altera schema, método nem endpoint descobertos.\n\nComponent Capability:\n - Path: actions[].params\n Category: actions\n Kind: array\n Description: Mapeamento de parametros.\n\nComponent Capability:\n - Path: actions[].params[].from\n Category: actions\n Kind: string\n Description: Origem do parametro.\n\nComponent Capability:\n - Path: actions[].params[].to\n Category: actions\n Kind: enum\n Description: Destino do parametro.\n\nComponent Capability:\n - Path: actions[].params[].name\n Category: actions\n Kind: string\n Description: Nome do parametro no destino.\n\nComponent Capability:\n - Path: actions[].form.initialValue\n Category: actions\n Kind: object\n Description: Seed fixo do formulario injetado em inputs.initialValue antes da abertura.\n\nComponent Capability:\n - Path: actions[].form.layoutPolicy\n Category: actions\n Kind: object\n Description: Politica schema-driven opt-in encaminhada ao Dynamic Form para materializar detalhe ou command form sem FormConfig.sections local; deve acompanhar schemaUrl compativel, especialmente schemaType=request para comandos.\n\nComponent Capability:\n - Path: actions[].back\n Category: navigation\n Kind: object\n Description: BackConfig por acao.\n\nComponent Capability:\n - Path: actions[].back.strategy\n Category: navigation\n Kind: enum\n Description: Estrategia de retorno da acao (auto, close, navigate).\n\nComponent Capability:\n - Path: actions[].back.returnTo\n Category: navigation\n Kind: string\n Description: Rota ou destino usado quando a estrategia de retorno for navigate.\n\nComponent Capability:\n - Path: actions[].back.confirmOnDirty\n Category: navigation\n Kind: boolean\n Description: Solicita confirmacao antes de sair com alteracoes nao salvas.\n\nComponent Capability:\n - Path: i18n\n Category: i18n\n Kind: object\n Description: Mensagens i18n do CRUD.\n\nComponent Capability:\n - Path: i18n.crudDialog\n Category: i18n\n Kind: object\n Description: Mapa de textos do dialog.\n\nCapability Note:\n - CrudMetadata agrega TableConfig e FormConfig; use os catalogos de tabela e formulario para detalhes.\n\nCapability Note:\n - actions[] herda campos de RowAction e ToolbarAction; combine com openMode/route/formId quando aplicavel.",
7752
7794
  "sourcePointer": "projects/praxis-crud/src/lib/ai/crud-ai-capabilities.ts",
7753
- "contentHash": "c9480d5b125a289a3cccf03b035759e277292fbad0895fe783128d5ef9d80691",
7795
+ "contentHash": "226468e02e18f80cc1aa469687dc2fd42746d7d0cb8fce960e4763aeaca41f73",
7754
7796
  "sourceKind": "component_definition",
7755
7797
  "sourceId": "praxis-crud",
7756
7798
  "corpusVersion": "1.0.0"
@@ -7788,9 +7830,9 @@
7788
7830
  {
7789
7831
  "chunkIndex": 15,
7790
7832
  "chunkKind": "authoring_manifest",
7791
- "content": "{\"operationId\":\"surface.create.configure\",\"schemaVersion\":\"1.0.0\",\"manifestVersion\":\"1.0.0\",\"componentId\":\"praxis-crud\",\"ownerPackage\":\"@praxisui/crud\",\"configSchemaId\":\"CrudMetadata\",\"chunkSection\":\"operation_card\",\"semanticSummary\":\"Configure create surface Effects: compile-domain-patch. Open create in a modal with the employee form.\",\"scope\":\"interaction\",\"target\":{\"kind\":\"createSurface\",\"resolver\":\"crud-action-by-id:create\",\"required\":true},\"inputContract\":{\"required\":[\"actionId\",\"openMode\"],\"properties\":[\"actionId\",\"openMode\",\"route\",\"formId\",\"form\",\"params\",\"back\"],\"semanticTerms\":[\"actionId\",\"openMode\",\"route\",\"formId\",\"form\",\"params\",\"back\",\"create\",\"edit\",\"view\",\"modal\",\"drawer\",\"form.schemaUrl\",\"form.submitUrl\",\"form.submitMethod\",\"form.apiEndpointKey\",\"form.initialValue\",\"form.layoutPolicy\",\"post\",\"put\",\"patch\",\"delete\",\"params.from\",\"params.to\",\"params.name\",\"routeParam\",\"query\",\"input\"]},\"effects\":[\"compile-domain-patch\"],\"affectedPaths\":[\"actions[].openMode\",\"actions[].route\",\"actions[].formId\",\"actions[].form\",\"actions[].params\",\"actions[].back\"],\"validators\":[{\"validatorId\":\"action-exists\",\"level\":\"error\",\"code\":\"CRUD_ACTION_EXISTS\",\"description\":\"Target action must exist or be created through CRUD action orchestration.\"},{\"validatorId\":\"open-mode-binding-complete\",\"level\":\"error\",\"code\":\"CRUD_OPEN_MODE_BINDING_COMPLETE\",\"description\":\"route requires route; modal/drawer require formId unless resolved by governed overrides.\"},{\"validatorId\":\"schema-url-canonical\",\"level\":\"error\",\"code\":\"CRUD_SCHEMA_URL_CANONICAL\",\"description\":\"Schema URLs must be canonical for the bound resource/action.\"},{\"validatorId\":\"submit-url-canonical\",\"level\":\"error\",\"code\":\"CRUD_SUBMIT_URL_CANONICAL\",\"description\":\"Submit URL and method must be canonical and declared together.\"},{\"validatorId\":\"resource-create-supported\",\"level\":\"error\",\"code\":\"CRUD_CREATE_SUPPORTED\",\"description\":\"Create surface requires resource create capability.\"},{\"validatorId\":\"form-child-operation-delegated\",\"level\":\"error\",\"code\":\"CRUD_FORM_CHILD_DELEGATED\",\"description\":\"FormConfig and FieldMetadata edits must delegate to dynamic-form/metadata-editor manifests.\"}],\"preconditions\":[\"crud-metadata-loaded\",\"resource-capabilities-resolved\"],\"submissionImpact\":\"affects-schema-backed-data\",\"presentationAffordances\":[],\"positiveExamples\":[{\"id\":\"crud-create-modal\",\"request\":\"Open create in a modal with the employee form.\",\"operationId\":\"surface.create.configure\",\"target\":\"action:create\",\"params\":{\"actionId\":\"create\",\"openMode\":\"modal\",\"formId\":\"employee-create\"},\"isPositive\":true}],\"negativeExamples\":[]}",
7833
+ "content": "{\"operationId\":\"surface.create.configure\",\"schemaVersion\":\"1.0.0\",\"manifestVersion\":\"1.0.0\",\"componentId\":\"praxis-crud\",\"ownerPackage\":\"@praxisui/crud\",\"configSchemaId\":\"CrudMetadata\",\"chunkSection\":\"operation_card\",\"semanticSummary\":\"Configure create surface Effects: compile-domain-patch. Open create in a modal with the employee form.\",\"scope\":\"interaction\",\"target\":{\"kind\":\"createSurface\",\"resolver\":\"crud-action-by-id:create\",\"required\":true},\"inputContract\":{\"required\":[\"actionId\",\"openMode\"],\"properties\":[\"actionId\",\"openMode\",\"route\",\"formId\",\"form\",\"params\",\"back\"],\"semanticTerms\":[\"actionId\",\"openMode\",\"route\",\"formId\",\"form\",\"params\",\"back\",\"create\",\"edit\",\"view\",\"modal\",\"drawer\",\"form.submitLabel\",\"form.schemaUrl\",\"form.submitUrl\",\"form.submitMethod\",\"form.apiEndpointKey\",\"form.initialValue\",\"form.layoutPolicy\",\"post\",\"put\",\"patch\",\"delete\",\"params.from\",\"params.to\",\"params.name\",\"routeParam\",\"query\",\"input\"]},\"effects\":[\"compile-domain-patch\"],\"affectedPaths\":[\"actions[].openMode\",\"actions[].route\",\"actions[].formId\",\"actions[].form\",\"actions[].params\",\"actions[].back\"],\"validators\":[{\"validatorId\":\"action-exists\",\"level\":\"error\",\"code\":\"CRUD_ACTION_EXISTS\",\"description\":\"Target action must exist or be created through CRUD action orchestration.\"},{\"validatorId\":\"open-mode-binding-complete\",\"level\":\"error\",\"code\":\"CRUD_OPEN_MODE_BINDING_COMPLETE\",\"description\":\"route requires route; modal/drawer require formId unless resolved by governed overrides.\"},{\"validatorId\":\"schema-url-canonical\",\"level\":\"error\",\"code\":\"CRUD_SCHEMA_URL_CANONICAL\",\"description\":\"Schema URLs must be canonical for the bound resource/action.\"},{\"validatorId\":\"submit-url-canonical\",\"level\":\"error\",\"code\":\"CRUD_SUBMIT_URL_CANONICAL\",\"description\":\"Submit URL and method must be canonical and declared together.\"},{\"validatorId\":\"resource-create-supported\",\"level\":\"error\",\"code\":\"CRUD_CREATE_SUPPORTED\",\"description\":\"Create surface requires resource create capability.\"},{\"validatorId\":\"form-child-operation-delegated\",\"level\":\"error\",\"code\":\"CRUD_FORM_CHILD_DELEGATED\",\"description\":\"FormConfig and FieldMetadata edits must delegate to dynamic-form/metadata-editor manifests.\"}],\"preconditions\":[\"crud-metadata-loaded\",\"resource-capabilities-resolved\"],\"submissionImpact\":\"affects-schema-backed-data\",\"presentationAffordances\":[],\"positiveExamples\":[{\"id\":\"crud-create-modal\",\"request\":\"Open create in a modal with the employee form.\",\"operationId\":\"surface.create.configure\",\"target\":\"action:create\",\"params\":{\"actionId\":\"create\",\"openMode\":\"modal\",\"formId\":\"employee-create\"},\"isPositive\":true}],\"negativeExamples\":[]}",
7792
7834
  "sourcePointer": "projects/praxis-crud/src/lib/ai/praxis-crud-authoring-manifest.ts",
7793
- "contentHash": "f5499ba6f93cd1b6ce032245f06f27c1589ef100c5b56c0aa6cfbf9d307d02e6",
7835
+ "contentHash": "c9d3a2b385b1e0a9a648fc32ce4a51a0436592c7659440662080210986483d20",
7794
7836
  "sourceKind": "component_definition",
7795
7837
  "sourceId": "praxis-crud",
7796
7838
  "corpusVersion": "1.0.0"
@@ -7798,9 +7840,9 @@
7798
7840
  {
7799
7841
  "chunkIndex": 16,
7800
7842
  "chunkKind": "authoring_manifest",
7801
- "content": "{\"operationId\":\"surface.edit.configure\",\"schemaVersion\":\"1.0.0\",\"manifestVersion\":\"1.0.0\",\"componentId\":\"praxis-crud\",\"ownerPackage\":\"@praxisui/crud\",\"configSchemaId\":\"CrudMetadata\",\"chunkSection\":\"operation_card\",\"semanticSummary\":\"Configure edit surface Effects: compile-domain-patch. Edit should navigate to /employees/:id and map the row id.\",\"scope\":\"interaction\",\"target\":{\"kind\":\"editSurface\",\"resolver\":\"crud-action-by-id:edit\",\"required\":true},\"inputContract\":{\"required\":[\"actionId\",\"openMode\"],\"properties\":[\"actionId\",\"openMode\",\"route\",\"formId\",\"form\",\"params\",\"back\"],\"semanticTerms\":[\"actionId\",\"openMode\",\"route\",\"formId\",\"form\",\"params\",\"back\",\"create\",\"edit\",\"view\",\"modal\",\"drawer\",\"form.schemaUrl\",\"form.submitUrl\",\"form.submitMethod\",\"form.apiEndpointKey\",\"form.initialValue\",\"form.layoutPolicy\",\"post\",\"put\",\"patch\",\"delete\",\"params.from\",\"params.to\",\"params.name\",\"routeParam\",\"query\",\"input\"]},\"effects\":[\"compile-domain-patch\"],\"affectedPaths\":[\"actions[].openMode\",\"actions[].route\",\"actions[].formId\",\"actions[].form\",\"actions[].params\",\"actions[].back\"],\"validators\":[{\"validatorId\":\"action-exists\",\"level\":\"error\",\"code\":\"CRUD_ACTION_EXISTS\",\"description\":\"Target action must exist or be created through CRUD action orchestration.\"},{\"validatorId\":\"id-field-known\",\"level\":\"error\",\"code\":\"CRUD_ID_FIELD_KNOWN\",\"description\":\"CRUD id field must exist for edit/view/delete flows.\"},{\"validatorId\":\"id-param-mapping-valid\",\"level\":\"error\",\"code\":\"CRUD_ID_PARAM_MAPPING_VALID\",\"description\":\"Edit/view actions must map resource id into route/query/input as required.\"},{\"validatorId\":\"open-mode-binding-complete\",\"level\":\"error\",\"code\":\"CRUD_OPEN_MODE_BINDING_COMPLETE\",\"description\":\"route requires route; modal/drawer require formId unless resolved by governed overrides.\"},{\"validatorId\":\"schema-url-canonical\",\"level\":\"error\",\"code\":\"CRUD_SCHEMA_URL_CANONICAL\",\"description\":\"Schema URLs must be canonical for the bound resource/action.\"},{\"validatorId\":\"submit-url-canonical\",\"level\":\"error\",\"code\":\"CRUD_SUBMIT_URL_CANONICAL\",\"description\":\"Submit URL and method must be canonical and declared together.\"},{\"validatorId\":\"resource-edit-supported\",\"level\":\"error\",\"code\":\"CRUD_EDIT_SUPPORTED\",\"description\":\"Edit surface requires resource edit capability.\"},{\"validatorId\":\"form-child-operation-delegated\",\"level\":\"error\",\"code\":\"CRUD_FORM_CHILD_DELEGATED\",\"description\":\"FormConfig and FieldMetadata edits must delegate to dynamic-form/metadata-editor manifests.\"}],\"preconditions\":[\"crud-metadata-loaded\",\"resource-capabilities-resolved\"],\"submissionImpact\":\"affects-schema-backed-data\",\"presentationAffordances\":[],\"positiveExamples\":[{\"id\":\"crud-edit-route-with-id\",\"request\":\"Edit should navigate to /employees/:id and map the row id.\",\"operationId\":\"surface.edit.configure\",\"target\":\"action:edit\",\"params\":{\"actionId\":\"edit\",\"openMode\":\"route\",\"route\":\"/employees/:id/edit\",\"params\":[{\"from\":\"id\",\"to\":\"routeParam\",\"name\":\"id\"}]},\"isPositive\":true}],\"negativeExamples\":[]}",
7843
+ "content": "{\"operationId\":\"surface.edit.configure\",\"schemaVersion\":\"1.0.0\",\"manifestVersion\":\"1.0.0\",\"componentId\":\"praxis-crud\",\"ownerPackage\":\"@praxisui/crud\",\"configSchemaId\":\"CrudMetadata\",\"chunkSection\":\"operation_card\",\"semanticSummary\":\"Configure edit surface Effects: compile-domain-patch. Edit should navigate to /employees/:id and map the row id.\",\"scope\":\"interaction\",\"target\":{\"kind\":\"editSurface\",\"resolver\":\"crud-action-by-id:edit\",\"required\":true},\"inputContract\":{\"required\":[\"actionId\",\"openMode\"],\"properties\":[\"actionId\",\"openMode\",\"route\",\"formId\",\"form\",\"params\",\"back\"],\"semanticTerms\":[\"actionId\",\"openMode\",\"route\",\"formId\",\"form\",\"params\",\"back\",\"create\",\"edit\",\"view\",\"modal\",\"drawer\",\"form.submitLabel\",\"form.schemaUrl\",\"form.submitUrl\",\"form.submitMethod\",\"form.apiEndpointKey\",\"form.initialValue\",\"form.layoutPolicy\",\"post\",\"put\",\"patch\",\"delete\",\"params.from\",\"params.to\",\"params.name\",\"routeParam\",\"query\",\"input\"]},\"effects\":[\"compile-domain-patch\"],\"affectedPaths\":[\"actions[].openMode\",\"actions[].route\",\"actions[].formId\",\"actions[].form\",\"actions[].params\",\"actions[].back\"],\"validators\":[{\"validatorId\":\"action-exists\",\"level\":\"error\",\"code\":\"CRUD_ACTION_EXISTS\",\"description\":\"Target action must exist or be created through CRUD action orchestration.\"},{\"validatorId\":\"id-field-known\",\"level\":\"error\",\"code\":\"CRUD_ID_FIELD_KNOWN\",\"description\":\"CRUD id field must exist for edit/view/delete flows.\"},{\"validatorId\":\"id-param-mapping-valid\",\"level\":\"error\",\"code\":\"CRUD_ID_PARAM_MAPPING_VALID\",\"description\":\"Edit/view actions must map resource id into route/query/input as required.\"},{\"validatorId\":\"open-mode-binding-complete\",\"level\":\"error\",\"code\":\"CRUD_OPEN_MODE_BINDING_COMPLETE\",\"description\":\"route requires route; modal/drawer require formId unless resolved by governed overrides.\"},{\"validatorId\":\"schema-url-canonical\",\"level\":\"error\",\"code\":\"CRUD_SCHEMA_URL_CANONICAL\",\"description\":\"Schema URLs must be canonical for the bound resource/action.\"},{\"validatorId\":\"submit-url-canonical\",\"level\":\"error\",\"code\":\"CRUD_SUBMIT_URL_CANONICAL\",\"description\":\"Submit URL and method must be canonical and declared together.\"},{\"validatorId\":\"resource-edit-supported\",\"level\":\"error\",\"code\":\"CRUD_EDIT_SUPPORTED\",\"description\":\"Edit surface requires resource edit capability.\"},{\"validatorId\":\"form-child-operation-delegated\",\"level\":\"error\",\"code\":\"CRUD_FORM_CHILD_DELEGATED\",\"description\":\"FormConfig and FieldMetadata edits must delegate to dynamic-form/metadata-editor manifests.\"}],\"preconditions\":[\"crud-metadata-loaded\",\"resource-capabilities-resolved\"],\"submissionImpact\":\"affects-schema-backed-data\",\"presentationAffordances\":[],\"positiveExamples\":[{\"id\":\"crud-edit-route-with-id\",\"request\":\"Edit should navigate to /employees/:id and map the row id.\",\"operationId\":\"surface.edit.configure\",\"target\":\"action:edit\",\"params\":{\"actionId\":\"edit\",\"openMode\":\"route\",\"route\":\"/employees/:id/edit\",\"params\":[{\"from\":\"id\",\"to\":\"routeParam\",\"name\":\"id\"}]},\"isPositive\":true}],\"negativeExamples\":[]}",
7802
7844
  "sourcePointer": "projects/praxis-crud/src/lib/ai/praxis-crud-authoring-manifest.ts",
7803
- "contentHash": "9ded2d956df668b13d39fa0e151cfd7e9ecfc01dbc47931d9444b6c4d0b55c2d",
7845
+ "contentHash": "7a896505e740d5970855e085291dffad2cc01a0b1b48835b1076584706a80a43",
7804
7846
  "sourceKind": "component_definition",
7805
7847
  "sourceId": "praxis-crud",
7806
7848
  "corpusVersion": "1.0.0"
@@ -7808,9 +7850,9 @@
7808
7850
  {
7809
7851
  "chunkIndex": 17,
7810
7852
  "chunkKind": "authoring_manifest",
7811
- "content": "{\"operationId\":\"surface.view.configure\",\"schemaVersion\":\"1.0.0\",\"manifestVersion\":\"1.0.0\",\"componentId\":\"praxis-crud\",\"ownerPackage\":\"@praxisui/crud\",\"configSchemaId\":\"CrudMetadata\",\"chunkSection\":\"operation_card\",\"semanticSummary\":\"Configure view surface Effects: compile-domain-patch. Open view in a drawer and keep the form readonly.\",\"scope\":\"interaction\",\"target\":{\"kind\":\"viewSurface\",\"resolver\":\"crud-action-by-id:view\",\"required\":true},\"inputContract\":{\"required\":[\"actionId\",\"openMode\"],\"properties\":[\"actionId\",\"openMode\",\"route\",\"formId\",\"form\",\"params\",\"back\"],\"semanticTerms\":[\"actionId\",\"openMode\",\"route\",\"formId\",\"form\",\"params\",\"back\",\"create\",\"edit\",\"view\",\"modal\",\"drawer\",\"form.schemaUrl\",\"form.submitUrl\",\"form.submitMethod\",\"form.apiEndpointKey\",\"form.initialValue\",\"form.layoutPolicy\",\"post\",\"put\",\"patch\",\"delete\",\"params.from\",\"params.to\",\"params.name\",\"routeParam\",\"query\",\"input\"]},\"effects\":[\"compile-domain-patch\"],\"affectedPaths\":[\"actions[].openMode\",\"actions[].route\",\"actions[].formId\",\"actions[].form\",\"actions[].params\",\"actions[].back\"],\"validators\":[{\"validatorId\":\"action-exists\",\"level\":\"error\",\"code\":\"CRUD_ACTION_EXISTS\",\"description\":\"Target action must exist or be created through CRUD action orchestration.\"},{\"validatorId\":\"open-mode-binding-complete\",\"level\":\"error\",\"code\":\"CRUD_OPEN_MODE_BINDING_COMPLETE\",\"description\":\"route requires route; modal/drawer require formId unless resolved by governed overrides.\"},{\"validatorId\":\"schema-url-canonical\",\"level\":\"error\",\"code\":\"CRUD_SCHEMA_URL_CANONICAL\",\"description\":\"Schema URLs must be canonical for the bound resource/action.\"},{\"validatorId\":\"resource-view-supported\",\"level\":\"error\",\"code\":\"CRUD_VIEW_SUPPORTED\",\"description\":\"View surface requires resource view capability.\"},{\"validatorId\":\"form-child-operation-delegated\",\"level\":\"error\",\"code\":\"CRUD_FORM_CHILD_DELEGATED\",\"description\":\"FormConfig and FieldMetadata edits must delegate to dynamic-form/metadata-editor manifests.\"},{\"validatorId\":\"readonly-form-delegation-valid\",\"level\":\"error\",\"code\":\"CRUD_READONLY_FORM_DELEGATED\",\"description\":\"Readonly form behavior belongs to the dynamic-form manifest.\"}],\"preconditions\":[\"crud-metadata-loaded\",\"resource-capabilities-resolved\"],\"submissionImpact\":\"config-only\",\"presentationAffordances\":[],\"positiveExamples\":[{\"id\":\"crud-view-drawer-readonly\",\"request\":\"Open view in a drawer and keep the form readonly.\",\"operationId\":\"surface.view.configure\",\"target\":\"action:view\",\"params\":{\"actionId\":\"view\",\"openMode\":\"drawer\",\"formId\":\"employee-view\"},\"isPositive\":true}],\"negativeExamples\":[]}",
7853
+ "content": "{\"operationId\":\"surface.view.configure\",\"schemaVersion\":\"1.0.0\",\"manifestVersion\":\"1.0.0\",\"componentId\":\"praxis-crud\",\"ownerPackage\":\"@praxisui/crud\",\"configSchemaId\":\"CrudMetadata\",\"chunkSection\":\"operation_card\",\"semanticSummary\":\"Configure view surface Effects: compile-domain-patch. Open view in a drawer and keep the form readonly.\",\"scope\":\"interaction\",\"target\":{\"kind\":\"viewSurface\",\"resolver\":\"crud-action-by-id:view\",\"required\":true},\"inputContract\":{\"required\":[\"actionId\",\"openMode\"],\"properties\":[\"actionId\",\"openMode\",\"route\",\"formId\",\"form\",\"params\",\"back\"],\"semanticTerms\":[\"actionId\",\"openMode\",\"route\",\"formId\",\"form\",\"params\",\"back\",\"create\",\"edit\",\"view\",\"modal\",\"drawer\",\"form.submitLabel\",\"form.schemaUrl\",\"form.submitUrl\",\"form.submitMethod\",\"form.apiEndpointKey\",\"form.initialValue\",\"form.layoutPolicy\",\"post\",\"put\",\"patch\",\"delete\",\"params.from\",\"params.to\",\"params.name\",\"routeParam\",\"query\",\"input\"]},\"effects\":[\"compile-domain-patch\"],\"affectedPaths\":[\"actions[].openMode\",\"actions[].route\",\"actions[].formId\",\"actions[].form\",\"actions[].params\",\"actions[].back\"],\"validators\":[{\"validatorId\":\"action-exists\",\"level\":\"error\",\"code\":\"CRUD_ACTION_EXISTS\",\"description\":\"Target action must exist or be created through CRUD action orchestration.\"},{\"validatorId\":\"open-mode-binding-complete\",\"level\":\"error\",\"code\":\"CRUD_OPEN_MODE_BINDING_COMPLETE\",\"description\":\"route requires route; modal/drawer require formId unless resolved by governed overrides.\"},{\"validatorId\":\"schema-url-canonical\",\"level\":\"error\",\"code\":\"CRUD_SCHEMA_URL_CANONICAL\",\"description\":\"Schema URLs must be canonical for the bound resource/action.\"},{\"validatorId\":\"resource-view-supported\",\"level\":\"error\",\"code\":\"CRUD_VIEW_SUPPORTED\",\"description\":\"View surface requires resource view capability.\"},{\"validatorId\":\"form-child-operation-delegated\",\"level\":\"error\",\"code\":\"CRUD_FORM_CHILD_DELEGATED\",\"description\":\"FormConfig and FieldMetadata edits must delegate to dynamic-form/metadata-editor manifests.\"},{\"validatorId\":\"readonly-form-delegation-valid\",\"level\":\"error\",\"code\":\"CRUD_READONLY_FORM_DELEGATED\",\"description\":\"Readonly form behavior belongs to the dynamic-form manifest.\"}],\"preconditions\":[\"crud-metadata-loaded\",\"resource-capabilities-resolved\"],\"submissionImpact\":\"config-only\",\"presentationAffordances\":[],\"positiveExamples\":[{\"id\":\"crud-view-drawer-readonly\",\"request\":\"Open view in a drawer and keep the form readonly.\",\"operationId\":\"surface.view.configure\",\"target\":\"action:view\",\"params\":{\"actionId\":\"view\",\"openMode\":\"drawer\",\"formId\":\"employee-view\"},\"isPositive\":true}],\"negativeExamples\":[]}",
7812
7854
  "sourcePointer": "projects/praxis-crud/src/lib/ai/praxis-crud-authoring-manifest.ts",
7813
- "contentHash": "04a5f40fda3340951d8b091e4e30c0e390ea46be04b65ede21c421b0bca8b89d",
7855
+ "contentHash": "454168b9dbefb4263f1b8a6b160d10fdba3204dd63c097b594503de29a7eab54",
7814
7856
  "sourceKind": "component_definition",
7815
7857
  "sourceId": "praxis-crud",
7816
7858
  "corpusVersion": "1.0.0"
@@ -7878,9 +7920,9 @@
7878
7920
  {
7879
7921
  "chunkIndex": 24,
7880
7922
  "chunkKind": "authoring_manifest",
7881
- "content": "{\"schemaVersion\":\"1.0.0\",\"manifestVersion\":\"1.0.0\",\"componentId\":\"praxis-crud\",\"ownerPackage\":\"@praxisui/crud\",\"configSchemaId\":\"CrudMetadata\",\"chunkSection\":\"editableTargets\",\"editableTargets\":[{\"kind\":\"resourceBinding\",\"resolver\":\"crud-resource-by-path-or-key\",\"description\":\"Resource path/key, optional schema path template, id field, endpoint key and query context owned by CRUD orchestration.\"},{\"kind\":\"listSurface\",\"resolver\":\"crud-list-surface\",\"description\":\"CRUD-hosted list surface and table delegation boundary.\"},{\"kind\":\"createSurface\",\"resolver\":\"crud-action-by-id:create\",\"description\":\"Create action open mode, route/form binding and launcher inputs.\"},{\"kind\":\"editSurface\",\"resolver\":\"crud-action-by-id:edit\",\"description\":\"Edit action open mode, route/form binding and launcher inputs.\"},{\"kind\":\"viewSurface\",\"resolver\":\"crud-action-by-id:view\",\"description\":\"View action open mode, route/form binding and launcher inputs.\"},{\"kind\":\"deleteBehavior\",\"resolver\":\"crud-action-by-id:delete\",\"description\":\"Delete action enablement, confirmation, endpoint and capability policy.\"},{\"kind\":\"dialogHost\",\"resolver\":\"crud-dialog-host-defaults\",\"description\":\"Route/modal/drawer defaults consumed by CrudLauncherService and DynamicFormDialogHostComponent, including contextual shell titles derived from action label, form title or resource metadata.\"},{\"kind\":\"formBinding\",\"resolver\":\"crud-action-form-contract-by-action-id\",\"description\":\"CRUD-owned form binding fields: formId, schemaUrl, submitUrl, submitMethod, params and initialValue. Shared FormConfig remains owned by Dynamic Form and is forwarded through CrudMetadata.form when present.\"},{\"kind\":\"permissions\",\"resolver\":\"crud-resource-capabilities\",\"description\":\"CRUD action availability derived from resource capabilities and action permissions.\"},{\"kind\":\"domainGovernanceContext\",\"resolver\":\"domain-catalog-context-by-resource-key\",\"description\":\"Read-only semantic/governance context resolved from Domain Catalog and referenced from CRUD queryContext.meta.\"},{\"kind\":\"childOperation\",\"resolver\":\"child-authoring-manifest-operation\",\"description\":\"Delegated form/table/dialog/settings-panel operation owned by the child component manifest.\"}]}",
7923
+ "content": "{\"schemaVersion\":\"1.0.0\",\"manifestVersion\":\"1.0.0\",\"componentId\":\"praxis-crud\",\"ownerPackage\":\"@praxisui/crud\",\"configSchemaId\":\"CrudMetadata\",\"chunkSection\":\"editableTargets\",\"editableTargets\":[{\"kind\":\"resourceBinding\",\"resolver\":\"crud-resource-by-path-or-key\",\"description\":\"Resource path/key, optional schema path template, id field, endpoint key and query context owned by CRUD orchestration.\"},{\"kind\":\"listSurface\",\"resolver\":\"crud-list-surface\",\"description\":\"CRUD-hosted list surface and table delegation boundary.\"},{\"kind\":\"createSurface\",\"resolver\":\"crud-action-by-id:create\",\"description\":\"Create action open mode, route/form binding and launcher inputs.\"},{\"kind\":\"editSurface\",\"resolver\":\"crud-action-by-id:edit\",\"description\":\"Edit action open mode, route/form binding and launcher inputs.\"},{\"kind\":\"viewSurface\",\"resolver\":\"crud-action-by-id:view\",\"description\":\"View action open mode, route/form binding and launcher inputs.\"},{\"kind\":\"deleteBehavior\",\"resolver\":\"crud-action-by-id:delete\",\"description\":\"Delete action enablement, confirmation, endpoint and capability policy.\"},{\"kind\":\"dialogHost\",\"resolver\":\"crud-dialog-host-defaults\",\"description\":\"Route/modal/drawer defaults consumed by CrudLauncherService and DynamicFormDialogHostComponent, including contextual shell titles derived from action label, form title or resource metadata.\"},{\"kind\":\"formBinding\",\"resolver\":\"crud-action-form-contract-by-action-id\",\"description\":\"CRUD-owned form binding fields: formId, presentation-only submitLabel, schemaUrl, submitUrl, submitMethod, params and initialValue. Shared FormConfig remains owned by Dynamic Form and is forwarded through CrudMetadata.form when present.\"},{\"kind\":\"permissions\",\"resolver\":\"crud-resource-capabilities\",\"description\":\"CRUD action availability derived from resource capabilities and action permissions.\"},{\"kind\":\"domainGovernanceContext\",\"resolver\":\"domain-catalog-context-by-resource-key\",\"description\":\"Read-only semantic/governance context resolved from Domain Catalog and referenced from CRUD queryContext.meta.\"},{\"kind\":\"childOperation\",\"resolver\":\"child-authoring-manifest-operation\",\"description\":\"Delegated form/table/dialog/settings-panel operation owned by the child component manifest.\"}]}",
7882
7924
  "sourcePointer": "projects/praxis-crud/src/lib/ai/praxis-crud-authoring-manifest.ts",
7883
- "contentHash": "dc108626d494c3ffbe5917c3f7849e30084766cd5efd62b55aebfd21ff76a2d8",
7925
+ "contentHash": "0504fc4e9a79e3e54d81b1ede92206837b867e14c74bf67a2dab06b9e09085db",
7884
7926
  "sourceKind": "component_definition",
7885
7927
  "sourceId": "praxis-crud",
7886
7928
  "corpusVersion": "1.0.0"
@@ -7898,9 +7940,9 @@
7898
7940
  {
7899
7941
  "chunkIndex": 26,
7900
7942
  "chunkKind": "authoring_manifest",
7901
- "content": "{\"schemaVersion\":\"1.0.0\",\"manifestVersion\":\"1.0.0\",\"componentId\":\"praxis-crud\",\"ownerPackage\":\"@praxisui/crud\",\"configSchemaId\":\"CrudMetadata\",\"chunkSection\":\"operations\",\"operations\":[{\"operationId\":\"surface.create.configure\",\"title\":\"Configure create surface\",\"scope\":\"interaction\",\"targetKind\":\"createSurface\",\"target\":{\"kind\":\"createSurface\",\"resolver\":\"crud-action-by-id:create\",\"ambiguityPolicy\":\"fail\",\"required\":true},\"inputSchema\":{\"type\":\"object\",\"required\":[\"actionId\",\"openMode\"],\"properties\":{\"actionId\":{\"enum\":[\"create\",\"edit\",\"view\"]},\"openMode\":{\"enum\":[\"route\",\"modal\",\"drawer\"]},\"route\":{\"type\":\"string\"},\"formId\":{\"type\":\"string\"},\"form\":{\"type\":\"object\",\"properties\":{\"schemaUrl\":{\"type\":\"string\"},\"submitUrl\":{\"type\":\"string\"},\"submitMethod\":{\"enum\":[\"post\",\"put\",\"patch\",\"delete\"]},\"apiEndpointKey\":{\"type\":\"string\"},\"initialValue\":{\"type\":\"object\"},\"layoutPolicy\":{\"type\":\"object\"}}},\"params\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"required\":[\"from\",\"to\",\"name\"],\"properties\":{\"from\":{\"type\":\"string\"},\"to\":{\"enum\":[\"routeParam\",\"query\",\"input\"]},\"name\":{\"type\":\"string\"}}}},\"back\":{\"type\":\"object\"}}},\"effects\":[{\"kind\":\"compile-domain-patch\",\"handler\":\"crud-create-surface-configure\",\"handlerContract\":{\"reads\":[\"CrudMetadata.actions\",\"CrudLauncherService.resolveOpenMode\",\"DynamicFormDialogHostComponent\",\"api_metadata\"],\"writes\":[\"CrudMetadata.actions[]\",\"CrudMetadata.actions[].form\",\"CrudMetadata.actions[].params\",\"CrudMetadata.actions[].back\"],\"identityKeys\":[\"actionId\"],\"inputSchema\":{\"type\":\"object\",\"required\":[\"actionId\",\"openMode\"],\"properties\":{\"actionId\":{\"enum\":[\"create\",\"edit\",\"view\"]},\"openMode\":{\"enum\":[\"route\",\"modal\",\"drawer\"]},\"route\":{\"type\":\"string\"},\"formId\":{\"type\":\"string\"},\"form\":{\"type\":\"object\",\"properties\":{\"schemaUrl\":{\"type\":\"string\"},\"submitUrl\":{\"type\":\"string\"},\"submitMethod\":{\"enum\":[\"post\",\"put\",\"patch\",\"delete\"]},\"apiEndpointKey\":{\"type\":\"string\"},\"initialValue\":{\"type\":\"object\"},\"layoutPolicy\":{\"type\":\"object\"}}},\"params\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"required\":[\"from\",\"to\",\"name\"],\"properties\":{\"from\":{\"type\":\"string\"},\"to\":{\"enum\":[\"routeParam\",\"query\",\"input\"]},\"name\":{\"type\":\"string\"}}}},\"back\":{\"type\":\"object\"}}},\"failureModes\":[\"action-not-found\",\"open-mode-binding-incomplete\",\"schema-url-not-canonical\",\"submit-url-not-canonical\",\"resource-create-not-supported\"],\"description\":\"Configures create action binding and launcher inputs without editing the child FormConfig.\"}}],\"validators\":[\"action-exists\",\"open-mode-binding-complete\",\"schema-url-canonical\",\"submit-url-canonical\",\"resource-create-supported\",\"form-child-operation-delegated\"],\"affectedPaths\":[\"actions[].openMode\",\"actions[].route\",\"actions[].formId\",\"actions[].form\",\"actions[].params\",\"actions[].back\"],\"submissionImpact\":\"affects-schema-backed-data\",\"preconditions\":[\"crud-metadata-loaded\",\"resource-capabilities-resolved\"]},{\"operationId\":\"surface.edit.configure\",\"title\":\"Configure edit surface\",\"scope\":\"interaction\",\"targetKind\":\"editSurface\",\"target\":{\"kind\":\"editSurface\",\"resolver\":\"crud-action-by-id:edit\",\"ambiguityPolicy\":\"fail\",\"required\":true},\"inputSchema\":{\"type\":\"object\",\"required\":[\"actionId\",\"openMode\"],\"properties\":{\"actionId\":{\"enum\":[\"create\",\"edit\",\"view\"]},\"openMode\":{\"enum\":[\"route\",\"modal\",\"drawer\"]},\"route\":{\"type\":\"string\"},\"formId\":{\"type\":\"string\"},\"form\":{\"type\":\"object\",\"properties\":{\"schemaUrl\":{\"type\":\"string\"},\"submitUrl\":{\"type\":\"string\"},\"submitMethod\":{\"enum\":[\"post\",\"put\",\"patch\",\"delete\"]},\"apiEndpointKey\":{\"type\":\"string\"},\"initialValue\":{\"type\":\"object\"},\"layoutPolicy\":{\"type\":\"object\"}}},\"params\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"required\":[\"from\",\"to\",\"name\"],\"properties\":{\"from\":{\"type\":\"string\"},\"to\":{\"enum\":[\"routeParam\",\"query\",\"input\"]},\"name\":{\"type\":\"string\"}}}},\"back\":{\"type\":\"object\"}}},\"effects\":[{\"kind\":\"compile-domain-patch\",\"handler\":\"crud-edit-surface-configure\",\"handlerContract\":{\"reads\":[\"CrudMetadata.actions\",\"CrudMetadata.resource.idField\",\"CrudLauncherService.resolveOpenMode\",\"api_metadata\"],\"writes\":[\"CrudMetadata.actions[]\",\"CrudMetadata.actions[].form\",\"CrudMetadata.actions[].params\",\"CrudMetadata.actions[].back\"],\"identityKeys\":[\"actionId\"],\"inputSchema\":{\"type\":\"object\",\"required\":[\"actionId\",\"openMode\"],\"properties\":{\"actionId\":{\"enum\":[\"create\",\"edit\",\"view\"]},\"openMode\":{\"enum\":[\"route\",\"modal\",\"drawer\"]},\"route\":{\"type\":\"string\"},\"formId\":{\"type\":\"string\"},\"form\":{\"type\":\"object\",\"properties\":{\"schemaUrl\":{\"type\":\"string\"},\"submitUrl\":{\"type\":\"string\"},\"submitMethod\":{\"enum\":[\"post\",\"put\",\"patch\",\"delete\"]},\"apiEndpointKey\":{\"type\":\"string\"},\"initialValue\":{\"type\":\"object\"},\"layoutPolicy\":{\"type\":\"object\"}}},\"params\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"required\":[\"from\",\"to\",\"name\"],\"properties\":{\"from\":{\"type\":\"string\"},\"to\":{\"enum\":[\"routeParam\",\"query\",\"input\"]},\"name\":{\"type\":\"string\"}}}},\"back\":{\"type\":\"object\"}}},\"failureModes\":[\"action-not-found\",\"id-param-missing\",\"open-mode-binding-incomplete\",\"resource-edit-not-supported\",\"submit-url-not-canonical\"],\"description\":\"Configures edit action routing/form binding and ensures id parameter mapping is available to the launcher.\"}}],\"validators\":[\"action-exists\",\"id-field-known\",\"id-param-mapping-valid\",\"open-mode-binding-complete\",\"schema-url-canonical\",\"submit-url-canonical\",\"resource-edit-supported\",\"form-child-operation-delegated\"],\"affectedPaths\":[\"actions[].openMode\",\"actions[].route\",\"actions[].formId\",\"actions[].form\",\"actions[].params\",\"actions[].back\"],\"submissionImpact\":\"affects-schema-backed-data\",\"preconditions\":[\"crud-metadata-loaded\",\"resource-capabilities-resolved\"]}]}",
7943
+ "content": "{\"schemaVersion\":\"1.0.0\",\"manifestVersion\":\"1.0.0\",\"componentId\":\"praxis-crud\",\"ownerPackage\":\"@praxisui/crud\",\"configSchemaId\":\"CrudMetadata\",\"chunkSection\":\"operations\",\"operations\":[{\"operationId\":\"surface.create.configure\",\"title\":\"Configure create surface\",\"scope\":\"interaction\",\"targetKind\":\"createSurface\",\"target\":{\"kind\":\"createSurface\",\"resolver\":\"crud-action-by-id:create\",\"ambiguityPolicy\":\"fail\",\"required\":true},\"inputSchema\":{\"type\":\"object\",\"required\":[\"actionId\",\"openMode\"],\"properties\":{\"actionId\":{\"enum\":[\"create\",\"edit\",\"view\"]},\"openMode\":{\"enum\":[\"route\",\"modal\",\"drawer\"]},\"route\":{\"type\":\"string\"},\"formId\":{\"type\":\"string\"},\"form\":{\"type\":\"object\",\"properties\":{\"submitLabel\":{\"type\":\"string\"},\"schemaUrl\":{\"type\":\"string\"},\"submitUrl\":{\"type\":\"string\"},\"submitMethod\":{\"enum\":[\"post\",\"put\",\"patch\",\"delete\"]},\"apiEndpointKey\":{\"type\":\"string\"},\"initialValue\":{\"type\":\"object\"},\"layoutPolicy\":{\"type\":\"object\"}}},\"params\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"required\":[\"from\",\"to\",\"name\"],\"properties\":{\"from\":{\"type\":\"string\"},\"to\":{\"enum\":[\"routeParam\",\"query\",\"input\"]},\"name\":{\"type\":\"string\"}}}},\"back\":{\"type\":\"object\"}}},\"effects\":[{\"kind\":\"compile-domain-patch\",\"handler\":\"crud-create-surface-configure\",\"handlerContract\":{\"reads\":[\"CrudMetadata.actions\",\"CrudLauncherService.resolveOpenMode\",\"DynamicFormDialogHostComponent\",\"api_metadata\"],\"writes\":[\"CrudMetadata.actions[]\",\"CrudMetadata.actions[].form\",\"CrudMetadata.actions[].params\",\"CrudMetadata.actions[].back\"],\"identityKeys\":[\"actionId\"],\"inputSchema\":{\"type\":\"object\",\"required\":[\"actionId\",\"openMode\"],\"properties\":{\"actionId\":{\"enum\":[\"create\",\"edit\",\"view\"]},\"openMode\":{\"enum\":[\"route\",\"modal\",\"drawer\"]},\"route\":{\"type\":\"string\"},\"formId\":{\"type\":\"string\"},\"form\":{\"type\":\"object\",\"properties\":{\"submitLabel\":{\"type\":\"string\"},\"schemaUrl\":{\"type\":\"string\"},\"submitUrl\":{\"type\":\"string\"},\"submitMethod\":{\"enum\":[\"post\",\"put\",\"patch\",\"delete\"]},\"apiEndpointKey\":{\"type\":\"string\"},\"initialValue\":{\"type\":\"object\"},\"layoutPolicy\":{\"type\":\"object\"}}},\"params\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"required\":[\"from\",\"to\",\"name\"],\"properties\":{\"from\":{\"type\":\"string\"},\"to\":{\"enum\":[\"routeParam\",\"query\",\"input\"]},\"name\":{\"type\":\"string\"}}}},\"back\":{\"type\":\"object\"}}},\"failureModes\":[\"action-not-found\",\"open-mode-binding-incomplete\",\"schema-url-not-canonical\",\"submit-url-not-canonical\",\"resource-create-not-supported\"],\"description\":\"Configures create action binding and launcher inputs without editing the child FormConfig.\"}}],\"validators\":[\"action-exists\",\"open-mode-binding-complete\",\"schema-url-canonical\",\"submit-url-canonical\",\"resource-create-supported\",\"form-child-operation-delegated\"],\"affectedPaths\":[\"actions[].openMode\",\"actions[].route\",\"actions[].formId\",\"actions[].form\",\"actions[].params\",\"actions[].back\"],\"submissionImpact\":\"affects-schema-backed-data\",\"preconditions\":[\"crud-metadata-loaded\",\"resource-capabilities-resolved\"]},{\"operationId\":\"surface.edit.configure\",\"title\":\"Configure edit surface\",\"scope\":\"interaction\",\"targetKind\":\"editSurface\",\"target\":{\"kind\":\"editSurface\",\"resolver\":\"crud-action-by-id:edit\",\"ambiguityPolicy\":\"fail\",\"required\":true},\"inputSchema\":{\"type\":\"object\",\"required\":[\"actionId\",\"openMode\"],\"properties\":{\"actionId\":{\"enum\":[\"create\",\"edit\",\"view\"]},\"openMode\":{\"enum\":[\"route\",\"modal\",\"drawer\"]},\"route\":{\"type\":\"string\"},\"formId\":{\"type\":\"string\"},\"form\":{\"type\":\"object\",\"properties\":{\"submitLabel\":{\"type\":\"string\"},\"schemaUrl\":{\"type\":\"string\"},\"submitUrl\":{\"type\":\"string\"},\"submitMethod\":{\"enum\":[\"post\",\"put\",\"patch\",\"delete\"]},\"apiEndpointKey\":{\"type\":\"string\"},\"initialValue\":{\"type\":\"object\"},\"layoutPolicy\":{\"type\":\"object\"}}},\"params\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"required\":[\"from\",\"to\",\"name\"],\"properties\":{\"from\":{\"type\":\"string\"},\"to\":{\"enum\":[\"routeParam\",\"query\",\"input\"]},\"name\":{\"type\":\"string\"}}}},\"back\":{\"type\":\"object\"}}},\"effects\":[{\"kind\":\"compile-domain-patch\",\"handler\":\"crud-edit-surface-configure\",\"handlerContract\":{\"reads\":[\"CrudMetadata.actions\",\"CrudMetadata.resource.idField\",\"CrudLauncherService.resolveOpenMode\",\"api_metadata\"],\"writes\":[\"CrudMetadata.actions[]\",\"CrudMetadata.actions[].form\",\"CrudMetadata.actions[].params\",\"CrudMetadata.actions[].back\"],\"identityKeys\":[\"actionId\"],\"inputSchema\":{\"type\":\"object\",\"required\":[\"actionId\",\"openMode\"],\"properties\":{\"actionId\":{\"enum\":[\"create\",\"edit\",\"view\"]},\"openMode\":{\"enum\":[\"route\",\"modal\",\"drawer\"]},\"route\":{\"type\":\"string\"},\"formId\":{\"type\":\"string\"},\"form\":{\"type\":\"object\",\"properties\":{\"submitLabel\":{\"type\":\"string\"},\"schemaUrl\":{\"type\":\"string\"},\"submitUrl\":{\"type\":\"string\"},\"submitMethod\":{\"enum\":[\"post\",\"put\",\"patch\",\"delete\"]},\"apiEndpointKey\":{\"type\":\"string\"},\"initialValue\":{\"type\":\"object\"},\"layoutPolicy\":{\"type\":\"object\"}}},\"params\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"required\":[\"from\",\"to\",\"name\"],\"properties\":{\"from\":{\"type\":\"string\"},\"to\":{\"enum\":[\"routeParam\",\"query\",\"input\"]},\"name\":{\"type\":\"string\"}}}},\"back\":{\"type\":\"object\"}}},\"failureModes\":[\"action-not-found\",\"id-param-missing\",\"open-mode-binding-incomplete\",\"resource-edit-not-supported\",\"submit-url-not-canonical\"],\"description\":\"Configures edit action routing/form binding and ensures id parameter mapping is available to the launcher.\"}}],\"validators\":[\"action-exists\",\"id-field-known\",\"id-param-mapping-valid\",\"open-mode-binding-complete\",\"schema-url-canonical\",\"submit-url-canonical\",\"resource-edit-supported\",\"form-child-operation-delegated\"],\"affectedPaths\":[\"actions[].openMode\",\"actions[].route\",\"actions[].formId\",\"actions[].form\",\"actions[].params\",\"actions[].back\"],\"submissionImpact\":\"affects-schema-backed-data\",\"preconditions\":[\"crud-metadata-loaded\",\"resource-capabilities-resolved\"]}]}",
7902
7944
  "sourcePointer": "projects/praxis-crud/src/lib/ai/praxis-crud-authoring-manifest.ts",
7903
- "contentHash": "3deb507703990cb7122d3f450c339c2546c7c9b01829f856a65a51de58d1847f",
7945
+ "contentHash": "a69add5e3a6a89e379839d5c8e148adbd16d897981f6036f8538ee08ea665b79",
7904
7946
  "sourceKind": "component_definition",
7905
7947
  "sourceId": "praxis-crud",
7906
7948
  "corpusVersion": "1.0.0"
@@ -7908,9 +7950,9 @@
7908
7950
  {
7909
7951
  "chunkIndex": 27,
7910
7952
  "chunkKind": "authoring_manifest",
7911
- "content": "{\"schemaVersion\":\"1.0.0\",\"manifestVersion\":\"1.0.0\",\"componentId\":\"praxis-crud\",\"ownerPackage\":\"@praxisui/crud\",\"configSchemaId\":\"CrudMetadata\",\"chunkSection\":\"operations\",\"operations\":[{\"operationId\":\"surface.view.configure\",\"title\":\"Configure view surface\",\"scope\":\"interaction\",\"targetKind\":\"viewSurface\",\"target\":{\"kind\":\"viewSurface\",\"resolver\":\"crud-action-by-id:view\",\"ambiguityPolicy\":\"fail\",\"required\":true},\"inputSchema\":{\"type\":\"object\",\"required\":[\"actionId\",\"openMode\"],\"properties\":{\"actionId\":{\"enum\":[\"create\",\"edit\",\"view\"]},\"openMode\":{\"enum\":[\"route\",\"modal\",\"drawer\"]},\"route\":{\"type\":\"string\"},\"formId\":{\"type\":\"string\"},\"form\":{\"type\":\"object\",\"properties\":{\"schemaUrl\":{\"type\":\"string\"},\"submitUrl\":{\"type\":\"string\"},\"submitMethod\":{\"enum\":[\"post\",\"put\",\"patch\",\"delete\"]},\"apiEndpointKey\":{\"type\":\"string\"},\"initialValue\":{\"type\":\"object\"},\"layoutPolicy\":{\"type\":\"object\"}}},\"params\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"required\":[\"from\",\"to\",\"name\"],\"properties\":{\"from\":{\"type\":\"string\"},\"to\":{\"enum\":[\"routeParam\",\"query\",\"input\"]},\"name\":{\"type\":\"string\"}}}},\"back\":{\"type\":\"object\"}}},\"effects\":[{\"kind\":\"compile-domain-patch\",\"handler\":\"crud-view-surface-configure\",\"handlerContract\":{\"reads\":[\"CrudMetadata.actions\",\"CrudLauncherService.resolveOpenMode\",\"DynamicFormDialogHostComponent\",\"api_metadata\"],\"writes\":[\"CrudMetadata.actions[]\",\"CrudMetadata.actions[].form\",\"CrudMetadata.actions[].params\",\"CrudMetadata.actions[].back\"],\"identityKeys\":[\"actionId\"],\"inputSchema\":{\"type\":\"object\",\"required\":[\"actionId\",\"openMode\"],\"properties\":{\"actionId\":{\"enum\":[\"create\",\"edit\",\"view\"]},\"openMode\":{\"enum\":[\"route\",\"modal\",\"drawer\"]},\"route\":{\"type\":\"string\"},\"formId\":{\"type\":\"string\"},\"form\":{\"type\":\"object\",\"properties\":{\"schemaUrl\":{\"type\":\"string\"},\"submitUrl\":{\"type\":\"string\"},\"submitMethod\":{\"enum\":[\"post\",\"put\",\"patch\",\"delete\"]},\"apiEndpointKey\":{\"type\":\"string\"},\"initialValue\":{\"type\":\"object\"},\"layoutPolicy\":{\"type\":\"object\"}}},\"params\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"required\":[\"from\",\"to\",\"name\"],\"properties\":{\"from\":{\"type\":\"string\"},\"to\":{\"enum\":[\"routeParam\",\"query\",\"input\"]},\"name\":{\"type\":\"string\"}}}},\"back\":{\"type\":\"object\"}}},\"failureModes\":[\"action-not-found\",\"open-mode-binding-incomplete\",\"resource-view-not-supported\",\"readonly-form-delegation-missing\"],\"description\":\"Configures view action binding and delegates readonly form behavior to the dynamic-form manifest.\"}}],\"validators\":[\"action-exists\",\"open-mode-binding-complete\",\"schema-url-canonical\",\"resource-view-supported\",\"form-child-operation-delegated\",\"readonly-form-delegation-valid\"],\"affectedPaths\":[\"actions[].openMode\",\"actions[].route\",\"actions[].formId\",\"actions[].form\",\"actions[].params\",\"actions[].back\"],\"submissionImpact\":\"config-only\",\"preconditions\":[\"crud-metadata-loaded\",\"resource-capabilities-resolved\"]},{\"operationId\":\"delete.enabled.set\",\"title\":\"Configure delete behavior\",\"scope\":\"interaction\",\"targetKind\":\"deleteBehavior\",\"target\":{\"kind\":\"deleteBehavior\",\"resolver\":\"crud-action-by-id:delete\",\"ambiguityPolicy\":\"fail\",\"required\":true},\"inputSchema\":{\"type\":\"object\",\"required\":[\"enabled\"],\"properties\":{\"enabled\":{\"type\":\"boolean\"},\"actionId\":{\"type\":\"string\"},\"requiresConfirmation\":{\"type\":\"boolean\"},\"autoDelete\":{\"type\":\"boolean\"},\"form\":{\"type\":\"object\",\"properties\":{\"submitUrl\":{\"type\":\"string\"},\"submitMethod\":{\"enum\":[\"delete\"]},\"apiEndpointKey\":{\"type\":\"string\"}}}}},\"effects\":[{\"kind\":\"compile-domain-patch\",\"handler\":\"crud-delete-behavior-set\",\"handlerContract\":{\"reads\":[\"CrudMetadata.actions\",\"CrudMetadata.resource\",\"GET /{resource}/{id}/capabilities\"],\"writes\":[\"CrudMetadata.actions[]\",\"CrudMetadata.actions[].requiresConfirmation\",\"CrudMetadata.actions[].autoDelete\",\"CrudMetadata.actions[].form\"],\"identityKeys\":[\"actionId\"],\"inputSchema\":{\"type\":\"object\",\"required\":[\"enabled\"],\"properties\":{\"enabled\":{\"type\":\"boolean\"},\"actionId\":{\"type\":\"string\"},\"requiresConfirmation\":{\"type\":\"boolean\"},\"autoDelete\":{\"type\":\"boolean\"},\"form\":{\"type\":\"object\",\"properties\":{\"submitUrl\":{\"type\":\"string\"},\"submitMethod\":{\"enum\":[\"delete\"]},\"apiEndpointKey\":{\"type\":\"string\"}}}}},\"failureModes\":[\"delete-action-not-found\",\"resource-delete-not-supported\",\"destructive-delete-not-confirmed\",\"delete-submit-url-not-canonical\"],\"description\":\"Enables or disables delete behavior with capability checks and explicit confirmation for destructive changes.\"}}],\"destructive\":true,\"requiresConfirmation\":true,\"validators\":[\"delete-action-exists\",\"resource-delete-supported\",\"destructive-delete-confirmed\",\"submit-url-canonical\",\"permissions-delete-valid\"],\"affectedPaths\":[\"actions[].disabled\",\"actions[].requiresConfirmation\",\"actions[].autoDelete\",\"actions[].form\",\"actions[].form.submitUrl\",\"actions[].form.submitMethod\",\"actions[].form.apiEndpointKey\"],\"submissionImpact\":\"affects-schema-backed-data\",\"preconditions\":[\"crud-metadata-loaded\",\"resource-capabilities-resolved\",\"explicit-confirmation-provided\"]},{\"operationId\":\"dialog.size.set\",\"title\":\"Configure CRUD dialog host defaults\",\"scope\":\"interaction\",\"targetKind\":\"dialogHost\",\"target\":{\"kind\":\"dialogHost\",\"resolver\":\"crud-dialog-host-defaults\",\"ambiguityPolicy\":\"fail\",\"required\":true},\"inputSchema\":{\"type\":\"object\",\"properties\":{\"defaultOpenMode\":{\"enum\":[\"route\",\"modal\",\"drawer\"]},\"modal\":{\"type\":\"object\",\"properties\":{\"width\":{\"type\":\"string\"},\"height\":{\"type\":\"string\"},\"minWidth\":{\"type\":\"string\"},\"minHeight\":{\"type\":\"string\"},\"maxWidth\":{\"type\":\"string\"},\"maxHeight\":{\"type\":\"string\"},\"density\":{\"type\":\"string\"},\"backdropStyle\":{\"enum\":[\"blur\",\"dim\",\"transparent\"]},\"canMaximize\":{\"type\":\"boolean\"},\"rememberLastState\":{\"type\":\"boolean\"},\"closeOnSave\":{\"type\":\"boolean\"},\"startMaximized\":{\"type\":\"boolean\"},\"disableCloseOnEsc\":{\"type\":\"boolean\"},\"disableCloseOnBackdrop\":{\"type\":\"boolean\"},\"fullscreenBreakpoint\":{\"type\":\"number\"},\"position\":{\"type\":\"object\",\"properties\":{\"top\":{\"type\":\"string\"},\"bottom\":{\"type\":\"string\"},\"left\":{\"type\":\"string\"},\"right\":{\"type\":\"string\"}}},\"edgeGap\":{\"type\":\"number\"}}},\"back\":{\"type\":\"object\"}}},\"effects\":[{\"kind\":\"compile-domain-patch\",\"handler\":\"crud-dialog-host-set\",\"handlerContract\":{\"reads\":[\"CrudMetadata.defaults\",\"CrudLauncherService.resolveOpenMode\",\"DialogService\",\"DynamicFormDialogHostComponent\",\"CRUD_DRAWER_ADAPTER\"],\"writes\":[\"CrudMetadata.defaults.openMode\",\"CrudMetadata.defaults.modal\",\"CrudMetadata.defaults.back\"],\"identityKeys\":[\"crudId\"],\"inputSchema\":{\"type\":\"object\",\"properties\":{\"defaultOpenMode\":{\"enum\":[\"route\",\"modal\",\"drawer\"]},\"modal\":{\"type\":\"object\",\"properties\":{\"width\":{\"type\":\"string\"},\"height\":{\"type\":\"string\"},\"minWidth\":{\"type\":\"string\"},\"minHeight\":{\"type\":\"string\"},\"maxWidth\":{\"type\":\"string\"},\"maxHeight\":{\"type\":\"string\"},\"density\":{\"type\":\"string\"},\"backdropStyle\":{\"enum\":[\"blur\",\"dim\",\"transparent\"]},\"canMaximize\":{\"type\":\"boolean\"},\"rememberLastState\":{\"type\":\"boolean\"},\"closeOnSave\":{\"type\":\"boolean\"},\"startMaximized\":{\"type\":\"boolean\"},\"disableCloseOnEsc\":{\"type\":\"boolean\"},\"disableCloseOnBackdrop\":{\"type\":\"boolean\"},\"fullscreenBreakpoint\":{\"type\":\"number\"},\"position\":{\"type\":\"object\",\"properties\":{\"top\":{\"type\":\"string\"},\"bottom\":{\"type\":\"string\"},\"left\":{\"type\":\"string\"},\"right\":{\"type\":\"string\"}}},\"edgeGap\":{\"type\":\"number\"}}},\"back\":{\"type\":\"object\"}}},\"failureModes\":[\"open-mode-unsupported\",\"drawer-runtime-unavailable\",\"modal-size-invalid\",\"drawer-position-lifecycle-unstable\",\"back-policy-invalid\"],\"description\":\"Configures CRUD-owned route/modal/drawer defaults consumed by the launcher, default dialog-backed drawer runtime and optional host drawer adapter.\"}}],\"validators\":[\"open-mode-supported\",\"modal-size-valid\",\"drawer-runtime-available\",\"drawer-position-lifecycle-stable\",\"back-policy-valid\",\"settings-panel-shell-compatible\"],\"affectedPaths\":[\"defaults.openMode\",\"defaults.modal\",\"defaults.back\"],\"submissionImpact\":\"config-only\",\"preconditions\":[\"crud-metadata-loaded\"]}]}",
7953
+ "content": "{\"schemaVersion\":\"1.0.0\",\"manifestVersion\":\"1.0.0\",\"componentId\":\"praxis-crud\",\"ownerPackage\":\"@praxisui/crud\",\"configSchemaId\":\"CrudMetadata\",\"chunkSection\":\"operations\",\"operations\":[{\"operationId\":\"surface.view.configure\",\"title\":\"Configure view surface\",\"scope\":\"interaction\",\"targetKind\":\"viewSurface\",\"target\":{\"kind\":\"viewSurface\",\"resolver\":\"crud-action-by-id:view\",\"ambiguityPolicy\":\"fail\",\"required\":true},\"inputSchema\":{\"type\":\"object\",\"required\":[\"actionId\",\"openMode\"],\"properties\":{\"actionId\":{\"enum\":[\"create\",\"edit\",\"view\"]},\"openMode\":{\"enum\":[\"route\",\"modal\",\"drawer\"]},\"route\":{\"type\":\"string\"},\"formId\":{\"type\":\"string\"},\"form\":{\"type\":\"object\",\"properties\":{\"submitLabel\":{\"type\":\"string\"},\"schemaUrl\":{\"type\":\"string\"},\"submitUrl\":{\"type\":\"string\"},\"submitMethod\":{\"enum\":[\"post\",\"put\",\"patch\",\"delete\"]},\"apiEndpointKey\":{\"type\":\"string\"},\"initialValue\":{\"type\":\"object\"},\"layoutPolicy\":{\"type\":\"object\"}}},\"params\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"required\":[\"from\",\"to\",\"name\"],\"properties\":{\"from\":{\"type\":\"string\"},\"to\":{\"enum\":[\"routeParam\",\"query\",\"input\"]},\"name\":{\"type\":\"string\"}}}},\"back\":{\"type\":\"object\"}}},\"effects\":[{\"kind\":\"compile-domain-patch\",\"handler\":\"crud-view-surface-configure\",\"handlerContract\":{\"reads\":[\"CrudMetadata.actions\",\"CrudLauncherService.resolveOpenMode\",\"DynamicFormDialogHostComponent\",\"api_metadata\"],\"writes\":[\"CrudMetadata.actions[]\",\"CrudMetadata.actions[].form\",\"CrudMetadata.actions[].params\",\"CrudMetadata.actions[].back\"],\"identityKeys\":[\"actionId\"],\"inputSchema\":{\"type\":\"object\",\"required\":[\"actionId\",\"openMode\"],\"properties\":{\"actionId\":{\"enum\":[\"create\",\"edit\",\"view\"]},\"openMode\":{\"enum\":[\"route\",\"modal\",\"drawer\"]},\"route\":{\"type\":\"string\"},\"formId\":{\"type\":\"string\"},\"form\":{\"type\":\"object\",\"properties\":{\"submitLabel\":{\"type\":\"string\"},\"schemaUrl\":{\"type\":\"string\"},\"submitUrl\":{\"type\":\"string\"},\"submitMethod\":{\"enum\":[\"post\",\"put\",\"patch\",\"delete\"]},\"apiEndpointKey\":{\"type\":\"string\"},\"initialValue\":{\"type\":\"object\"},\"layoutPolicy\":{\"type\":\"object\"}}},\"params\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"required\":[\"from\",\"to\",\"name\"],\"properties\":{\"from\":{\"type\":\"string\"},\"to\":{\"enum\":[\"routeParam\",\"query\",\"input\"]},\"name\":{\"type\":\"string\"}}}},\"back\":{\"type\":\"object\"}}},\"failureModes\":[\"action-not-found\",\"open-mode-binding-incomplete\",\"resource-view-not-supported\",\"readonly-form-delegation-missing\"],\"description\":\"Configures view action binding and delegates readonly form behavior to the dynamic-form manifest.\"}}],\"validators\":[\"action-exists\",\"open-mode-binding-complete\",\"schema-url-canonical\",\"resource-view-supported\",\"form-child-operation-delegated\",\"readonly-form-delegation-valid\"],\"affectedPaths\":[\"actions[].openMode\",\"actions[].route\",\"actions[].formId\",\"actions[].form\",\"actions[].params\",\"actions[].back\"],\"submissionImpact\":\"config-only\",\"preconditions\":[\"crud-metadata-loaded\",\"resource-capabilities-resolved\"]},{\"operationId\":\"delete.enabled.set\",\"title\":\"Configure delete behavior\",\"scope\":\"interaction\",\"targetKind\":\"deleteBehavior\",\"target\":{\"kind\":\"deleteBehavior\",\"resolver\":\"crud-action-by-id:delete\",\"ambiguityPolicy\":\"fail\",\"required\":true},\"inputSchema\":{\"type\":\"object\",\"required\":[\"enabled\"],\"properties\":{\"enabled\":{\"type\":\"boolean\"},\"actionId\":{\"type\":\"string\"},\"requiresConfirmation\":{\"type\":\"boolean\"},\"autoDelete\":{\"type\":\"boolean\"},\"form\":{\"type\":\"object\",\"properties\":{\"submitUrl\":{\"type\":\"string\"},\"submitMethod\":{\"enum\":[\"delete\"]},\"apiEndpointKey\":{\"type\":\"string\"}}}}},\"effects\":[{\"kind\":\"compile-domain-patch\",\"handler\":\"crud-delete-behavior-set\",\"handlerContract\":{\"reads\":[\"CrudMetadata.actions\",\"CrudMetadata.resource\",\"GET /{resource}/{id}/capabilities\"],\"writes\":[\"CrudMetadata.actions[]\",\"CrudMetadata.actions[].requiresConfirmation\",\"CrudMetadata.actions[].autoDelete\",\"CrudMetadata.actions[].form\"],\"identityKeys\":[\"actionId\"],\"inputSchema\":{\"type\":\"object\",\"required\":[\"enabled\"],\"properties\":{\"enabled\":{\"type\":\"boolean\"},\"actionId\":{\"type\":\"string\"},\"requiresConfirmation\":{\"type\":\"boolean\"},\"autoDelete\":{\"type\":\"boolean\"},\"form\":{\"type\":\"object\",\"properties\":{\"submitUrl\":{\"type\":\"string\"},\"submitMethod\":{\"enum\":[\"delete\"]},\"apiEndpointKey\":{\"type\":\"string\"}}}}},\"failureModes\":[\"delete-action-not-found\",\"resource-delete-not-supported\",\"destructive-delete-not-confirmed\",\"delete-submit-url-not-canonical\"],\"description\":\"Enables or disables delete behavior with capability checks and explicit confirmation for destructive changes.\"}}],\"destructive\":true,\"requiresConfirmation\":true,\"validators\":[\"delete-action-exists\",\"resource-delete-supported\",\"destructive-delete-confirmed\",\"submit-url-canonical\",\"permissions-delete-valid\"],\"affectedPaths\":[\"actions[].disabled\",\"actions[].requiresConfirmation\",\"actions[].autoDelete\",\"actions[].form\",\"actions[].form.submitUrl\",\"actions[].form.submitMethod\",\"actions[].form.apiEndpointKey\"],\"submissionImpact\":\"affects-schema-backed-data\",\"preconditions\":[\"crud-metadata-loaded\",\"resource-capabilities-resolved\",\"explicit-confirmation-provided\"]},{\"operationId\":\"dialog.size.set\",\"title\":\"Configure CRUD dialog host defaults\",\"scope\":\"interaction\",\"targetKind\":\"dialogHost\",\"target\":{\"kind\":\"dialogHost\",\"resolver\":\"crud-dialog-host-defaults\",\"ambiguityPolicy\":\"fail\",\"required\":true},\"inputSchema\":{\"type\":\"object\",\"properties\":{\"defaultOpenMode\":{\"enum\":[\"route\",\"modal\",\"drawer\"]},\"modal\":{\"type\":\"object\",\"properties\":{\"width\":{\"type\":\"string\"},\"height\":{\"type\":\"string\"},\"minWidth\":{\"type\":\"string\"},\"minHeight\":{\"type\":\"string\"},\"maxWidth\":{\"type\":\"string\"},\"maxHeight\":{\"type\":\"string\"},\"density\":{\"type\":\"string\"},\"backdropStyle\":{\"enum\":[\"blur\",\"dim\",\"transparent\"]},\"canMaximize\":{\"type\":\"boolean\"},\"rememberLastState\":{\"type\":\"boolean\"},\"closeOnSave\":{\"type\":\"boolean\"},\"startMaximized\":{\"type\":\"boolean\"},\"disableCloseOnEsc\":{\"type\":\"boolean\"},\"disableCloseOnBackdrop\":{\"type\":\"boolean\"},\"fullscreenBreakpoint\":{\"type\":\"number\"},\"position\":{\"type\":\"object\",\"properties\":{\"top\":{\"type\":\"string\"},\"bottom\":{\"type\":\"string\"},\"left\":{\"type\":\"string\"},\"right\":{\"type\":\"string\"}}},\"edgeGap\":{\"type\":\"number\"}}},\"back\":{\"type\":\"object\"}}},\"effects\":[{\"kind\":\"compile-domain-patch\",\"handler\":\"crud-dialog-host-set\",\"handlerContract\":{\"reads\":[\"CrudMetadata.defaults\",\"CrudLauncherService.resolveOpenMode\",\"DialogService\",\"DynamicFormDialogHostComponent\",\"CRUD_DRAWER_ADAPTER\"],\"writes\":[\"CrudMetadata.defaults.openMode\",\"CrudMetadata.defaults.modal\",\"CrudMetadata.defaults.back\"],\"identityKeys\":[\"crudId\"],\"inputSchema\":{\"type\":\"object\",\"properties\":{\"defaultOpenMode\":{\"enum\":[\"route\",\"modal\",\"drawer\"]},\"modal\":{\"type\":\"object\",\"properties\":{\"width\":{\"type\":\"string\"},\"height\":{\"type\":\"string\"},\"minWidth\":{\"type\":\"string\"},\"minHeight\":{\"type\":\"string\"},\"maxWidth\":{\"type\":\"string\"},\"maxHeight\":{\"type\":\"string\"},\"density\":{\"type\":\"string\"},\"backdropStyle\":{\"enum\":[\"blur\",\"dim\",\"transparent\"]},\"canMaximize\":{\"type\":\"boolean\"},\"rememberLastState\":{\"type\":\"boolean\"},\"closeOnSave\":{\"type\":\"boolean\"},\"startMaximized\":{\"type\":\"boolean\"},\"disableCloseOnEsc\":{\"type\":\"boolean\"},\"disableCloseOnBackdrop\":{\"type\":\"boolean\"},\"fullscreenBreakpoint\":{\"type\":\"number\"},\"position\":{\"type\":\"object\",\"properties\":{\"top\":{\"type\":\"string\"},\"bottom\":{\"type\":\"string\"},\"left\":{\"type\":\"string\"},\"right\":{\"type\":\"string\"}}},\"edgeGap\":{\"type\":\"number\"}}},\"back\":{\"type\":\"object\"}}},\"failureModes\":[\"open-mode-unsupported\",\"drawer-runtime-unavailable\",\"modal-size-invalid\",\"drawer-position-lifecycle-unstable\",\"back-policy-invalid\"],\"description\":\"Configures CRUD-owned route/modal/drawer defaults consumed by the launcher, default dialog-backed drawer runtime and optional host drawer adapter.\"}}],\"validators\":[\"open-mode-supported\",\"modal-size-valid\",\"drawer-runtime-available\",\"drawer-position-lifecycle-stable\",\"back-policy-valid\",\"settings-panel-shell-compatible\"],\"affectedPaths\":[\"defaults.openMode\",\"defaults.modal\",\"defaults.back\"],\"submissionImpact\":\"config-only\",\"preconditions\":[\"crud-metadata-loaded\"]}]}",
7912
7954
  "sourcePointer": "projects/praxis-crud/src/lib/ai/praxis-crud-authoring-manifest.ts",
7913
- "contentHash": "4f5db040ac558fe75f10d94b93027509881c104ecb7c345ee929f58c86ab62ca",
7955
+ "contentHash": "aeac1aa4a0974965ee0dd0a53fe3e1c24cea2bdef83e2d36fb545e03204d112e",
7914
7956
  "sourceKind": "component_definition",
7915
7957
  "sourceId": "praxis-crud",
7916
7958
  "corpusVersion": "1.0.0"
@@ -7958,9 +8000,9 @@
7958
8000
  {
7959
8001
  "chunkIndex": 32,
7960
8002
  "chunkKind": "context_pack",
7961
- "content": "{\"componentContext\":{\"version\":\"v1\",\"optionsByPath\":{\"defaults.openMode\":{\"mode\":\"enum\",\"options\":[{\"value\":\"route\",\"label\":\"Route\"},{\"value\":\"modal\",\"label\":\"Modal\"},{\"value\":\"drawer\",\"label\":\"Drawer\"}]},\"actions[].openMode\":{\"mode\":\"enum\",\"options\":[{\"value\":\"route\",\"label\":\"Route\"},{\"value\":\"modal\",\"label\":\"Modal\"},{\"value\":\"drawer\",\"label\":\"Drawer\"}]},\"actions[].params[].to\":{\"mode\":\"enum\",\"options\":[{\"value\":\"routeParam\",\"label\":\"Route param\"},{\"value\":\"query\",\"label\":\"Query param\"},{\"value\":\"input\",\"label\":\"Dialog input\"}]},\"defaults.header.variant\":{\"mode\":\"enum\",\"options\":[{\"value\":\"ghost\",\"label\":\"Ghost\"},{\"value\":\"tonal\",\"label\":\"Tonal\"},{\"value\":\"outlined\",\"label\":\"Outlined\"}]},\"actions[].type\":{\"mode\":\"enum\",\"options\":[{\"value\":\"button\",\"label\":\"Button\"},{\"value\":\"icon\",\"label\":\"Icon\"},{\"value\":\"fab\",\"label\":\"Fab\"},{\"value\":\"menu\",\"label\":\"Menu\"}]},\"actions[].appearance\":{\"mode\":\"enum\",\"options\":[{\"value\":\"filled\",\"label\":\"Filled\"},{\"value\":\"outlined\",\"label\":\"Outlined\"},{\"value\":\"elevated\",\"label\":\"Elevated\"},{\"value\":\"text\",\"label\":\"Text\"},{\"value\":\"tonal\",\"label\":\"Tonal\"}]},\"actions[].position\":{\"mode\":\"enum\",\"options\":[{\"value\":\"start\",\"label\":\"Start\"},{\"value\":\"end\",\"label\":\"End\"}]},\"defaults.back.strategy\":{\"mode\":\"enum\",\"options\":[{\"value\":\"auto\",\"label\":\"Auto\"},{\"value\":\"close\",\"label\":\"Close\"},{\"value\":\"navigate\",\"label\":\"Navigate\"}]},\"actions[].back.strategy\":{\"mode\":\"enum\",\"options\":[{\"value\":\"auto\",\"label\":\"Auto\"},{\"value\":\"close\",\"label\":\"Close\"},{\"value\":\"navigate\",\"label\":\"Navigate\"}]},\"resource.endpointKey\":{\"mode\":\"enum\",\"options\":[{\"value\":\"default\",\"label\":\"Default\"},{\"value\":\"humanResources\",\"label\":\"Human resources\"},{\"value\":\"uiWrappersTest\",\"label\":\"UI wrappers test\"}]}},\"actionCatalog\":[{\"id\":\"resource.path.set\",\"intentExamples\":[\"resource\",\"endpoint\",\"api\",\"path\",\"rota\"],\"patchTemplate\":{\"resource\":{\"path\":\"{{value}}\"}}},{\"id\":\"resource.idField.set\",\"intentExamples\":[\"id field\",\"chave\",\"primary key\"],\"patchTemplate\":{\"resource\":{\"idField\":\"{{value}}\"}}},{\"id\":\"defaults.openMode.set\",\"intentExamples\":[\"open mode\",\"open\",\"route\",\"modal\",\"drawer\"],\"patchTemplate\":{\"defaults\":{\"openMode\":\"{{value}}\"}}},{\"id\":\"defaults.header.variant.set\",\"intentExamples\":[\"header\",\"variant\",\"style\",\"back button\"],\"patchTemplate\":{\"defaults\":{\"header\":{\"variant\":\"{{value}}\"}}}},{\"id\":\"defaults.header.backLabel.set\",\"intentExamples\":[\"back label\",\"voltar\",\"header label\"],\"patchTemplate\":{\"defaults\":{\"header\":{\"backLabel\":\"{{value}}\"}}}},{\"id\":\"defaults.header.showBack.enable\",\"intentExamples\":[\"show back\",\"back button\",\"enable back\"],\"patchTemplate\":{\"defaults\":{\"header\":{\"showBack\":true}}}},{\"id\":\"defaults.header.showBack.disable\",\"intentExamples\":[\"hide back\",\"disable back\"],\"patchTemplate\":{\"defaults\":{\"header\":{\"showBack\":false}}}},{\"id\":\"defaults.back.strategy.set\",\"intentExamples\":[\"back\",\"return\",\"navigation\"],\"patchTemplate\":{\"defaults\":{\"back\":{\"strategy\":\"{{value}}\"}}}},{\"id\":\"defaults.back.returnTo.set\",\"intentExamples\":[\"return to\",\"back route\",\"navigate back\"],\"patchTemplate\":{\"defaults\":{\"back\":{\"returnTo\":\"{{value}}\"}}}},{\"id\":\"defaults.back.confirmOnDirty.enable\",\"intentExamples\":[\"confirm\",\"dirty\",\"unsaved\",\"confirm exit\"],\"patchTemplate\":{\"defaults\":{\"back\":{\"confirmOnDirty\":true}}}},{\"id\":\"defaults.back.confirmOnDirty.disable\",\"intentExamples\":[\"no confirm\",\"disable confirm\"],\"patchTemplate\":{\"defaults\":{\"back\":{\"confirmOnDirty\":false}}}},{\"id\":\"action.add\",\"intentExamples\":[\"add action\",\"new action\",\"create action\"],\"patchTemplate\":{\"actions\":[{\"id\":\"{{target}}\",\"action\":\"{{params.action}}\",\"label\":\"{{value}}\",\"icon\":\"{{params.icon}}\"}]}},{\"id\":\"action.label.set\",\"intentExamples\":[\"label\",\"rename action\",\"titulo\"],\"patchTemplate\":{\"actions\":[{\"id\":\"{{target}}\",\"label\":\"{{value}}\"}]}},{\"id\":\"action.icon.set\",\"intentExamples\":[\"icon\",\"icone\"],\"patchTemplate\":{\"actions\":[{\"id\":\"{{target}}\",\"icon\":\"{{value}}\"}]}},{\"id\":\"action.openMode.set\",\"intentExamples\":[\"open mode\",\"route\",\"modal\",\"drawer\"],\"patchTemplate\":{\"actions\":[{\"id\":\"{{target}}\",\"openMode\":\"{{value}}\"}]}},{\"id\":\"action.route.set\",\"intentExamples\":[\"route\",\"url\",\"navigate\"],\"patchTemplate\":{\"actions\":[{\"id\":\"{{target}}\",\"route\":\"{{value}}\"}]}},{\"id\":\"action.formId.set\",\"intentExamples\":[\"form\",\"formId\",\"dialog\",\"drawer\"],\"patchTemplate\":{\"actions\":[{\"id\":\"{{target}}\",\"formId\":\"{{value}}\"}]}},{\"id\":\"action.params.add\",\"intentExamples\":[\"param\",\"params\",\"query\",\"route param\"],\"patchTemplate\":{\"actions\":[{\"id\":\"{{target}}\",\"params\":[{\"from\":\"{{params.from}}\",\"to\":\"{{params.to}}\",\"name\":\"{{params.name}}\"}]}]}},{\"id\":\"action.initialValue.set\",\"intentExamples\":[\"initial value\",\"seed\",\"default form values\",\"prefill\"],\"patchTemplate\":{\"actions\":[{\"id\":\"{{target}}\",\"form\":{\"initialValue\":\"{{value}}\"}}]}},{\"id\":\"action.confirmation.enable\",\"intentExamples\":[\"confirm\",\"confirmation\",\"requires confirmation\"],\"patchTemplate\":{\"actions\":[{\"id\":\"{{target}}\",\"requiresConfirmation\":true}]}},{\"id\":\"action.confirmation.disable\",\"intentExamples\":[\"no confirm\",\"disable confirmation\"],\"patchTemplate\":{\"actions\":[{\"id\":\"{{target}}\",\"requiresConfirmation\":false}]}},{\"id\":\"action.visibleWhen.set\",\"intentExamples\":[\"visible when\",\"visibility\",\"show when\"],\"patchTemplate\":{\"actions\":[{\"id\":\"{{target}}\",\"visibleWhen\":\"{{value}}\"}]}},{\"id\":\"action.type.set\",\"intentExamples\":[\"type\",\"button type\",\"toolbar\"],\"patchTemplate\":{\"actions\":[{\"id\":\"{{target}}\",\"type\":\"{{value}}\"}]}},{\"id\":\"action.appearance.set\",\"intentExamples\":[\"appearance\",\"variant\",\"style\"],\"patchTemplate\":{\"actions\":[{\"id\":\"{{target}}\",\"appearance\":\"{{value}}\"}]}},{\"id\":\"action.position.set\",\"intentExamples\":[\"position\",\"start\",\"end\"],\"patchTemplate\":{\"actions\":[{\"id\":\"{{target}}\",\"position\":\"{{value}}\"}]}},{\"id\":\"action.back.strategy.set\",\"intentExamples\":[\"back\",\"return\",\"navigation\"],\"patchTemplate\":{\"actions\":[{\"id\":\"{{target}}\",\"back\":{\"strategy\":\"{{value}}\"}}]}},{\"id\":\"ADD_CONDITIONAL_RENDERER\",\"intentExamples\":[\"conditional renderer\",\"renderer condicional\",\"badge condicional\",\"chip condicional\",\"badge se\",\"chip se\",\"conditional badge\",\"conditional chip\"],\"patchTemplate\":{\"table\":{\"columns\":[{\"field\":\"{{target}}\",\"conditionalRenderers\":[{\"condition\":\"{{params.condition}}\",\"renderer\":\"{{params.renderer}}\"}]}]}}}],\"fieldResolvers\":{\"actions[]\":[\"id\",\"label\",\"action\"],\"resource.path\":[],\"table.columns[].field\":[\"field\",\"header\"]},\"hints\":[\"Use actions[].id as the canonical action key; avoid array indexes.\",\"When adding actions, include params.action to describe the underlying CRUD action.\",\"openMode route requires actions[].route; modal or drawer require actions[].formId unless the host completes bindings via per-action override before opening.\",\"Table and form are full configs; patch nested fields instead of replacing the whole object.\",\"Use ADD_CONDITIONAL_RENDERER for table conditional badges/chips (table.columns[].conditionalRenderers).\",\"CRUD agrega TableConfig e FormConfig; siga o contrato da tabela para columns/conditionalRenderers.\",\"DOC: Widget purpose: CRUD shell that composes a table + optional form from metadata.\",\"DOC: Host inputs: metadata (required) and crudId (required). componentInstanceId/context/enableCustomization are optional.\",\"DOC: CrudMetadata requires component='praxis-crud' and table (TableConfig).\",\"DOC: inner table renders with resource.path (remote) or metadata.data (local). If both are provided, resource.path takes precedence.\",\"DOC: If actions open modal/drawer, actions[].formId is required unless a per-action override resolves it before opening; for route mode, actions[].route is required unless override resolves it.\"]}}",
8003
+ "content": "{\"componentContext\":{\"version\":\"v1\",\"optionsByPath\":{\"defaults.openMode\":{\"mode\":\"enum\",\"options\":[{\"value\":\"route\",\"label\":\"Route\"},{\"value\":\"modal\",\"label\":\"Modal\"},{\"value\":\"drawer\",\"label\":\"Drawer\"}]},\"actions[].openMode\":{\"mode\":\"enum\",\"options\":[{\"value\":\"route\",\"label\":\"Route\"},{\"value\":\"modal\",\"label\":\"Modal\"},{\"value\":\"drawer\",\"label\":\"Drawer\"}]},\"actions[].params[].to\":{\"mode\":\"enum\",\"options\":[{\"value\":\"routeParam\",\"label\":\"Route param\"},{\"value\":\"query\",\"label\":\"Query param\"},{\"value\":\"input\",\"label\":\"Dialog input\"}]},\"defaults.header.variant\":{\"mode\":\"enum\",\"options\":[{\"value\":\"ghost\",\"label\":\"Ghost\"},{\"value\":\"tonal\",\"label\":\"Tonal\"},{\"value\":\"outlined\",\"label\":\"Outlined\"}]},\"actions[].type\":{\"mode\":\"enum\",\"options\":[{\"value\":\"button\",\"label\":\"Button\"},{\"value\":\"icon\",\"label\":\"Icon\"},{\"value\":\"fab\",\"label\":\"Fab\"},{\"value\":\"menu\",\"label\":\"Menu\"}]},\"actions[].appearance\":{\"mode\":\"enum\",\"options\":[{\"value\":\"filled\",\"label\":\"Filled\"},{\"value\":\"outlined\",\"label\":\"Outlined\"},{\"value\":\"elevated\",\"label\":\"Elevated\"},{\"value\":\"text\",\"label\":\"Text\"},{\"value\":\"tonal\",\"label\":\"Tonal\"}]},\"actions[].position\":{\"mode\":\"enum\",\"options\":[{\"value\":\"start\",\"label\":\"Start\"},{\"value\":\"end\",\"label\":\"End\"}]},\"defaults.back.strategy\":{\"mode\":\"enum\",\"options\":[{\"value\":\"auto\",\"label\":\"Auto\"},{\"value\":\"close\",\"label\":\"Close\"},{\"value\":\"navigate\",\"label\":\"Navigate\"}]},\"actions[].back.strategy\":{\"mode\":\"enum\",\"options\":[{\"value\":\"auto\",\"label\":\"Auto\"},{\"value\":\"close\",\"label\":\"Close\"},{\"value\":\"navigate\",\"label\":\"Navigate\"}]},\"resource.endpointKey\":{\"mode\":\"enum\",\"options\":[{\"value\":\"default\",\"label\":\"Default\"},{\"value\":\"humanResources\",\"label\":\"Human resources\"},{\"value\":\"uiWrappersTest\",\"label\":\"UI wrappers test\"}]}},\"actionCatalog\":[{\"id\":\"resource.path.set\",\"intentExamples\":[\"resource\",\"endpoint\",\"api\",\"path\",\"rota\"],\"patchTemplate\":{\"resource\":{\"path\":\"{{value}}\"}}},{\"id\":\"resource.idField.set\",\"intentExamples\":[\"id field\",\"chave\",\"primary key\"],\"patchTemplate\":{\"resource\":{\"idField\":\"{{value}}\"}}},{\"id\":\"defaults.openMode.set\",\"intentExamples\":[\"open mode\",\"open\",\"route\",\"modal\",\"drawer\"],\"patchTemplate\":{\"defaults\":{\"openMode\":\"{{value}}\"}}},{\"id\":\"defaults.header.variant.set\",\"intentExamples\":[\"header\",\"variant\",\"style\",\"back button\"],\"patchTemplate\":{\"defaults\":{\"header\":{\"variant\":\"{{value}}\"}}}},{\"id\":\"defaults.header.backLabel.set\",\"intentExamples\":[\"back label\",\"voltar\",\"header label\"],\"patchTemplate\":{\"defaults\":{\"header\":{\"backLabel\":\"{{value}}\"}}}},{\"id\":\"defaults.header.showBack.enable\",\"intentExamples\":[\"show back\",\"back button\",\"enable back\"],\"patchTemplate\":{\"defaults\":{\"header\":{\"showBack\":true}}}},{\"id\":\"defaults.header.showBack.disable\",\"intentExamples\":[\"hide back\",\"disable back\"],\"patchTemplate\":{\"defaults\":{\"header\":{\"showBack\":false}}}},{\"id\":\"defaults.back.strategy.set\",\"intentExamples\":[\"back\",\"return\",\"navigation\"],\"patchTemplate\":{\"defaults\":{\"back\":{\"strategy\":\"{{value}}\"}}}},{\"id\":\"defaults.back.returnTo.set\",\"intentExamples\":[\"return to\",\"back route\",\"navigate back\"],\"patchTemplate\":{\"defaults\":{\"back\":{\"returnTo\":\"{{value}}\"}}}},{\"id\":\"defaults.back.confirmOnDirty.enable\",\"intentExamples\":[\"confirm\",\"dirty\",\"unsaved\",\"confirm exit\"],\"patchTemplate\":{\"defaults\":{\"back\":{\"confirmOnDirty\":true}}}},{\"id\":\"defaults.back.confirmOnDirty.disable\",\"intentExamples\":[\"no confirm\",\"disable confirm\"],\"patchTemplate\":{\"defaults\":{\"back\":{\"confirmOnDirty\":false}}}},{\"id\":\"action.add\",\"intentExamples\":[\"add action\",\"new action\",\"create action\"],\"patchTemplate\":{\"actions\":[{\"id\":\"{{target}}\",\"action\":\"{{params.action}}\",\"label\":\"{{value}}\",\"icon\":\"{{params.icon}}\"}]}},{\"id\":\"action.label.set\",\"intentExamples\":[\"label\",\"rename action\",\"titulo\"],\"patchTemplate\":{\"actions\":[{\"id\":\"{{target}}\",\"label\":\"{{value}}\"}]}},{\"id\":\"action.icon.set\",\"intentExamples\":[\"icon\",\"icone\"],\"patchTemplate\":{\"actions\":[{\"id\":\"{{target}}\",\"icon\":\"{{value}}\"}]}},{\"id\":\"action.openMode.set\",\"intentExamples\":[\"open mode\",\"route\",\"modal\",\"drawer\"],\"patchTemplate\":{\"actions\":[{\"id\":\"{{target}}\",\"openMode\":\"{{value}}\"}]}},{\"id\":\"action.route.set\",\"intentExamples\":[\"route\",\"url\",\"navigate\"],\"patchTemplate\":{\"actions\":[{\"id\":\"{{target}}\",\"route\":\"{{value}}\"}]}},{\"id\":\"action.formId.set\",\"intentExamples\":[\"form\",\"formId\",\"dialog\",\"drawer\"],\"patchTemplate\":{\"actions\":[{\"id\":\"{{target}}\",\"formId\":\"{{value}}\"}]}},{\"id\":\"action.submitLabel.set\",\"intentExamples\":[\"submit label\",\"save button label\",\"rótulo do botão salvar\"],\"patchTemplate\":{\"actions\":[{\"id\":\"{{target}}\",\"form\":{\"submitLabel\":\"{{value}}\"}}]}},{\"id\":\"action.params.add\",\"intentExamples\":[\"param\",\"params\",\"query\",\"route param\"],\"patchTemplate\":{\"actions\":[{\"id\":\"{{target}}\",\"params\":[{\"from\":\"{{params.from}}\",\"to\":\"{{params.to}}\",\"name\":\"{{params.name}}\"}]}]}},{\"id\":\"action.initialValue.set\",\"intentExamples\":[\"initial value\",\"seed\",\"default form values\",\"prefill\"],\"patchTemplate\":{\"actions\":[{\"id\":\"{{target}}\",\"form\":{\"initialValue\":\"{{value}}\"}}]}},{\"id\":\"action.confirmation.enable\",\"intentExamples\":[\"confirm\",\"confirmation\",\"requires confirmation\"],\"patchTemplate\":{\"actions\":[{\"id\":\"{{target}}\",\"requiresConfirmation\":true}]}},{\"id\":\"action.confirmation.disable\",\"intentExamples\":[\"no confirm\",\"disable confirmation\"],\"patchTemplate\":{\"actions\":[{\"id\":\"{{target}}\",\"requiresConfirmation\":false}]}},{\"id\":\"action.visibleWhen.set\",\"intentExamples\":[\"visible when\",\"visibility\",\"show when\"],\"patchTemplate\":{\"actions\":[{\"id\":\"{{target}}\",\"visibleWhen\":\"{{value}}\"}]}},{\"id\":\"action.type.set\",\"intentExamples\":[\"type\",\"button type\",\"toolbar\"],\"patchTemplate\":{\"actions\":[{\"id\":\"{{target}}\",\"type\":\"{{value}}\"}]}},{\"id\":\"action.appearance.set\",\"intentExamples\":[\"appearance\",\"variant\",\"style\"],\"patchTemplate\":{\"actions\":[{\"id\":\"{{target}}\",\"appearance\":\"{{value}}\"}]}},{\"id\":\"action.position.set\",\"intentExamples\":[\"position\",\"start\",\"end\"],\"patchTemplate\":{\"actions\":[{\"id\":\"{{target}}\",\"position\":\"{{value}}\"}]}},{\"id\":\"action.back.strategy.set\",\"intentExamples\":[\"back\",\"return\",\"navigation\"],\"patchTemplate\":{\"actions\":[{\"id\":\"{{target}}\",\"back\":{\"strategy\":\"{{value}}\"}}]}},{\"id\":\"ADD_CONDITIONAL_RENDERER\",\"intentExamples\":[\"conditional renderer\",\"renderer condicional\",\"badge condicional\",\"chip condicional\",\"badge se\",\"chip se\",\"conditional badge\",\"conditional chip\"],\"patchTemplate\":{\"table\":{\"columns\":[{\"field\":\"{{target}}\",\"conditionalRenderers\":[{\"condition\":\"{{params.condition}}\",\"renderer\":\"{{params.renderer}}\"}]}]}}}],\"fieldResolvers\":{\"actions[]\":[\"id\",\"label\",\"action\"],\"resource.path\":[],\"table.columns[].field\":[\"field\",\"header\"]},\"hints\":[\"Use actions[].id as the canonical action key; avoid array indexes.\",\"When adding actions, include params.action to describe the underlying CRUD action.\",\"openMode route requires actions[].route; modal or drawer require actions[].formId unless the host completes bindings via per-action override before opening.\",\"Table and form are full configs; patch nested fields instead of replacing the whole object.\",\"Use ADD_CONDITIONAL_RENDERER for table conditional badges/chips (table.columns[].conditionalRenderers).\",\"CRUD agrega TableConfig e FormConfig; siga o contrato da tabela para columns/conditionalRenderers.\",\"DOC: Widget purpose: CRUD shell that composes a table + optional form from metadata.\",\"DOC: Host inputs: metadata (required) and crudId (required). componentInstanceId/context/enableCustomization are optional.\",\"DOC: CrudMetadata requires component='praxis-crud' and table (TableConfig).\",\"DOC: inner table renders with resource.path (remote) or metadata.data (local). If both are provided, resource.path takes precedence.\",\"DOC: If actions open modal/drawer, actions[].formId is required unless a per-action override resolves it before opening; for route mode, actions[].route is required unless override resolves it.\"]}}",
7962
8004
  "sourcePointer": "projects/praxis-crud/src/lib/ai/crud-context-pack.ts",
7963
- "contentHash": "c33c6b5d3305fcacb2777515510d779fdef9f4ae5400458702c594c76d8986ab",
8005
+ "contentHash": "f3fee44b247f15b384b472ee2f3078d2f7dfe84a95d5b8e61379f863cd8adf85",
7964
8006
  "sourceKind": "component_definition",
7965
8007
  "sourceId": "praxis-crud",
7966
8008
  "corpusVersion": "1.0.0"
@@ -283,6 +283,7 @@ class CrudLauncherService {
283
283
  const mergedBackdropClasses = mergeClassList(backdropClasses, modalCfg.backdropClass);
284
284
  const ref = await this.dialog.openAsync(() => prefetchedDialogHost ?? this.loadDialogHost(), {
285
285
  ...modalCfg,
286
+ injector: runtime?.injector,
286
287
  panelClass: panelClasses,
287
288
  backdropClass: mergedBackdropClasses,
288
289
  autoFocus: modalCfg.autoFocus ?? true,
@@ -879,6 +880,7 @@ function normalizeCrudAction(action) {
879
880
  : undefined,
880
881
  form: action?.form
881
882
  ? {
883
+ submitLabel: trimString(action.form.submitLabel) || undefined,
882
884
  schemaUrl: trimString(action.form.schemaUrl) || undefined,
883
885
  submitUrl: trimString(action.form.submitUrl) || undefined,
884
886
  submitMethod: trimString(action.form.submitMethod) || undefined,
@@ -4193,7 +4195,7 @@ class PraxisCrudComponent {
4193
4195
  return;
4194
4196
  }
4195
4197
  if (!this.hasExplicitOpenBinding(effectiveAction)) {
4196
- const openedByDiscovery = await this.tryOpenDiscoveredCrudSurface(effectiveAction.action, contextualRow, runtimeEvent);
4198
+ const openedByDiscovery = await this.tryOpenDiscoveredCrudSurface(effectiveAction, contextualRow, runtimeEvent);
4197
4199
  if (openedByDiscovery) {
4198
4200
  return;
4199
4201
  }
@@ -4252,6 +4254,7 @@ class PraxisCrudComponent {
4252
4254
  showResourceIdentityKey: this.showResourceIdentityKey,
4253
4255
  focusOrigin: runtimeEvent?.focusOrigin ?? null,
4254
4256
  surfaceRuntime: this.resolveSurfaceRuntime(),
4257
+ injector: this.injector,
4255
4258
  });
4256
4259
  this.afterOpen.emit({ mode, action: effectiveAction.action });
4257
4260
  if (mode === 'drawer') {
@@ -4551,6 +4554,7 @@ class PraxisCrudComponent {
4551
4554
  links: this.tableCollectionLinks,
4552
4555
  showResourceIdentityKey: this.showResourceIdentityKey,
4553
4556
  surfaceRuntime: this.resolveSurfaceRuntime(),
4557
+ injector: this.injector,
4554
4558
  });
4555
4559
  this.afterOpen.emit({ mode, action: normalizedAction });
4556
4560
  if (mode !== 'drawer' && ref) {
@@ -4780,7 +4784,7 @@ class PraxisCrudComponent {
4780
4784
  return this.selectedRow ?? undefined;
4781
4785
  }
4782
4786
  async tryOpenDiscoveredCrudSurface(action, row, runtimeEvent) {
4783
- const normalizedAction = String(action || '').trim().toLowerCase();
4787
+ const normalizedAction = String(action.action || '').trim().toLowerCase();
4784
4788
  if (!this.surfaceService) {
4785
4789
  return false;
4786
4790
  }
@@ -4810,6 +4814,7 @@ class PraxisCrudComponent {
4810
4814
  subtitle: surface.description ?? undefined,
4811
4815
  parentIdentity: runtimeEvent?.resourceIdentity ?? null,
4812
4816
  });
4817
+ this.applyDiscoveredFormPresentationOverrides(payload, action);
4813
4818
  }
4814
4819
  catch (error) {
4815
4820
  this.error.emit(error);
@@ -4856,7 +4861,7 @@ class PraxisCrudComponent {
4856
4861
  this.bindDiscoveredSurfaceLifecycle(await openPromise);
4857
4862
  this.afterOpen.emit({
4858
4863
  mode: this.mapSurfacePresentationToCrudMode(payload?.presentation),
4859
- action,
4864
+ action: normalizedAction,
4860
4865
  });
4861
4866
  }
4862
4867
  catch (err) {
@@ -4864,6 +4869,43 @@ class PraxisCrudComponent {
4864
4869
  }
4865
4870
  return true;
4866
4871
  }
4872
+ /**
4873
+ * Keeps discovery authoritative for schema, operation and endpoint while
4874
+ * preserving presentation-only choices authored in the CRUD composition.
4875
+ */
4876
+ applyDiscoveredFormPresentationOverrides(payload, action) {
4877
+ if (payload?.widget?.id !== 'praxis-dynamic-form') {
4878
+ return;
4879
+ }
4880
+ const submitLabel = String(action.form?.submitLabel || '').trim();
4881
+ if (!submitLabel || String(action.action || '').trim().toLowerCase() === 'view') {
4882
+ return;
4883
+ }
4884
+ const inputs = payload.widget.inputs || (payload.widget.inputs = {});
4885
+ const configuredActions = this.isRecord(inputs['actions'])
4886
+ ? inputs['actions']
4887
+ : {};
4888
+ const configuredSubmit = this.isRecord(configuredActions['submit'])
4889
+ ? configuredActions['submit']
4890
+ : {};
4891
+ inputs['actions'] = {
4892
+ ...configuredActions,
4893
+ showSaveButton: true,
4894
+ showCancelButton: false,
4895
+ showResetButton: false,
4896
+ submit: {
4897
+ ...configuredSubmit,
4898
+ id: configuredSubmit['id'] || 'submit',
4899
+ type: 'submit',
4900
+ visible: true,
4901
+ label: submitLabel,
4902
+ },
4903
+ };
4904
+ const bindingOrder = Array.isArray(payload.widget.bindingOrder)
4905
+ ? payload.widget.bindingOrder.filter((input) => input !== 'actions')
4906
+ : [];
4907
+ payload.widget.bindingOrder = [...bindingOrder, 'actions'];
4908
+ }
4867
4909
  async resolveDiscoveredSurfaceCatalog(action, row) {
4868
4910
  try {
4869
4911
  if (action === 'create') {
@@ -6549,7 +6591,10 @@ class DynamicFormDialogHostComponent {
6549
6591
  }
6550
6592
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: DynamicFormDialogHostComponent, deps: [{ token: MatDialogRef, optional: true }, { token: MAT_DIALOG_DATA, optional: true }, { token: DialogService }, { token: i2$1.GenericCrudService }, { token: ASYNC_CONFIG_STORAGE }, { token: SURFACE_DRAWER_REF, optional: true }, { token: SURFACE_DRAWER_CONTENT_DATA, optional: true }], target: i0.ɵɵFactoryTarget.Component });
6551
6593
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: DynamicFormDialogHostComponent, isStandalone: true, selector: "praxis-dynamic-form-dialog-host", outputs: { reactiveDeterminationExecuted: "reactiveDeterminationExecuted", reactiveDeterminationPendingChange: "reactiveDeterminationPendingChange", reactiveDeterminationStabilityChange: "reactiveDeterminationStabilityChange" }, host: { properties: { "attr.data-density": "modal.density || \"default\"", "attr.data-presentation": "presentation", "class.praxis-drawer": "presentation === \"drawer\"", "class.praxis-surface-frame": "isSurfaceFrame" }, classAttribute: "praxis-dialog" }, providers: [
6552
- GenericCrudService,
6594
+ {
6595
+ provide: GenericCrudService,
6596
+ useFactory: () => inject(GenericCrudService, { skipSelf: true }),
6597
+ },
6553
6598
  providePraxisI18nConfig(PRAXIS_CRUD_RUNTIME_I18N_CONFIG),
6554
6599
  ], viewQueries: [{ propertyName: "formComp", first: true, predicate: PraxisDynamicForm, descendants: true }], ngImport: i0, template: `
6555
6600
  @if (!isSurfaceFrame) {
@@ -6652,7 +6697,7 @@ class DynamicFormDialogHostComponent {
6652
6697
  (reactiveDeterminationPendingChange)="onReactiveDeterminationPendingChange($event)"
6653
6698
  ></praxis-dynamic-form>
6654
6699
  </mat-dialog-content>
6655
- `, isInline: true, styles: ["praxis-dynamic-form-dialog-host{--dlg-header-h: 56px;--dlg-footer-h: 56px;--dlg-pad: 16px;display:flex;flex-direction:column;height:100%;overflow:hidden}praxis-dynamic-form-dialog-host[data-density=compact]{--dlg-header-h: 44px;--dlg-footer-h: 44px;--dlg-pad: 12px}praxis-dynamic-form-dialog-host .dialog-header{position:sticky;top:0;z-index:1;display:flex;align-items:center;gap:var(--dlg-pad);min-height:var(--dlg-header-h);padding:10px var(--dlg-pad);margin:0;background:var(--md-sys-color-surface-container-high);border-bottom:1px solid var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface)}praxis-dynamic-form-dialog-host .dialog-title{margin:0;font:inherit;font-weight:600;color:var(--md-sys-color-on-surface)}praxis-dynamic-form-dialog-host .dialog-heading{display:grid;min-width:0;gap:2px}praxis-dynamic-form-dialog-host .dialog-title-icon{display:inline-grid;flex:0 0 auto;width:36px;height:36px;place-items:center;border-radius:10px;color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 12%,transparent)}praxis-dynamic-form-dialog-host .dialog-title-icon mat-icon{width:22px;height:22px;font-size:22px}praxis-dynamic-form-dialog-host .dialog-subtitle{display:-webkit-box;overflow:hidden;color:var(--md-sys-color-on-surface-variant);font-size:.82rem;font-weight:400;line-height:1.35;-webkit-box-orient:vertical;-webkit-line-clamp:2}praxis-dynamic-form-dialog-host .spacer{flex:1}praxis-dynamic-form-dialog-host .dialog-content{flex:1 1 auto;overflow:auto;padding:var(--dlg-pad);max-height:calc(100svh - var(--dlg-header-h) - 32px)}praxis-dynamic-form-dialog-host .crud-operation-context{position:sticky;top:0;z-index:1;display:grid;gap:.75rem;margin-block-end:var(--dlg-pad);padding-block:.5rem .75rem;background:var(--pfx-form-surface, var(--md-sys-color-surface));border-bottom:1px solid var(--md-sys-color-outline-variant)}praxis-dynamic-form-dialog-host .crud-resource-identity{display:grid;gap:.25rem;min-width:0}praxis-dynamic-form-dialog-host .crud-resource-identity__label{color:var(--md-sys-color-on-surface-variant);font:var(--md-sys-typescale-label-medium, 500 .75rem/1rem inherit)}praxis-dynamic-form-dialog-host.praxis-drawer{--dlg-header-h: 72px;width:100%;min-width:0;max-width:100vw;height:100dvh;background:var(--pfx-form-surface, var(--md-sys-color-surface));color:var(--md-sys-color-on-surface)}praxis-dynamic-form-dialog-host.praxis-drawer .dialog-header{background:color-mix(in srgb,var(--md-sys-color-surface-container-high, var(--md-sys-color-surface)),transparent 4%)}praxis-dynamic-form-dialog-host.praxis-drawer .dialog-content{display:flex;flex-direction:column;max-height:none;min-height:0;padding:clamp(12px,2.4vw,24px)}praxis-dynamic-form-dialog-host.praxis-drawer .dialog-content>praxis-dynamic-form{display:block;flex:1 1 auto;min-height:0}praxis-dynamic-form-dialog-host.praxis-drawer .dialog-content>praxis-dynamic-form>.praxis-dynamic-form{min-height:100%}praxis-dynamic-form-dialog-host.praxis-drawer .dialog-content>praxis-dynamic-form>.praxis-dynamic-form>praxis-form-actions[data-actions-placement=afterSections]{margin-top:auto;padding-top:var(--pfx-actions-gap-top, var(--pfx-section-gap, 20px))}praxis-dynamic-form-dialog-host.praxis-surface-frame .dialog-content{max-height:none;min-height:0;padding:clamp(12px,2.4vw,24px)}praxis-dynamic-form-dialog-host .dialog-header button.praxis-icon-button{color:var(--md-sys-color-on-surface-variant)}praxis-dynamic-form-dialog-host .dialog-header button.praxis-icon-button:hover{color:var(--md-sys-color-primary)}praxis-dynamic-form-dialog-host .dialog-footer{position:sticky;bottom:0;z-index:1;padding:var(--dlg-pad)}.pfx-blur-backdrop{background-color:var(--pfx-backdrop, rgba(15, 23, 42, .42))!important;backdrop-filter:blur(var(--pfx-backdrop-blur, 10px)) saturate(110%);-webkit-backdrop-filter:blur(var(--pfx-backdrop-blur, 10px)) saturate(110%)}.pfx-transparent-backdrop{background-color:transparent!important}.cdk-overlay-pane.pfx-dialog-pane{overflow:hidden;transition:width .2s ease,height .2s ease,margin .2s ease}.cdk-overlay-pane.pfx-dialog-pane .mat-mdc-dialog-surface,.cdk-overlay-pane.pfx-dialog-pane .mdc-dialog__surface{display:flex;flex-direction:column;width:100%;min-width:0;height:100%;max-height:inherit;overflow:hidden;background:var(--pfx-form-surface, var(--md-sys-color-surface))!important;border:1px solid var(--pfx-form-stroke, var(--md-sys-color-outline-variant))!important}.cdk-overlay-pane.pfx-dialog-pane.pfx-dialog-frosted .mat-mdc-dialog-surface,.cdk-overlay-pane.pfx-dialog-pane.pfx-dialog-frosted .mdc-dialog__surface{backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.cdk-overlay-pane.pfx-drawer-pane{margin:0!important;border-radius:0!important;box-shadow:var(--md-sys-elevation-level3, 0 24px 80px rgba(15, 23, 42, .28)),0 0 0 1px color-mix(in srgb,var(--md-sys-color-outline, #64748b) 24%,transparent)}.cdk-overlay-pane.pfx-drawer-pane.pfx-drawer-maximized{margin:var(--pfx-drawer-edge-gap, 8px)!important}.cdk-overlay-pane.pfx-drawer-pane .mat-mdc-dialog-surface,.cdk-overlay-pane.pfx-drawer-pane .mdc-dialog__surface{min-width:0!important;border-radius:0!important}\n"], dependencies: [{ kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: PraxisResourceIdentityComponent, selector: "praxis-resource-identity", inputs: ["identity", "emptyTitle", "density", "showMetadataLabels", "showKey", "showKeyLabel", "ariaLabel"] }, { kind: "component", type: PraxisDynamicForm, selector: "praxis-dynamic-form", inputs: ["resourcePath", "resourceId", "initialValue", "editorialContext", "mode", "config", "actions", "schemaSource", "schemaUrl", "readUrl", "submitUrl", "submitMethod", "submitIdempotencyKey", "submitCorrelationId", "submitResourceVersion", "submitResourceVersionTargetResourceKey", "submitResourceVersionTargetIdField", "responseSchemaUrl", "apiEndpointKey", "apiUrlEntry", "enableCustomization", "showAiAssistant", "formId", "componentInstanceId", "configPersistenceStrategy", "layout", "generatedLayoutPreset", "layoutPolicy", "backConfig", "hooks", "removeEmptyContainersOnSave", "reactiveValidation", "reactiveValidationDebounceMs", "notifyIfOutdated", "snoozeMs", "autoOpenSettingsOnOutdated", "readonlyModeGlobal", "disabledModeGlobal", "presentationModeGlobal", "visibleGlobal", "fieldIconPolicy", "domainRules", "customEndpoints"], outputs: ["formSubmit", "formCancel", "formReset", "configChange", "configPatchChange", "formReady", "valueChange", "payloadPreviewChange", "syncCompleted", "initializationError", "loadingStateChange", "enableCustomizationChange", "customAction", "actionConfirmation", "schemaStatusChange", "fieldRenderError", "ruleDiagnosticsChange", "reactiveDeterminationExecuted", "reactiveDeterminationPendingChange"] }], encapsulation: i0.ViewEncapsulation.None });
6700
+ `, isInline: true, styles: ["praxis-dynamic-form-dialog-host{--dlg-header-h: 56px;--dlg-footer-h: 56px;--dlg-pad: 16px;display:flex;flex-direction:column;height:100%;overflow:hidden}praxis-dynamic-form-dialog-host[data-density=compact]{--dlg-header-h: 44px;--dlg-footer-h: 44px;--dlg-pad: 12px}praxis-dynamic-form-dialog-host .dialog-header{position:sticky;top:0;z-index:1;display:flex;align-items:center;gap:var(--dlg-pad);min-height:var(--dlg-header-h);padding:10px var(--dlg-pad);margin:0;background:var(--md-sys-color-surface-container-high);border-bottom:1px solid var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface)}praxis-dynamic-form-dialog-host .dialog-title{margin:0;font:inherit;font-weight:600;color:var(--md-sys-color-on-surface)}praxis-dynamic-form-dialog-host .dialog-heading{display:grid;min-width:0;gap:2px}praxis-dynamic-form-dialog-host .dialog-title-icon{display:inline-grid;flex:0 0 auto;width:36px;height:36px;place-items:center;border-radius:10px;color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 12%,transparent)}praxis-dynamic-form-dialog-host .dialog-title-icon mat-icon{width:22px;height:22px;font-size:22px}praxis-dynamic-form-dialog-host .dialog-subtitle{display:-webkit-box;overflow:hidden;color:var(--md-sys-color-on-surface-variant);font-size:.82rem;font-weight:400;line-height:1.35;-webkit-box-orient:vertical;-webkit-line-clamp:2}praxis-dynamic-form-dialog-host .spacer{flex:1}praxis-dynamic-form-dialog-host .dialog-content{flex:1 1 auto;overflow:auto;padding:var(--dlg-pad);max-height:calc(100svh - var(--dlg-header-h) - 32px)}praxis-dynamic-form-dialog-host .crud-operation-context{position:sticky;top:0;z-index:1;display:grid;gap:.75rem;margin-block-end:var(--dlg-pad);padding-block:.5rem .75rem;background:var(--pfx-form-surface, var(--md-sys-color-surface));border-bottom:1px solid var(--md-sys-color-outline-variant)}praxis-dynamic-form-dialog-host .crud-resource-identity{display:grid;gap:.25rem;min-width:0}praxis-dynamic-form-dialog-host .crud-resource-identity__label{color:var(--md-sys-color-on-surface-variant);font:var(--md-sys-typescale-label-medium, 500 .75rem/1rem inherit)}praxis-dynamic-form-dialog-host.praxis-drawer{--dlg-header-h: 72px;width:100%;min-width:0;max-width:100vw;height:100dvh;background:var(--pfx-form-surface, var(--md-sys-color-surface));color:var(--md-sys-color-on-surface)}praxis-dynamic-form-dialog-host.praxis-drawer .dialog-header{background:color-mix(in srgb,var(--md-sys-color-surface-container-high, var(--md-sys-color-surface)),transparent 4%)}praxis-dynamic-form-dialog-host.praxis-drawer .dialog-content{display:flex;flex-direction:column;max-height:none;min-height:0;padding:clamp(12px,2.4vw,24px)}praxis-dynamic-form-dialog-host.praxis-drawer .dialog-content>praxis-dynamic-form{display:block;flex:1 1 auto;min-height:0}praxis-dynamic-form-dialog-host.praxis-drawer .dialog-content>praxis-dynamic-form>.praxis-dynamic-form{min-height:100%}praxis-dynamic-form-dialog-host.praxis-drawer .dialog-content>praxis-dynamic-form>.praxis-dynamic-form>praxis-form-actions[data-actions-placement=afterSections]{margin-top:auto;padding-top:var(--pfx-actions-gap-top, var(--pfx-section-gap, 20px))}praxis-dynamic-form-dialog-host.praxis-surface-frame .dialog-content{max-height:none;min-height:0;padding:clamp(12px,2.4vw,24px)}praxis-dynamic-form-dialog-host .dialog-header button.praxis-icon-button{color:var(--md-sys-color-on-surface-variant)}praxis-dynamic-form-dialog-host .dialog-header button.praxis-icon-button:hover{color:var(--md-sys-color-primary)}praxis-dynamic-form-dialog-host .dialog-footer{position:sticky;bottom:0;z-index:1;padding:var(--dlg-pad)}.pfx-blur-backdrop{background-color:var(--pfx-backdrop, rgba(15, 23, 42, .42))!important;backdrop-filter:blur(var(--pfx-backdrop-blur, 10px)) saturate(110%);-webkit-backdrop-filter:blur(var(--pfx-backdrop-blur, 10px)) saturate(110%)}.pfx-transparent-backdrop{background-color:transparent!important}.cdk-overlay-pane.pfx-dialog-pane{overflow:hidden;transition:width .2s ease,height .2s ease,margin .2s ease}.cdk-overlay-pane.pfx-dialog-pane .mat-mdc-dialog-surface,.cdk-overlay-pane.pfx-dialog-pane .mdc-dialog__surface{display:flex;flex-direction:column;width:100%;min-width:0;height:100%;max-height:inherit;overflow:hidden;background:var(--pfx-form-surface, var(--md-sys-color-surface))!important;border:1px solid var(--pfx-form-stroke, var(--md-sys-color-outline-variant))!important}.cdk-overlay-pane.pfx-dialog-pane.pfx-dialog-frosted .mat-mdc-dialog-surface,.cdk-overlay-pane.pfx-dialog-pane.pfx-dialog-frosted .mdc-dialog__surface{backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.cdk-overlay-pane.pfx-drawer-pane{margin:0!important;border-radius:0!important;box-shadow:var(--md-sys-elevation-level3, 0 24px 80px rgba(15, 23, 42, .28)),0 0 0 1px color-mix(in srgb,var(--md-sys-color-outline, #64748b) 24%,transparent)}.cdk-overlay-pane.pfx-drawer-pane.pfx-drawer-maximized{margin:var(--pfx-drawer-edge-gap, 8px)!important}.cdk-overlay-pane.pfx-drawer-pane .mat-mdc-dialog-surface,.cdk-overlay-pane.pfx-drawer-pane .mdc-dialog__surface{min-width:0!important;border-radius:0!important}\n"], dependencies: [{ kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: PraxisResourceIdentityComponent, selector: "praxis-resource-identity", inputs: ["identity", "emptyTitle", "density", "showMetadataLabels", "showKey", "showKeyLabel", "ariaLabel"] }, { kind: "component", type: PraxisDynamicForm, selector: "praxis-dynamic-form", inputs: ["resourcePath", "resourceId", "initialValue", "emptyState", "editorialContext", "mode", "config", "actions", "schemaSource", "schemaUrl", "readUrl", "submitUrl", "submitMethod", "submitIdempotencyKey", "submitCorrelationId", "submitResourceVersion", "submitResourceVersionTargetResourceKey", "submitResourceVersionTargetIdField", "responseSchemaUrl", "apiEndpointKey", "apiUrlEntry", "enableCustomization", "showAiAssistant", "formId", "componentInstanceId", "configPersistenceStrategy", "layout", "generatedLayoutPreset", "layoutPolicy", "backConfig", "hooks", "removeEmptyContainersOnSave", "reactiveValidation", "reactiveValidationDebounceMs", "notifyIfOutdated", "snoozeMs", "autoOpenSettingsOnOutdated", "readonlyModeGlobal", "disabledModeGlobal", "presentationModeGlobal", "visibleGlobal", "fieldIconPolicy", "domainRules", "customEndpoints"], outputs: ["formSubmit", "formCancel", "formReset", "configChange", "configPatchChange", "formReady", "valueChange", "payloadPreviewChange", "syncCompleted", "initializationError", "loadingStateChange", "enableCustomizationChange", "customAction", "actionConfirmation", "schemaStatusChange", "fieldRenderError", "ruleDiagnosticsChange", "reactiveDeterminationExecuted", "reactiveDeterminationPendingChange"] }], encapsulation: i0.ViewEncapsulation.None });
6656
6701
  }
6657
6702
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: DynamicFormDialogHostComponent, decorators: [{
6658
6703
  type: Component,
@@ -6664,7 +6709,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
6664
6709
  PraxisResourceIdentityComponent,
6665
6710
  PraxisDynamicForm
6666
6711
  ], encapsulation: ViewEncapsulation.None, providers: [
6667
- GenericCrudService,
6712
+ {
6713
+ provide: GenericCrudService,
6714
+ useFactory: () => inject(GenericCrudService, { skipSelf: true }),
6715
+ },
6668
6716
  providePraxisI18nConfig(PRAXIS_CRUD_RUNTIME_I18N_CONFIG),
6669
6717
  ], host: {
6670
6718
  class: 'praxis-dialog',
@@ -7315,7 +7363,7 @@ const PRAXIS_CRUD_COMPONENT_METADATA = {
7315
7363
  {
7316
7364
  name: 'metadata.actions[].form',
7317
7365
  type: 'CrudActionFormContract',
7318
- description: 'Contrato canônico explícito para modal/drawer quando o host precisa informar schemaUrl, submitUrl e submitMethod sem depender do fallback genérico por resource.path.',
7366
+ description: 'Contrato da ação para modal/drawer. submitLabel personaliza apenas a apresentação; schemaUrl, submitUrl e submitMethod continuam sujeitos à resolução canônica por resource.path e discovery.',
7319
7367
  },
7320
7368
  {
7321
7369
  name: 'enableCustomization',
@@ -7714,6 +7762,7 @@ const CRUD_AI_CAPABILITIES = {
7714
7762
  { path: 'actions[].openMode', category: 'actions', valueKind: 'enum', allowedValues: ENUMS.openMode, description: 'Modo de abertura da acao.' },
7715
7763
  { path: 'actions[].route', category: 'actions', valueKind: 'string', description: 'Rota para openMode=route.' },
7716
7764
  { path: 'actions[].formId', category: 'actions', valueKind: 'string', description: 'FormId canonico para modal/drawer; se ausente, o host precisa resolve-lo por override por acao antes da abertura.' },
7765
+ { path: 'actions[].form.submitLabel', category: 'actions', valueKind: 'string', description: 'Rótulo de apresentação do submit; não altera schema, método nem endpoint descobertos.' },
7717
7766
  { path: 'actions[].params', category: 'actions', valueKind: 'array', description: 'Mapeamento de parametros.' },
7718
7767
  { path: 'actions[].params[].from', category: 'actions', valueKind: 'string', description: 'Origem do parametro.' },
7719
7768
  { path: 'actions[].params[].to', category: 'actions', valueKind: 'enum', allowedValues: ENUMS.paramTarget, description: 'Destino do parametro.' },
@@ -7752,6 +7801,7 @@ const surfaceConfigureSchema = {
7752
7801
  form: {
7753
7802
  type: 'object',
7754
7803
  properties: {
7804
+ submitLabel: { type: 'string' },
7755
7805
  schemaUrl: { type: 'string' },
7756
7806
  submitUrl: { type: 'string' },
7757
7807
  submitMethod: { enum: ['post', 'put', 'patch', 'delete'] },
@@ -7902,7 +7952,7 @@ const PRAXIS_CRUD_AUTHORING_MANIFEST = {
7902
7952
  { kind: 'viewSurface', resolver: 'crud-action-by-id:view', description: 'View action open mode, route/form binding and launcher inputs.' },
7903
7953
  { kind: 'deleteBehavior', resolver: 'crud-action-by-id:delete', description: 'Delete action enablement, confirmation, endpoint and capability policy.' },
7904
7954
  { kind: 'dialogHost', resolver: 'crud-dialog-host-defaults', description: 'Route/modal/drawer defaults consumed by CrudLauncherService and DynamicFormDialogHostComponent, including contextual shell titles derived from action label, form title or resource metadata.' },
7905
- { kind: 'formBinding', resolver: 'crud-action-form-contract-by-action-id', description: 'CRUD-owned form binding fields: formId, schemaUrl, submitUrl, submitMethod, params and initialValue. Shared FormConfig remains owned by Dynamic Form and is forwarded through CrudMetadata.form when present.' },
7955
+ { kind: 'formBinding', resolver: 'crud-action-form-contract-by-action-id', description: 'CRUD-owned form binding fields: formId, presentation-only submitLabel, schemaUrl, submitUrl, submitMethod, params and initialValue. Shared FormConfig remains owned by Dynamic Form and is forwarded through CrudMetadata.form when present.' },
7906
7956
  { kind: 'permissions', resolver: 'crud-resource-capabilities', description: 'CRUD action availability derived from resource capabilities and action permissions.' },
7907
7957
  { kind: 'domainGovernanceContext', resolver: 'domain-catalog-context-by-resource-key', description: 'Read-only semantic/governance context resolved from Domain Catalog and referenced from CRUD queryContext.meta.' },
7908
7958
  { kind: 'childOperation', resolver: 'child-authoring-manifest-operation', description: 'Delegated form/table/dialog/settings-panel operation owned by the child component manifest.' },
package/package.json CHANGED
@@ -1,20 +1,20 @@
1
1
  {
2
2
  "name": "@praxisui/crud",
3
- "version": "9.0.61",
3
+ "version": "9.0.63",
4
4
  "description": "CRUD building blocks for Praxis UI: integrates dynamic forms and tables with unified configuration and services.",
5
5
  "peerDependencies": {
6
6
  "@angular/common": "^21.0.0",
7
7
  "@angular/core": "^21.0.0",
8
- "@praxisui/dynamic-form": "^9.0.61",
9
- "@praxisui/table": "^9.0.61",
10
- "@praxisui/core": "^9.0.61",
11
- "@praxisui/dynamic-fields": "^9.0.61",
12
- "@praxisui/settings-panel": "^9.0.61",
8
+ "@praxisui/dynamic-form": "^9.0.63",
9
+ "@praxisui/table": "^9.0.63",
10
+ "@praxisui/core": "^9.0.63",
11
+ "@praxisui/dynamic-fields": "^9.0.63",
12
+ "@praxisui/settings-panel": "^9.0.63",
13
13
  "@angular/cdk": "^21.0.0",
14
14
  "@angular/forms": "^21.0.0",
15
15
  "@angular/material": "^21.0.0",
16
16
  "@angular/router": "^21.0.0",
17
- "@praxisui/ai": "^9.0.61",
17
+ "@praxisui/ai": "^9.0.63",
18
18
  "rxjs": "~7.8.0"
19
19
  },
20
20
  "dependencies": {
@@ -2,7 +2,7 @@ import * as _praxisui_core from '@praxisui/core';
2
2
  import { RowAction, ToolbarAction, ApiEndpoint, ApiUrlEntry, DynamicFormLayoutPolicy, BackConfig, TableConfig, PraxisDataQueryContext, FormConfig, ReactiveDeterminationExecutionEvent, ResourceActionCatalogItem, ResourceSurfaceCatalogItem, MaterializedResourceIdentity, PraxisResourceEvent, LoadingState, RestApiLinks, ResourceCapabilitySnapshot, SurfaceDrawerRef, GenericCrudService, AsyncConfigStorage, ComponentDocMeta, AiCapabilityCatalog, AiCapability, AiCapabilityCategory, AiValueKind, ComponentAuthoringManifest, SettingsValueProvider } from '@praxisui/core';
3
3
  export { BackConfig } from '@praxisui/core';
4
4
  import * as _angular_core from '@angular/core';
5
- import { NgZone, OnChanges, EventEmitter, SimpleChanges, OnInit, AfterViewInit, Provider, OnDestroy } from '@angular/core';
5
+ import { NgZone, OnChanges, EventEmitter, SimpleChanges, Injector, OnInit, AfterViewInit, Provider, OnDestroy } from '@angular/core';
6
6
  import { TableConfigPersistenceStrategy } from '@praxisui/table';
7
7
  import { MatDialogConfig, MatDialogRef, MatDialog } from '@angular/material/dialog';
8
8
  export { MAT_DIALOG_DATA as DIALOG_DATA } from '@angular/material/dialog';
@@ -66,6 +66,8 @@ interface CrudParamMapping {
66
66
  name: string;
67
67
  }
68
68
  interface CrudActionFormContract {
69
+ /** Presentation-only label for the submit action; it never overrides the discovered operation. */
70
+ submitLabel?: string;
69
71
  schemaUrl?: string;
70
72
  submitUrl?: string;
71
73
  submitMethod?: 'post' | 'put' | 'patch' | 'delete';
@@ -338,6 +340,11 @@ declare class PraxisCrudComponent implements OnChanges {
338
340
  private extractDiscoveryActionConfig;
339
341
  private resolveSelectedRowForAction;
340
342
  private tryOpenDiscoveredCrudSurface;
343
+ /**
344
+ * Keeps discovery authoritative for schema, operation and endpoint while
345
+ * preserving presentation-only choices authored in the CRUD composition.
346
+ */
347
+ private applyDiscoveredFormPresentationOverrides;
341
348
  private resolveDiscoveredSurfaceCatalog;
342
349
  private tryOpenDiscoveredWorkflowAction;
343
350
  private notifySurfaceNavigationFailure;
@@ -438,6 +445,8 @@ interface CrudDrawerOpenConfig {
438
445
  }
439
446
 
440
447
  interface CrudLaunchRuntime {
448
+ /** Caller injector retained only for the detached dialog component tree. */
449
+ injector?: Injector;
441
450
  capabilities?: ResourceCapabilitySnapshot | null;
442
451
  links?: RestApiLinks | null;
443
452
  resourceIdentity?: MaterializedResourceIdentity | null;