Skip to content

A form names the fields each write accepts from its person, and the host page sends none that no write accepts - #142

Merged
sharkysan merged 4 commits into
mainfrom
feat/page-sends-only-writable-fields
Oct 31, 2026
Merged

sharkysan merged 4 commits into
mainfrom
feat/page-sends-only-writable-fields

Conversation

@sharkysan

@sharkysan sharkysan commented Oct 31, 2026 •

Copy link
Copy Markdown
Owner

A form names the fields each write accepts from its person, and the host page draws a field that no write accepts as unwritable and sends it in no save (0117).

With the merge of #138 this record is 0117: the lint record took 0116.

Why

formancy's renderers submit every field, disabled ones included, and the server removes the echo it can prove (0022). So nothing was wrongly written, but:

  • on a form whose tenant is a column of its own (a product's prices, a party), the host page sent the tenant in every update and every change from a date. The tenant is the token's alone (0011). The plane test's rule that no body names a tenant is why its journey left out a change from a date (0115);
  • a field the policy lets a person read and not write was drawn writable, and an edit of it was refused only after Save.

What changes

  • data-core: writableFields(policy, context, bindings, operation), each field the over-posting check accepts alone, in the bindings' order. copiedFields now asks it, so no second list of what may be written exists.
  • data-server: GET /v1/forms/:id adds writable: { create, update }, with null for a write the form does not offer.
  • data-client: a form reply without writable, or naming a write the form does not offer, is unexpected, so a host upgrades its server before its client.
  • host page: session.ts draws a field in neither list disabled and leaves it out of every create, update and change from a date. The submitted answers stay whole for the session's own comparisons, so a field left out is never counted as changed.
  • Left as it was: a field written on create only is still drawn writable on an opened record and sent. Dropping it from an update would silently drop a change the person made to a field drawn writable after a create.
  • Tests:
    • the price form's note is now read-only for the clerk, a field the bindings write and the policy keeps from them;
    • change.test.tsx checks what is drawn disabled and what an update sends;
    • plane.test.tsx also creates, updates and changes a price on the page's own origin. The supersede exception is left for the demo's door alone, since the live demo publishes no form over versions.
  • Docs:
    • record 0117, and the status lines of 0022, 0029 and 0115;
    • the limitations: 0115's testing line is gone, and 0117 says the rest;
    • README, CHANGELOG, both package READMEs, and the architecture's building blocks, runtime view and cross-cutting concepts.

Watched failing

  • data-core: with every binding named.
  • data-server: with writable left out of the reply.
  • data-client: with writable left unchecked.
  • host page: in CI, against the branch's second commit, which mutated the page's half: nothing new drawn disabled, and every answer sent.
    • change.test.tsx: the note was writable, on both engines.
    • plane.test.tsx: tenant_id was in the price's update and its change from a date, on both engines. The create sent none, since an empty field isn't submitted.
    • session-work.test.ts failed too, for the fixture's missing writable, which the third commit adds with a new case. That case was watched failing locally: nothing was disabled.
  • temporal-round-trip-page.test.ts expected an instant and a time withheld by the policy alone to be drawn enabled, as before. It passed under the mutation and failed on the real code (both engines, both renderers), so it now expects them disabled, like the ones the account may not write. The note beside them still saves, and both columns stay byte-identical.
  • The same run's WebKit leg passed every check of the host's browser gate, then Node crashed on an uncaught ECONNRESET while shutting down. This change doesn't cause that, and the final run will show whether it recurs.

The second commit is reverted by the third, and the squash leaves no trace of it.

Run locally

On a Mac (arm64, Node 22.14), with Docker hung, so the host suites ran in CI only:

  • pnpm build, pnpm typecheck, eslint and prettier on the touched files;
  • data-core 800/800;
  • the host's session-work.test.ts 5/5, which needs no server;
  • data-server's fake-port files 612/612;
  • data-client's transport file 34/34;
  • the studio 256/256;
  • the repo checks this change touches (architecture, source size, limitations, pictures' README, generated blocks, code style, lint).

@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

… and limitations, README, CHANGELOG and the architecture
@sharkysan
sharkysan marked this pull request as ready for review October 31, 2026 16:58
… page now draws every field no write accepts
@sharkysan
sharkysan merged commit 670a36a into main Oct 31, 2026
40 checks passed
@sharkysan
sharkysan deleted the feat/page-sends-only-writable-fields branch October 31, 2026 19:26
sharkysan added a commit that referenced this pull request Nov 1, 2026
…column through a regeneration (#145)

A field's presentation may set or remove its help text: FieldPresentation.description is text that replaces or adds it, or null that removes the base's. applyPresentation refuses help text equal to the base's, a removal where the base has none, and help text over a spec 3 base; presentationOf derives it; rebasePresentation carries it by the column, keeping the person's over a comment that changed too (both-changed, property description) and reporting it field-gone with its column.

The studio's Presentation step has a Help text box under each field's label: empty removes help text, past 300 characters the box says so. The carried panel offers "Use the generator's help text" for a help-text conflict, where every both-changed had offered the label. Record 0119; the Presentation picture retaken on CI's runner, with two host pictures that had moved since #142 and #144.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants