Tigris Object Storage Documentation Audit
The docs are broad and feature-complete, but the agent-facing surface points at a deprecated package, and a single question — "can I set a bucket policy / use versioning?" — gets four different answers across the API, RBAC, IAM, and pricing pages.
1. AI-agent onboarding installs a deprecated CLI package (critical)
Location: /docs/ai-agents/welcome-agent-get-started.md and /docs/ai-agents/tigris-cli-quickstart.md
Problem: Both agent-facing pages instruct readers to npm install -g @tigrisdata/tigris-cli. The npm registry shows @tigrisdata/tigris-cli is at 1.0.0-beta.32 and is explicitly deprecated: "deprecated":"Package no longer supported.". The canonical home page (/docs/index.md) and CLI page (/docs/cli.md) instead use @tigrisdata/cli, which the registry shows live and supported at 3.1.0 ("description":"Command line interface for Tigris object storage"). The welcome page even tells the agent "Do NOT hallucinate URLs" while handing it a dead package, and the troubleshooting step doubles down ("reinstall with npm install -g @tigrisdata/tigris-cli").
Consequence: AI agents — the exact audience this page targets and tells to "run commands automatically" — install an unsupported beta CLI (last published at v1.0.0-beta.32 vs the real v3.1.0), or fail outright if the deprecated package is eventually unpublished. A human following the same page gets a CLI two major versions behind the documented one.
The fix: Replace every @tigrisdata/tigris-cli reference on both agent pages (install, npx fallback, and troubleshooting) with @tigrisdata/cli, matching the home and CLI pages. Unpublish or hard-deprecate the old package's README so search traffic doesn't keep landing on it.
2. "Can I set a bucket policy / use versioning?" has four conflicting answers (critical)
Location: /docs/api/s3.md vs /docs/concepts/authnz.md vs /docs/iam/policies/supported-actions.md vs /pricing/
Problem: The same operations are simultaneously supported, granted, billed, and unsupported depending on the page:
- /docs/api/s3.md marks
GetBucketPolicy ❌,PutBucketPolicy ❌,PutBucketVersioning ❌,GetBucketVersioning ⚠️,PutBucketNotificationConfiguration ❌. - /docs/concepts/authnz.md RBAC table grants
GetBucketPolicy,PutBucketPolicy,DeleteBucketPolicy,PutObjectLockConfiguration,PutObjectRetention,PutObjectLegalHoldto Admin/Editor roles. - /docs/iam/policies/supported-actions.md — the "Full List of Supported S3-Compatible IAM Actions" — omits
s3:GetBucketPolicy/s3:PutBucketPolicy, all versioning actions, and all Object Lock actions, and warns "Using unsupported actions will result in an error during policy creation." - /pricing/ bills
PutBucketPolicy,GetBucketPolicy,GetBucketVersioning,PutObjectRetention,PutObjectLegalHold,PutObjectLockConfigurationas Class A/B requests.
Consequence: A developer cannot determine whether these features exist. Writing an IAM policy with s3:PutObjectRetention (implied supported by RBAC + pricing) errors out per the IAM page. Code calling PutBucketPolicy (granted in RBAC, billed in pricing) fails per the S3 compat matrix. Agents, which can't apply human judgment, will generate policies that fail at creation time.
The fix: Establish one authoritative capability list and make /api/s3.md, the RBAC table, the IAM supported-actions list, and the pricing request classes derive from it. If Object Lock / bucket policy / versioning are unsupported, remove them from the RBAC table and pricing; if supported, fix the S3 matrix and add the s3: actions to the IAM list.
3. ChatGPT MCP setup field has no URL to enter (critical)
Location: /docs/mcp/remote.md → "ChatGPT (web)" section
Problem: The ChatGPT instructions read: 'In the MCP Server URL field, enter ""' — the URL value is blank. Every other client section on the same page supplies the real endpoint: Claude Desktop and Claude Code use https://mcp.storage.dev/mcp, Goose uses npx -y mcp-remote https://mcp.storage.dev/mcp, etc.
Consequence: A developer (or agent) following the ChatGPT steps literally has nothing to paste into the required field and cannot complete the connection. The one client whose setup is purely manual UI clicks is the one missing its critical value.
The fix: Fill in the ChatGPT MCP Server URL with https://mcp.storage.dev/mcp to match the other client sections.
4. OAuth sessions silently expire in ~1 hour, but the agent flow that depends on tigris login never says so (significant)
Location: /docs/cli.md vs /docs/ai-agents/welcome-agent-get-started.md and /docs/ai-agents/tigris-cli-quickstart.md
Problem: /docs/cli.md states "Sessions created with tigris login oauth will automatically expire in about an hour." The agent onboarding pages build their entire "automated after initial login" protocol on tigris login / OAuth but never mention this expiry.
Consequence: An agent doing long-running automation ("create buckets, generate access keys, set environment variables, integrate the SDK") will hit auth failures roughly an hour in, with no documented explanation on the page it's following. The fix (tigris configure to save permanent credentials) is described on a different page the agent flow doesn't reference for persistence.
The fix: On the agent pages, note the ~1-hour OAuth expiry and recommend tigris configure --access-key ... --access-secret ... for any automation expected to outlast a single session.
5. The canonical "Get Started" page is an empty redirect stub (significant)
Location: /docs/get-started.md
Problem: The page contains only "Get Started Redirecting to Get Started...". It is a top-level entry in llms.txt and the destination of the "Get Started" link at the bottom of the agent onboarding page, yet has no content and points at /docs/.md.
Consequence: A reader or agent landing on the canonical Get Started URL gets an empty page and a malformed self-referential link instead of onboarding content. Agents that fetch the markdown (not the rendered redirect) get nothing actionable.
The fix: Either populate /docs/get-started.md with real getting-started content or remove it from llms.txt and repoint links directly to /docs/.
6. RBAC table lists the same operations twice with conflicting permissions (significant)
Location: /docs/concepts/authnz.md → Role-Based Access Control table
Problem: Within one table, GetBucketAccelerateConfiguration appears twice (once as Editor ✅ / ReadOnly ❌, later as ReadOnly ✅) and GetBucketOwnershipControls appears twice with conflicting ReadOnly values (❌ then ✅).
Consequence: A developer building least-privilege roles cannot tell whether a ReadOnly principal can call these operations. The table is the authoritative RBAC reference, so the ambiguity propagates into real access-control decisions.
The fix: De-duplicate the table, resolve each operation to a single authoritative row per role, and add a test that fails on duplicate operation names.
7. Home page promises a Go SDK that isn't in the docs (significant)
Location: /docs/ (home) and /docs/llms.txt vs github.com/tigrisdata/storage
Problem: The home page advertises "Tigris SDK – Type-safe libraries for TypeScript and Go." But the native Go SDK lives in a separate repo, github.com/tigrisdata/storage-go (go get github.com/tigrisdata/storage-go), and is not surfaced in the docs SDK navigation (llms.txt lists only the JS Storage SDK and "Use Your Existing S3 Code"). The docs' Go examples use the AWS SDK (go get github.com/aws/aws-sdk-go-v2/service/s3) instead. Several shipped JS packages (@tigrisdata/iam, @tigrisdata/agent-kit, @tigrisdata/react, @tigrisdata/keyv-tigris) are likewise undocumented in the nav.
Consequence: A Go developer reads "type-safe Go library," searches the docs, finds only AWS-SDK examples, and never discovers the native storage-go package. The promised type-safe Go experience is effectively undiscoverable from the docs.
The fix: Add a Go SDK page (install, auth, quickstart) linking github.com/tigrisdata/storage-go and pkg.go.dev, and list the other shipped @tigrisdata/* packages in the SDK nav — or soften the home-page claim if Go isn't first-class yet.
8. Three unreconciled credential/env-var conventions (significant)
Location: /docs/sdks/tigris.md and /docs/sdks/tigris/using-sdk.md vs /docs/ai-agents/welcome-agent-get-started.md vs /docs/cli.md and /docs/
Problem: The docs use three different credential conventions without ever reconciling them on one page:
- Native SDK:
TIGRIS_STORAGE_ACCESS_KEY_ID,TIGRIS_STORAGE_SECRET_ACCESS_KEY,TIGRIS_STORAGE_BUCKET - Agent / S3 path:
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY, plusAWS_ENDPOINT_URL_S3 - Home page:
AWS_ENDPOINT_URL=https://t3.storage.dev
Consequence: A developer who configures AWS_* vars after the S3 quickstart, then switches to the native SDK, finds nothing works because the native SDK reads TIGRIS_STORAGE_*. There's no single page mapping which variables which tool reads, so the failure mode is silent "no credentials found."
The fix: Add a single credentials/environment reference table mapping each tool (native SDK, AWS SDK/CLI path, CLI) to the exact env vars it reads, and cross-link it from every quickstart.
9. S3 compatibility is measured by two different test suites with conflicting capability claims (significant)
Location: /docs/api/s3.md vs /docs/acceleration-gateway.md and /docs/acceleration-gateway/s3-compatibility.md
Problem: /docs/api/s3.md reports "61/68 (90%)" using tigrisdata-community/s3-api-compat-tests (68 tests). The TAG pages report compatibility "validated against 214 tests from the ceph/s3-tests suite." Worse, the TAG s3-compatibility page lists GetBucketPolicy as "Forwarded to Tigris" (i.e., usable through TAG) while the main API page marks Tigris's own GetBucketPolicy ❌ — so TAG forwards an operation the backend doesn't support. TAG also claims bucket "Versioning … Policy" coverage in its S3-API-coverage box while its own "Not Supported" note lists object versioning.
Consequence: Developers can't compare the two compatibility numbers (different suites, different sizes) and can't trust the TAG coverage list — calling a "forwarded" GetBucketPolicy through TAG will hit an unsupported backend operation. Agents reading the optimistic TAG list will assume features that error at runtime.
The fix: State both suites explicitly and stop presenting the two scores as comparable; reconcile the TAG "forwarded/supported" list against the backend S3 matrix so a forwarded op is never marked supported when the backend returns an error.
10. Object versioning support is described three incompatible ways (significant)
Location: /docs/snapshots.md vs /docs/api/s3.md vs /docs/acceleration-gateway/s3-compatibility.md
Problem: /docs/snapshots.md says "a subset of S3-compatible object versioning APIs is available for snapshot-enabled buckets." /docs/api/s3.md marks GetBucketVersioning ⚠️/PutBucketVersioning ❌. The TAG s3-compatibility page lists object versioning flatly under "Not supported."
Consequence: A developer trying to enable or query versioning can't tell whether it works at all, only on snapshot-enabled buckets, or never through TAG. The conditions (snapshot-enabled vs not, direct vs gateway) are scattered across three pages with no single reconciliation.
The fix: Add one "Versioning" section that states exactly which versioning APIs work, under which bucket configuration, and through which access path (direct vs TAG), and link the snapshots, S3 matrix, and TAG pages to it.
11. Region tables disagree on London (lhr) and on which regions exist (significant)
Location: /docs/concepts/regions.md vs /docs/buckets/locations.md
Problem: /docs/concepts/regions.md lists London lhr under EUR for t3.storage.dev. But /docs/buckets/locations.md's Multi-Region EUR "Candidate Regions" lists only ams (Amsterdam) and fra (Frankfurt) — lhr is omitted. The Fly.io table in regions.md additionally adds syd, gru, jnb, which don't appear in the t3.storage.dev list.
Consequence: A developer choosing a multi-region EUR bucket can't tell whether London is an available placement region. Picking lhr based on the regions page may not be honored by multi-region placement per the locations page.
The fix: Generate the region/candidate-region tables from one source of truth and explicitly note which regions are valid for multi-region placement vs merely reachable endpoints.
12. Regions page tells you to "contact us at" a missing email address (minor)
Location: /docs/concepts/regions.md → closing note
Problem: The note reads "If you need a region that isn't listed, contact us at to discuss your requirements." — the email address is blank.
Consequence: A developer needing an unlisted region is told to make contact but given no address to contact, dead-ending the one documented path for region requests.
The fix: Insert the support/sales email (or link to /support) in the note.
13. Presigned URL expiration limits conflict across pages and exceed the AWS norm (minor)
Location: /docs/objects/presigned.md vs /docs/sdks/tigris/using-sdk.md vs /docs/ai-agents/tigris-cli-quickstart.md
Problem: /docs/objects/presigned.md states the expiration "can be set to a maximum of 90 days" — far beyond the standard AWS SigV4 presigned-URL ceiling of 7 days. The native SDK reference documents a 3600s default with no maximum stated, and the CLI quickstart shows --expires-in 7200. No page reconciles the default vs maximum, or explains how Tigris exceeds the SigV4 7-day limit.
Consequence: Developers familiar with S3 will assume a 7-day cap and under-provision; those who try a 90-day URL with a standard AWS SigV4 client (the 7-day-capped path) may get rejected before the request reaches Tigris, with no guidance on which signing path supports 90 days.
The fix: State the default and maximum in one place, clarify which signing mechanism allows >7 days (and which standard AWS clients cannot), and cross-link the SDK and CLI expiration parameters to it.
14. Native SDK method signatures render with empty generics (minor)
Location: /docs/sdks/tigris/using-sdk.md → Responses / method reference
Problem: The signatures render as put(...): Promise>;, get(...): Promise>;, head(...): Promise> — the TigrisStorageResponse<…> type parameter is missing between the angle brackets, even though the prose says "All methods return a generic response of type TigrisStorageResponse." The list options table also has a malformed row where the "default configuration" link wrapped onto its own table row.
Consequence: A developer can't see what each method actually resolves to (Promise<TigrisStorageResponse<what?>>), and an agent parsing these signatures gets a syntactically broken return type. (May be partly a rendering/extraction artifact — verify against the live rendered page.)
The fix: Restore the full generic type parameters in the rendered signatures and fix the wrapped list options table row.
15. Home-page feature blurbs oversimplify consistency and storage tiers (minor)
Location: /docs/ (home) vs /docs/concepts/consistency.md and /docs/objects/tiers.md
Problem: The home Features list says "Geo-Redundant – Cross-region redundancy with strong consistency," but /docs/concepts/consistency.md clarifies that Global and Dual-region buckets are only eventually consistent cross-region. The home list also names "Standard, infrequent access, and archive" tiers, omitting the fourth tier — Archive Instant Retrieval — that /docs/objects/tiers.md and /pricing/ both document.
Consequence: A reader who picks a Global bucket expecting "strong consistency" everywhere can be surprised by sub-second-but-real cross-region replication lag; a reader sizing tiers from the home page misses a billed tier (Archive Instant Retrieval at $0.004/GB/mo with $0.03/GB retrieval).
The fix: Qualify the home-page consistency claim (strong same-region; cross-region varies by location type) and list all four storage tiers, linking to the consistency and tiers reference pages.
What they do well
- The S3 compatibility matrix compares Tigris against Cloudflare R2 and Google Cloud Storage with a named, reproducible test suite — rare transparency for a storage vendor.
- The pricing page pins concrete, parseable numbers (per-tier $/GB, minimum retention windows, request classes), and most MCP client setups include the real endpoint and copy-pasteable commands.
- llms.txt exists and maps the full doc surface, and the docs ship machine-readable
.mdvariants of pages — genuinely agent-friendly when the content underneath is correct.
Top 3 recommendations
- Fix the agent path first: replace the deprecated
@tigrisdata/tigris-cliwith@tigrisdata/clieverywhere, fill in the blank ChatGPT MCP URL, surface the 1-hour OAuth expiry, and replace the empty Get Started stub — these are the steps agents execute automatically and fail on silently. - Create one authoritative S3 capability source that the API matrix, RBAC table, IAM supported-actions list, and pricing request classes all derive from, so "can I set a bucket policy / use versioning / Object Lock?" has exactly one answer.
- Reconcile the scattered references: a single credentials/env-var table, one region source of truth (resolve
lhr), one presigned-URL limits statement, and a real Go SDK page — eliminating the cross-page contradictions a human can paper over but an agent cannot.