Provider Preset Specification

Purpose and scope

Providers can distribute a *.s3client.json file that configures their service in S3Client. The file can be generated entirely with the provider’s own tools. It contains connection settings and a declaration of supported S3 features, with no access credentials or secrets.

This specification covers the public s3client-provider-preset format, version 1.0, and the corresponding S3Client behavior as reviewed on October 10, 2026. It is intended for S3 service providers and requires no access to S3Client’s source code. JSON keys, tokens, and example values are case-sensitive. Required, optional, and forbidden describe the file format; runtime conditions explain separately when S3Client can use a feature.

The service profile is copied into an account when the account is created. Operations then use that account’s configuration; they do not infer capabilities from the provider’s name or identifier. Replacing or removing an installed preset does not change existing accounts.

The declaration must describe the particular service version, offering, and deployment it targets. It neither grants permissions nor enables remote features. Versioning, Object Lock, lifecycle rules, encryption, and logging still need to be configured on the relevant buckets. Credentials may lack permission to call an API even when the service supports it.

The functional scope is the Amazon S3 API. Implementation differences that affect use in S3Client must be expressed through the fields defined here where those fields can represent them. Arbitrary extension fields, proprietary features, and invented tokens are not accepted.

Minimal provider file

This complete example includes only required fields. It describes a fictional service with one region, one directly readable storage class, and no conditional capabilities or optional policies. Common S3 operations remain available, including GET/HEAD, single-request PUT, CopyObject, individual deletion, and v1 listing. Multipart uploads, ACLs, tagging, lifecycle editing, website configuration, and explicit encryption selection are not enabled.

Replace the identity, endpoint, region, and storage class declarations with those of the target service. The .example host is a placeholder. See the complete provider file example for a profile with additional capabilities and explicit optional policies.

{
  "kind": "s3client-provider-preset",
  "schemaVersion": {
    "major": 1,
    "minor": 0
  },
  "preset": {
    "id": "example.object-storage.minimal",
    "name": "Example Object Storage Minimal",
    "serviceProfile": {
      "capabilities": [],
      "serverSideCopyDomain": "",
      "protocol": "https",
      "port": 443,
      "regions": [
        {
          "name": "Default Region",
          "location": "us-east-1",
          "endpoint": "s3.storage.example",
          "authentication": "sigv4",
          "accessStyle": "path",
          "serverSideCopyDomain": "",
          "accountRegionalBucketNamespaceAvailable": false,
          "s3ControlRouting": {}
        }
      ],
      "storageClassPolicySet": {
        "defaultPolicyId": "standard-only",
        "policies": [
          {
            "id": "standard-only",
            "defaultClassName": "STANDARD",
            "classes": [
              {
                "name": "STANDARD",
                "placementPaths": [
                  "putObject",
                  "copyObject"
                ],
                "accessStrategy": "alwaysDirect",
                "restorePolicy": {
                  "semantics": "unsupported",
                  "days": {
                    "mode": "forbidden"
                  },
                  "retrievalTier": {
                    "mode": "forbidden",
                    "acceptedTiers": []
                  },
                  "versionSupported": false
                },
                "archiveStateHeaders": []
              }
            ],
            "transitions": [],
            "restoreStatusListingOperations": [],
            "intelligentTieringOperations": []
          }
        ],
        "bindings": []
      },
      "defaultRegionLocation": "us-east-1"
    }
  }
}

File format

Common JSON rules

  • Encode the file as UTF-8 with a single JSON object at the root. Use .s3client.json as the recommended distribution suffix.
  • The maximum file size is 33,554,432 bytes (32 MiB). The reader also limits nesting to 32 levels and the total number of JSON values to 1,000,000.
  • Comments, trailing commas, and duplicate keys are forbidden. Equivalent key spellings, including a Unicode-escaped spelling of an existing key, count as duplicates.
  • Every object has a closed set of keys. Unknown fields are rejected, including a root-level $schema. Supply the schema reference to an external validator rather than adding it to the file.
  • Booleans must be true or false, never numbers or strings. Token arrays are sets without duplicates and their order has no meaning. ACL API, operation and form declarations are keyed objects.
  • Strings must contain valid Unicode scalar values and no NUL character. Leading or trailing whitespace means TAB through CR, NEL, or a Unicode separator character. Ordinary strings must not exceed 4,096 Unicode scalar values or have leading or trailing whitespace. A stricter field-specific maximum takes precedence. Empty strings are allowed only where explicitly stated.
  • An omitted optional field receives the default specified here. null is not equivalent to omission: it is forbidden except for the two ACL fields explicitly defined as nullable.

Integers from -9007199254740991 through 9007199254740991 can be represented as JSON numbers. For 64-bit integers outside that range, use the exact object form {"$integer":"9223372036854775807"}. Its string must be canonical decimal notation, with no +, redundant leading zeros, or whitespace. In provider presets, this form is particularly relevant to defaultMinimumObjectSize, whose range is 0 through 9223372036854775807. Use ordinary JSON numbers for the small integers specified elsewhere in this document.

  • Storage class names and references are ASCII JSON strings only; Base64 containers are forbidden.

Envelope

FieldPresenceType and value
kindRequiredThe exact string "s3client-provider-preset".
schemaVersionRequiredThe exact object {"major":1,"minor":0}.
softwareOptionalThe exact object {"name":"S3Client","website":"https://s3client.com"}.
presetRequiredAn object containing exactly id, name, and serviceProfile.

software identifies the S3Client format, not the provider or the program that generated the file. It may be omitted. If included, both values are fixed.

Generate new files in version 1.0. Other versions, including future versions, are rejected before preset-specific fields are validated. These version numbers apply to the public provider file only.

Import and export behavior

Import accepts only schema 1.0 and validates the document without schema conversion. Installing a preset with an existing custom identifier replaces that preset; existing accounts retain their settings. Reading a file does not rewrite it.

Export always writes the current schema, version 1.0, includes software, and writes every optional service profile field with its effective value, including defaults for fields omitted at import. It also serializes nested policies from their effective values. An import/export round trip preserves the preset’s identity and configuration, but does not preserve the original JSON representation: omitted fields can become explicit, token order and formatting can change. Storage class names are always written as strings.

Preset identity

preset.id is a stable identifier of 1 to 128 ASCII characters. It consists of dot-separated segments. Each segment starts and ends with a lowercase letter or digit and may contain hyphens. Empty segments, uppercase letters, whitespace, _, .-, and -. are forbidden. The identifier must match:

^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)*$

For example, example.object-storage.general is valid. Keep the same identifier when publishing an update to a preset. Use distinct identifiers for offerings or versions that must coexist.

preset.name is a nonempty display name of up to 4,096 Unicode scalar values, with no leading or trailing whitespace. An English name fits S3Client’s English user interface.

During installation, amazon.s3.general and generic.s3-compatible are reserved identifiers. The names Amazon S3 and S3-compatible storage are also reserved, case-insensitively. Two custom presets with different identifiers cannot have the same name, ignoring case. These installation checks apply in addition to the file’s syntactic validation.

Service profile fields

All fields in this table belong to preset.serviceProfile.

FieldPresenceType and purpose
capabilitiesRequiredAn array of enabled capability tokens. [] disables all conditional capabilities.
objectLockActivationTokenOptionalString, default "", at most 4,096 visible ASCII characters (U+0021 through U+007E); null is invalid. A nonempty value is sent as x-amz-bucket-object-lock-token only when enabling Object Lock on an existing bucket. It is not a credential. It is never sent during bucket creation or default-retention changes.
serverSideCopyDomainRequiredA possibly empty string identifying a shared server-side copy domain.
protocolRequired"https" or "http".
portRequiredAn integer from 1 to 65,535; required even for ports 443 and 80.
regionsRequiredAn array of 1 to 100 region objects.
defaultRegionLocationRequiredThe canonical location of an existing region. Array order does not change this selection.
requestLimitsOptionalGeneral request header limits; omitted fields default to zero, meaning no configured limit.
storageClassPolicySetRequiredA set of storage class policies.
aclPolicyOptionalA complete ACL policy. If omitted, all ACL APIs and request forms are disabled.
lifecycleCapabilityPolicySetOptionalLifecycle policies. If omitted, all detailed options are disabled.
bucketTaggingCapabilityPolicyOptionalThe bucket tagging API selection. Defaults to "unavailable".
objectTaggingCapabilityPolicyOptionalObject describing reading, editing and tags in content operations; when omitted, these features are unavailable.
bucketLoggingCompatibilityPolicyOptionalstrictS3 (default) or preserveKnownLoggingAdditions.
websiteCapabilityPolicySetOptionalStatic website policies. If omitted, all options are disabled.
encryptionCapabilityPolicySetOptionalEncryption policies. If omitted, all operation and mode arrays are empty and all booleans are false.

Omitted lifecycle, website, and encryption policy sets are each treated as a set with a single policy named default and no bindings. They are not inferred from capabilities.

A profile must not contain provider, credentials, accessKeyId, secretAccessKey, sessionToken, an account UUID, serviceAccountId, KMS favorites, SSE-C keys, a personal bucket list, bucket settings, or directCopyBetweenAccountsEnabled. Those are account or operation data, not public service characteristics.

Connection settings and regions

Region objects

All eight fields below are required, including fields whose value is an empty string, false, or {}.

FieldType and meaning
nameA nonempty label, such as "Europe West". Unique ignoring case.
locationA nonempty, unique S3 region identifier used for routing and signing. Must already use its canonical representation.
endpointThe canonical S3 data service host, with no scheme, port, path, query, or credentials. Maximum 253 Unicode scalar values.
authentication"sigv2" or "sigv4".
accessStyle"path", "virtual-hosted", or "virtual-hosted-with-path-fallback".
serverSideCopyDomainA possibly empty string overriding the global copy domain for this region.
accountRegionalBucketNamespaceAvailableA boolean declaring regional availability of the account-regional namespace.
s3ControlRoutingAn object defining S3 Control routes, or {} when no routes are declared.

Region locations and endpoints must already be canonical in the file. Import rejects values that would change during normalization; it does not correct them. For example, US-EAST-1, EU, and S3.Example.COM. are rejected in region objects.

To generate a canonical location, apply case folding, except that the exact legacy S3 value EU maps to eu-west-1. Lowercase eu remains a distinct identifier. Write the resulting value, such as us-east-1 or eu-west-1, directly in the file.

Write DNS endpoints as lowercase IDNA ASCII without a trailing dot, such as s3.example.com. IPv4 addresses are allowed in canonical form. IPv6 addresses must use their canonical bracketed form, such as [::1]. IP addresses require accessStyle: "path". Supply the base host, not https://s3.example.com, s3.example.com:443, s3.example.com/buckets, or *.s3.example.com.

For bucket photos and key image.jpg, the address styles produce:

StyleConstructed address
pathhttps://s3.example.com:443/photos/image.jpg
virtual-hostedhttps://photos.s3.example.com:443/image.jpg
virtual-hosted-with-path-fallbackNormally virtual-hosted; path style when using HTTPS and the bucket name contains a dot.

The last style defines this specific local choice, which is useful with wildcard TLS certificates. It does not mean trying a request and switching styles after an error.

The profile’s protocol and port apply to the S3 endpoints in every region. Distribute separate presets for deployments requiring different protocols or ports. S3 Control routes have their own protocol and port.

Server-side copy domains

serverSideCopyDomain is an opaque, case-sensitive identifier of up to 4,096 Unicode scalar values. A nonempty value declares that sources and destinations with that identifier share a namespace in which S3 server-side copying is possible. It is neither a URL nor a property inferred from the provider’s brand.

A nonempty regional domain overrides the global domain. An empty regional domain inherits the global value. If both are empty, S3Client uses a domain specific to the local account. Copies within that account remain possible, but no shared domain is declared between separate accounts. An empty string therefore does not disable CopyObject within the account.

Copying directly between separate accounts also requires the user to enable direct copying in both accounts. A public preset cannot enable that setting. Permissions, encryption, size, and UploadPartCopy availability are checked separately. Otherwise, S3Client can transfer the data through the client.

Do not assign one domain to isolated deployments, such as every installation of a particular S3 server. Regions that cannot copy directly to one another need distinct regional domains. The domain also helps identify a shared object namespace, so an incorrect declaration can cause sources and destinations to be misidentified.

S3 Control routes

s3ControlRouting accepts only generalPurposeRoute and directoryBucketRoute, both optional. Omit unavailable routes rather than setting them to null. Each included route contains exactly these fields:

FieldConstraint
hostTemplateThe canonical control service host, distinct from the S3 data endpoint.
protocol"http" or "https".
portAn integer from 1 to 65,535.
signingRegionA canonical identifier exactly matching the region’s location.
signingService"s3" for generalPurposeRoute; "s3express" for directoryBucketRoute.
arnPartitionA string of 1 to 64 characters from [a-z0-9-], such as "aws".

For generalPurposeRoute, hostTemplate must start with exactly {accountId}. and contain that substitution once. No other braces or substitutions are allowed. After replacing it with the 12-digit account ID, the host must not exceed 253 Unicode scalar values, leaving at most 240 units for the suffix after {accountId}.. For directoryBucketRoute, substitutions are forbidden and the host limit is 253 units.

When both routes are present in a region, they must declare exactly the same arnPartition.

An example s3ControlRouting object for us-east-1:

{
  "generalPurposeRoute": {
    "hostTemplate": "{accountId}.s3-control.us-east-1.amazonaws.com",
    "protocol": "https",
    "port": 443,
    "signingRegion": "us-east-1",
    "signingService": "s3",
    "arnPartition": "aws"
  },
  "directoryBucketRoute": {
    "hostTemplate": "s3express-control.us-east-1.amazonaws.com",
    "protocol": "https",
    "port": 443,
    "signingRegion": "us-east-1",
    "signingService": "s3express",
    "arnPartition": "aws"
  }
}

These routes support resource tagging through S3 Control. Their presence does not enable tagging APIs or declare general support for directory buckets or S3 Express.

Capability catalog

Declaring capabilities and dependencies

capabilities contains enabled tokens only. An absent token is disabled; there is no unknown state. Order is unrestricted and duplicates are forbidden. The following 53 tokens are the complete set accepted by this version. Use exactly these strings in JSON.

The catalog is not a list of every feature S3Client can use. Several features are declared through separate policies:

FeatureDeclaration
ACL APIs and ACLs on object writesaclPolicy
Storage classes, restoration, and allowed lifecycle transitionsstorageClassPolicySet
Detailed lifecycle rule formslifecycleCapabilityPolicySet, together with the lifecycle API tokens
Bucket and object tagsbucketTaggingCapabilityPolicy and objectTaggingCapabilityPolicy
Static website configurationwebsiteCapabilityPolicySet
Encryption operations and optionsencryptionCapabilityPolicySet, together with the applicable encryption tokens

Do not invent capability tokens for these features. The sections below define their policies.

Disable a capability only when the server does not support the feature or S3Client cannot use it correctly within the declared scope. A behavioral difference from Amazon S3 alone is not a reason to disable it. If the feature remains usable in S3Client, keep the capability enabled even when the server performs the operation or returns a response differently.

Qualification checks the operations S3Client actually performs, the responses it can handle, and the effects needed for the intended workflow: data, metadata, permissions, versions, and concurrency guarantees. It does not require identical reproduction of every Amazon response or implementation detail. A deviation observed in a test therefore does not automatically disable a capability; document its concrete effect on S3Client.

Use existing policies, scopes, and options to describe limited but usable support. For example, an ACL update that the service performs by copying the object may remain supported for the current object, but must not be declared usable for an exact version if it creates a different version instead. If a restriction affects an operation S3Client performs and no setting can avoid it, do not declare the feature globally usable. Describe the restriction separately when requesting additional compatibility from S3Client.

The validator rejects a preset if any of these dependencies is missing:

Declared tokenAlso required
conditional-delete-multiple-objectsdelete-multiple-objects
delete-multiple-object-versionsdelete-multiple-objects
upload-part-copymultipart-upload
conditional-upload-part-copy-sourceupload-part-copy
list-multipart-uploadsmultipart-upload
list-objects-v2-start-afterlist-objects-v2
get-bucket-object-lock-configurationobject-versions
enable-bucket-object-lockobject-versions, get-bucket-object-lock-configuration
put-bucket-object-lock-configurationobject-versions, get-bucket-object-lock-configuration
create-bucket-object-lockobject-versions
get-object-retentionobject-versions, get-bucket-object-lock-configuration
put-object-retentionobject-versions, get-bucket-object-lock-configuration, get-object-retention
get-object-legal-holdobject-versions, get-bucket-object-lock-configuration
put-object-legal-holdobject-versions, get-bucket-object-lock-configuration, get-object-legal-hold
put-object-lockobject-versions, get-bucket-object-lock-configuration
create-multipart-upload-object-lockobject-versions, get-bucket-object-lock-configuration
copy-object-lockobject-versions, get-bucket-object-lock-configuration
bypass-governance-retentionobject-versions, get-bucket-object-lock-configuration

The following tables describe additional runtime conditions. Not all of them are checked when importing the file.

Listing and transfers

TokenService contract and S3Client use
list-objects-v2ListObjectsV2, including prefix, delimiter, max-keys, encoding-type=url, and pagination through continuation-token requests and NextContinuationToken responses. S3Client uses it for normal browsing; without this token, it uses v1 ListObjects. Range scans have the additional requirement described below.
list-objects-v2-start-afterThe StartAfter parameter of ListObjectsV2, starting strictly after the specified key. Enables parallel range scans and requires list-objects-v2.
list-buckets-paginationListBuckets accepts max-buckets and continuation-token and returns the next cursor in ContinuationToken. S3Client requests pages of up to 10,000 buckets. Without this token, it sends a request without these parameters.
multipart-uploadThe CreateMultipartUpload, UploadPart, CompleteMultipartUpload, and AbortMultipartUpload workflow. Supports transfers in parts, including objects too large for a single request. Does not imply support for UploadPartCopy or ListMultipartUploads.
upload-part-copyUploadPartCopy reads an S3 source, optionally a byte range, to create a part on the server. Requires multipart-upload, a compatible copy domain, and the necessary permissions.
conditional-copy-sourceCopyObject accepts x-amz-copy-source-if-match with the observed source ETag and refuses to copy a different source revision. Covers all usable source objects, including completed multipart objects and supported versions. Without this token, S3Client explicitly permits CopyObject without that header, including moves, renames, property rewrites, version promotion, and synchronization. Does not require multipart-upload and does not declare UploadPartCopy conditions.
conditional-upload-part-copy-sourceThe same source ETag condition is enforced by every UploadPartCopy request, including when its source was uploaded in multiple parts. Requires upload-part-copy. Without this token, S3Client explicitly permits copying parts without that header. Independent of conditional-copy-source: declare each API’s support separately.
list-multipart-uploadsListMultipartUploads discovers unfinished uploads so they can be aborted during cleanup. Includes prefix, encoding-type=url, max-uploads=1000, and pagination with key-marker and upload-id-marker, using NextKeyMarker and NextUploadIdMarker from truncated responses. Requires multipart-upload. This is not the listing of parts of a completed object.
head-object-part-numberHeadObject?partNumber=N reports a part’s size, and x-amz-mp-parts-count reports the number of parts in a completed multipart object. Used when reading properties. There is no format-level dependency on multipart-upload: another client may have created the object.
presigned-urlThe service accepts presigned URLs using the configured signing method. S3Client can generate temporary authenticated access links. This does not declare public access or website hosting. A URL alone does not convey an SSE-C key.
bittorrent-deliveryThe legacy S3 GetObjectTorrent API returns a torrent file. Enable only if the service actually implements it; acceptance of this token does not guarantee its availability in current Amazon S3.

Common S3 operations, including object GET/HEAD, single-request PUT, CopyObject, individual deletion, and v1 listing, have no base capability token. capabilities: [] does not mean that S3 access is unavailable.

Key range scans use ListObjectsV2 only when both list-objects-v2 and list-objects-v2-start-after are enabled. Otherwise, they use the exclusive marker of v1 ListObjects, even when normal browsing uses v2. Version listing uses ListObjectVersions according to the requested mode and the object-versions capability.

Conditional writes and deletes

TokenService contract and S3Client use
conditional-writeOn the destination of PutObject, CopyObject, and CompleteMultipartUpload, If-None-Match: * rejects creation if a current object already exists at the key. S3Client requires SigV4.
conditional-overwriteOn the destination of the same three APIs, If-Match: <ETag> rejects replacement if the current ETag differs from the observation used to prepare the action. S3Client requires SigV4.
delete-multiple-objectsDeleteObjects accepts up to 1,000 keys without a versionId in an XML body and returns per-object successes and errors. S3Client batches these deletions to reduce requests; without this token, it deletes objects individually. On a versioned bucket, deleting a current key may create a delete marker.
delete-multiple-object-versionsDeleteObjects also supports targets with an explicit versionId: data versions, delete markers, and the null version. Requires delete-multiple-objects. Without this token, S3Client deletes these targets individually with DeleteObject only when object-versions enables individual version access, while continuing to batch keys without a versionId. Batched version deletion remains available independently of object-versions; it can also serve a single target when individual deletion is unavailable. If no compatible method exists, deletion fails before any request. Mixed batches are split according to these capabilities, without probing requests.
conditional-delete-objectDeleteObject accepts If-Match with an observed ETag and rejects deletion when the target’s ETag differs. Used particularly for moves and synchronization. It does not guarantee detection of changes that leave the ETag unchanged.
conditional-delete-multiple-objectsEach Object in the DeleteObjects XML accepts its own ETag element as a deletion condition. Requires delete-multiple-objects. This is not a single HTTP If-Match header applied to the whole batch.

S3Client treats failed write preconditions as conflicts. The service must enforce the conditions atomically; a preliminary HEAD followed by an unconditional PUT does not satisfy this contract. An ETag is an opaque value, not necessarily an MD5 checksum or a version identifier. An ETag condition cannot detect a change that leaves that value unchanged, including some metadata, ACL, tag, or encryption changes.

On a versioned bucket, If-None-Match: * concerns the current object: older versions alone do not prevent creation, and a current delete marker counts as absence. If-Match compares an ETag; it does not select an older version for replacement. Conditional deletions likewise do not require a missing object to be reported as a conflict. A DeleteObjects batch is not an all-or-nothing transaction: some targets can succeed while others fail, and an HTTP 200 response can contain per-object errors.

The source copy header x-amz-copy-source-if-match does not establish support for conditional-overwrite or conditional-write, which protect the destination. Declare a token covering all three destination APIs only if all three paths are compatible. See the PutObject parameters, CopyObject conditions, UploadPartCopy conditions, DeleteObject conditions, and the DeleteObjects request body.

Source copy conditions use the captured destination account capabilities, because its service executes the copy. Selecting another signing account does not change that declaration. Enabling a source-condition token preserves the condition whenever the source has a usable ETag; omitting it authorizes copies without that condition, without probing the service or retrying a failed conditional copy without protection. Declare support only when false conditions prevent the content read, not merely when the header is accepted or a preliminary HEAD succeeds.

Disabling these tokens does not remove source HEAD checks, explicit version IDs, rewrite identity validation, GET If-Match, destination write conditions, or conditional deletion. Nevertheless, an unversioned or mutable source may change after observation. An unprotected CopyObject may copy a later revision; unprotected UploadPartCopy requests may combine different revisions. In-place rewrites may replace concurrent changes, and synchronization may transfer content different from its initial observation. Destination validation does not restore the missing source guarantee. Immutable selected versions retain their version-based identity; the literal null version is not an immutable version.

Versioning and protection

TokenService contract and S3Client use
object-versionsListObjectVersions with key/version marker pagination, and object access, copying or individual deletion with an explicit versionId. Enables version views and workflows independently from bucket versioning configuration. Batched version deletion is declared separately.
get-bucket-versioningReads the bucket state through GetBucketVersioning. Does not authorize changes.
put-bucket-versioningEnables or suspends bucket versioning through PutBucketVersioning. Does not enable version listing or reading the bucket state by itself.
get-bucket-object-lock-configurationRead whether Object Lock is enabled and the bucket default retention.
enable-bucket-object-lockPermanently enable Object Lock on an existing bucket.
put-bucket-object-lock-configurationSet or remove default retention for future versions; existing protections remain.
create-bucket-object-lockEnable Object Lock in the bucket creation request. The creation option is unchecked by default.
get-object-retentionRead a version’s retention mode and expiration.
put-object-retentionSet or change retention, within Governance and Compliance restrictions.
get-object-legal-holdRead a version’s legal hold.
put-object-legal-holdSet or remove a version’s legal hold.
put-object-lockSend retention and legal hold on PutObject.
create-multipart-upload-object-lockSend retention and legal hold on CreateMultipartUpload. Multipart upload must also be available for that transfer.
copy-object-lockSend retention and legal hold on CopyObject. Multipart copies use the multipart protection capability.
bypass-governance-retentionSend Governance bypass after an explicit choice and with remote permission. Does not bypass Compliance or legal hold.

S3Client does not expose versioning for directory buckets. An explicit versionId=null on object reads or deletion targets their current object and does not enable versioning or provide an immutable identity; other explicit version IDs are rejected. Versioning and Object Lock configuration are available for general purpose buckets discovered as belonging to the account. An external bucket is one accessed by name without being discovered as belonging to that account; its versions can still be listed when object-versions is enabled and it is not a directory bucket. Object Lock requires bucket versioning and cannot be disabled after activation. A delete marker is not a data version that can be tagged or protected as an object.

Read capabilities are separate from write capabilities. S3Client requires the configuration reads listed in the dependency table to establish the state before editing; changing retention or legal hold also requires the corresponding version read. A declared capability neither grants remote permission nor proves that a particular bucket has Object Lock enabled. The protection on a returned HEAD response must not be treated as absent because an optional read API is disabled. Rewrites that cannot read or preserve the necessary protection fail explicitly.

Protection is validated against the actual transfer path: simple upload, multipart initiation or CopyObject. A relay copy uses the destination upload path. Governance bypass remains an explicit choice and cannot remove a legal hold or shorten Compliance retention. Removing a default-retention rule does not disable Object Lock or remove existing version protections.

Bucket creation, ownership, and ARNs

TokenService contract and S3Client use
get-bucket-ownership-controlsGetBucketOwnershipControls reads BucketOwnerEnforced, BucketOwnerPreferred, or ObjectWriter. Used, among other things, to determine whether bucket ACLs are active.
put-bucket-ownership-controlsPutBucketOwnershipControls replaces this setting on an existing bucket. Does not declare read support or support for the creation header.
create-bucket-object-ownershipCreateBucket accepts x-amz-object-ownership with these three values, allowing ownership to be selected at creation.
create-bucket-recreation-resets-aclDeclares a hazardous behavior: CreateBucket may succeed on an already owned bucket and reset its ACL. S3Client checks owned buckets before creation in the historical case of no explicit region or us-east-1, outside the account-regional namespace. Declare the behavior if it exists; the token does not authorize recreating a bucket.
create-bucket-account-regional-namespaceCreateBucket accepts x-amz-bucket-namespace: account-regional. Also requires accountRegionalBucketNamespaceAvailable: true in the selected region and the user’s 12-digit serviceAccountId to construct a name ending in -<accountId>-<region>-an. Do not put this account ID in the preset. This is not a directory bucket.
standard-s3-resource-arnStandard S3 resource ARNs are usable for this service, such as arn:aws:s3:::bucket and arn:aws:s3:::bucket/key. Allows reconstruction of a missing ARN; does not declare an IAM API. For S3 Control, the partition comes from the configured route.

The three ownership capabilities apply to general purpose buckets in S3Client. BucketOwnerEnforced makes the bucket owner own the objects and disables effective bucket and object ACLs. BucketOwnerPreferred makes the bucket owner own newly written objects sent with bucket-owner-full-control; other writes retain writer ownership. ObjectWriter makes the uploading account own new objects. Declaring ACL APIs does not override these bucket settings.

Lifecycle

TokenService contract
get-bucket-lifecycle-configurationGetBucketLifecycleConfiguration reads lifecycle rules.
put-bucket-lifecycle-configurationPutBucketLifecycleConfiguration creates or replaces the entire rule set in one request. Allowed options are declared in lifecycleCapabilityPolicySet; transitions are declared in storageClassPolicySet.
delete-bucket-lifecycleDeleteBucketLifecycle removes the entire configuration. It does not immediately delete objects.

S3Client’s lifecycle editor applies to general purpose buckets and requires read support. Editing and deleting also require their respective capabilities. A valid JSON preset with PUT support alone therefore does not make the editor usable.

Encryption

TokenService contract
sse-s3Explicit SSE-S3 selection (AES256) when writing objects. Allowed APIs are specified by sseS3Operations.
sse-kmsExplicit SSE-KMS selection (aws:kms), with allowed APIs in sseKmsOperations.
dsse-kmsExplicit DSSE-KMS selection (aws:kms:dsse), with allowed APIs in dsseKmsOperations.
sse-cAES-256 SSE-C encryption with a customer-provided key. Allowed APIs and source/destination roles are specified by the dedicated operation arrays. S3Client requires HTTPS.
get-bucket-encryptionGetBucketEncryption reads the remote bucket configuration.
put-bucket-encryptionPutBucketEncryption writes that configuration. Allowed modes and options are declared separately in the encryption policy.
delete-bucket-encryptionDeleteBucketEncryption removes the remote configuration. It neither decrypts existing objects nor guarantees unencrypted future writes.
update-object-encryptionUpdateObjectEncryption changes encryption for an object or version without copying its data. S3Client requires a general purpose bucket, an SSE-KMS destination, sse-kms, HTTPS, SigV4, a full KMS key ARN, and an SSE-S3 or SSE-KMS source without Object Lock protection. Combined changes and preconditions must not require copying. The Bucket Key option is controlled by updateBucketKeys.

The bucket encryption editor reads an interpretable configuration before editing or deleting it. Declare GET as well as PUT/DELETE for that workflow. Object write capabilities and bucket default encryption modes are independent. A service that always encrypts objects may still reject explicit algorithm selection.

S3Client’s bucket encryption operations apply to general purpose buckets. PUT requires SigV4, including for SSE-S3.

UpdateObjectEncryption is distinct from copying an object onto itself. PutBucketEncryption sets a bucket default; it does not convert existing objects.

Bucket access logging

TokenService contract
get-bucket-loggingGetBucketLogging reads the access log delivery configuration.
put-bucket-loggingPutBucketLogging enables, replaces, or disables that configuration. There is no DELETE token: disabling uses PUT.
bucket-logging-target-object-key-formatPUT accepts an explicit TargetObjectKeyFormat: SimplePrefix or PartitionedPrefix, using EventTime or DeliveryTime as the date source.
bucket-logging-target-grantsPUT accepts TargetGrants granting access to delivered logs. These grants are separate from the account’s general ACL policy.

The editing workflow requires GET and PUT and applies to general purpose buckets. Both options require PUT support. S3Client refuses to write nonempty TargetGrants when the destination bucket is known to use BucketOwnerEnforced; it does not silently remove them. This feature is distinct from proprietary service logs and CloudTrail.

Logging response compatibility

SimplePrefix is equivalent to the implicit default format. When bucket-logging-target-object-key-format is disabled, S3Client preserves this meaning by omitting the field on PUT; a partitioned format requires that capability.

bucketLoggingCompatibilityPolicy defaults to strictS3. preserveKnownLoggingAdditions accepts only ObjectRollTime and RecordsBatchSize as unsigned 32-bit integers, and LoggingType equal to Standard, under LoggingEnabled. S3Client preserves present fields when updating enabled logging and compares them during conflict detection. Disabling logging removes the entire configuration. They are not editable settings; Journal, unknown additions and incorrect locations or structures remain uneditable. This policy does not replace logging GET/PUT capabilities.

Context-specific policy selection

storageClassPolicySet, lifecycleCapabilityPolicySet, websiteCapabilityPolicySet, and encryptionCapabilityPolicySet share this envelope:

{
  "defaultPolicyId": "general",
  "policies": [],
  "bindings": []
}

This illustrates the structure only: policies: [] is invalid. Each set contains 1 to 32 policies and 0 to 1,000 bindings. All three keys are required; no additional keys are allowed.

Each policy has a nonempty id of up to 256 Unicode scalar values, with no leading or trailing whitespace or NUL character. Identifiers are unique and case-sensitive within their set. defaultPolicyId and each policyId must reference an existing policy in that same set. The same identifier may be used in different sets without linking those policies.

A binding selects a whole policy; it does not merge it with the default. Every binding contains selectorKind and policyId, plus only the fields required by its selector:

PriorityselectorKindAdditional required fields
1exactBucketendpoint, bucketName
2endpointAndBucketKindendpoint, bucketKind
3regionAndBucketKindregionLocation, bucketKind
4bucketKindbucketKind
5endpointendpoint
6regionregionLocation

If several selectors match, the highest-priority selector wins regardless of array order. If none matches, defaultPolicyId is used. Two bindings of the same selector type must not have identical criteria after normalization, even if they reference the same policy.

Binding selector locations and endpoints must already be canonical, using the same rules as region objects. Import rejects a value that would change during normalization. regionLocation is limited to 4,096 Unicode scalar values. bucketName is nonempty, limited to 256 Unicode scalar values, has no leading or trailing whitespace or NUL character, and is compared exactly. Wildcards and prefix matching are not supported.

bucketKind accepts generalPurpose, directory, or outposts. There is no unknown selector. A policy for a bucket type cannot add functionality that S3Client’s execution paths do not support.

This regional binding can be added to a set containing a policy named eu-standard:

{
  "selectorKind": "region",
  "policyId": "eu-standard",
  "regionLocation": "eu-west-1"
}

Policies do not override global capabilities. A disabled global capability remains disabled even if a regional policy declares options for that feature. Only these four policy sets support bindings. The capability tokens, ACL policy, bucket and object tagging policies, and logging compatibility policy apply to the whole profile. Use separate presets if those declarations differ between regions or offerings.

Storage classes and archiving

Storage class policy structure

Every object in storageClassPolicySet.policies contains exactly these six required fields:

FieldType and meaning
idThe policy identifier.
defaultClassNameThe name of a class present in classes.
classesAn array of 1 to 100 class descriptions, with unique, case-sensitive names.
transitionsAn array of 0 to 1,000 allowed lifecycle transitions.
restoreStatusListingOperationsAn array of listObjects, listObjectsV2, and/or listObjectVersions: listing APIs that accept a request for restore status.
intelligentTieringOperationsAn array of get, put, list, and/or delete: declared support for the corresponding S3 Intelligent-Tiering configuration APIs.

Declaring Intelligent-Tiering support does not create a remote configuration. Listing options do not replace the list-objects-v2 or object-versions capabilities needed to use the relevant APIs. [] declares that these options are unavailable.

restoreStatusListingOperations permits the x-amz-optional-object-attributes: RestoreStatus header on each named API and the return of restore progress and expiry information. The four Intelligent-Tiering tokens correspond to GetBucketIntelligentTieringConfiguration, PutBucketIntelligentTieringConfiguration, ListBucketIntelligentTieringConfigurations, and DeleteBucketIntelligentTieringConfiguration, respectively. This S3Client version stores the declaration but does not call these four APIs or provide an Intelligent-Tiering configuration screen. Reading and restoring objects in an Intelligent-Tiering class remain governed by that class’s access and restore policies.

Class names, defaultClassName, sourceClassName, and targetClassName consist of 1 to 256 ASCII bytes. Allowed characters are letters, digits, ! # $ % & ' * + - . ^ _, the backtick, |, and ~. Spaces are forbidden. Use the exact token the service expects in x-amz-storage-class, not a marketing label. The format does not define a closed list of class names; the mechanisms remain those of the S3 APIs.

Class descriptions

Every class contains these five required fields and the optional declaration below:

FieldValues and behavior
nameThe class token sent to the service.
placementPathsA subset of putObject, createMultipartUpload, and copyObject: paths that allow placement into this class.
accessStrategyalwaysDirect, restoreRequired, or archiveStateDependent.
restorePolicyAn object describing RestoreObject, even when restoration is unavailable.
archiveStateHeadersA subset of restore and archiveStatus, corresponding to x-amz-restore and x-amz-archive-status.
sameObjectStorageClassChangeOptional boolean, default false. Allows changing to this destination class by copying an object to the same bucket and key in the same storage namespace. Requires at least one enabled placement path. The engine still checks the path actually used, including putObject for an existing client-side copy path.

sameObjectStorageClassChange is independent of ordinary copy placement: copyObject alone does not enable a class change on the same key. The effective destination class is compared with the observed source class, including selection of the service default. A selected historical version copied to the same key is treated conservatively as a same-object copy, comparing against that source version. A matching class, metadata-only change or encryption-only change does not itself require this permission; S3Client does not remove storage-class headers to bypass a restriction. Uploads (including explicit replacement uploads) and copies to a different key retain their ordinary placement rules. true does not enable additional transports: multipart copy still requires its existing capabilities and policies. Placement constraints select a compatible method before multipart preferences, within server copying or an already-required client relay. A class restriction alone does not trigger download/reupload; a disabled same-object permission is never bypassed. Absent means false; present null or non-boolean values are rejected. Existing accounts are not reconfigured when a preset is imported or replaced.

The existing source HEAD is used before the final same-object decision and any qualification that can write. This is not an atomic storage-class precondition: a class change after HEAD can retain the ETag.

placementPaths: [] is valid. A class may be encountered when reading an object or reached through lifecycle rules without being selectable for uploads or copies. For transfers that may need multiple paths, S3Client offers only classes compatible with the necessary paths. Multipart placement uses createMultipartUpload, not an uploadPart token.

defaultClassName must identify the class actually applied when no storage class header is sent. Selecting the service default omits x-amz-storage-class, but S3Client still treats this name as the effective class. Preserving a source class that equals the destination default may also omit the header. Explicitly selecting a different class requires the corresponding placement path to be allowed.

alwaysDirect means the class can be read without restoration. restoreRequired means it is archived and requires a still-valid temporary readable copy or an appropriate restoration. archiveStateDependent means the class may be in a directly readable or archived tier; S3Client must observe its state before selecting a path.

archiveStateDependent requires at least one entry in archiveStateHeaders. For x-amz-archive-status, the recognized states are ARCHIVE_ACCESS and DEEP_ARCHIVE_ACCESS. For x-amz-restore, S3Client interprets ongoing-request and, for temporary readable copies, expiry-date as an HTTP date in GMT. Unknown or contradictory states are not treated as readable.

After a successful HEAD, absence of these headers has a defined meaning. With restoreRequired, the object is still considered archived. With archiveStateDependent, absence of an archive indicator means it is not archived. Declare only headers for which the service follows these semantics. S3Client does not assume that an unknown class is directly readable.

Restoration

restorePolicy contains exactly semantics, days, retrievalTier, and versionSupported. All four are required.

semanticsMeaning
unsupportedRestoreObject is unavailable for this class.
temporaryReadableCopyRestoration produces a temporary readable copy while the object remains in its archive class.
rehydrateToDirectTierRestoration returns the object to a directly readable tier, with no temporary-copy duration.

days requires mode (forbidden, optional, or required) and may include minimum and maximum, each an integer from 1 to 2147483647. Omit undeclared bounds; null is forbidden. If both are present, minimum <= maximum. forbidden disallows both bounds.

retrievalTier contains exactly a required mode (forbidden, optional, or required) and acceptedTiers, a duplicate-free array drawn from expedited, standard, and bulk. With forbidden, the array must be empty. With either other mode, it must be nonempty.

versionSupported states whether RestoreObject can target an explicit versionId. It does not, on its own, declare account versioning support.

The following consistency rules are mandatory:

  • unsupported requires days.mode: "forbidden", retrievalTier.mode: "forbidden", acceptedTiers: [], and versionSupported: false.
  • temporaryReadableCopy requires days.mode to be optional or required.
  • rehydrateToDirectTier requires days.mode: "forbidden".

This archive class with a temporary readable copy can be included in classes only if the service provides the described behavior:

{
  "name": "GLACIER",
  "placementPaths": [
    "putObject",
    "createMultipartUpload",
    "copyObject"
  ],
  "sameObjectStorageClassChange": true,
  "accessStrategy": "restoreRequired",
  "restorePolicy": {
    "semantics": "temporaryReadableCopy",
    "days": {
      "mode": "required",
      "minimum": 1
    },
    "retrievalTier": {
      "mode": "optional",
      "acceptedTiers": [
        "expedited",
        "standard",
        "bulk"
      ]
    },
    "versionSupported": true
  },
  "archiveStateHeaders": [
    "restore"
  ]
}

Class transitions

A transition describes a supported lifecycle engine operation, not a rule to install immediately. It contains exactly sourceClassName, targetClassName, scopes, and constraints, all required.

Both classes must exist in the same policy and must be different. scopes is a nonempty array drawn from currentVersion and noncurrentVersion. For the same source/target pair, two entries must not share a scope; disjoint scopes are allowed.

constraints accepts these fields:

FieldPresenceConstraint and meaning
objectSizeFilterMayOverrideDefaultRequiredA boolean stating whether a size filter can override the default minimum size.
compatibleVersioningStatesRequiredA nonempty array drawn from neverEnabled, suspended, and enabled.
minimumCurrentAgeDaysOptionalAn integer from 0 to 2147483647: the minimum current-version age. Requires the currentVersion scope.
minimumNoncurrentAgeDaysOptionalThe same range: the minimum noncurrent-version age. Requires noncurrentVersion.
minimumSourceResidenceDaysOptionalThe same range: the minimum residence time in the source class.
defaultMinimumObjectSizeOptionalAn integer from 0 to 9223372036854775807, in bytes. Use $integer beyond the exact JSON number range.

An omitted field declares no constraint at that location. A value of 0 explicitly declares a zero bound. objectSizeFilterMayOverrideDefault: true requires defaultMinimumObjectSize to be present. Versioning states and minimum bounds are used to validate transitions requested by lifecycle rules.

This example describes a current-version transition, assuming both classes are present:

{
  "sourceClassName": "STANDARD",
  "targetClassName": "GLACIER",
  "scopes": [
    "currentVersion"
  ],
  "constraints": {
    "minimumCurrentAgeDays": 30,
    "defaultMinimumObjectSize": 131072,
    "objectSizeFilterMayOverrideDefault": true,
    "compatibleVersioningStates": [
      "neverEnabled",
      "suspended",
      "enabled"
    ]
  }
}

The values illustrate the syntax; they are not universal minimums to copy into every service profile.

Lifecycle options

Each policy in lifecycleCapabilityPolicySet.policies contains the fields below. Arrays must not contain duplicates and may be empty.

FieldPresenceTokens or value
idRequiredThe policy identifier.
filtersRequiredempty, prefix, tag, objectSizeGreaterThan, objectSizeLessThan, and.
allowedRuleStatusesOptionalenabled, disabled; omitted means no writable status.
allowedVersioningStatesOptionalneverEnabled, suspended, enabled; omitted means no compatible state. An unknown bucket state blocks writing when the policy does not allow all three states.
pairedExpirationRulesOptionalBoolean, default false. When true, each day-based expiration requires a separate expired-delete-marker rule with the same filter and status, and conversely. Requires both expiration forms. Rule IDs do not determine pairing.
combinedObjectSizeBoundsOptionalBoolean, default false: enables both bounds in the same And filter. Requires objectSizeGreaterThan, objectSizeLessThan and and in filters.
maximumTagsOptionalAn integer from 1 to 10: the declared tag limit for a filter. Requires tag.
currentExpirationsRequireddays, date, expiredObjectDeleteMarker.
noncurrentVersionsRequiredexpiration, newerNoncurrentVersionsForExpiration, newerNoncurrentVersionsForTransition.
abortIncompleteMultipartUploadRequiredA boolean declaring automatic cancellation of incomplete uploads.
transitionTriggersRequiredcurrentDays, currentDate, noncurrentDays.
combinationsRequiredmultipleActionTypes, multipleCurrentTransitions, multipleNoncurrentTransitions.
maximumActionsPerRuleOptionalAn integer from 1 to 2147483647: the maximum total number of actions in a rule.
transitionDefaultMinimumObjectSizeModesRequiredall_storage_classes_128K, varies_by_storage_class.

Filters cover no criteria (empty), a key prefix, a tag, object sizes strictly greater or less than a byte threshold, and logical And combinations. and does not enable criteria absent from filters. Omitting maximumTags adds no policy-specific limit; S3Client still enforces the S3 limit of 10 tags per filter.

Current-version expiration can use age (Days), a date (Date), or removal of an expired delete marker (ExpiredObjectDeleteMarker). expiration applies to NoncurrentVersionExpiration. newerNoncurrentVersionsForExpiration and newerNoncurrentVersionsForTransition permit the NewerNoncurrentVersions parameter, which retains a number of noncurrent versions before expiration or transition.

currentDays and currentDate allow age-based and date-based current-version transitions. noncurrentDays allows transitions based on noncurrent age. A trigger does not make every target class available: the storage class policy resolved for the same bucket must also allow the transition.

multipleActionTypes allows multiple action types in one rule. multipleCurrentTransitions and multipleNoncurrentTransitions allow multiple transitions within their respective scopes. These options remain subject to S3 rule constraints, declared transitions, and maximumActionsPerRule. Omitting that limit adds no provider-specific action cap.

The minimum-size modes correspond to the lifecycle configuration header x-amz-transition-default-minimum-object-size. all_storage_classes_128K specifies a default 128 KiB minimum for all classes; varies_by_storage_class specifies class-dependent behavior. Neither replaces explicit filters or the profile’s transition constraints.

The validator also enforces these dependencies:

  • newerNoncurrentVersionsForExpiration requires expiration.
  • newerNoncurrentVersionsForTransition requires noncurrentDays.
  • multipleCurrentTransitions requires currentDays or currentDate.
  • multipleNoncurrentTransitions requires noncurrentDays.

An editable lifecycle configuration needs GET/PUT APIs in capabilities and supported rule forms in this policy. Rules that transition objects between storage classes also need the corresponding classes and transitions in storageClassPolicySet. Expiration and incomplete multipart upload cancellation rules do not require any declared transitions; transitions: [] is valid for those workflows. Do not declare automatic cancellation of incomplete multipart uploads simply because manual AbortMultipartUpload is supported; these are separate mechanisms.

Bucket and object tags

Bucket tags

bucketTaggingCapabilityPolicy is one of these strings:

ValueBehavior
unavailableNo bucket tagging workflow is available.
bucket-tagging-subresourceGetBucketTagging, PutBucketTagging, and DeleteBucketTagging on the S3 ?tagging subresource of general purpose buckets. PUT replaces the complete tag set.
s3-control-resource-taggingListTagsForResource, TagResource, and UntagResource through S3 Control for general purpose or directory buckets. Adding/updating tags and removing tags are separate actions.

The API choice is explicit. S3Client does not try one API and fall back to the other. With S3 Control, each applicable region must declare a route for the bucket type. The user’s account must provide a serviceAccountId of 12 ASCII digits, used for the owner, routes, and ARNs. Do not add that field to the public preset.

S3Client rejects this S3 Control workflow for an external bucket without a verified owner. An available ARN must match the expected partition, bucket, type, region, and owner. Reconstructing a missing ARN requires standard-s3-resource-arn. This workflow does not cover Outposts buckets.

Object tags

objectTaggingCapabilityPolicy is an object. All fields are optional; null, unknown keys and unknown tokens are forbidden.

FieldValues and contract
readScopeunavailable (default), current-object, object-and-versions: targets supported by GetObjectTagging.
editingScopeThe same values, default unavailable: targets for replacing the complete tag set with PutObjectTagging or clearing it with clearMethod. Must not exceed readScope.
clearMethoddeleteTagging (default) uses DeleteObjectTagging; putEmptyTagSet uses PutObjectTagging with an empty tag set. Both perform the same logical clear.
contentOperationsUnique array containing putObject, createMultipartUpload, copyObject; default []. Declares x-amz-tagging on each named API; copying also requires the directive behavior described by copyMode.
copyModeunavailable (default), independentDirectives, coupledToMetadata. An available mode requires copyObject in contentOperations, and conversely.
currentObjectVerificationresponse-version-header (default) or versioned-read-then-head. The latter requires readScope: object-and-versions.

current-object enables current objects; object-and-versions additionally enables explicit versionId targets. These APIs apply to general purpose buckets and exclude delete markers. Reading does not enable editing. Transfers use the source account’s permissions to read tags and the destination account’s content operations to write them.

independentDirectives denotes Amazon S3’s independent metadata and tagging directives. coupledToMetadata denotes a server requiring identical directives: to preserve tags while replacing metadata, S3Client prepares tags and sends REPLACE/REPLACE, including an empty tag set. COPY/COPY remains direct without an additional tagging GET. A required read that is unavailable, denied or uninterpretable blocks the copy before writing. No automatic corrective PUT is added after the copy. An ETag protects content, not concurrent tag changes.

currentObjectVerification selects how S3Client binds a tag read to an observed object:

  • response-version-header: after observing a version with HEAD, S3Client reads current-object tags and requires a matching x-amz-version-id in the tagging response. A missing or different version header blocks that observation. No second HEAD is added for this strategy.
  • versioned-read-then-head: when HEAD has identified a current version, S3Client reads tags with that explicit versionId, then issues a second HEAD of the current object. The version ID, ETag, size, and last-modified time must still match. The version-specific tagging response may omit its version header; a contradictory header is rejected. This strategy requires readScope: object-and-versions and permission for both version-specific tag reads and HEAD, notably s3:GetObjectVersionTagging and s3:GetObject on Amazon S3.

When preparing tags for a copy, S3Client reuses the source HEAD already prepared for that copy. It reads the observed version’s tags when version-specific reads are available; an immutable exact source needs no second HEAD after the tag read. Explicit immutable versions do not need a current-object check. The mutable null version also requires content identity verification. If HEAD supplies no version ID, no version can be pinned by either strategy.

Preparing a current-object tag edit does not change its write target: PutObjectTagging and the selected clear API still omit versionId. Neither strategy makes a read followed by a write atomic, and an ETag cannot detect concurrent tag-only changes.

Example for a service that provides version-specific tag reads, requires coupled copy directives, and clears tags through an empty PUT:

{
  "readScope": "object-and-versions",
  "editingScope": "object-and-versions",
  "currentObjectVerification": "versioned-read-then-head",
  "clearMethod": "putEmptyTagSet",
  "contentOperations": [
    "putObject",
    "createMultipartUpload",
    "copyObject"
  ],
  "copyMode": "coupledToMetadata"
}

Static website hosting

Each policy in websiteCapabilityPolicySet.policies contains exactly these six required fields:

FieldType and contract
idThe policy identifier.
getBucketWebsiteA boolean declaring reads through GetBucketWebsite.
putBucketWebsiteA boolean declaring creation/replacement through PutBucketWebsite.
deleteBucketWebsiteA boolean declaring deletion through DeleteBucketWebsite.
redirectAllRequestsToA boolean declaring RedirectAllRequestsTo: a global redirect to a host and optionally a protocol.
routingRulesA boolean declaring conditional RoutingRules with S3 conditions and redirects.

Basic index/error document configuration is covered by PUT availability, with no additional boolean. These workflows apply to general purpose buckets. Redirect options do not replace GET/PUT support. The editor must read a configuration before editing it; an uninterpretable configuration is not silently replaced.

The three APIs are independent in the format. Setting every boolean to false declares unavailability. This block describes the bucket configuration subresource. It contains no website endpoint, DNS settings, certificate, public access policy, or CDN option, and does not automatically make objects public.

Encryption details

Allowed operations and modes

Each policy in encryptionCapabilityPolicySet.policies requires id. All other fields are optional: omitted operation/mode arrays default to [], and omitted booleans default to false. Arrays contain unique tokens in any order. Numeric masks, unknown tokens, inapplicable operations, and null are rejected.

FieldAllowed tokensMeaning
sseS3OperationsputObject, createMultipartUpload, copyObjectSSE-S3 selection.
sseKmsOperationsThe same three operationsSSE-KMS selection.
dsseKmsOperationsThe same three operationsDSSE-KMS selection.
customerKeyOperationsputObject, createMultipartUpload, copyObject, uploadPart, uploadPartCopy, completeMultipartUpload, getObject, headObjectDestination SSE-C headers, or headers for the object being read.
customerCopySourceOperationscopyObject, uploadPartCopySSE-C headers for decrypting the copy source.
kmsContextOperationsputObject, createMultipartUpload, copyObjectAdditional KMS context.
bucketKeyOperationsThe same three operationsExplicit Bucket Key option.
bucketEncryptionModessse-s3, sse-kms, dsse-kmsModes available for bucket default encryption.
blockedEncryptionTypesBooleanRemote configuration of SSE-C blocking.
bucketKeyConfigurationBooleanBucket Key option in bucket default encryption.
updateBucketKeysBooleanBucket Key option in UpdateObjectEncryption.

A structurally valid preset can declare sse-kms with no allowed SSE-KMS write operations. This does not enable encryption selection on those paths. The offline validator reports provably inactive declarations without changing them.

Runtime conditions

Explicit object encryption selection requires both the corresponding global capability token and the API operation in the resolved policy. SSE-S3/KMS/DSSE-KMS selection headers are not sent on GET/HEAD. An explicitly requested KMS context or Bucket Key option also requires its operation. false counts as an explicit Bucket Key value.

The service default mode adds no selection header and leaves the remote bucket or service configuration in effect. It does not mean that the object will be unencrypted.

For SSE-C, the algorithm, Base64-encoded key, and key MD5 headers follow the S3 API. Source and destination roles are independent. Allowing CopyObject in customerKeyOperations is not enough to copy an SSE-C source; the corresponding operation in customerCopySourceOperations must also be enabled in the source policy.

A multipart SSE-C upload requires CreateMultipartUpload and UploadPart in customerKeyOperations. A multipart copy to SSE-C requires CreateMultipartUpload and UploadPartCopy in that array. If the source is also SSE-C, its policy must allow UploadPartCopy in customerCopySourceOperations. The completeMultipartUpload operation describes SSE-C headers available at completion, but its absence alone does not prevent S3Client’s current multipart workflow.

SSE-C requires HTTPS and cannot be used on directory buckets. DSSE-KMS cannot be used on directory buckets. Use HTTPS and SigV4 for KMS configurations; S3Client specifically enforces these conditions when changing object encryption and performing in-place updates.

Bucket encryption fields are separate from object write operations. PutBucketEncryption requires its global capability and the modes/options declared in the policy. SSE-C and additional KMS context cannot be configured as bucket default encryption. Changing the bucket default does not retroactively encrypt existing objects.

UpdateObjectEncryption does not reuse sseKmsOperations as an operation declaration. It has its own global token and the updateBucketKeys option. S3Client requires a full KMS key ARN, not an alias or bare key ID. Additional KMS context requires a copy workflow. An in-place update is selected only for an SSE-S3 or SSE-KMS source without Object Lock protection, when combined changes and preconditions do not require copying. An SSE-C or DSSE-KMS source therefore requires copying in S3Client. If the action permits only an in-place update and these conditions are not met, it is unavailable. Eligible explicit versions can be updated in place without copying the object or creating a new version.

Never distribute SSE-C keys, secret keys, or credentials in this block. A user’s KMS key reference or favorite also falls outside the public profile.

SSE-S3 and SSE-C policy example

This is a complete encryptionCapabilityPolicySet value, suitable only for a service that meets this contract. Add sse-s3 and sse-c to capabilities, plus multipart-upload for multipart workflows.

{
  "defaultPolicyId": "encryption-general",
  "policies": [
    {
      "id": "encryption-general",
      "sseS3Operations": [
        "putObject",
        "createMultipartUpload",
        "copyObject"
      ],
      "sseKmsOperations": [],
      "dsseKmsOperations": [],
      "customerKeyOperations": [
        "putObject",
        "createMultipartUpload",
        "copyObject",
        "uploadPart",
        "uploadPartCopy",
        "completeMultipartUpload",
        "getObject",
        "headObject"
      ],
      "customerCopySourceOperations": [
        "copyObject",
        "uploadPartCopy"
      ],
      "kmsContextOperations": [],
      "bucketKeyOperations": [],
      "bucketEncryptionModes": [
        "sse-s3"
      ],
      "blockedEncryptionTypes": false,
      "bucketKeyConfiguration": false,
      "updateBucketKeys": false
    }
  ],
  "bindings": []
}

Bucket mode sse-s3 becomes editable only with the bucket encryption GET/PUT capabilities. This example declares no KMS support.

General request limits

requestLimits is independent of aclPolicy and remains effective when ACLs are disabled. It accepts only maximumPutHeaderBytes and maximumPostHeaderBytes, each an optional integer from 0 to 2147483647. Omission and zero mean no configured limit; null is forbidden.

A positive limit applies to the complete assembled request header section for the corresponding method, not only ACL headers. The same limit informs local ACL encoding selection. A request exceeding the limit is rejected before it is sent. These fields are forbidden inside aclPolicy.compatibility.

ACL policy

Activation, APIs, and scope

ACLs describe S3 grants on buckets and objects. They are separate from IAM policies, bucket policies, and public access settings. Omitting aclPolicy disables this workflow. If present, the object must contain exactly these six required fields:

FieldType
activation"enabled" or "disabled".
apiSupportAn object mapping the API names below to boolean support; omitted entries are false.
objectAclScopeAn exact object with string fields get and put.
readSemanticsAn exact object with string fields bucket and object.
operationPoliciesAn object mapping write operation names to policies; omitted entries are fully disabled.
compatibilityThe complete object of limits, groups, and error rules.

activation: "disabled" prevents use of the policy but does not exempt its other fields from validation. enabled requires at least one API to be declared supported in apiSupport.

apiSupport accepts only getBucketAcl, putBucketAcl, getObjectAcl, and putObjectAcl, each with a boolean value. Key order has no meaning. Missing keys are false; an empty object declares no API support.

objectAclScope.get accepts:

TokenRead scope
noneNo object ACL reads.
currentObjectThe current object only.
objectAndVersionsThe current object and explicit versions.

objectAclScope.put accepts none, currentObject, or objectAndVersions. Writes cannot be projections. getObjectAcl: true requires a GET scope other than none; putObjectAcl: true requires a PUT scope other than none.

The scope of the dedicated PutObjectAcl API is separate from sending an ACL with PutObject, CopyObject, or CreateMultipartUpload. Those paths are described by their operation policies.

Read semantics

readSemantics.bucket and readSemantics.object describe how faithfully API results represent the stored ACL:

TokenMeaning and consequence
storedExactThe complete stored ACL. Supports reasoning about exact preservation of its grants.
effectivePotentiallyFilteredAn effective result that may omit stored grants. Propagation cannot guarantee preservation of the complete ACL; S3Client requires acceptance of propagation limited to the observable grants where applicable.
bucketProjectionAn object ACL derived from the bucket. It is not a stored object ACL to copy exactly. Forbidden for bucket.
syntheticA generated result that does not represent a stored ACL. It must not be treated as evidence of exact permission preservation.

Read scope and read semantics are independent. For a bucket projection, use readSemantics.object: "bucketProjection" with objectAclScope.get: "currentObject" or "objectAndVersions", according to the supported targets. bucketProjection is not a GET scope in version 1.0. Projected ACLs remain read-only and cannot establish exact object ACL preservation or verify an independent object ACL write. Delete markers and virtual prefixes are not object ACL targets.

Do not declare storedExact if the service ignores written ACLs, returns a fixed synthetic response, or filters grants according to the caller. A successful HTTP response does not establish this fidelity.

The five write operation policies

operationPolicies accepts only these keys: putBucketAcl, putObject, copyObject, createMultipartUpload, and putObjectAcl. Their order has no meaning. A missing operation has no write forms, no allowed grants or canned ACLs, and no preferred explicit encoding.

Each present operation contains exactly these five required fields:

FieldContents
formSupportAn object accepting only boolean cannedHeader, grantHeaders, and xmlBody. An omitted form is false.
allowedCannedAclsA duplicate-free array of allowed canned ACLs.
allowedPermissionsA duplicate-free array of allowed elementary permissions.
allowedGroupGranteesA duplicate-free array of allowed group URI identifiers.
preferredExplicitGrantEncodingnull, grantHeaders, xmlBody, or adaptive, subject to the rules below.

cannedHeader sends x-amz-acl; grantHeaders sends x-amz-grant-*; xmlBody sends an AccessControlPolicy body on a dedicated ACL PUT. Unknown operation/form keys and the former array representations are rejected.

xmlBody: true is forbidden for PutObject, CopyObject, and CreateMultipartUpload, whose bodies serve other purposes. If apiSupport declares putBucketAcl or putObjectAcl supported, its dedicated policy must offer at least one write form.

allowedCannedAcls accepts these tokens:

TokenS3 meaning
privateACL access restricted to the owner.
public-readPublic read access.
public-read-writePublic read and write access as applicable to the resource.
authenticated-readRead access for the authenticated users group.
aws-exec-readRead access associated with the AWS EC2 service.
bucket-owner-readObject read access granted to the bucket owner.
bucket-owner-full-controlFull object control granted to the bucket owner.

For PutBucketAcl, only private, public-read, public-read-write, and authenticated-read are allowed. The other three are object ACLs. cannedHeader: true requires at least one token in allowedCannedAcls.

allowedPermissions accepts only READ, WRITE, READ_ACP, and WRITE_ACP. WRITE is allowed only for buckets, so only in PutBucketAcl. Object operations allow READ, READ_ACP, and WRITE_ACP. FULL_CONTROL is not a token in this array: it is represented by the full set of elementary permissions for the resource and may be encoded as full control in S3 requests.

grantHeaders: true or xmlBody: true requires a nonempty permission array. allowedGroupGrantees defines the groups allowed for the operation, not the individual user grantees of each ACL. Common S3 group URIs are:

http://acs.amazonaws.com/groups/global/AllUsers
http://acs.amazonaws.com/groups/global/AuthenticatedUsers
http://acs.amazonaws.com/groups/s3/LogDelivery

The last URI is forbidden in object operation policies. Each declared URI must be nonempty, have no leading or trailing whitespace, and be at most 4,096 Unicode scalar values. The array allows up to 1,000 entries. Describe the groups the service actually accepts; do not assume it supports every common S3 group.

preferredExplicitGrantEncoding follows these rules:

  • For PutObject, CopyObject, and CreateMultipartUpload, the value must be null.
  • For PutBucketAcl and PutObjectAcl, if neither grantHeaders nor xmlBody is supported, the value must be null.
  • For those two ACL PUTs with explicit grant support, the value is required and non-null. grantHeaders requires that form to be supported, xmlBody requires that form to be supported, and adaptive requires both forms to be supported.

adaptive selects between forms already declared supported, taking into account what the client can encode and the header limits. It is not automatic detection of an API that might be supported.

ACL compatibility and limits

compatibility contains exactly these six required fields:

FieldConstraint and meaning
ownerXmlPolicy"omit" or "echoKnownTargetOwner".
maximumGrantsAn integer from 1 to 1,000: the maximum number of encoded grant elements.
predefinedGroupsAn array of 0 to 1,000 exact {"id":"URI","displayName":"Label"} objects.
ownershipControlsNotFoundErrorCodesAn array of 0 to 1,000 S3 error codes indicating absent ownership configuration.
ownershipControlsUnsupportedErrorCodesAn array of 0 to 1,000 S3 error codes indicating an unavailable ownership API.
aclErrorRulesAn array of 0 to 7,000 explicit ACL error interpretation rules.

ownerXmlPolicy: "omit" omits the Owner element from write XML. echoKnownTargetOwner includes the target’s known current owner; S3Client must know that owner before encoding the PUT. It does not name the signing account as a new owner.

predefinedGroups supplies labels for the offered groups. id must be unique, nonempty, and canonical. displayName must be canonical but may be empty. These groups are not automatically allowed in every operation; allowedGroupGrantees is checked separately.

Error code arrays contain unique, nonempty, canonical strings of up to 4,096 Unicode scalar values. Distinguish missing configuration from an unimplemented API. A permission denial is not evidence that the service lacks support.

ACL error rules

Every aclErrorRules entry contains exactly these six required fields:

FieldValues
operationgetBucketAcl, putBucketAcl, getObjectAcl, putObjectAcl, putObject, copyObject, createMultipartUpload.
writeFormnull, cannedHeader, grantHeaders, or xmlBody.
errorCodeAn exact, nonempty, canonical S3 code of up to 4,096 Unicode scalar values.
minimumHttpStatusAn integer from 100 to 599.
maximumHttpStatusAn integer from 100 to 599, greater than or equal to the minimum.
actionrequireOwnershipObservation, markOperationUnsupported, or markFormUnsupported.

A rule matches the operation, error code, and an HTTP status within the inclusive range. A non-null form restricts the match to that form. Actions have these effects and constraints:

ActionEffect and validation
requireOwnershipObservationRequires ownership to be observed to explain an ACL rejection. Write operations only; writeForm must be null.
markOperationUnsupportedMarks the operation unavailable in the relevant runtime context. writeForm must be null. AccessDenied is forbidden for this action.
markFormUnsupportedMarks a form unavailable in that context. Requires a non-null form applicable to the operation; XML is allowed only for dedicated ACL PUTs. AccessDenied is forbidden.

Rules must not overlap for the same operation, code, and applicable status. A writeForm: null rule also covers specific forms. Ranges sharing an endpoint overlap. Conflicting or duplicate rules are rejected even if they specify the same action.

These rules declare how to interpret specific ACL responses. They must not be used to introduce an unknown state across all capabilities or to conceal authentication errors. Without a rule, an error remains an operation error. Use aclErrorRules: [] when no special handling is needed.

Active ACL policy example

This policy permits ACL reads and replacement through canned headers or XML. Object creation and copying allow only x-amz-acl. It illustrates a specific contract that must be qualified against the service, not a generic preset to copy unchanged.

{
  "activation": "enabled",
  "apiSupport": {
    "getBucketAcl": true,
    "putBucketAcl": true,
    "getObjectAcl": true,
    "putObjectAcl": true
  },
  "objectAclScope": {
    "get": "objectAndVersions",
    "put": "objectAndVersions"
  },
  "readSemantics": {
    "bucket": "storedExact",
    "object": "storedExact"
  },
  "operationPolicies": {
    "putBucketAcl": {
      "formSupport": {
        "cannedHeader": true,
        "grantHeaders": false,
        "xmlBody": true
      },
      "allowedCannedAcls": [
        "private",
        "public-read"
      ],
      "allowedPermissions": [
        "READ",
        "WRITE",
        "READ_ACP",
        "WRITE_ACP"
      ],
      "allowedGroupGrantees": [
        "http://acs.amazonaws.com/groups/global/AllUsers"
      ],
      "preferredExplicitGrantEncoding": "xmlBody"
    },
    "putObject": {
      "formSupport": {
        "cannedHeader": true,
        "grantHeaders": false,
        "xmlBody": false
      },
      "allowedCannedAcls": [
        "private",
        "public-read",
        "bucket-owner-full-control"
      ],
      "allowedPermissions": [],
      "allowedGroupGrantees": [],
      "preferredExplicitGrantEncoding": null
    },
    "copyObject": {
      "formSupport": {
        "cannedHeader": true,
        "grantHeaders": false,
        "xmlBody": false
      },
      "allowedCannedAcls": [
        "private",
        "public-read",
        "bucket-owner-full-control"
      ],
      "allowedPermissions": [],
      "allowedGroupGrantees": [],
      "preferredExplicitGrantEncoding": null
    },
    "createMultipartUpload": {
      "formSupport": {
        "cannedHeader": true,
        "grantHeaders": false,
        "xmlBody": false
      },
      "allowedCannedAcls": [
        "private",
        "public-read",
        "bucket-owner-full-control"
      ],
      "allowedPermissions": [],
      "allowedGroupGrantees": [],
      "preferredExplicitGrantEncoding": null
    },
    "putObjectAcl": {
      "formSupport": {
        "cannedHeader": true,
        "grantHeaders": false,
        "xmlBody": true
      },
      "allowedCannedAcls": [
        "private",
        "public-read",
        "bucket-owner-full-control"
      ],
      "allowedPermissions": [
        "READ",
        "READ_ACP",
        "WRITE_ACP"
      ],
      "allowedGroupGrantees": [
        "http://acs.amazonaws.com/groups/global/AllUsers"
      ],
      "preferredExplicitGrantEncoding": "xmlBody"
    }
  },
  "compatibility": {
    "ownerXmlPolicy": "omit",
    "maximumGrants": 100,
    "predefinedGroups": [
      {
        "id": "http://acs.amazonaws.com/groups/global/AllUsers",
        "displayName": "All Users"
      }
    ],
    "ownershipControlsNotFoundErrorCodes": [],
    "ownershipControlsUnsupportedErrorCodes": [],
    "aclErrorRules": []
  }
}

To disable ACLs entirely, omitting aclPolicy is simpler than generating a full object with every API and form set to false. If the object is included, the required objects must remain present and all scope, encoding, and permission constraints must still hold.

Complete provider file example

This is a conservative starting point for a fictional service with ListObjectsV2, multipart uploads, and one directly readable class. Optional policies are explicit. ACLs are omitted and therefore disabled. Replace the identity, host, region, and support declarations with those of the target service. The .example host is not a service to contact.

{
  "kind": "s3client-provider-preset",
  "schemaVersion": {
    "major": 1,
    "minor": 0
  },
  "software": {
    "name": "S3Client",
    "website": "https://s3client.com"
  },
  "preset": {
    "id": "example.object-storage.general",
    "name": "Example Object Storage",
    "serviceProfile": {
      "capabilities": [
        "list-objects-v2",
        "multipart-upload"
      ],
      "serverSideCopyDomain": "",
      "protocol": "https",
      "port": 443,
      "regions": [
        {
          "name": "Default Region",
          "location": "us-east-1",
          "endpoint": "s3.storage.example",
          "authentication": "sigv4",
          "accessStyle": "path",
          "serverSideCopyDomain": "",
          "accountRegionalBucketNamespaceAvailable": false,
          "s3ControlRouting": {}
        }
      ],
      "storageClassPolicySet": {
        "defaultPolicyId": "standard-only",
        "policies": [
          {
            "id": "standard-only",
            "defaultClassName": "STANDARD",
            "classes": [
              {
                "name": "STANDARD",
                "placementPaths": [
                  "putObject",
                  "createMultipartUpload",
                  "copyObject"
                ],
                "sameObjectStorageClassChange": true,
                "accessStrategy": "alwaysDirect",
                "restorePolicy": {
                  "semantics": "unsupported",
                  "days": {
                    "mode": "forbidden"
                  },
                  "retrievalTier": {
                    "mode": "forbidden",
                    "acceptedTiers": []
                  },
                  "versionSupported": false
                },
                "archiveStateHeaders": []
              }
            ],
            "transitions": [],
            "restoreStatusListingOperations": [],
            "intelligentTieringOperations": []
          }
        ],
        "bindings": []
      },
      "lifecycleCapabilityPolicySet": {
        "defaultPolicyId": "unavailable",
        "policies": [
          {
            "id": "unavailable",
            "filters": [],
            "combinedObjectSizeBounds": false,
            "allowedRuleStatuses": [],
            "allowedVersioningStates": [],
            "pairedExpirationRules": false,
            "currentExpirations": [],
            "noncurrentVersions": [],
            "abortIncompleteMultipartUpload": false,
            "transitionTriggers": [],
            "combinations": [],
            "transitionDefaultMinimumObjectSizeModes": []
          }
        ],
        "bindings": []
      },
      "bucketTaggingCapabilityPolicy": "unavailable",
      "objectTaggingCapabilityPolicy": {
        "currentObjectVerification": "response-version-header",
        "readScope": "unavailable",
        "editingScope": "unavailable",
        "clearMethod": "deleteTagging",
        "contentOperations": [],
        "copyMode": "unavailable"
      },
      "bucketLoggingCompatibilityPolicy": "strictS3",
      "websiteCapabilityPolicySet": {
        "defaultPolicyId": "unavailable",
        "policies": [
          {
            "id": "unavailable",
            "getBucketWebsite": false,
            "putBucketWebsite": false,
            "deleteBucketWebsite": false,
            "redirectAllRequestsTo": false,
            "routingRules": false
          }
        ],
        "bindings": []
      },
      "encryptionCapabilityPolicySet": {
        "defaultPolicyId": "unavailable",
        "policies": [
          {
            "id": "unavailable",
            "sseS3Operations": [],
            "sseKmsOperations": [],
            "dsseKmsOperations": [],
            "customerKeyOperations": [],
            "customerCopySourceOperations": [],
            "kmsContextOperations": [],
            "bucketKeyOperations": [],
            "bucketEncryptionModes": [],
            "blockedEncryptionTypes": false,
            "bucketKeyConfiguration": false,
            "updateBucketKeys": false
          }
        ],
        "bindings": []
      },
      "defaultRegionLocation": "us-east-1"
    }
  }
}

For a file containing only required fields, see the minimal provider file. Fields marked Optional in the service profile table may be omitted, as may software and optional nested fields such as sameObjectStorageClassChange; their documented defaults then apply. Keep storageClassPolicySet, the required class fields, all eight region fields, and every other required field. Omit an optional declaration only when its default accurately describes the intended service profile.

To describe region-specific options, retain one regions array, add the necessary policies to each relevant set, and associate them using bindings. Fields outside the four policy sets do not support policy bindings. If a difference cannot be represented faithfully, distribute separate presets rather than incorrectly declaring a feature globally usable.

Generating and validating files without S3Client

Generation procedure

  1. Define the declaration’s scope: service, offering, version, and deployment conditions. Use separate presets when those conditions change global capabilities or connection settings.
  2. Generate the required envelope and profile keys in version 1.0 format. Choose a stable, non-reserved identifier.
  3. Describe each region, its signing and addressing settings, and its copy domains. Write region locations and endpoints in their canonical form before import. Declare only the S3 Control routes that are used.
  4. Enable capabilities supported by the server and usable by S3Client under the qualification criteria above, then satisfy their mandatory dependencies.
  5. Describe storage classes, actual accessibility, and restoration behavior. Declare lifecycle, tagging, website, encryption, and ACL options separately.
  6. Check consistency across declarations. For example, SSE-C selection needs its token and operations; a transition needs its classes, scope, and trigger; an ACL PUT API needs a write form.
  7. Serialize as UTF-8, using a parser that rejects duplicate keys, and retain a readable version for review. Include no secrets.

Providers can complete every step with their own tools. Installing the file in S3Client later is separate from generating it.

JSON Schema and semantic validation

The companion provider preset JSON Schema uses JSON Schema Draft 2020-12. It references the shared service profile schema. Distribute both files together and resolve their identifiers locally for offline validation. Every profile block has closed keys, required fields, token definitions and structural bounds.

Semantic validation additionally checks canonical hosts and locations, references between policies and classes, uniqueness by identifier or normalized matching criteria, default-region references, numeric bound ordering, ACL scope/form/permission consistency, overlapping error rules, and policy-specific combinations. The native reader checks UTF-8, duplicate keys, maximum document size, nesting depth and node count before decoding. Passing JSON Schema alone does not certify these semantic requirements or the actual remote API behavior.

Run s3client-preset-validator FILE... to check importability without opening the application or contacting S3. It reads files without rewriting them. Exit 0 means valid; exit 1 means invalid; exit 2 means an argument or file-access error. Add --strict to treat warnings as failures. Warnings identify unused policies and declarations proven inactive by global capabilities, transport, or the absence of a lifecycle trigger for their scopes; they never modify a preset. With multiple files, file-access errors take precedence over validation failures. Contextual declarations that may become usable under another binding are not reported as universally inactive.

Check these items before distribution:

LevelChecks
JSON syntaxUTF-8, a single root object, no comments or duplicate keys, bounded size and depth.
Envelopekind, current version 1.0, fixed metadata if present, valid identity.
StructureExact required and optional fields for every object; no account fields or secrets.
Tokens and typesNo invented tokens, incorrect case, numeric booleans, inapplicable operation tokens, or unauthorized null.
ConnectionCanonical region locations and host-only endpoints, path style for IP addresses, unique regions, an existing default-region reference, consistent S3 Control routes.
Policies1 to 32 policies per set, unique identifiers, existing references, no duplicate binding criteria.
Runtime behaviorCapabilities and options compatible with the actual APIs, multipart paths, bucket type, and transport requirements.
InstallationNo reserved identifiers or names; no name conflict with another installed custom preset.

Functional qualification must examine actual API effects, not HTTP status codes alone. Examples include atomic rejection of a conditional PUT with a mismatching precondition, ACL preservation on readback, version-aware tagging, accurate archive status, and copying across declared domains. A separate qualification report can accompany the JSON to describe the service version, deployment, checked operations, and known restrictions. Do not add these observations as arbitrary JSON keys.

Common mistakes

Incorrect declarationCorrection
endpoint: "https://s3.example.com:443"Use endpoint: "s3.example.com", protocol: "https", and port: 443.
A region with location: "EU" or endpoint: "S3.Example.COM."Write location: "eu-west-1" and endpoint: "s3.example.com"; import rejects noncanonical region values.
A region without s3ControlRoutingEmit {} if no route is available.
upload-part-copy without multipart-uploadAdd the prerequisite if supported; otherwise remove the dependent capability.
sse-c alone, without an encryption policyDeclare the actual allowed operations and HTTPS; otherwise SSE-C selection remains unusable.
policies: [], or a defaultPolicyId not found in policiesInclude at least one policy and reference an existing identifier.
Optional bounds written as nullOmit the field; the two nullable ACL fields are exceptions.
FULL_CONTROL in allowedPermissionsExpress it as the resource’s elementary bucket or object permissions.
Numeric encryption masks or ordered ACL arraysUse named operation arrays for encryption and keyed objects for ACL policies.
Reusing one copy domain across isolated installationsUse a deployment-specific domain, distinct regional domains, or an empty value according to the actual contract.

Public API reference

The Amazon S3 API Reference defines the scope of APIs and parameters. Qualification assesses their actual use by S3Client under the criteria above, without requiring behavior identical to Amazon’s. Declarations must accurately reflect the provider’s behavior. An S3Client limitation stated here must not be presented as a universal restriction on all S3 services.