@praxisui/dynamic-form 10.0.0-rc.40 → 10.0.0-rc.42

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
@@ -747,13 +747,87 @@ das abas. Acima desse limite, reaparece a navegação por abas. O Settings Panel
747
747
  organiza título, expandir e fechar em uma grade até 599px; a prévia, quando
748
748
  suportada, ocupa a linha seguinte. Nenhum documento ou protocolo de Save é alterado.
749
749
 
750
+ ### Filhos de páginas governadas
751
+
752
+ Consulte [o adapter nativo de página](docs/governed-page-widget-adapter.md) para reconstrução sem defaults, presença exata, identidade derivada e execução sem preferências concorrentes.
753
+
754
+ ### Schema-backed custom fields
755
+
756
+ Core expands an object marked `x-ui.customFieldsContainer: true` (or the inline
757
+ `customFields` object) into fields named `customFields.<key>`. Dynamic Form uses
758
+ those names as nested reactive-form paths and keeps the wire payload nested:
759
+ `{ "customFields": { "numero_calcado": 38, "data_exame": "2026-10-27" } }`.
760
+ The `customField`, `customFieldKey` and `customFieldScope` metadata identifies
761
+ schema-backed fields; it does not make them local/transient authoring fields.
762
+ Saved containers colliding with the server's expanded namespace are replaced by
763
+ its direct children, including a container previously marked `source: 'local'`.
764
+ Noncolliding local fields and existing child placement remain. Restrictive parent
765
+ flags remain restrictive in children; they do not create a submit omission policy.
766
+
767
+ Date controls hydrate nested API values without mutating the input. Submit applies
768
+ the same date/lookup serialization, required/dirty handling and omission policies
769
+ to flat and dotted names. Missing nested values do not create containers. Filter
770
+ Form preserves supported nested values during same-context metadata rebuilds,
771
+ unless the new field has an explicit default (reset). A removed server field can
772
+ remain as metadata for layout continuity, but becomes disabled and omitted from
773
+ applicable payloads. Hidden alone is not omission: explicit local and legitimate
774
+ hidden fields keep their published semantics. No host adapter is needed for the
775
+ supported nested value paths.
776
+
777
+ Temporal normalization is metadata-aware: legacy date tuples and local datetime
778
+ strings are transformed only on declared temporal fields, including collection
779
+ item schemas. Numeric/unknown arrays such as `[2026, 10, 27]` remain arrays;
780
+ ordinary/unknown strings retain their spaces and date-like text. The `DateInput`
781
+ control follows date-only serialization. A same-context metadata rebuild can
782
+ restore nested dirty/touched control paths, including collection items, without
783
+ marking unrelated controls touched. This does not preserve a draft across every
784
+ reset, identity switch or retry.
785
+
786
+ Scalar arrays use the operation schema's `fieldMetadata[].items`, separately
787
+ from object collections' `array.itemSchema.fields`. Core's shared normalizer turns
788
+ valid UI tokens into declared strings, safe integers, finite numbers or exact
789
+ booleans and enforces the item enum after conversion. Date/date-time item formats
790
+ use that same contract. An invalid/null item rejects the entire projection rather
791
+ than silently dropping it; an optional null container and an empty array remain
792
+ distinct valid inputs. Form validation and prepared submit must agree, so a token
793
+ such as `12.5` cannot be submitted as an integer. This subset does not promise
794
+ integer precision beyond JavaScript's safe range or an object-array editor.
795
+
796
+ Record paths do not traverse array intermediates in computed-rule contexts;
797
+ collection submit uses its own item-schema pipeline. The canonical Metadata key
798
+ policy rejects reserved control names such as `constructor`, `toString` and
799
+ `hasOwnProperty`; payload helper support does not relax that policy. Existing
800
+ stored definitions with such keys require a backend migration.
801
+
802
+ Read-only/disabled does not automatically mean omission from `getRawValue()`.
803
+ The canonical backend command request projection excludes read-only custom fields
804
+ from properties and required, while response schemas retain them for display.
805
+ Use the exact operation request schema; merging response fields into commands or
806
+ adding an unimplemented `x-ui.submitPolicy` adapter would break that boundary.
807
+ Reconciliation treats a successful empty schema as authoritative. Removed
808
+ server-backed fields become hidden, disabled and `submitPolicy: 'omit'`, including
809
+ manual sync and Filter; explicit local fields remain local. Reappearance restores
810
+ the current server constraints rather than stale saved required/type/enum/items.
811
+
812
+ Each fresh schema-loading cycle revalidates HTTP and normalizes its body; compiled
813
+ L1 is not a readiness shortcut. A matching 304 can reuse the cached representation.
814
+ Status 0, denied access, malformed schema and failed saved-config reconciliation
815
+ cannot make the old form ready. Authorization errors show access feedback without
816
+ a generic retry action; timeout/transport failures retain their retry surface.
817
+ Schema loading/error or a known unconfirmed enterprise context blocks submit.
818
+ Context changes cancel obsolete reads, revalidate metadata and invalidate the old
819
+ initial-value seed; retry is not a general cross-context autosave guarantee.
820
+
821
+ The confirmed enterprise context supplies effective tenant/locale and context
822
+ version. Explicit schema URLs conflicting with that context are rejected. Identity
823
+ visible only to cookies/interceptors still requires a captured context version or
824
+ complete cache/session invalidation by the host; backend authorization is always
825
+ required. See the [enterprise review](https://github.com/codexrodrigues/praxis-ui-angular/pull/658)
826
+ for source, candidate gates, host proof and remaining adoption limits.
827
+
750
828
  <!-- praxis-npm-catalog-links:start -->
751
829
  ## Official documentation and examples
752
830
 
753
831
  - [Canonical technical overview: Overview](https://praxisui.dev/docs/components/praxis-dynamic-form)
754
832
  - [Praxis Angular public catalog](https://praxisui.dev/angular)
755
833
  <!-- praxis-npm-catalog-links:end -->
756
-
757
- ### Filhos de páginas governadas
758
-
759
- Consulte [o adapter nativo de página](docs/governed-page-widget-adapter.md) para reconstrução sem defaults, presença exata, identidade derivada e execução sem preferências concorrentes.
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": "1.0.0",
3
- "generatedAt": "2026-10-26T18:09:20.136Z",
3
+ "generatedAt": "2026-11-01T13:59:56.156Z",
4
4
  "packageName": "@praxisui/dynamic-form",
5
- "packageVersion": "10.0.0-rc.40",
5
+ "packageVersion": "10.0.0-rc.42",
6
6
  "sourceRegistry": "praxis-component-registry-ingestion",
7
7
  "sourceRegistryVersion": "1.0.0",
8
8
  "componentCount": 2,
@@ -71,11 +71,23 @@
71
71
  },
72
72
  {
73
73
  "name": "schemaSource",
74
- "type": "'resource' | 'filter'",
74
+ "type": "'resource' | 'filter' | 'action'",
75
75
  "required": false,
76
76
  "description": "Fonte do schema de campos",
77
77
  "default": "resource"
78
78
  },
79
+ {
80
+ "name": "actionId",
81
+ "type": "string | null",
82
+ "required": false,
83
+ "description": "Identificador canônico da ação de workflow ou comando governado associado ao formulário"
84
+ },
85
+ {
86
+ "name": "operationId",
87
+ "type": "string | null",
88
+ "required": false,
89
+ "description": "OperationId canônico publicado pelo catálogo de ações ou surfaces para execução do comando"
90
+ },
79
91
  {
80
92
  "name": "schemaUrl",
81
93
  "type": "string | null",
@@ -9418,9 +9430,9 @@
9418
9430
  {
9419
9431
  "chunkIndex": 0,
9420
9432
  "chunkKind": "summary",
9421
- "content": "Component ID: praxis-dynamic-form\nSelector: praxis-dynamic-form\nFriendly Name: Praxis Dynamic Form\nDescription: Formulario dinamico com layout por secoes/linhas/colunas e campos renderizados por metadados.\nCategory: form\nLib/Package: @praxisui/dynamic-form\nTags: widget, form, configurable, hasWizard, stable\nInputs:\n - resourcePath (string)\n - resourceId (string | number | null)\n - initialValue (Record<string, unknown> | null)\n - emptyState (PraxisDynamicFormEmptyState | null)\n - editorialContext (Record<string, unknown> | null)\n - mode ('create' | 'edit' | 'view' | 'presentation' | 'dossier')\n - config (FormConfig)\n - actions (FormConfig['actions'] | null)\n - schemaSource ('resource' | 'filter')\n - schemaUrl (string | null)\n - readUrl (string | null)\n - apiEndpointKey (ApiEndpoint | string | null)\n - apiUrlEntry (ApiUrlEntry | null)\n - submitUrl (string | null)\n - submitMethod ('post' | 'put' | 'patch' | null)\n - submitIdempotencyKey (string | null)\n - submitCorrelationId (string | null)\n - submitResourceVersion (string | number | null)\n - submitResourceVersionTargetResourceKey (string | null)\n - submitResourceVersionTargetIdField (string | null)\n - responseSchemaUrl (string | null)\n - enableCustomization (boolean)\n - showAiAssistant (boolean)\n - formId (string)\n - componentInstanceId (string)\n - configPersistenceStrategy ('local-first' | 'input-first' | 'volatile')\n - layout (FormLayout)\n - generatedLayoutPreset ('default' | 'compactPresentation')\n - layoutPolicy (DynamicFormLayoutPolicy | null)\n - backConfig (BackConfig)\n - hooks (FormHooksLayout)\n - removeEmptyContainersOnSave (boolean)\n - reactiveValidation (boolean | null)\n - reactiveValidationDebounceMs (number | null)\n - notifyIfOutdated ('inline' | 'snackbar' | 'both' | 'none')\n - snoozeMs (number)\n - autoOpenSettingsOnOutdated (boolean)\n - readonlyModeGlobal (boolean | null)\n - disabledModeGlobal (boolean | null)\n - presentation (DynamicFormPresentationSnapshot | null)\n - presentationPreset (FormPresentationPreset)\n - presentationModeGlobal (boolean | null)\n - fieldIconPolicy ('all' | 'presentation-only' | 'none')\n - visibleGlobal (boolean | null)\n - customEndpoints (EndpointConfig)\nOutputs:\n - formSubmit (FormSubmitEvent)\n - formCancel (void)\n - formReset (void)\n - configChange (FormConfig)\n - configPatchChange (DynamicFormConfigPatchChangeEvent)\n - formReady (FormReadyEvent)\n - valueChange (FormValueChangeEvent)\n - payloadPreviewChange (FormPayloadPreviewEvent)\n - syncCompleted (SyncResult)\n - initializationError (FormInitializationError)\n - enableCustomizationChange (boolean)\n - customAction (FormCustomActionEvent)\n - actionConfirmation (FormActionConfirmationEvent)\n - schemaStatusChange ({ outdated: boolean; serverHash?: string; lastVerifiedAt?: string; formId?: string })\n - reactiveDeterminationExecuted (ReactiveDeterminationExecutionEvent)\n - reactiveDeterminationPendingChange (boolean)\n",
9433
+ "content": "Component ID: praxis-dynamic-form\nSelector: praxis-dynamic-form\nFriendly Name: Praxis Dynamic Form\nDescription: Formulario dinamico com layout por secoes/linhas/colunas e campos renderizados por metadados.\nCategory: form\nLib/Package: @praxisui/dynamic-form\nTags: widget, form, configurable, hasWizard, stable\nInputs:\n - resourcePath (string)\n - resourceId (string | number | null)\n - initialValue (Record<string, unknown> | null)\n - emptyState (PraxisDynamicFormEmptyState | null)\n - editorialContext (Record<string, unknown> | null)\n - mode ('create' | 'edit' | 'view' | 'presentation' | 'dossier')\n - config (FormConfig)\n - actions (FormConfig['actions'] | null)\n - schemaSource ('resource' | 'filter' | 'action')\n - actionId (string | null)\n - operationId (string | null)\n - schemaUrl (string | null)\n - readUrl (string | null)\n - apiEndpointKey (ApiEndpoint | string | null)\n - apiUrlEntry (ApiUrlEntry | null)\n - submitUrl (string | null)\n - submitMethod ('post' | 'put' | 'patch' | null)\n - submitIdempotencyKey (string | null)\n - submitCorrelationId (string | null)\n - submitResourceVersion (string | number | null)\n - submitResourceVersionTargetResourceKey (string | null)\n - submitResourceVersionTargetIdField (string | null)\n - responseSchemaUrl (string | null)\n - enableCustomization (boolean)\n - showAiAssistant (boolean)\n - formId (string)\n - componentInstanceId (string)\n - configPersistenceStrategy ('local-first' | 'input-first' | 'volatile')\n - layout (FormLayout)\n - generatedLayoutPreset ('default' | 'compactPresentation')\n - layoutPolicy (DynamicFormLayoutPolicy | null)\n - backConfig (BackConfig)\n - hooks (FormHooksLayout)\n - removeEmptyContainersOnSave (boolean)\n - reactiveValidation (boolean | null)\n - reactiveValidationDebounceMs (number | null)\n - notifyIfOutdated ('inline' | 'snackbar' | 'both' | 'none')\n - snoozeMs (number)\n - autoOpenSettingsOnOutdated (boolean)\n - readonlyModeGlobal (boolean | null)\n - disabledModeGlobal (boolean | null)\n - presentation (DynamicFormPresentationSnapshot | null)\n - presentationPreset (FormPresentationPreset)\n - presentationModeGlobal (boolean | null)\n - fieldIconPolicy ('all' | 'presentation-only' | 'none')\n - visibleGlobal (boolean | null)\n - customEndpoints (EndpointConfig)\nOutputs:\n - formSubmit (FormSubmitEvent)\n - formCancel (void)\n - formReset (void)\n - configChange (FormConfig)\n - configPatchChange (DynamicFormConfigPatchChangeEvent)\n - formReady (FormReadyEvent)\n - valueChange (FormValueChangeEvent)\n - payloadPreviewChange (FormPayloadPreviewEvent)\n - syncCompleted (SyncResult)\n - initializationError (FormInitializationError)\n - enableCustomizationChange (boolean)\n - customAction (FormCustomActionEvent)\n - actionConfirmation (FormActionConfirmationEvent)\n - schemaStatusChange ({ outdated: boolean; serverHash?: string; lastVerifiedAt?: string; formId?: string })\n - reactiveDeterminationExecuted (ReactiveDeterminationExecutionEvent)\n - reactiveDeterminationPendingChange (boolean)\n",
9422
9434
  "sourcePointer": "projects/praxis-dynamic-form/src/lib/praxis-dynamic-form.metadata.ts",
9423
- "contentHash": "c23522b0ae4de2b4f759620ac16675455e6d0fe9e97b630e7248b82a8a3d463c",
9435
+ "contentHash": "97e0c3da46840798955442e4cb38ad5e4946c2fa4f5eb841b85182993a83a59e",
9424
9436
  "sourceKind": "component_definition",
9425
9437
  "sourceId": "praxis-dynamic-form",
9426
9438
  "corpusVersion": "1.0.0"
@@ -0,0 +1,229 @@
1
+ ---
2
+ title: "Custom fields: revisão de adoção corporativa"
3
+ slug: "dynamic-form-custom-fields-enterprise-review"
4
+ description: "Registro de achados, fontes, provas e pendências da adoção de custom fields no Core e Dynamic Form."
5
+ doc_type: "reference"
6
+ document_kind: "governance-reference"
7
+ component: "dynamic-form"
8
+ category: "architecture"
9
+ audience:
10
+ - "frontend"
11
+ - "host"
12
+ - "architect"
13
+ - "platform-team"
14
+ level: "advanced"
15
+ status: "active"
16
+ owner: "praxis-ui"
17
+ last_updated: "2026-10-27"
18
+ toc: true
19
+ sidebar: false
20
+ source_of_truth:
21
+ - "projects/praxis-core/src/lib/services/schema-normalization-kernel.ts"
22
+ - "projects/praxis-core/src/lib/models/form/materialize-custom-fields-layout.ts"
23
+ - "projects/praxis-core/src/lib/services/dynamic-form.service.ts"
24
+ - "projects/praxis-core/src/lib/schema/schema-metadata-client.ts"
25
+ - "projects/praxis-core/src/lib/services/generic-crud.service.ts"
26
+ - "projects/praxis-dynamic-form/src/lib/praxis-dynamic-form.ts"
27
+ - "projects/praxis-dynamic-form/src/lib/utils/prepare-submit-payload.ts"
28
+ - "projects/praxis-dynamic-form/src/lib/services/form-rules.service.ts"
29
+ ---
30
+
31
+ # Custom fields: revisão de adoção corporativa
32
+
33
+ ## Escopo e baseline
34
+
35
+ A [Issue 657](https://github.com/codexrodrigues/praxis-ui-angular/issues/657) e o
36
+ [PR 658](https://github.com/codexrodrigues/praxis-ui-angular/pull/658) materializam
37
+ custom fields no runtime oficial. A revisão atual parte de Angular `48b004c9e` e
38
+ Metadata `368d96266b`. Os PRs 658/304 permanecem sem merge. A revisão da fonte e os gates focais desta rodada estão concluídos, com as
39
+ exceções preexistentes e pendências downstream registradas abaixo. Fonte candidata e provas
40
+ não certificam publicação, deploy, release ou adoção corporativa irrestrita.
41
+
42
+ A revisão anterior partiu de Angular `6598ef221f0708c6628b02380c0e27110fa4a1ae`
43
+ e skills `59c64169fe062de69c83b886c75b681d4e7ee967`; seus achados motivaram esta
44
+ rodada. O backend é dono da definição, autorização e validação. Core projeta,
45
+ reconcilia e transporta; Form/Table materializam controles e payloads. A landing
46
+ publica essa fonte, e não uma semântica alternativa.
47
+
48
+ Classificação: `contrato-publico`, com correções de semântica já suportada e mal
49
+ materializada em Core/Form/Table e alinhamento canônico backend. Consumidores:
50
+ Form schema-driven/salvo, Filter standalone/integrado/avançado, discovery e
51
+ GenericCrud. Derivados: READMEs, JSON API, dois guias Table, vendor docs da landing
52
+ e skills existentes. Não há nova rota pública para este relatório, nem alteração
53
+ de endpoint, corpus HTTP ou recipe pela documentação.
54
+
55
+ ## Achados, tratamento e fontes
56
+
57
+ | Cenário / origem | Correção na fonte candidata | Gate / limite |
58
+ | --- | --- | --- |
59
+ | Container salvo ou local colidente substituía filhos e podia perder a subárvore no payload. | `materialize-custom-fields-layout`, reconciliadores e sync migram pai direto para filhos schema-backed, preservando posições, rich content e locais não colidentes; diagnostics persistem a correção. | Integração normalizer/reconcile/FormGroup/submit nos três caminhos; não transferir omit/defaults/validadores escalares do pai. |
60
+ | Restrições e identidade eram relaxadas por metadata antiga. | Pisos disabled/readOnly/formHidden do container; identidade customField/key/scope e constraints items/enum server-owned. FieldAccess ausente é herdado; policies equivalentes por sets são aceitas, conflito exige policy leaf efetiva do backend. | Conflito de normalização bloqueia inicialização, incluindo configuração salva; listas OR não implementam AND arbitrário. |
61
+ | Cache/deduplicação/replay e getters podiam cruzar tenant, autenticação ou recurso por chamada. | `schema-request-key`, `schema-request-context`, `schema-fetch`, SchemaMetadataClient, GenericCrud e Discovery capturam contexto/headers, isolam representação e deduplicam só trabalho em andamento. GenericCrud só publica derivados do recurso configurado; callbacks obsoletos não publicam. | Snapshot antes de await/subscription e retry304 igual; provider/hook/aliases inválidos falham antes do request. Getters singleton não são mapa de resultados por chamada. |
62
+ | L1, cache status0 ou configuração salva podiam parecer schema autorizado atual. | Novo ciclo HTTP revalida e normaliza; L1 compilado não estabelece readiness. Corpo cacheado só após 304 correspondente; status0/401/403/normalização inválida não recuperam silenciosamente o form. | Sem modo offline. Discovery não usa resumo do catálogo ou schema response para substituir request vazio/negado. Fallback de indisponibilidade conhecido só nas trilhas equivalentes já suportadas. |
63
+ | Remover o último campo gerava defs=[] ignorado; sync/filter conservavam órfãos aplicáveis/required. | Schema vazio bem-sucedido é autoritativo. Reconcile Form/Filter e sync manual marcam órfãos não locais hidden+disabled+omit; reaparecimento usa required/type/items/enum atuais. | Hidden legítimo e `source: local` explícito conservam sua semântica; raw draft pode manter diagnóstico, mas não é payload aplicável. |
64
+ | Request publicava read-only que o backend recusava; nomes admitidos colidiam com controles. | Metadata PR304 exclui read-only de comando properties/required e mantém leitura/filtro apropriados; política de chaves rejeita nomes reservados exatos. | Consumir schema da operação; não mesclar response em comando nem inventar x-ui.submitPolicy local. Definições antigas exigem migração explícita. |
65
+ | Arrays IN/enum perdiam tipo e diferentes fronteiras emitiam valores incompatíveis. | FieldDefinition/Metadata `items: FieldScalarItemsSchema`; parser Core único `normalizeScalarArrayValue`, validators e projeção Form/Table. Modal Apply/Save usa payload do child; merge de shortcut reprojeta omit. | Rejeição inteira de item inválido/null, sem descarte parcial; bloqueio pending/invalid inclui debounce anterior. Zero filtros ativos DISABLED permite limpar. |
66
+ | Regras computed liam alias pontuado antigo. | Contexto JSON Logic aninhado via helper interno; `fieldValues` continua mapa plano de target IDs. | Cadeia em ordem inversa, condições true/false e imutabilidade. Arrays intermediários não são record paths suportados. |
67
+ | Heurística temporal alterava strings e arrays numéricos; rebuild perdia estado aninhado. | Normalização metadata-aware de datas e item schemas, DateInput date-only e snapshot dirty/touched por leaf/FormArray. Campos planos escrevem draft privado, sem clone raiz por campo. | Arrays numéricos/unknown e strings não temporais preservados; não é autosave entre contextos/resets. |
68
+ | Erro de acesso parecia conexão/retry e submit podia usar estado não pronto. | Form distingue acesso, contexto não confirmado, projeção inválida e transporte. Loading/erro/known nonready bloqueiam submit; preview scalar inválido emite formData:null/isValid:false com raw intacto. | 401/403 não oferecem retry genérico. Troca confirmada invalida seed anterior e revalida; não restaura draft de outro tenant. |
69
+
70
+ ## Contratos e limites ainda exigidos do host
71
+
72
+ A fonte backend inspecionada é o candidato PR304, docs em `99b75a2dde`:
73
+ [spec canônica](https://github.com/codexrodrigues/praxis-metadata-starter/blob/99b75a2dde/docs/spec/custom-fields-and-resource-facts.md).
74
+ A política rejeita exatamente `constructor`, `prototype`, `hasOwnProperty`,
75
+ `isPrototypeOf`, `propertyIsEnumerable`, `toLocaleString`, `toString` e `valueOf`,
76
+ com comparação sensível a maiúsculas. `__proto__` já é inválido pelo formato da
77
+ chave. Não corrigir dados antigos com aliases silenciosos de frontend.
78
+
79
+ Read-only/disabled/hidden não significam omissão universal. Na escrita, a projeção
80
+ canônica exclui custom fields read-only; filtros podem mantê-los como operandos de
81
+ busca e respostas como leitura. Campos contextuais legítimos continuam sujeitos
82
+ ao contrato da operação. `rawFormData`/`getRawValue()` são diagnósticos, não uma
83
+ instrução para ignorar o payload projetado.
84
+
85
+ A chave de representação usa URL real, identidade semântica e tenant/locale
86
+ capturados; headers adicionais selecionam um token opaco por sessão/página.
87
+ O lookup de headers é limitado e fica só em memória: credenciais/fingerprints não
88
+ são persistidos em chaves ou metadata. Isso não redige corpos arbitrários do
89
+ servidor. Contexto enterprise confirmado fornece tenant/locale/version; GenericCrud,
90
+ Discovery e Form bloqueiam um snapshot conhecido não pronto. O cliente standalone
91
+ SchemaMetadataClient captura o hook e não descobre o serviço DI por conta própria. Parâmetros explícitos conflitantes falham.
92
+
93
+ Cookies/interceptors que alterem identidade depois do snapshot não são observáveis
94
+ pelo cache. O host precisa materializar a versão confirmada nos headers capturados
95
+ ou invalidar todo o escopo de cache/sessão; recriar somente um cliente sobre o
96
+ mesmo armazenamento não basta. Tenant nunca substitui autorização por principal.
97
+ GenericCrud mantém getters do recurso configurado: overrides por chamada devolvem
98
+ seus resultados, sem transformar esses getters em uma API multiscope.
99
+
100
+ Scalar `items` cobre string/integer/number/boolean e formatos date/date-time
101
+ suportados. Inteiros precisam ser seguros no JavaScript; números finitos seguem
102
+ sintaxe JSON e booleans são exatos. Enum é aplicado depois da conversão. `null`
103
+ container/ausente e `[]` não equivalem a item null; required continua independente.
104
+ Não anunciar arbitrary JSON Schema items, editor object-array, precisão int64 ou
105
+ record paths de regras através de arrays intermediários.
106
+
107
+ ## UX e progresso
108
+
109
+ | Situação | Comportamento / limite comunicável |
110
+ | --- | --- |
111
+ | Schema loading, timeout e transporte | SchemaMetadataClient aplica deadline; leituras supersedidas são canceladas. Falha recuperável oferece retry. Não é modo offline ou promessa de recuperar todo rascunho. |
112
+ | Acesso negado ou contexto não confirmado | Form não monta controles cacheados como prontos nem permite submit; acesso tem feedback próprio sem retry genérico. Recuperação depende de contexto/autorização do host. |
113
+ | Config salva, defs vazias ou projeção inválida | Vazio bem-sucedido reconcilia; erro não mantém configuração antiga pronta. FieldAccess conflitante é erro de metadata, não autorização alternativa de host. |
114
+ | Troca de tenant/registro | Cancela geração antiga, invalida seed anterior e revalida. Não comunica continuidade de dados entre identidades. |
115
+ | Campo removido/reaparecido | Órfão server-backed pode manter metadata/layout/raw diagnóstico, mas fica disabled/omit. Ao voltar usa constraints do schema atual. |
116
+ | Rebuild do filtro | Valores suportados do mesmo contexto podem ser restaurados; default explícito pode resetar. Hidden/local legítimo não é removido por uma política genérica. |
117
+ | Valor scalar inválido | Permanece corrigível no raw/control com feedback; nenhuma emissão aplicável/submit/shortcut ou preview com formData utilizável. |
118
+ | Narrow viewport | Ações/labels devem permanecer acessíveis por scroll sem overflow horizontal. Densidade da toolbar não prova campo acima da dobra ou conformidade de teclado/AXE. |
119
+
120
+ ## Evidências da rodada atual
121
+
122
+ - Core: 471 casos distintos na campanha atual. Quatro falhas de fixture/guard foram
123
+ corrigidas; rerun focal de contexto/discovery 61/61 aprovado. Não somar 471+61.
124
+ - Comandos de build Core e Form com closure de 13 libs aprovados. Core precedeu
125
+ o último guard; a closure final Form recompilou Core/Form/Table e cobre a fonte
126
+ final de produção. Pureza e MatSelect zero-debt também passaram.
127
+ - Form: 406 casos distintos aprovados, com rerun focal das três fixtures
128
+ corrigidas. Deltas posteriores ao build são apenas testes.
129
+ - Browser: seis casos distintos aprovados (quatro Form e dois Table). Os quatro
130
+ Form cobrem editor desktop/resize, abertura narrow inicial, warm-cache seguido
131
+ de403 e formulário público scalar/enum. O último caso passou em rerun após
132
+ corrigir uma corrida do teste ao observar a ação ficar disabled. Table cobre
133
+ toolbar/gerenciador de campos/avançado/modal, sem prova de query IN por browser.
134
+ - Table: **224/224 aprovados** após o alinhamento das quatro fixtures year/month
135
+ ao contrato introduzido em `6de618805`. O runtime e o registry preservam
136
+ inlineYearRange/inlineMonthRange como wrappers numéricos; não são aliases de
137
+ inlinePeriodRange. Os testes agora verificam IDs, modo range, imutabilidade,
138
+ hidratação em controle real e payload numérico no submit. O resultado anterior
139
+ 220/224 é histórico e foi substituído pela execução focal completa aprovada.
140
+ - Dynamic Fields: **10/10 aprovados** nos componentes inline-year-range,
141
+ inline-month-range e inline-period-range. A prova distingue limites numéricos
142
+ de identificadores de períodos, sem alterar a semântica de produção.
143
+ - Quickstart: revisão cruzada confirmou 25 casos distintos sem falha no candidato
144
+ backend e a prova HTTP Neon coordenada no trabalho backend. Três pilotos
145
+ históricos (EventosFolha, MetadataMigration e OpenApiGroupResolution), além do
146
+ verify integral e do pin de artefato público, permanecem pendentes no Draft482;
147
+ não inferir adoção completa a partir do piloto. Fontes brutas e fingerprint estão no registro
148
+ backend `docs/technical/ISSUE-303-EXECUTION.md` e no PR304.
149
+ - Frontmatter incremental dos documentos desta rodada validado. Skills867
150
+ publicado em `d351c44`; landing docs no PR270 em `cfc0212`. Validação canônica
151
+ de skills e gates documentais aprovados. O fechamento documental corrigiu também as
152
+ cinco cópias vendor antigas: List, Metadata Editor, Page Builder, Table API e
153
+ Visual Builder. Os dois guias Dynamic Fields foram alinhados ao contrato de
154
+ ranges; o link prospectivo do Page Builder aponta à fonte GitHub existente.
155
+ Full vendor freshness passou para os 75 documentos, assim como docs25,
156
+ published-guides146 e sitemap. Nenhuma sincronização instalada ou merge.
157
+
158
+ A E2E ampliada `surface-open-form-demo.playwright.spec.ts` cobre o editor,
159
+ abertura narrow inicial, leitura autorizada seguida de403 sem reaproveitar
160
+ campos prontos, e formulário público com items/enum, bloqueio de token inválido e
161
+ submit nested tipado. Esses casos passaram na execução final e usam
162
+ schema/HTTP mockado; não substituem prova backend Neon. Não há prova AXE,
163
+ teclado completo, tema claro, filtro IN por browser ou persistência real pelo E2E.
164
+
165
+ A coordenação inspecionou screenshots desktop e narrow estabilizados: labels e
166
+ quadros acessíveis, sem overflow horizontal; a toolbar estreita continua densa e
167
+ o campo pode exigir scroll. O rerun Playwright pode limpar `test-results`, então
168
+ este registro não publica links para screenshots transitórios. Logs em
169
+ `/tmp/praxis-658-e2e-form-final.log`, `praxis-658-e2e-scalar-rerun.log` e
170
+ `praxis-658-e2e-table-final.log` pertencem à campanha local coordenada.
171
+
172
+ O receipt `/tmp/praxis-658-source-freeze.json` vincula as provas à árvore de
173
+ 44 arquivos fonte/teste alterados contra48b004, fingerprint SHA256
174
+ `f99a2bdde6f3fa9f05cd56025e1d375c24c6bcffa2fef5e541e155d6c2650bda`.
175
+ O lockfile não mudou. O commit Angular final é registrado no PR658 após o freeze
176
+ documental; o fingerprint distingue a fonte validada das edições de relatório.
177
+
178
+ ## Evidência histórica anterior
179
+
180
+ A rodada anterior passou 313 casos Core distintos (311+duas novas em rerun70),
181
+ 324 Form e build closure13. Um E2E mockado passou em1280×720 e após resize390×844,
182
+ com screenshots finais inspecionados pela coordenação: sem overflow, tabs para
183
+ select, ações sticky e campo narrow atingível por scroll, abaixo da dobra. Essa
184
+ execução não cobria abertura narrow inicial nem submit real. Capturas ignoradas
185
+ pelo Git em `test-results/surface-open-form-demo.pla-6e87b-the-employee-drawer-surface-chromium/`.
186
+ Esses resultados não são somados aos gates da árvore atual.
187
+
188
+ ## Publicação e guidance
189
+
190
+ O [PR skills867](https://github.com/codexrodrigues/praxis-codex-skills/pull/867)
191
+ pertence ao incremento Angular Core/Form/Table; o
192
+ [PR skills868](https://github.com/codexrodrigues/praxis-codex-skills/pull/868)
193
+ pertence ao backend e tem escritor próprio. Integração canônica e sincronização
194
+ instalada são estados separados e permanecem pendentes enquanto os PRs não forem
195
+ integrados. O [PR270 da landing](https://github.com/codexrodrigues/praxis-ui-landing-page/pull/270)
196
+ usa o fluxo vendor oficial em worktree isolado. Este registro
197
+ não cria nova rota, manifesto, endpoint, corpus ou assets públicos.
198
+
199
+
200
+ ## Fechamento Table e documentação — 27/10/2026
201
+
202
+ Escopo autorizado: corrigir as quatro falhas preexistentes da Table e as cinco
203
+ cópias documentais divergentes enquanto a campanha financeira Quickstart segue
204
+ em outro chat. Classificação transversal: testes e documentação, sem modificação
205
+ de runtime, API, dependências, rotas ou configuração de build. Inventário
206
+ `ja-suportado-mal-nomeado-ou-mal-materializado`: contrato e implementação já
207
+ concordavam; expectativas e guias ainda ensinavam a conversão antiga.
208
+
209
+ A auditoria das cinco cópias vendor encontrou versões históricas exatas das fontes
210
+ Angular, sem conteúdo exclusivo novo a preservar. A correção usa o sync oficial
211
+ com `PRAXIS_UI_ANGULAR_ROOT` apontando ao worktree revisado. O ajuste dos dois guias
212
+ Dynamic Fields é derivado do mesmo diagnóstico; não cria controles ou DTOs.
213
+
214
+ A revisão independente confrontou o patch dos quatro testes, os wrappers e
215
+ registry, o contrato runtime e o histórico. O coordenador revisou os guias e a
216
+ projeção vendor. Evidências locais: `/tmp/praxis-658-table-alignment.log` (224),
217
+ `/tmp/praxis-658-range-contracts.log` (10) e
218
+ `/tmp/praxis-658-alignment-docs.log`. A bateria Table inclui componente, host e projeção; Dynamic Fields cobre os três
219
+ componentes de range, com `tools/karma/karma.headless.conf.cjs`. Não foi repetido build
220
+ ou E2E porque este incremento altera somente specs/documentação. Os builds e E2E
221
+ da fonte de produção `f5880172f` continuam válidos.
222
+
223
+ Skills: `atualizar-existente` para `praxis-fields-inline-overlay-runtime`, com a
224
+ distinção de valores numéricos/períodos e provas de promoção; `existente-adequada`
225
+ para publicação na landing, que já determina owner-first, sync oficial e gates
226
+ completos. A atualização canônica segue no PR867; integração e sync instalado
227
+ aguardam a revisão sem merge. Os commits finais deste fechamento estão nos PRs
228
+ 658/270/867. Pilotos financeiros, verify integral e pin público do Quickstart
229
+ continuam sob coordenação exclusiva do outro chat; este incremento não os aprova.