The bucket endpoints now accept `versioning_status`, and the lifecycle
configuration has its own PUT/GET/DELETE beside the bucket, so the
versioning section stops being form state only.
- Create sends `DISABLED`/`ENABLED`, then writes the retention policy as a
second call, since Storage stores it separately from the bucket
- Edit derives `ENABLED`/`SUSPENDED` through `toVersioningStatusUpdate`;
`DISABLED` is not an accepted update, so a bucket that was never
versioned sends no versioning field at all
- Edit reads the stored policy back to prefill, rather than assuming none
`toLifecycleRules`/`fromLifecycleRules` map the form onto the API's rules.
"Both conditions" is one rule; "either condition" needs two, because S3
only honors a version cap alongside an age. The policy is only written
when one of the three fields the form owns actually changed — a blind PUT
replaces the whole configuration and would drop rules the dashboard
cannot model.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N3euXsz25sTybsGTcxCFfn