* refactor(s3api): move Lifecycle XML structs to leaf package lifecycle_xml
The structs S3 PutBucketLifecycleConfiguration parses and the canonical
conversion to s3lifecycle.Rule lived in package s3api, which transitively
imports weed/server (which imports weed/shell). Any caller outside
weed/s3api — the shell, the future lifecycle worker — that wanted to
parse a bucket's lifecycle XML hit an import cycle.
Moves:
weed/s3api/s3api_policy.go -> lifecycle_xml/types.go
weed/s3api/s3api_lifecycle_canonical.go -> lifecycle_xml/canonical.go
s3api_lifecycle_canonical_test.go -> lifecycle_xml/canonical_test.go
s3api_policy_test.go -> lifecycle_xml/round_trip_test.go
Renames the public RuleStatus type (was unexported ruleStatus) and adds
small accessor methods (Set/Val/AndSet/TagSet) for fields the s3api
handler needs to read across the package boundary. Adds NewPrefix and
NewExpirationDays constructors so the GET handler can build response
rules without poking at unexported fields. Adds a Tag struct local to
the package so it has zero internal seaweed deps. Adds a one-shot
ParseCanonical(xml []byte) helper for non-server callers.
s3api_policy.go was misnamed — its content is lifecycle XML, not S3
bucket policy. The new package name reflects the actual scope.
* test(s3api/lifecycle_xml): exercise public API in tests
- canonical_test.go's parseLifecycle helper went through xml.Unmarshal
directly; route it through the package's exported Parse so tests
validate the public entrypoint.
- round_trip_test.go asserted internal flags (rule.Filter.tagSet,
rule.Filter.andSet, Transition.set, NoncurrentVersionTransition.set);
switch to TagSet(), AndSet(), Set() — exercises the public contract
that downstream callers (s3api handler, future shell command) rely on.