feat(#571): admin switch for sharing with people and groups #578

Merged
Cordy merged 6 commits from fix-571ui into main 2026-09-17 20:07:18 +00:00
Owner

First UI slice of #571: the admin control for ShareInternalDisabled, which #575 has been enforcing server-side with no way to set it.

It is a checkbox, not a toggle. The mockup drew toggles; the scout showed every other switch on that screen is an input[type=checkbox] in .field.check. Matching what is there.

Placed second, directly under Public share links, because those two are the pair a reader compares — outside and inside. The three that follow (upload links, require password, maximum expiry) are all modifiers of public links specifically, so putting the new switch after them would read as though it modified them too. It uses the subfield variant so it can carry a hint: "sharing" now means two different things on this page, and the label alone does not separate them.

The mapping is the part that can break silently. shareInternalDisabled is stored negative like its two neighbours, so an instance upgrading into the field keeps sharing on. That inversion is one ! and a flipped checkbox still renders perfectly — which is exactly why the existing pure:sharing-policy block has tests. This extends them:

  • the round trip grows a third dimension, so all eight combinations are covered rather than four;
  • the two sharing switches do not move together — turning public links off must leave internal sharing on, and vice versa. This is the whole reason the field exists, and it is the one a careless refactor would undo;
  • absent keys read as all three enabled;
  • switching all three off stores explicit true, not undefined.

Red witnessed: 5 failing, every one undefined where a boolean belongs.

One note on how this went, because it is the same class of mistake twice in one session. The first green wrote !v.shareInternalDisabled on the assumption that sharingPolicyToForm's parameter was named v. It is not, and the whole mapping threw v is not defined — eight tests, including four that had been passing. The workflow now reads both signatures out of the block and prints them before splicing. Same lesson as the gofmt-alignment anchors earlier: if the source already contains the fact, do not retype it.

Verified: sharing-policy.test.js green, all eight web tests green, extract.js + node --check (the #389 fence gate) green, the \\u escape guard from #568 green, full Go suite green.

First UI slice of #571: the admin control for `ShareInternalDisabled`, which #575 has been enforcing server-side with no way to set it. **It is a checkbox, not a toggle.** The mockup drew toggles; the scout showed every other switch on that screen is an `input[type=checkbox]` in `.field.check`. Matching what is there. **Placed second, directly under Public share links**, because those two are the pair a reader compares — outside and inside. The three that follow (upload links, require password, maximum expiry) are all modifiers of public links specifically, so putting the new switch after them would read as though it modified them too. It uses the `subfield` variant so it can carry a hint: "sharing" now means two different things on this page, and the label alone does not separate them. **The mapping is the part that can break silently.** `shareInternalDisabled` is stored negative like its two neighbours, so an instance upgrading into the field keeps sharing on. That inversion is one `!` and a flipped checkbox still renders perfectly — which is exactly why the existing `pure:sharing-policy` block has tests. This extends them: - the round trip grows a third dimension, so all eight combinations are covered rather than four; - **`the two sharing switches do not move together`** — turning public links off must leave internal sharing on, and vice versa. This is the whole reason the field exists, and it is the one a careless refactor would undo; - absent keys read as all three enabled; - switching all three off stores explicit `true`, not `undefined`. Red witnessed: 5 failing, every one `undefined` where a boolean belongs. **One note on how this went**, because it is the same class of mistake twice in one session. The first green wrote `!v.shareInternalDisabled` on the assumption that `sharingPolicyToForm`'s parameter was named `v`. It is not, and the whole mapping threw `v is not defined` — eight tests, including four that had been passing. The workflow now *reads* both signatures out of the block and prints them before splicing. Same lesson as the gofmt-alignment anchors earlier: if the source already contains the fact, do not retype it. Verified: `sharing-policy.test.js` green, all eight web tests green, `extract.js` + `node --check` (the #389 fence gate) green, the `\\u` escape guard from #568 green, full Go suite green.
Cordy merged commit e7e3dd3943 into main 2026-09-17 20:07:18 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: Cordy/Cairn#578
No description provided.