Skip to content

Commit ec59176

Browse files
frristclaude
andcommitted
docs(s3-object-lock): pin the conformance-run corrections
Three details the implementation run against the versitygw suite pinned differently than first specified: key existence outranks the lock-enabled gate in the §6 check order (GetObjectRetention_non_existing_object runs against a lock-free bucket and expects NoSuchKey, matching posix); the missing-configuration error splits by path, with the spaced variant on the four per-version methods and the NoSpaces variant on all three creation-time header paths; and the controller passes an absent retain-until header as a pointer to the zero time. §11 also records the versioning-disabled-mode exclusion precisely and the versioned-teardown home for lock-enabled-bucket cases from plain-conf groups. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent c0341cb commit ec59176

1 file changed

Lines changed: 27 additions & 14 deletions

File tree

docs/s3-object-lock.md

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ bucket.
7272
| target version is a delete marker | `ErrMethodNotAllowed` (405) |
7373
| key or version absent | `ErrNoSuchKey` / `GetNoSuchVersionErr` |
7474
| malformed versionId | `InvalidArgument` (`InvalidArgVersionId`) |
75-
| lock op against a bucket without lock enabled | `ErrMissingObjectLockConfiguration` (400); the CreateMultipartUpload path uses the `...NoSpaces` variant |
75+
| lock op against a bucket without lock enabled | the four per-version methods answer `ErrMissingObjectLockConfiguration` (400); the creation-time header paths (PutObject, CopyObject, CreateMultipartUpload) answer the `...NoSpaces` variant — the wire messages differ by one space and the conformance suite distinguishes them |
7676
| `PutObjectLockConfiguration` on a non-Enabled-versioning bucket | `ErrObjectLockConfigurationNotAllowed` (409) |
7777
| `PutBucketVersioning(Suspended)` on a lock bucket | `ErrSuspendedVersioningNotAllowed` (400) |
7878

@@ -274,14 +274,17 @@ only exist on buckets that were Enabled when it was written and can never leave
274274
All four run the same check order:
275275

276276
1. `registry.Get` misses: `ErrNoSuchBucket`.
277-
2. `State.ObjectLockConfig` nil or not Enabled: `ErrMissingObjectLockConfiguration`
278-
(`...NoSpaces` is not used here; it belongs to CreateMultipartUpload, §7). This is the
279-
only lock-specific step; the rest of the order is the skeleton any per-version state
280-
operation runs.
281-
3. `classifyVersionID` rejects the token: `InvalidArgument` (`InvalidArgVersionId`).
282-
4. The current version (empty versionId) or the named one resolves per the §6.1 grammar of
283-
the versioning design; a miss is `ErrNoSuchKey` / `GetNoSuchVersionErr`.
284-
5. The resolved version is a delete marker: `ErrMethodNotAllowed` (pinned by
277+
2. The key is absent from the top MST: `ErrNoSuchKey`. Key existence outranks the lock
278+
gate — a missing key on a bucket without lock reports `NoSuchKey`, never the
279+
missing-configuration error (`GetObjectRetention_non_existing_object` pins it against a
280+
lock-free bucket, matching posix).
281+
3. `State.ObjectLockConfig` nil or not Enabled: `ErrMissingObjectLockConfiguration`. This
282+
and step 2's precedence are the only lock-specific parts of the order; the rest is the
283+
skeleton any per-version state operation runs.
284+
4. `classifyVersionID` rejects the token: `InvalidArgument` (`InvalidArgVersionId`).
285+
5. The named version resolves per the §6.1 grammar of the versioning design (the current
286+
version for an empty versionId); a miss is `GetNoSuchVersionErr`.
287+
6. The resolved version is a delete marker: `ErrMethodNotAllowed` (pinned by
285288
`Versioning_Put_GetObjectRetention_delete_marker` and the legal-hold twin).
286289

287290
**Reads** run it lock-free over `resolveVersion` (`s3frontend/version.go:144`), which already
@@ -318,9 +321,11 @@ validated by the controller (`utils.ParsObjectLockHdrs`: mode and date required
318321
RFC3339, future-dated, known enum values). The backend's obligations:
319322

320323
- **Validation.** Lock headers against a bucket whose `ObjectLockConfig` is not enabled:
321-
`ErrMissingObjectLockConfiguration` from PutObject and CopyObject,
322-
`ErrMissingObjectLockConfigurationNoSpaces` from CreateMultipartUpload (the wire messages
323-
differ by one space; the conformance suite distinguishes them).
324+
`ErrMissingObjectLockConfigurationNoSpaces` from all three creation-time paths (§2's
325+
variant split; `PutObject_missing_bucket_lock` and `CopyObject_missing_bucket_lock` pin
326+
the wording). The controller populates the retain-until pointer unconditionally, so an
327+
absent header arrives as a pointer to the zero time and absence is judged on the zero
328+
value, never on nil.
324329
- **Stamping, inside the commit.** When lock headers are present, `commitVersion` writes the
325330
new version's `VersionState` (retention =
326331
`json.Marshal(types.ObjectLockRetention{Mode, RetainUntilDate})` when a mode was supplied;
@@ -407,10 +412,18 @@ for `COMPLIANCE`), sleeps past expiry, and deletes.
407412
`TestWORMProtection`:
408413

409414
- The six Put/Get groups are pass-table rows, with two exceptions.
410-
`PutObjectLockConfiguration_not_enabled_on_bucket_creation` is dispatch-gated to the
411-
unversioned conf upstream and is omitted with the conf choice.
415+
`PutObjectLockConfiguration_not_enabled_on_bucket_creation` asserts the
416+
versioning-disabled gateway mode, where a lock configuration lands on an unversioned
417+
bucket with no versioning check (upstream's own comment calls it not S3 compatible);
418+
ingot answers the AWS 409 and the row is excluded, with
419+
`Versioning_object_lock_not_enabled_on_bucket_creation` pinning that behavior.
412420
`PutObjectRetention_overwrite_governance_with_permission` installs a bucket policy: XFail
413421
until bucket policies land.
422+
- Lock-enabled-bucket cases from the plain-conf groups (`PutObject_with_object_lock`,
423+
`PutObject_racey_success`, the CopyObject lock-header cases,
424+
`CreateMultipartUpload_with_object_lock`) run under a dedicated versioned-conf category:
425+
their buckets are versioning-Enabled, and the plain teardown cannot empty a non-empty
426+
versioned bucket.
414427
- `TestWORMProtection` contributes no pass rows yet. Its `checkWORMProtection`-based cases
415428
assert versitygw's unversioned-gateway lock model, where a plain PUT or unscoped DELETE
416429
against a locked object fails with `ErrObjectLocked`; a lock bucket in ingot is always

0 commit comments

Comments
 (0)