Skip to content

feat(s3s): add capability mechanism for opt-in semantics#533

Open
LeonWang0735 wants to merge 3 commits intos3s-project:mainfrom
LeonWang0735:feat/Explicit-Capability-Mechanism
Open

feat(s3s): add capability mechanism for opt-in semantics#533
LeonWang0735 wants to merge 3 commits intos3s-project:mainfrom
LeonWang0735:feat/Explicit-Capability-Mechanism

Conversation

@LeonWang0735
Copy link
Copy Markdown
Contributor

Type of Change

  • New Feature
  • Bug Fix
  • Documentation
  • Performance Improvement
  • Test/CI
  • Refactor
  • Other:

Related Issues

FEAT #475

Summary of Changes

Capability mechanism (opt-in semantics)

  • Goal: Let S3 backends explicitly declare which semantics they support. When a request uses a capability the backend has not declared, s3s returns 501 NotImplemented instead of silently ignoring it.
  • Design:Capability enum (#[non_exhaustive]). Currently only has a #[doc(hidden)] __Test variant for tests; real capabilities can be added later.
  • Capabilities: A set built on BTreeSet<Capability> with empty(), with(), contains(), missing(),
    check(required, supported): Returns NotImplemented if supported does not include every capability in required.
    S3 trait: Default fn capabilities(&self) -> Capabilities { Capabilities::empty() }.
  • Codegen: Each operation gets a generated required_capabilities(input).
    In Operation::call(), after deserializing the request and before calling the S3 impl, the generated code runs
    if !required.is_empty() { capability::check(&required,&ccx.s3.capabilities())? }.
  • Current policy: Only future input fields are gated. Existing fields (e.g. part_number) are not gated, so in codegen every operation’s required_capabilities returns Capabilities::empty(), and existing backends are unchanged.

Testing issues for this feature

  • Using a real capability for integration tests would break existing backends
    If codegen gated something like part_number with a real capability (e.g. GetObjectPartNumber), any existing backend that does not declare that capability would get 501 for requests that include partNumber, which is a breaking change. So I do not gate existing fields just to make integration tests possible.

  • Using __Test plus a field recreates the same trade-off
    I briefly gated part_number with Capability::__Test to restore the five integration tests. That made the tests pass but had the same effect as gating a real capability: requests with partNumber still returned 501 for backends that do not declare __Test. Reverting that kept backward compatibility but removed the only way to trigger the check on the real call path in tests.

  • Current test coverage
    Only the four unit tests in capability.rs exercise check() (empty required, missing capability, declared capability, superset). The codegen-injected required_capabilities and check call are not exercised by any integration test; their shape is validated by inspection. When a real capability is added and a field is gated in codegen, integration tests can be added for that path.

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 5, 2026

Codecov Report

❌ Patch coverage is 9.75057% with 398 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
crates/s3s/src/ops/generated_minio.rs 1.01% 392 Missing ⚠️
crates/s3s/src/capability.rs 92.85% 3 Missing ⚠️
crates/s3s/src/s3_trait.rs 0.00% 3 Missing ⚠️

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a capability mechanism for s3s that allows S3 backends to explicitly declare which optional semantics they support (issue #475). When a request requires capabilities the backend hasn't declared, s3s returns a 501 NotImplemented error instead of silently ignoring the feature.

Changes:

  • Adds a new capability module with Capability enum (#[non_exhaustive], currently only __Test), Capabilities set wrapper, and a check() function.
  • Adds codegen to emit required_capabilities(input) stubs and capability enforcement in every operation's call() method.
  • Adds capabilities() default method to the S3 trait, plus re-exports in lib.rs.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
crates/s3s/src/capability.rs New module: Capability enum, Capabilities set, check() function, and unit tests
crates/s3s/src/lib.rs Registers capability as a public module and re-exports Capabilities/Capability
crates/s3s/src/s3_trait.rs Generated: adds capabilities() default method to S3 trait
codegen/src/v1/s3_trait.rs Codegen for capabilities() method in S3 trait
codegen/src/v1/ops.rs Codegen for required_capabilities() stub and capability check in call()
crates/s3s/src/ops/generated.rs Generated: required_capabilities + capability check for all ops
crates/s3s/src/ops/generated_minio.rs Generated: same as above for MinIO variant

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants