Move the model-route access modal off the deprecated allowed_users
policy/field onto the unified allowed_principals + principals surface,
persisting everything through a single /access POST.
- "specific users" radio now uses allowed_principals; a returned legacy
allowed_users value is normalized so existing routes still select it.
- derive the picker's selection and the full grant set from `principals`
in GET /access (fall back to legacy `items` if a backend doesn't
return principals yet).
- save as `principals`: the principal-based override sends its staged
set; the user picker maps its selection to USER-kind grants and
preserves any non-user grants from the snapshot (no longer sends
`users`).
- guard saving before the GET seeds principals (would wipe grants);
share the ALLOWED_PRINCIPALS_POLICY constant.
- AccessControlFormData: `users` optional, add `principals`.
Reopening the Access Settings dialog after a save could leave the
radio on the wrong policy: the form initialized `access_policy`
from the route list's snapshot, but the list isn't refreshed when
the dialog closes, so the snapshot's value silently shadowed the
just-saved policy.
Backend now returns the route's authoritative `access_policy` on
`GET /v2/model-routes/{id}/access`. Use that value when the GET
resolves, falling back to the parent snapshot only as the initial
seed so the radio isn't briefly unselected.
While we're here, widen the `access_policy` type from a closed
union to `string` — plugins can contribute additional policy
values via the `accessControl.allowedUsersOverride` slot, so the
wire type shouldn't restrict to the OSS-side enum.