Skip to content

docs(partner-integrations): fix access control and add permission recipes - #563

Open
adilansari wants to merge 3 commits into
mainfrom
docs/partner-access-control
Open

adilansari wants to merge 3 commits into
mainfrom
docs/partner-access-control

Conversation

@adilansari

@adilansari adilansari commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Why

Railway lost production buckets last week. Their users deleted them over S3 with the key that /provision returns. When they asked how to stop that, our Access Control page pointed the wrong way. It said IAM policies "further restrict what a role allows", so a Deny s3:DeleteBucket looked like the fix. It isn't. The provisioned key is the bucket owner, and owner and role allows return before policies are read.

RunPod asked for the same model in August (users get read/write on one bucket, no bucket admin). The ReadWrite role shipped right after (tigris-os#5097), but the docs never showed partners how to use it.

So I audited the page claim by claim against tigris-os origin/main, fixed what was wrong, and added recipes for the setups partners keep asking about.

What was wrong

Claim on the page Reality (tigris-os)
Create key is POST .../access-keys It's POST .../key (api/extensions/v1/api.yaml)
user_role: Admin updates org settings, invites users user_role is the caller identity for one call, not stored on the key. It gates other users' keys and which bucket roles the call can grant. UpdateOrganization isn't gated, and there is no invite API (gateway/extensions/controller.go, iamapi_management_handlers.go:1641)
The three fields are independent A Member call can only grant roles on buckets that user_id provisioned, otherwise 403 (iamapi_management_handlers.go:1666-1740)
Policies run after roles and can restrict them Owner, */Admin and role allows return first. A Deny only beats a policy Allow or default-allow (auth_credentials.go:987-1104 vs :2204)
* grants all buckets Works with every role, but only an Admin call can grant it
Scope settable on Create/Update Also on Provision
Nothing on the provisioned key It's the bucket owner (controller.go:177-188, auth_credentials.go:999)
Provision response has bucket, org_id (architecture page) It returns bucket_name, access_key_id, secret_access_key (gateway/handlers/extensions.go:506)
Soft-deleted buckets are purged after retention (soft-delete page) Nothing purges a soft-deleted bucket; scanAllBuckets skips them (server/services/v1/worker.go:606)
Disabling soft delete or changing retention doesn't touch already-deleted objects Cleanup reads the bucket's current rule, so both apply to existing tombstones (tombstone_cleanup_task.go:722)

The diagram labels are fixed to match.

What's new

  • The Provisioned Access Key: it's the owner, keep it in your backend.
  • How Tigris Evaluates a Request: the actual order, so partners can tell what a policy can and can't do.
  • Permission Recipes: data access without bucket admin, read-only (one bucket and all buckets), mixed access, upload-only, backend admin key, soft delete as a backstop, bucket settings from the backend, and rotate or revoke.
  • Common Questions on the architecture page, from the RunPod thread: which user_id to use, org_id scope, global bucket names, and billing units.

Left out on purpose

  • Prefix-scoped keys. The authz cache key has no list prefix (auth_credentials.go:1432), so one allowed prefix list can unlock a full-bucket list for 15 minutes. That needs a fix before we document it.
  • IP-restricted keys. aws:SourceIp sees internal LB addresses in some regions (audit logs show 10.x peers in FRA and NRT), so the recipe would lock users out.

Note

Low Risk
Documentation-only changes; no runtime behavior. Incorrect prior guidance could have led partners to unsafe key handling, so accuracy matters for integrators.

Overview
Partner integrations docs are corrected to match actual auth behavior and add practical setup guidance. user_role is documented as per Partner API call (not stored on keys); the create-key path is POST .../key; the provisioned key is the bucket owner (roles/policies cannot limit it); and S3 authorization order is spelled out so IAM Deny cannot override owner, * Admin, or bucket-role allows.

New content includes permission recipes (ReadWrite without bucket admin, rotating off the provisioned key, upload-only via policy, soft delete, backend-managed bucket settings) and architecture Common Questions (user_id, global bucket names, billing units). The access-control diagram labels are updated to match.

Soft delete docs are fixed: the retention window applies only to objects, not soft-deleted buckets (they remain until restore or explicit purge). Object vs bucket lifecycles are split in the diagram; notes now say changing retention affects existing tombstones and turning soft delete off can purge recoverable objects.

Reviewed by Cursor Bugbot for commit 40600cb. Bugbot is set up for automated code reviews on this repo. Configure here.

@vercel

vercel Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
docs-redirect Ready Ready Preview Oct 9, 2026 11:50pm UTC
tigris-os-docs Ready Ready Preview Oct 9, 2026 11:50pm UTC

Request Review

…ipes

Audit the partner Access Control page against the gateway code and fix
the claims that were wrong: the create-key path, what user_role gates,
and the claim that IAM policies can restrict a bucket role. Document
that the provisioned key owns its bucket, the order Tigris uses to
evaluate a request, and recipes for common partner permission setups.

Also fix the provision response example and add common partner
questions to the architecture page, and correct the soft delete page:
soft-deleted buckets are not purged when retention ends, and retention
changes apply to objects that are already soft-deleted.
… recipe

user_role limits bucket roles and key ownership, not IAM policies. A
Member call can create a policy for any bucket and attach it to any key
in the org, so the Member row no longer says that it can update only
its own keys.

Add a recipe to move users off the provisioned key. Rotating the key is
not enough, because keys that the user created with it keep working.

Also:
- Provision creates a new owner key on each call. Say that the backend
  can delete it and keep managing the bucket with the Partner API.
- Soft delete does not stop owner, Editor, or admin keys. They can turn
  it off or purge a soft-deleted bucket over S3.
- Role and scope changes can take up to 15 minutes, like rotate and
  delete.
- Turning off soft delete does not remove objects in the next cleanup.
  Say that Tigris can remove them later.
@greptile-apps

greptile-apps Bot commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

[Low impact] The latest changes introduce no new blocking issue.

Summary

Corrects partner access-control guidance and adds permission recipes.

  • Partner guides separate caller roles from access-key permissions.
  • Permission recipes show how partners can give users narrower keys.
  • Backend recipes cover bucket protection, settings, and key upkeep.
  • Soft delete now explains separate lifecycles for objects and buckets.
  • The architecture guide answers common partner setup questions.

No new findings were accepted. The supplied previous threads have no comment numbers, so previousFindings is empty.

Reviews (3) · Last reviewed commit: "docs: separate bucket and object retenti..." · Reviewed by Greptile

Comment thread docs/buckets/soft-delete.mdx
Comment thread docs/buckets/soft-delete.mdx Outdated
Comment thread docs/partner-integrations/access-control.mdx Outdated
The soft delete page still said in three places that a deleted bucket is
removed after the retention window. Split the lifecycle diagram into
object and bucket flows, say that retention applies only to objects,
and remove the retention claim from the delete dialog description.

Put the "turn off soft delete" risk and the org admin key warning in
warning callouts, and remove the Member note that repeats the recipe
intro.
@adilansari

Copy link
Copy Markdown
Contributor Author

@greptile review

This branch was successfully deployed

2 active deployments
Preview – tigris-os-docs — 40600cb0 Deployed Oct 9, 2026 by vercel[bot]
Preview – docs-redirect — 40600cb0 Deployed Oct 9, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant