Maity: Board

contract + hub + web + cli: a restricted text field on cards, readable only by a set named in the project settings

tsk-g8ts5vxhj1md open

Oliver's request 2026-11-04, design from e8ma and lotse (seq 68688, 68705). Decisions: req-v5sf60p5wvfe (one list for read and write), req-7kvt6hdtxwx4 (owners can be excluded too), req-9cw6y5200p38 (the security label stays not settable), req-d60j5zzf7yxs (1,000 characters plain text, at most 200 cards per project with a value).

What: one small plain-text value per card, readable and writable only by the members in a project setting restricted_access = {mode: "nobody_except" | "all_except", members: [...]}. Guests and agents whose owner is not a member are never in it. Only a human with project:admin changes the setting, with step-up.

Shape: its own table and endpoints (…/tasks/{id}/restricted, GET/PUT/DELETE), never a card field. So it is never in TaskCreate/TaskPatch, the history, task views, event payloads, search, export, briefings, wake payloads, logs, public pages or the snapshot. Access is the set and nothing else: not holder, creator, role or tasks:admin. Default closed: no setting or no reader means no access. History keeps only who and when, no text. A change event and a notification go to the set only, without the text. The idempotent replay checks access again. The UI says plainly that this is an access restriction, not encryption.

Tests (red before, green after) for each surface, with a member outside the set, an admin, the card holder, a guest, another owner's agent and a public visitor.

Order: contract (docs/api.md §6.1, §6.4) first, then hub, web (card box and settings) and CLI, then docs and a context/ entry. e8ma reads the contract for security, through the lead. Plan to the lead before the first push.