Skip to content

feat(publish form): lock pre-filled values and statements (#678) - #679

Merged
tkuhn merged 2 commits into
masterfrom
feat/678-locked-prefilled-values
Sep 4, 2026
Merged

feat(publish form): lock pre-filled values and statements (#678)#679
tkuhn merged 2 commits into
masterfrom
feat/678-locked-prefilled-values

Conversation

@tkuhn

@tkuhn tkuhn commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Closes #678.

A link into the publish form can pre-fill fields with URL parameters, but some of those values are not the user's to change: the "Create Introduction" link fills in the public key of the local key pair, and an introduction declaring a different key is simply wrong.

Two new page parameters

locked names the pre-filled values that cannot be changed:

/publish?template=…&param_public-key=<key>&locked=param_public-key

It holds per repetition, as the name carries the repetition suffix of the field it refers to (param_public-key is the first key group, param_public-key__1 the second). That is what lets a link pre-fill and fix the keys a user already has while leaving them free to add more with "+".

locked-statements names the statements whose repetitions are fixed — no adding, no removing:

&param_public-key=<key A>&param_public-key__1=<key B>
&locked=param_public-key,param_public-key__1&locked-statements=public-key

A statement is named either by its node in the template (st2) or by a placeholder that occurs in it and no other (public-key). Resolved when the lock is queried rather than when it is parsed, since the statements are only built afterwards.

Both take the same template prefixes as the pre-fill parameters (param_ / prparam_ / piparamN_; a bare name means the assertion template), accept comma-separated lists and repetition, and are independent of each other: a locked value in an unlocked statement can still be dropped by removing its repetition, and a locked statement's values stay editable unless locked names them too.

Two things worth reviewing

The field stays enabled in Wicket. Disabling it looks right and is wrong: the browser sends nothing for a disabled control, and the form then reads the field as an emptied one — the value disappears and its required check fails. Text inputs get readonly, which browsers submit; choice fields render as select, which HTML has no readonly for, so they are disabled with the value mirrored in a hidden field of the same name. This was caught by driving the running app, not by the tests.

Locks shift with values on removal. RepetitionGroup.remove() does not delete a slot; it shifts the following groups' values up through fixed placeholder slots. The lock belongs to the pre-filled value rather than the slot, so it travels with it — otherwise removing a locked repetition would leave the value that slides into its place uneditable. Only IRIs that actually get a repetition suffix are shifted: iriSet holds the statement's constants too, and one can share a placeholder's postfix (rdfs:comment beside a comment placeholder), which shifted the same lock twice and undid it.

A value lock is a guardrail — it is stated in the URL, so it stops accidental edits, not deliberate ones. A statement lock genuinely holds: Wicket does not invoke the listener of an invisible component, so a hidden "+" cannot be triggered from the page either.

Also

  • The "Create Introduction" link in ProfileAccountPanel now locks param_user and param_public-key.
  • Optional statements need no separate lock to be kept present: one is dropped by leaving a field empty, and a locked value cannot be cleared. Forcing an optional statement to stay absent would be a hide-the-field feature and is deliberately not part of this.
  • Design notes in docs/locked-prefilled-values.md.

Testing

  • LockedFieldTest (15) — per-repetition locking, lock shifting on removal, readonly/hidden-mirror rendering, statement locks.
  • PublishFormLockTest (8) — parameter parsing for both locks.
  • Full suite: 1259 passing, 0 failures.
  • Verified end-to-end against the "Introducing a user" template on a local instance: locked key readonly with its value, second and added groups editable, "-" on the locked group shifting the neighbour up as editable, locked-statements removing the group's "+"/"-", and Preview producing a signed nanopub containing the locked key. Nothing published.

Note: previewing after removing a key group reports "Invalid choice" on "has key location", which still references the removed declaration. That is pre-existing — the control run with no locking at all behaves identically.

🤖 Generated with Claude Code

https://claude.ai/code/session_01An6DWbMvqQM7z312vC7apK

tkuhn and others added 2 commits September 4, 2026 05:42
A link into the publish form can pre-fill fields with URL parameters, but some
of those values are not the user's to change: the "Create Introduction" link
fills in the public key of the local key pair, and an introduction declaring a
different key is simply wrong.

Two new page parameters state that:

- `locked` names the pre-filled values that cannot be changed. It holds per
  repetition, as the name carries the repetition suffix of the field it refers
  to, so a link can pre-fill and fix the keys a user already has while leaving
  them free to add more.
- `locked-statements` names the statements whose repetitions are fixed: no
  adding, no removing. Independent of the value lock, and named either by the
  statement node or by a placeholder that occurs in it and no other.

Both take the same template prefixes as the pre-fill parameters
(`param_`/`prparam_`/`piparamN_`, bare = assertion template).

A locked field stays enabled as far as Wicket is concerned and keeps being
submitted: disabling it in Wicket looks right and is wrong, since the browser
sends nothing for a disabled control and the form then reads the field as an
emptied one, losing the value and failing its required check. Text inputs are
marked readonly, which browsers submit; choice fields, which render as `select`
and have no readonly in HTML, are disabled with their value mirrored in a hidden
field of the same name.

Removing a repetition group shifts the values of the following groups up through
fixed placeholder slots, so the locks shift with them: the lock belongs to the
pre-filled value, not to the slot, and removing a locked repetition must leave
the value that slides into its place editable.

The "Create Introduction" link now locks the user and the public key. Optional
statements need no separate lock to be kept, as one is dropped by leaving a
field empty and a locked value cannot be cleared.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01An6DWbMvqQM7z312vC7apK
A view entry action fills form fields from the row it sits on, through its
"col:field" query mappings. Writing the field as "!field" now locks it too, so
the form shows the value the action filled in but does not let the user change
it.

This is for values an action determines rather than proposes. The case at hand
is the "derive new introduction" action of the introductions view, which appends
the local public key to an existing introduction: a different key there makes
the introduction wrong, so the field should not invite editing.

Applies to param_ targets only, as a raw @ key is a fill-mode switch rather than
a form field. Several locked mappings accumulate into repeated `locked`
parameters, which the publish form already reads.

Note the deploy order this implies: a view nanopublication that starts using "!"
should be published only once the deployment reads it, as an older version
treats "!public-key__.1" as a field name of its own and fills nothing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01An6DWbMvqQM7z312vC7apK
@tkuhn
tkuhn merged commit d4ef870 into master Sep 4, 2026
8 checks passed
@tkuhn
tkuhn deleted the feat/678-locked-prefilled-values branch September 4, 2026 04:16
@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 5.13.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Locking pre-filled content

1 participant