Repository navigation
Conversation
e035fcf to
7b99f81
Compare
|
@codex review |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Codex Review: Didn't find any major issues. What shall we delve into next? Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
7b99f81 to
729b425
Compare
729b425 to
eb735f4
Compare
eb735f4 to
7ff2638
Compare
13fe304 to
b73203a
Compare
4302b89 to
6beeafb
Compare
6beeafb to
ff05320
Compare
ff05320 to
63011b6
Compare
639c1f2 to
579d49c
Compare
579d49c to
266e6c7
Compare
|
@codex review |
6f23555 to
553c2d9
Compare
553c2d9 to
9498ebf
Compare
9498ebf to
64a19bf
Compare
64a19bf to
ba1dc86
Compare
ba1dc86 to
ed6b75d
Compare
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ed6b75de31
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
ed6b75d to
f994be5
Compare
f994be5 to
8414874
Compare
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 841487419b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Rollback timeout and deletion ordering can leave a failed creation’s bucket in an inconsistent, unretryable state.
Review effort: Balanced
Findings: 1
Open (2)
What changed in this PR
Adds signed x-bucket-policy support to CreateBucket, persisting policies and issuing principal grants during bucket creation.
Changes:
- Decodes, verifies, validates, and stores header policies.
- Adds rollback revocation and
InvalidBucketPolicyhandling. - Adds unit, wiring, and integration coverage.
| File | Description |
|---|---|
pkg/rpc/service/bucket/service.go |
Implements policy handling and rollback. |
pkg/rpc/service/bucket/service_test.go |
Tests creation, policy persistence, and rollback. |
pkg/rpc/service/auth/operation.go |
Exports case-insensitive header lookup. |
pkg/rpc/rpc_test.go |
Updates bucket service construction. |
pkg/rpc/failure.go |
Maps invalid policies to receipt failures. |
pkg/rpc/failure_test.go |
Tests failure-name mapping. |
pkg/rpc/create.go |
Documents handler behavior. |
pkg/fx/rpc_test.go |
Adds policy-service wiring. |
pkg/bucketpolicy/bucketpolicy.go |
Updates package documentation. |
pkg/api/service/bucketpolicy/service.go |
Extracts reusable policy write logic. |
itest/stack_test.go |
Registers the integration scenario. |
itest/iam_test.go |
Tests policy-header behavior end to end. |
AGENTS.md |
Documents the new RPC contract. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…t-policy A CreateBucket request may carry the new bucket's policy as base64 JSON in the x-bucket-policy header. The header must be covered by the request signature and decode as a policy document; a refusal is the InvalidBucketPolicy failure, the name the management API uses. The document is written right after the bucket row through the policy service's Write, the same validation and rotation a management-API policy PUT gets: the principals it names have their keys issued delegations over the new bucket inside the write. The bucket is deleted if that write fails, so no bucket outlives a refused or failed policy. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
When a step after the policy write fails, Create's rollback publishes revocations for the grants that write issued, then deletes the grants, the policy and the bucket row. It did the deletes even when the publish failed, so a proof chain a gateway had already fetched outlived every record that could revoke it. The rollback now returns after a failed tenant-issuer load or publish, leaving the bucket for a DeleteBucket retry, which revokes before it deletes. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
policyFromHeader read the header through auth.HeaderValue, which treats an empty value as absent, so a CreateBucket carrying the header with an empty value created a bucket with no policy and skipped the signed-header check. A present but empty or whitespace-only header is now an InvalidBucketPolicy refusal. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…tenant key Create's rollback loaded the tenant issuer before it knew whether there was anything to revoke, and returned when the load failed. A policy write that fails on that same key lookup issues no grants, so the rollback left the bucket row behind: retries got BucketAlreadyOwnedByYou and DeleteBucket could not remove the row, needing the key and a Sprue space that was never provisioned. The rollback now lists the bucket's tenant-issued delegations first and loads the issuer and publishes only when there is one; with nothing to revoke it deletes directly. A publish that fails still keeps the bucket for a DeleteBucket retry. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Create's rollback ran on a context detached from the request with no deadline, and the Swarf client has no timeout of its own, so a revocation service that accepted the request and never answered hung the create forever. The rollback's context now carries the Swarf batch bound, grant.BatchTimeout, on top of the detached context: a client disconnect still does not abort it, and a publish that times out fails and keeps the bucket for a DeleteBucket retry. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The fixture kept the fake Swarf under two fields; the deadline-recording wrapper embeds it, so one field serves both. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…s deletes safe A create that failed before storing the bucket's root, whose rollback could not publish the revocations, kept the bucket row for a DeleteBucket retry, but Delete first asked Sprue whether the space was empty, which needs the root proof, so the retry could never succeed and the name stayed taken. Delete now skips the emptiness check when the bucket holds no root: no space a proof can reach exists for it. The rollback's deletes shared the publish's deadline, so a publish returning near it left them an expired context; they now run under a fresh one. They also deleted the policy before the bucket row, so a failed row delete left a live bucket without its policy on the memory backend; they now run inside the policy store's DeleteByBucket callback as Delete's do, delegations and row first, the policy last. Tests: a bucket kept without its root is deleted on retry without a Sprue call and its name is free again; the deletes' deadline is later than the publish's; a row the rollback cannot delete keeps its policy. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
RFC 30 (113d4ded) makes CreateBucket plain again: a bucket's policy is set with PutBucketPolicy, never on the create. Create and its rollback return to their earlier shape (the rollback deletes the bucket row), and the header constant, its decoding, the blank-header refusal, the rollback's revoke and publish, the root check a header-less delete needed, and the header tests and docs go with it. What PutBucketPolicy builds on stays: the policy service's Write, the exported auth.HeaderValue, the bucket service's policyWrites dependency, the InvalidBucketPolicy failure mapping, and the API module in the RPC wiring test. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
| policies: policies, | ||
| uploads: uploads, | ||
| revocations: revocations, | ||
| policyWrites: policyWrites, |
There was a problem hiding this comment.
Urm, is this PR needed now? This property seems unused.
There was a problem hiding this comment.
I'll fold this it into #89 and close this PR. I left this PR as a standalone when refactoring as it was simpler.


Splits the policy write out of the management PUT so the bucket service can use it.
/s3/bucket/policy(#89) builds on it. CreateBucket is unchanged: a new bucket has no policy until aPutBucketPolicywrites one.bucketpolicysvc.Service.Write, split fromPutpolicyWritesdependencyauth.HeaderValueexportedInvalidBucketPolicyreceipt failureChange log
x-bucket-policycreate header and its rollback, after RFC 30 moved the console's default policy to aPutBucketPolicyafter the create.References
🤖 Generated with Claude Code